@gemx-dev/heatmap-react 3.5.44 → 3.5.46
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/components/Layout/ContentHeader.d.ts +4 -0
- package/dist/esm/components/Layout/ContentHeader.d.ts.map +1 -0
- package/dist/esm/components/Layout/VizMode.d.ts +2 -0
- package/dist/esm/components/Layout/VizMode.d.ts.map +1 -0
- package/dist/esm/components/Test.d.ts +121 -0
- package/dist/esm/components/Test.d.ts.map +1 -0
- package/dist/esm/components/VizDom/VizDomContainer.d.ts +6 -0
- package/dist/esm/components/VizDom/VizDomContainer.d.ts.map +1 -0
- package/dist/esm/components/VizDom/VizDomRenderer.d.ts.map +1 -1
- package/dist/esm/components/VizElement/ClickedElementOverlay.d.ts +17 -0
- package/dist/esm/components/VizElement/ClickedElementOverlay.d.ts.map +1 -0
- package/dist/esm/components/VizElement/HeatmapElements.d.ts.map +1 -1
- package/dist/esm/components/VizElement/HoveredElementOverlay.d.ts +12 -0
- package/dist/esm/components/VizElement/HoveredElementOverlay.d.ts.map +1 -0
- package/dist/esm/components/VizElement/MissingElementMessage.d.ts +7 -0
- package/dist/esm/components/VizElement/MissingElementMessage.d.ts.map +1 -0
- package/dist/esm/components/VizElement/VizElements.d.ts.map +1 -1
- package/dist/esm/components/VizElement/temp/ClarityVisualizer.d.ts +150 -0
- package/dist/esm/components/VizElement/temp/ClarityVisualizer.d.ts.map +1 -0
- package/dist/esm/components/VizElement/temp/VizElementRank.d.ts +74 -0
- package/dist/esm/components/VizElement/temp/VizElementRank.d.ts.map +1 -0
- package/dist/esm/components/VizLive/VizLive.d.ts +2 -0
- package/dist/esm/components/VizLive/VizLive.d.ts.map +1 -0
- package/dist/esm/components/VizLive/VizLiveHeatmap.d.ts.map +1 -1
- package/dist/esm/components/VizLive/VizLiveRenderer.d.ts.map +1 -1
- package/dist/esm/configs/style.d.ts +0 -2
- package/dist/esm/configs/style.d.ts.map +1 -1
- package/dist/esm/helpers/index.d.ts +2 -1
- package/dist/esm/helpers/index.d.ts.map +1 -1
- package/dist/esm/helpers/viewport-fixer.d.ts +13 -0
- package/dist/esm/helpers/viewport-fixer.d.ts.map +1 -0
- package/dist/esm/helpers/viewport-replacer.d.ts +26 -0
- package/dist/esm/helpers/viewport-replacer.d.ts.map +1 -0
- package/dist/esm/hooks/vix-elements/useHoveredElement.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useClickmap.d.ts +1 -3
- package/dist/esm/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +1 -1
- package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts +1 -3
- package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/esm/hooks/viz-live/index.d.ts +1 -1
- package/dist/esm/hooks/viz-live/{useVizLiveIframeMsg.d.ts → useIframeMessage.d.ts} +10 -2
- package/dist/esm/hooks/viz-live/useIframeMessage.d.ts.map +1 -0
- package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useContainerDimensions.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts +1 -1
- package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts +10 -0
- package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts.map +1 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +203 -910
- package/dist/esm/index.mjs +203 -910
- package/dist/esm/stores/index.d.ts +0 -1
- package/dist/esm/stores/index.d.ts.map +1 -1
- package/dist/esm/stores/interaction.d.ts.map +1 -1
- package/dist/esm/stores/mode-live.d.ts +0 -4
- package/dist/esm/stores/mode-live.d.ts.map +1 -1
- package/dist/esm/stores/viz.d.ts +4 -0
- package/dist/esm/stores/viz.d.ts.map +1 -1
- package/dist/esm/types/index.d.ts +1 -1
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/types/viewport-fixer.d.ts +31 -0
- package/dist/esm/types/viewport-fixer.d.ts.map +1 -0
- package/dist/umd/components/Layout/ContentHeader.d.ts +4 -0
- package/dist/umd/components/Layout/ContentHeader.d.ts.map +1 -0
- package/dist/umd/components/Test.d.ts +121 -0
- package/dist/umd/components/Test.d.ts.map +1 -0
- package/dist/umd/components/VizDom/VizDomContainer.d.ts +2 -0
- package/dist/umd/components/VizDom/VizDomContainer.d.ts.map +1 -0
- package/dist/umd/components/VizDom/VizDomRenderer.d.ts.map +1 -1
- package/dist/umd/components/VizElement/ClickedElementOverlay.d.ts +17 -0
- package/dist/umd/components/VizElement/ClickedElementOverlay.d.ts.map +1 -0
- package/dist/umd/components/VizElement/HeatmapElements.d.ts.map +1 -1
- package/dist/umd/components/VizElement/HoveredElementOverlay.d.ts +12 -0
- package/dist/umd/components/VizElement/HoveredElementOverlay.d.ts.map +1 -0
- package/dist/umd/components/VizElement/MissingElementMessage.d.ts +7 -0
- package/dist/umd/components/VizElement/MissingElementMessage.d.ts.map +1 -0
- package/dist/umd/components/VizElement/VizElements.d.ts.map +1 -1
- package/dist/umd/components/VizElement/temp/ClarityVisualizer.d.ts +150 -0
- package/dist/umd/components/VizElement/temp/ClarityVisualizer.d.ts.map +1 -0
- package/dist/umd/components/VizElement/temp/VizElementRank.d.ts +74 -0
- package/dist/umd/components/VizElement/temp/VizElementRank.d.ts.map +1 -0
- package/dist/umd/components/VizLive/VizLiveHeatmap.d.ts.map +1 -1
- package/dist/umd/components/VizLive/VizLiveRenderer.d.ts.map +1 -1
- package/dist/umd/configs/style.d.ts +0 -2
- package/dist/umd/configs/style.d.ts.map +1 -1
- package/dist/umd/helpers/index.d.ts +2 -1
- package/dist/umd/helpers/index.d.ts.map +1 -1
- package/dist/umd/helpers/viewport-fixer.d.ts +13 -0
- package/dist/umd/helpers/viewport-fixer.d.ts.map +1 -0
- package/dist/umd/helpers/viewport-replacer.d.ts +26 -0
- package/dist/umd/helpers/viewport-replacer.d.ts.map +1 -0
- package/dist/umd/hooks/vix-elements/useHoveredElement.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useClickmap.d.ts +1 -3
- package/dist/umd/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +1 -1
- package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts +1 -3
- package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/umd/hooks/viz-live/index.d.ts +1 -1
- package/dist/umd/hooks/viz-live/{useVizLiveIframeMsg.d.ts → useIframeMessage.d.ts} +10 -2
- package/dist/umd/hooks/viz-live/useIframeMessage.d.ts.map +1 -0
- package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useContainerDimensions.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts +1 -1
- package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts +10 -0
- package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts.map +1 -0
- package/dist/umd/index.d.ts +1 -1
- package/dist/umd/index.d.ts.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/stores/index.d.ts +0 -1
- package/dist/umd/stores/index.d.ts.map +1 -1
- package/dist/umd/stores/interaction.d.ts.map +1 -1
- package/dist/umd/stores/mode-live.d.ts +0 -4
- package/dist/umd/stores/mode-live.d.ts.map +1 -1
- package/dist/umd/stores/viz.d.ts +4 -0
- package/dist/umd/stores/viz.d.ts.map +1 -1
- package/dist/umd/types/index.d.ts +1 -1
- package/dist/umd/types/index.d.ts.map +1 -1
- package/dist/umd/types/viewport-fixer.d.ts +31 -0
- package/dist/umd/types/viewport-fixer.d.ts.map +1 -0
- package/package.json +13 -15
- package/src/components/GraphView.tsx +58 -0
- package/src/components/Layout/ContentMetricBar.tsx +23 -0
- package/src/components/Layout/ContentToolbar.tsx +22 -0
- package/src/components/Layout/ContentTopBar.tsx +24 -0
- package/src/components/Layout/ContentVizByMode.tsx +14 -0
- package/src/components/Layout/HeatmapLayout.tsx +60 -0
- package/src/components/Layout/LeftSidebar.tsx +44 -0
- package/src/components/Layout/WrapperLayout.tsx +12 -0
- package/src/components/Layout/WrapperPreview.tsx +24 -0
- package/src/components/Layout/index.ts +1 -0
- package/src/components/VizDom/ReplayControls.tsx +48 -0
- package/src/components/VizDom/VizContainer.tsx +40 -0
- package/src/components/VizDom/VizDomHeatmap.tsx +28 -0
- package/src/components/VizDom/VizDomRenderer.tsx +82 -0
- package/src/components/VizDom/VizLoading.tsx +8 -0
- package/src/components/VizDom/WrapperVisual.tsx +73 -0
- package/src/components/VizDom/index.ts +5 -0
- package/src/components/VizElement/DefaultRankBadges.tsx +36 -0
- package/src/components/VizElement/ElementCallout.tsx +82 -0
- package/src/components/VizElement/ElementMissing.tsx +35 -0
- package/src/components/VizElement/ElementOverlay.tsx +66 -0
- package/src/components/VizElement/HeatmapElements.tsx +127 -0
- package/src/components/VizElement/HeatmapExample.tsx +70 -0
- package/src/components/VizElement/RankBadge.tsx +25 -0
- package/src/components/VizElement/VizElements.tsx +57 -0
- package/src/components/VizElement/index.ts +1 -0
- package/src/components/VizLive/VizLiveHeatmap.tsx +27 -0
- package/src/components/VizLive/VizLiveRenderer.tsx +47 -0
- package/src/components/VizLive/index.ts +1 -0
- package/src/components/VizScrollmap/AverageFoldLine.tsx +57 -0
- package/src/components/VizScrollmap/HoverZones.tsx +58 -0
- package/src/components/VizScrollmap/MetricRow.tsx +0 -0
- package/src/components/VizScrollmap/ScrollMapMinimap.tsx +64 -0
- package/src/components/VizScrollmap/ScrollMapOverlay.tsx +79 -0
- package/src/components/VizScrollmap/ScrollZoneHoverArea.tsx +35 -0
- package/src/components/VizScrollmap/ScrollZoneTooltip.tsx +146 -0
- package/src/components/VizScrollmap/ScrollmapMarker.tsx +106 -0
- package/src/components/VizScrollmap/VizScrollMap.tsx +36 -0
- package/src/components/VizScrollmap/index.ts +1 -0
- package/src/components/VizScrollmapV2/ScrollmapOverlay.css +94 -0
- package/src/components/VizScrollmapV2/ScrollmapOverlayV2.tsx +130 -0
- package/src/components/VizScrollmapV2/index.ts +1 -0
- package/src/components/VizScrollmapV2/scrollmap.types.ts +21 -0
- package/src/components/VizScrollmapV2/useScrollmapOverlay.ts +187 -0
- package/src/components/index.tsx +2 -0
- package/src/configs/iframe.ts +15 -0
- package/src/configs/index.ts +2 -0
- package/src/configs/style.ts +21 -0
- package/src/constants/index.ts +4 -0
- package/src/global.d.ts +5 -0
- package/src/helpers/elm-callout.ts +347 -0
- package/src/helpers/elm-getter.ts +70 -0
- package/src/helpers/iframe-helper/fixer.ts +100 -0
- package/src/helpers/iframe-helper/index.ts +1 -0
- package/src/helpers/iframe-helper/init.ts +56 -0
- package/src/helpers/iframe-helper/navigation-blocker-v2.ts +371 -0
- package/src/helpers/iframe-helper/navigation-blocker.ts +367 -0
- package/src/helpers/iframe-helper/style-replacer.ts +231 -0
- package/src/helpers/iframe.ts +42 -0
- package/src/helpers/index.ts +8 -0
- package/src/helpers/viz-canvas/area-clustering.ts +234 -0
- package/src/helpers/viz-canvas/area-overlay-manager-v2.ts +176 -0
- package/src/helpers/viz-canvas/area-overlay-manager.ts +273 -0
- package/src/helpers/viz-canvas/hierarchical-area-clustering.ts +420 -0
- package/src/helpers/viz-canvas/index.ts +2 -0
- package/src/helpers/viz-elements.ts +43 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/register/index.ts +4 -0
- package/src/hooks/register/useRegisterConfig.ts +17 -0
- package/src/hooks/register/useRegisterControl.ts +13 -0
- package/src/hooks/register/useRegisterData.ts +36 -0
- package/src/hooks/register/useRegisterHeatmap.ts +38 -0
- package/src/hooks/viz-area/useAreaHeatmap.ts +336 -0
- package/src/hooks/viz-area/useAreaHeatmapManager.ts +692 -0
- package/src/hooks/viz-canvas/index.ts +1 -0
- package/src/hooks/viz-canvas/useAreamap.ts +162 -0
- package/src/hooks/viz-canvas/useClickmap.ts +24 -0
- package/src/hooks/viz-canvas/useHeatmapCanvas.ts +27 -0
- package/src/hooks/viz-canvas/useScrollmap.ts +22 -0
- package/src/hooks/viz-elements/index.ts +5 -0
- package/src/hooks/viz-elements/useClickedElement.ts +86 -0
- package/src/hooks/viz-elements/useElementCalloutVisible.ts +45 -0
- package/src/hooks/viz-elements/useHeatmapEffects.ts +30 -0
- package/src/hooks/viz-elements/useHeatmapElementPosition.ts +60 -0
- package/src/hooks/viz-elements/useHeatmapMouseHandler.ts +255 -0
- package/src/hooks/viz-elements/useHoveredElement.ts +170 -0
- package/src/hooks/viz-live/index.ts +1 -0
- package/src/hooks/viz-live/useVizLiveIframeMsg.ts +88 -0
- package/src/hooks/viz-live/useVizLiveRender.ts +67 -0
- package/src/hooks/viz-render/index.ts +1 -0
- package/src/hooks/viz-render/useHeatmapRender.ts +71 -0
- package/src/hooks/viz-render/useHeatmapVizRender.ts +20 -0
- package/src/hooks/viz-render/useReplayRender.ts +160 -0
- package/src/hooks/viz-scale/index.ts +2 -0
- package/src/hooks/viz-scale/useContainerDimensions.ts +48 -0
- package/src/hooks/viz-scale/useContentDimensions.ts +25 -0
- package/src/hooks/viz-scale/useHeatmapScale.ts +52 -0
- package/src/hooks/viz-scale/useObserveIframeHeight.ts +162 -0
- package/src/hooks/viz-scale/useScaleCalculation.ts +31 -0
- package/src/hooks/viz-scale/useScrollSync.ts +36 -0
- package/src/hooks/viz-scale/useWrapperRefHeight.ts +91 -0
- package/src/hooks/viz-scrollmap/index.ts +2 -0
- package/src/hooks/viz-scrollmap/useScrollmapZones.ts +165 -0
- package/src/hooks/viz-scrollmap/useZonePositions.ts +38 -0
- package/src/index.ts +10 -0
- package/src/stores/comp.ts +31 -0
- package/src/stores/config.ts +37 -0
- package/src/stores/data.ts +30 -0
- package/src/stores/index.ts +10 -0
- package/src/stores/interaction.ts +32 -0
- package/src/stores/mode-live.ts +38 -0
- package/src/stores/mode-single.ts +18 -0
- package/src/stores/viz-scrollmap.ts +22 -0
- package/src/stores/viz.ts +17 -0
- package/src/styles/base.css +1 -0
- package/src/styles/style.css +137 -0
- package/src/types/clarity.ts +45 -0
- package/src/types/control.ts +10 -0
- package/src/types/elm-callout.ts +9 -0
- package/src/types/heatmap-info.ts +11 -0
- package/src/types/heatmap.ts +25 -0
- package/src/types/iframe-helper.ts +18 -0
- package/src/types/index.ts +12 -0
- package/src/types/viz-canvas.ts +20 -0
- package/src/types/viz-element.ts +34 -0
- package/src/types/viz-scrollmap.ts +28 -0
- package/src/ui/BoxStack/BoxStack.tsx +136 -0
- package/src/ui/BoxStack/index.ts +1 -0
- package/src/ui/index.ts +1 -0
- package/src/utils/debounce.ts +10 -0
- package/src/utils/device.ts +7 -0
- package/src/utils/retry.ts +20 -0
- package/src/utils/sort.ts +5 -0
- package/dist/esm/helpers/iframe-helper/fixer.d.ts +0 -18
- package/dist/esm/helpers/iframe-helper/fixer.d.ts.map +0 -1
- package/dist/esm/helpers/iframe-helper/index.d.ts +0 -2
- package/dist/esm/helpers/iframe-helper/index.d.ts.map +0 -1
- package/dist/esm/helpers/iframe-helper/init.d.ts +0 -5
- package/dist/esm/helpers/iframe-helper/init.d.ts.map +0 -1
- package/dist/esm/helpers/iframe-helper/navigation-blocker-v2.d.ts +0 -28
- package/dist/esm/helpers/iframe-helper/navigation-blocker-v2.d.ts.map +0 -1
- package/dist/esm/helpers/iframe-helper/navigation-blocker.d.ts +0 -20
- package/dist/esm/helpers/iframe-helper/navigation-blocker.d.ts.map +0 -1
- package/dist/esm/helpers/iframe-helper/style-replacer.d.ts +0 -25
- package/dist/esm/helpers/iframe-helper/style-replacer.d.ts.map +0 -1
- package/dist/esm/hooks/vix-elements/useHeatmapMouseHandler.d.ts +0 -34
- package/dist/esm/hooks/vix-elements/useHeatmapMouseHandler.d.ts.map +0 -1
- package/dist/esm/hooks/viz-live/useVizLiveIframeMsg.d.ts.map +0 -1
- package/dist/esm/hooks/viz-live/useVizLiveRender.d.ts +0 -4
- package/dist/esm/hooks/viz-live/useVizLiveRender.d.ts.map +0 -1
- package/dist/esm/hooks/viz-scale/useObserveIframeHeight.d.ts +0 -10
- package/dist/esm/hooks/viz-scale/useObserveIframeHeight.d.ts.map +0 -1
- package/dist/esm/stores/mode-single.d.ts +0 -9
- package/dist/esm/stores/mode-single.d.ts.map +0 -1
- package/dist/esm/types/iframe-helper.d.ts +0 -20
- package/dist/esm/types/iframe-helper.d.ts.map +0 -1
- package/dist/umd/helpers/iframe-helper/fixer.d.ts +0 -18
- package/dist/umd/helpers/iframe-helper/fixer.d.ts.map +0 -1
- package/dist/umd/helpers/iframe-helper/index.d.ts +0 -2
- package/dist/umd/helpers/iframe-helper/index.d.ts.map +0 -1
- package/dist/umd/helpers/iframe-helper/init.d.ts +0 -5
- package/dist/umd/helpers/iframe-helper/init.d.ts.map +0 -1
- package/dist/umd/helpers/iframe-helper/navigation-blocker-v2.d.ts +0 -28
- package/dist/umd/helpers/iframe-helper/navigation-blocker-v2.d.ts.map +0 -1
- package/dist/umd/helpers/iframe-helper/navigation-blocker.d.ts +0 -20
- package/dist/umd/helpers/iframe-helper/navigation-blocker.d.ts.map +0 -1
- package/dist/umd/helpers/iframe-helper/style-replacer.d.ts +0 -25
- package/dist/umd/helpers/iframe-helper/style-replacer.d.ts.map +0 -1
- package/dist/umd/hooks/vix-elements/useHeatmapMouseHandler.d.ts +0 -34
- package/dist/umd/hooks/vix-elements/useHeatmapMouseHandler.d.ts.map +0 -1
- package/dist/umd/hooks/viz-live/useVizLiveIframeMsg.d.ts.map +0 -1
- package/dist/umd/hooks/viz-live/useVizLiveRender.d.ts +0 -4
- package/dist/umd/hooks/viz-live/useVizLiveRender.d.ts.map +0 -1
- package/dist/umd/hooks/viz-scale/useObserveIframeHeight.d.ts +0 -10
- package/dist/umd/hooks/viz-scale/useObserveIframeHeight.d.ts.map +0 -1
- package/dist/umd/stores/mode-single.d.ts +0 -9
- package/dist/umd/stores/mode-single.d.ts.map +0 -1
- package/dist/umd/types/iframe-helper.d.ts +0 -20
- package/dist/umd/types/iframe-helper.d.ts.map +0 -1
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
export class IframeNavigationBlocker {
|
|
2
|
+
private doc: Document;
|
|
3
|
+
private win: Window;
|
|
4
|
+
private isEnabled = true;
|
|
5
|
+
private originalWindowOpen: typeof window.open;
|
|
6
|
+
|
|
7
|
+
constructor(iframe: HTMLIFrameElement) {
|
|
8
|
+
if (!iframe.contentDocument || !iframe.contentWindow) {
|
|
9
|
+
throw new Error('Iframe document or window not accessible');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
this.doc = iframe.contentDocument;
|
|
13
|
+
this.win = iframe.contentWindow;
|
|
14
|
+
this.originalWindowOpen = this.win.open.bind(this.win);
|
|
15
|
+
|
|
16
|
+
this.init();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private init(): void {
|
|
20
|
+
console.log('[NavigationBlocker] Initializing...');
|
|
21
|
+
|
|
22
|
+
// Block navigation through links
|
|
23
|
+
this.blockLinkNavigation();
|
|
24
|
+
|
|
25
|
+
// Block form submissions
|
|
26
|
+
this.blockFormSubmissions();
|
|
27
|
+
|
|
28
|
+
// Block window.open and location methods
|
|
29
|
+
this.blockWindowNavigation();
|
|
30
|
+
|
|
31
|
+
// Block beforeunload to prevent navigation
|
|
32
|
+
this.blockBeforeUnload();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private blockLinkNavigation(): void {
|
|
36
|
+
this.doc.addEventListener(
|
|
37
|
+
'click',
|
|
38
|
+
(e) => {
|
|
39
|
+
if (!this.isEnabled) return;
|
|
40
|
+
|
|
41
|
+
const target = e.target as HTMLElement;
|
|
42
|
+
const link = target.closest('a');
|
|
43
|
+
|
|
44
|
+
if (link) {
|
|
45
|
+
const href = link.getAttribute('href');
|
|
46
|
+
|
|
47
|
+
// Allow hash links (same-page navigation)
|
|
48
|
+
if (!href || href === '' || href === '#' || href.startsWith('#')) {
|
|
49
|
+
console.log('[NavigationBlocker] Allowed hash navigation:', href);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Block javascript: links
|
|
54
|
+
if (href.startsWith('javascript:')) {
|
|
55
|
+
console.log('[NavigationBlocker] Blocked javascript: protocol');
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
e.stopPropagation();
|
|
58
|
+
e.stopImmediatePropagation();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Block all external links
|
|
63
|
+
if (
|
|
64
|
+
href.startsWith('http') ||
|
|
65
|
+
href.startsWith('//') ||
|
|
66
|
+
href.startsWith('/') ||
|
|
67
|
+
href.startsWith('.')
|
|
68
|
+
) {
|
|
69
|
+
console.log('[NavigationBlocker] Blocked navigation to:', href);
|
|
70
|
+
e.preventDefault();
|
|
71
|
+
e.stopPropagation();
|
|
72
|
+
e.stopImmediatePropagation();
|
|
73
|
+
|
|
74
|
+
this.notifyBlockedNavigation(href);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Block target="_blank"
|
|
79
|
+
const targetAttr = link.getAttribute('target');
|
|
80
|
+
if (targetAttr && targetAttr !== '_self') {
|
|
81
|
+
console.log('[NavigationBlocker] Blocked new window/tab:', href);
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
e.stopPropagation();
|
|
84
|
+
e.stopImmediatePropagation();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
true,
|
|
90
|
+
); // Capture phase (true)
|
|
91
|
+
|
|
92
|
+
// Add attribute to CSS to style disabled links
|
|
93
|
+
this.doc.querySelectorAll('a[href]').forEach((link) => {
|
|
94
|
+
const href = link.getAttribute('href');
|
|
95
|
+
if (href && !href.startsWith('#')) {
|
|
96
|
+
link.setAttribute('data-navigation-blocked', 'true');
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private blockFormSubmissions(): void {
|
|
102
|
+
this.doc.addEventListener(
|
|
103
|
+
'submit',
|
|
104
|
+
(e) => {
|
|
105
|
+
if (!this.isEnabled) return;
|
|
106
|
+
|
|
107
|
+
const form = e.target as HTMLFormElement;
|
|
108
|
+
const action = form.getAttribute('action');
|
|
109
|
+
|
|
110
|
+
// Allow forms without action or action = #
|
|
111
|
+
if (!action || action === '' || action === '#') {
|
|
112
|
+
console.log('[NavigationBlocker] Allowed same-page form submission');
|
|
113
|
+
e.preventDefault();
|
|
114
|
+
this.handleFormSubmit(form);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Block external form submissions
|
|
119
|
+
console.log('[NavigationBlocker] Blocked form submission to:', action);
|
|
120
|
+
e.preventDefault();
|
|
121
|
+
e.stopPropagation();
|
|
122
|
+
e.stopImmediatePropagation();
|
|
123
|
+
this.notifyBlockedNavigation(action);
|
|
124
|
+
},
|
|
125
|
+
true,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private blockWindowNavigation(): void {
|
|
130
|
+
// Override window.open
|
|
131
|
+
this.win.open = ((...args: any[]) => {
|
|
132
|
+
if (!this.isEnabled) {
|
|
133
|
+
return this.originalWindowOpen(...args);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const url = args[0]?.toString() || 'popup';
|
|
137
|
+
console.log('[NavigationBlocker] Blocked window.open:', url);
|
|
138
|
+
this.notifyBlockedNavigation(url);
|
|
139
|
+
return null;
|
|
140
|
+
}) as any;
|
|
141
|
+
|
|
142
|
+
// Block location.href through prototype
|
|
143
|
+
const locationProto = Object.getPrototypeOf(this.win.location);
|
|
144
|
+
const originalHrefDescriptor = Object.getOwnPropertyDescriptor(locationProto, 'href');
|
|
145
|
+
|
|
146
|
+
if (originalHrefDescriptor && originalHrefDescriptor.set) {
|
|
147
|
+
const originalHrefSetter = originalHrefDescriptor.set;
|
|
148
|
+
|
|
149
|
+
Object.defineProperty(locationProto, 'href', {
|
|
150
|
+
...originalHrefDescriptor,
|
|
151
|
+
set: (value: string) => {
|
|
152
|
+
if (!this.isEnabled) {
|
|
153
|
+
return originalHrefSetter.call(this.win.location, value);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Allow hash changes
|
|
157
|
+
if (value.startsWith('#')) {
|
|
158
|
+
return originalHrefSetter.call(this.win.location, value);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
console.log('[NavigationBlocker] Blocked location.href =', value);
|
|
162
|
+
this.notifyBlockedNavigation(value);
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Block location methods
|
|
168
|
+
const originalAssign = this.win.location.assign;
|
|
169
|
+
console.log(
|
|
170
|
+
`🚀 🐥 ~ IframeNavigationBlocker ~ blockWindowNavigation ~ this.win.location:`,
|
|
171
|
+
this.win.location,
|
|
172
|
+
);
|
|
173
|
+
const originalReplace = this.win.location.replace;
|
|
174
|
+
const originalReload = this.win.location.reload;
|
|
175
|
+
|
|
176
|
+
Object.defineProperty(this.win.location, 'assign', {
|
|
177
|
+
writable: true,
|
|
178
|
+
value: ((url: string | URL) => {
|
|
179
|
+
if (!this.isEnabled) {
|
|
180
|
+
return originalAssign.call(this.win.location, url);
|
|
181
|
+
}
|
|
182
|
+
console.log('[NavigationBlocker] Blocked location.assign:', url);
|
|
183
|
+
this.notifyBlockedNavigation(url.toString());
|
|
184
|
+
}) as any,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// this.win.location.assign = ((url: string | URL) => {
|
|
188
|
+
// if (!this.isEnabled) {
|
|
189
|
+
// return originalAssign.call(this.win.location, url);
|
|
190
|
+
// }
|
|
191
|
+
// console.log('[NavigationBlocker] Blocked location.assign:', url);
|
|
192
|
+
// this.notifyBlockedNavigation(url.toString());
|
|
193
|
+
// }) as any;
|
|
194
|
+
|
|
195
|
+
Object.defineProperty(this.win.location, 'replace', {
|
|
196
|
+
writable: true,
|
|
197
|
+
value: ((url: string | URL) => {
|
|
198
|
+
if (!this.isEnabled) {
|
|
199
|
+
return originalReplace.call(this.win.location, url);
|
|
200
|
+
}
|
|
201
|
+
console.log('[NavigationBlocker] Blocked location.replace:', url);
|
|
202
|
+
this.notifyBlockedNavigation(url.toString());
|
|
203
|
+
}) as any,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
Object.defineProperty(this.win.location, 'reload', {
|
|
207
|
+
writable: true,
|
|
208
|
+
value: (() => {
|
|
209
|
+
if (!this.isEnabled) {
|
|
210
|
+
return originalReload.call(this.win.location);
|
|
211
|
+
}
|
|
212
|
+
console.log('[NavigationBlocker] Blocked location.reload');
|
|
213
|
+
this.notifyBlockedNavigation('reload');
|
|
214
|
+
}) as any,
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// Block history navigation
|
|
218
|
+
const originalPushState = this.win.history.pushState;
|
|
219
|
+
const originalReplaceState = this.win.history.replaceState;
|
|
220
|
+
|
|
221
|
+
this.win.history.pushState = ((state: any, title: string, url?: string | URL | null) => {
|
|
222
|
+
if (!this.isEnabled) {
|
|
223
|
+
return originalPushState.call(this.win.history, state, title, url);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Allow hash-only changes
|
|
227
|
+
const urlStr = url?.toString() || '';
|
|
228
|
+
if (!urlStr || urlStr.startsWith('#')) {
|
|
229
|
+
return originalPushState.call(this.win.history, state, title, url);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
console.log('[NavigationBlocker] Blocked history.pushState:', url);
|
|
233
|
+
this.notifyBlockedNavigation(urlStr);
|
|
234
|
+
}) as any;
|
|
235
|
+
|
|
236
|
+
this.win.history.replaceState = ((state: any, title: string, url?: string | URL | null) => {
|
|
237
|
+
if (!this.isEnabled) {
|
|
238
|
+
return originalReplaceState.call(this.win.history, state, title, url);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const urlStr = url?.toString() || '';
|
|
242
|
+
if (!urlStr || urlStr.startsWith('#')) {
|
|
243
|
+
return originalReplaceState.call(this.win.history, state, title, url);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
console.log('[NavigationBlocker] Blocked history.replaceState:', url);
|
|
247
|
+
this.notifyBlockedNavigation(urlStr);
|
|
248
|
+
}) as any;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private blockBeforeUnload(): void {
|
|
252
|
+
// Block page unload (navigation away)
|
|
253
|
+
this.win.addEventListener('beforeunload', (e) => {
|
|
254
|
+
if (!this.isEnabled) return;
|
|
255
|
+
|
|
256
|
+
console.log('[NavigationBlocker] Blocked beforeunload');
|
|
257
|
+
e.preventDefault();
|
|
258
|
+
e.returnValue = '';
|
|
259
|
+
return '';
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Monitor popstate (back/forward navigation)
|
|
263
|
+
this.win.addEventListener('popstate', (e) => {
|
|
264
|
+
if (!this.isEnabled) return;
|
|
265
|
+
|
|
266
|
+
console.log('[NavigationBlocker] Detected popstate, may block if needed');
|
|
267
|
+
// Can add logic to block back/forward if needed
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
private handleFormSubmit(form: HTMLFormElement): void {
|
|
272
|
+
// Handle in-page form submissions if needed
|
|
273
|
+
const formData = new FormData(form);
|
|
274
|
+
// Polyfill for FormData.entries() for environments that don't support it
|
|
275
|
+
const data: Record<string, any> = {};
|
|
276
|
+
formData.forEach((value, key) => {
|
|
277
|
+
// If the field already exists, convert to array (handle multiple values, e.g. checkboxes)
|
|
278
|
+
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
279
|
+
if (Array.isArray(data[key])) {
|
|
280
|
+
data[key].push(value);
|
|
281
|
+
} else {
|
|
282
|
+
data[key] = [data[key], value];
|
|
283
|
+
}
|
|
284
|
+
} else {
|
|
285
|
+
data[key] = value;
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
console.log('[NavigationBlocker] Handling form data:', data);
|
|
290
|
+
|
|
291
|
+
// Dispatch custom event to parent
|
|
292
|
+
window.dispatchEvent(
|
|
293
|
+
new CustomEvent('iframe-form-submit', {
|
|
294
|
+
detail: { form, data },
|
|
295
|
+
}),
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
private notifyBlockedNavigation(url: string): void {
|
|
300
|
+
console.warn('[NavigationBlocker] Navigation blocked to:', url);
|
|
301
|
+
|
|
302
|
+
// Dispatch event to parent
|
|
303
|
+
window.dispatchEvent(
|
|
304
|
+
new CustomEvent('iframe-navigation-blocked', {
|
|
305
|
+
detail: { url, timestamp: Date.now() },
|
|
306
|
+
}),
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
// Optional: Show message
|
|
310
|
+
if (this.shouldShowMessage(url)) {
|
|
311
|
+
this.showBlockedMessage(url);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
private shouldShowMessage(url: string): boolean {
|
|
316
|
+
// Có thể customize logic này
|
|
317
|
+
return !url.startsWith('#') && url !== 'reload';
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
private showBlockedMessage(url: string): void {
|
|
321
|
+
const message = this.doc.createElement('div');
|
|
322
|
+
message.style.cssText = `
|
|
323
|
+
position: fixed;
|
|
324
|
+
top: 20px;
|
|
325
|
+
right: 20px;
|
|
326
|
+
background: #ff6b6b;
|
|
327
|
+
color: white;
|
|
328
|
+
padding: 12px 20px;
|
|
329
|
+
border-radius: 8px;
|
|
330
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
331
|
+
z-index: 999999;
|
|
332
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
333
|
+
font-size: 14px;
|
|
334
|
+
max-width: 300px;
|
|
335
|
+
word-break: break-word;
|
|
336
|
+
`;
|
|
337
|
+
|
|
338
|
+
const shortUrl = url.length > 50 ? url.substring(0, 47) + '...' : url;
|
|
339
|
+
message.innerHTML = `
|
|
340
|
+
<div style="font-weight: 600; margin-bottom: 4px;">Navigation Blocked</div>
|
|
341
|
+
<div style="font-size: 12px; opacity: 0.9;">${shortUrl}</div>
|
|
342
|
+
`;
|
|
343
|
+
|
|
344
|
+
this.doc.body.appendChild(message);
|
|
345
|
+
|
|
346
|
+
setTimeout(() => {
|
|
347
|
+
message.style.opacity = '0';
|
|
348
|
+
message.style.transition = 'opacity 0.3s';
|
|
349
|
+
setTimeout(() => message.remove(), 300);
|
|
350
|
+
}, 3000);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
public enable(): void {
|
|
354
|
+
this.isEnabled = true;
|
|
355
|
+
console.log('[NavigationBlocker] Enabled');
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
public disable(): void {
|
|
359
|
+
this.isEnabled = false;
|
|
360
|
+
console.log('[NavigationBlocker] Disabled');
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
public destroy(): void {
|
|
364
|
+
this.isEnabled = false;
|
|
365
|
+
console.log('[NavigationBlocker] Destroyed');
|
|
366
|
+
}
|
|
367
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import type { IframeStyleConfig } from '../../types';
|
|
2
|
+
|
|
3
|
+
export class IframeStyleReplacer {
|
|
4
|
+
private doc: Document;
|
|
5
|
+
private win: Window;
|
|
6
|
+
private config: IframeStyleConfig;
|
|
7
|
+
private regex = /([-.\d]+)(vh|svh|lvh|dvh|vw|svw|lvw|dvw)/gi;
|
|
8
|
+
|
|
9
|
+
constructor(iframe: HTMLIFrameElement, config: IframeStyleConfig) {
|
|
10
|
+
if (!iframe.contentDocument || !iframe.contentWindow) {
|
|
11
|
+
throw new Error('Iframe document or window not accessible');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
this.doc = iframe.contentDocument;
|
|
15
|
+
this.win = iframe.contentWindow;
|
|
16
|
+
this.config = config;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private px(value: number): string {
|
|
20
|
+
return `${value.toFixed(2)}px`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private convert(value: string, unit: string): string {
|
|
24
|
+
const num = parseFloat(value);
|
|
25
|
+
if (isNaN(num)) return value;
|
|
26
|
+
|
|
27
|
+
const map: Record<string, number> = {
|
|
28
|
+
vh: this.config.targetHeight,
|
|
29
|
+
svh: this.config.targetHeight,
|
|
30
|
+
lvh: this.config.targetHeight,
|
|
31
|
+
dvh: this.config.targetHeight,
|
|
32
|
+
vw: this.config.targetWidth,
|
|
33
|
+
svw: this.config.targetWidth,
|
|
34
|
+
lvw: this.config.targetWidth,
|
|
35
|
+
dvw: this.config.targetWidth,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return this.px((num / 100) * (map[unit.toLowerCase()] || 0));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private replaceInText(cssText: string): string {
|
|
42
|
+
return cssText.replace(this.regex, (_, value, unit) => this.convert(value, unit));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private processInlineStyles(): number {
|
|
46
|
+
let count = 0;
|
|
47
|
+
this.doc.querySelectorAll('[style]').forEach((el) => {
|
|
48
|
+
const style = el.getAttribute('style');
|
|
49
|
+
if (style && this.regex.test(style)) {
|
|
50
|
+
this.regex.lastIndex = 0;
|
|
51
|
+
el.setAttribute('style', this.replaceInText(style));
|
|
52
|
+
count++;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
console.log(`[IframeStyleReplacer] Replaced ${count} inline style elements`);
|
|
56
|
+
return count;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private processStyleTags(): number {
|
|
60
|
+
let count = 0;
|
|
61
|
+
this.doc.querySelectorAll('style').forEach((tag) => {
|
|
62
|
+
const css = tag.textContent || '';
|
|
63
|
+
if (this.regex.test(css)) {
|
|
64
|
+
this.regex.lastIndex = 0;
|
|
65
|
+
tag.textContent = this.replaceInText(css);
|
|
66
|
+
count++;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
console.log(`[IframeStyleReplacer] Replaced ${count} <style> tags`);
|
|
70
|
+
return count;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private processRule(rule: CSSRule): number {
|
|
74
|
+
let count = 0;
|
|
75
|
+
|
|
76
|
+
if ('style' in rule && rule.style) {
|
|
77
|
+
const style = (rule as CSSStyleRule).style;
|
|
78
|
+
for (let i = 0; i < style.length; i++) {
|
|
79
|
+
const prop = style[i];
|
|
80
|
+
const value = style.getPropertyValue(prop);
|
|
81
|
+
if (value && this.regex.test(value)) {
|
|
82
|
+
this.regex.lastIndex = 0;
|
|
83
|
+
style.setProperty(prop, this.replaceInText(value), style.getPropertyPriority(prop));
|
|
84
|
+
count++;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if ('cssRules' in rule) {
|
|
90
|
+
const rules = rule as unknown as CSSStyleSheet;
|
|
91
|
+
for (const r of Array.from(rules.cssRules || [])) {
|
|
92
|
+
count += this.processRule(r);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return count;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private processStylesheets(): number {
|
|
100
|
+
let total = 0;
|
|
101
|
+
Array.from(this.doc.styleSheets).forEach((sheet) => {
|
|
102
|
+
try {
|
|
103
|
+
// Bỏ qua external CSS (cross-origin)
|
|
104
|
+
if (sheet.href && !sheet.href.startsWith(this.win.location.origin)) {
|
|
105
|
+
console.log('[IframeStyleReplacer] Skipping external CSS:', sheet.href);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const rules = sheet.cssRules || sheet.rules;
|
|
110
|
+
if (!rules) return;
|
|
111
|
+
|
|
112
|
+
for (const rule of Array.from(rules)) {
|
|
113
|
+
total += this.processRule(rule);
|
|
114
|
+
}
|
|
115
|
+
} catch (e) {
|
|
116
|
+
console.warn('[IframeStyleReplacer] Cannot read stylesheet (CORS?):', (e as Error).message);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
console.log(`[IframeStyleReplacer] Replaced ${total} rules in stylesheets`);
|
|
120
|
+
return total;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private async processLinkedStylesheets(): Promise<number> {
|
|
124
|
+
const links = this.doc.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"]');
|
|
125
|
+
let count = 0;
|
|
126
|
+
|
|
127
|
+
for (const link of Array.from(links)) {
|
|
128
|
+
if (!link.href.startsWith(this.win.location.origin)) {
|
|
129
|
+
console.log('[IframeStyleReplacer] Skipping external CSS:', link.href);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const res = await fetch(link.href);
|
|
135
|
+
let css = await res.text();
|
|
136
|
+
|
|
137
|
+
if (this.regex.test(css)) {
|
|
138
|
+
this.regex.lastIndex = 0;
|
|
139
|
+
css = this.replaceInText(css);
|
|
140
|
+
|
|
141
|
+
const style = this.doc.createElement('style');
|
|
142
|
+
style.textContent = css;
|
|
143
|
+
style.dataset.originalHref = link.href;
|
|
144
|
+
|
|
145
|
+
link.parentNode?.insertBefore(style, link);
|
|
146
|
+
link.remove();
|
|
147
|
+
count++;
|
|
148
|
+
}
|
|
149
|
+
} catch (e) {
|
|
150
|
+
console.warn('[IframeStyleReplacer] Cannot load CSS:', link.href, e);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
console.log(`[IframeStyleReplacer] Replaced ${count} linked CSS files`);
|
|
155
|
+
return count;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private getFinalHeight(): number {
|
|
159
|
+
// Trigger reflow
|
|
160
|
+
void this.doc.body.offsetHeight;
|
|
161
|
+
|
|
162
|
+
return Math.max(
|
|
163
|
+
this.doc.body.scrollHeight,
|
|
164
|
+
this.doc.body.offsetHeight,
|
|
165
|
+
this.doc.documentElement.scrollHeight,
|
|
166
|
+
this.doc.documentElement.offsetHeight,
|
|
167
|
+
this.doc.documentElement.clientHeight,
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private getFinalWidth(): number {
|
|
172
|
+
return Math.max(
|
|
173
|
+
this.doc.body.scrollWidth,
|
|
174
|
+
this.doc.body.offsetWidth,
|
|
175
|
+
this.doc.documentElement.scrollWidth,
|
|
176
|
+
this.doc.documentElement.offsetWidth,
|
|
177
|
+
this.doc.documentElement.clientWidth,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private async waitForResources(): Promise<void> {
|
|
182
|
+
if ('fonts' in this.doc) {
|
|
183
|
+
await (this.doc as any).fonts.ready;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const images = Array.from(this.doc.images).filter((img) => !img.complete);
|
|
187
|
+
if (images.length > 0) {
|
|
188
|
+
await Promise.all(
|
|
189
|
+
images.map(
|
|
190
|
+
(img) =>
|
|
191
|
+
new Promise((resolve) => {
|
|
192
|
+
img.onload = img.onerror = resolve;
|
|
193
|
+
}),
|
|
194
|
+
),
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public async run(): Promise<{ height: number; width: number }> {
|
|
200
|
+
try {
|
|
201
|
+
console.log('[IframeStyleReplacer] Starting viewport units replacement...');
|
|
202
|
+
|
|
203
|
+
this.processInlineStyles();
|
|
204
|
+
this.processStyleTags();
|
|
205
|
+
this.processStylesheets();
|
|
206
|
+
|
|
207
|
+
await this.processLinkedStylesheets();
|
|
208
|
+
// await this.waitForResources();
|
|
209
|
+
|
|
210
|
+
return await new Promise((resolve) => {
|
|
211
|
+
requestAnimationFrame(() => {
|
|
212
|
+
const height = this.getFinalHeight();
|
|
213
|
+
const width = this.getFinalWidth();
|
|
214
|
+
|
|
215
|
+
console.log('[IframeStyleReplacer] Calculated dimensions:', { height, width });
|
|
216
|
+
resolve({ height, width });
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
} catch (err) {
|
|
220
|
+
console.error('[IframeStyleReplacer] Critical error:', err);
|
|
221
|
+
return {
|
|
222
|
+
height: this.doc.body.scrollHeight || 1000,
|
|
223
|
+
width: this.doc.body.scrollWidth || 1000,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
public updateConfig(config: Partial<IframeStyleConfig>): void {
|
|
229
|
+
this.config = { ...this.config, ...config };
|
|
230
|
+
}
|
|
231
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { decode } from '@gemx-dev/clarity-decode';
|
|
2
|
+
import { DecodedEvent, DecodedPayload } from '../types';
|
|
3
|
+
|
|
4
|
+
export function findLastSizeOfDom(data: DecodedPayload[]) {
|
|
5
|
+
const firstDoc = data.find((item) => item.envelope.sequence === 1)?.doc;
|
|
6
|
+
const docSorted = firstDoc?.sort(sort);
|
|
7
|
+
const firstEvent = docSorted?.[0];
|
|
8
|
+
const docSize = {
|
|
9
|
+
width: firstEvent?.data.width,
|
|
10
|
+
height: firstEvent?.data.height,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const newData = JSON.parse(JSON.stringify(data)) as DecodedPayload[];
|
|
14
|
+
const reversedData = newData.reverse();
|
|
15
|
+
const lastResizeEvent = reversedData.find((item) => !!item.resize);
|
|
16
|
+
const firstEventResize = lastResizeEvent?.resize?.[0];
|
|
17
|
+
const resize = {
|
|
18
|
+
width: firstEventResize?.data.width,
|
|
19
|
+
height: firstEventResize?.data.height,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
doc: docSize,
|
|
24
|
+
resize: resize,
|
|
25
|
+
size: {
|
|
26
|
+
width: resize.width ?? docSize.width,
|
|
27
|
+
height: resize.height ?? docSize.height,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function sort(a: DecodedEvent, b: DecodedEvent): number {
|
|
33
|
+
return a.time - b.time;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function decodePayloads(payload: string): DecodedPayload | null {
|
|
37
|
+
try {
|
|
38
|
+
return decode(payload) as unknown as DecodedPayload;
|
|
39
|
+
} catch (error) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|