@standhigher/besttrack-page-extension 0.5.8 → 0.5.10

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.
Files changed (2) hide show
  1. package/dist/index.js +39 -13
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -566,6 +566,7 @@ function syncTrackingQueryToUrl(type, value, contactValue = "") {
566
566
  }
567
567
  var TRACKING_RESULT_SELECTOR = "[data-tracking-result]";
568
568
  var TRACKING_RESULT_SCROLL_GAP = 8;
569
+ var TRACKING_RESULT_DEFAULT_SCROLL_OFFSET = 64;
569
570
  function scrollingParent(node) {
570
571
  let parent = node.parentElement;
571
572
  while (parent && parent !== document.body && parent !== document.documentElement) {
@@ -575,11 +576,13 @@ function scrollingParent(node) {
575
576
  }
576
577
  return null;
577
578
  }
578
- function isTopPinned(style) {
579
- if (style.position !== "sticky" && style.position !== "fixed") return false;
579
+ function isTopPinned(style, rect, portTop, themeHeader = false) {
580
580
  if (style.display === "none" || style.visibility === "hidden") return false;
581
+ if (themeHeader) return rect.bottom > portTop && rect.top <= portTop + 1;
582
+ if (style.position !== "sticky" && style.position !== "fixed") return false;
581
583
  const top = Number.parseFloat(style.top);
582
- return Number.isFinite(top) && top >= 0 && top <= 240;
584
+ if (Number.isFinite(top)) return top >= 0 && top <= 240;
585
+ return rect.bottom > portTop && rect.top <= portTop + 1;
583
586
  }
584
587
  function trackingResultScrollOffset(node) {
585
588
  if (typeof window === "undefined" || typeof document === "undefined") return 0;
@@ -591,18 +594,19 @@ function trackingResultScrollOffset(node) {
591
594
  const targetRect = node.getBoundingClientRect();
592
595
  let covered = 0;
593
596
  const seen = /* @__PURE__ */ new Set();
594
- const consider = (el) => {
597
+ const consider = (el, themeHeader = false) => {
595
598
  if (!(el instanceof HTMLElement) || seen.has(el) || el === node || node.contains(el)) return;
596
- seen.add(el);
597
599
  const style = getComputedStyle(el);
598
- if (!isTopPinned(style)) return;
599
- if (style.position !== "fixed" && scrollingParent(el) !== scrollPort) return;
600
600
  const rect = el.getBoundingClientRect();
601
+ if (!isTopPinned(style, rect, portTop, themeHeader)) return;
602
+ seen.add(el);
603
+ if (!themeHeader && style.position !== "fixed" && scrollingParent(el) !== scrollPort) return;
601
604
  if (rect.width <= 0 || rect.height <= 0) return;
602
605
  const overlapLeft = Math.max(rect.left, portLeft, targetRect.left);
603
606
  const overlapRight = Math.min(rect.right, portRight, Math.max(targetRect.right, targetRect.left));
604
607
  if (overlapRight - overlapLeft <= 8) return;
605
- const pinTop = Number.parseFloat(style.top) || 0;
608
+ const parsedTop = Number.parseFloat(style.top);
609
+ const pinTop = Number.isFinite(parsedTop) ? Math.max(0, parsedTop) : Math.max(0, rect.top - portTop);
606
610
  const precedes = (node.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_PRECEDING) !== 0;
607
611
  const coversPortTop = rect.bottom > portTop && rect.top <= portTop + pinTop + 1;
608
612
  if (!precedes && !coversPortTop) return;
@@ -610,10 +614,19 @@ function trackingResultScrollOffset(node) {
610
614
  };
611
615
  if (typeof document.elementsFromPoint === "function") {
612
616
  const x = targetRect.width > 0 ? Math.min(Math.max(targetRect.left + targetRect.width / 2, portLeft), portRight) : portLeft + (portRight - portLeft) / 2;
613
- document.elementsFromPoint(x, portTop + 1).forEach(consider);
617
+ document.elementsFromPoint(x, portTop + 1).forEach((el) => consider(el));
614
618
  }
615
- document.querySelectorAll("header, nav, [role='banner']").forEach(consider);
616
- return covered > 0 ? Math.ceil(covered + TRACKING_RESULT_SCROLL_GAP) : 0;
619
+ document.querySelectorAll("header, nav, [role='banner'], [role='navigation']").forEach((el) => consider(el));
620
+ document.querySelectorAll("sticky-header, .shopify-section-header-sticky, [data-sticky-header], [class*='header-sticky'], [class*='sticky-header']").forEach((el) => consider(el, true));
621
+ if (covered === 0) document.querySelectorAll("*").forEach((el) => consider(el));
622
+ const rootStyle = getComputedStyle(document.documentElement);
623
+ const bodyStyle = getComputedStyle(document.body);
624
+ const nodeStyle = getComputedStyle(node);
625
+ const configured = Number.parseFloat(
626
+ rootStyle.getPropertyValue("--bt-tracking-scroll-offset") || bodyStyle.getPropertyValue("--bt-tracking-scroll-offset") || nodeStyle.getPropertyValue("--bt-tracking-scroll-offset")
627
+ );
628
+ const minimum = Number.isFinite(configured) ? Math.max(0, configured) : TRACKING_RESULT_DEFAULT_SCROLL_OFFSET;
629
+ return Math.max(minimum, covered > 0 ? Math.ceil(covered + TRACKING_RESULT_SCROLL_GAP) : 0);
617
630
  }
618
631
  function scrollToTrackingResult(root = typeof document === "undefined" ? null : document, schedule = typeof requestAnimationFrame === "function" ? (callback) => {
619
632
  requestAnimationFrame(callback);
@@ -663,6 +676,7 @@ var POWERED_BY_HIDDEN_STORE_DOMAINS = /* @__PURE__ */ new Set([
663
676
  "nbstore-unlrgjwn.myshopify.com",
664
677
  "wavvveglobal.com"
665
678
  ]);
679
+ var TRACKING_PAGE_BOOTSTRAP_SCRIPT_ID = "besttrack-page-bootstrap";
666
680
  function getUrlParam2(params, key) {
667
681
  return params.get(key)?.trim() ?? "";
668
682
  }
@@ -672,11 +686,21 @@ var normalizeStoreDomain = (value) => {
672
686
  const host = trimmedValue.replace(/^[a-z][a-z\d+.-]*:\/\//i, "").replace(/^\/\//, "").split(/[/?#]/)[0].replace(/:\d+$/, "");
673
687
  return host.replace(/^www\./, "");
674
688
  };
689
+ function readBootstrapWatermarkRemoval(runtimeWindow) {
690
+ const raw = runtimeWindow.document?.getElementById?.(TRACKING_PAGE_BOOTSTRAP_SCRIPT_ID)?.textContent?.trim() ?? "";
691
+ if (!raw) return false;
692
+ try {
693
+ const parsed = JSON.parse(raw);
694
+ return parsed.enableTrackingPageWatermarkRemoval === true;
695
+ } catch {
696
+ return false;
697
+ }
698
+ }
675
699
  function shouldHidePoweredBy(targetWindow) {
676
700
  const runtimeWindow = targetWindow ?? (typeof window === "undefined" ? void 0 : window);
677
701
  if (!runtimeWindow) return false;
678
702
  const shopifyWindow = runtimeWindow;
679
- if (shopifyWindow.__BESTRACK__?.featureFlags?.enableTrackingPageWatermarkRemoval === true) {
703
+ if (shopifyWindow.__BESTRACK__?.featureFlags?.enableTrackingPageWatermarkRemoval === true || readBootstrapWatermarkRemoval(runtimeWindow)) {
680
704
  return true;
681
705
  }
682
706
  const searchParams = new URLSearchParams(runtimeWindow.location.search);
@@ -1533,7 +1557,9 @@ function configuredRecommendations(products) {
1533
1557
  title: product.title || product.id,
1534
1558
  description: "",
1535
1559
  imageUrl: product.imageUrl,
1536
- href: product.handle ? `/products/${product.handle}` : void 0,
1560
+ // Product snapshots only persist the Shopify handle. Resolve the generated
1561
+ // storefront path before RecommendationCards applies its URL safety check.
1562
+ href: resolveShopifyRecommendHref(void 0, product.handle),
1537
1563
  ...product.price ? { price: product.price } : {}
1538
1564
  }));
1539
1565
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@standhigher/besttrack-page-extension",
3
- "version": "0.5.8",
3
+ "version": "0.5.10",
4
4
  "description": "BestTrack business extension entry point for @standhigher/puck-page-builder.",
5
5
  "type": "module",
6
6
  "files": [
@@ -22,7 +22,7 @@
22
22
  "dependencies": {
23
23
  "embla-carousel-autoplay": "^8.6.0",
24
24
  "embla-carousel-react": "^8.6.0",
25
- "@standhigher/puck-page-builder": "0.12.8"
25
+ "@standhigher/puck-page-builder": "0.12.10"
26
26
  },
27
27
  "devDependencies": {
28
28
  "tsup": "^8.5.1",