@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
package/src/types.ts CHANGED
@@ -5462,6 +5462,17 @@ export enum HostEvent {
5462
5462
  * @version SDK: 1.54.0 | ThoughtSpot Cloud: 26.11.0.cl
5463
5463
  */
5464
5464
  EditVisualization = 'editVisualization',
5465
+ /**
5466
+ * Exits Liveboard edit mode , equivalent to clicking the
5467
+ * *Cancel* button in the Liveboard edit header. The Liveboard returns to
5468
+ * view mode and the embedded app emits the {@link EmbedEvent.Cancel} event.
5469
+ * @version SDK: 1.55.0 | ThoughtSpot Cloud: 26.12.0.cl
5470
+ * @example
5471
+ * ```js
5472
+ * liveboardEmbed.trigger(HostEvent.ExitEditMode);
5473
+ * ```
5474
+ */
5475
+ ExitEditMode = 'exitEditMode',
5465
5476
  /**
5466
5477
  * Trigger the **Copy link** action on a Liveboard or visualization
5467
5478
  * Payload: {@link VizScopedRequest}.
@@ -7006,6 +7017,40 @@ export enum HostEvent {
7006
7017
  * @version SDK: 1.49.0 | ThoughtSpot Cloud: 26.6.0.cl
7007
7018
  */
7008
7019
  RefreshLiveboardBrowserCache = 'refreshLiveboardBrowserCache',
7020
+
7021
+ /**
7022
+ * Switch the embed between dark appearance and its default appearance
7023
+ * while it is open, without reloading it.
7024
+ * Payload: {@link UpdateThemeRequest}.
7025
+ *
7026
+ * Use it to keep the embed in step with a theme switch in your
7027
+ * application; the appearance the embed loads with is set by `isDarkMode`.
7028
+ * The event resolves with the applied value, such as `{ isDarkMode: true }`.
7029
+ * When dark appearance is not available in the embed, the embed does not
7030
+ * change and the event rejects with an error message instead.
7031
+ * @version SDK: 1.55.0 | ThoughtSpot Cloud: 26.12.0.cl
7032
+ * @param - `isDarkMode` - `true` for dark appearance, `false` for the
7033
+ * default appearance.
7034
+ * @example
7035
+ * ```js
7036
+ * appEmbed.trigger(HostEvent.UpdateTheme, { isDarkMode: true });
7037
+ * ```
7038
+ * @example
7039
+ * ```js
7040
+ * // Follow a theme switch in your application
7041
+ * const themeSwitch = document.querySelector('#theme-switch');
7042
+ * themeSwitch.addEventListener('change', async (event) => {
7043
+ * try {
7044
+ * await appEmbed.trigger(HostEvent.UpdateTheme, {
7045
+ * isDarkMode: event.target.checked,
7046
+ * });
7047
+ * } catch (error) {
7048
+ * console.warn(error);
7049
+ * }
7050
+ * });
7051
+ * ```
7052
+ */
7053
+ UpdateTheme = 'UpdateTheme',
7009
7054
  }
7010
7055
 
7011
7056
  /**
@@ -9515,6 +9560,29 @@ export enum Action {
9515
9560
  * ```
9516
9561
  */
9517
9562
  CustomizeHomepage = 'customizeHomepage',
9563
+ /**
9564
+ * Controls the visibility and disabled state of the *Cancel* button in the
9565
+ * Liveboard edit header, the button that discards the changes made in edit
9566
+ * mode and returns the Liveboard to view mode. The button is shown only
9567
+ * while the Liveboard is in edit mode.
9568
+ * @version SDK: 1.55.0 | ThoughtSpot Cloud: 26.12.0.cl
9569
+ * @example
9570
+ * ```js
9571
+ * const liveboardEmbed = new LiveboardEmbed('#tsEmbed', {
9572
+ * ... // other embed view config
9573
+ * hiddenActions: [Action.Cancel],
9574
+ * });
9575
+ * ```
9576
+ * @example
9577
+ * ```js
9578
+ * const liveboardEmbed = new LiveboardEmbed('#tsEmbed', {
9579
+ * ... // other embed view config
9580
+ * disabledActions: [Action.Cancel],
9581
+ * disabledActionReason: 'Save your changes to leave edit mode',
9582
+ * });
9583
+ * ```
9584
+ */
9585
+ Cancel = 'cancel',
9518
9586
  }
9519
9587
  export interface AnswerServiceType {
9520
9588
  getAnswer?: (offset: number, batchSize: number) => any;
@@ -0,0 +1,148 @@
1
+ import {
2
+ describeRuntimeFilters,
3
+ describeRuntimeParameters,
4
+ summarizeRuntimeDataForTelemetry,
5
+ } from './runtimeTelemetry';
6
+ import { RuntimeFilter, RuntimeFilterOp, RuntimeParameter } from '../types';
7
+ import { ApplicabilityLevel } from '../contracts/ui-passthrough-contracts';
8
+
9
+ const customerFilters: RuntimeFilter[] = [
10
+ {
11
+ columnName: 'Patient SSN',
12
+ operator: RuntimeFilterOp.EQ,
13
+ values: ['123-45-6789'],
14
+ },
15
+ {
16
+ columnName: 'Revenue',
17
+ operator: RuntimeFilterOp.BW,
18
+ values: [1000, 5000],
19
+ },
20
+ ];
21
+
22
+ const customerParameters: RuntimeParameter[] = [
23
+ {
24
+ name: 'Sales Region',
25
+ value: 'EMEA',
26
+ applicability: { level: ApplicabilityLevel.Tab, targetId: 'tab-guid' },
27
+ },
28
+ ];
29
+
30
+ describe('describeRuntimeFilters', () => {
31
+ test('reports the count and the operators used', () => {
32
+ expect(describeRuntimeFilters(customerFilters)).toEqual({
33
+ count: 2,
34
+ operators: ['EQ', 'BW'],
35
+ });
36
+ });
37
+
38
+ test('de-duplicates repeated operators', () => {
39
+ const filters = [
40
+ { columnName: 'a', operator: RuntimeFilterOp.EQ, values: ['x'] },
41
+ { columnName: 'b', operator: RuntimeFilterOp.EQ, values: ['y'] },
42
+ ];
43
+ expect(describeRuntimeFilters(filters).operators).toEqual(['EQ']);
44
+ });
45
+
46
+ test('drops an operator that is not a RuntimeFilterOp member', () => {
47
+ const filters = [
48
+ { columnName: 'a', operator: 'a-customer-value' as any, values: ['x'] },
49
+ ];
50
+ expect(describeRuntimeFilters(filters)).toEqual({ count: 1, operators: [] });
51
+ });
52
+
53
+ test('tolerates a filter with no operator', () => {
54
+ expect(describeRuntimeFilters([undefined as any, {} as any])).toEqual({
55
+ count: 2,
56
+ operators: [],
57
+ });
58
+ });
59
+
60
+ test('reports an empty list', () => {
61
+ expect(describeRuntimeFilters([])).toEqual({ count: 0, operators: [] });
62
+ });
63
+ });
64
+
65
+ describe('describeRuntimeParameters', () => {
66
+ test('reports the count and the applicability levels used', () => {
67
+ expect(describeRuntimeParameters(customerParameters)).toEqual({
68
+ count: 1,
69
+ applicabilityLevels: ['TAB'],
70
+ });
71
+ });
72
+
73
+ test('reports no level when the parameter has no applicability', () => {
74
+ expect(describeRuntimeParameters([{ name: 'Region', value: 'EMEA' }])).toEqual({
75
+ count: 1,
76
+ applicabilityLevels: [],
77
+ });
78
+ });
79
+
80
+ test('drops a level that is not an ApplicabilityLevel member', () => {
81
+ const parameters = [
82
+ { name: 'Region', value: 'EMEA', applicability: { level: 'EVERYWHERE' as any } },
83
+ ];
84
+ expect(describeRuntimeParameters(parameters).applicabilityLevels).toEqual([]);
85
+ });
86
+ });
87
+
88
+ describe('summarizeRuntimeDataForTelemetry', () => {
89
+ test('never returns a column name, a parameter name or an operand', () => {
90
+ const props = summarizeRuntimeDataForTelemetry({
91
+ liveboardId: 'lb-guid',
92
+ runtimeFilters: customerFilters,
93
+ runtimeParameters: customerParameters,
94
+ });
95
+
96
+ const serialised = JSON.stringify(props);
97
+ ['Patient SSN', '123-45-6789', 'Revenue', '1000', '5000', 'Sales Region', 'EMEA', 'tab-guid'].forEach(
98
+ (customerValue) => {
99
+ expect(serialised).not.toContain(customerValue);
100
+ },
101
+ );
102
+ });
103
+
104
+ test('replaces both arrays with their summaries', () => {
105
+ expect(
106
+ summarizeRuntimeDataForTelemetry({
107
+ runtimeFilters: customerFilters,
108
+ runtimeParameters: customerParameters,
109
+ }),
110
+ ).toEqual({
111
+ runtimeFilters: { count: 2, operators: ['EQ', 'BW'] },
112
+ runtimeParameters: { count: 1, applicabilityLevels: ['TAB'] },
113
+ });
114
+ });
115
+
116
+ test('leaves every other view config property untouched', () => {
117
+ expect(
118
+ summarizeRuntimeDataForTelemetry({
119
+ liveboardId: 'lb-guid',
120
+ fullHeight: true,
121
+ hiddenActions: ['download'],
122
+ }),
123
+ ).toEqual({
124
+ liveboardId: 'lb-guid',
125
+ fullHeight: true,
126
+ hiddenActions: ['download'],
127
+ });
128
+ });
129
+
130
+ test('omits the keys entirely when they are absent', () => {
131
+ const props = summarizeRuntimeDataForTelemetry({ liveboardId: 'lb-guid' });
132
+ expect(props).not.toHaveProperty('runtimeFilters');
133
+ expect(props).not.toHaveProperty('runtimeParameters');
134
+ });
135
+
136
+ test('drops a non-array value rather than passing it through', () => {
137
+ const props = summarizeRuntimeDataForTelemetry({
138
+ runtimeFilters: { columnName: 'Patient SSN' } as any,
139
+ runtimeParameters: 'Sales Region' as any,
140
+ });
141
+ expect(props).not.toHaveProperty('runtimeFilters');
142
+ expect(props).not.toHaveProperty('runtimeParameters');
143
+ });
144
+
145
+ test('tolerates an undefined view config', () => {
146
+ expect(summarizeRuntimeDataForTelemetry(undefined as any)).toEqual({});
147
+ });
148
+ });
@@ -0,0 +1,50 @@
1
+ import { RuntimeFilter, RuntimeFilterOp, RuntimeParameter } from '../types';
2
+ import { ApplicabilityLevel } from '../contracts/ui-passthrough-contracts';
3
+
4
+ // Membership is checked, not just the key: a bare key allowlist would upload an
5
+ // arbitrary customer string sitting under `operator` verbatim.
6
+ const isEnumMember = (enumObject: Record<string, string>, value: unknown): boolean =>
7
+ typeof value === 'string' && Object.values(enumObject).includes(value);
8
+
9
+ const uniqueEnumMembers = (
10
+ enumObject: Record<string, string>,
11
+ values: unknown[],
12
+ ): string[] => Array.from(new Set(values.filter((v) => isEnumMember(enumObject, v)))) as string[];
13
+
14
+ export const describeRuntimeFilters = (
15
+ runtimeFilters: RuntimeFilter[],
16
+ ): { count: number; operators: string[] } => ({
17
+ count: runtimeFilters.length,
18
+ operators: uniqueEnumMembers(
19
+ RuntimeFilterOp as unknown as Record<string, string>,
20
+ runtimeFilters.map((filter) => filter?.operator),
21
+ ),
22
+ });
23
+
24
+ export const describeRuntimeParameters = (
25
+ runtimeParameters: RuntimeParameter[],
26
+ ): { count: number; applicabilityLevels: string[] } => ({
27
+ count: runtimeParameters.length,
28
+ applicabilityLevels: uniqueEnumMembers(
29
+ ApplicabilityLevel as unknown as Record<string, string>,
30
+ runtimeParameters.map((parameter) => parameter?.applicability?.level),
31
+ ),
32
+ });
33
+
34
+ // Column names, parameter names and operands are customer data and must never
35
+ // reach Mixpanel; an unrecognized shape is dropped rather than forwarded.
36
+ export const summarizeRuntimeDataForTelemetry = <T extends Record<string, any>>(
37
+ viewConfig: T,
38
+ ): Record<string, any> => {
39
+ const { runtimeFilters, runtimeParameters, ...rest } = viewConfig ?? ({} as T);
40
+ const telemetryProps: Record<string, any> = { ...rest };
41
+
42
+ if (Array.isArray(runtimeFilters)) {
43
+ telemetryProps.runtimeFilters = describeRuntimeFilters(runtimeFilters);
44
+ }
45
+ if (Array.isArray(runtimeParameters)) {
46
+ telemetryProps.runtimeParameters = describeRuntimeParameters(runtimeParameters);
47
+ }
48
+
49
+ return telemetryProps;
50
+ };