@thoughtspot/visual-embed-sdk 1.52.2-beta.2 → 1.53.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 (237) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/css-variables.d.ts +373 -5
  3. package/cjs/src/css-variables.d.ts.map +1 -1
  4. package/cjs/src/embed/app.d.ts +14 -0
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +6 -3
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +28 -0
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/auto-frame-renderer.d.ts.map +1 -1
  11. package/cjs/src/embed/auto-frame-renderer.js +244 -4
  12. package/cjs/src/embed/auto-frame-renderer.js.map +1 -1
  13. package/cjs/src/embed/auto-frame-renderer.spec.js +389 -0
  14. package/cjs/src/embed/auto-frame-renderer.spec.js.map +1 -1
  15. package/cjs/src/embed/bodyless-conversation.js +1 -1
  16. package/cjs/src/embed/bodyless-conversation.js.map +1 -1
  17. package/cjs/src/embed/conversation.d.ts +15 -0
  18. package/cjs/src/embed/conversation.d.ts.map +1 -1
  19. package/cjs/src/embed/conversation.js +7 -3
  20. package/cjs/src/embed/conversation.js.map +1 -1
  21. package/cjs/src/embed/conversation.spec.js +66 -0
  22. package/cjs/src/embed/conversation.spec.js.map +1 -1
  23. package/cjs/src/embed/liveboard-override-utils.d.ts +59 -0
  24. package/cjs/src/embed/liveboard-override-utils.d.ts.map +1 -0
  25. package/cjs/src/embed/liveboard-override-utils.js +19 -0
  26. package/cjs/src/embed/liveboard-override-utils.js.map +1 -0
  27. package/cjs/src/embed/liveboard-override-utils.spec.d.ts +2 -0
  28. package/cjs/src/embed/liveboard-override-utils.spec.d.ts.map +1 -0
  29. package/cjs/src/embed/liveboard-override-utils.spec.js +34 -0
  30. package/cjs/src/embed/liveboard-override-utils.spec.js.map +1 -0
  31. package/cjs/src/embed/liveboard.d.ts +58 -13
  32. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  33. package/cjs/src/embed/liveboard.js +11 -34
  34. package/cjs/src/embed/liveboard.js.map +1 -1
  35. package/cjs/src/embed/liveboard.spec.js +104 -79
  36. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  37. package/cjs/src/embed/search-bar.js +1 -1
  38. package/cjs/src/embed/search-bar.js.map +1 -1
  39. package/cjs/src/embed/search.js +1 -1
  40. package/cjs/src/embed/search.js.map +1 -1
  41. package/cjs/src/embed/search.spec.js +20 -0
  42. package/cjs/src/embed/search.spec.js.map +1 -1
  43. package/cjs/src/embed/spotter-utils.d.ts +11 -0
  44. package/cjs/src/embed/spotter-utils.d.ts.map +1 -1
  45. package/cjs/src/embed/spotter-utils.js +13 -1
  46. package/cjs/src/embed/spotter-utils.js.map +1 -1
  47. package/cjs/src/embed/spotter-viz-utils.d.ts +15 -0
  48. package/cjs/src/embed/spotter-viz-utils.d.ts.map +1 -1
  49. package/cjs/src/embed/spotter-viz-utils.js.map +1 -1
  50. package/cjs/src/embed/spotter-viz-utils.spec.js +11 -0
  51. package/cjs/src/embed/spotter-viz-utils.spec.js.map +1 -1
  52. package/cjs/src/embed/ts-embed.d.ts +27 -34
  53. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  54. package/cjs/src/embed/ts-embed.js +224 -102
  55. package/cjs/src/embed/ts-embed.js.map +1 -1
  56. package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
  57. package/cjs/src/embed/ts-embed.spec.js +543 -166
  58. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  59. package/cjs/src/index.d.ts +4 -2
  60. package/cjs/src/index.d.ts.map +1 -1
  61. package/cjs/src/index.js +4 -2
  62. package/cjs/src/index.js.map +1 -1
  63. package/cjs/src/mixpanel-service.d.ts +1 -0
  64. package/cjs/src/mixpanel-service.d.ts.map +1 -1
  65. package/cjs/src/mixpanel-service.js +1 -0
  66. package/cjs/src/mixpanel-service.js.map +1 -1
  67. package/cjs/src/react/all-types-export.d.ts +1 -1
  68. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  69. package/cjs/src/react/all-types-export.js +2 -1
  70. package/cjs/src/react/all-types-export.js.map +1 -1
  71. package/cjs/src/types.d.ts +182 -2
  72. package/cjs/src/types.d.ts.map +1 -1
  73. package/cjs/src/types.js +109 -0
  74. package/cjs/src/types.js.map +1 -1
  75. package/cjs/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
  76. package/cjs/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  77. package/cjs/src/utils/graphql/answerService/answer-queries.js +8 -1
  78. package/cjs/src/utils/graphql/answerService/answer-queries.js.map +1 -1
  79. package/cjs/src/utils/graphql/answerService/answerService.d.ts +28 -4
  80. package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  81. package/cjs/src/utils/graphql/answerService/answerService.js +39 -4
  82. package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
  83. package/cjs/src/utils/graphql/answerService/answerService.spec.js +124 -0
  84. package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  85. package/dist/{index-CnHREfvN.js → index-CyDR8j_0.js} +1 -1
  86. package/dist/src/css-variables.d.ts +373 -5
  87. package/dist/src/css-variables.d.ts.map +1 -1
  88. package/dist/src/embed/app.d.ts +14 -0
  89. package/dist/src/embed/app.d.ts.map +1 -1
  90. package/dist/src/embed/auto-frame-renderer.d.ts.map +1 -1
  91. package/dist/src/embed/conversation.d.ts +15 -0
  92. package/dist/src/embed/conversation.d.ts.map +1 -1
  93. package/dist/src/embed/liveboard-override-utils.d.ts +59 -0
  94. package/dist/src/embed/liveboard-override-utils.d.ts.map +1 -0
  95. package/dist/src/embed/liveboard-override-utils.spec.d.ts +2 -0
  96. package/dist/src/embed/liveboard-override-utils.spec.d.ts.map +1 -0
  97. package/dist/src/embed/liveboard.d.ts +58 -13
  98. package/dist/src/embed/liveboard.d.ts.map +1 -1
  99. package/dist/src/embed/spotter-utils.d.ts +11 -0
  100. package/dist/src/embed/spotter-utils.d.ts.map +1 -1
  101. package/dist/src/embed/spotter-viz-utils.d.ts +15 -0
  102. package/dist/src/embed/spotter-viz-utils.d.ts.map +1 -1
  103. package/dist/src/embed/ts-embed.d.ts +27 -34
  104. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  105. package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
  106. package/dist/src/index.d.ts +4 -2
  107. package/dist/src/index.d.ts.map +1 -1
  108. package/dist/src/mixpanel-service.d.ts +1 -0
  109. package/dist/src/mixpanel-service.d.ts.map +1 -1
  110. package/dist/src/react/all-types-export.d.ts +1 -1
  111. package/dist/src/react/all-types-export.d.ts.map +1 -1
  112. package/dist/src/types.d.ts +182 -2
  113. package/dist/src/types.d.ts.map +1 -1
  114. package/dist/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
  115. package/dist/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  116. package/dist/src/utils/graphql/answerService/answerService.d.ts +28 -4
  117. package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  118. package/dist/tsembed-react.es.js +437 -191
  119. package/dist/tsembed-react.js +436 -190
  120. package/dist/tsembed.es.js +680 -196
  121. package/dist/tsembed.js +678 -194
  122. package/dist/visual-embed-sdk-react-full.d.ts +702 -56
  123. package/dist/visual-embed-sdk-react.d.ts +697 -56
  124. package/dist/visual-embed-sdk.d.ts +744 -57
  125. package/lib/package.json +1 -1
  126. package/lib/src/css-variables.d.ts +373 -5
  127. package/lib/src/css-variables.d.ts.map +1 -1
  128. package/lib/src/embed/app.d.ts +14 -0
  129. package/lib/src/embed/app.d.ts.map +1 -1
  130. package/lib/src/embed/app.js +7 -4
  131. package/lib/src/embed/app.js.map +1 -1
  132. package/lib/src/embed/app.spec.js +28 -0
  133. package/lib/src/embed/app.spec.js.map +1 -1
  134. package/lib/src/embed/auto-frame-renderer.d.ts.map +1 -1
  135. package/lib/src/embed/auto-frame-renderer.js +244 -4
  136. package/lib/src/embed/auto-frame-renderer.js.map +1 -1
  137. package/lib/src/embed/auto-frame-renderer.spec.js +389 -0
  138. package/lib/src/embed/auto-frame-renderer.spec.js.map +1 -1
  139. package/lib/src/embed/bodyless-conversation.js +1 -1
  140. package/lib/src/embed/bodyless-conversation.js.map +1 -1
  141. package/lib/src/embed/conversation.d.ts +15 -0
  142. package/lib/src/embed/conversation.d.ts.map +1 -1
  143. package/lib/src/embed/conversation.js +8 -4
  144. package/lib/src/embed/conversation.js.map +1 -1
  145. package/lib/src/embed/conversation.spec.js +67 -1
  146. package/lib/src/embed/conversation.spec.js.map +1 -1
  147. package/lib/src/embed/liveboard-override-utils.d.ts +59 -0
  148. package/lib/src/embed/liveboard-override-utils.d.ts.map +1 -0
  149. package/lib/src/embed/liveboard-override-utils.js +15 -0
  150. package/lib/src/embed/liveboard-override-utils.js.map +1 -0
  151. package/lib/src/embed/liveboard-override-utils.spec.d.ts +2 -0
  152. package/lib/src/embed/liveboard-override-utils.spec.d.ts.map +1 -0
  153. package/lib/src/embed/liveboard-override-utils.spec.js +32 -0
  154. package/lib/src/embed/liveboard-override-utils.spec.js.map +1 -0
  155. package/lib/src/embed/liveboard.d.ts +58 -13
  156. package/lib/src/embed/liveboard.d.ts.map +1 -1
  157. package/lib/src/embed/liveboard.js +11 -33
  158. package/lib/src/embed/liveboard.js.map +1 -1
  159. package/lib/src/embed/liveboard.spec.js +104 -79
  160. package/lib/src/embed/liveboard.spec.js.map +1 -1
  161. package/lib/src/embed/search-bar.js +1 -1
  162. package/lib/src/embed/search-bar.js.map +1 -1
  163. package/lib/src/embed/search.js +1 -1
  164. package/lib/src/embed/search.js.map +1 -1
  165. package/lib/src/embed/search.spec.js +20 -0
  166. package/lib/src/embed/search.spec.js.map +1 -1
  167. package/lib/src/embed/spotter-utils.d.ts +11 -0
  168. package/lib/src/embed/spotter-utils.d.ts.map +1 -1
  169. package/lib/src/embed/spotter-utils.js +12 -0
  170. package/lib/src/embed/spotter-utils.js.map +1 -1
  171. package/lib/src/embed/spotter-viz-utils.d.ts +15 -0
  172. package/lib/src/embed/spotter-viz-utils.d.ts.map +1 -1
  173. package/lib/src/embed/spotter-viz-utils.js.map +1 -1
  174. package/lib/src/embed/spotter-viz-utils.spec.js +11 -0
  175. package/lib/src/embed/spotter-viz-utils.spec.js.map +1 -1
  176. package/lib/src/embed/ts-embed.d.ts +27 -34
  177. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  178. package/lib/src/embed/ts-embed.js +224 -102
  179. package/lib/src/embed/ts-embed.js.map +1 -1
  180. package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
  181. package/lib/src/embed/ts-embed.spec.js +544 -167
  182. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  183. package/lib/src/index.d.ts +4 -2
  184. package/lib/src/index.d.ts.map +1 -1
  185. package/lib/src/index.js +3 -2
  186. package/lib/src/index.js.map +1 -1
  187. package/lib/src/mixpanel-service.d.ts +1 -0
  188. package/lib/src/mixpanel-service.d.ts.map +1 -1
  189. package/lib/src/mixpanel-service.js +1 -0
  190. package/lib/src/mixpanel-service.js.map +1 -1
  191. package/lib/src/react/all-types-export.d.ts +1 -1
  192. package/lib/src/react/all-types-export.d.ts.map +1 -1
  193. package/lib/src/react/all-types-export.js +1 -1
  194. package/lib/src/react/all-types-export.js.map +1 -1
  195. package/lib/src/types.d.ts +182 -2
  196. package/lib/src/types.d.ts.map +1 -1
  197. package/lib/src/types.js +109 -0
  198. package/lib/src/types.js.map +1 -1
  199. package/lib/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
  200. package/lib/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  201. package/lib/src/utils/graphql/answerService/answer-queries.js +7 -0
  202. package/lib/src/utils/graphql/answerService/answer-queries.js.map +1 -1
  203. package/lib/src/utils/graphql/answerService/answerService.d.ts +28 -4
  204. package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  205. package/lib/src/utils/graphql/answerService/answerService.js +39 -4
  206. package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
  207. package/lib/src/utils/graphql/answerService/answerService.spec.js +125 -1
  208. package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  209. package/lib/src/visual-embed-sdk.d.ts +744 -57
  210. package/package.json +1 -1
  211. package/src/css-variables.ts +475 -26
  212. package/src/embed/app.spec.ts +32 -0
  213. package/src/embed/app.ts +28 -4
  214. package/src/embed/auto-frame-renderer.spec.ts +464 -0
  215. package/src/embed/auto-frame-renderer.ts +305 -6
  216. package/src/embed/bodyless-conversation.ts +1 -1
  217. package/src/embed/conversation.spec.ts +94 -1
  218. package/src/embed/conversation.ts +28 -3
  219. package/src/embed/liveboard-override-utils.spec.ts +38 -0
  220. package/src/embed/liveboard-override-utils.ts +71 -0
  221. package/src/embed/liveboard.spec.ts +119 -92
  222. package/src/embed/liveboard.ts +56 -40
  223. package/src/embed/search-bar.tsx +1 -1
  224. package/src/embed/search.spec.ts +23 -0
  225. package/src/embed/search.ts +1 -1
  226. package/src/embed/spotter-utils.ts +12 -0
  227. package/src/embed/spotter-viz-utils.spec.ts +11 -0
  228. package/src/embed/spotter-viz-utils.ts +15 -0
  229. package/src/embed/ts-embed.spec.ts +685 -207
  230. package/src/embed/ts-embed.ts +227 -97
  231. package/src/index.ts +16 -1
  232. package/src/mixpanel-service.ts +1 -0
  233. package/src/react/all-types-export.ts +6 -0
  234. package/src/types.ts +186 -5
  235. package/src/utils/graphql/answerService/answer-queries.ts +8 -0
  236. package/src/utils/graphql/answerService/answerService.spec.ts +145 -1
  237. package/src/utils/graphql/answerService/answerService.ts +65 -3
@@ -45,7 +45,7 @@ import {
45
45
  getHostEventsConfig,
46
46
  getValueFromWindow,
47
47
  deserializeParam,
48
- getScrollableAncestors,
48
+ setParamIfDefined,
49
49
  } from '../utils';
50
50
  import { getCustomActions } from '../utils/custom-actions';
51
51
  import {
@@ -116,9 +116,6 @@ const TS_EMBED_ID = '_thoughtspot-embed';
116
116
  */
117
117
  const PRERENDER_CONTAINER_ORIGINAL_POSITION_KEY = 'tsEmbedOriginalPosition';
118
118
  const PRERENDER_WRAPPER_ID_PREFIX = 'tsEmbed-pre-render-wrapper-';
119
- const PRERENDER_PARKED_TRANSFORM = 'translateY(-100%)';
120
- /** The height createPreRenderWrapper() seeds before anything is measured. */
121
- const UNMEASURED_WRAPPER_HEIGHT = '100vh';
122
119
 
123
120
  // The container applies UpdateEmbedParams through React state, so a delivered
124
121
  // post is not the same as the params being in effect.
@@ -129,6 +126,98 @@ const UPDATE_EMBED_PARAMS_SETTLE_MS = 200;
129
126
  // truthy and parses to {}.
130
127
  const NO_RUNTIME_PARAMS = '&';
131
128
 
129
+ /**
130
+ * Params kept on the iframe `src` when `excludeConfigFromURL` is set. The rest
131
+ * are sent in the APP_INIT payload.
132
+ * @internal
133
+ */
134
+ export const BOOTSTRAP_URL_PARAMS: ReadonlySet<string> = new Set<string>([
135
+ // Marks the app as embedded.
136
+ Param.EmbedApp,
137
+ // The host page URL, used to validate the postMessage origin.
138
+ Param.HostAppUrl,
139
+ // The SDK version.
140
+ Param.Version,
141
+ // The authentication type set in init.
142
+ Param.AuthType,
143
+ // Whether the app signs the user in automatically.
144
+ Param.AutoLogin,
145
+ // Stops the app from redirecting to its login page.
146
+ Param.DisableLoginRedirect,
147
+ // Forces the SAML redirect for EmbeddedSSO.
148
+ Param.ForceSAMLAutoRedirect,
149
+ // Set for cookieless trusted authentication.
150
+ Param.cookieless,
151
+ // Lets the app use the pre-fetched auth info.
152
+ Param.preAuthCache,
153
+ // Blocks access to the full app outside the embed.
154
+ Param.blockNonEmbedFullAppAccess,
155
+ // The org to load, which the auth info depends on.
156
+ Param.OverrideOrgId,
157
+ // The host window height when the iframe loads.
158
+ Param.ViewPortHeight,
159
+ // The host window width when the iframe loads.
160
+ Param.ViewPortWidth,
161
+ // The app's client log level.
162
+ Param.ClientLogLevel,
163
+ // Lets the app override the native console.
164
+ Param.OverrideNativeConsole,
165
+ // An extra Pendo tracking key.
166
+ Param.PendoTrackingKey,
167
+ // The locale for number formatting.
168
+ Param.NumberFormatLocale,
169
+ // The locale for date formatting.
170
+ Param.DateFormatLocale,
171
+ // The currency format.
172
+ Param.CurrencyFormat,
173
+ // The UI language.
174
+ Param.Locale,
175
+ // Turns on dark mode.
176
+ Param.IsDarkMode,
177
+ // Turns on the radiant theme that dark mode needs.
178
+ Param.RadiantThemeEnabled,
179
+ // Marks a SearchEmbed or SearchBarEmbed.
180
+ Param.searchEmbed,
181
+ // Marks a LiveboardEmbed.
182
+ Param.livedBoardEmbed,
183
+ // Marks a SpotterAgentEmbed.
184
+ Param.isSpotterAgentEmbed,
185
+ // Marks a SpotterEmbed.
186
+ Param.SpotterEnabled,
187
+ // Marks an AppEmbed.
188
+ Param.IsFullAppEmbed,
189
+ // Legacy flag for the onBeforeGetVizData API intercept.
190
+ Param.IsOnBeforeGetVizDataInterceptEnabled,
191
+ // Lets the host override links in the app.
192
+ Param.LinkOverride,
193
+ // Turns on version 2 of the link overrides.
194
+ Param.EnableLinkOverridesV2,
195
+ // Stops links from opening in a new tab.
196
+ Param.DisableRedirectionLinksInNewTab,
197
+ // Uses replaceState instead of pushState for app navigation.
198
+ Param.OverrideHistoryState,
199
+ // Shows search results as a table.
200
+ Param.ForceTable,
201
+ // The URL of the custom string IDs file.
202
+ Param.StringIDsUrl,
203
+ // The data sources that search opens with.
204
+ Param.DataSources,
205
+ // Exposes translation IDs in the app.
206
+ Param.ExposeTranslationIDs,
207
+ // The URL of the custom icon sprite.
208
+ Param.IconSpriteUrl,
209
+ // The tag that filters the metadata lists in an AppEmbed.
210
+ Param.Tag,
211
+ // Set when a Liveboard embed shows a single visualization (vizId).
212
+ Param.vizEmbed,
213
+ // Whether search opens with the last-selected data sources.
214
+ Param.UseLastSelectedDataSource,
215
+ // The query mode Spotter opens in.
216
+ Param.DefaultQueryMode,
217
+ // The initial search query. Omitted with excludeSearchTokenStringFromURL.
218
+ Param.searchTokenString,
219
+ ]);
220
+
132
221
  /**
133
222
  * The event id map from v2 event names to v1 event id
134
223
  * v1 events are the classic embed events implemented in Blink v1
@@ -165,6 +254,8 @@ export class TsEmbed {
165
254
 
166
255
  protected isAppInitialized = false;
167
256
 
257
+ private initDataParams: Partial<Record<Param, any>> & Record<string, any> = {};
258
+
168
259
  /**
169
260
  * A reference to the iframe within which the ThoughtSpot app
170
261
  * will be rendered.
@@ -234,7 +325,8 @@ export class TsEmbed {
234
325
 
235
326
  private preRenderContainerEl: HTMLElement = document.body;
236
327
 
237
- /** Last height the embedded app reported, once fullHeight has measured one. */
328
+ private containerScrollListener: (() => void) | null = null;
329
+
238
330
  protected hostEventClient: HostEventClient;
239
331
 
240
332
  protected isReadyForRenderPromise;
@@ -585,6 +677,19 @@ export class TsEmbed {
585
677
  return this.getDefaultAppInitData();
586
678
  }
587
679
 
680
+ private withInitDataParams(appInitData: Record<string, any>): Record<string, any> {
681
+ if (isEmpty(this.initDataParams)) {
682
+ return appInitData;
683
+ }
684
+ return {
685
+ ...appInitData,
686
+ embedParams: {
687
+ ...this.initDataParams,
688
+ ...(appInitData.embedParams || {}),
689
+ },
690
+ };
691
+ }
692
+
588
693
  /**
589
694
  * Send Custom style as part of payload of APP_INIT
590
695
  * @param _
@@ -592,7 +697,7 @@ export class TsEmbed {
592
697
  */
593
698
  private appInitCb = async (_: any, responder: any) => {
594
699
  try {
595
- const appInitData = await this.getAppInitData();
700
+ const appInitData = this.withInitDataParams(await this.getAppInitData());
596
701
  this.isAppInitialized = true;
597
702
  responder({
598
703
  type: EmbedEvent.APP_INIT,
@@ -798,6 +903,15 @@ export class TsEmbed {
798
903
  if (this.embedConfig.currencyFormat) {
799
904
  queryParams[Param.CurrencyFormat] = this.embedConfig.currencyFormat;
800
905
  }
906
+ // The view config wins over init, so an embed can opt out of a dark
907
+ // mode set in `init`. `??` and not `||`, so that an explicit `false`
908
+ // overrides an init-level `true`.
909
+ const isDarkMode = this.viewConfig.isDarkMode ?? this.embedConfig.isDarkMode;
910
+ setParamIfDefined(queryParams, Param.IsDarkMode, isDarkMode, true);
911
+ // The app's dark mode lives in its radiant theme, so turn that on too.
912
+ if (isDarkMode) {
913
+ queryParams[Param.RadiantThemeEnabled] = true;
914
+ }
801
915
 
802
916
  const {
803
917
  disabledActions,
@@ -953,7 +1067,7 @@ export class TsEmbed {
953
1067
  }
954
1068
 
955
1069
  protected getEmbedParams() {
956
- const queryParams = this.getEmbedParamsObject();
1070
+ const queryParams = this.getUrlQueryParamsObject();
957
1071
  return getQueryParamString(queryParams);
958
1072
  }
959
1073
 
@@ -962,6 +1076,25 @@ export class TsEmbed {
962
1076
  return params;
963
1077
  }
964
1078
 
1079
+ protected getUrlQueryParamsObject(): Record<any, any> {
1080
+ const queryParams = this.getEmbedParamsObject();
1081
+ if (!this.isConfigExcludedFromUrl()) {
1082
+ this.initDataParams = {};
1083
+ return queryParams;
1084
+ }
1085
+ const urlParams: Record<any, any> = {};
1086
+ const excludedParams: Partial<Record<Param, any>> & Record<string, any> = {};
1087
+ Object.entries(queryParams).forEach(([key, value]) => {
1088
+ if (BOOTSTRAP_URL_PARAMS.has(key)) {
1089
+ urlParams[key] = value;
1090
+ } else {
1091
+ excludedParams[key] = deserializeParam(value);
1092
+ }
1093
+ });
1094
+ this.initDataParams = excludedParams;
1095
+ return urlParams;
1096
+ }
1097
+
965
1098
  protected getRootIframeSrc() {
966
1099
  const query = this.getEmbedParams();
967
1100
  return this.getEmbedBasePath(query);
@@ -1150,7 +1283,7 @@ export class TsEmbed {
1150
1283
  top: '0',
1151
1284
  left: '0',
1152
1285
  width: '100vw',
1153
- height: UNMEASURED_WRAPPER_HEIGHT,
1286
+ height: '100vh',
1154
1287
  };
1155
1288
  setStyleProperties(preRenderWrapper, initialPreRenderWrapperStyle);
1156
1289
 
@@ -1236,26 +1369,10 @@ export class TsEmbed {
1236
1369
  }
1237
1370
 
1238
1371
  /**
1239
- * Resolves the configured preRenderContainer to a live element. A string
1240
- * selector is re-queried on every call so a remounted container (E.g.: React
1241
- * replacing the node) resolves to the fresh element; an element passed
1242
- * directly cannot be re-resolved.
1243
- *
1244
- * With nothing configured the frame goes into the host element's nearest
1245
- * scrolling ancestor, falling back to `document.body`.
1246
- *
1247
- * The wrapper is absolutely positioned, so it follows the page for free —
1248
- * but only while it sits inside whatever scrolls. `document.body` is right
1249
- * only when the document itself is the scroller; an app that scrolls an
1250
- * inner element instead left the frame pinned to the viewport while the page
1251
- * moved under it (SCAL-338563). Being inside the scroller also lets wheel
1252
- * events chain out of the frame into it, which they cannot do from
1253
- * `document.body`.
1254
- *
1255
- * A scrolling ancestor is layout chrome rather than route content, so it
1256
- * outlives the embed in practice; and if it does go, the host element goes
1257
- * with it and this instance is remounting anyway.
1258
- * `reconcilePreRenderContainer` re-runs this on a detached container.
1372
+ * Resolves the configured preRenderContainer to a live element, falling
1373
+ * back to `document.body`. A string selector is re-queried on every call so
1374
+ * a remounted container (E.g.: React replacing the node) resolves to the
1375
+ * fresh element; an element passed directly cannot be re-resolved.
1259
1376
  */
1260
1377
  private resolvePreRenderContainerTarget(): HTMLElement {
1261
1378
  const containerConfig = this.getPreRenderConfig().containerSelector;
@@ -1272,13 +1389,7 @@ export class TsEmbed {
1272
1389
  } else if (containerConfig) {
1273
1390
  container = containerConfig;
1274
1391
  }
1275
- if (container) {
1276
- return container as HTMLElement;
1277
- }
1278
- if (!this.hostElement) {
1279
- return document.body;
1280
- }
1281
- return getScrollableAncestors(this.hostElement)[0] ?? document.body;
1392
+ return (container as HTMLElement) ?? document.body;
1282
1393
  }
1283
1394
 
1284
1395
  private inheritPreRenderContainer(): void {
@@ -1332,9 +1443,8 @@ export class TsEmbed {
1332
1443
  * Re-attaches the wrapper to a live container when the previously resolved
1333
1444
  * one has been detached or no longer holds the wrapper — e.g. the host app
1334
1445
  * remounted a custom preRenderContainer, which would otherwise leave a stale
1335
- * reference and collapse the wrapper. Selectors and the auto-resolved
1336
- * scrolling ancestor are both re-resolved; a container passed as an element
1337
- * is left untouched, as there is nothing to re-query.
1446
+ * reference and collapse the wrapper. Only string selectors can be
1447
+ * re-resolved; a container passed as an element is left untouched.
1338
1448
  */
1339
1449
  private reconcilePreRenderContainer(): void {
1340
1450
  const wrapper = this.preRenderWrapper;
@@ -1353,6 +1463,14 @@ export class TsEmbed {
1353
1463
  if (resolved === stored && stored.contains(wrapper)) {
1354
1464
  return;
1355
1465
  }
1466
+ if (this.containerScrollListener && stored !== resolved) {
1467
+ if (stored !== document.body) {
1468
+ stored.removeEventListener('scroll', this.containerScrollListener);
1469
+ }
1470
+ if (resolved !== document.body) {
1471
+ resolved.addEventListener('scroll', this.containerScrollListener);
1472
+ }
1473
+ }
1356
1474
  this.preRenderContainerEl = resolved;
1357
1475
  this.applyPreRenderContainerPositioning();
1358
1476
  if (wrapper.parentNode !== resolved) {
@@ -1421,11 +1539,10 @@ export class TsEmbed {
1421
1539
  */
1422
1540
  protected setIFrameHeight(height: number | string): void {
1423
1541
  if (this.isPreRendered) {
1424
- const next = getCssDimension(height);
1425
1542
  if (this.insertedDomEl) {
1426
- (this.insertedDomEl as HTMLElement).style.height = next;
1543
+ (this.insertedDomEl as HTMLElement).style.height = getCssDimension(height);
1427
1544
  } else if (this.preRenderWrapper) {
1428
- this.preRenderWrapper.style.height = next;
1545
+ this.preRenderWrapper.style.height = getCssDimension(height);
1429
1546
  }
1430
1547
  } else {
1431
1548
  // normal (non-preRender) mode: size the iframe directly
@@ -1821,6 +1938,12 @@ export class TsEmbed {
1821
1938
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_RENDER_CALLED, {
1822
1939
  embedComponentType: this.viewConfig.embedComponentType,
1823
1940
  });
1941
+ uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_INIT_ACTIONS, {
1942
+ embedComponentType: this.viewConfig.embedComponentType,
1943
+ hiddenActions: this.viewConfig.hiddenActions ?? [],
1944
+ visibleActions: this.viewConfig.visibleActions ?? [],
1945
+ disabledActions: this.viewConfig.disabledActions ?? [],
1946
+ });
1824
1947
  if (!getIsInitCalled()) {
1825
1948
  logger.error(ERROR_MESSAGE.RENDER_CALLED_BEFORE_INIT);
1826
1949
  }
@@ -1990,27 +2113,15 @@ export class TsEmbed {
1990
2113
  }
1991
2114
 
1992
2115
  /**
1993
- * Re-sizes the wrapper when its placeholder changes size.
1994
- *
1995
- * Position deliberately has no equivalent. An absolutely positioned wrapper
1996
- * follows its containing block for free, so a correctly placed frame is the
1997
- * browser's job and costs nothing; repositioning it on scroll would mean a
1998
- * layout read and a style write per frame to compensate for placing it in
1999
- * the wrong box. Size is the one thing the browser will not do for us: the
2000
- * placeholder grows when the embedded app reports a new height, and the
2001
- * wrapper has to be told.
2002
- */
2003
- private observePreRenderSize(): void {
2004
- if (this.getPreRenderConfig().doNotTrackSize || typeof ResizeObserver === 'undefined') {
2005
- return;
2006
- }
2007
- const placeholder = this.getPreRenderPlaceHolderElement();
2008
- if (!placeholder) {
2116
+ * Detaches and clears the container scroll listener, if one is attached.
2117
+ */
2118
+ private removeContainerScrollListener(): void {
2119
+ if (!this.containerScrollListener) {
2009
2120
  return;
2010
2121
  }
2011
- this.resizeObserver?.disconnect();
2012
- this.resizeObserver = new ResizeObserver(() => this.syncPreRenderStyle());
2013
- this.resizeObserver.observe(placeholder);
2122
+ const customContainer = this.getCustomPreRenderContainer();
2123
+ customContainer?.removeEventListener('scroll', this.containerScrollListener);
2124
+ this.containerScrollListener = null;
2014
2125
  }
2015
2126
 
2016
2127
  /**
@@ -2020,7 +2131,7 @@ export class TsEmbed {
2020
2131
  public destroy(): void {
2021
2132
  try {
2022
2133
  this.removeFullscreenChangeHandler();
2023
- this.resizeObserver?.disconnect();
2134
+ this.removeContainerScrollListener();
2024
2135
  this.unsubscribeToEvents();
2025
2136
  this.preRenderWrapper?.remove();
2026
2137
  this.restorePreRenderContainerPosition();
@@ -2079,6 +2190,28 @@ export class TsEmbed {
2079
2190
  // blocked.
2080
2191
  protected preRenderParamsApplied: Promise<void> = Promise.resolve();
2081
2192
 
2193
+ protected isConfigExcludedFromUrl(): boolean {
2194
+ const flag =
2195
+ this.viewConfig.additionalFlags?.excludeConfigFromURL ??
2196
+ this.embedConfig.additionalFlags?.excludeConfigFromURL;
2197
+ return flag === true || flag === 'true';
2198
+ }
2199
+
2200
+ protected async triggerUpdateEmbedParams(): Promise<void> {
2201
+ try {
2202
+ const params = await this.getUpdateEmbedParamsObject();
2203
+ this.trigger(HostEvent.UpdateEmbedParams, params);
2204
+ } catch (error) {
2205
+ logger.error(ERROR_MESSAGE.UPDATE_PARAMS_FAILED, error);
2206
+ this.handleError({
2207
+ errorType: ErrorDetailsTypes.API,
2208
+ message: error?.message || ERROR_MESSAGE.UPDATE_PARAMS_FAILED,
2209
+ code: EmbedErrorCodes.UPDATE_PARAMS_FAILED,
2210
+ error: error?.message || error,
2211
+ });
2212
+ }
2213
+ }
2214
+
2082
2215
  protected beforePrerenderVisible(): void {
2083
2216
  // We can ignore this as its a bit expensive and the newer customers
2084
2217
  // have moved on to UpdateEmbedParams supported clusters
@@ -2089,16 +2222,7 @@ export class TsEmbed {
2089
2222
  this.preRenderParamsApplied = new Promise<void>((resolve) => {
2090
2223
  this.executeAfterEmbedContainerLoaded(async () => {
2091
2224
  try {
2092
- const params = await this.getUpdateEmbedParamsObject();
2093
- this.trigger(HostEvent.UpdateEmbedParams, params);
2094
- } catch (error) {
2095
- logger.error(ERROR_MESSAGE.UPDATE_PARAMS_FAILED, error);
2096
- this.handleError({
2097
- errorType: ErrorDetailsTypes.API,
2098
- message: error?.message || ERROR_MESSAGE.UPDATE_PARAMS_FAILED,
2099
- code: EmbedErrorCodes.UPDATE_PARAMS_FAILED,
2100
- error: error?.message || error,
2101
- });
2225
+ await this.triggerUpdateEmbedParams();
2102
2226
  } finally {
2103
2227
  setTimeout(resolve, UPDATE_EMBED_PARAMS_SETTLE_MS);
2104
2228
  }
@@ -2134,18 +2258,14 @@ export class TsEmbed {
2134
2258
 
2135
2259
  if (this.hostElement) {
2136
2260
  this.insertedDomEl = this.createPreRenderPlaceholder();
2137
- // Carry a height fullHeight has already measured onto the fresh
2138
- // placeholder, so a re-show does not flash at frameParams height.
2139
- // UNMEASURED_WRAPPER_HEIGHT is what createPreRenderWrapper() seeds
2140
- // before anything has been measured; treating that as a measurement
2141
- // is what made a first reveal overshoot to a full viewport.
2142
- const wrapperHeight = this.preRenderWrapper.style.height;
2143
- if (
2144
- (this.viewConfig as { fullHeight: boolean }).fullHeight
2145
- && wrapperHeight
2146
- && wrapperHeight !== UNMEASURED_WRAPPER_HEIGHT
2147
- ) {
2148
- (this.insertedDomEl as HTMLDivElement).style.height = wrapperHeight;
2261
+ if ((this.viewConfig as { fullHeight: boolean }).fullHeight) {
2262
+ // If fullHeight has already sized the wrapper, seed the
2263
+ // placeholder with the same height so syncPreRenderStyle gets
2264
+ // an accurate rect.
2265
+ const existingHeight = this.preRenderWrapper.style.height;
2266
+ if (existingHeight) {
2267
+ (this.insertedDomEl as HTMLDivElement).style.height = existingHeight;
2268
+ }
2149
2269
  }
2150
2270
 
2151
2271
  const placeHolderId = this.getPreRenderIds().placeHolder;
@@ -2162,20 +2282,32 @@ export class TsEmbed {
2162
2282
  this.hostElement.appendChild(this.insertedDomEl);
2163
2283
 
2164
2284
  this.syncPreRenderStyle();
2165
- this.observePreRenderSize();
2285
+
2286
+ const customContainer = this.getCustomPreRenderContainer();
2287
+ if (customContainer && !this.containerScrollListener) {
2288
+ this.containerScrollListener = () => this.syncPreRenderStyle();
2289
+ customContainer.addEventListener('scroll', this.containerScrollListener);
2290
+ }
2291
+
2292
+ if (!this.getPreRenderConfig().doNotTrackSize) {
2293
+ const observeTarget = (this.insertedDomEl as HTMLElement) ?? this.hostElement;
2294
+ this.resizeObserver = new ResizeObserver((entries) => {
2295
+ entries.forEach((entry) => {
2296
+ if (entry.target === observeTarget) {
2297
+ this.syncPreRenderStyle();
2298
+ }
2299
+ });
2300
+ });
2301
+ this.resizeObserver.observe(observeTarget);
2302
+ }
2166
2303
  }
2167
2304
 
2168
2305
  removeStyleProperties(this.preRenderWrapper, [
2169
2306
  'z-index',
2170
2307
  'opacity',
2308
+ 'pointer-events',
2171
2309
  'overflow',
2172
- 'transform',
2173
2310
  ]);
2174
- // Set rather than removed: a container that carries `pointer-events:
2175
- // none` — the usual styling for a parking root that must not swallow
2176
- // clicks — passes it down, and dropping the property here would leave
2177
- // the inherited `none` in force and the frame dead to input.
2178
- setStyleProperties(this.preRenderWrapper, { pointerEvents: 'auto' });
2179
2311
  this.subscribeToEvents();
2180
2312
 
2181
2313
  // Setup fullscreen change handler for prerendered components
@@ -2255,16 +2387,14 @@ export class TsEmbed {
2255
2387
  top: '0',
2256
2388
  left: '0',
2257
2389
  overflow: 'hidden',
2258
- // Keeps the measured size — so the next show needs no resize, which
2259
- // is the point of pre-rendering — while lifting the box out of
2260
- // the container's scrollable area. Overflow only extends
2261
- // downwards, so a hidden frame parked above the top edge adds
2262
- // none, where one left at full height shows as blank scroll space.
2263
- transform: PRERENDER_PARKED_TRANSFORM,
2264
2390
  };
2265
2391
  setStyleProperties(this.preRenderWrapper, preRenderHideStyles);
2266
2392
 
2267
- this.resizeObserver?.disconnect();
2393
+ this.removeContainerScrollListener();
2394
+
2395
+ if (this.resizeObserver) {
2396
+ this.resizeObserver.disconnect();
2397
+ }
2268
2398
 
2269
2399
  const placeHolderEle = this.getPreRenderPlaceHolderElement();
2270
2400
  if (placeHolderEle) {
package/src/index.ts CHANGED
@@ -34,6 +34,13 @@ import { SearchBarEmbed, SearchBarViewConfig } from './embed/search-bar';
34
34
  import { SpotterAgentEmbed, SpotterAgentEmbedViewConfig, BodylessConversation, BodylessConversationViewConfig} from './embed/bodyless-conversation';
35
35
  import { SpotterEmbed, SpotterEmbedViewConfig, SpotterChatViewConfig, SpotterSidebarViewConfig, SpotterAnalystConfig, SpotterQueryMode, SpotterShareConversationConfig, StarterPromptsConfig, StarterPromptCategory, StarterPreviewDataCategory, StarterPromptQuestion, ConversationEmbed, ConversationViewConfig } from './embed/conversation';
36
36
  import { SpotterVizConfig, SpotterVizStarterPrompt, SpotterVizLoaderTip } from './embed/spotter-viz-utils';
37
+ import { SpotterExperienceVersion } from './embed/spotter-utils';
38
+ import {
39
+ LiveboardOverride,
40
+ LiveboardDataSourceOverride,
41
+ LiveboardFilterQuery,
42
+ LiveboardParameterQuery,
43
+ } from './embed/liveboard-override-utils';
37
44
  import {
38
45
  AuthFailureType, AuthStatus, AuthEvent, AuthEventEmitter,
39
46
  } from './auth';
@@ -84,7 +91,9 @@ import {
84
91
  VisualizationOverrides,
85
92
  } from './types';
86
93
  import { CustomCssVariables } from './css-variables';
87
- import { AnswerService, SessionInterface, UnderlyingDataPoint } from './utils/graphql/answerService/answerService';
94
+ import {
95
+ AnswerService, SessionInterface, UnderlyingDataPoint, SortOptions,
96
+ } from './utils/graphql/answerService/answerService';
88
97
  import { getEmbedConfig } from './embed/embedConfig';
89
98
  import { uploadMixpanelEvent, MIXPANEL_EVENT } from './mixpanel-service';
90
99
  import { tokenizedFetch } from './tokenizedFetch';
@@ -202,6 +211,7 @@ export {
202
211
  // types
203
212
  SessionInterface,
204
213
  UnderlyingDataPoint,
214
+ SortOptions,
205
215
  Page,
206
216
  AuthType,
207
217
  RuntimeFilter,
@@ -216,9 +226,14 @@ export {
216
226
  SearchViewConfig,
217
227
  SearchBarViewConfig,
218
228
  LiveboardViewConfig,
229
+ LiveboardOverride,
230
+ LiveboardDataSourceOverride,
231
+ LiveboardFilterQuery,
232
+ LiveboardParameterQuery,
219
233
  SpotterVizConfig,
220
234
  SpotterVizStarterPrompt,
221
235
  SpotterVizLoaderTip,
236
+ SpotterExperienceVersion,
222
237
  AppViewConfig,
223
238
  PrefetchFeatures,
224
239
  FrameParams,
@@ -19,6 +19,7 @@ let mixpanelInstance: mixpanel.Mixpanel;
19
19
  export const MIXPANEL_EVENT = {
20
20
  VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
21
21
  VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
22
+ VISUAL_SDK_INIT_ACTIONS: 'visual-sdk-init-actions',
22
23
  VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
23
24
  VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
24
25
  VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
@@ -34,6 +34,7 @@ export {
34
34
  AuthType,
35
35
  RuntimeFilter,
36
36
  RuntimeFilterOp,
37
+ SortOptions,
37
38
  EmbedEvent,
38
39
  HostEvent,
39
40
  DataSourceVisualMode,
@@ -42,6 +43,10 @@ export {
42
43
  SearchViewConfig,
43
44
  SearchBarViewConfig,
44
45
  LiveboardViewConfig,
46
+ LiveboardOverride,
47
+ LiveboardDataSourceOverride,
48
+ LiveboardFilterQuery,
49
+ LiveboardParameterQuery,
45
50
  AppViewConfig,
46
51
  PrefetchFeatures,
47
52
  FrameParams,
@@ -124,6 +129,7 @@ export {
124
129
  CustomActionsPosition,
125
130
  CustomActionTarget,
126
131
  SpotterAnalystConfig,
132
+ SpotterExperienceVersion,
127
133
  StarterPromptsConfig,
128
134
  StarterPromptCategory,
129
135
  StarterPreviewDataCategory,