@papyrus-sdk/ui-react 0.2.16 → 0.2.17

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.js CHANGED
@@ -1366,6 +1366,7 @@ var import_react4 = require("react");
1366
1366
  var import_core4 = require("@papyrus-sdk/core");
1367
1367
  var import_types = require("@papyrus-sdk/types");
1368
1368
  var import_jsx_runtime4 = require("react/jsx-runtime");
1369
+ var SCALE_PRECISION = 1e3;
1369
1370
  var PageRenderer = ({
1370
1371
  engine,
1371
1372
  pageIndex,
@@ -1437,21 +1438,22 @@ var PageRenderer = ({
1437
1438
  if (!availableWidth || !pageSize?.width) return 1;
1438
1439
  const targetWidth = Math.max(0, availableWidth - 48);
1439
1440
  if (!targetWidth) return 1;
1440
- return Math.min(1, targetWidth / pageSize.width);
1441
+ const rawScale = Math.min(1, targetWidth / pageSize.width);
1442
+ return Math.round(rawScale * SCALE_PRECISION) / SCALE_PRECISION;
1441
1443
  }, [availableWidth, pageSize]);
1442
1444
  const displaySize = (0, import_react4.useMemo)(() => {
1443
1445
  if (!pageSize) return null;
1444
1446
  const scale = zoom * fitScale;
1445
1447
  return {
1446
- width: pageSize.width * scale,
1447
- height: pageSize.height * scale
1448
+ width: Math.max(1, Math.round(pageSize.width * scale)),
1449
+ height: Math.max(1, Math.round(pageSize.height * scale))
1448
1450
  };
1449
1451
  }, [pageSize, zoom, fitScale]);
1450
1452
  (0, import_react4.useEffect)(() => {
1451
1453
  if (!displaySize || !onMeasuredSize) return;
1452
1454
  onMeasuredSize(pageIndex, {
1453
- width: Math.round(displaySize.width),
1454
- height: Math.round(displaySize.height)
1455
+ width: displaySize.width,
1456
+ height: displaySize.height
1455
1457
  });
1456
1458
  }, [displaySize, onMeasuredSize, pageIndex]);
1457
1459
  (0, import_react4.useEffect)(() => {
@@ -2102,6 +2104,8 @@ var import_jsx_runtime5 = require("react/jsx-runtime");
2102
2104
  var BASE_OVERSCAN = 6;
2103
2105
  var MIN_ZOOM = 0.2;
2104
2106
  var MAX_ZOOM = 5;
2107
+ var WIDTH_SNAP_PX = 4;
2108
+ var WIDTH_HYSTERESIS_PX = 6;
2105
2109
  var Viewer = ({ engine }) => {
2106
2110
  const {
2107
2111
  pageCount,
@@ -2172,26 +2176,47 @@ var Viewer = ({ engine }) => {
2172
2176
  []
2173
2177
  );
2174
2178
  (0, import_react5.useEffect)(() => {
2175
- const element = viewerRef.current;
2176
- if (!element) return;
2179
+ const viewerElement = viewerRef.current;
2180
+ if (!viewerElement) return;
2181
+ const measurementTarget = viewerElement.parentElement ?? viewerElement;
2182
+ let rafId = null;
2183
+ const normalizeWidth = (rawWidth) => Math.max(0, Math.floor(rawWidth / WIDTH_SNAP_PX) * WIDTH_SNAP_PX);
2177
2184
  const updateWidth = () => {
2178
- const rawWidth = element.getBoundingClientRect?.().width ?? element.offsetWidth;
2179
- const nextWidth = Math.round(rawWidth);
2185
+ const rawWidth = measurementTarget.getBoundingClientRect?.().width ?? measurementTarget.clientWidth ?? measurementTarget.offsetWidth;
2186
+ const nextWidth = normalizeWidth(rawWidth);
2180
2187
  if (nextWidth <= 0) return;
2181
2188
  const previousWidth = lastWidthRef.current;
2182
- if (previousWidth != null && Math.abs(nextWidth - previousWidth) < 2)
2189
+ if (previousWidth != null && Math.abs(nextWidth - previousWidth) < WIDTH_HYSTERESIS_PX)
2183
2190
  return;
2184
2191
  lastWidthRef.current = nextWidth;
2185
2192
  setAvailableWidth(nextWidth);
2186
2193
  };
2187
- updateWidth();
2194
+ const scheduleWidthUpdate = () => {
2195
+ if (rafId != null) cancelAnimationFrame(rafId);
2196
+ rafId = requestAnimationFrame(() => {
2197
+ rafId = null;
2198
+ updateWidth();
2199
+ });
2200
+ };
2201
+ scheduleWidthUpdate();
2188
2202
  if (typeof ResizeObserver === "undefined") {
2189
- window.addEventListener("resize", updateWidth);
2190
- return () => window.removeEventListener("resize", updateWidth);
2203
+ window.addEventListener("resize", scheduleWidthUpdate);
2204
+ window.visualViewport?.addEventListener("resize", scheduleWidthUpdate);
2205
+ return () => {
2206
+ if (rafId != null) cancelAnimationFrame(rafId);
2207
+ window.removeEventListener("resize", scheduleWidthUpdate);
2208
+ window.visualViewport?.removeEventListener(
2209
+ "resize",
2210
+ scheduleWidthUpdate
2211
+ );
2212
+ };
2191
2213
  }
2192
- const observer = new ResizeObserver(() => updateWidth());
2193
- observer.observe(element);
2194
- return () => observer.disconnect();
2214
+ const observer = new ResizeObserver(() => scheduleWidthUpdate());
2215
+ observer.observe(measurementTarget);
2216
+ return () => {
2217
+ if (rafId != null) cancelAnimationFrame(rafId);
2218
+ observer.disconnect();
2219
+ };
2195
2220
  }, []);
2196
2221
  (0, import_react5.useEffect)(() => {
2197
2222
  let active = true;