@gemx-dev/heatmap-react 3.5.43 → 3.5.44

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 (50) hide show
  1. package/dist/esm/helpers/iframe-helper/fixer.d.ts +18 -0
  2. package/dist/esm/helpers/iframe-helper/fixer.d.ts.map +1 -0
  3. package/dist/esm/helpers/iframe-helper/index.d.ts +2 -0
  4. package/dist/esm/helpers/iframe-helper/index.d.ts.map +1 -0
  5. package/dist/esm/helpers/iframe-helper/init.d.ts +5 -0
  6. package/dist/esm/helpers/iframe-helper/init.d.ts.map +1 -0
  7. package/dist/esm/helpers/iframe-helper/navigation-blocker-v2.d.ts +28 -0
  8. package/dist/esm/helpers/iframe-helper/navigation-blocker-v2.d.ts.map +1 -0
  9. package/dist/esm/helpers/iframe-helper/navigation-blocker.d.ts +20 -0
  10. package/dist/esm/helpers/iframe-helper/navigation-blocker.d.ts.map +1 -0
  11. package/dist/{umd/helpers/viewport-replacer.d.ts → esm/helpers/iframe-helper/style-replacer.d.ts} +5 -5
  12. package/dist/esm/helpers/iframe-helper/style-replacer.d.ts.map +1 -0
  13. package/dist/esm/helpers/index.d.ts +1 -2
  14. package/dist/esm/helpers/index.d.ts.map +1 -1
  15. package/dist/esm/index.js +355 -36
  16. package/dist/esm/index.mjs +355 -36
  17. package/dist/esm/types/iframe-helper.d.ts +20 -0
  18. package/dist/esm/types/iframe-helper.d.ts.map +1 -0
  19. package/dist/esm/types/index.d.ts +1 -1
  20. package/dist/esm/types/index.d.ts.map +1 -1
  21. package/dist/umd/helpers/iframe-helper/fixer.d.ts +18 -0
  22. package/dist/umd/helpers/iframe-helper/fixer.d.ts.map +1 -0
  23. package/dist/umd/helpers/iframe-helper/index.d.ts +2 -0
  24. package/dist/umd/helpers/iframe-helper/index.d.ts.map +1 -0
  25. package/dist/umd/helpers/iframe-helper/init.d.ts +5 -0
  26. package/dist/umd/helpers/iframe-helper/init.d.ts.map +1 -0
  27. package/dist/umd/helpers/iframe-helper/navigation-blocker-v2.d.ts +28 -0
  28. package/dist/umd/helpers/iframe-helper/navigation-blocker-v2.d.ts.map +1 -0
  29. package/dist/umd/helpers/iframe-helper/navigation-blocker.d.ts +20 -0
  30. package/dist/umd/helpers/iframe-helper/navigation-blocker.d.ts.map +1 -0
  31. package/dist/{esm/helpers/viewport-replacer.d.ts → umd/helpers/iframe-helper/style-replacer.d.ts} +5 -5
  32. package/dist/umd/helpers/iframe-helper/style-replacer.d.ts.map +1 -0
  33. package/dist/umd/helpers/index.d.ts +1 -2
  34. package/dist/umd/helpers/index.d.ts.map +1 -1
  35. package/dist/umd/index.js +2 -2
  36. package/dist/umd/types/iframe-helper.d.ts +20 -0
  37. package/dist/umd/types/iframe-helper.d.ts.map +1 -0
  38. package/dist/umd/types/index.d.ts +1 -1
  39. package/dist/umd/types/index.d.ts.map +1 -1
  40. package/package.json +1 -1
  41. package/dist/esm/helpers/viewport-fixer.d.ts +0 -15
  42. package/dist/esm/helpers/viewport-fixer.d.ts.map +0 -1
  43. package/dist/esm/helpers/viewport-replacer.d.ts.map +0 -1
  44. package/dist/esm/types/viewport-fixer.d.ts +0 -31
  45. package/dist/esm/types/viewport-fixer.d.ts.map +0 -1
  46. package/dist/umd/helpers/viewport-fixer.d.ts +0 -15
  47. package/dist/umd/helpers/viewport-fixer.d.ts.map +0 -1
  48. package/dist/umd/helpers/viewport-replacer.d.ts.map +0 -1
  49. package/dist/umd/types/viewport-fixer.d.ts +0 -31
  50. package/dist/umd/types/viewport-fixer.d.ts.map +0 -1
package/dist/esm/index.js CHANGED
@@ -511,7 +511,300 @@ function isElementInViewport(elementRect, visualRef, scale) {
511
511
  return elementBottom > viewportTop && elementTop < viewportBottom;
512
512
  }
513
513
 
514
- class ViewportUnitsReplacer {
514
+ class IframeNavigationBlockerV2 {
515
+ doc;
516
+ win;
517
+ isEnabled = false;
518
+ showMessage = false;
519
+ originalWindowOpen;
520
+ observers = [];
521
+ constructor(iframe) {
522
+ if (!iframe.contentDocument || !iframe.contentWindow) {
523
+ throw new Error('Iframe document or window not accessible');
524
+ }
525
+ this.doc = iframe.contentDocument;
526
+ this.win = iframe.contentWindow;
527
+ this.originalWindowOpen = this.win.open.bind(this.win);
528
+ this.init();
529
+ }
530
+ init() {
531
+ console.log('[NavigationBlocker] Initializing...');
532
+ try {
533
+ // Chặn navigation qua links
534
+ this.blockLinkNavigation();
535
+ // Chặn form submissions
536
+ this.blockFormSubmissions();
537
+ // Chặn window.open (này an toàn)
538
+ this.blockWindowOpen();
539
+ // Chặn beforeunload để prevent navigation
540
+ this.blockBeforeUnload();
541
+ // Monitor DOM changes để block dynamic links
542
+ this.monitorDOMChanges();
543
+ // Inject CSP nếu có thể
544
+ this.injectCSP();
545
+ }
546
+ catch (error) {
547
+ console.error('[NavigationBlocker] Init error:', error);
548
+ }
549
+ }
550
+ blockLinkNavigation() {
551
+ // Sử dụng capture phase để chặn sớm nhất
552
+ this.doc.addEventListener('click', (e) => {
553
+ if (!this.isEnabled)
554
+ return;
555
+ const target = e.target;
556
+ const link = target.closest('a');
557
+ if (link) {
558
+ const href = link.getAttribute('href');
559
+ // Cho phép hash links và empty links
560
+ if (!href || href === '' || href === '#' || href.startsWith('#')) {
561
+ console.log('[NavigationBlocker] Allowed hash navigation:', href);
562
+ return;
563
+ }
564
+ // Chặn tất cả các loại navigation
565
+ console.log('[NavigationBlocker] Blocked link navigation to:', href);
566
+ e.preventDefault();
567
+ e.stopPropagation();
568
+ e.stopImmediatePropagation();
569
+ this.notifyBlockedNavigation(href);
570
+ }
571
+ }, true);
572
+ // Chặn cả middle click và right click "open in new tab"
573
+ this.doc.addEventListener('auxclick', (e) => {
574
+ if (!this.isEnabled)
575
+ return;
576
+ const target = e.target;
577
+ const link = target.closest('a');
578
+ if (link) {
579
+ const href = link.getAttribute('href');
580
+ if (href && !href.startsWith('#')) {
581
+ console.log('[NavigationBlocker] Blocked auxclick navigation');
582
+ e.preventDefault();
583
+ e.stopPropagation();
584
+ e.stopImmediatePropagation();
585
+ }
586
+ }
587
+ }, true);
588
+ // Disable tất cả links ngay từ đầu
589
+ this.disableAllLinks();
590
+ }
591
+ disableAllLinks() {
592
+ this.doc.querySelectorAll('a[href]').forEach((link) => {
593
+ const href = link.getAttribute('href');
594
+ if (href && !href.startsWith('#')) {
595
+ // Thêm pointer-events: none và cursor
596
+ link.style.cursor = 'not-allowed';
597
+ link.setAttribute('data-navigation-blocked', 'true');
598
+ // Remove href để browser không hiện preview
599
+ link.setAttribute('data-original-href', href);
600
+ link.removeAttribute('href');
601
+ // Hoặc giữ href nhưng disable
602
+ // link.setAttribute('onclick', 'return false');
603
+ }
604
+ });
605
+ }
606
+ blockFormSubmissions() {
607
+ this.doc.addEventListener('submit', (e) => {
608
+ if (!this.isEnabled)
609
+ return;
610
+ const form = e.target;
611
+ const action = form.getAttribute('action');
612
+ // Cho phép forms không có action
613
+ if (!action || action === '' || action === '#') {
614
+ console.log('[NavigationBlocker] Allowed same-page form');
615
+ e.preventDefault();
616
+ this.handleFormSubmit(form);
617
+ return;
618
+ }
619
+ // Chặn tất cả external submissions
620
+ console.log('[NavigationBlocker] Blocked form submission to:', action);
621
+ e.preventDefault();
622
+ e.stopPropagation();
623
+ e.stopImmediatePropagation();
624
+ this.notifyBlockedNavigation(action);
625
+ }, true);
626
+ }
627
+ blockWindowOpen() {
628
+ // Override window.open - đây là safe
629
+ this.win.open = ((...args) => {
630
+ if (!this.isEnabled) {
631
+ return this.originalWindowOpen(...args);
632
+ }
633
+ const url = args[0]?.toString() || 'popup';
634
+ console.log('[NavigationBlocker] Blocked window.open:', url);
635
+ this.notifyBlockedNavigation(url);
636
+ return null;
637
+ });
638
+ }
639
+ blockBeforeUnload() {
640
+ // Chặn unload
641
+ this.win.addEventListener('beforeunload', (e) => {
642
+ if (!this.isEnabled)
643
+ return;
644
+ console.log('[NavigationBlocker] Blocked beforeunload');
645
+ e.preventDefault();
646
+ e.returnValue = '';
647
+ return '';
648
+ }, true);
649
+ // Chặn unload
650
+ this.win.addEventListener('unload', (e) => {
651
+ if (!this.isEnabled)
652
+ return;
653
+ console.log('[NavigationBlocker] Blocked unload');
654
+ e.preventDefault();
655
+ e.stopPropagation();
656
+ }, true);
657
+ // Monitor popstate
658
+ this.win.addEventListener('popstate', (e) => {
659
+ if (!this.isEnabled)
660
+ return;
661
+ console.log('[NavigationBlocker] Blocked popstate');
662
+ e.preventDefault();
663
+ e.stopPropagation();
664
+ }, true);
665
+ }
666
+ monitorDOMChanges() {
667
+ // Monitor khi có links mới được thêm vào
668
+ const observer = new MutationObserver((mutations) => {
669
+ if (!this.isEnabled)
670
+ return;
671
+ mutations.forEach((mutation) => {
672
+ mutation.addedNodes.forEach((node) => {
673
+ if (node.nodeType === Node.ELEMENT_NODE) {
674
+ const element = node;
675
+ // Nếu là link
676
+ if (element.tagName === 'A') {
677
+ const href = element.getAttribute('href');
678
+ if (href && !href.startsWith('#')) {
679
+ element.style.cursor = 'not-allowed';
680
+ element.setAttribute('data-navigation-blocked', 'true');
681
+ element.setAttribute('data-original-href', href);
682
+ element.removeAttribute('href');
683
+ }
684
+ }
685
+ // Tìm links trong subtree
686
+ element.querySelectorAll('a[href]').forEach((link) => {
687
+ const href = link.getAttribute('href');
688
+ if (href && !href.startsWith('#')) {
689
+ link.style.cursor = 'not-allowed';
690
+ link.setAttribute('data-navigation-blocked', 'true');
691
+ link.setAttribute('data-original-href', href);
692
+ link.removeAttribute('href');
693
+ }
694
+ });
695
+ }
696
+ });
697
+ });
698
+ });
699
+ observer.observe(this.doc.body, {
700
+ childList: true,
701
+ subtree: true,
702
+ });
703
+ this.observers.push(observer);
704
+ }
705
+ injectCSP() {
706
+ // Thêm CSP meta tag nếu chưa có (optional)
707
+ try {
708
+ const existingCSP = this.doc.querySelector('meta[http-equiv="Content-Security-Policy"]');
709
+ if (!existingCSP) {
710
+ const meta = this.doc.createElement('meta');
711
+ meta.httpEquiv = 'Content-Security-Policy';
712
+ meta.content = "navigate-to 'none'"; // Chặn tất cả navigation
713
+ this.doc.head.appendChild(meta);
714
+ console.log('[NavigationBlocker] Injected CSP');
715
+ }
716
+ }
717
+ catch (error) {
718
+ console.warn('[NavigationBlocker] Could not inject CSP:', error);
719
+ }
720
+ }
721
+ handleFormSubmit(form) {
722
+ const formData = new FormData(form);
723
+ const data = {};
724
+ formData.forEach((value, key) => {
725
+ data[key] = value;
726
+ });
727
+ console.log('[NavigationBlocker] Handling form data:', data);
728
+ window.dispatchEvent(new CustomEvent('iframe-form-submit', {
729
+ detail: { form, data },
730
+ }));
731
+ }
732
+ notifyBlockedNavigation(url) {
733
+ console.warn('[NavigationBlocker] Navigation blocked to:', url);
734
+ window.dispatchEvent(new CustomEvent('iframe-navigation-blocked', {
735
+ detail: { url, timestamp: Date.now() },
736
+ }));
737
+ if (this.shouldShowMessage(url)) {
738
+ this.showBlockedMessage(url);
739
+ }
740
+ }
741
+ shouldShowMessage(url) {
742
+ return !url.startsWith('#') && url !== 'reload' && url !== 'popup';
743
+ }
744
+ showBlockedMessage(url) {
745
+ if (!this.showMessage)
746
+ return;
747
+ const message = this.doc.createElement('div');
748
+ message.style.cssText = `
749
+ position: fixed;
750
+ top: 20px;
751
+ right: 20px;
752
+ background: #ff6b6b;
753
+ color: white;
754
+ padding: 12px 20px;
755
+ border-radius: 8px;
756
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
757
+ z-index: 999999;
758
+ font-family: system-ui, -apple-system, sans-serif;
759
+ font-size: 14px;
760
+ max-width: 300px;
761
+ word-break: break-word;
762
+ pointer-events: none;
763
+ `;
764
+ const shortUrl = url.length > 50 ? url.substring(0, 47) + '...' : url;
765
+ message.innerHTML = `
766
+ <div style="font-weight: 600; margin-bottom: 4px;">🚫 Navigation Blocked</div>
767
+ <div style="font-size: 12px; opacity: 0.9;">${this.escapeHtml(shortUrl)}</div>
768
+ `;
769
+ this.doc.body.appendChild(message);
770
+ setTimeout(() => {
771
+ message.style.opacity = '0';
772
+ message.style.transition = 'opacity 0.3s';
773
+ setTimeout(() => message.remove(), 300);
774
+ }, 3000);
775
+ }
776
+ escapeHtml(text) {
777
+ const div = this.doc.createElement('div');
778
+ div.textContent = text;
779
+ return div.innerHTML;
780
+ }
781
+ enable() {
782
+ this.isEnabled = true;
783
+ console.log('[NavigationBlocker] Enabled');
784
+ }
785
+ enableMessage() {
786
+ this.showMessage = true;
787
+ console.log('[NavigationBlocker] Enabled message');
788
+ }
789
+ disable() {
790
+ this.isEnabled = false;
791
+ console.log('[NavigationBlocker] Disabled');
792
+ }
793
+ disableMessage() {
794
+ this.showMessage = false;
795
+ console.log('[NavigationBlocker] Disabled message');
796
+ }
797
+ destroy() {
798
+ this.isEnabled = false;
799
+ this.showMessage = false;
800
+ // Cleanup observers
801
+ this.observers.forEach((observer) => observer.disconnect());
802
+ this.observers = [];
803
+ console.log('[NavigationBlocker] Destroyed');
804
+ }
805
+ }
806
+
807
+ class IframeStyleReplacer {
515
808
  doc;
516
809
  win;
517
810
  config;
@@ -556,7 +849,7 @@ class ViewportUnitsReplacer {
556
849
  count++;
557
850
  }
558
851
  });
559
- console.log(`[ViewportReplacer] Replaced ${count} inline style elements`);
852
+ console.log(`[IframeStyleReplacer] Replaced ${count} inline style elements`);
560
853
  return count;
561
854
  }
562
855
  processStyleTags() {
@@ -569,7 +862,7 @@ class ViewportUnitsReplacer {
569
862
  count++;
570
863
  }
571
864
  });
572
- console.log(`[ViewportReplacer] Replaced ${count} <style> tags`);
865
+ console.log(`[IframeStyleReplacer] Replaced ${count} <style> tags`);
573
866
  return count;
574
867
  }
575
868
  processRule(rule) {
@@ -600,7 +893,7 @@ class ViewportUnitsReplacer {
600
893
  try {
601
894
  // Bỏ qua external CSS (cross-origin)
602
895
  if (sheet.href && !sheet.href.startsWith(this.win.location.origin)) {
603
- console.log('[ViewportReplacer] Skipping external CSS:', sheet.href);
896
+ console.log('[IframeStyleReplacer] Skipping external CSS:', sheet.href);
604
897
  return;
605
898
  }
606
899
  const rules = sheet.cssRules || sheet.rules;
@@ -611,10 +904,10 @@ class ViewportUnitsReplacer {
611
904
  }
612
905
  }
613
906
  catch (e) {
614
- console.warn('[ViewportReplacer] Cannot read stylesheet (CORS?):', e.message);
907
+ console.warn('[IframeStyleReplacer] Cannot read stylesheet (CORS?):', e.message);
615
908
  }
616
909
  });
617
- console.log(`[ViewportReplacer] Replaced ${total} rules in stylesheets`);
910
+ console.log(`[IframeStyleReplacer] Replaced ${total} rules in stylesheets`);
618
911
  return total;
619
912
  }
620
913
  async processLinkedStylesheets() {
@@ -622,7 +915,7 @@ class ViewportUnitsReplacer {
622
915
  let count = 0;
623
916
  for (const link of Array.from(links)) {
624
917
  if (!link.href.startsWith(this.win.location.origin)) {
625
- console.log('[ViewportReplacer] Skipping external CSS:', link.href);
918
+ console.log('[IframeStyleReplacer] Skipping external CSS:', link.href);
626
919
  continue;
627
920
  }
628
921
  try {
@@ -640,10 +933,10 @@ class ViewportUnitsReplacer {
640
933
  }
641
934
  }
642
935
  catch (e) {
643
- console.warn('[ViewportReplacer] Cannot load CSS:', link.href, e);
936
+ console.warn('[IframeStyleReplacer] Cannot load CSS:', link.href, e);
644
937
  }
645
938
  }
646
- console.log(`[ViewportReplacer] Replaced ${count} linked CSS files`);
939
+ console.log(`[IframeStyleReplacer] Replaced ${count} linked CSS files`);
647
940
  return count;
648
941
  }
649
942
  getFinalHeight() {
@@ -667,7 +960,7 @@ class ViewportUnitsReplacer {
667
960
  }
668
961
  async run() {
669
962
  try {
670
- console.log('[ViewportReplacer] Starting viewport units replacement...');
963
+ console.log('[IframeStyleReplacer] Starting viewport units replacement...');
671
964
  this.processInlineStyles();
672
965
  this.processStyleTags();
673
966
  this.processStylesheets();
@@ -677,13 +970,13 @@ class ViewportUnitsReplacer {
677
970
  requestAnimationFrame(() => {
678
971
  const height = this.getFinalHeight();
679
972
  const width = this.getFinalWidth();
680
- console.log('[ViewportReplacer] Calculated dimensions:', { height, width });
973
+ console.log('[IframeStyleReplacer] Calculated dimensions:', { height, width });
681
974
  resolve({ height, width });
682
975
  });
683
976
  });
684
977
  }
685
978
  catch (err) {
686
- console.error('[ViewportReplacer] Critical error:', err);
979
+ console.error('[IframeStyleReplacer] Critical error:', err);
687
980
  return {
688
981
  height: this.doc.body.scrollHeight || 1000,
689
982
  width: this.doc.body.scrollWidth || 1000,
@@ -695,10 +988,11 @@ class ViewportUnitsReplacer {
695
988
  }
696
989
  }
697
990
 
698
- class ViewportUnitsFixer {
991
+ class IframeHelperFixer {
699
992
  iframe;
700
993
  config;
701
994
  replacer = null;
995
+ navigationBlocker = null;
702
996
  constructor(config) {
703
997
  this.config = config;
704
998
  this.iframe = config.iframe;
@@ -706,10 +1000,11 @@ class ViewportUnitsFixer {
706
1000
  }
707
1001
  async init() {
708
1002
  if (!this.iframe) {
709
- console.error('[ViewportFixer] iframe not found');
1003
+ console.error('[IframeHelper] iframe not found');
710
1004
  this.config.onError?.(new Error('iframe not found'));
711
1005
  return;
712
1006
  }
1007
+ // Wait for iframe to load completely
713
1008
  if (this.iframe.contentDocument?.readyState === 'complete') {
714
1009
  await this.process();
715
1010
  }
@@ -719,17 +1014,19 @@ class ViewportUnitsFixer {
719
1014
  }
720
1015
  async process() {
721
1016
  if (!this.iframe.contentDocument || !this.iframe.contentWindow) {
722
- console.error('[ViewportFixer] Cannot access iframe document');
1017
+ console.error('[IframeHelper] Cannot access iframe document');
723
1018
  this.config.onError?.(new Error('Cannot access iframe document'));
724
1019
  return;
725
1020
  }
726
1021
  try {
727
- console.log('[ViewportFixer] Processing viewport units...');
728
- // Tạo replacer instance với iframe và config
729
- this.replacer = new ViewportUnitsReplacer(this.iframe, this.config);
730
- // Chạy replacement
1022
+ console.log('[IframeHelper] Processing viewport units...');
1023
+ // Create replacer instance
1024
+ this.replacer = new IframeStyleReplacer(this.iframe, this.config);
1025
+ // Create navigation blocker
1026
+ this.navigationBlocker = new IframeNavigationBlockerV2(this.iframe);
1027
+ // Run replacement
731
1028
  const result = await this.replacer.run();
732
- console.log('[ViewportFixer] Process completed:', result);
1029
+ console.log('[IframeHelper] Process completed:', result);
733
1030
  // Trigger success callback
734
1031
  this.config.onSuccess?.(result);
735
1032
  // Dispatch custom event
@@ -738,12 +1035,12 @@ class ViewportUnitsFixer {
738
1035
  }));
739
1036
  }
740
1037
  catch (error) {
741
- console.error('[ViewportFixer] Failed to process:', error);
1038
+ console.error('[IframeHelper] Failed to process:', error);
742
1039
  this.config.onError?.(error);
743
1040
  }
744
1041
  }
745
1042
  async recalculate() {
746
- console.log('[ViewportFixer] Recalculating...');
1043
+ console.log('[IframeHelper] Recalculating...');
747
1044
  await this.process();
748
1045
  }
749
1046
  updateConfig(config) {
@@ -752,16 +1049,39 @@ class ViewportUnitsFixer {
752
1049
  this.replacer.updateConfig(config);
753
1050
  }
754
1051
  }
1052
+ enableNavigationBlocking() {
1053
+ this.navigationBlocker?.enable();
1054
+ }
1055
+ enableNavigationBlockingMessage() {
1056
+ this.navigationBlocker?.enableMessage();
1057
+ }
1058
+ disableNavigationBlocking() {
1059
+ this.navigationBlocker?.disable();
1060
+ }
1061
+ disableNavigationBlockingMessage() {
1062
+ this.navigationBlocker?.disableMessage();
1063
+ }
755
1064
  destroy() {
756
1065
  this.replacer = null;
757
- console.log('[ViewportFixer] Destroyed');
1066
+ this.navigationBlocker?.destroy();
1067
+ this.navigationBlocker = null;
1068
+ console.log('[IframeHelper] Destroyed');
758
1069
  }
759
1070
  }
760
- function initViewportFixer(config) {
761
- const fixer = new ViewportUnitsFixer(config);
1071
+
1072
+ function initIframeHelperFixer(config) {
1073
+ const fixer = new IframeHelperFixer(config);
762
1074
  window.addEventListener('iframe-dimensions-applied', ((e) => {
763
1075
  const ev = e;
764
- console.log('[ViewportFixer] Iframe dimensions finalized:', ev.detail);
1076
+ console.log('[IframeHelper] Iframe dimensions finalized:', ev.detail);
1077
+ }));
1078
+ window.addEventListener('iframe-navigation-blocked', ((e) => {
1079
+ const ev = e;
1080
+ console.warn('[IframeHelper] Iframe tried to navigate to:', ev.detail.url);
1081
+ }));
1082
+ window.addEventListener('iframe-form-submit', ((e) => {
1083
+ const ev = e;
1084
+ console.log('[IframeHelper] Iframe form submitted:', ev.detail.data);
765
1085
  }));
766
1086
  return fixer;
767
1087
  }
@@ -1291,7 +1611,7 @@ function useVizLiveRender() {
1291
1611
  if (!iframe || !htmlContent)
1292
1612
  return;
1293
1613
  setIsRenderViz(false);
1294
- reset$1(iframe, { width: contentWidth, height: wrapperHeight }, (height) => {
1614
+ reset(iframe, { width: contentWidth, height: wrapperHeight }, (height) => {
1295
1615
  height && setIframeHeight(height);
1296
1616
  setIsRenderViz(true);
1297
1617
  });
@@ -1300,8 +1620,8 @@ function useVizLiveRender() {
1300
1620
  iframeRef,
1301
1621
  };
1302
1622
  }
1303
- function reset$1(iframe, rect, onSuccess) {
1304
- const viewportFixer = initViewportFixer({
1623
+ function reset(iframe, rect, onSuccess) {
1624
+ const fixer = initIframeHelperFixer({
1305
1625
  targetWidth: rect.width,
1306
1626
  targetHeight: rect.height,
1307
1627
  iframe: iframe,
@@ -1310,8 +1630,8 @@ function reset$1(iframe, rect, onSuccess) {
1310
1630
  onSuccess(data.height);
1311
1631
  },
1312
1632
  });
1313
- viewportFixer.recalculate();
1314
- return iframe;
1633
+ // fixer.recalculate();
1634
+ fixer.enableNavigationBlocking();
1315
1635
  }
1316
1636
 
1317
1637
  let visualizer = new Visualizer();
@@ -1329,7 +1649,7 @@ const useHeatmapRender = () => {
1329
1649
  if (!iframe?.contentWindow)
1330
1650
  return;
1331
1651
  await visualizer.html(payloads, iframe.contentWindow);
1332
- reset(iframe, payloads, (height) => {
1652
+ initIframe(iframe, payloads, (height) => {
1333
1653
  height && setIframeHeight(height);
1334
1654
  setIsRenderViz(true);
1335
1655
  setVizRef(visualizer);
@@ -1347,11 +1667,11 @@ const useHeatmapRender = () => {
1347
1667
  iframeRef,
1348
1668
  };
1349
1669
  };
1350
- function reset(iframe, payloads, onSuccess) {
1670
+ function initIframe(iframe, payloads, onSuccess) {
1351
1671
  const { size } = findLastSizeOfDom(payloads);
1352
1672
  const docWidth = size.width ?? 0;
1353
1673
  const docHeight = size.height ?? 0;
1354
- const viewportFixer = initViewportFixer({
1674
+ initIframeHelperFixer({
1355
1675
  targetWidth: docWidth,
1356
1676
  targetHeight: docHeight,
1357
1677
  iframe: iframe,
@@ -1360,8 +1680,7 @@ function reset(iframe, payloads, onSuccess) {
1360
1680
  onSuccess(data.height);
1361
1681
  },
1362
1682
  });
1363
- viewportFixer.recalculate();
1364
- return iframe;
1683
+ // fixer.recalculate();
1365
1684
  }
1366
1685
 
1367
1686
  function isMobileDevice(userAgent) {