@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/dist/index.mjs CHANGED
@@ -3,6 +3,8 @@ import { useEffect, useMemo, useRef, useState } from "react";
3
3
  import { createPortal } from "react-dom";
4
4
  import { useViewerStore } from "@papyrus-sdk/core";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
+ var MOBILE_LANDSCAPE_MAX_HEIGHT_PX = 500;
7
+ var MOBILE_VIEWPORT_QUERY = `(max-width: 639px), (orientation: landscape) and (max-height: ${MOBILE_LANDSCAPE_MAX_HEIGHT_PX}px)`;
6
8
  var Topbar = ({
7
9
  engine,
8
10
  showBrand = false,
@@ -57,7 +59,7 @@ var Topbar = ({
57
59
  }, [hasMobileMenu]);
58
60
  useEffect(() => {
59
61
  if (!canUseDOM || typeof window.matchMedia !== "function") return;
60
- const mediaQuery = window.matchMedia("(max-width: 639px)");
62
+ const mediaQuery = window.matchMedia(MOBILE_VIEWPORT_QUERY);
61
63
  const updateViewport = () => setIsMobileViewport(mediaQuery.matches);
62
64
  updateViewport();
63
65
  if (typeof mediaQuery.addEventListener === "function") {
@@ -1770,8 +1772,12 @@ var PageRenderer = ({
1770
1772
  activeSearchIndex,
1771
1773
  textLayerVersion
1772
1774
  ]);
1773
- const handleMouseDown = (e) => {
1774
- const target = e.target;
1775
+ const getTouchPoint = (event) => {
1776
+ const touch = event.touches[0] ?? event.changedTouches[0];
1777
+ if (!touch) return null;
1778
+ return { x: touch.clientX, y: touch.clientY };
1779
+ };
1780
+ const handlePointerDown = (clientX, clientY, target) => {
1775
1781
  const clickedInsideAnnotation = Boolean(
1776
1782
  target?.closest("[data-papyrus-annotation-id]")
1777
1783
  );
@@ -1785,8 +1791,8 @@ var PageRenderer = ({
1785
1791
  if (activeTool === "ink") {
1786
1792
  const rect2 = containerRef.current?.getBoundingClientRect();
1787
1793
  if (!rect2) return;
1788
- const x2 = (e.clientX - rect2.left) / rect2.width;
1789
- const y2 = (e.clientY - rect2.top) / rect2.height;
1794
+ const x2 = (clientX - rect2.left) / rect2.width;
1795
+ const y2 = (clientY - rect2.top) / rect2.height;
1790
1796
  setIsInkDrawing(true);
1791
1797
  setInkPoints([{ x: x2, y: y2 }]);
1792
1798
  return;
@@ -1795,25 +1801,25 @@ var PageRenderer = ({
1795
1801
  const rect = containerRef.current?.getBoundingClientRect();
1796
1802
  if (!rect) return;
1797
1803
  setIsDragging(true);
1798
- const x = e.clientX - rect.left;
1799
- const y = e.clientY - rect.top;
1804
+ const x = clientX - rect.left;
1805
+ const y = clientY - rect.top;
1800
1806
  setStartPos({ x, y });
1801
1807
  setCurrentRect({ x, y, w: 0, h: 0 });
1802
1808
  };
1803
- const handleMouseMove = (e) => {
1809
+ const handlePointerMove = (clientX, clientY) => {
1804
1810
  if (isInkDrawing) {
1805
1811
  const rect2 = containerRef.current?.getBoundingClientRect();
1806
1812
  if (!rect2) return;
1807
- const x = (e.clientX - rect2.left) / rect2.width;
1808
- const y = (e.clientY - rect2.top) / rect2.height;
1813
+ const x = (clientX - rect2.left) / rect2.width;
1814
+ const y = (clientY - rect2.top) / rect2.height;
1809
1815
  setInkPoints((prev) => [...prev, { x, y }]);
1810
1816
  return;
1811
1817
  }
1812
1818
  if (!isDragging) return;
1813
1819
  const rect = containerRef.current?.getBoundingClientRect();
1814
1820
  if (!rect) return;
1815
- const currentX = e.clientX - rect.left;
1816
- const currentY = e.clientY - rect.top;
1821
+ const currentX = clientX - rect.left;
1822
+ const currentY = clientY - rect.top;
1817
1823
  setCurrentRect({
1818
1824
  x: Math.min(startPos.x, currentX),
1819
1825
  y: Math.min(startPos.y, currentY),
@@ -1821,7 +1827,7 @@ var PageRenderer = ({
1821
1827
  h: Math.abs(currentY - startPos.y)
1822
1828
  });
1823
1829
  };
1824
- const handleMouseUp = (e) => {
1830
+ const handlePointerUp = () => {
1825
1831
  if (isInkDrawing) {
1826
1832
  setIsInkDrawing(false);
1827
1833
  if (inkPoints.length > 1) {
@@ -1986,6 +1992,37 @@ var PageRenderer = ({
1986
1992
  }
1987
1993
  }
1988
1994
  };
1995
+ const handleMouseDown = (e) => {
1996
+ handlePointerDown(e.clientX, e.clientY, e.target);
1997
+ };
1998
+ const handleMouseMove = (e) => {
1999
+ handlePointerMove(e.clientX, e.clientY);
2000
+ };
2001
+ const handleMouseUp = () => {
2002
+ handlePointerUp();
2003
+ };
2004
+ const handleTouchStart = (event) => {
2005
+ if (event.touches.length > 1) return;
2006
+ const point = getTouchPoint(event);
2007
+ if (!point) return;
2008
+ handlePointerDown(point.x, point.y, event.target);
2009
+ if ((activeTool === "ink" || !canSelectText) && event.cancelable) {
2010
+ event.preventDefault();
2011
+ }
2012
+ };
2013
+ const handleTouchMove = (event) => {
2014
+ if (event.touches.length > 1) return;
2015
+ const point = getTouchPoint(event);
2016
+ if (!point) return;
2017
+ handlePointerMove(point.x, point.y);
2018
+ if ((isInkDrawing || isDragging) && event.cancelable) {
2019
+ event.preventDefault();
2020
+ }
2021
+ };
2022
+ const handleTouchEnd = (event) => {
2023
+ if (event.touches.length > 0) return;
2024
+ handlePointerUp();
2025
+ };
1989
2026
  const getPageFilter = () => {
1990
2027
  switch (pageTheme) {
1991
2028
  case "sepia":
@@ -2003,10 +2040,18 @@ var PageRenderer = ({
2003
2040
  {
2004
2041
  ref: containerRef,
2005
2042
  className: `relative inline-block shadow-2xl bg-white mb-10 ${canSelectText ? "" : "no-select cursor-crosshair"}`,
2006
- style: { scrollMarginTop: "20px", minHeight: "100px" },
2043
+ style: {
2044
+ scrollMarginTop: "20px",
2045
+ minHeight: "100px",
2046
+ touchAction: activeTool === "ink" || activeTool === "text" || activeTool === "comment" ? "none" : "auto"
2047
+ },
2007
2048
  onMouseDown: handleMouseDown,
2008
2049
  onMouseMove: handleMouseMove,
2009
2050
  onMouseUp: handleMouseUp,
2051
+ onTouchStart: handleTouchStart,
2052
+ onTouchMove: handleTouchMove,
2053
+ onTouchEnd: handleTouchEnd,
2054
+ onTouchCancel: handleTouchEnd,
2010
2055
  children: [
2011
2056
  loading && /* @__PURE__ */ jsx4("div", { className: "absolute inset-0 bg-gray-50 flex items-center justify-center z-10 animate-pulse", children: /* @__PURE__ */ jsx4("span", { className: "text-[10px] font-black text-gray-400 uppercase tracking-widest", children: "Sincronizando..." }) }),
2012
2057
  /* @__PURE__ */ jsx4(
@@ -2482,9 +2527,12 @@ var MIN_ZOOM = 0.2;
2482
2527
  var MAX_ZOOM = 5;
2483
2528
  var WIDTH_SNAP_PX = 4;
2484
2529
  var WIDTH_HYSTERESIS_PX = 6;
2530
+ var HEIGHT_SNAP_PX = 4;
2531
+ var HEIGHT_HYSTERESIS_PX = 6;
2485
2532
  var MOBILE_HEADER_HIDE_DELTA_PX = 28;
2486
2533
  var MOBILE_HEADER_SHOW_DELTA_PX = 16;
2487
2534
  var MOBILE_HEADER_TOP_RESET_PX = 12;
2535
+ var MOBILE_LANDSCAPE_MAX_HEIGHT_PX2 = 500;
2488
2536
  var Viewer = ({ engine, style }) => {
2489
2537
  const viewerState = useViewerStore5();
2490
2538
  const {
@@ -2510,6 +2558,7 @@ var Viewer = ({ engine, style }) => {
2510
2558
  const jumpRef = useRef4(false);
2511
2559
  const jumpTimerRef = useRef4(null);
2512
2560
  const lastWidthRef = useRef4(null);
2561
+ const lastHeightRef = useRef4(null);
2513
2562
  const lastScrollTopRef = useRef4(0);
2514
2563
  const scrollDownAccumulatorRef = useRef4(0);
2515
2564
  const scrollUpAccumulatorRef = useRef4(0);
@@ -2523,11 +2572,14 @@ var Viewer = ({ engine, style }) => {
2523
2572
  rafId: null
2524
2573
  });
2525
2574
  const [availableWidth, setAvailableWidth] = useState5(null);
2575
+ const [availableHeight, setAvailableHeight] = useState5(null);
2526
2576
  const [basePageSize, setBasePageSize] = useState5(null);
2527
2577
  const [pageSizes, setPageSizes] = useState5({});
2528
2578
  const [colorPickerOpen, setColorPickerOpen] = useState5(false);
2529
- const isCompact = availableWidth !== null && availableWidth < 820;
2530
- const isMobileViewport = availableWidth !== null && availableWidth < 640;
2579
+ const isLandscape = availableWidth !== null && availableHeight !== null && availableWidth > availableHeight;
2580
+ const isLandscapeShort = isLandscape && availableHeight !== null && availableHeight <= MOBILE_LANDSCAPE_MAX_HEIGHT_PX2;
2581
+ const isCompact = availableWidth !== null && (availableWidth < 820 || isLandscapeShort);
2582
+ const isMobileViewport = availableWidth !== null && (availableWidth < 640 || isLandscapeShort);
2531
2583
  const paddingY = isCompact ? "py-10" : "py-16";
2532
2584
  const toolDockPosition = isCompact ? "bottom-4" : "bottom-8";
2533
2585
  const colorPalette = [
@@ -2578,21 +2630,32 @@ var Viewer = ({ engine, style }) => {
2578
2630
  const measurementTarget = viewerElement.parentElement ?? viewerElement;
2579
2631
  let rafId = null;
2580
2632
  const normalizeWidth = (rawWidth) => Math.max(0, Math.floor(rawWidth / WIDTH_SNAP_PX) * WIDTH_SNAP_PX);
2581
- const updateWidth = () => {
2633
+ const normalizeHeight = (rawHeight) => Math.max(0, Math.floor(rawHeight / HEIGHT_SNAP_PX) * HEIGHT_SNAP_PX);
2634
+ const updateSize = () => {
2582
2635
  const rawWidth = measurementTarget.getBoundingClientRect?.().width ?? measurementTarget.clientWidth ?? measurementTarget.offsetWidth;
2636
+ const rawHeight = measurementTarget.getBoundingClientRect?.().height ?? measurementTarget.clientHeight ?? measurementTarget.offsetHeight;
2583
2637
  const nextWidth = normalizeWidth(rawWidth);
2584
- if (nextWidth <= 0) return;
2638
+ const nextHeight = normalizeHeight(rawHeight);
2639
+ if (nextWidth <= 0 || nextHeight <= 0) return;
2585
2640
  const previousWidth = lastWidthRef.current;
2586
- if (previousWidth != null && Math.abs(nextWidth - previousWidth) < WIDTH_HYSTERESIS_PX)
2587
- return;
2588
- lastWidthRef.current = nextWidth;
2589
- setAvailableWidth(nextWidth);
2641
+ const previousHeight = lastHeightRef.current;
2642
+ const widthChanged = previousWidth == null || Math.abs(nextWidth - previousWidth) >= WIDTH_HYSTERESIS_PX;
2643
+ const heightChanged = previousHeight == null || Math.abs(nextHeight - previousHeight) >= HEIGHT_HYSTERESIS_PX;
2644
+ if (!widthChanged && !heightChanged) return;
2645
+ if (widthChanged) {
2646
+ lastWidthRef.current = nextWidth;
2647
+ setAvailableWidth(nextWidth);
2648
+ }
2649
+ if (heightChanged) {
2650
+ lastHeightRef.current = nextHeight;
2651
+ setAvailableHeight(nextHeight);
2652
+ }
2590
2653
  };
2591
2654
  const scheduleWidthUpdate = () => {
2592
2655
  if (rafId != null) cancelAnimationFrame(rafId);
2593
2656
  rafId = requestAnimationFrame(() => {
2594
2657
  rafId = null;
2595
- updateWidth();
2658
+ updateSize();
2596
2659
  });
2597
2660
  };
2598
2661
  scheduleWidthUpdate();