@gemx-dev/heatmap-react 3.5.35 → 3.5.37
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/ContentToolbar.d.ts.map +1 -1
- package/dist/esm/components/Layout/LeftSidebar.d.ts.map +1 -1
- package/dist/esm/components/VizDom/VizDomContainer.d.ts.map +1 -1
- package/dist/esm/configs/iframe.d.ts +1 -1
- package/dist/esm/configs/iframe.d.ts.map +1 -1
- package/dist/esm/helpers/index.d.ts +2 -0
- 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 +25 -0
- package/dist/esm/helpers/viewport-replacer.d.ts.map +1 -0
- package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useContentDimensions.d.ts +1 -1
- package/dist/esm/hooks/viz-scale/useContentDimensions.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts +0 -1
- package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useScrollSync.d.ts.map +1 -1
- package/dist/esm/index.js +318 -31
- package/dist/esm/index.mjs +318 -31
- package/dist/esm/stores/viz.d.ts +2 -0
- package/dist/esm/stores/viz.d.ts.map +1 -1
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/types/viewport-fixer.d.ts +28 -0
- package/dist/esm/types/viewport-fixer.d.ts.map +1 -0
- package/dist/esm/ui/BoxStack/BoxStack.d.ts +1 -1
- package/dist/esm/ui/BoxStack/BoxStack.d.ts.map +1 -1
- package/dist/style.css +45 -1
- package/dist/umd/components/Layout/ContentToolbar.d.ts.map +1 -1
- package/dist/umd/components/Layout/LeftSidebar.d.ts.map +1 -1
- package/dist/umd/components/VizDom/VizDomContainer.d.ts.map +1 -1
- package/dist/umd/configs/iframe.d.ts +1 -1
- package/dist/umd/configs/iframe.d.ts.map +1 -1
- package/dist/umd/helpers/index.d.ts +2 -0
- 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 +25 -0
- package/dist/umd/helpers/viewport-replacer.d.ts.map +1 -0
- package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useContentDimensions.d.ts +1 -1
- package/dist/umd/hooks/viz-scale/useContentDimensions.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts +0 -1
- package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useScrollSync.d.ts.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/stores/viz.d.ts +2 -0
- package/dist/umd/stores/viz.d.ts.map +1 -1
- package/dist/umd/types/index.d.ts +1 -0
- package/dist/umd/types/index.d.ts.map +1 -1
- package/dist/umd/types/viewport-fixer.d.ts +28 -0
- package/dist/umd/types/viewport-fixer.d.ts.map +1 -0
- package/dist/umd/ui/BoxStack/BoxStack.d.ts +1 -1
- package/dist/umd/ui/BoxStack/BoxStack.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentToolbar.d.ts","sourceRoot":"","sources":["../../../src/components/Layout/ContentToolbar.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"ContentToolbar.d.ts","sourceRoot":"","sources":["../../../src/components/Layout/ContentToolbar.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAmBlC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LeftSidebar.d.ts","sourceRoot":"","sources":["../../../src/components/Layout/LeftSidebar.tsx"],"names":[],"mappings":"AAOA,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"LeftSidebar.d.ts","sourceRoot":"","sources":["../../../src/components/Layout/LeftSidebar.tsx"],"names":[],"mappings":"AAOA,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAqC/B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VizDomContainer.d.ts","sourceRoot":"","sources":["../../../src/components/VizDom/VizDomContainer.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"VizDomContainer.d.ts","sourceRoot":"","sources":["../../../src/components/VizDom/VizDomContainer.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAiCnC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iframe.d.ts","sourceRoot":"","sources":["../../src/configs/iframe.ts"],"names":[],"mappings":"AAAA,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"iframe.d.ts","sourceRoot":"","sources":["../../src/configs/iframe.ts"],"names":[],"mappings":"AAAA,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,cAAc,EAAE,WAM5B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAE/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { DebugInfo, ViewportConfig } from '../types';
|
|
2
|
+
export declare class ViewportUnitsFixer {
|
|
3
|
+
private iframe;
|
|
4
|
+
private config;
|
|
5
|
+
constructor(config: ViewportConfig);
|
|
6
|
+
private init;
|
|
7
|
+
private injectScript;
|
|
8
|
+
private handleMessage;
|
|
9
|
+
recalculate(): void;
|
|
10
|
+
}
|
|
11
|
+
export declare function initViewportFixer(config: ViewportConfig): ViewportUnitsFixer;
|
|
12
|
+
export declare function debugViewportUnits(): DebugInfo | null;
|
|
13
|
+
//# sourceMappingURL=viewport-fixer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewport-fixer.d.ts","sourceRoot":"","sources":["../../src/helpers/viewport-fixer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAyC,cAAc,EAAE,MAAM,UAAU,CAAC;AAE5F,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,MAAM,CAAiB;gBAEnB,MAAM,EAAE,cAAc;YAOpB,IAAI;YAgBJ,YAAY;IAwB1B,OAAO,CAAC,aAAa;IAMd,WAAW,IAAI,IAAI;CAG3B;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,cAAc,GAAG,kBAAkB,CAU5E;AAED,wBAAgB,kBAAkB,IAAI,SAAS,GAAG,IAAI,CA+BrD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ViewportConfig } from '../types';
|
|
2
|
+
declare global {
|
|
3
|
+
interface Window {
|
|
4
|
+
__viewportConfig?: ViewportConfig;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export default class ViewportUnitsReplacer {
|
|
8
|
+
private config;
|
|
9
|
+
private readonly regex;
|
|
10
|
+
constructor();
|
|
11
|
+
private px;
|
|
12
|
+
private convert;
|
|
13
|
+
private replaceInText;
|
|
14
|
+
private processInlineStyles;
|
|
15
|
+
private processStyleTags;
|
|
16
|
+
private processRule;
|
|
17
|
+
private processStylesheets;
|
|
18
|
+
private processLinkedStylesheets;
|
|
19
|
+
private getFinalHeight;
|
|
20
|
+
private notifyParent;
|
|
21
|
+
private waitForResources;
|
|
22
|
+
private run;
|
|
23
|
+
private init;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=viewport-replacer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewport-replacer.d.ts","sourceRoot":"","sources":["../../src/helpers/viewport-replacer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,gBAAgB,CAAC,EAAE,cAAc,CAAC;KACnC;CACF;AAED,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACxC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgD;;IAatE,OAAO,CAAC,EAAE;IAIV,OAAO,CAAC,OAAO;IAkBf,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,WAAW;IAyBnB,OAAO,CAAC,kBAAkB;YAwBZ,wBAAwB;IAkCtC,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,YAAY;YAYN,gBAAgB;YAkBhB,GAAG;IAmBjB,OAAO,CAAC,IAAI;CAOb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHeatmapRender.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-render/useHeatmapRender.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useHeatmapRender.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-render/useHeatmapRender.ts"],"names":[],"mappings":"AAMA,UAAU,uBAAuB;IAC/B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACtD;AAED,eAAO,MAAM,gBAAgB,QAAO,uBAsCnC,CAAC"}
|
|
@@ -4,6 +4,6 @@ interface IUseContentDimensionsProps {
|
|
|
4
4
|
interface IUseContentDimensionsResult {
|
|
5
5
|
contentWidth: number;
|
|
6
6
|
}
|
|
7
|
-
export declare const useContentDimensions: (
|
|
7
|
+
export declare const useContentDimensions: ({ iframeRef, }: IUseContentDimensionsProps) => IUseContentDimensionsResult;
|
|
8
8
|
export {};
|
|
9
9
|
//# sourceMappingURL=useContentDimensions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useContentDimensions.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-scale/useContentDimensions.ts"],"names":[],"mappings":"AAGA,UAAU,0BAA0B;IAClC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACtD;AAED,UAAU,2BAA2B;IACnC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"useContentDimensions.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-scale/useContentDimensions.ts"],"names":[],"mappings":"AAGA,UAAU,0BAA0B;IAClC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACtD;AAED,UAAU,2BAA2B;IACnC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,oBAAoB,GAAI,gBAElC,0BAA0B,KAAG,2BAa/B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHeatmapScale.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-scale/useHeatmapScale.ts"],"names":[],"mappings":"AAMA,UAAU,kBAAkB;IAC1B,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACnD,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACrD,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CACnD;AAED,UAAU,sBAAsB;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED,eAAO,MAAM,eAAe,GAAI,OAAO,kBAAkB,KAAG,
|
|
1
|
+
{"version":3,"file":"useHeatmapScale.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-scale/useHeatmapScale.ts"],"names":[],"mappings":"AAMA,UAAU,kBAAkB;IAC1B,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACnD,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACrD,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CACnD;AAED,UAAU,sBAAsB;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED,eAAO,MAAM,eAAe,GAAI,OAAO,kBAAkB,KAAG,sBA4B3D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIframeHeight.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-scale/useIframeHeight.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useIframeHeight.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-scale/useIframeHeight.ts"],"names":[],"mappings":"AAGA,UAAU,qBAAqB;IAC7B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACtD;AAED,UAAU,sBAAsB;IAC9B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,eAAe,GAAI,OAAO,qBAAqB,KAAG,sBA8F9D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useScrollSync.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-scale/useScrollSync.ts"],"names":[],"mappings":"AAGA,UAAU,mBAAmB;IAC3B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACtD;AAED,UAAU,oBAAoB;IAC5B,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED,eAAO,MAAM,aAAa,GAAI,eAAe,mBAAmB,KAAG,
|
|
1
|
+
{"version":3,"file":"useScrollSync.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-scale/useScrollSync.ts"],"names":[],"mappings":"AAGA,UAAU,mBAAmB;IAC3B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACtD;AAED,UAAU,oBAAoB;IAC5B,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED,eAAO,MAAM,aAAa,GAAI,eAAe,mBAAmB,KAAG,oBAwBlE,CAAC"}
|
package/dist/esm/index.js
CHANGED
|
@@ -128,6 +128,8 @@ const useHeatmapInteractionStore = create()((set, get) => {
|
|
|
128
128
|
|
|
129
129
|
const useHeatmapVizStore = create()((set, get) => {
|
|
130
130
|
return {
|
|
131
|
+
isRenderViz: false,
|
|
132
|
+
setIsRenderViz: (isRenderViz) => set({ isRenderViz }),
|
|
131
133
|
scale: 1,
|
|
132
134
|
vizRef: undefined,
|
|
133
135
|
iframeHeight: 0,
|
|
@@ -436,6 +438,253 @@ function isElementInViewport(elementRect, visualRef, scale) {
|
|
|
436
438
|
return elementBottom > viewportTop && elementTop < viewportBottom;
|
|
437
439
|
}
|
|
438
440
|
|
|
441
|
+
class ViewportUnitsFixer {
|
|
442
|
+
iframe = null;
|
|
443
|
+
config;
|
|
444
|
+
constructor(config) {
|
|
445
|
+
this.config = config;
|
|
446
|
+
this.iframe = config.iframe;
|
|
447
|
+
this.init();
|
|
448
|
+
}
|
|
449
|
+
async init() {
|
|
450
|
+
if (!this.iframe) {
|
|
451
|
+
console.error('[Parent] Required elements not found');
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
// this.injectScriptContent = await generateIframeInjectScript();
|
|
455
|
+
window.addEventListener('message', this.handleMessage.bind(this));
|
|
456
|
+
if (this.iframe.contentDocument?.readyState === 'complete') {
|
|
457
|
+
await this.injectScript();
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
this.iframe.addEventListener('load', () => this.injectScript());
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
async injectScript() {
|
|
464
|
+
if (!this.iframe?.contentWindow || !this.iframe.contentDocument)
|
|
465
|
+
return;
|
|
466
|
+
const win = this.iframe.contentWindow;
|
|
467
|
+
const doc = this.iframe.contentDocument;
|
|
468
|
+
win.__viewportConfig = this.config;
|
|
469
|
+
const script = doc.createElement('script');
|
|
470
|
+
script.textContent = `
|
|
471
|
+
(function() {
|
|
472
|
+
'use strict';
|
|
473
|
+
${(await Promise.resolve().then(function () { return viewportReplacer; })).default}
|
|
474
|
+
new ViewportUnitsReplacer()
|
|
475
|
+
})();
|
|
476
|
+
`;
|
|
477
|
+
script.type = 'text/javascript';
|
|
478
|
+
script.id = 'viewport-replacer';
|
|
479
|
+
script.onload = () => console.log('[Parent] Viewport replacer module loaded');
|
|
480
|
+
script.onerror = () => console.error('[Parent] Không load được replacer script');
|
|
481
|
+
doc.head.appendChild(script);
|
|
482
|
+
}
|
|
483
|
+
handleMessage(event) {
|
|
484
|
+
const data = event.data;
|
|
485
|
+
if (!data || data.type !== 'IFRAME_HEIGHT_CALCULATED')
|
|
486
|
+
return;
|
|
487
|
+
this.config.onSuccess?.(data);
|
|
488
|
+
}
|
|
489
|
+
recalculate() {
|
|
490
|
+
this.injectScript();
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
function initViewportFixer(config) {
|
|
494
|
+
const fixer = new ViewportUnitsFixer(config);
|
|
495
|
+
window.viewportFixer = fixer;
|
|
496
|
+
window.addEventListener('iframe-dimensions-applied', ((e) => {
|
|
497
|
+
const ev = e;
|
|
498
|
+
console.log('Iframe dimensions finalized:', ev.detail);
|
|
499
|
+
}));
|
|
500
|
+
return fixer;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
class ViewportUnitsReplacer {
|
|
504
|
+
config;
|
|
505
|
+
regex = /([-.\d]+)(vh|svh|lvh|dvh|vw|svw|lvw|dvw)/gi;
|
|
506
|
+
constructor() {
|
|
507
|
+
if (!window.__viewportConfig) {
|
|
508
|
+
throw new Error('[Iframe] Do not have viewport config');
|
|
509
|
+
}
|
|
510
|
+
this.config = window.__viewportConfig;
|
|
511
|
+
console.log('[Iframe] ViewportUnitsReplacer started with config:', this.config);
|
|
512
|
+
this.init();
|
|
513
|
+
}
|
|
514
|
+
px(value) {
|
|
515
|
+
return `${value.toFixed(2)}px`;
|
|
516
|
+
}
|
|
517
|
+
convert(value, unit) {
|
|
518
|
+
const num = parseFloat(value);
|
|
519
|
+
if (isNaN(num))
|
|
520
|
+
return value;
|
|
521
|
+
const map = {
|
|
522
|
+
vh: this.config.targetHeight,
|
|
523
|
+
svh: this.config.targetHeight,
|
|
524
|
+
lvh: this.config.targetHeight,
|
|
525
|
+
dvh: this.config.targetHeight,
|
|
526
|
+
vw: this.config.targetWidth,
|
|
527
|
+
svw: this.config.targetWidth,
|
|
528
|
+
lvw: this.config.targetWidth,
|
|
529
|
+
dvw: this.config.targetWidth,
|
|
530
|
+
};
|
|
531
|
+
return this.px((num / 100) * (map[unit.toLowerCase()] || 0));
|
|
532
|
+
}
|
|
533
|
+
replaceInText(cssText) {
|
|
534
|
+
return cssText.replace(this.regex, (_, value, unit) => this.convert(value, unit));
|
|
535
|
+
}
|
|
536
|
+
processInlineStyles() {
|
|
537
|
+
let count = 0;
|
|
538
|
+
document.querySelectorAll('[style]').forEach((el) => {
|
|
539
|
+
const style = el.getAttribute('style');
|
|
540
|
+
if (style && this.regex.test(style)) {
|
|
541
|
+
el.setAttribute('style', this.replaceInText(style));
|
|
542
|
+
count++;
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
console.log(`[Iframe] Replaced ${count} inline style elements`);
|
|
546
|
+
return count;
|
|
547
|
+
}
|
|
548
|
+
processStyleTags() {
|
|
549
|
+
let count = 0;
|
|
550
|
+
document.querySelectorAll('style').forEach((tag) => {
|
|
551
|
+
const css = tag.textContent || '';
|
|
552
|
+
if (this.regex.test(css)) {
|
|
553
|
+
tag.textContent = this.replaceInText(css);
|
|
554
|
+
count++;
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
console.log(`[Iframe] Replaced ${count} <style> tags`);
|
|
558
|
+
return count;
|
|
559
|
+
}
|
|
560
|
+
processRule(rule) {
|
|
561
|
+
let count = 0;
|
|
562
|
+
if ('style' in rule && rule.style) {
|
|
563
|
+
const style = rule.style;
|
|
564
|
+
for (let i = 0; i < style.length; i++) {
|
|
565
|
+
const prop = style[i];
|
|
566
|
+
const value = style.getPropertyValue(prop);
|
|
567
|
+
if (value && this.regex.test(value)) {
|
|
568
|
+
style.setProperty(prop, this.replaceInText(value), style.getPropertyPriority(prop));
|
|
569
|
+
count++;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
if ('cssRules' in rule) {
|
|
574
|
+
const rules = rule;
|
|
575
|
+
for (const r of Array.from(rules.cssRules || [])) {
|
|
576
|
+
count += this.processRule(r);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
return count;
|
|
580
|
+
}
|
|
581
|
+
processStylesheets() {
|
|
582
|
+
let total = 0;
|
|
583
|
+
Array.from(document.styleSheets).forEach((sheet) => {
|
|
584
|
+
try {
|
|
585
|
+
// Bỏ qua external CSS (cross-origin)
|
|
586
|
+
if (sheet.href && !sheet.href.startsWith(location.origin)) {
|
|
587
|
+
console.log('[Iframe] Skipping external CSS:', sheet.href);
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
const rules = sheet.cssRules || sheet.rules;
|
|
591
|
+
if (!rules)
|
|
592
|
+
return;
|
|
593
|
+
for (const rule of Array.from(rules)) {
|
|
594
|
+
total += this.processRule(rule);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
catch (e) {
|
|
598
|
+
console.warn('[Iframe] Cannot read stylesheet (CORS?):', e.message);
|
|
599
|
+
}
|
|
600
|
+
});
|
|
601
|
+
console.log(`[Iframe] Replaced ${total} rules in stylesheets`);
|
|
602
|
+
return total;
|
|
603
|
+
}
|
|
604
|
+
async processLinkedStylesheets() {
|
|
605
|
+
const links = document.querySelectorAll('link[rel="stylesheet"]');
|
|
606
|
+
let count = 0;
|
|
607
|
+
for (const link of Array.from(links)) {
|
|
608
|
+
if (!link.href.startsWith(location.origin)) {
|
|
609
|
+
console.log('[Iframe] Skipping external CSS:', link.href);
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
try {
|
|
613
|
+
const res = await fetch(link.href);
|
|
614
|
+
let css = await res.text();
|
|
615
|
+
if (this.regex.test(css)) {
|
|
616
|
+
css = this.replaceInText(css);
|
|
617
|
+
const style = document.createElement('style');
|
|
618
|
+
style.textContent = css;
|
|
619
|
+
style.dataset.originalHref = link.href;
|
|
620
|
+
link.parentNode?.insertBefore(style, link);
|
|
621
|
+
link.remove();
|
|
622
|
+
count++;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
catch (e) {
|
|
626
|
+
console.warn('[Iframe] Cannot load CSS:', link.href, e);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
console.log(`[Iframe] Replaced ${count} linked CSS files`);
|
|
630
|
+
return count;
|
|
631
|
+
}
|
|
632
|
+
getFinalHeight() {
|
|
633
|
+
// Trigger reflow
|
|
634
|
+
void document.body.offsetHeight;
|
|
635
|
+
return Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight, document.documentElement.clientHeight);
|
|
636
|
+
}
|
|
637
|
+
notifyParent(height) {
|
|
638
|
+
window.parent.postMessage({
|
|
639
|
+
type: 'IFRAME_HEIGHT_CALCULATED',
|
|
640
|
+
height,
|
|
641
|
+
width: document.body.scrollWidth,
|
|
642
|
+
}, '*');
|
|
643
|
+
console.log('[Iframe] Sent height to parent:', height);
|
|
644
|
+
}
|
|
645
|
+
async waitForResources() {
|
|
646
|
+
if ('fonts' in document) {
|
|
647
|
+
await document.fonts.ready;
|
|
648
|
+
}
|
|
649
|
+
const images = Array.from(document.images).filter((img) => !img.complete);
|
|
650
|
+
if (images.length > 0) {
|
|
651
|
+
await Promise.all(images.map((img) => new Promise((resolve) => {
|
|
652
|
+
img.onload = img.onerror = resolve;
|
|
653
|
+
})));
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
async run() {
|
|
657
|
+
try {
|
|
658
|
+
this.processInlineStyles();
|
|
659
|
+
this.processStyleTags();
|
|
660
|
+
this.processStylesheets();
|
|
661
|
+
await this.processLinkedStylesheets();
|
|
662
|
+
// await this.waitForResources();
|
|
663
|
+
requestAnimationFrame(() => {
|
|
664
|
+
const height = this.getFinalHeight();
|
|
665
|
+
this.notifyParent(height);
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
catch (err) {
|
|
669
|
+
console.error('[Iframe] Critical error:', err);
|
|
670
|
+
this.notifyParent(document.body.scrollHeight || 1000);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
init() {
|
|
674
|
+
if (document.readyState === 'loading') {
|
|
675
|
+
document.addEventListener('DOMContentLoaded', () => this.run());
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
this.run();
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
var viewportReplacer = /*#__PURE__*/Object.freeze({
|
|
684
|
+
__proto__: null,
|
|
685
|
+
default: ViewportUnitsReplacer
|
|
686
|
+
});
|
|
687
|
+
|
|
439
688
|
const scrollToElementIfNeeded = (visualRef, rect, scale) => {
|
|
440
689
|
if (!visualRef.current)
|
|
441
690
|
return;
|
|
@@ -691,24 +940,22 @@ const useHeatmapRender = () => {
|
|
|
691
940
|
const data = useHeatmapDataStore((state) => state.data);
|
|
692
941
|
const config = useHeatmapDataStore((state) => state.config);
|
|
693
942
|
const setVizRef = useHeatmapVizStore((state) => state.setVizRef);
|
|
943
|
+
const setIsRenderViz = useHeatmapVizStore((state) => state.setIsRenderViz);
|
|
944
|
+
const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
|
|
694
945
|
const iframeRef = useRef(null);
|
|
695
946
|
const renderHeatmap = useCallback(async (payloads) => {
|
|
696
947
|
if (!payloads || payloads.length === 0)
|
|
697
948
|
return;
|
|
949
|
+
setIsRenderViz(false);
|
|
698
950
|
const visualizer = new Visualizer();
|
|
699
951
|
const iframe = iframeRef.current;
|
|
700
952
|
if (!iframe?.contentWindow)
|
|
701
953
|
return;
|
|
702
954
|
await visualizer.html(payloads, iframe.contentWindow);
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
// const isRemove = !(isClosedEcomsendWidget || isEcomsendWidget);
|
|
708
|
-
// if (isRemove) {
|
|
709
|
-
// element.remove();
|
|
710
|
-
// }
|
|
711
|
-
// });
|
|
955
|
+
reset(iframe, payloads, (height) => {
|
|
956
|
+
height && setIframeHeight(height);
|
|
957
|
+
setIsRenderViz(true);
|
|
958
|
+
});
|
|
712
959
|
setVizRef(visualizer);
|
|
713
960
|
}, []);
|
|
714
961
|
useEffect(() => {
|
|
@@ -723,6 +970,50 @@ const useHeatmapRender = () => {
|
|
|
723
970
|
iframeRef,
|
|
724
971
|
};
|
|
725
972
|
};
|
|
973
|
+
function sort(a, b) {
|
|
974
|
+
return a.time - b.time;
|
|
975
|
+
}
|
|
976
|
+
function findLastSizeOfDom(data) {
|
|
977
|
+
const firstDoc = data.find((item) => item.envelope.sequence === 1)?.doc;
|
|
978
|
+
const docSorted = firstDoc?.sort(sort);
|
|
979
|
+
const firstEvent = docSorted?.[0];
|
|
980
|
+
const docSize = {
|
|
981
|
+
width: firstEvent?.data.width,
|
|
982
|
+
height: firstEvent?.data.height,
|
|
983
|
+
};
|
|
984
|
+
const newData = JSON.parse(JSON.stringify(data));
|
|
985
|
+
const reversedData = newData.reverse();
|
|
986
|
+
const lastResizeEvent = reversedData.find((item) => !!item.resize);
|
|
987
|
+
const firstEventResize = lastResizeEvent?.resize?.[0];
|
|
988
|
+
const resize = {
|
|
989
|
+
width: firstEventResize?.data.width,
|
|
990
|
+
height: firstEventResize?.data.height,
|
|
991
|
+
};
|
|
992
|
+
return {
|
|
993
|
+
doc: docSize,
|
|
994
|
+
resize: resize,
|
|
995
|
+
size: {
|
|
996
|
+
width: resize.width ?? docSize.width,
|
|
997
|
+
height: resize.height ?? docSize.height,
|
|
998
|
+
},
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
function reset(iframe, payloads, onSuccess) {
|
|
1002
|
+
const { size } = findLastSizeOfDom(payloads);
|
|
1003
|
+
const docWidth = size.width ?? 0;
|
|
1004
|
+
const docHeight = size.height ?? 0;
|
|
1005
|
+
const viewportFixer = initViewportFixer({
|
|
1006
|
+
targetWidth: docWidth,
|
|
1007
|
+
targetHeight: docHeight,
|
|
1008
|
+
iframe: iframe,
|
|
1009
|
+
onSuccess: (data) => {
|
|
1010
|
+
onSuccess(data.height);
|
|
1011
|
+
iframe.height = `${data.height}px`;
|
|
1012
|
+
},
|
|
1013
|
+
});
|
|
1014
|
+
viewportFixer.recalculate();
|
|
1015
|
+
return iframe;
|
|
1016
|
+
}
|
|
726
1017
|
|
|
727
1018
|
function isMobileDevice(userAgent) {
|
|
728
1019
|
if (!userAgent)
|
|
@@ -894,24 +1185,24 @@ const useContainerDimensions = (props) => {
|
|
|
894
1185
|
return { containerWidth, containerHeight };
|
|
895
1186
|
};
|
|
896
1187
|
|
|
897
|
-
const useContentDimensions = (
|
|
898
|
-
const
|
|
899
|
-
const
|
|
1188
|
+
const useContentDimensions = ({ iframeRef, }) => {
|
|
1189
|
+
const config = useHeatmapDataStore((state) => state.config);
|
|
1190
|
+
const contentWidth = config?.width ?? 0;
|
|
900
1191
|
useEffect(() => {
|
|
901
1192
|
if (!contentWidth)
|
|
902
1193
|
return;
|
|
903
1194
|
if (!iframeRef.current)
|
|
904
1195
|
return;
|
|
905
|
-
iframeRef.current.width = `${contentWidth}px`;
|
|
1196
|
+
// iframeRef.current.width = `${contentWidth}px`;
|
|
906
1197
|
}, [contentWidth, iframeRef]);
|
|
907
1198
|
return { contentWidth };
|
|
908
1199
|
};
|
|
909
1200
|
|
|
910
|
-
// Hook 3: Iframe Height Observer
|
|
911
1201
|
const useIframeHeight = (props) => {
|
|
912
|
-
const { iframeRef
|
|
1202
|
+
const { iframeRef } = props;
|
|
913
1203
|
const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
|
|
914
1204
|
const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
|
|
1205
|
+
const isRenderViz = useHeatmapVizStore((state) => state.isRenderViz);
|
|
915
1206
|
const resizeObserverRef = useRef(null);
|
|
916
1207
|
const mutationObserverRef = useRef(null);
|
|
917
1208
|
const updateIframeHeight = useCallback(() => {
|
|
@@ -933,17 +1224,9 @@ const useIframeHeight = (props) => {
|
|
|
933
1224
|
console.warn('Cannot measure iframe content:', error);
|
|
934
1225
|
}
|
|
935
1226
|
}, [iframeRef, setIframeHeight]);
|
|
936
|
-
useEffect(() => {
|
|
937
|
-
if (contentWidth > 0) {
|
|
938
|
-
const timeoutId = setTimeout(() => {
|
|
939
|
-
updateIframeHeight();
|
|
940
|
-
}, 100);
|
|
941
|
-
return () => clearTimeout(timeoutId);
|
|
942
|
-
}
|
|
943
|
-
}, [contentWidth]);
|
|
944
1227
|
useEffect(() => {
|
|
945
1228
|
const iframe = iframeRef.current;
|
|
946
|
-
if (!iframe)
|
|
1229
|
+
if (!iframe || !isRenderViz)
|
|
947
1230
|
return;
|
|
948
1231
|
const setupObservers = () => {
|
|
949
1232
|
try {
|
|
@@ -995,7 +1278,7 @@ const useIframeHeight = (props) => {
|
|
|
995
1278
|
}
|
|
996
1279
|
iframe.removeEventListener('load', setupObservers);
|
|
997
1280
|
};
|
|
998
|
-
}, [iframeRef, updateIframeHeight]);
|
|
1281
|
+
}, [iframeRef, isRenderViz, updateIframeHeight]);
|
|
999
1282
|
return { iframeHeight };
|
|
1000
1283
|
};
|
|
1001
1284
|
|
|
@@ -1025,7 +1308,6 @@ const useScrollSync = ({ iframeRef }) => {
|
|
|
1025
1308
|
if (iframeWindow && iframeDocument) {
|
|
1026
1309
|
const iframeScrollTop = scrollTop / widthScale;
|
|
1027
1310
|
iframe.style.top = `${iframeScrollTop}px`;
|
|
1028
|
-
// iframeWindow.scrollTo({ top: iframeScrollTop, behavior: 'smooth' });
|
|
1029
1311
|
}
|
|
1030
1312
|
}
|
|
1031
1313
|
catch (error) {
|
|
@@ -1036,13 +1318,14 @@ const useScrollSync = ({ iframeRef }) => {
|
|
|
1036
1318
|
};
|
|
1037
1319
|
|
|
1038
1320
|
const useHeatmapScale = (props) => {
|
|
1321
|
+
// const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
|
|
1039
1322
|
const { wrapperRef, iframeRef, visualRef } = props;
|
|
1040
1323
|
// 1. Observe container dimensions
|
|
1041
1324
|
const { containerWidth, containerHeight } = useContainerDimensions({ wrapperRef });
|
|
1042
1325
|
// 2. Get content dimensions from config
|
|
1043
1326
|
const { contentWidth } = useContentDimensions({ iframeRef });
|
|
1044
1327
|
// 3. Observe iframe height (now reacts to width changes)
|
|
1045
|
-
const { iframeHeight } = useIframeHeight({ iframeRef
|
|
1328
|
+
const { iframeHeight } = useIframeHeight({ iframeRef });
|
|
1046
1329
|
// 4. Calculate scale
|
|
1047
1330
|
const { scale } = useScaleCalculation({ containerWidth, contentWidth });
|
|
1048
1331
|
// 5. Setup scroll sync
|
|
@@ -1068,7 +1351,8 @@ const BoxStack = forwardRef(({ children, ...props }, ref) => {
|
|
|
1068
1351
|
const style = props.style || {};
|
|
1069
1352
|
const gap = props.gap || 0;
|
|
1070
1353
|
const height = props.height || 'auto';
|
|
1071
|
-
const
|
|
1354
|
+
const isZIndexDefined = typeof props.zIndex !== undefined;
|
|
1355
|
+
const zIndex = props.zIndex;
|
|
1072
1356
|
const backgroundColor = props.backgroundColor || 'transparent';
|
|
1073
1357
|
const styleGap = useMemo(() => {
|
|
1074
1358
|
switch (flexDirection) {
|
|
@@ -1091,8 +1375,8 @@ const BoxStack = forwardRef(({ children, ...props }, ref) => {
|
|
|
1091
1375
|
justifyContent,
|
|
1092
1376
|
alignItems,
|
|
1093
1377
|
height,
|
|
1094
|
-
zIndex,
|
|
1095
1378
|
backgroundColor,
|
|
1379
|
+
...(isZIndexDefined ? { zIndex } : {}),
|
|
1096
1380
|
...styleGap,
|
|
1097
1381
|
...style,
|
|
1098
1382
|
};
|
|
@@ -1414,11 +1698,12 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
|
|
|
1414
1698
|
const VizDomContainer = () => {
|
|
1415
1699
|
const controls = useHeatmapControlStore((state) => state.controls);
|
|
1416
1700
|
const isRendering = useHeatmapDataStore((state) => state.isRendering);
|
|
1701
|
+
const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
|
|
1417
1702
|
if (isRendering)
|
|
1418
1703
|
return controls.VizLoading ?? null;
|
|
1419
|
-
return (jsx(BoxStack, { id: "gx-hm-viz-container", flexDirection: "column", flex: "1 1 auto", overflow: "auto", children:
|
|
1704
|
+
return (jsx(BoxStack, { id: "gx-hm-viz-container", flexDirection: "column", flex: "1 1 auto", overflow: "auto", zIndex: 1, children: jsxs(BoxStack, { id: "gx-hm-content", flexDirection: "column", flex: "1 1 auto", overflow: "hidden", style: {
|
|
1420
1705
|
minWidth: '394px',
|
|
1421
|
-
}, children: jsx(VizDomRenderer, {}) }) }));
|
|
1706
|
+
}, children: [jsx(VizDomRenderer, {}), iframeHeight === 0 && (jsxs("div", { className: "gx-hm-loading", children: [jsx("div", { className: "gx-hm-loading--spinner" }), jsx("p", { className: "gx-hm-loading--text", children: "Loading visualization..." })] }))] }) }));
|
|
1422
1707
|
};
|
|
1423
1708
|
|
|
1424
1709
|
const ContentMetricBar = () => {
|
|
@@ -1431,6 +1716,7 @@ const ContentMetricBar = () => {
|
|
|
1431
1716
|
const ContentToolbar = () => {
|
|
1432
1717
|
const controls = useHeatmapControlStore((state) => state.controls);
|
|
1433
1718
|
return (jsx("div", { id: "gx-hm-content-toolbar", style: {
|
|
1719
|
+
zIndex: 2,
|
|
1434
1720
|
position: 'absolute',
|
|
1435
1721
|
bottom: 0,
|
|
1436
1722
|
left: '8px',
|
|
@@ -1451,6 +1737,7 @@ const LeftSidebar = () => {
|
|
|
1451
1737
|
return (jsx("div", { className: "gx-hm-sidebar", style: {
|
|
1452
1738
|
height: '100%',
|
|
1453
1739
|
display: 'flex',
|
|
1740
|
+
zIndex: 1,
|
|
1454
1741
|
...(isHideSidebar
|
|
1455
1742
|
? {
|
|
1456
1743
|
width: '0',
|