@thoughtspot/visual-embed-sdk 1.50.0 → 1.51.0

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 (222) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/css-variables.d.ts +95 -0
  3. package/cjs/src/css-variables.d.ts.map +1 -1
  4. package/cjs/src/embed/app.d.ts +136 -15
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +59 -37
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +419 -149
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/conversation.d.ts +230 -1
  11. package/cjs/src/embed/conversation.d.ts.map +1 -1
  12. package/cjs/src/embed/conversation.js +30 -16
  13. package/cjs/src/embed/conversation.js.map +1 -1
  14. package/cjs/src/embed/conversation.spec.js +221 -17
  15. package/cjs/src/embed/conversation.spec.js.map +1 -1
  16. package/cjs/src/embed/events.spec.js +635 -0
  17. package/cjs/src/embed/events.spec.js.map +1 -1
  18. package/cjs/src/embed/host-events.spec.js +151 -0
  19. package/cjs/src/embed/host-events.spec.js.map +1 -1
  20. package/cjs/src/embed/hostEventClient/contracts.d.ts +51 -14
  21. package/cjs/src/embed/hostEventClient/contracts.d.ts.map +1 -1
  22. package/cjs/src/embed/hostEventClient/contracts.js +11 -1
  23. package/cjs/src/embed/hostEventClient/contracts.js.map +1 -1
  24. package/cjs/src/embed/hostEventClient/host-event-client.d.ts +1 -0
  25. package/cjs/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
  26. package/cjs/src/embed/hostEventClient/host-event-client.js +9 -0
  27. package/cjs/src/embed/hostEventClient/host-event-client.js.map +1 -1
  28. package/cjs/src/embed/hostEventClient/host-event-client.spec.js +218 -0
  29. package/cjs/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
  30. package/cjs/src/embed/hostEventClient/utils.d.ts +2 -0
  31. package/cjs/src/embed/hostEventClient/utils.d.ts.map +1 -1
  32. package/cjs/src/embed/hostEventClient/utils.js +32 -2
  33. package/cjs/src/embed/hostEventClient/utils.js.map +1 -1
  34. package/cjs/src/embed/hostEventClient/utils.spec.js +178 -0
  35. package/cjs/src/embed/hostEventClient/utils.spec.js.map +1 -1
  36. package/cjs/src/embed/liveboard.d.ts +42 -1
  37. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  38. package/cjs/src/embed/liveboard.js +26 -6
  39. package/cjs/src/embed/liveboard.js.map +1 -1
  40. package/cjs/src/embed/liveboard.spec.js +83 -2
  41. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  42. package/cjs/src/embed/spotter-utils.d.ts +8 -1
  43. package/cjs/src/embed/spotter-utils.d.ts.map +1 -1
  44. package/cjs/src/embed/spotter-utils.js +14 -1
  45. package/cjs/src/embed/spotter-utils.js.map +1 -1
  46. package/cjs/src/embed/spotter-utils.spec.js +61 -0
  47. package/cjs/src/embed/spotter-utils.spec.js.map +1 -1
  48. package/cjs/src/embed/spotter-viz-utils.d.ts +34 -0
  49. package/cjs/src/embed/spotter-viz-utils.d.ts.map +1 -1
  50. package/cjs/src/embed/spotter-viz-utils.js.map +1 -1
  51. package/cjs/src/embed/spotter-viz-utils.spec.js +17 -0
  52. package/cjs/src/embed/spotter-viz-utils.spec.js.map +1 -1
  53. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  54. package/cjs/src/embed/ts-embed.js +29 -7
  55. package/cjs/src/embed/ts-embed.js.map +1 -1
  56. package/cjs/src/embed/ts-embed.spec.js +146 -0
  57. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  58. package/cjs/src/errors.d.ts +1 -0
  59. package/cjs/src/errors.d.ts.map +1 -1
  60. package/cjs/src/errors.js +1 -0
  61. package/cjs/src/errors.js.map +1 -1
  62. package/cjs/src/index.d.ts +2 -2
  63. package/cjs/src/index.d.ts.map +1 -1
  64. package/cjs/src/index.js +3 -2
  65. package/cjs/src/index.js.map +1 -1
  66. package/cjs/src/mixpanel-service.d.ts +4 -0
  67. package/cjs/src/mixpanel-service.d.ts.map +1 -1
  68. package/cjs/src/mixpanel-service.js +4 -0
  69. package/cjs/src/mixpanel-service.js.map +1 -1
  70. package/cjs/src/react/util.spec.js +251 -0
  71. package/cjs/src/react/util.spec.js.map +1 -1
  72. package/cjs/src/types.d.ts +573 -11
  73. package/cjs/src/types.d.ts.map +1 -1
  74. package/cjs/src/types.js +519 -2
  75. package/cjs/src/types.js.map +1 -1
  76. package/cjs/src/utils/processData.spec.js +93 -0
  77. package/cjs/src/utils/processData.spec.js.map +1 -1
  78. package/cjs/src/utils/processTrigger.spec.js +61 -0
  79. package/cjs/src/utils/processTrigger.spec.js.map +1 -1
  80. package/dist/{index-B5xoN6Cp.js → index-aBzH5ZwF.js} +1 -1
  81. package/dist/src/css-variables.d.ts +95 -0
  82. package/dist/src/css-variables.d.ts.map +1 -1
  83. package/dist/src/embed/app.d.ts +136 -15
  84. package/dist/src/embed/app.d.ts.map +1 -1
  85. package/dist/src/embed/conversation.d.ts +230 -1
  86. package/dist/src/embed/conversation.d.ts.map +1 -1
  87. package/dist/src/embed/hostEventClient/contracts.d.ts +51 -14
  88. package/dist/src/embed/hostEventClient/contracts.d.ts.map +1 -1
  89. package/dist/src/embed/hostEventClient/host-event-client.d.ts +1 -0
  90. package/dist/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
  91. package/dist/src/embed/hostEventClient/utils.d.ts +2 -0
  92. package/dist/src/embed/hostEventClient/utils.d.ts.map +1 -1
  93. package/dist/src/embed/liveboard.d.ts +42 -1
  94. package/dist/src/embed/liveboard.d.ts.map +1 -1
  95. package/dist/src/embed/spotter-utils.d.ts +8 -1
  96. package/dist/src/embed/spotter-utils.d.ts.map +1 -1
  97. package/dist/src/embed/spotter-viz-utils.d.ts +34 -0
  98. package/dist/src/embed/spotter-viz-utils.d.ts.map +1 -1
  99. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  100. package/dist/src/errors.d.ts +1 -0
  101. package/dist/src/errors.d.ts.map +1 -1
  102. package/dist/src/index.d.ts +2 -2
  103. package/dist/src/index.d.ts.map +1 -1
  104. package/dist/src/mixpanel-service.d.ts +4 -0
  105. package/dist/src/mixpanel-service.d.ts.map +1 -1
  106. package/dist/src/types.d.ts +573 -11
  107. package/dist/src/types.d.ts.map +1 -1
  108. package/dist/tsembed-react.es.js +936 -142
  109. package/dist/tsembed-react.js +935 -141
  110. package/dist/tsembed.es.js +935 -142
  111. package/dist/tsembed.js +933 -140
  112. package/dist/visual-embed-sdk-react-full.d.ts +1147 -44
  113. package/dist/visual-embed-sdk-react.d.ts +1153 -46
  114. package/dist/visual-embed-sdk.d.ts +1161 -46
  115. package/lib/package.json +1 -1
  116. package/lib/src/css-variables.d.ts +95 -0
  117. package/lib/src/css-variables.d.ts.map +1 -1
  118. package/lib/src/embed/app.d.ts +136 -15
  119. package/lib/src/embed/app.d.ts.map +1 -1
  120. package/lib/src/embed/app.js +60 -38
  121. package/lib/src/embed/app.js.map +1 -1
  122. package/lib/src/embed/app.spec.js +420 -150
  123. package/lib/src/embed/app.spec.js.map +1 -1
  124. package/lib/src/embed/conversation.d.ts +230 -1
  125. package/lib/src/embed/conversation.d.ts.map +1 -1
  126. package/lib/src/embed/conversation.js +31 -17
  127. package/lib/src/embed/conversation.js.map +1 -1
  128. package/lib/src/embed/conversation.spec.js +222 -18
  129. package/lib/src/embed/conversation.spec.js.map +1 -1
  130. package/lib/src/embed/events.spec.js +635 -0
  131. package/lib/src/embed/events.spec.js.map +1 -1
  132. package/lib/src/embed/host-events.spec.js +152 -1
  133. package/lib/src/embed/host-events.spec.js.map +1 -1
  134. package/lib/src/embed/hostEventClient/contracts.d.ts +51 -14
  135. package/lib/src/embed/hostEventClient/contracts.d.ts.map +1 -1
  136. package/lib/src/embed/hostEventClient/contracts.js +10 -0
  137. package/lib/src/embed/hostEventClient/contracts.js.map +1 -1
  138. package/lib/src/embed/hostEventClient/host-event-client.d.ts +1 -0
  139. package/lib/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
  140. package/lib/src/embed/hostEventClient/host-event-client.js +10 -1
  141. package/lib/src/embed/hostEventClient/host-event-client.js.map +1 -1
  142. package/lib/src/embed/hostEventClient/host-event-client.spec.js +218 -0
  143. package/lib/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
  144. package/lib/src/embed/hostEventClient/utils.d.ts +2 -0
  145. package/lib/src/embed/hostEventClient/utils.d.ts.map +1 -1
  146. package/lib/src/embed/hostEventClient/utils.js +28 -1
  147. package/lib/src/embed/hostEventClient/utils.js.map +1 -1
  148. package/lib/src/embed/hostEventClient/utils.spec.js +179 -1
  149. package/lib/src/embed/hostEventClient/utils.spec.js.map +1 -1
  150. package/lib/src/embed/liveboard.d.ts +42 -1
  151. package/lib/src/embed/liveboard.d.ts.map +1 -1
  152. package/lib/src/embed/liveboard.js +26 -6
  153. package/lib/src/embed/liveboard.js.map +1 -1
  154. package/lib/src/embed/liveboard.spec.js +83 -2
  155. package/lib/src/embed/liveboard.spec.js.map +1 -1
  156. package/lib/src/embed/spotter-utils.d.ts +8 -1
  157. package/lib/src/embed/spotter-utils.d.ts.map +1 -1
  158. package/lib/src/embed/spotter-utils.js +12 -0
  159. package/lib/src/embed/spotter-utils.js.map +1 -1
  160. package/lib/src/embed/spotter-utils.spec.js +62 -1
  161. package/lib/src/embed/spotter-utils.spec.js.map +1 -1
  162. package/lib/src/embed/spotter-viz-utils.d.ts +34 -0
  163. package/lib/src/embed/spotter-viz-utils.d.ts.map +1 -1
  164. package/lib/src/embed/spotter-viz-utils.js.map +1 -1
  165. package/lib/src/embed/spotter-viz-utils.spec.js +17 -0
  166. package/lib/src/embed/spotter-viz-utils.spec.js.map +1 -1
  167. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  168. package/lib/src/embed/ts-embed.js +29 -7
  169. package/lib/src/embed/ts-embed.js.map +1 -1
  170. package/lib/src/embed/ts-embed.spec.js +146 -0
  171. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  172. package/lib/src/errors.d.ts +1 -0
  173. package/lib/src/errors.d.ts.map +1 -1
  174. package/lib/src/errors.js +1 -0
  175. package/lib/src/errors.js.map +1 -1
  176. package/lib/src/index.d.ts +2 -2
  177. package/lib/src/index.d.ts.map +1 -1
  178. package/lib/src/index.js +2 -2
  179. package/lib/src/index.js.map +1 -1
  180. package/lib/src/mixpanel-service.d.ts +4 -0
  181. package/lib/src/mixpanel-service.d.ts.map +1 -1
  182. package/lib/src/mixpanel-service.js +4 -0
  183. package/lib/src/mixpanel-service.js.map +1 -1
  184. package/lib/src/react/util.spec.js +251 -0
  185. package/lib/src/react/util.spec.js.map +1 -1
  186. package/lib/src/types.d.ts +573 -11
  187. package/lib/src/types.d.ts.map +1 -1
  188. package/lib/src/types.js +519 -2
  189. package/lib/src/types.js.map +1 -1
  190. package/lib/src/utils/processData.spec.js +93 -0
  191. package/lib/src/utils/processData.spec.js.map +1 -1
  192. package/lib/src/utils/processTrigger.spec.js +61 -0
  193. package/lib/src/utils/processTrigger.spec.js.map +1 -1
  194. package/lib/src/visual-embed-sdk.d.ts +1161 -46
  195. package/package.json +1 -1
  196. package/src/css-variables.ts +118 -0
  197. package/src/embed/app.spec.ts +530 -183
  198. package/src/embed/app.ts +209 -66
  199. package/src/embed/conversation.spec.ts +275 -21
  200. package/src/embed/conversation.ts +262 -17
  201. package/src/embed/events.spec.ts +757 -1
  202. package/src/embed/host-events.spec.ts +194 -0
  203. package/src/embed/hostEventClient/contracts.ts +57 -14
  204. package/src/embed/hostEventClient/host-event-client.spec.ts +338 -0
  205. package/src/embed/hostEventClient/host-event-client.ts +16 -0
  206. package/src/embed/hostEventClient/utils.spec.ts +204 -0
  207. package/src/embed/hostEventClient/utils.ts +37 -10
  208. package/src/embed/liveboard.spec.ts +108 -2
  209. package/src/embed/liveboard.ts +82 -14
  210. package/src/embed/spotter-utils.spec.ts +68 -1
  211. package/src/embed/spotter-utils.ts +16 -1
  212. package/src/embed/spotter-viz-utils.spec.ts +17 -0
  213. package/src/embed/spotter-viz-utils.ts +34 -0
  214. package/src/embed/ts-embed.spec.ts +186 -0
  215. package/src/embed/ts-embed.ts +30 -4
  216. package/src/errors.ts +1 -0
  217. package/src/index.ts +3 -1
  218. package/src/mixpanel-service.ts +4 -0
  219. package/src/react/util.spec.tsx +255 -0
  220. package/src/types.ts +575 -8
  221. package/src/utils/processData.spec.ts +97 -0
  222. package/src/utils/processTrigger.spec.ts +91 -0
@@ -402,11 +402,12 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
402
402
  /**
403
403
  * Enables the 'what you see is what you get' PDF export for Liveboards. Each tab is rendered on a single page
404
404
  * following the exact UI layout, instead of splitting visualizations across multiple A4 pages.
405
- * This feature is GA from version 26.5.0.cl. It is disabled by default in embed deployments.
405
+ * This feature is GA from SDK version 1.51.0 and ThoughtSpot version 26.8.0.cl.
406
406
  *
407
407
  * Supported embed types: `AppEmbed`, `LiveboardEmbed`
408
408
  * @type {boolean}
409
409
  * @version SDK: 1.48.0 | ThoughtSpot: 26.5.0.cl
410
+ * @default true
410
411
  * @example
411
412
  * ```js
412
413
  * // Replace <EmbedComponent> with embed component name. For example, AppEmbed or LiveboardEmbed
@@ -419,10 +420,12 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
419
420
  isContinuousLiveboardPDFEnabled?: boolean;
420
421
  /**
421
422
  * This flag is used to enable/disable the XLSX/CSV download option for Liveboards
423
+ * This feature is GA from SDK version 1.51.0 and ThoughtSpot version 26.6.0.cl.
422
424
  *
423
425
  * Supported embed types: `AppEmbed`, `LiveboardEmbed`
424
426
  * @type {boolean}
425
427
  * @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
428
+ * @default true
426
429
  * @example
427
430
  * ```js
428
431
  * // Replace <EmbedComponent> with embed component name. For example, AppEmbed or LiveboardEmbed
@@ -435,10 +438,12 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
435
438
  isLiveboardXLSXCSVDownloadEnabled?: boolean;
436
439
  /**
437
440
  * This flag is used to enable/disable the granular XLSX/CSV schedules feature
441
+ * This feature is GA from SDK version 1.51.0 and ThoughtSpot version 26.6.0.cl.
438
442
  *
439
443
  * Supported embed types: `AppEmbed`, `LiveboardEmbed`
440
444
  * @type {boolean}
441
445
  * @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
446
+ * @default true
442
447
  * @example
443
448
  * ```js
444
449
  * // Replace <EmbedComponent> with embed component name. For example, AppEmbed or LiveboardEmbed
@@ -529,6 +534,21 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
529
534
  * ```
530
535
  */
531
536
  updatedSpotterChatPrompt?: boolean;
537
+ /**
538
+ * showSpotterRadiance : Controls the radiance on the Spotter page.
539
+ *
540
+ * Supported embed types: `LiveboardEmbed`
541
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
542
+ * @default false
543
+ * @example
544
+ * ```js
545
+ * const embed = new LiveboardEmbed('#tsEmbed', {
546
+ * ... //other embed view config
547
+ * showSpotterRadiance : true,
548
+ * })
549
+ * ```
550
+ */
551
+ showSpotterRadiance?: boolean;
532
552
  /**
533
553
  * Enables the stop answer generation button in the Spotter embed UI,
534
554
  * allowing users to interrupt an ongoing answer generation.
@@ -580,6 +600,12 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
580
600
  * { label: 'Tip', text: 'try asking about revenue by region' },
581
601
  * { label: 'Tip', text: 'use natural language' },
582
602
  * ],
603
+ * // liveboardBrandName, spotterBrandName, insightTileBrandName, insightTileViewPlanLabel and insightTileLoaderText require SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
604
+ * liveboardBrandName: 'Reports',
605
+ * spotterBrandName: 'Analyst',
606
+ * insightTileBrandName: 'Insight card',
607
+ * insightTileViewPlanLabel: 'View plan',
608
+ * insightTileLoaderText: 'Generating insight',
583
609
  * },
584
610
  * })
585
611
  * ```
@@ -598,6 +624,21 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
598
624
  * ```
599
625
  */
600
626
  enableLiveboardDataCache?: boolean;
627
+ /**
628
+ * updatedSpotterExperience : Controls the updated Spotter experience.
629
+ *
630
+ * Supported embed types: `LiveboardEmbed`
631
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
632
+ * @default false
633
+ * @example
634
+ * ```js
635
+ * const embed = new LiveboardEmbed('#tsEmbed', {
636
+ * ... //other embed view config
637
+ * updatedSpotterExperience : true,
638
+ * })
639
+ * ```
640
+ */
641
+ updatedSpotterExperience?: boolean;
601
642
  }
602
643
 
603
644
  /**
@@ -673,34 +714,37 @@ export class LiveboardEmbed extends V1Embed {
673
714
  showLiveboardDescription,
674
715
  showLiveboardTitle,
675
716
  isLiveboardHeaderSticky = true,
676
- isLiveboardCompactHeaderEnabled = false,
717
+ isLiveboardCompactHeaderEnabled,
677
718
  showLiveboardVerifiedBadge = true,
678
719
  showLiveboardReverifyBanner = true,
679
- hideIrrelevantChipsInLiveboardTabs = false,
720
+ hideIrrelevantChipsInLiveboardTabs,
680
721
  showMaskedFilterChip = false,
681
- isLiveboardMasterpiecesEnabled = false,
722
+ isLiveboardMasterpiecesEnabled,
682
723
  newChartsLibrary,
683
- isEnhancedFilterInteractivityEnabled = false,
724
+ isEnhancedFilterInteractivityEnabled,
684
725
  enableAskSage,
685
726
  enable2ColumnLayout,
686
727
  dataPanelV2 = true,
728
+ updatedSpotterExperience,
687
729
  enableCustomColumnGroups = false,
688
730
  oAuthPollingInterval,
689
731
  isForceRedirect,
690
732
  dataSourceId,
691
- coverAndFilterOptionInPDF = false,
733
+ coverAndFilterOptionInPDF,
692
734
  isLiveboardStylingAndGroupingEnabled,
693
735
  isPNGInScheduledEmailsEnabled = false,
694
- isLiveboardXLSXCSVDownloadEnabled = false,
695
- isGranularXLSXCSVSchedulesEnabled = false,
736
+ isLiveboardXLSXCSVDownloadEnabled,
737
+ isGranularXLSXCSVSchedulesEnabled,
696
738
  showSpotterLimitations,
697
739
  isCentralizedLiveboardFilterUXEnabled = false,
740
+ isScopedLiveboardFilteringEnabled,
698
741
  isLinkParametersEnabled,
699
742
  updatedSpotterChatPrompt,
743
+ showSpotterRadiance,
700
744
  enableStopAnswerGenerationEmbed,
701
745
  spotterChatConfig,
702
746
  isThisPeriodInDateFiltersEnabled,
703
- isContinuousLiveboardPDFEnabled = false,
747
+ isContinuousLiveboardPDFEnabled,
704
748
  enableLiveboardDataCache,
705
749
  } = this.viewConfig;
706
750
 
@@ -726,6 +770,9 @@ export class LiveboardEmbed extends V1Embed {
726
770
  if (!isUndefined(updatedSpotterChatPrompt)) {
727
771
  params[Param.UpdatedSpotterChatPrompt] = !!updatedSpotterChatPrompt;
728
772
  }
773
+ if (!isUndefined(showSpotterRadiance)) {
774
+ params[Param.ShowSpotterRadiance] = !!showSpotterRadiance;
775
+ }
729
776
  if (!isUndefined(enableStopAnswerGenerationEmbed)) {
730
777
  params[Param.EnableStopAnswerGenerationEmbed] = !!enableStopAnswerGenerationEmbed;
731
778
  }
@@ -790,6 +837,10 @@ export class LiveboardEmbed extends V1Embed {
790
837
  params[Param.ShowSpotterLimitations] = showSpotterLimitations;
791
838
  }
792
839
 
840
+ if (!isUndefined(updatedSpotterExperience)) {
841
+ params[Param.UpdatedSpotterExperience] = !!updatedSpotterExperience;
842
+ }
843
+
793
844
  // Handle spotterChatConfig params
794
845
  if (spotterChatConfig) {
795
846
  const {
@@ -823,6 +874,12 @@ export class LiveboardEmbed extends V1Embed {
823
874
  ] = isCentralizedLiveboardFilterUXEnabled;
824
875
  }
825
876
 
877
+ if (isScopedLiveboardFilteringEnabled !== undefined) {
878
+ params[
879
+ Param.isScopedLiveboardFilteringEnabled
880
+ ] = isScopedLiveboardFilteringEnabled;
881
+ }
882
+
826
883
  if (isThisPeriodInDateFiltersEnabled !== undefined) {
827
884
  params[Param.IsThisPeriodInDateFiltersEnabled] = isThisPeriodInDateFiltersEnabled;
828
885
  }
@@ -840,16 +897,27 @@ export class LiveboardEmbed extends V1Embed {
840
897
  }
841
898
 
842
899
  params[Param.LiveboardHeaderSticky] = isLiveboardHeaderSticky;
843
- params[Param.LiveboardHeaderV2] = isLiveboardCompactHeaderEnabled;
900
+ if (!isUndefined(isLiveboardCompactHeaderEnabled)) {
901
+ params[Param.LiveboardHeaderV2] = isLiveboardCompactHeaderEnabled;
902
+ }
844
903
  params[Param.ShowLiveboardVerifiedBadge] = showLiveboardVerifiedBadge;
845
904
  params[Param.ShowLiveboardReverifyBanner] = showLiveboardReverifyBanner;
846
- params[Param.HideIrrelevantFiltersInTab] = hideIrrelevantChipsInLiveboardTabs;
905
+ if (!isUndefined(hideIrrelevantChipsInLiveboardTabs)) {
906
+ params[Param.HideIrrelevantFiltersInTab] = hideIrrelevantChipsInLiveboardTabs;
907
+ }
847
908
  params[Param.ShowMaskedFilterChip] = showMaskedFilterChip;
848
- params[Param.IsLiveboardMasterpiecesEnabled] = isLiveboardMasterpiecesEnabled;
849
- params[Param.IsEnhancedFilterInteractivityEnabled] = isEnhancedFilterInteractivityEnabled;
909
+ if (!isUndefined(isLiveboardMasterpiecesEnabled)) {
910
+ params[Param.IsLiveboardMasterpiecesEnabled] = isLiveboardMasterpiecesEnabled;
911
+ }
912
+ if (!isUndefined(isEnhancedFilterInteractivityEnabled)) {
913
+ params[Param.IsEnhancedFilterInteractivityEnabled] =
914
+ isEnhancedFilterInteractivityEnabled;
915
+ }
850
916
  params[Param.DataPanelV2Enabled] = dataPanelV2;
851
917
  params[Param.EnableCustomColumnGroups] = enableCustomColumnGroups;
852
- params[Param.CoverAndFilterOptionInPDF] = coverAndFilterOptionInPDF;
918
+ if (!isUndefined(coverAndFilterOptionInPDF)) {
919
+ params[Param.CoverAndFilterOptionInPDF] = coverAndFilterOptionInPDF;
920
+ }
853
921
 
854
922
  const queryParams = getQueryParamString(params, true);
855
923
 
@@ -1,4 +1,8 @@
1
- import { resolveEnablePastConversationsSidebar, buildSpotterSidebarAppInitData } from './spotter-utils';
1
+ import {
2
+ resolveEnablePastConversationsSidebar,
3
+ buildSpotterSidebarAppInitData,
4
+ buildSpotterShareConversationAppInitData,
5
+ } from './spotter-utils';
2
6
  import { ErrorDetailsTypes, EmbedErrorCodes } from '../types';
3
7
  import { ERROR_MESSAGE } from '../errors';
4
8
 
@@ -36,6 +40,22 @@ describe('buildSpotterSidebarAppInitData', () => {
36
40
  });
37
41
  });
38
42
 
43
+ it('forwards a nested spotterChatPinConfig object through untouched', () => {
44
+ const spotterChatPinConfig = {
45
+ enabled: true,
46
+ pinLabel: 'Pin to top',
47
+ unpinLabel: 'Unpin',
48
+ };
49
+ const result = buildSpotterSidebarAppInitData(base, {
50
+ spotterSidebarConfig: {
51
+ enablePastConversationsSidebar: true,
52
+ spotterChatPinConfig,
53
+ },
54
+ }, noopError);
55
+ expect(result.embedParams?.spotterSidebarConfig?.spotterChatPinConfig)
56
+ .toEqual(spotterChatPinConfig);
57
+ });
58
+
39
59
  it('promotes standalone flag into spotterSidebarConfig.enablePastConversationsSidebar', () => {
40
60
  const result = buildSpotterSidebarAppInitData(base, { enablePastConversationsSidebar: true }, noopError);
41
61
  expect(result.embedParams?.spotterSidebarConfig?.enablePastConversationsSidebar).toBe(true);
@@ -106,3 +126,50 @@ describe('buildSpotterSidebarAppInitData', () => {
106
126
  expect(result.embedParams?.spotterSidebarConfig?.enablePastConversationsSidebar).toBe(true);
107
127
  });
108
128
  });
129
+
130
+ describe('buildSpotterShareConversationAppInitData', () => {
131
+ const base = { type: 'APP_INIT' } as any;
132
+
133
+ it('returns base unchanged when no spotterShareConversationConfig', () => {
134
+ const result = buildSpotterShareConversationAppInitData(base, {});
135
+ expect(result).toBe(base);
136
+ });
137
+
138
+ it('nests spotterShareConversationConfig under embedParams', () => {
139
+ const result = buildSpotterShareConversationAppInitData(base, {
140
+ spotterShareConversationConfig: { enableShareConversation: true },
141
+ });
142
+ expect(result.embedParams?.spotterShareConversationConfig).toEqual({
143
+ enableShareConversation: true,
144
+ });
145
+ });
146
+
147
+ it('passes label override fields through untouched', () => {
148
+ const spotterShareConversationConfig = {
149
+ enableShareConversation: true,
150
+ spotterShareLabel: 'Share',
151
+ spotterShareModalTitle: 'Share conversation',
152
+ spotterShareConfirmLabel: 'Share',
153
+ spotterShareCancelLabel: 'Cancel',
154
+ spotterShareAddUsersLabel: 'Add users or groups',
155
+ spotterShareEmptyTitle: 'No users added yet',
156
+ spotterShareEmptySubtitle: 'Not shared with any user',
157
+ spotterShareIncludeNewMessagesLabel: 'Include new messages',
158
+ spotterShareUpToCurrentLabel: 'Share up to current moment',
159
+ spotterShareStaleInfoLabel: 'This snapshot may be stale',
160
+ };
161
+ const result = buildSpotterShareConversationAppInitData(base, {
162
+ spotterShareConversationConfig,
163
+ });
164
+ expect(result.embedParams?.spotterShareConversationConfig).toEqual(spotterShareConversationConfig);
165
+ });
166
+
167
+ it('preserves existing embedParams when nesting the share config', () => {
168
+ const withParams = { type: 'APP_INIT', embedParams: { existing: 'keep' } } as any;
169
+ const result = buildSpotterShareConversationAppInitData(withParams, {
170
+ spotterShareConversationConfig: { enableShareConversation: true },
171
+ });
172
+ expect(result.embedParams?.existing).toBe('keep');
173
+ expect(result.embedParams?.spotterShareConversationConfig?.enableShareConversation).toBe(true);
174
+ });
175
+ });
@@ -1,7 +1,7 @@
1
1
  import { DefaultAppInitData, ErrorDetailsTypes, EmbedErrorCodes } from '../types';
2
2
  import { validateHttpUrl } from '../utils';
3
3
  import { ERROR_MESSAGE } from '../errors';
4
- import type { SpotterSidebarViewConfig } from './conversation';
4
+ import type { SpotterSidebarViewConfig, SpotterShareConversationConfig } from './conversation';
5
5
  import type { VisualizationOverrides } from '../types';
6
6
 
7
7
  /**
@@ -79,3 +79,18 @@ export function buildSpotterSidebarAppInitData<T extends DefaultAppInitData>(
79
79
  },
80
80
  };
81
81
  }
82
+
83
+ export function buildSpotterShareConversationAppInitData<T extends DefaultAppInitData>(
84
+ initData: T,
85
+ viewConfig: { spotterShareConversationConfig?: SpotterShareConversationConfig },
86
+ ): T & { embedParams?: { spotterShareConversationConfig?: SpotterShareConversationConfig } } {
87
+ const { spotterShareConversationConfig } = viewConfig;
88
+ if (!spotterShareConversationConfig) return initData;
89
+ return {
90
+ ...initData,
91
+ embedParams: {
92
+ ...((initData as T & { embedParams?: Record<string, unknown> }).embedParams || {}),
93
+ spotterShareConversationConfig,
94
+ },
95
+ };
96
+ }
@@ -20,6 +20,23 @@ describe('buildSpotterVizAppInitData', () => {
20
20
  expect(result.embedParams?.spotterVizConfig?.brandHeadline).toBe("Hi, there! I'm");
21
21
  });
22
22
 
23
+ it('passes liveboardBrandName, spotterBrandName, insightTileBrandName, insightTileViewPlanLabel and insightTileLoaderText through spotterVizConfig', () => {
24
+ const spotterViz = {
25
+ brandName: 'MyBrand',
26
+ liveboardBrandName: 'Reports',
27
+ spotterBrandName: 'Analyst',
28
+ insightTileBrandName: 'Insight card',
29
+ insightTileViewPlanLabel: 'View plan',
30
+ insightTileLoaderText: 'Generating insight',
31
+ };
32
+ const result = buildSpotterVizAppInitData(base, { spotterViz });
33
+ expect(result.embedParams?.spotterVizConfig?.liveboardBrandName).toBe('Reports');
34
+ expect(result.embedParams?.spotterVizConfig?.spotterBrandName).toBe('Analyst');
35
+ expect(result.embedParams?.spotterVizConfig?.insightTileBrandName).toBe('Insight card');
36
+ expect(result.embedParams?.spotterVizConfig?.insightTileViewPlanLabel).toBe('View plan');
37
+ expect(result.embedParams?.spotterVizConfig?.insightTileLoaderText).toBe('Generating insight');
38
+ });
39
+
23
40
  it('preserves existing embedParams when adding spotterVizConfig', () => {
24
41
  const existing = { ...base, embedParams: { spotterSidebarConfig: { enablePastConversationsSidebar: true } } };
25
42
  const spotterViz = { brandName: 'MyBrand' };
@@ -38,6 +38,12 @@ export interface SpotterVizStarterPrompt {
38
38
  * { label: 'Tip', text: 'try asking about revenue by region' },
39
39
  * { label: 'Tip', text: 'use natural language' },
40
40
  * ],
41
+ * // liveboardBrandName, spotterBrandName, insightTileBrandName, insightTileViewPlanLabel and insightTileLoaderText require SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
42
+ * liveboardBrandName: 'Reports',
43
+ * spotterBrandName: 'Analyst',
44
+ * insightTileBrandName: 'Insight card',
45
+ * insightTileViewPlanLabel: 'View plan',
46
+ * insightTileLoaderText: 'Generating insight',
41
47
  * },
42
48
  * })
43
49
  * ```
@@ -94,6 +100,34 @@ export interface SpotterVizConfig {
94
100
  * @version SDK: 1.51.0 | ThoughtSpot Cloud: 26.8.0.cl
95
101
  */
96
102
  loaderTips?: SpotterVizLoaderTip[];
103
+ /**
104
+ * Custom term used to replace "Liveboard" in the agent's responses.
105
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
106
+ * @default ''
107
+ */
108
+ liveboardBrandName?: string;
109
+ /**
110
+ * Custom term used to replace "Spotter" in the agent's responses.
111
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
112
+ * @default ''
113
+ */
114
+ spotterBrandName?: string;
115
+ /**
116
+ * Custom term used to replace "Insight tile" in the UI and in the agent's responses.
117
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
118
+ * @default ''
119
+ */
120
+ insightTileBrandName?: string;
121
+ /**
122
+ * Custom term used to replace "View plan" in the insight tile menu.
123
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
124
+ */
125
+ insightTileViewPlanLabel?: string;
126
+ /**
127
+ * Custom loader text shown on the insight tile.
128
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
129
+ */
130
+ insightTileLoaderText?: string;
97
131
  }
98
132
 
99
133
  /**
@@ -1409,6 +1409,40 @@ describe('Unit test case for ts embed', () => {
1409
1409
  const { mockGetPreauthInfo } = await setup(true, 123);
1410
1410
  expect(mockGetPreauthInfo).toHaveBeenCalledTimes(0);
1411
1411
  });
1412
+
1413
+ test('should NOT trigger InfoSuccess when getPreauthInfo resolves with no .info field', async () => {
1414
+ jest.spyOn(window, 'addEventListener').mockImplementationOnce(
1415
+ (event, handler) => {
1416
+ (handler as EventListener)({
1417
+ data: { type: 'xyz' },
1418
+ ports: [3000],
1419
+ source: null,
1420
+ } as any);
1421
+ },
1422
+ );
1423
+ mockProcessTrigger.mockResolvedValueOnce({ session: 'test' });
1424
+ jest.spyOn(authService, 'fetchPreauthInfoService').mockResolvedValueOnce({
1425
+ ok: true,
1426
+ headers: new Headers({ 'content-type': 'application/json' }),
1427
+ json: async () => ({}), // no .info field
1428
+ } as any);
1429
+ const iFrame: any = document.createElement('div');
1430
+ jest.spyOn(baseInstance, 'getAuthPromise').mockResolvedValueOnce(true as any);
1431
+ const tsEmbed = new SearchEmbed(getRootEl(), {});
1432
+ iFrame.contentWindow = { postMessage: jest.fn() };
1433
+ jest.spyOn(iFrame, 'addEventListener').mockImplementationOnce(
1434
+ (event, handler) => { (handler as EventListener)({} as Event); },
1435
+ );
1436
+ jest.spyOn(document, 'createElement').mockReturnValueOnce(iFrame);
1437
+ await tsEmbed.render();
1438
+
1439
+ await executeAfterWait(() => {
1440
+ const infoSuccessCall = mockProcessTrigger.mock.calls.find(
1441
+ (call) => call[1] === HostEvent.InfoSuccess,
1442
+ );
1443
+ expect(infoSuccessCall).toBeUndefined();
1444
+ });
1445
+ });
1412
1446
  });
1413
1447
 
1414
1448
  describe('Preauth Cache for FullAppEmbed with PrimaryNavBar', () => {
@@ -2281,6 +2315,46 @@ describe('Unit test case for ts embed', () => {
2281
2315
  });
2282
2316
  });
2283
2317
 
2318
+ it('Sets the overrideHistoryState param', async () => {
2319
+ const appEmbed = new AppEmbed(getRootEl(), {
2320
+ frameParams: {
2321
+ width: '100%',
2322
+ height: '100%',
2323
+ },
2324
+ overrideHistoryState: true,
2325
+ });
2326
+ await appEmbed.render();
2327
+ expectUrlToHaveParamsWithValues(getIFrameSrc(), {
2328
+ overrideHistoryState: true,
2329
+ });
2330
+ });
2331
+
2332
+ it('Sets the overrideHistoryState param to false', async () => {
2333
+ const appEmbed = new AppEmbed(getRootEl(), {
2334
+ frameParams: {
2335
+ width: '100%',
2336
+ height: '100%',
2337
+ },
2338
+ overrideHistoryState: false,
2339
+ });
2340
+ await appEmbed.render();
2341
+ expectUrlToHaveParamsWithValues(getIFrameSrc(), {
2342
+ overrideHistoryState: false,
2343
+ });
2344
+ });
2345
+
2346
+ it('Should not add overrideHistoryState param when it is undefined', async () => {
2347
+ const appEmbed = new AppEmbed(getRootEl(), {
2348
+ frameParams: {
2349
+ width: '100%',
2350
+ height: '100%',
2351
+ },
2352
+ });
2353
+ await appEmbed.render();
2354
+ const url = getIFrameSrc();
2355
+ expect(url).not.toContain('overrideHistoryState');
2356
+ });
2357
+
2284
2358
  it('Should not add contextMenuEnabledOnWhichClick flag to the iframe src when it is not passed', async () => {
2285
2359
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
2286
2360
  ...defaultViewConfig,
@@ -4570,6 +4644,28 @@ describe('Trigger method edge cases', () => {
4570
4644
  expect(result).toBeNull();
4571
4645
  });
4572
4646
  });
4647
+
4648
+ test('isValidationError catch: handleError called with embedErrorDetails and error is rethrown', async () => {
4649
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
4650
+ const handleErrorSpy = jest.spyOn(searchEmbed as any, 'handleError').mockImplementation(() => {});
4651
+ await searchEmbed.render();
4652
+
4653
+ // First processTrigger call is getAvailableUIPassthroughKeys for DrillDown
4654
+ mockProcessTrigger.mockResolvedValueOnce([
4655
+ { value: { keys: Object.values(UIPassthroughEvent) } },
4656
+ ]);
4657
+
4658
+ // DrillDown with no points → throwDrillDownValidationError → isValidationError=true
4659
+ await expect(
4660
+ searchEmbed.trigger(HostEvent.DrillDown, {} as any),
4661
+ ).rejects.toThrow('DrillDown requires a valid points object');
4662
+
4663
+ expect(handleErrorSpy).toHaveBeenCalledWith(
4664
+ expect.objectContaining({
4665
+ data: expect.objectContaining({ code: EmbedErrorCodes.HOST_EVENT_VALIDATION }),
4666
+ }),
4667
+ );
4668
+ });
4573
4669
  });
4574
4670
 
4575
4671
  describe('PreRender replaceExistingPreRender scenarios', () => {
@@ -4580,6 +4676,10 @@ describe('PreRender replaceExistingPreRender scenarios', () => {
4580
4676
  });
4581
4677
  });
4582
4678
 
4679
+ beforeEach(() => {
4680
+ document.body.innerHTML = getDocumentBody();
4681
+ });
4682
+
4583
4683
  afterEach(() => {
4584
4684
  const rootEle = document.getElementById('myRoot');
4585
4685
  rootEle?.remove();
@@ -4725,6 +4825,52 @@ describe('Fullscreen change handler behavior', () => {
4725
4825
  );
4726
4826
  });
4727
4827
  });
4828
+
4829
+ test('disableFullscreenPresentation undefined defaults to true — no fullscreenchange listener registered', () => {
4830
+ init({
4831
+ thoughtSpotHost: 'tshost',
4832
+ authType: AuthType.None,
4833
+ // disableFullscreenPresentation not set → defaults to true via ?? true
4834
+ });
4835
+
4836
+ const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
4837
+ const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
4838
+
4839
+ embed['setupFullscreenChangeHandler']();
4840
+
4841
+ expect(addEventListenerSpy).not.toHaveBeenCalledWith('fullscreenchange', expect.any(Function));
4842
+
4843
+ addEventListenerSpy.mockRestore();
4844
+ // Restore for other tests in this describe
4845
+ init({ thoughtSpotHost: 'tshost', authType: AuthType.None, disableFullscreenPresentation: false });
4846
+ });
4847
+
4848
+ test('fullscreenchange fires but iFrame.contentWindow is null — trigger NOT called, debug log emitted', () => {
4849
+ const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
4850
+ // Give the embed a fake iFrame with null contentWindow
4851
+ (embed as any).iFrame = { contentWindow: null };
4852
+
4853
+ const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
4854
+ const loggerDebugSpy = jest.spyOn(logger, 'debug').mockImplementation(() => {});
4855
+ const triggerSpy = jest.spyOn(embed, 'trigger' as any).mockImplementation(() => Promise.resolve(null));
4856
+
4857
+ embed['setupFullscreenChangeHandler']();
4858
+
4859
+ // Capture the registered handler directly instead of dispatching to document
4860
+ const fullscreenCall = addEventListenerSpy.mock.calls.find((c) => c[0] === 'fullscreenchange');
4861
+ expect(fullscreenCall).toBeTruthy();
4862
+ const handler = fullscreenCall[1] as EventListener;
4863
+
4864
+ Object.defineProperty(document, 'fullscreenElement', { value: null, writable: true, configurable: true });
4865
+ handler(new Event('fullscreenchange'));
4866
+
4867
+ expect(triggerSpy).not.toHaveBeenCalled();
4868
+ expect(loggerDebugSpy).toHaveBeenCalledWith(expect.stringContaining('Skipping ExitPresentMode'));
4869
+
4870
+ addEventListenerSpy.mockRestore();
4871
+ loggerDebugSpy.mockRestore();
4872
+ triggerSpy.mockRestore();
4873
+ });
4728
4874
  });
4729
4875
 
4730
4876
  describe('ShowPreRender with UpdateEmbedParams', () => {
@@ -5315,5 +5461,45 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
5315
5461
 
5316
5462
  embed.destroy();
5317
5463
  });
5464
+
5465
+ // showPreRender located the stale placeholder with a subtree-wide
5466
+ // querySelector but removed it with hostElement.removeChild(), which
5467
+ // only accepts direct children. With fullHeight the placeholder can be
5468
+ // nested deeper than a direct child, so removeChild threw
5469
+ // "NotFoundError: Failed to execute 'removeChild' on 'Node'".
5470
+ it('showPreRender removes a placeholder nested below a direct child without throwing', async () => {
5471
+ createRootEleForEmbed();
5472
+ const embed = new LiveboardEmbed('#tsEmbedDiv', {
5473
+ preRenderId: 'ph-nested-test',
5474
+ liveboardId: 'lb-id',
5475
+ fullHeight: true,
5476
+ } as any);
5477
+ await embed.preRender();
5478
+ await waitFor(
5479
+ () => !!document.querySelector('#tsEmbed-pre-render-child-ph-nested-test'),
5480
+ );
5481
+
5482
+ const hostElement = document.querySelector('#tsEmbedDiv') as HTMLElement;
5483
+ const placeHolderId = 'tsEmbed-pre-render-placeholder-ph-nested-test';
5484
+ // Simulate the fullHeight layout where the placeholder ends up as
5485
+ // a grandchild of the host element rather than a direct child.
5486
+ const intermediateWrapper = document.createElement('div');
5487
+ const staleNestedPlaceholder = document.createElement('div');
5488
+ staleNestedPlaceholder.id = placeHolderId;
5489
+ intermediateWrapper.appendChild(staleNestedPlaceholder);
5490
+ hostElement.appendChild(intermediateWrapper);
5491
+
5492
+ expect(hostElement.querySelector(`#${placeHolderId}`)).toBe(staleNestedPlaceholder);
5493
+ // Before the fix this threw NotFoundError.
5494
+ await expect(embed.showPreRender()).resolves.toBeDefined();
5495
+ // The stale nested placeholder is gone; the fresh one is a direct child.
5496
+ expect(staleNestedPlaceholder.isConnected).toBe(false);
5497
+ const currentPlaceholder = (
5498
+ embed as any
5499
+ ).getPreRenderPlaceHolderElement() as HTMLDivElement;
5500
+ expect(currentPlaceholder.parentElement).toBe(hostElement);
5501
+
5502
+ embed.destroy();
5503
+ });
5318
5504
  });
5319
5505
  });