@thoughtspot/visual-embed-sdk 1.24.0-preRender.2 → 1.24.0-preRender.4

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 (139) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/embed/app.d.ts +1 -3
  3. package/cjs/src/embed/app.d.ts.map +1 -1
  4. package/cjs/src/embed/app.js +2 -8
  5. package/cjs/src/embed/app.js.map +1 -1
  6. package/cjs/src/embed/app.spec.js +8 -0
  7. package/cjs/src/embed/app.spec.js.map +1 -1
  8. package/cjs/src/embed/liveboard.d.ts +3 -3
  9. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  10. package/cjs/src/embed/liveboard.js +26 -9
  11. package/cjs/src/embed/liveboard.js.map +1 -1
  12. package/cjs/src/embed/liveboard.spec.js +56 -0
  13. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  14. package/cjs/src/embed/sage.d.ts +1 -3
  15. package/cjs/src/embed/sage.d.ts.map +1 -1
  16. package/cjs/src/embed/sage.js +2 -8
  17. package/cjs/src/embed/sage.js.map +1 -1
  18. package/cjs/src/embed/search.d.ts +1 -4
  19. package/cjs/src/embed/search.d.ts.map +1 -1
  20. package/cjs/src/embed/search.js +2 -9
  21. package/cjs/src/embed/search.js.map +1 -1
  22. package/cjs/src/embed/ts-embed.d.ts +54 -18
  23. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  24. package/cjs/src/embed/ts-embed.js +134 -93
  25. package/cjs/src/embed/ts-embed.js.map +1 -1
  26. package/cjs/src/embed/ts-embed.spec.js +102 -0
  27. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  28. package/cjs/src/react/all-types-export.d.ts +1 -1
  29. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  30. package/cjs/src/react/all-types-export.js +6 -2
  31. package/cjs/src/react/all-types-export.js.map +1 -1
  32. package/cjs/src/react/index.d.ts +103 -5
  33. package/cjs/src/react/index.d.ts.map +1 -1
  34. package/cjs/src/react/index.js +81 -1
  35. package/cjs/src/react/index.js.map +1 -1
  36. package/cjs/src/react/index.spec.js +22 -0
  37. package/cjs/src/react/index.spec.js.map +1 -1
  38. package/cjs/src/types.d.ts +18 -0
  39. package/cjs/src/types.d.ts.map +1 -1
  40. package/cjs/src/types.js.map +1 -1
  41. package/cjs/src/utils.d.ts +27 -0
  42. package/cjs/src/utils.d.ts.map +1 -1
  43. package/cjs/src/utils.js +31 -0
  44. package/cjs/src/utils.js.map +1 -1
  45. package/cjs/src/utils.spec.d.ts +0 -3
  46. package/cjs/src/utils.spec.d.ts.map +1 -1
  47. package/cjs/src/utils.spec.js +59 -6
  48. package/cjs/src/utils.spec.js.map +1 -1
  49. package/dist/src/embed/app.d.ts +1 -3
  50. package/dist/src/embed/app.d.ts.map +1 -1
  51. package/dist/src/embed/liveboard.d.ts +3 -3
  52. package/dist/src/embed/liveboard.d.ts.map +1 -1
  53. package/dist/src/embed/sage.d.ts +1 -3
  54. package/dist/src/embed/sage.d.ts.map +1 -1
  55. package/dist/src/embed/search.d.ts +1 -4
  56. package/dist/src/embed/search.d.ts.map +1 -1
  57. package/dist/src/embed/ts-embed.d.ts +54 -18
  58. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  59. package/dist/src/react/all-types-export.d.ts +1 -1
  60. package/dist/src/react/all-types-export.d.ts.map +1 -1
  61. package/dist/src/react/index.d.ts +103 -5
  62. package/dist/src/react/index.d.ts.map +1 -1
  63. package/dist/src/types.d.ts +18 -0
  64. package/dist/src/types.d.ts.map +1 -1
  65. package/dist/src/utils.d.ts +27 -0
  66. package/dist/src/utils.d.ts.map +1 -1
  67. package/dist/src/utils.spec.d.ts +0 -3
  68. package/dist/src/utils.spec.d.ts.map +1 -1
  69. package/dist/tsembed-react.es.js +17590 -243
  70. package/dist/tsembed-react.js +17590 -242
  71. package/dist/tsembed.es.js +17519 -252
  72. package/dist/tsembed.js +17519 -252
  73. package/dist/visual-embed-sdk-react-full.d.ts +187 -32
  74. package/dist/visual-embed-sdk-react.d.ts +187 -32
  75. package/dist/visual-embed-sdk.d.ts +84 -27
  76. package/lib/package.json +1 -1
  77. package/lib/src/embed/app.d.ts +1 -3
  78. package/lib/src/embed/app.d.ts.map +1 -1
  79. package/lib/src/embed/app.js +2 -8
  80. package/lib/src/embed/app.js.map +1 -1
  81. package/lib/src/embed/app.spec.js +8 -0
  82. package/lib/src/embed/app.spec.js.map +1 -1
  83. package/lib/src/embed/liveboard.d.ts +3 -3
  84. package/lib/src/embed/liveboard.d.ts.map +1 -1
  85. package/lib/src/embed/liveboard.js +25 -9
  86. package/lib/src/embed/liveboard.js.map +1 -1
  87. package/lib/src/embed/liveboard.spec.js +57 -1
  88. package/lib/src/embed/liveboard.spec.js.map +1 -1
  89. package/lib/src/embed/sage.d.ts +1 -3
  90. package/lib/src/embed/sage.d.ts.map +1 -1
  91. package/lib/src/embed/sage.js +2 -8
  92. package/lib/src/embed/sage.js.map +1 -1
  93. package/lib/src/embed/search.d.ts +1 -4
  94. package/lib/src/embed/search.d.ts.map +1 -1
  95. package/lib/src/embed/search.js +2 -9
  96. package/lib/src/embed/search.js.map +1 -1
  97. package/lib/src/embed/ts-embed.d.ts +54 -18
  98. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  99. package/lib/src/embed/ts-embed.js +134 -93
  100. package/lib/src/embed/ts-embed.js.map +1 -1
  101. package/lib/src/embed/ts-embed.spec.js +102 -0
  102. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  103. package/lib/src/react/all-types-export.d.ts +1 -1
  104. package/lib/src/react/all-types-export.d.ts.map +1 -1
  105. package/lib/src/react/all-types-export.js +1 -1
  106. package/lib/src/react/all-types-export.js.map +1 -1
  107. package/lib/src/react/index.d.ts +103 -5
  108. package/lib/src/react/index.d.ts.map +1 -1
  109. package/lib/src/react/index.js +80 -0
  110. package/lib/src/react/index.js.map +1 -1
  111. package/lib/src/react/index.spec.js +23 -1
  112. package/lib/src/react/index.spec.js.map +1 -1
  113. package/lib/src/types.d.ts +18 -0
  114. package/lib/src/types.d.ts.map +1 -1
  115. package/lib/src/types.js.map +1 -1
  116. package/lib/src/utils.d.ts +27 -0
  117. package/lib/src/utils.d.ts.map +1 -1
  118. package/lib/src/utils.js +31 -0
  119. package/lib/src/utils.js.map +1 -1
  120. package/lib/src/utils.spec.d.ts +0 -3
  121. package/lib/src/utils.spec.d.ts.map +1 -1
  122. package/lib/src/utils.spec.js +60 -7
  123. package/lib/src/utils.spec.js.map +1 -1
  124. package/lib/src/visual-embed-sdk.d.ts +84 -27
  125. package/package.json +1 -1
  126. package/src/embed/app.spec.ts +8 -0
  127. package/src/embed/app.ts +6 -11
  128. package/src/embed/liveboard.spec.ts +76 -1
  129. package/src/embed/liveboard.ts +28 -12
  130. package/src/embed/sage.ts +2 -11
  131. package/src/embed/search.ts +2 -12
  132. package/src/embed/ts-embed.spec.ts +127 -0
  133. package/src/embed/ts-embed.ts +169 -123
  134. package/src/react/all-types-export.ts +5 -1
  135. package/src/react/index.spec.tsx +42 -1
  136. package/src/react/index.tsx +120 -17
  137. package/src/types.ts +19 -0
  138. package/src/utils.spec.ts +78 -7
  139. package/src/utils.ts +29 -1
@@ -88,12 +88,17 @@ export class TsEmbed {
88
88
  * This is useful for removing the DOM node when the
89
89
  * embed instance is destroyed.
90
90
  */
91
- private insertedDomEl: Node;
91
+ protected insertedDomEl: Node;
92
92
 
93
93
  /**
94
94
  * The DOM node where the ThoughtSpot app is to be embedded.
95
95
  */
96
- private el: Element;
96
+ protected el: Element;
97
+
98
+ /**
99
+ * The key to store the embed instance in the DOM node
100
+ */
101
+ protected embedNodeKey = '__tsEmbed'
97
102
 
98
103
  protected isAppInitialized = false;
99
104
 
@@ -129,13 +134,18 @@ export class TsEmbed {
129
134
  /**
130
135
  * A flag that is set to true post render.
131
136
  */
132
- private isRendered: boolean;
137
+ protected isRendered: boolean;
133
138
 
134
139
  /**
135
140
  * A flag to mark if an error has occurred.
136
141
  */
137
142
  private isError: boolean;
138
143
 
144
+ /**
145
+ * A flag that is set to true post preRender.
146
+ */
147
+ private isPreRendered: boolean;
148
+
139
149
  /**
140
150
  * Should we encode URL Query Params using base64 encoding which thoughtspot
141
151
  * will generate for embedding. This provides additional security to
@@ -147,6 +157,8 @@ export class TsEmbed {
147
157
 
148
158
  private defaultHiddenActions = [Action.ReportError];
149
159
 
160
+ private resizeObserver: ResizeObserver;
161
+
150
162
  constructor(domSelector: DOMSelector, viewConfig?: ViewConfig) {
151
163
  this.el = getDOMNode(domSelector);
152
164
  // TODO: handle error
@@ -377,7 +389,8 @@ export class TsEmbed {
377
389
  queryParams[Param.ViewPortWidth] = window.innerWidth;
378
390
  queryParams[Param.Version] = version;
379
391
  queryParams[Param.AuthType] = this.embedConfig.authType;
380
- queryParams[Param.blockNonEmbedFullAppAccess] = this.embedConfig.blockNonEmbedFullAppAccess ?? true;
392
+ queryParams[Param.blockNonEmbedFullAppAccess] = this.embedConfig.blockNonEmbedFullAppAccess
393
+ ?? true;
381
394
  if (this.embedConfig.disableLoginRedirect === true || this.embedConfig.autoLogin === true) {
382
395
  queryParams[Param.DisableLoginRedirect] = true;
383
396
  }
@@ -454,7 +467,8 @@ export class TsEmbed {
454
467
  queryParams[Param.ContextMenuTrigger] = false;
455
468
  }
456
469
 
457
- const spriteUrl = customizations?.iconSpriteUrl || this.embedConfig.customizations?.iconSpriteUrl;
470
+ const spriteUrl = customizations?.iconSpriteUrl
471
+ || this.embedConfig.customizations?.iconSpriteUrl;
458
472
  if (spriteUrl) {
459
473
  queryParams[Param.IconSpriteUrl] = spriteUrl.replace('https://', '');
460
474
  }
@@ -533,7 +547,9 @@ export class TsEmbed {
533
547
  // @ts-ignore
534
548
  iFrame.allow = 'clipboard-read; clipboard-write';
535
549
 
536
- const { height: frameHeight, width: frameWidth, ...restParams } = this.viewConfig.frameParams || {};
550
+ const {
551
+ height: frameHeight, width: frameWidth, ...restParams
552
+ } = this.viewConfig.frameParams || {};
537
553
  const width = getCssDimension(frameWidth || DEFAULT_EMBED_WIDTH);
538
554
  const height = getCssDimension(frameHeight || DEFAULT_EMBED_HEIGHT);
539
555
  setAttributes(iFrame, restParams);
@@ -545,15 +561,15 @@ export class TsEmbed {
545
561
  return iFrame;
546
562
  }
547
563
 
548
- protected handleInsertionIntoDOM(child: string | Node, showPreRenderByDefault = false): void {
564
+ protected handleInsertionIntoDOM(child: string | Node): void {
549
565
  if (this.isPreRendered) {
550
- if (!this.viewConfig.preRenderId) {
551
- throw Error('PreRender id is required for preRender');
552
- }
553
- this.insertIntoDOMForPreRender(child, showPreRenderByDefault);
566
+ this.insertIntoDOMForPreRender(child);
554
567
  } else {
555
568
  this.insertIntoDOM(child);
556
569
  }
570
+ if (this.insertedDomEl instanceof Node) {
571
+ this.insertedDomEl[this.embedNodeKey] = this;
572
+ }
557
573
  }
558
574
 
559
575
  /**
@@ -561,9 +577,8 @@ export class TsEmbed {
561
577
  * event listeners.
562
578
  *
563
579
  * @param url - The URL of the embedded ThoughtSpot app.
564
- * @param showPreRenderByDefault - The flag to show the preRender by default.
565
580
  */
566
- protected async renderIFrame(url: string, showPreRenderByDefault = false): Promise<any> {
581
+ protected async renderIFrame(url: string): Promise<any> {
567
582
  if (this.isError) {
568
583
  return null;
569
584
  }
@@ -588,10 +603,7 @@ export class TsEmbed {
588
603
  return getAuthPromise()
589
604
  ?.then((isLoggedIn: boolean) => {
590
605
  if (!isLoggedIn) {
591
- this.handleInsertionIntoDOM(
592
- this.embedConfig.loginFailedMessage,
593
- showPreRenderByDefault,
594
- );
606
+ this.handleInsertionIntoDOM(this.embedConfig.loginFailedMessage);
595
607
  return;
596
608
  }
597
609
 
@@ -614,7 +626,7 @@ export class TsEmbed {
614
626
  this.iFrame.addEventListener('error', () => {
615
627
  nextInQueue();
616
628
  });
617
- this.handleInsertionIntoDOM(this.iFrame, showPreRenderByDefault);
629
+ this.handleInsertionIntoDOM(this.iFrame);
618
630
  const prefetchIframe = document.querySelectorAll('.prefetchIframe');
619
631
  if (prefetchIframe.length) {
620
632
  prefetchIframe.forEach((el) => {
@@ -634,15 +646,6 @@ export class TsEmbed {
634
646
  });
635
647
  }
636
648
 
637
- public getPreRenderIds() {
638
- return {
639
- wrapper: `tsEmbed-pre-render-wrapper-${this.viewConfig.preRenderId}`,
640
- // shield:
641
- // `tsEmbed-pre-render-shield-${this.viewConfig.preRenderId}`,
642
- child: `tsEmbed-pre-render-child-${this.viewConfig.preRenderId}`,
643
- };
644
- }
645
-
646
649
  protected createPreRenderWrapper(): HTMLDivElement {
647
650
  if (!this.viewConfig.preRenderId) {
648
651
  throw new Error('PreRender id is required to create PreRender wrapper');
@@ -661,44 +664,38 @@ export class TsEmbed {
661
664
  };
662
665
  setStyleProperties(preRenderWrapper, initialPreRenderWrapperStyle);
663
666
 
664
- // const preRenderShield = document.createElement('div');
665
- // preRenderShield.id = preRenderIds.shield;
666
- // setStyleProperties(preRenderShield, { position: 'absolute',
667
- // width: '100%', height: '100%' });
668
-
669
- // preRenderWrapper.appendChild(preRenderShield);
670
-
671
- // this.preRenderWrapper = preRenderWrapper;
672
- // this.preRenderShield = preRenderShield;
673
- // this.preRenderChild = child;
674
-
675
667
  return preRenderWrapper;
676
668
  }
677
669
 
678
670
  protected preRenderWrapper: HTMLElement;
679
671
 
680
- // protected preRenderShield: HTMLElement;
681
-
682
672
  protected preRenderChild: HTMLElement;
683
673
 
684
674
  protected connectPreRendered(): boolean {
685
675
  const preRenderIds = this.getPreRenderIds();
686
676
  this.preRenderWrapper = this.preRenderWrapper
687
- || document.getElementById(preRenderIds.wrapper);
688
- // this.preRenderShield = this.preRenderShield
689
- // || document.getElementById(preRenderIds.shield);
677
+ || document.getElementById(preRenderIds.wrapper);
678
+
690
679
  this.preRenderChild = this.preRenderChild || document.getElementById(preRenderIds.child);
691
680
 
692
681
  if (this.preRenderWrapper && this.preRenderChild) {
693
682
  this.isPreRendered = true;
694
- this.iFrame = this.preRenderChild as HTMLIFrameElement;
683
+ if (this.preRenderChild instanceof HTMLIFrameElement) {
684
+ this.iFrame = this.preRenderChild;
685
+ }
686
+ this.insertedDomEl = this.preRenderWrapper;
687
+ this.isRendered = true;
695
688
  }
696
689
 
697
690
  return this.isPreRenderAvailable();
698
691
  }
699
692
 
700
693
  protected isPreRenderAvailable(): boolean {
701
- return this.isPreRendered;
694
+ return (
695
+ this.isRendered
696
+ && this.isPreRendered
697
+ && Boolean(this.preRenderWrapper && this.preRenderChild)
698
+ );
702
699
  }
703
700
 
704
701
  protected createPreRenderChild(child: string | Node): HTMLElement {
@@ -724,10 +721,7 @@ export class TsEmbed {
724
721
  return divChildNode;
725
722
  }
726
723
 
727
- protected insertIntoDOMForPreRender(
728
- child: string | Node,
729
- showPreRenderByDefault = false,
730
- ): void {
724
+ protected insertIntoDOMForPreRender(child: string | Node): void {
731
725
  const preRenderChild = this.createPreRenderChild(child);
732
726
  const preRenderWrapper = this.createPreRenderWrapper();
733
727
  preRenderWrapper.appendChild(preRenderChild);
@@ -738,8 +732,9 @@ export class TsEmbed {
738
732
  if (preRenderChild instanceof HTMLIFrameElement) {
739
733
  this.iFrame = preRenderChild;
740
734
  }
735
+ this.insertedDomEl = preRenderWrapper;
741
736
 
742
- if (showPreRenderByDefault) {
737
+ if (this.showPreRenderByDefault) {
743
738
  this.showPreRender();
744
739
  } else {
745
740
  this.hidePreRender();
@@ -748,74 +743,7 @@ export class TsEmbed {
748
743
  document.body.appendChild(preRenderWrapper);
749
744
  }
750
745
 
751
- public hidePreRender(): void {
752
- if (!this.isPreRenderAvailable()) {
753
- // if the embed component is not preRendered , nothing to hide
754
- console.warn(
755
- 'Warning: You should call PreRender before hiding it using hidePreRender.',
756
- );
757
- return;
758
- }
759
- const preRenderHideStyles = {
760
- opacity: '0',
761
- pointerEvents: 'none',
762
- zIndex: '-1000',
763
- position: 'absolute ',
764
- top: '0',
765
- left: '0',
766
- };
767
- setStyleProperties(this.preRenderWrapper, preRenderHideStyles);
768
-
769
- // const childBoundingRect = this.preRenderChild.getBoundingClientRect();
770
- //
771
- // setStyleProperties(this.preRenderShield, {
772
- // opacity: '0',
773
- // pointerEvents: 'none',
774
- // zIndex: '1',
775
- // width: `${childBoundingRect.width}px`,
776
- // height: `${childBoundingRect.height}px`,
777
- // position: 'absolute',
778
- // top: '0',
779
- // left: '0',
780
- // });
781
-
782
- this.unsubscribeToEvents();
783
- }
784
-
785
- public showPreRender(): void {
786
- if (!this.isPreRenderAvailable()) {
787
- const isAvailable = this.connectPreRendered();
788
- if (!isAvailable) {
789
- // if the Embed component is not preRendered , Render it now and
790
- this.preRender(true);
791
- // show it (hide is defalt behaviour)
792
- // console.log('No preRender found, creating new ');
793
- return;
794
- }
795
- }
796
-
797
- this.syncPreRenderStyle();
798
-
799
- removeStyleProperties(this.preRenderWrapper, ['z-index', 'opacity', 'pointer-events']);
800
-
801
- // setStyleProperties(this.preRenderShield, { zIndex: '-1' });
802
-
803
- this.subscribeToEvents();
804
- }
805
-
806
- public syncPreRenderStyle(): void {
807
- if (!this.el) {
808
- throw new Error('Embed element is not defined');
809
- }
810
- const elBoundingClient = this.el.getBoundingClientRect();
811
-
812
- setStyleProperties(this.preRenderWrapper, {
813
- top: `${elBoundingClient.y}px`,
814
- left: `${elBoundingClient.x}px`,
815
- width: `${elBoundingClient.width}px`,
816
- height: `${elBoundingClient.height}px`,
817
- });
818
- }
746
+ private showPreRenderByDefault = false;
819
747
 
820
748
  protected insertIntoDOM(child: string | Node): void {
821
749
  if (this.viewConfig.insertAsSibling) {
@@ -1048,15 +976,23 @@ export class TsEmbed {
1048
976
  return this;
1049
977
  }
1050
978
 
1051
- private isPreRendered: boolean;
979
+ protected handleRenderForPrerender() {
980
+ this.render();
981
+ }
1052
982
 
1053
983
  /**
1054
984
  * Creates the preRender shell
1055
985
  *
1056
- * @param showPreRenderByDefault
986
+ * @param showPreRenderByDefault - Show the preRender after render, hidden by default
1057
987
  */
1058
988
  public preRender(showPreRenderByDefault = false): TsEmbed {
989
+ if (!this.viewConfig.preRenderId) {
990
+ console.error('PreRender id is required for preRender');
991
+ return this;
992
+ }
1059
993
  this.isPreRendered = true;
994
+ this.showPreRenderByDefault = showPreRenderByDefault;
995
+ this.handleRenderForPrerender();
1060
996
  return this;
1061
997
  }
1062
998
 
@@ -1118,8 +1054,119 @@ export class TsEmbed {
1118
1054
  */
1119
1055
  public async prerenderGeneric(): Promise<any> {
1120
1056
  const prerenderFrameSrc = this.getRootIframeSrc();
1057
+ this.isRendered = true;
1121
1058
  return this.renderIFrame(prerenderFrameSrc);
1122
1059
  }
1060
+
1061
+ protected beforePrerenderVisible(): void {
1062
+ // Override in subclass
1063
+ }
1064
+
1065
+ /**
1066
+ * Displays the PreRender component.
1067
+ * If the component is not preRendered, it attempts to create and render it.
1068
+ * Also, synchronizes the style of the PreRender component with the embedding
1069
+ * element.
1070
+ */
1071
+ public showPreRender(): void {
1072
+ if (!this.isPreRenderAvailable()) {
1073
+ const isAvailable = this.connectPreRendered();
1074
+ if (!isAvailable) {
1075
+ // if the Embed component is not preRendered , Render it now and
1076
+ this.preRender(true);
1077
+ return;
1078
+ }
1079
+ }
1080
+
1081
+ if (this.el) {
1082
+ this.syncPreRenderStyle();
1083
+
1084
+ this.resizeObserver = new ResizeObserver((entries) => {
1085
+ entries.forEach((entry) => {
1086
+ if (entry.contentRect && entry.target === this.el) {
1087
+ setStyleProperties(this.preRenderWrapper, {
1088
+ width: `${entry.contentRect.width}px`,
1089
+ height: `${entry.contentRect.height}px`,
1090
+ });
1091
+ }
1092
+ });
1093
+ });
1094
+ this.resizeObserver.observe(this.el);
1095
+ }
1096
+
1097
+ this.beforePrerenderVisible();
1098
+
1099
+ removeStyleProperties(this.preRenderWrapper, ['z-index', 'opacity', 'pointer-events']);
1100
+
1101
+ this.subscribeToEvents();
1102
+ }
1103
+
1104
+ /**
1105
+ * Synchronizes the style properties of the PreRender component with the embedding
1106
+ * element. This function adjusts the position, width, and height of the PreRender
1107
+ * component
1108
+ * to match the dimensions and position of the embedding element.
1109
+ *
1110
+ * @throws {Error} Throws an error if the embedding element (passed as domSelector)
1111
+ * is not defined or not found.
1112
+ */
1113
+ public syncPreRenderStyle(): void {
1114
+ if (!this.el) {
1115
+ throw new Error('Embed element is not defined');
1116
+ }
1117
+ const elBoundingClient = this.el.getBoundingClientRect();
1118
+
1119
+ setStyleProperties(this.preRenderWrapper, {
1120
+ top: `${elBoundingClient.y}px`,
1121
+ left: `${elBoundingClient.x}px`,
1122
+ width: `${elBoundingClient.width}px`,
1123
+ height: `${elBoundingClient.height}px`,
1124
+ });
1125
+ }
1126
+
1127
+ /**
1128
+ * Hides the PreRender component if it is available.
1129
+ * If the component is not preRendered, it issues a warning.
1130
+ */
1131
+ public hidePreRender(): void {
1132
+ if (!this.isPreRenderAvailable()) {
1133
+ // if the embed component is not preRendered , nothing to hide
1134
+ console.warn(
1135
+ 'Warning: You should call PreRender before hiding it using hidePreRender.',
1136
+ );
1137
+ return;
1138
+ }
1139
+ const preRenderHideStyles = {
1140
+ opacity: '0',
1141
+ pointerEvents: 'none',
1142
+ zIndex: '-1000',
1143
+ position: 'absolute ',
1144
+ top: '0',
1145
+ left: '0',
1146
+ };
1147
+ setStyleProperties(this.preRenderWrapper, preRenderHideStyles);
1148
+
1149
+ if (this.resizeObserver) {
1150
+ this.resizeObserver.disconnect();
1151
+ }
1152
+
1153
+ this.unsubscribeToEvents();
1154
+ }
1155
+
1156
+ /**
1157
+ * Retrieves unique HTML element IDs for PreRender-related elements.
1158
+ * These IDs are constructed based on the provided 'preRenderId' from 'viewConfig'.
1159
+ *
1160
+ * @returns {object} An object containing the IDs for the PreRender elements.
1161
+ * @property {string} wrapper - The HTML element ID for the PreRender wrapper.
1162
+ * @property {string} child - The HTML element ID for the PreRender child.
1163
+ */
1164
+ public getPreRenderIds() {
1165
+ return {
1166
+ wrapper: `tsEmbed-pre-render-wrapper-${this.viewConfig.preRenderId}`,
1167
+ child: `tsEmbed-pre-render-child-${this.viewConfig.preRenderId}`,
1168
+ };
1169
+ }
1123
1170
  }
1124
1171
 
1125
1172
  /**
@@ -1141,10 +1188,9 @@ export class V1Embed extends TsEmbed {
1141
1188
  * Render the app in an iframe and set up event handlers
1142
1189
  *
1143
1190
  * @param iframeSrc
1144
- * @param showPreRenderByDefault - if true the preRender will be shown by default
1145
1191
  */
1146
- protected renderV1Embed(iframeSrc: string, showPreRenderByDefault = false): any {
1147
- return this.renderIFrame(iframeSrc, showPreRenderByDefault);
1192
+ protected renderV1Embed(iframeSrc: string): Promise<any> {
1193
+ return this.renderIFrame(iframeSrc);
1148
1194
  }
1149
1195
 
1150
1196
  protected getRootIframeSrc(): string {
@@ -1,11 +1,15 @@
1
1
  export {
2
2
  SearchEmbed,
3
+ PreRenderedSearchEmbed,
3
4
  LiveboardEmbed,
5
+ PreRenderedLiveboardEmbed,
4
6
  SearchBarEmbed,
7
+ PreRenderedSearchBarEmbed,
5
8
  AppEmbed,
9
+ PreRenderedAppEmbed,
6
10
  SageEmbed,
11
+ PreRenderedSageEmbed,
7
12
  useEmbedRef,
8
- PreRenderedLiveboardEmbed,
9
13
  } from './index';
10
14
 
11
15
  export {
@@ -15,7 +15,7 @@ import {
15
15
  mockMessageChannel,
16
16
  } from '../test/test-utils';
17
17
  import {
18
- SearchEmbed, AppEmbed, LiveboardEmbed, useEmbedRef, SearchBarEmbed,
18
+ SearchEmbed, AppEmbed, LiveboardEmbed, useEmbedRef, SearchBarEmbed, PreRenderedLiveboardEmbed,
19
19
  } from './index';
20
20
  import * as allExports from './index';
21
21
  import {
@@ -226,6 +226,47 @@ describe('React Components', () => {
226
226
  );
227
227
  });
228
228
  });
229
+
230
+ describe('PreRenderedLiveboardEmbed', () => {
231
+ it('should preRender the liveboard ', async () => {
232
+ const preRenderId = 'tsEmbed-pre-render-wrapper-test';
233
+
234
+ const { container } = render(
235
+ <PreRenderedLiveboardEmbed
236
+ className="embedClass"
237
+ preRenderId="test"
238
+ liveboardId="libId"
239
+ />,
240
+ );
241
+
242
+ await waitFor(() => getIFrameEl());
243
+ const preRenderWrapper = document.body.querySelector(`#${preRenderId}`) as HTMLDivElement;
244
+
245
+ expect(preRenderWrapper).toBeInstanceOf(HTMLDivElement);
246
+ expect((preRenderWrapper as HTMLDivElement).childElementCount).toBe(1);
247
+
248
+ const preRenderChildId = 'tsEmbed-pre-render-child-test';
249
+ const preRenderChild = document.body.querySelector(`#${preRenderChildId}`);
250
+ expect(preRenderWrapper.children[0]).toBe(preRenderChild);
251
+
252
+ (window as any).ResizeObserver = jest.fn().mockImplementation(() => ({
253
+ disconnect: jest.fn(),
254
+ observe: jest.fn(),
255
+ unobserve: jest.fn(),
256
+ }));
257
+ const { container: libContainer } = render(
258
+ <LiveboardEmbed
259
+ className="embedClass"
260
+ preRenderId="test"
261
+ liveboardId="libId"
262
+ />,
263
+ );
264
+
265
+ expect(preRenderWrapper.style.opacity).toBe('');
266
+ expect(preRenderWrapper.style.pointerEvents).toBe('');
267
+ expect(preRenderWrapper.style.zIndex).toBe('');
268
+ });
269
+ });
229
270
  });
230
271
 
231
272
  describe('allExports', () => {