@merittdev/horus-lens 0.5.0 → 0.5.2

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/react.cjs CHANGED
@@ -29083,7 +29083,7 @@ var ApiErrorSchema = external_exports.object({
29083
29083
 
29084
29084
  // ../core/dist/index.js
29085
29085
  var SDK_NAME = "@merittdev/horus-lens";
29086
- var SDK_VERSION = true ? "0.5.0" : "0.0.0-dev";
29086
+ var SDK_VERSION = true ? "0.5.2" : "0.0.0-dev";
29087
29087
  var DEFAULT_ENDPOINT = "https://api.horus.sh";
29088
29088
  var DEFAULT_REPLAY_WINDOW_MS = 15e3;
29089
29089
  var DEFAULT_MAX_CONSOLE_ENTRIES = 200;
@@ -29095,6 +29095,7 @@ var MAX_SERIALIZED_ARG_CHARS = 2e3;
29095
29095
  var MAX_DOM_BYTES = 2 * 1024 * 1024;
29096
29096
  var MAX_TARGET_TEXT_CHARS = 200;
29097
29097
  var SCREENSHOT_TIMEOUT_MS = 2e4;
29098
+ var SCREENSHOT_RESOURCE_TIMEOUT_MS = 3500;
29098
29099
  var SCREENSHOT_MAX_SCALE = 2;
29099
29100
  var SCREENSHOT_MAX_PIXELS = 25e5;
29100
29101
  var AUTO_CAPTURE_COOLDOWN_MS = 10 * 60 * 1e3;
@@ -29649,6 +29650,14 @@ var ReplayRecorder = class {
29649
29650
  }
29650
29651
  };
29651
29652
  var SVG_RASTERIZE_TIMEOUT_MS = 3e3;
29653
+ function isOffscreenMedia(node2) {
29654
+ if (!(node2 instanceof HTMLImageElement) && !(node2 instanceof HTMLIFrameElement) && !(typeof HTMLVideoElement !== "undefined" && node2 instanceof HTMLVideoElement)) {
29655
+ return false;
29656
+ }
29657
+ const r = node2.getBoundingClientRect();
29658
+ if (r.width === 0 && r.height === 0) return false;
29659
+ return r.bottom < 0 || r.top > window.innerHeight || r.right < 0 || r.left > window.innerWidth;
29660
+ }
29652
29661
  function computeCropRect(crop, scale, rasterWidth, rasterHeight) {
29653
29662
  let sx = Math.round(crop.x * scale);
29654
29663
  let sy = Math.round(crop.y * scale);
@@ -29664,8 +29673,11 @@ function computeCropRect(crop, scale, rasterWidth, rasterHeight) {
29664
29673
  async function captureScreenshot(excludeHost, crop, composite) {
29665
29674
  if (typeof document === "undefined" || typeof window === "undefined") return null;
29666
29675
  try {
29667
- const viewportPixels = window.innerWidth * window.innerHeight || 1;
29668
- const pixelCap = Math.sqrt(SCREENSHOT_MAX_PIXELS / viewportPixels);
29676
+ const viewportOnly = !composite && !crop;
29677
+ const captureW = composite ? composite.docWidth : window.innerWidth;
29678
+ const captureH = composite ? composite.docHeight : window.innerHeight;
29679
+ const capturePixels = captureW * captureH || 1;
29680
+ const pixelCap = Math.sqrt(SCREENSHOT_MAX_PIXELS / capturePixels);
29669
29681
  const scale = Math.max(1, Math.min(window.devicePixelRatio || 1, SCREENSHOT_MAX_SCALE, pixelCap));
29670
29682
  const capture = domToBlob(document.documentElement, {
29671
29683
  scale,
@@ -29674,18 +29686,35 @@ async function captureScreenshot(excludeHost, crop, composite) {
29674
29686
  // JPEG has no alpha — transparent page regions (and any capture box
29675
29687
  // extending past short content) would otherwise encode as BLACK.
29676
29688
  backgroundColor: "#ffffff",
29677
- // When compositing annotations, force the capture box to the editor's
29678
- // document measurement (scrollHeight-based). modern-screenshot otherwise
29679
- // sizes from documentElement's bounding box, which on pages SHORTER than
29680
- // the viewport is the content height only — marks drawn in the lower
29681
- // viewport band would fall off the raster and the crop would clamp short.
29689
+ // Composite (annotations): force the capture box to the editor's document
29690
+ // measurement so marks in the lower viewport band aren't clipped.
29682
29691
  ...composite ? { width: composite.docWidth, height: composite.docHeight } : {},
29683
- // Exclude the overlay from the capture CLONE — never hide the live node.
29684
- filter: (node2) => node2 !== excludeHost,
29685
- // Per-resource fetch budget: a single slow cross-origin image must not
29686
- // consume the whole capture window.
29692
+ // Plain report: clip the render to the viewport and shift the scrolled
29693
+ // content into it, so only the visible region is rasterized/fetched.
29694
+ ...viewportOnly ? {
29695
+ width: window.innerWidth,
29696
+ height: window.innerHeight,
29697
+ style: {
29698
+ transform: `translate(${-window.scrollX}px, ${-window.scrollY}px)`,
29699
+ transformOrigin: "top left"
29700
+ }
29701
+ } : {},
29702
+ // Exclude the overlay from the capture CLONE (never hide the live node),
29703
+ // and — for a plain viewport report — drop images/iframes entirely outside
29704
+ // the viewport so we don't fetch dozens of off-screen cross-origin assets.
29705
+ filter: (node2) => {
29706
+ if (node2 === excludeHost) return false;
29707
+ if (viewportOnly && isOffscreenMedia(node2)) return false;
29708
+ return true;
29709
+ },
29710
+ // Skip web-font download/embed. On font-heavy pages (multiple custom
29711
+ // families) this is a dominant, flaky cost; fallback fonts are fine for a
29712
+ // bug-report screenshot and capture becomes far more reliable.
29713
+ font: false,
29687
29714
  fetch: { requestInit: { cache: "force-cache" }, bypassingCache: false },
29688
- timeout: SCREENSHOT_TIMEOUT_MS - 1e3
29715
+ // PER-RESOURCE cap (NOT the overall budget): a hanging asset fails fast to
29716
+ // a placeholder instead of stalling the whole capture.
29717
+ timeout: SCREENSHOT_RESOURCE_TIMEOUT_MS
29689
29718
  });
29690
29719
  const started = Date.now();
29691
29720
  const timeout = new Promise((resolve) => {
@@ -29714,14 +29743,8 @@ async function captureScreenshot(excludeHost, crop, composite) {
29714
29743
  return null;
29715
29744
  }
29716
29745
  }
29717
- const effectiveCrop = crop ?? (composite ? void 0 : {
29718
- x: window.scrollX,
29719
- y: window.scrollY,
29720
- width: window.innerWidth,
29721
- height: window.innerHeight
29722
- });
29723
- if (effectiveCrop) {
29724
- const cropped = await cropBlob(blob2, effectiveCrop, scale);
29746
+ if (crop) {
29747
+ const cropped = await cropBlob(blob2, crop, scale);
29725
29748
  return cropped ?? blob2;
29726
29749
  }
29727
29750
  return blob2;