@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.
Files changed (57) hide show
  1. package/dist/esm/components/Layout/ContentToolbar.d.ts.map +1 -1
  2. package/dist/esm/components/Layout/LeftSidebar.d.ts.map +1 -1
  3. package/dist/esm/components/VizDom/VizDomContainer.d.ts.map +1 -1
  4. package/dist/esm/configs/iframe.d.ts +1 -1
  5. package/dist/esm/configs/iframe.d.ts.map +1 -1
  6. package/dist/esm/helpers/index.d.ts +2 -0
  7. package/dist/esm/helpers/index.d.ts.map +1 -1
  8. package/dist/esm/helpers/viewport-fixer.d.ts +13 -0
  9. package/dist/esm/helpers/viewport-fixer.d.ts.map +1 -0
  10. package/dist/esm/helpers/viewport-replacer.d.ts +25 -0
  11. package/dist/esm/helpers/viewport-replacer.d.ts.map +1 -0
  12. package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
  13. package/dist/esm/hooks/viz-scale/useContentDimensions.d.ts +1 -1
  14. package/dist/esm/hooks/viz-scale/useContentDimensions.d.ts.map +1 -1
  15. package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
  16. package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts +0 -1
  17. package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts.map +1 -1
  18. package/dist/esm/hooks/viz-scale/useScrollSync.d.ts.map +1 -1
  19. package/dist/esm/index.js +318 -31
  20. package/dist/esm/index.mjs +318 -31
  21. package/dist/esm/stores/viz.d.ts +2 -0
  22. package/dist/esm/stores/viz.d.ts.map +1 -1
  23. package/dist/esm/types/index.d.ts +1 -0
  24. package/dist/esm/types/index.d.ts.map +1 -1
  25. package/dist/esm/types/viewport-fixer.d.ts +28 -0
  26. package/dist/esm/types/viewport-fixer.d.ts.map +1 -0
  27. package/dist/esm/ui/BoxStack/BoxStack.d.ts +1 -1
  28. package/dist/esm/ui/BoxStack/BoxStack.d.ts.map +1 -1
  29. package/dist/style.css +45 -1
  30. package/dist/umd/components/Layout/ContentToolbar.d.ts.map +1 -1
  31. package/dist/umd/components/Layout/LeftSidebar.d.ts.map +1 -1
  32. package/dist/umd/components/VizDom/VizDomContainer.d.ts.map +1 -1
  33. package/dist/umd/configs/iframe.d.ts +1 -1
  34. package/dist/umd/configs/iframe.d.ts.map +1 -1
  35. package/dist/umd/helpers/index.d.ts +2 -0
  36. package/dist/umd/helpers/index.d.ts.map +1 -1
  37. package/dist/umd/helpers/viewport-fixer.d.ts +13 -0
  38. package/dist/umd/helpers/viewport-fixer.d.ts.map +1 -0
  39. package/dist/umd/helpers/viewport-replacer.d.ts +25 -0
  40. package/dist/umd/helpers/viewport-replacer.d.ts.map +1 -0
  41. package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
  42. package/dist/umd/hooks/viz-scale/useContentDimensions.d.ts +1 -1
  43. package/dist/umd/hooks/viz-scale/useContentDimensions.d.ts.map +1 -1
  44. package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
  45. package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts +0 -1
  46. package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts.map +1 -1
  47. package/dist/umd/hooks/viz-scale/useScrollSync.d.ts.map +1 -1
  48. package/dist/umd/index.js +2 -2
  49. package/dist/umd/stores/viz.d.ts +2 -0
  50. package/dist/umd/stores/viz.d.ts.map +1 -1
  51. package/dist/umd/types/index.d.ts +1 -0
  52. package/dist/umd/types/index.d.ts.map +1 -1
  53. package/dist/umd/types/viewport-fixer.d.ts +28 -0
  54. package/dist/umd/types/viewport-fixer.d.ts.map +1 -0
  55. package/dist/umd/ui/BoxStack/BoxStack.d.ts +1 -1
  56. package/dist/umd/ui/BoxStack/BoxStack.d.ts.map +1 -1
  57. 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,EAkBlC,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,EAoC/B,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,EAoBnC,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"}
@@ -3,7 +3,7 @@ interface IFrameAttrs {
3
3
  title: string;
4
4
  sandbox: string;
5
5
  scrolling: string;
6
- height: string;
6
+ height?: string;
7
7
  }
8
8
  export declare const HEATMAP_IFRAME: IFrameAttrs;
9
9
  export {};
@@ -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;CAChB;AAED,eAAO,MAAM,cAAc,EAAE,WAM5B,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"}
@@ -2,4 +2,6 @@ export * from './elm-callout';
2
2
  export * from './elm-getter';
3
3
  export * from './iframe';
4
4
  export * from './viz-elements';
5
+ export * from './viewport-fixer';
6
+ export * from './viewport-replacer';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -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":"AAKA,UAAU,uBAAuB;IAC/B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACtD;AAED,eAAO,MAAM,gBAAgB,QAAO,uBAyCnC,CAAC"}
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: (props: IUseContentDimensionsProps) => IUseContentDimensionsResult;
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,GAC/B,OAAO,0BAA0B,KAChC,2BAaF,CAAC"}
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,sBA0B3D,CAAC"}
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,6 +1,5 @@
1
1
  interface IUseIframeHeightProps {
2
2
  iframeRef: React.RefObject<HTMLIFrameElement | null>;
3
- contentWidth: number;
4
3
  }
5
4
  interface IUseIframeHeightResult {
6
5
  iframeHeight: number;
@@ -1 +1 @@
1
- {"version":3,"file":"useIframeHeight.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-scale/useIframeHeight.ts"],"names":[],"mappings":"AAKA,UAAU,qBAAqB;IAC7B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACrD,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,sBAAsB;IAC9B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,eAAe,GAAI,OAAO,qBAAqB,KAAG,sBAuG9D,CAAC"}
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,oBAyBlE,CAAC"}
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
- // iframe.contentDocument?.body.querySelectorAll('body>*').forEach((element) => {
704
- // console.log(`🚀 🐥 ~ useHeatmapRender ~ element:`, element);
705
- // const isClosedEcomsendWidget = element.closest('#ecomsend-widget');
706
- // const isEcomsendWidget = element.querySelector('#ecomsend-widget');
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 = (props) => {
898
- const contentWidth = useHeatmapDataStore((state) => state.config?.width ?? 0);
899
- const { iframeRef } = props;
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, contentWidth } = props;
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, contentWidth });
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 zIndex = props.zIndex || 0;
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: jsx(BoxStack, { id: "gx-hm-content", flexDirection: "column", flex: "1 1 auto", overflow: "hidden", style: {
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',