@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.
- package/dist/esm/helpers/iframe-helper/fixer.d.ts +18 -0
- package/dist/esm/helpers/iframe-helper/fixer.d.ts.map +1 -0
- package/dist/esm/helpers/iframe-helper/index.d.ts +2 -0
- package/dist/esm/helpers/iframe-helper/index.d.ts.map +1 -0
- package/dist/esm/helpers/iframe-helper/init.d.ts +5 -0
- package/dist/esm/helpers/iframe-helper/init.d.ts.map +1 -0
- package/dist/esm/helpers/iframe-helper/navigation-blocker-v2.d.ts +28 -0
- package/dist/esm/helpers/iframe-helper/navigation-blocker-v2.d.ts.map +1 -0
- package/dist/esm/helpers/iframe-helper/navigation-blocker.d.ts +20 -0
- package/dist/esm/helpers/iframe-helper/navigation-blocker.d.ts.map +1 -0
- package/dist/{umd/helpers/viewport-replacer.d.ts → esm/helpers/iframe-helper/style-replacer.d.ts} +5 -5
- package/dist/esm/helpers/iframe-helper/style-replacer.d.ts.map +1 -0
- package/dist/esm/helpers/index.d.ts +1 -2
- package/dist/esm/helpers/index.d.ts.map +1 -1
- package/dist/esm/index.js +355 -36
- package/dist/esm/index.mjs +355 -36
- package/dist/esm/types/iframe-helper.d.ts +20 -0
- package/dist/esm/types/iframe-helper.d.ts.map +1 -0
- package/dist/esm/types/index.d.ts +1 -1
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/umd/helpers/iframe-helper/fixer.d.ts +18 -0
- package/dist/umd/helpers/iframe-helper/fixer.d.ts.map +1 -0
- package/dist/umd/helpers/iframe-helper/index.d.ts +2 -0
- package/dist/umd/helpers/iframe-helper/index.d.ts.map +1 -0
- package/dist/umd/helpers/iframe-helper/init.d.ts +5 -0
- package/dist/umd/helpers/iframe-helper/init.d.ts.map +1 -0
- package/dist/umd/helpers/iframe-helper/navigation-blocker-v2.d.ts +28 -0
- package/dist/umd/helpers/iframe-helper/navigation-blocker-v2.d.ts.map +1 -0
- package/dist/umd/helpers/iframe-helper/navigation-blocker.d.ts +20 -0
- package/dist/umd/helpers/iframe-helper/navigation-blocker.d.ts.map +1 -0
- package/dist/{esm/helpers/viewport-replacer.d.ts → umd/helpers/iframe-helper/style-replacer.d.ts} +5 -5
- package/dist/umd/helpers/iframe-helper/style-replacer.d.ts.map +1 -0
- package/dist/umd/helpers/index.d.ts +1 -2
- package/dist/umd/helpers/index.d.ts.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/types/iframe-helper.d.ts +20 -0
- package/dist/umd/types/iframe-helper.d.ts.map +1 -0
- package/dist/umd/types/index.d.ts +1 -1
- package/dist/umd/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/esm/helpers/viewport-fixer.d.ts +0 -15
- package/dist/esm/helpers/viewport-fixer.d.ts.map +0 -1
- package/dist/esm/helpers/viewport-replacer.d.ts.map +0 -1
- package/dist/esm/types/viewport-fixer.d.ts +0 -31
- package/dist/esm/types/viewport-fixer.d.ts.map +0 -1
- package/dist/umd/helpers/viewport-fixer.d.ts +0 -15
- package/dist/umd/helpers/viewport-fixer.d.ts.map +0 -1
- package/dist/umd/helpers/viewport-replacer.d.ts.map +0 -1
- package/dist/umd/types/viewport-fixer.d.ts +0 -31
- package/dist/umd/types/viewport-fixer.d.ts.map +0 -1
package/dist/esm/index.mjs
CHANGED
|
@@ -511,7 +511,300 @@ function isElementInViewport(elementRect, visualRef, scale) {
|
|
|
511
511
|
return elementBottom > viewportTop && elementTop < viewportBottom;
|
|
512
512
|
}
|
|
513
513
|
|
|
514
|
-
class
|
|
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(`[
|
|
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(`[
|
|
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('[
|
|
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('[
|
|
907
|
+
console.warn('[IframeStyleReplacer] Cannot read stylesheet (CORS?):', e.message);
|
|
615
908
|
}
|
|
616
909
|
});
|
|
617
|
-
console.log(`[
|
|
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('[
|
|
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('[
|
|
936
|
+
console.warn('[IframeStyleReplacer] Cannot load CSS:', link.href, e);
|
|
644
937
|
}
|
|
645
938
|
}
|
|
646
|
-
console.log(`[
|
|
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('[
|
|
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('[
|
|
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('[
|
|
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
|
|
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('[
|
|
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('[
|
|
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('[
|
|
728
|
-
//
|
|
729
|
-
this.replacer = new
|
|
730
|
-
//
|
|
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('[
|
|
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('[
|
|
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('[
|
|
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
|
-
|
|
1066
|
+
this.navigationBlocker?.destroy();
|
|
1067
|
+
this.navigationBlocker = null;
|
|
1068
|
+
console.log('[IframeHelper] Destroyed');
|
|
758
1069
|
}
|
|
759
1070
|
}
|
|
760
|
-
|
|
761
|
-
|
|
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('[
|
|
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
|
|
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
|
|
1304
|
-
const
|
|
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
|
-
|
|
1314
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
1364
|
-
return iframe;
|
|
1683
|
+
// fixer.recalculate();
|
|
1365
1684
|
}
|
|
1366
1685
|
|
|
1367
1686
|
function isMobileDevice(userAgent) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface IframeStyleConfig {
|
|
2
|
+
iframe: HTMLIFrameElement;
|
|
3
|
+
targetWidth: number;
|
|
4
|
+
targetHeight: number;
|
|
5
|
+
onSuccess?: (result: {
|
|
6
|
+
height: number;
|
|
7
|
+
width: number;
|
|
8
|
+
}) => void;
|
|
9
|
+
onError?: (error: Error) => void;
|
|
10
|
+
}
|
|
11
|
+
export interface IframeDimensionsDetail {
|
|
12
|
+
height: number;
|
|
13
|
+
width: number;
|
|
14
|
+
}
|
|
15
|
+
export interface IframeDebugInfo {
|
|
16
|
+
iframe: number;
|
|
17
|
+
body: number;
|
|
18
|
+
remaining: number;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=iframe-helper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iframe-helper.d.ts","sourceRoot":"","sources":["../../src/types/iframe-helper.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAChE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAE9B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAE9B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAE9B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAE9B,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { IframeStyleConfig } from '../../types';
|
|
2
|
+
export declare class IframeHelperFixer {
|
|
3
|
+
private iframe;
|
|
4
|
+
private config;
|
|
5
|
+
private replacer;
|
|
6
|
+
private navigationBlocker;
|
|
7
|
+
constructor(config: IframeStyleConfig);
|
|
8
|
+
private init;
|
|
9
|
+
private process;
|
|
10
|
+
recalculate(): Promise<void>;
|
|
11
|
+
updateConfig(config: Partial<IframeStyleConfig>): void;
|
|
12
|
+
enableNavigationBlocking(): void;
|
|
13
|
+
enableNavigationBlockingMessage(): void;
|
|
14
|
+
disableNavigationBlocking(): void;
|
|
15
|
+
disableNavigationBlockingMessage(): void;
|
|
16
|
+
destroy(): void;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=fixer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixer.d.ts","sourceRoot":"","sources":["../../../src/helpers/iframe-helper/fixer.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIxE,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,iBAAiB,CAA0C;gBAEvD,MAAM,EAAE,iBAAiB;YAMvB,IAAI;YAeJ,OAAO;IAoCR,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAKlC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAOtD,wBAAwB,IAAI,IAAI;IAGhC,+BAA+B,IAAI,IAAI;IAIvC,yBAAyB,IAAI,IAAI;IAGjC,gCAAgC,IAAI,IAAI;IAIxC,OAAO,IAAI,IAAI;CAMvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/helpers/iframe-helper/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { IframeDebugInfo, IframeStyleConfig } from '../../types';
|
|
2
|
+
import { IframeHelperFixer } from './fixer';
|
|
3
|
+
export declare function initIframeHelperFixer(config: IframeStyleConfig): IframeHelperFixer;
|
|
4
|
+
export declare function debugIframeStyle(): IframeDebugInfo | null;
|
|
5
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/helpers/iframe-helper/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAA0B,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,GAAG,iBAAiB,CAmBlF;AAED,wBAAgB,gBAAgB,IAAI,eAAe,GAAG,IAAI,CA+BzD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare class IframeNavigationBlockerV2 {
|
|
2
|
+
private doc;
|
|
3
|
+
private win;
|
|
4
|
+
private isEnabled;
|
|
5
|
+
private showMessage;
|
|
6
|
+
private originalWindowOpen;
|
|
7
|
+
private observers;
|
|
8
|
+
constructor(iframe: HTMLIFrameElement);
|
|
9
|
+
private init;
|
|
10
|
+
private blockLinkNavigation;
|
|
11
|
+
private disableAllLinks;
|
|
12
|
+
private blockFormSubmissions;
|
|
13
|
+
private blockWindowOpen;
|
|
14
|
+
private blockBeforeUnload;
|
|
15
|
+
private monitorDOMChanges;
|
|
16
|
+
private injectCSP;
|
|
17
|
+
private handleFormSubmit;
|
|
18
|
+
private notifyBlockedNavigation;
|
|
19
|
+
private shouldShowMessage;
|
|
20
|
+
private showBlockedMessage;
|
|
21
|
+
private escapeHtml;
|
|
22
|
+
enable(): void;
|
|
23
|
+
enableMessage(): void;
|
|
24
|
+
disable(): void;
|
|
25
|
+
disableMessage(): void;
|
|
26
|
+
destroy(): void;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=navigation-blocker-v2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation-blocker-v2.d.ts","sourceRoot":"","sources":["../../../src/helpers/iframe-helper/navigation-blocker-v2.ts"],"names":[],"mappings":"AAAA,qBAAa,yBAAyB;IACpC,OAAO,CAAC,GAAG,CAAW;IACtB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,SAAS,CAA0B;gBAE/B,MAAM,EAAE,iBAAiB;IAYrC,OAAO,CAAC,IAAI;IA0BZ,OAAO,CAAC,mBAAmB;IAyD3B,OAAO,CAAC,eAAe;IAkBvB,OAAO,CAAC,oBAAoB;IA4B5B,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,iBAAiB;IA0CzB,OAAO,CAAC,iBAAiB;IA4CzB,OAAO,CAAC,SAAS;IAgBjB,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,uBAAuB;IAc/B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,kBAAkB;IAoC1B,OAAO,CAAC,UAAU;IAMX,MAAM,IAAI,IAAI;IAKd,aAAa,IAAI,IAAI;IAKrB,OAAO,IAAI,IAAI;IAKf,cAAc,IAAI,IAAI;IAKtB,OAAO,IAAI,IAAI;CASvB"}
|