@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
  function _mergeNamespaces(n, m) {
4
4
  m.forEach(function (e) {
@@ -3238,6 +3238,17 @@ var HostEvent;
3238
3238
  * @version SDK: 1.54.0 | ThoughtSpot Cloud: 26.11.0.cl
3239
3239
  */
3240
3240
  HostEvent["EditVisualization"] = "editVisualization";
3241
+ /**
3242
+ * Exits Liveboard edit mode , equivalent to clicking the
3243
+ * *Cancel* button in the Liveboard edit header. The Liveboard returns to
3244
+ * view mode and the embedded app emits the {@link EmbedEvent.Cancel} event.
3245
+ * @version SDK: 1.55.0 | ThoughtSpot Cloud: 26.12.0.cl
3246
+ * @example
3247
+ * ```js
3248
+ * liveboardEmbed.trigger(HostEvent.ExitEditMode);
3249
+ * ```
3250
+ */
3251
+ HostEvent["ExitEditMode"] = "exitEditMode";
3241
3252
  /**
3242
3253
  * Trigger the **Copy link** action on a Liveboard or visualization
3243
3254
  * Payload: {@link VizScopedRequest}.
@@ -4773,6 +4784,39 @@ var HostEvent;
4773
4784
  * @version SDK: 1.49.0 | ThoughtSpot Cloud: 26.6.0.cl
4774
4785
  */
4775
4786
  HostEvent["RefreshLiveboardBrowserCache"] = "refreshLiveboardBrowserCache";
4787
+ /**
4788
+ * Switch the embed between dark appearance and its default appearance
4789
+ * while it is open, without reloading it.
4790
+ * Payload: {@link UpdateThemeRequest}.
4791
+ *
4792
+ * Use it to keep the embed in step with a theme switch in your
4793
+ * application; the appearance the embed loads with is set by `isDarkMode`.
4794
+ * The event resolves with the applied value, such as `{ isDarkMode: true }`.
4795
+ * When dark appearance is not available in the embed, the embed does not
4796
+ * change and the event rejects with an error message instead.
4797
+ * @version SDK: 1.55.0 | ThoughtSpot Cloud: 26.12.0.cl
4798
+ * @param - `isDarkMode` - `true` for dark appearance, `false` for the
4799
+ * default appearance.
4800
+ * @example
4801
+ * ```js
4802
+ * appEmbed.trigger(HostEvent.UpdateTheme, { isDarkMode: true });
4803
+ * ```
4804
+ * @example
4805
+ * ```js
4806
+ * // Follow a theme switch in your application
4807
+ * const themeSwitch = document.querySelector('#theme-switch');
4808
+ * themeSwitch.addEventListener('change', async (event) => {
4809
+ * try {
4810
+ * await appEmbed.trigger(HostEvent.UpdateTheme, {
4811
+ * isDarkMode: event.target.checked,
4812
+ * });
4813
+ * } catch (error) {
4814
+ * console.warn(error);
4815
+ * }
4816
+ * });
4817
+ * ```
4818
+ */
4819
+ HostEvent["UpdateTheme"] = "UpdateTheme";
4776
4820
  })(HostEvent || (HostEvent = {}));
4777
4821
  /**
4778
4822
  * The different visual modes that the data sources panel within
@@ -7248,6 +7292,29 @@ var Action;
7248
7292
  * ```
7249
7293
  */
7250
7294
  Action["CustomizeHomepage"] = "customizeHomepage";
7295
+ /**
7296
+ * Controls the visibility and disabled state of the *Cancel* button in the
7297
+ * Liveboard edit header, the button that discards the changes made in edit
7298
+ * mode and returns the Liveboard to view mode. The button is shown only
7299
+ * while the Liveboard is in edit mode.
7300
+ * @version SDK: 1.55.0 | ThoughtSpot Cloud: 26.12.0.cl
7301
+ * @example
7302
+ * ```js
7303
+ * const liveboardEmbed = new LiveboardEmbed('#tsEmbed', {
7304
+ * ... // other embed view config
7305
+ * hiddenActions: [Action.Cancel],
7306
+ * });
7307
+ * ```
7308
+ * @example
7309
+ * ```js
7310
+ * const liveboardEmbed = new LiveboardEmbed('#tsEmbed', {
7311
+ * ... // other embed view config
7312
+ * disabledActions: [Action.Cancel],
7313
+ * disabledActionReason: 'Save your changes to leave edit mode',
7314
+ * });
7315
+ * ```
7316
+ */
7317
+ Action["Cancel"] = "cancel";
7251
7318
  })(Action || (Action = {}));
7252
7319
  var PrefetchFeatures;
7253
7320
  (function (PrefetchFeatures) {
@@ -7752,7 +7819,7 @@ var TableContentDensity;
7752
7819
  TableContentDensity["Compact"] = "COMPACT";
7753
7820
  })(TableContentDensity || (TableContentDensity = {}));
7754
7821
 
7755
- var version$1="1.53.0";var pkg = {version:version$1};
7822
+ var version$1="1.53.1";var pkg = {version:version$1};
7756
7823
 
7757
7824
  const { version } = pkg;
7758
7825
 
@@ -10921,7 +10988,7 @@ class AnswerService {
10921
10988
  async getTML() {
10922
10989
  const { object } = await this.executeQuery(getAnswerTML, {});
10923
10990
  const edoc = object[0].edoc;
10924
- const YAML = await import('./index-CyDR8j_0.js');
10991
+ const YAML = await import('./index-CrBnZBZv.js');
10925
10992
  const parsedDoc = YAML.parse(edoc);
10926
10993
  return {
10927
10994
  answer: {
@@ -20040,6 +20107,32 @@ function initMixpanel(sessionInfo) {
20040
20107
  }
20041
20108
  }
20042
20109
 
20110
+ // Membership is checked, not just the key: a bare key allowlist would upload an
20111
+ // arbitrary customer string sitting under `operator` verbatim.
20112
+ const isEnumMember = (enumObject, value) => typeof value === 'string' && Object.values(enumObject).includes(value);
20113
+ const uniqueEnumMembers = (enumObject, values) => Array.from(new Set(values.filter((v) => isEnumMember(enumObject, v))));
20114
+ const describeRuntimeFilters = (runtimeFilters) => ({
20115
+ count: runtimeFilters.length,
20116
+ operators: uniqueEnumMembers(RuntimeFilterOp, runtimeFilters.map((filter) => filter === null || filter === void 0 ? void 0 : filter.operator)),
20117
+ });
20118
+ const describeRuntimeParameters = (runtimeParameters) => ({
20119
+ count: runtimeParameters.length,
20120
+ 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; })),
20121
+ });
20122
+ // Column names, parameter names and operands are customer data and must never
20123
+ // reach Mixpanel; an unrecognized shape is dropped rather than forwarded.
20124
+ const summarizeRuntimeDataForTelemetry = (viewConfig) => {
20125
+ const { runtimeFilters, runtimeParameters, ...rest } = viewConfig !== null && viewConfig !== void 0 ? viewConfig : {};
20126
+ const telemetryProps = { ...rest };
20127
+ if (Array.isArray(runtimeFilters)) {
20128
+ telemetryProps.runtimeFilters = describeRuntimeFilters(runtimeFilters);
20129
+ }
20130
+ if (Array.isArray(runtimeParameters)) {
20131
+ telemetryProps.runtimeParameters = describeRuntimeParameters(runtimeParameters);
20132
+ }
20133
+ return telemetryProps;
20134
+ };
20135
+
20043
20136
  var eventemitter3 = createCommonjsModule(function (module) {
20044
20137
 
20045
20138
  var has = Object.prototype.hasOwnProperty
@@ -22348,6 +22441,9 @@ const TS_EMBED_ID = '_thoughtspot-embed';
22348
22441
  */
22349
22442
  const PRERENDER_CONTAINER_ORIGINAL_POSITION_KEY = 'tsEmbedOriginalPosition';
22350
22443
  const PRERENDER_WRAPPER_ID_PREFIX = 'tsEmbed-pre-render-wrapper-';
22444
+ const PRERENDER_PARKED_TRANSFORM = 'translateY(-100%)';
22445
+ /** The height createPreRenderWrapper() seeds before anything is measured. */
22446
+ const UNMEASURED_WRAPPER_HEIGHT = '100vh';
22351
22447
  // The container applies UpdateEmbedParams through React state, so a delivered
22352
22448
  // post is not the same as the params being in effect.
22353
22449
  const UPDATE_EMBED_PARAMS_SETTLE_MS = 200;
@@ -22484,7 +22580,6 @@ class TsEmbed {
22484
22580
  this.shouldEncodeUrlQueryParams = false;
22485
22581
  this.defaultHiddenActions = [Action.ReportError];
22486
22582
  this.preRenderContainerEl = document.body;
22487
- this.containerScrollListener = null;
22488
22583
  /**
22489
22584
  * Handler for fullscreen change events
22490
22585
  */
@@ -22664,9 +22759,7 @@ class TsEmbed {
22664
22759
  ...viewConfig,
22665
22760
  };
22666
22761
  this.registerAppInit();
22667
- uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_EMBED_CREATE, {
22668
- ...viewConfig,
22669
- });
22762
+ uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_EMBED_CREATE, summarizeRuntimeDataForTelemetry(viewConfig));
22670
22763
  const embedConfig = getEmbedConfig();
22671
22764
  if (embedConfig) {
22672
22765
  this.embedConfig = embedConfig;
@@ -23370,7 +23463,7 @@ class TsEmbed {
23370
23463
  top: '0',
23371
23464
  left: '0',
23372
23465
  width: '100vw',
23373
- height: '100vh',
23466
+ height: UNMEASURED_WRAPPER_HEIGHT,
23374
23467
  };
23375
23468
  setStyleProperties(preRenderWrapper, initialPreRenderWrapperStyle);
23376
23469
  return preRenderWrapper;
@@ -23438,10 +23531,12 @@ class TsEmbed {
23438
23531
  return placeholder;
23439
23532
  }
23440
23533
  /**
23441
- * Resolves the configured preRenderContainer to a live element, falling
23442
- * back to `document.body`. A string selector is re-queried on every call so
23443
- * a remounted container (E.g.: React replacing the node) resolves to the
23444
- * fresh element; an element passed directly cannot be re-resolved.
23534
+ * Resolves the configured preRenderContainer, or defaults to the host's
23535
+ * nearest scrolling ancestor (document.body if none). The absolutely
23536
+ * positioned wrapper only follows the page while it sits inside what
23537
+ * scrolls, so body is right only when the document itself scrolls — an inner
23538
+ * scroller left the frame pinned to the viewport (SCAL-338563). A string
23539
+ * selector is re-queried each call so a remounted container resolves fresh.
23445
23540
  */
23446
23541
  resolvePreRenderContainerTarget() {
23447
23542
  var _a;
@@ -23461,7 +23556,13 @@ class TsEmbed {
23461
23556
  else if (containerConfig) {
23462
23557
  container = containerConfig;
23463
23558
  }
23464
- return (_a = container) !== null && _a !== void 0 ? _a : document.body;
23559
+ if (container) {
23560
+ return container;
23561
+ }
23562
+ if (!this.hostElement) {
23563
+ return document.body;
23564
+ }
23565
+ return (_a = getScrollableAncestors(this.hostElement)[0]) !== null && _a !== void 0 ? _a : document.body;
23465
23566
  }
23466
23567
  inheritPreRenderContainer() {
23467
23568
  var _a;
@@ -23506,8 +23607,9 @@ class TsEmbed {
23506
23607
  * Re-attaches the wrapper to a live container when the previously resolved
23507
23608
  * one has been detached or no longer holds the wrapper — e.g. the host app
23508
23609
  * remounted a custom preRenderContainer, which would otherwise leave a stale
23509
- * reference and collapse the wrapper. Only string selectors can be
23510
- * re-resolved; a container passed as an element is left untouched.
23610
+ * reference and collapse the wrapper. Selectors and the auto-resolved
23611
+ * scrolling ancestor are both re-resolved; a container passed as an element
23612
+ * is left untouched, as there is nothing to re-query.
23511
23613
  */
23512
23614
  reconcilePreRenderContainer() {
23513
23615
  const wrapper = this.preRenderWrapper;
@@ -23526,14 +23628,6 @@ class TsEmbed {
23526
23628
  if (resolved === stored && stored.contains(wrapper)) {
23527
23629
  return;
23528
23630
  }
23529
- if (this.containerScrollListener && stored !== resolved) {
23530
- if (stored !== document.body) {
23531
- stored.removeEventListener('scroll', this.containerScrollListener);
23532
- }
23533
- if (resolved !== document.body) {
23534
- resolved.addEventListener('scroll', this.containerScrollListener);
23535
- }
23536
- }
23537
23631
  this.preRenderContainerEl = resolved;
23538
23632
  this.applyPreRenderContainerPositioning();
23539
23633
  if (wrapper.parentNode !== resolved) {
@@ -23595,11 +23689,12 @@ class TsEmbed {
23595
23689
  */
23596
23690
  setIFrameHeight(height) {
23597
23691
  if (this.isPreRendered) {
23692
+ const next = getCssDimension(height);
23598
23693
  if (this.insertedDomEl) {
23599
- this.insertedDomEl.style.height = getCssDimension(height);
23694
+ this.insertedDomEl.style.height = next;
23600
23695
  }
23601
23696
  else if (this.preRenderWrapper) {
23602
- this.preRenderWrapper.style.height = getCssDimension(height);
23697
+ this.preRenderWrapper.style.height = next;
23603
23698
  }
23604
23699
  }
23605
23700
  else {
@@ -24041,34 +24136,47 @@ class TsEmbed {
24041
24136
  delete container.dataset[PRERENDER_CONTAINER_ORIGINAL_POSITION_KEY];
24042
24137
  }
24043
24138
  /**
24044
- * Detaches and clears the container scroll listener, if one is attached.
24045
- */
24046
- removeContainerScrollListener() {
24047
- if (!this.containerScrollListener) {
24139
+ * Re-sizes the wrapper when its placeholder changes size.
24140
+ *
24141
+ * Position deliberately has no equivalent. An absolutely positioned wrapper
24142
+ * follows its containing block for free, so a correctly placed frame is the
24143
+ * browser's job and costs nothing; repositioning it on scroll would mean a
24144
+ * layout read and a style write per frame to compensate for placing it in
24145
+ * the wrong box. Size is the one thing the browser will not do for us: the
24146
+ * placeholder grows when the embedded app reports a new height, and the
24147
+ * wrapper has to be told.
24148
+ */
24149
+ observePreRenderSize() {
24150
+ var _a;
24151
+ if (this.getPreRenderConfig().doNotTrackSize || typeof ResizeObserver === 'undefined') {
24048
24152
  return;
24049
24153
  }
24050
- const customContainer = this.getCustomPreRenderContainer();
24051
- customContainer === null || customContainer === void 0 ? void 0 : customContainer.removeEventListener('scroll', this.containerScrollListener);
24052
- this.containerScrollListener = null;
24154
+ const placeholder = this.getPreRenderPlaceHolderElement();
24155
+ if (!placeholder) {
24156
+ return;
24157
+ }
24158
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
24159
+ this.resizeObserver = new ResizeObserver(() => this.syncPreRenderStyle());
24160
+ this.resizeObserver.observe(placeholder);
24053
24161
  }
24054
24162
  /**
24055
24163
  * Destroys the ThoughtSpot embed, and remove any nodes from the DOM.
24056
24164
  * @version SDK: 1.19.1 | ThoughtSpot: *
24057
24165
  */
24058
24166
  destroy() {
24059
- var _a, _b, _c;
24167
+ var _a, _b, _c, _d;
24060
24168
  try {
24061
24169
  this.removeFullscreenChangeHandler();
24062
- this.removeContainerScrollListener();
24170
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
24063
24171
  this.unsubscribeToEvents();
24064
- (_a = this.preRenderWrapper) === null || _a === void 0 ? void 0 : _a.remove();
24172
+ (_b = this.preRenderWrapper) === null || _b === void 0 ? void 0 : _b.remove();
24065
24173
  this.restorePreRenderContainerPosition();
24066
24174
  if (!this.isRendered) {
24067
24175
  return;
24068
24176
  }
24069
24177
  if (!getEmbedConfig().waitForCleanupOnDestroy) {
24070
24178
  this.trigger(HostEvent.DestroyEmbed);
24071
- (_c = (_b = this.insertedDomEl) === null || _b === void 0 ? void 0 : _b.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(this.insertedDomEl);
24179
+ (_d = (_c = this.insertedDomEl) === null || _c === void 0 ? void 0 : _c.parentNode) === null || _d === void 0 ? void 0 : _d.removeChild(this.insertedDomEl);
24072
24180
  }
24073
24181
  else {
24074
24182
  const cleanupTimeout = getEmbedConfig().cleanupTimeout;
@@ -24159,7 +24267,7 @@ class TsEmbed {
24159
24267
  * wrapper to overlay it.
24160
24268
  */
24161
24269
  async showPreRender() {
24162
- var _a, _b;
24270
+ var _a;
24163
24271
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_SHOW_PRE_RENDER, {
24164
24272
  preRenderId: this.getPreRenderConfig().id,
24165
24273
  embedComponentType: this.viewConfig.embedComponentType,
@@ -24178,14 +24286,16 @@ class TsEmbed {
24178
24286
  this.beforePrerenderVisible();
24179
24287
  if (this.hostElement) {
24180
24288
  this.insertedDomEl = this.createPreRenderPlaceholder();
24181
- if (this.viewConfig.fullHeight) {
24182
- // If fullHeight has already sized the wrapper, seed the
24183
- // placeholder with the same height so syncPreRenderStyle gets
24184
- // an accurate rect.
24185
- const existingHeight = this.preRenderWrapper.style.height;
24186
- if (existingHeight) {
24187
- this.insertedDomEl.style.height = existingHeight;
24188
- }
24289
+ // Carry a height fullHeight has already measured onto the fresh
24290
+ // placeholder, so a re-show does not flash at frameParams height.
24291
+ // UNMEASURED_WRAPPER_HEIGHT is what createPreRenderWrapper() seeds
24292
+ // before anything has been measured; treating that as a measurement
24293
+ // is what made a first reveal overshoot to a full viewport.
24294
+ const wrapperHeight = this.preRenderWrapper.style.height;
24295
+ if (this.viewConfig.fullHeight
24296
+ && wrapperHeight
24297
+ && wrapperHeight !== UNMEASURED_WRAPPER_HEIGHT) {
24298
+ this.insertedDomEl.style.height = wrapperHeight;
24189
24299
  }
24190
24300
  const placeHolderId = this.getPreRenderIds().placeHolder;
24191
24301
  // Remove any stale placeholder from a previous cycle. It is located
@@ -24199,29 +24309,19 @@ class TsEmbed {
24199
24309
  (_a = this.hostElement.querySelector(`#${placeHolderId}`)) === null || _a === void 0 ? void 0 : _a.remove();
24200
24310
  this.hostElement.appendChild(this.insertedDomEl);
24201
24311
  this.syncPreRenderStyle();
24202
- const customContainer = this.getCustomPreRenderContainer();
24203
- if (customContainer && !this.containerScrollListener) {
24204
- this.containerScrollListener = () => this.syncPreRenderStyle();
24205
- customContainer.addEventListener('scroll', this.containerScrollListener);
24206
- }
24207
- if (!this.getPreRenderConfig().doNotTrackSize) {
24208
- const observeTarget = (_b = this.insertedDomEl) !== null && _b !== void 0 ? _b : this.hostElement;
24209
- this.resizeObserver = new ResizeObserver((entries) => {
24210
- entries.forEach((entry) => {
24211
- if (entry.target === observeTarget) {
24212
- this.syncPreRenderStyle();
24213
- }
24214
- });
24215
- });
24216
- this.resizeObserver.observe(observeTarget);
24217
- }
24312
+ this.observePreRenderSize();
24218
24313
  }
24219
24314
  removeStyleProperties(this.preRenderWrapper, [
24220
24315
  'z-index',
24221
24316
  'opacity',
24222
- 'pointer-events',
24223
24317
  'overflow',
24318
+ 'transform',
24224
24319
  ]);
24320
+ // Set rather than removed: a container that carries `pointer-events:
24321
+ // none` — the usual styling for a parking root that must not swallow
24322
+ // clicks — passes it down, and dropping the property here would leave
24323
+ // the inherited `none` in force and the frame dead to input.
24324
+ setStyleProperties(this.preRenderWrapper, { pointerEvents: 'auto' });
24225
24325
  this.subscribeToEvents();
24226
24326
  // Setup fullscreen change handler for prerendered components
24227
24327
  if (this.iFrame) {
@@ -24274,6 +24374,7 @@ class TsEmbed {
24274
24374
  * If the component is not preRendered, it issues a warning.
24275
24375
  */
24276
24376
  hidePreRender() {
24377
+ var _a;
24277
24378
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_HIDE_PRE_RENDER, {
24278
24379
  preRenderId: this.getPreRenderConfig().id,
24279
24380
  embedComponentType: this.viewConfig.embedComponentType,
@@ -24285,20 +24386,25 @@ class TsEmbed {
24285
24386
  return;
24286
24387
  }
24287
24388
  const { zIndex } = this.getPreRenderConfig();
24389
+ // A hidden pre-render frame must add no scroll space to the host page.
24288
24390
  const preRenderHideStyles = {
24289
24391
  opacity: '0',
24290
24392
  pointerEvents: 'none',
24291
24393
  zIndex: zIndex !== undefined ? String(zIndex) : '-1000',
24292
- position: 'absolute',
24394
+ // Resolves to the viewport, so the hidden frame belongs to no
24395
+ // scroll container's overflow; syncPreRenderStyle restores absolute
24396
+ // on show.
24397
+ position: 'fixed',
24293
24398
  top: '0',
24294
24399
  left: '0',
24295
24400
  overflow: 'hidden',
24401
+ // The one exception: a transformed or contained ancestor captures
24402
+ // `fixed`; parking above the top edge keeps it out of that
24403
+ // overflow.
24404
+ transform: PRERENDER_PARKED_TRANSFORM,
24296
24405
  };
24297
24406
  setStyleProperties(this.preRenderWrapper, preRenderHideStyles);
24298
- this.removeContainerScrollListener();
24299
- if (this.resizeObserver) {
24300
- this.resizeObserver.disconnect();
24301
- }
24407
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
24302
24408
  const placeHolderEle = this.getPreRenderPlaceHolderElement();
24303
24409
  if (placeHolderEle) {
24304
24410
  placeHolderEle.parentElement.removeChild(placeHolderEle);
@@ -24464,8 +24570,11 @@ function buildSpotterSidebarAppInitData(defaultAppInitData, viewConfig, handleEr
24464
24570
  embedParams: { visualOverridesParams: visualOverrides },
24465
24571
  };
24466
24572
  }
24573
+ // The app reads enableSpotterInstructionAndMoreSettings from the top level
24574
+ // of embedParams, so lift it out of the sidebar config.
24575
+ const { enableSpotterInstructionAndMoreSettings, ...sidebarConfigRest } = spotterSidebarConfig || {};
24467
24576
  const resolvedSidebarConfig = {
24468
- ...spotterSidebarConfig,
24577
+ ...sidebarConfigRest,
24469
24578
  ...(resolvedEnablePastConversations !== undefined && {
24470
24579
  enablePastConversationsSidebar: resolvedEnablePastConversations,
24471
24580
  }),
@@ -24487,6 +24596,9 @@ function buildSpotterSidebarAppInitData(defaultAppInitData, viewConfig, handleEr
24487
24596
  embedParams: {
24488
24597
  ...(defaultAppInitData.embedParams || {}),
24489
24598
  spotterSidebarConfig: resolvedSidebarConfig,
24599
+ ...(enableSpotterInstructionAndMoreSettings !== undefined
24600
+ ? { enableSpotterInstructionAndMoreSettings }
24601
+ : {}),
24490
24602
  ...(visualOverrides !== undefined ? { visualOverridesParams: visualOverrides } : {}),
24491
24603
  },
24492
24604
  };
@@ -25056,6 +25168,46 @@ class AppEmbed extends V1Embed {
25056
25168
  }
25057
25169
  }
25058
25170
 
25171
+ /**
25172
+ * This method is like `_.isEqual` except that it accepts `customizer` which
25173
+ * is invoked to compare values. If `customizer` returns `undefined`, comparisons
25174
+ * are handled by the method instead. The `customizer` is invoked with up to
25175
+ * six arguments: (objValue, othValue [, index|key, object, other, stack]).
25176
+ *
25177
+ * @static
25178
+ * @memberOf _
25179
+ * @since 4.0.0
25180
+ * @category Lang
25181
+ * @param {*} value The value to compare.
25182
+ * @param {*} other The other value to compare.
25183
+ * @param {Function} [customizer] The function to customize comparisons.
25184
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
25185
+ * @example
25186
+ *
25187
+ * function isGreeting(value) {
25188
+ * return /^h(?:i|ello)$/.test(value);
25189
+ * }
25190
+ *
25191
+ * function customizer(objValue, othValue) {
25192
+ * if (isGreeting(objValue) && isGreeting(othValue)) {
25193
+ * return true;
25194
+ * }
25195
+ * }
25196
+ *
25197
+ * var array = ['hello', 'goodbye'];
25198
+ * var other = ['hi', 'goodbye'];
25199
+ *
25200
+ * _.isEqualWith(array, other, customizer);
25201
+ * // => true
25202
+ */
25203
+ function isEqualWith(value, other, customizer) {
25204
+ customizer = typeof customizer == 'function' ? customizer : undefined;
25205
+ var result = customizer ? customizer(value, other) : undefined;
25206
+ return result === undefined ? _baseIsEqual(value, other, undefined, customizer) : !!result;
25207
+ }
25208
+
25209
+ var isEqualWith_1 = isEqualWith;
25210
+
25059
25211
  const getPreviewQuery = `
25060
25212
  query GetEurekaVizSnapshots(
25061
25213
  $vizId: String!, $liveboardId: String!) {
@@ -25170,6 +25322,11 @@ const HOME_SETTLE_MS = 200;
25170
25322
  * })
25171
25323
  * ```
25172
25324
  */
25325
+ /**
25326
+ * A shallow copy without the keys whose value is `undefined`, so a key that was
25327
+ * assigned `undefined` compares equal to one that was never set.
25328
+ */
25329
+ const definedEntries = (config = {}) => Object.fromEntries(Object.entries(config).filter(([, value]) => value !== undefined));
25173
25330
  class LiveboardEmbed extends V1Embed {
25174
25331
  constructor(domSelector, viewConfig) {
25175
25332
  viewConfig.embedComponentType = 'LiveboardEmbed';
@@ -25455,16 +25612,18 @@ class LiveboardEmbed extends V1Embed {
25455
25612
  beforePrerenderVisible() {
25456
25613
  super.beforePrerenderVisible();
25457
25614
  // Captured before showPreRender() hands the wrapper over to this
25458
- // instance. Itself means a hide/show, not a hand-over, so there is
25459
- // nothing stale to clear.
25615
+ // instance. React builds a new instance per mount, so an equal config
25616
+ // is a hide/show, not a hand-over: there is nothing stale to clear.
25460
25617
  const previous = this.getPreRenderObj();
25461
- const showing = previous === this ? undefined : previous === null || previous === void 0 ? void 0 : previous.currentLiveboardState;
25618
+ const previousRoute = this.isSameEmbedConfig(previous)
25619
+ ? undefined
25620
+ : previous === null || previous === void 0 ? void 0 : previous.currentLiveboardState;
25462
25621
  this.executeAfterEmbedContainerLoaded(async () => {
25463
25622
  // Without this the params callback suspends on its await and
25464
25623
  // Navigate goes out first, so the container loads with the previous
25465
25624
  // config's filters.
25466
25625
  await this.preRenderParamsApplied;
25467
- if (this.isShowingLiveboardRoute(showing)) {
25626
+ if (this.isAlreadyOnSameRoute(previousRoute)) {
25468
25627
  // Navigate to the route we are already on is a no-op, so the
25469
25628
  // liveboard keeps its state. Home unmounts the container, which
25470
25629
  // clears it.
@@ -25485,17 +25644,27 @@ class LiveboardEmbed extends V1Embed {
25485
25644
  };
25486
25645
  });
25487
25646
  }
25647
+ // definedEntries drops undefined-valued keys: a shown instance carries
25648
+ // vizId/activeTabId/etc as undefined, so a raw isEqual never matches again.
25649
+ // Functions compare equal, since React passes a fresh closure per render.
25650
+ isSameEmbedConfig(previous) {
25651
+ if (!previous)
25652
+ return false;
25653
+ if (previous === this)
25654
+ return true;
25655
+ return isEqualWith_1(definedEntries(previous.viewConfig), definedEntries(this.viewConfig), (a, b) => (typeof a === 'function' && typeof b === 'function' ? true : undefined));
25656
+ }
25488
25657
  // The whole route, not just the liveboard id: the path is built from the
25489
25658
  // viz, tab and view too, so a same-liveboard show onto another tab is a
25490
25659
  // real navigation.
25491
- isShowingLiveboardRoute(showing) {
25492
- if (!(showing === null || showing === void 0 ? void 0 : showing.liveboardId))
25660
+ isAlreadyOnSameRoute(previousRoute) {
25661
+ if (!(previousRoute === null || previousRoute === void 0 ? void 0 : previousRoute.liveboardId))
25493
25662
  return false;
25494
25663
  const { liveboardId, vizId, activeTabId, personalizedViewId, } = this.viewConfig;
25495
- return showing.liveboardId === liveboardId
25496
- && showing.vizId === vizId
25497
- && showing.activeTabId === activeTabId
25498
- && showing.personalizedViewId === personalizedViewId;
25664
+ return previousRoute.liveboardId === liveboardId
25665
+ && previousRoute.vizId === vizId
25666
+ && previousRoute.activeTabId === activeTabId
25667
+ && previousRoute.personalizedViewId === personalizedViewId;
25499
25668
  }
25500
25669
  async handleRenderForPrerender() {
25501
25670
  if (isUndefined$1(this.viewConfig.liveboardId)) {