@thoughtspot/visual-embed-sdk 1.53.0 → 1.53.1

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 (151) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/contracts/contracts.spec.js +4 -0
  3. package/cjs/src/contracts/contracts.spec.js.map +1 -1
  4. package/cjs/src/contracts/host-event-contracts.d.ts +10 -0
  5. package/cjs/src/contracts/host-event-contracts.d.ts.map +1 -1
  6. package/cjs/src/embed/app.d.ts +1 -0
  7. package/cjs/src/embed/app.d.ts.map +1 -1
  8. package/cjs/src/embed/app.js.map +1 -1
  9. package/cjs/src/embed/conversation.d.ts +14 -0
  10. package/cjs/src/embed/conversation.d.ts.map +1 -1
  11. package/cjs/src/embed/conversation.js.map +1 -1
  12. package/cjs/src/embed/conversation.spec.js +22 -0
  13. package/cjs/src/embed/conversation.spec.js.map +1 -1
  14. package/cjs/src/embed/host-events.spec.js +32 -0
  15. package/cjs/src/embed/host-events.spec.js.map +1 -1
  16. package/cjs/src/embed/liveboard.d.ts +2 -16
  17. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  18. package/cjs/src/embed/liveboard.js +29 -10
  19. package/cjs/src/embed/liveboard.js.map +1 -1
  20. package/cjs/src/embed/liveboard.spec.js +97 -0
  21. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  22. package/cjs/src/embed/spotter-utils.d.ts +1 -0
  23. package/cjs/src/embed/spotter-utils.d.ts.map +1 -1
  24. package/cjs/src/embed/spotter-utils.js +7 -1
  25. package/cjs/src/embed/spotter-utils.js.map +1 -1
  26. package/cjs/src/embed/spotter-utils.spec.js +19 -0
  27. package/cjs/src/embed/spotter-utils.spec.js.map +1 -1
  28. package/cjs/src/embed/ts-embed.d.ts +21 -16
  29. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  30. package/cjs/src/embed/ts-embed.js +77 -63
  31. package/cjs/src/embed/ts-embed.js.map +1 -1
  32. package/cjs/src/embed/ts-embed.spec.js +240 -7
  33. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  34. package/cjs/src/index.d.ts +2 -2
  35. package/cjs/src/index.d.ts.map +1 -1
  36. package/cjs/src/index.js.map +1 -1
  37. package/cjs/src/react/all-types-export.d.ts +1 -1
  38. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  39. package/cjs/src/react/all-types-export.js.map +1 -1
  40. package/cjs/src/types.d.ts +69 -2
  41. package/cjs/src/types.d.ts.map +1 -1
  42. package/cjs/src/types.js +67 -0
  43. package/cjs/src/types.js.map +1 -1
  44. package/cjs/src/utils/runtimeTelemetry.d.ts +11 -0
  45. package/cjs/src/utils/runtimeTelemetry.d.ts.map +1 -0
  46. package/cjs/src/utils/runtimeTelemetry.js +34 -0
  47. package/cjs/src/utils/runtimeTelemetry.js.map +1 -0
  48. package/cjs/src/utils/runtimeTelemetry.spec.d.ts +2 -0
  49. package/cjs/src/utils/runtimeTelemetry.spec.d.ts.map +1 -0
  50. package/cjs/src/utils/runtimeTelemetry.spec.js +124 -0
  51. package/cjs/src/utils/runtimeTelemetry.spec.js.map +1 -0
  52. package/dist/{index-CyDR8j_0.js → index-CrBnZBZv.js} +1 -1
  53. package/dist/src/contracts/host-event-contracts.d.ts +10 -0
  54. package/dist/src/contracts/host-event-contracts.d.ts.map +1 -1
  55. package/dist/src/embed/app.d.ts +1 -0
  56. package/dist/src/embed/app.d.ts.map +1 -1
  57. package/dist/src/embed/conversation.d.ts +14 -0
  58. package/dist/src/embed/conversation.d.ts.map +1 -1
  59. package/dist/src/embed/liveboard.d.ts +2 -16
  60. package/dist/src/embed/liveboard.d.ts.map +1 -1
  61. package/dist/src/embed/spotter-utils.d.ts +1 -0
  62. package/dist/src/embed/spotter-utils.d.ts.map +1 -1
  63. package/dist/src/embed/ts-embed.d.ts +21 -16
  64. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  65. package/dist/src/index.d.ts +2 -2
  66. package/dist/src/index.d.ts.map +1 -1
  67. package/dist/src/react/all-types-export.d.ts +1 -1
  68. package/dist/src/react/all-types-export.d.ts.map +1 -1
  69. package/dist/src/types.d.ts +69 -2
  70. package/dist/src/types.d.ts.map +1 -1
  71. package/dist/src/utils/runtimeTelemetry.d.ts +11 -0
  72. package/dist/src/utils/runtimeTelemetry.d.ts.map +1 -0
  73. package/dist/src/utils/runtimeTelemetry.spec.d.ts +2 -0
  74. package/dist/src/utils/runtimeTelemetry.spec.d.ts.map +1 -0
  75. package/dist/tsembed-react.es.js +247 -78
  76. package/dist/tsembed-react.js +246 -77
  77. package/dist/tsembed.es.js +247 -78
  78. package/dist/tsembed.js +246 -77
  79. package/dist/visual-embed-sdk-react-full.d.ts +116 -18
  80. package/dist/visual-embed-sdk-react.d.ts +116 -18
  81. package/dist/visual-embed-sdk.d.ts +116 -33
  82. package/lib/package.json +1 -1
  83. package/lib/src/contracts/contracts.spec.js +4 -0
  84. package/lib/src/contracts/contracts.spec.js.map +1 -1
  85. package/lib/src/contracts/host-event-contracts.d.ts +10 -0
  86. package/lib/src/contracts/host-event-contracts.d.ts.map +1 -1
  87. package/lib/src/embed/app.d.ts +1 -0
  88. package/lib/src/embed/app.d.ts.map +1 -1
  89. package/lib/src/embed/app.js.map +1 -1
  90. package/lib/src/embed/conversation.d.ts +14 -0
  91. package/lib/src/embed/conversation.d.ts.map +1 -1
  92. package/lib/src/embed/conversation.js.map +1 -1
  93. package/lib/src/embed/conversation.spec.js +22 -0
  94. package/lib/src/embed/conversation.spec.js.map +1 -1
  95. package/lib/src/embed/host-events.spec.js +32 -0
  96. package/lib/src/embed/host-events.spec.js.map +1 -1
  97. package/lib/src/embed/liveboard.d.ts +2 -16
  98. package/lib/src/embed/liveboard.d.ts.map +1 -1
  99. package/lib/src/embed/liveboard.js +28 -10
  100. package/lib/src/embed/liveboard.js.map +1 -1
  101. package/lib/src/embed/liveboard.spec.js +97 -0
  102. package/lib/src/embed/liveboard.spec.js.map +1 -1
  103. package/lib/src/embed/spotter-utils.d.ts +1 -0
  104. package/lib/src/embed/spotter-utils.d.ts.map +1 -1
  105. package/lib/src/embed/spotter-utils.js +7 -1
  106. package/lib/src/embed/spotter-utils.js.map +1 -1
  107. package/lib/src/embed/spotter-utils.spec.js +19 -0
  108. package/lib/src/embed/spotter-utils.spec.js.map +1 -1
  109. package/lib/src/embed/ts-embed.d.ts +21 -16
  110. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  111. package/lib/src/embed/ts-embed.js +78 -64
  112. package/lib/src/embed/ts-embed.js.map +1 -1
  113. package/lib/src/embed/ts-embed.spec.js +240 -7
  114. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  115. package/lib/src/index.d.ts +2 -2
  116. package/lib/src/index.d.ts.map +1 -1
  117. package/lib/src/index.js.map +1 -1
  118. package/lib/src/react/all-types-export.d.ts +1 -1
  119. package/lib/src/react/all-types-export.d.ts.map +1 -1
  120. package/lib/src/react/all-types-export.js.map +1 -1
  121. package/lib/src/types.d.ts +69 -2
  122. package/lib/src/types.d.ts.map +1 -1
  123. package/lib/src/types.js +67 -0
  124. package/lib/src/types.js.map +1 -1
  125. package/lib/src/utils/runtimeTelemetry.d.ts +11 -0
  126. package/lib/src/utils/runtimeTelemetry.d.ts.map +1 -0
  127. package/lib/src/utils/runtimeTelemetry.js +28 -0
  128. package/lib/src/utils/runtimeTelemetry.js.map +1 -0
  129. package/lib/src/utils/runtimeTelemetry.spec.d.ts +2 -0
  130. package/lib/src/utils/runtimeTelemetry.spec.d.ts.map +1 -0
  131. package/lib/src/utils/runtimeTelemetry.spec.js +122 -0
  132. package/lib/src/utils/runtimeTelemetry.spec.js.map +1 -0
  133. package/lib/src/visual-embed-sdk.d.ts +116 -33
  134. package/package.json +1 -1
  135. package/src/contracts/contracts.spec.ts +4 -0
  136. package/src/contracts/host-event-contracts.ts +13 -0
  137. package/src/embed/app.ts +1 -0
  138. package/src/embed/conversation.spec.ts +24 -0
  139. package/src/embed/conversation.ts +14 -0
  140. package/src/embed/host-events.spec.ts +44 -0
  141. package/src/embed/liveboard.spec.ts +111 -0
  142. package/src/embed/liveboard.ts +34 -10
  143. package/src/embed/spotter-utils.spec.ts +20 -0
  144. package/src/embed/spotter-utils.ts +12 -1
  145. package/src/embed/ts-embed.spec.ts +297 -8
  146. package/src/embed/ts-embed.ts +79 -64
  147. package/src/index.ts +2 -0
  148. package/src/react/all-types-export.ts +1 -0
  149. package/src/types.ts +68 -0
  150. package/src/utils/runtimeTelemetry.spec.ts +148 -0
  151. package/src/utils/runtimeTelemetry.ts +50 -0
@@ -1,4 +1,4 @@
1
- /* @thoughtspot/visual-embed-sdk version 1.53.0 */
1
+ /* @thoughtspot/visual-embed-sdk version 1.53.1 */
2
2
  'use client';
3
3
  import * as React from 'react';
4
4
  import React__default, { useRef, useCallback } from 'react';
@@ -3423,6 +3423,17 @@ var HostEvent;
3423
3423
  * @version SDK: 1.54.0 | ThoughtSpot Cloud: 26.11.0.cl
3424
3424
  */
3425
3425
  HostEvent["EditVisualization"] = "editVisualization";
3426
+ /**
3427
+ * Exits Liveboard edit mode , equivalent to clicking the
3428
+ * *Cancel* button in the Liveboard edit header. The Liveboard returns to
3429
+ * view mode and the embedded app emits the {@link EmbedEvent.Cancel} event.
3430
+ * @version SDK: 1.55.0 | ThoughtSpot Cloud: 26.12.0.cl
3431
+ * @example
3432
+ * ```js
3433
+ * liveboardEmbed.trigger(HostEvent.ExitEditMode);
3434
+ * ```
3435
+ */
3436
+ HostEvent["ExitEditMode"] = "exitEditMode";
3426
3437
  /**
3427
3438
  * Trigger the **Copy link** action on a Liveboard or visualization
3428
3439
  * Payload: {@link VizScopedRequest}.
@@ -4958,6 +4969,39 @@ var HostEvent;
4958
4969
  * @version SDK: 1.49.0 | ThoughtSpot Cloud: 26.6.0.cl
4959
4970
  */
4960
4971
  HostEvent["RefreshLiveboardBrowserCache"] = "refreshLiveboardBrowserCache";
4972
+ /**
4973
+ * Switch the embed between dark appearance and its default appearance
4974
+ * while it is open, without reloading it.
4975
+ * Payload: {@link UpdateThemeRequest}.
4976
+ *
4977
+ * Use it to keep the embed in step with a theme switch in your
4978
+ * application; the appearance the embed loads with is set by `isDarkMode`.
4979
+ * The event resolves with the applied value, such as `{ isDarkMode: true }`.
4980
+ * When dark appearance is not available in the embed, the embed does not
4981
+ * change and the event rejects with an error message instead.
4982
+ * @version SDK: 1.55.0 | ThoughtSpot Cloud: 26.12.0.cl
4983
+ * @param - `isDarkMode` - `true` for dark appearance, `false` for the
4984
+ * default appearance.
4985
+ * @example
4986
+ * ```js
4987
+ * appEmbed.trigger(HostEvent.UpdateTheme, { isDarkMode: true });
4988
+ * ```
4989
+ * @example
4990
+ * ```js
4991
+ * // Follow a theme switch in your application
4992
+ * const themeSwitch = document.querySelector('#theme-switch');
4993
+ * themeSwitch.addEventListener('change', async (event) => {
4994
+ * try {
4995
+ * await appEmbed.trigger(HostEvent.UpdateTheme, {
4996
+ * isDarkMode: event.target.checked,
4997
+ * });
4998
+ * } catch (error) {
4999
+ * console.warn(error);
5000
+ * }
5001
+ * });
5002
+ * ```
5003
+ */
5004
+ HostEvent["UpdateTheme"] = "UpdateTheme";
4961
5005
  })(HostEvent || (HostEvent = {}));
4962
5006
  /**
4963
5007
  * The different visual modes that the data sources panel within
@@ -7433,6 +7477,29 @@ var Action;
7433
7477
  * ```
7434
7478
  */
7435
7479
  Action["CustomizeHomepage"] = "customizeHomepage";
7480
+ /**
7481
+ * Controls the visibility and disabled state of the *Cancel* button in the
7482
+ * Liveboard edit header, the button that discards the changes made in edit
7483
+ * mode and returns the Liveboard to view mode. The button is shown only
7484
+ * while the Liveboard is in edit mode.
7485
+ * @version SDK: 1.55.0 | ThoughtSpot Cloud: 26.12.0.cl
7486
+ * @example
7487
+ * ```js
7488
+ * const liveboardEmbed = new LiveboardEmbed('#tsEmbed', {
7489
+ * ... // other embed view config
7490
+ * hiddenActions: [Action.Cancel],
7491
+ * });
7492
+ * ```
7493
+ * @example
7494
+ * ```js
7495
+ * const liveboardEmbed = new LiveboardEmbed('#tsEmbed', {
7496
+ * ... // other embed view config
7497
+ * disabledActions: [Action.Cancel],
7498
+ * disabledActionReason: 'Save your changes to leave edit mode',
7499
+ * });
7500
+ * ```
7501
+ */
7502
+ Action["Cancel"] = "cancel";
7436
7503
  })(Action || (Action = {}));
7437
7504
  var PrefetchFeatures;
7438
7505
  (function (PrefetchFeatures) {
@@ -7937,7 +8004,7 @@ var TableContentDensity;
7937
8004
  TableContentDensity["Compact"] = "COMPACT";
7938
8005
  })(TableContentDensity || (TableContentDensity = {}));
7939
8006
 
7940
- var version$1="1.53.0";var pkg = {version:version$1};
8007
+ var version$1="1.53.1";var pkg = {version:version$1};
7941
8008
 
7942
8009
  const { version } = pkg;
7943
8010
 
@@ -10707,7 +10774,7 @@ class AnswerService {
10707
10774
  async getTML() {
10708
10775
  const { object } = await this.executeQuery(getAnswerTML, {});
10709
10776
  const edoc = object[0].edoc;
10710
- const YAML = await import('./index-CyDR8j_0.js');
10777
+ const YAML = await import('./index-CrBnZBZv.js');
10711
10778
  const parsedDoc = YAML.parse(edoc);
10712
10779
  return {
10713
10780
  answer: {
@@ -19890,6 +19957,32 @@ function initMixpanel(sessionInfo) {
19890
19957
  }
19891
19958
  }
19892
19959
 
19960
+ // Membership is checked, not just the key: a bare key allowlist would upload an
19961
+ // arbitrary customer string sitting under `operator` verbatim.
19962
+ const isEnumMember = (enumObject, value) => typeof value === 'string' && Object.values(enumObject).includes(value);
19963
+ const uniqueEnumMembers = (enumObject, values) => Array.from(new Set(values.filter((v) => isEnumMember(enumObject, v))));
19964
+ const describeRuntimeFilters = (runtimeFilters) => ({
19965
+ count: runtimeFilters.length,
19966
+ operators: uniqueEnumMembers(RuntimeFilterOp, runtimeFilters.map((filter) => filter === null || filter === void 0 ? void 0 : filter.operator)),
19967
+ });
19968
+ const describeRuntimeParameters = (runtimeParameters) => ({
19969
+ count: runtimeParameters.length,
19970
+ applicabilityLevels: uniqueEnumMembers(ApplicabilityLevel, runtimeParameters.map((parameter) => { var _a; return (_a = parameter === null || parameter === void 0 ? void 0 : parameter.applicability) === null || _a === void 0 ? void 0 : _a.level; })),
19971
+ });
19972
+ // Column names, parameter names and operands are customer data and must never
19973
+ // reach Mixpanel; an unrecognized shape is dropped rather than forwarded.
19974
+ const summarizeRuntimeDataForTelemetry = (viewConfig) => {
19975
+ const { runtimeFilters, runtimeParameters, ...rest } = viewConfig !== null && viewConfig !== void 0 ? viewConfig : {};
19976
+ const telemetryProps = { ...rest };
19977
+ if (Array.isArray(runtimeFilters)) {
19978
+ telemetryProps.runtimeFilters = describeRuntimeFilters(runtimeFilters);
19979
+ }
19980
+ if (Array.isArray(runtimeParameters)) {
19981
+ telemetryProps.runtimeParameters = describeRuntimeParameters(runtimeParameters);
19982
+ }
19983
+ return telemetryProps;
19984
+ };
19985
+
19893
19986
  var eventemitter3 = createCommonjsModule(function (module) {
19894
19987
 
19895
19988
  var has = Object.prototype.hasOwnProperty
@@ -22019,6 +22112,9 @@ const TS_EMBED_ID = '_thoughtspot-embed';
22019
22112
  */
22020
22113
  const PRERENDER_CONTAINER_ORIGINAL_POSITION_KEY = 'tsEmbedOriginalPosition';
22021
22114
  const PRERENDER_WRAPPER_ID_PREFIX = 'tsEmbed-pre-render-wrapper-';
22115
+ const PRERENDER_PARKED_TRANSFORM = 'translateY(-100%)';
22116
+ /** The height createPreRenderWrapper() seeds before anything is measured. */
22117
+ const UNMEASURED_WRAPPER_HEIGHT = '100vh';
22022
22118
  // The container applies UpdateEmbedParams through React state, so a delivered
22023
22119
  // post is not the same as the params being in effect.
22024
22120
  const UPDATE_EMBED_PARAMS_SETTLE_MS = 200;
@@ -22155,7 +22251,6 @@ class TsEmbed {
22155
22251
  this.shouldEncodeUrlQueryParams = false;
22156
22252
  this.defaultHiddenActions = [Action.ReportError];
22157
22253
  this.preRenderContainerEl = document.body;
22158
- this.containerScrollListener = null;
22159
22254
  /**
22160
22255
  * Handler for fullscreen change events
22161
22256
  */
@@ -22335,9 +22430,7 @@ class TsEmbed {
22335
22430
  ...viewConfig,
22336
22431
  };
22337
22432
  this.registerAppInit();
22338
- uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_EMBED_CREATE, {
22339
- ...viewConfig,
22340
- });
22433
+ uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_EMBED_CREATE, summarizeRuntimeDataForTelemetry(viewConfig));
22341
22434
  const embedConfig = getEmbedConfig();
22342
22435
  if (embedConfig) {
22343
22436
  this.embedConfig = embedConfig;
@@ -23041,7 +23134,7 @@ class TsEmbed {
23041
23134
  top: '0',
23042
23135
  left: '0',
23043
23136
  width: '100vw',
23044
- height: '100vh',
23137
+ height: UNMEASURED_WRAPPER_HEIGHT,
23045
23138
  };
23046
23139
  setStyleProperties(preRenderWrapper, initialPreRenderWrapperStyle);
23047
23140
  return preRenderWrapper;
@@ -23109,10 +23202,12 @@ class TsEmbed {
23109
23202
  return placeholder;
23110
23203
  }
23111
23204
  /**
23112
- * Resolves the configured preRenderContainer to a live element, falling
23113
- * back to `document.body`. A string selector is re-queried on every call so
23114
- * a remounted container (E.g.: React replacing the node) resolves to the
23115
- * fresh element; an element passed directly cannot be re-resolved.
23205
+ * Resolves the configured preRenderContainer, or defaults to the host's
23206
+ * nearest scrolling ancestor (document.body if none). The absolutely
23207
+ * positioned wrapper only follows the page while it sits inside what
23208
+ * scrolls, so body is right only when the document itself scrolls — an inner
23209
+ * scroller left the frame pinned to the viewport (SCAL-338563). A string
23210
+ * selector is re-queried each call so a remounted container resolves fresh.
23116
23211
  */
23117
23212
  resolvePreRenderContainerTarget() {
23118
23213
  var _a;
@@ -23132,7 +23227,13 @@ class TsEmbed {
23132
23227
  else if (containerConfig) {
23133
23228
  container = containerConfig;
23134
23229
  }
23135
- return (_a = container) !== null && _a !== void 0 ? _a : document.body;
23230
+ if (container) {
23231
+ return container;
23232
+ }
23233
+ if (!this.hostElement) {
23234
+ return document.body;
23235
+ }
23236
+ return (_a = getScrollableAncestors(this.hostElement)[0]) !== null && _a !== void 0 ? _a : document.body;
23136
23237
  }
23137
23238
  inheritPreRenderContainer() {
23138
23239
  var _a;
@@ -23177,8 +23278,9 @@ class TsEmbed {
23177
23278
  * Re-attaches the wrapper to a live container when the previously resolved
23178
23279
  * one has been detached or no longer holds the wrapper — e.g. the host app
23179
23280
  * remounted a custom preRenderContainer, which would otherwise leave a stale
23180
- * reference and collapse the wrapper. Only string selectors can be
23181
- * re-resolved; a container passed as an element is left untouched.
23281
+ * reference and collapse the wrapper. Selectors and the auto-resolved
23282
+ * scrolling ancestor are both re-resolved; a container passed as an element
23283
+ * is left untouched, as there is nothing to re-query.
23182
23284
  */
23183
23285
  reconcilePreRenderContainer() {
23184
23286
  const wrapper = this.preRenderWrapper;
@@ -23197,14 +23299,6 @@ class TsEmbed {
23197
23299
  if (resolved === stored && stored.contains(wrapper)) {
23198
23300
  return;
23199
23301
  }
23200
- if (this.containerScrollListener && stored !== resolved) {
23201
- if (stored !== document.body) {
23202
- stored.removeEventListener('scroll', this.containerScrollListener);
23203
- }
23204
- if (resolved !== document.body) {
23205
- resolved.addEventListener('scroll', this.containerScrollListener);
23206
- }
23207
- }
23208
23302
  this.preRenderContainerEl = resolved;
23209
23303
  this.applyPreRenderContainerPositioning();
23210
23304
  if (wrapper.parentNode !== resolved) {
@@ -23266,11 +23360,12 @@ class TsEmbed {
23266
23360
  */
23267
23361
  setIFrameHeight(height) {
23268
23362
  if (this.isPreRendered) {
23363
+ const next = getCssDimension(height);
23269
23364
  if (this.insertedDomEl) {
23270
- this.insertedDomEl.style.height = getCssDimension(height);
23365
+ this.insertedDomEl.style.height = next;
23271
23366
  }
23272
23367
  else if (this.preRenderWrapper) {
23273
- this.preRenderWrapper.style.height = getCssDimension(height);
23368
+ this.preRenderWrapper.style.height = next;
23274
23369
  }
23275
23370
  }
23276
23371
  else {
@@ -23712,34 +23807,47 @@ class TsEmbed {
23712
23807
  delete container.dataset[PRERENDER_CONTAINER_ORIGINAL_POSITION_KEY];
23713
23808
  }
23714
23809
  /**
23715
- * Detaches and clears the container scroll listener, if one is attached.
23716
- */
23717
- removeContainerScrollListener() {
23718
- if (!this.containerScrollListener) {
23810
+ * Re-sizes the wrapper when its placeholder changes size.
23811
+ *
23812
+ * Position deliberately has no equivalent. An absolutely positioned wrapper
23813
+ * follows its containing block for free, so a correctly placed frame is the
23814
+ * browser's job and costs nothing; repositioning it on scroll would mean a
23815
+ * layout read and a style write per frame to compensate for placing it in
23816
+ * the wrong box. Size is the one thing the browser will not do for us: the
23817
+ * placeholder grows when the embedded app reports a new height, and the
23818
+ * wrapper has to be told.
23819
+ */
23820
+ observePreRenderSize() {
23821
+ var _a;
23822
+ if (this.getPreRenderConfig().doNotTrackSize || typeof ResizeObserver === 'undefined') {
23719
23823
  return;
23720
23824
  }
23721
- const customContainer = this.getCustomPreRenderContainer();
23722
- customContainer === null || customContainer === void 0 ? void 0 : customContainer.removeEventListener('scroll', this.containerScrollListener);
23723
- this.containerScrollListener = null;
23825
+ const placeholder = this.getPreRenderPlaceHolderElement();
23826
+ if (!placeholder) {
23827
+ return;
23828
+ }
23829
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
23830
+ this.resizeObserver = new ResizeObserver(() => this.syncPreRenderStyle());
23831
+ this.resizeObserver.observe(placeholder);
23724
23832
  }
23725
23833
  /**
23726
23834
  * Destroys the ThoughtSpot embed, and remove any nodes from the DOM.
23727
23835
  * @version SDK: 1.19.1 | ThoughtSpot: *
23728
23836
  */
23729
23837
  destroy() {
23730
- var _a, _b, _c;
23838
+ var _a, _b, _c, _d;
23731
23839
  try {
23732
23840
  this.removeFullscreenChangeHandler();
23733
- this.removeContainerScrollListener();
23841
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
23734
23842
  this.unsubscribeToEvents();
23735
- (_a = this.preRenderWrapper) === null || _a === void 0 ? void 0 : _a.remove();
23843
+ (_b = this.preRenderWrapper) === null || _b === void 0 ? void 0 : _b.remove();
23736
23844
  this.restorePreRenderContainerPosition();
23737
23845
  if (!this.isRendered) {
23738
23846
  return;
23739
23847
  }
23740
23848
  if (!getEmbedConfig().waitForCleanupOnDestroy) {
23741
23849
  this.trigger(HostEvent.DestroyEmbed);
23742
- (_c = (_b = this.insertedDomEl) === null || _b === void 0 ? void 0 : _b.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(this.insertedDomEl);
23850
+ (_d = (_c = this.insertedDomEl) === null || _c === void 0 ? void 0 : _c.parentNode) === null || _d === void 0 ? void 0 : _d.removeChild(this.insertedDomEl);
23743
23851
  }
23744
23852
  else {
23745
23853
  const cleanupTimeout = getEmbedConfig().cleanupTimeout;
@@ -23830,7 +23938,7 @@ class TsEmbed {
23830
23938
  * wrapper to overlay it.
23831
23939
  */
23832
23940
  async showPreRender() {
23833
- var _a, _b;
23941
+ var _a;
23834
23942
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_SHOW_PRE_RENDER, {
23835
23943
  preRenderId: this.getPreRenderConfig().id,
23836
23944
  embedComponentType: this.viewConfig.embedComponentType,
@@ -23849,14 +23957,16 @@ class TsEmbed {
23849
23957
  this.beforePrerenderVisible();
23850
23958
  if (this.hostElement) {
23851
23959
  this.insertedDomEl = this.createPreRenderPlaceholder();
23852
- if (this.viewConfig.fullHeight) {
23853
- // If fullHeight has already sized the wrapper, seed the
23854
- // placeholder with the same height so syncPreRenderStyle gets
23855
- // an accurate rect.
23856
- const existingHeight = this.preRenderWrapper.style.height;
23857
- if (existingHeight) {
23858
- this.insertedDomEl.style.height = existingHeight;
23859
- }
23960
+ // Carry a height fullHeight has already measured onto the fresh
23961
+ // placeholder, so a re-show does not flash at frameParams height.
23962
+ // UNMEASURED_WRAPPER_HEIGHT is what createPreRenderWrapper() seeds
23963
+ // before anything has been measured; treating that as a measurement
23964
+ // is what made a first reveal overshoot to a full viewport.
23965
+ const wrapperHeight = this.preRenderWrapper.style.height;
23966
+ if (this.viewConfig.fullHeight
23967
+ && wrapperHeight
23968
+ && wrapperHeight !== UNMEASURED_WRAPPER_HEIGHT) {
23969
+ this.insertedDomEl.style.height = wrapperHeight;
23860
23970
  }
23861
23971
  const placeHolderId = this.getPreRenderIds().placeHolder;
23862
23972
  // Remove any stale placeholder from a previous cycle. It is located
@@ -23870,29 +23980,19 @@ class TsEmbed {
23870
23980
  (_a = this.hostElement.querySelector(`#${placeHolderId}`)) === null || _a === void 0 ? void 0 : _a.remove();
23871
23981
  this.hostElement.appendChild(this.insertedDomEl);
23872
23982
  this.syncPreRenderStyle();
23873
- const customContainer = this.getCustomPreRenderContainer();
23874
- if (customContainer && !this.containerScrollListener) {
23875
- this.containerScrollListener = () => this.syncPreRenderStyle();
23876
- customContainer.addEventListener('scroll', this.containerScrollListener);
23877
- }
23878
- if (!this.getPreRenderConfig().doNotTrackSize) {
23879
- const observeTarget = (_b = this.insertedDomEl) !== null && _b !== void 0 ? _b : this.hostElement;
23880
- this.resizeObserver = new ResizeObserver((entries) => {
23881
- entries.forEach((entry) => {
23882
- if (entry.target === observeTarget) {
23883
- this.syncPreRenderStyle();
23884
- }
23885
- });
23886
- });
23887
- this.resizeObserver.observe(observeTarget);
23888
- }
23983
+ this.observePreRenderSize();
23889
23984
  }
23890
23985
  removeStyleProperties(this.preRenderWrapper, [
23891
23986
  'z-index',
23892
23987
  'opacity',
23893
- 'pointer-events',
23894
23988
  'overflow',
23989
+ 'transform',
23895
23990
  ]);
23991
+ // Set rather than removed: a container that carries `pointer-events:
23992
+ // none` — the usual styling for a parking root that must not swallow
23993
+ // clicks — passes it down, and dropping the property here would leave
23994
+ // the inherited `none` in force and the frame dead to input.
23995
+ setStyleProperties(this.preRenderWrapper, { pointerEvents: 'auto' });
23896
23996
  this.subscribeToEvents();
23897
23997
  // Setup fullscreen change handler for prerendered components
23898
23998
  if (this.iFrame) {
@@ -23945,6 +24045,7 @@ class TsEmbed {
23945
24045
  * If the component is not preRendered, it issues a warning.
23946
24046
  */
23947
24047
  hidePreRender() {
24048
+ var _a;
23948
24049
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_HIDE_PRE_RENDER, {
23949
24050
  preRenderId: this.getPreRenderConfig().id,
23950
24051
  embedComponentType: this.viewConfig.embedComponentType,
@@ -23956,20 +24057,25 @@ class TsEmbed {
23956
24057
  return;
23957
24058
  }
23958
24059
  const { zIndex } = this.getPreRenderConfig();
24060
+ // A hidden pre-render frame must add no scroll space to the host page.
23959
24061
  const preRenderHideStyles = {
23960
24062
  opacity: '0',
23961
24063
  pointerEvents: 'none',
23962
24064
  zIndex: zIndex !== undefined ? String(zIndex) : '-1000',
23963
- position: 'absolute',
24065
+ // Resolves to the viewport, so the hidden frame belongs to no
24066
+ // scroll container's overflow; syncPreRenderStyle restores absolute
24067
+ // on show.
24068
+ position: 'fixed',
23964
24069
  top: '0',
23965
24070
  left: '0',
23966
24071
  overflow: 'hidden',
24072
+ // The one exception: a transformed or contained ancestor captures
24073
+ // `fixed`; parking above the top edge keeps it out of that
24074
+ // overflow.
24075
+ transform: PRERENDER_PARKED_TRANSFORM,
23967
24076
  };
23968
24077
  setStyleProperties(this.preRenderWrapper, preRenderHideStyles);
23969
- this.removeContainerScrollListener();
23970
- if (this.resizeObserver) {
23971
- this.resizeObserver.disconnect();
23972
- }
24078
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
23973
24079
  const placeHolderEle = this.getPreRenderPlaceHolderElement();
23974
24080
  if (placeHolderEle) {
23975
24081
  placeHolderEle.parentElement.removeChild(placeHolderEle);
@@ -24674,8 +24780,11 @@ function buildSpotterSidebarAppInitData(defaultAppInitData, viewConfig, handleEr
24674
24780
  embedParams: { visualOverridesParams: visualOverrides },
24675
24781
  };
24676
24782
  }
24783
+ // The app reads enableSpotterInstructionAndMoreSettings from the top level
24784
+ // of embedParams, so lift it out of the sidebar config.
24785
+ const { enableSpotterInstructionAndMoreSettings, ...sidebarConfigRest } = spotterSidebarConfig || {};
24677
24786
  const resolvedSidebarConfig = {
24678
- ...spotterSidebarConfig,
24787
+ ...sidebarConfigRest,
24679
24788
  ...(resolvedEnablePastConversations !== undefined && {
24680
24789
  enablePastConversationsSidebar: resolvedEnablePastConversations,
24681
24790
  }),
@@ -24697,6 +24806,9 @@ function buildSpotterSidebarAppInitData(defaultAppInitData, viewConfig, handleEr
24697
24806
  embedParams: {
24698
24807
  ...(defaultAppInitData.embedParams || {}),
24699
24808
  spotterSidebarConfig: resolvedSidebarConfig,
24809
+ ...(enableSpotterInstructionAndMoreSettings !== undefined
24810
+ ? { enableSpotterInstructionAndMoreSettings }
24811
+ : {}),
24700
24812
  ...(visualOverrides !== undefined ? { visualOverridesParams: visualOverrides } : {}),
24701
24813
  },
24702
24814
  };
@@ -25266,6 +25378,46 @@ let AppEmbed$1 = class AppEmbed extends V1Embed {
25266
25378
  }
25267
25379
  };
25268
25380
 
25381
+ /**
25382
+ * This method is like `_.isEqual` except that it accepts `customizer` which
25383
+ * is invoked to compare values. If `customizer` returns `undefined`, comparisons
25384
+ * are handled by the method instead. The `customizer` is invoked with up to
25385
+ * six arguments: (objValue, othValue [, index|key, object, other, stack]).
25386
+ *
25387
+ * @static
25388
+ * @memberOf _
25389
+ * @since 4.0.0
25390
+ * @category Lang
25391
+ * @param {*} value The value to compare.
25392
+ * @param {*} other The other value to compare.
25393
+ * @param {Function} [customizer] The function to customize comparisons.
25394
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
25395
+ * @example
25396
+ *
25397
+ * function isGreeting(value) {
25398
+ * return /^h(?:i|ello)$/.test(value);
25399
+ * }
25400
+ *
25401
+ * function customizer(objValue, othValue) {
25402
+ * if (isGreeting(objValue) && isGreeting(othValue)) {
25403
+ * return true;
25404
+ * }
25405
+ * }
25406
+ *
25407
+ * var array = ['hello', 'goodbye'];
25408
+ * var other = ['hi', 'goodbye'];
25409
+ *
25410
+ * _.isEqualWith(array, other, customizer);
25411
+ * // => true
25412
+ */
25413
+ function isEqualWith(value, other, customizer) {
25414
+ customizer = typeof customizer == 'function' ? customizer : undefined;
25415
+ var result = customizer ? customizer(value, other) : undefined;
25416
+ return result === undefined ? _baseIsEqual(value, other, undefined, customizer) : !!result;
25417
+ }
25418
+
25419
+ var isEqualWith_1 = isEqualWith;
25420
+
25269
25421
  const getPreviewQuery = `
25270
25422
  query GetEurekaVizSnapshots(
25271
25423
  $vizId: String!, $liveboardId: String!) {
@@ -25380,6 +25532,11 @@ const HOME_SETTLE_MS = 200;
25380
25532
  * })
25381
25533
  * ```
25382
25534
  */
25535
+ /**
25536
+ * A shallow copy without the keys whose value is `undefined`, so a key that was
25537
+ * assigned `undefined` compares equal to one that was never set.
25538
+ */
25539
+ const definedEntries = (config = {}) => Object.fromEntries(Object.entries(config).filter(([, value]) => value !== undefined));
25383
25540
  let LiveboardEmbed$1 = class LiveboardEmbed extends V1Embed {
25384
25541
  constructor(domSelector, viewConfig) {
25385
25542
  viewConfig.embedComponentType = 'LiveboardEmbed';
@@ -25665,16 +25822,18 @@ let LiveboardEmbed$1 = class LiveboardEmbed extends V1Embed {
25665
25822
  beforePrerenderVisible() {
25666
25823
  super.beforePrerenderVisible();
25667
25824
  // Captured before showPreRender() hands the wrapper over to this
25668
- // instance. Itself means a hide/show, not a hand-over, so there is
25669
- // nothing stale to clear.
25825
+ // instance. React builds a new instance per mount, so an equal config
25826
+ // is a hide/show, not a hand-over: there is nothing stale to clear.
25670
25827
  const previous = this.getPreRenderObj();
25671
- const showing = previous === this ? undefined : previous === null || previous === void 0 ? void 0 : previous.currentLiveboardState;
25828
+ const previousRoute = this.isSameEmbedConfig(previous)
25829
+ ? undefined
25830
+ : previous === null || previous === void 0 ? void 0 : previous.currentLiveboardState;
25672
25831
  this.executeAfterEmbedContainerLoaded(async () => {
25673
25832
  // Without this the params callback suspends on its await and
25674
25833
  // Navigate goes out first, so the container loads with the previous
25675
25834
  // config's filters.
25676
25835
  await this.preRenderParamsApplied;
25677
- if (this.isShowingLiveboardRoute(showing)) {
25836
+ if (this.isAlreadyOnSameRoute(previousRoute)) {
25678
25837
  // Navigate to the route we are already on is a no-op, so the
25679
25838
  // liveboard keeps its state. Home unmounts the container, which
25680
25839
  // clears it.
@@ -25695,17 +25854,27 @@ let LiveboardEmbed$1 = class LiveboardEmbed extends V1Embed {
25695
25854
  };
25696
25855
  });
25697
25856
  }
25857
+ // definedEntries drops undefined-valued keys: a shown instance carries
25858
+ // vizId/activeTabId/etc as undefined, so a raw isEqual never matches again.
25859
+ // Functions compare equal, since React passes a fresh closure per render.
25860
+ isSameEmbedConfig(previous) {
25861
+ if (!previous)
25862
+ return false;
25863
+ if (previous === this)
25864
+ return true;
25865
+ return isEqualWith_1(definedEntries(previous.viewConfig), definedEntries(this.viewConfig), (a, b) => (typeof a === 'function' && typeof b === 'function' ? true : undefined));
25866
+ }
25698
25867
  // The whole route, not just the liveboard id: the path is built from the
25699
25868
  // viz, tab and view too, so a same-liveboard show onto another tab is a
25700
25869
  // real navigation.
25701
- isShowingLiveboardRoute(showing) {
25702
- if (!(showing === null || showing === void 0 ? void 0 : showing.liveboardId))
25870
+ isAlreadyOnSameRoute(previousRoute) {
25871
+ if (!(previousRoute === null || previousRoute === void 0 ? void 0 : previousRoute.liveboardId))
25703
25872
  return false;
25704
25873
  const { liveboardId, vizId, activeTabId, personalizedViewId, } = this.viewConfig;
25705
- return showing.liveboardId === liveboardId
25706
- && showing.vizId === vizId
25707
- && showing.activeTabId === activeTabId
25708
- && showing.personalizedViewId === personalizedViewId;
25874
+ return previousRoute.liveboardId === liveboardId
25875
+ && previousRoute.vizId === vizId
25876
+ && previousRoute.activeTabId === activeTabId
25877
+ && previousRoute.personalizedViewId === personalizedViewId;
25709
25878
  }
25710
25879
  async handleRenderForPrerender() {
25711
25880
  if (isUndefined$1(this.viewConfig.liveboardId)) {