@thoughtspot/visual-embed-sdk 1.23.2 → 1.23.3

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 (73) hide show
  1. package/cjs/package.json +8 -7
  2. package/cjs/src/auth.d.ts.map +1 -1
  3. package/cjs/src/auth.js +3 -0
  4. package/cjs/src/auth.js.map +1 -1
  5. package/cjs/src/embed/base.d.ts +2 -0
  6. package/cjs/src/embed/base.d.ts.map +1 -1
  7. package/cjs/src/embed/base.js +4 -2
  8. package/cjs/src/embed/base.js.map +1 -1
  9. package/cjs/src/embed/ts-embed.d.ts +3 -1
  10. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  11. package/cjs/src/embed/ts-embed.js +11 -4
  12. package/cjs/src/embed/ts-embed.js.map +1 -1
  13. package/cjs/src/mixpanel-service.d.ts +1 -0
  14. package/cjs/src/mixpanel-service.d.ts.map +1 -1
  15. package/cjs/src/mixpanel-service.js +10 -3
  16. package/cjs/src/mixpanel-service.js.map +1 -1
  17. package/cjs/src/mixpanel-service.spec.js +12 -3
  18. package/cjs/src/mixpanel-service.spec.js.map +1 -1
  19. package/cjs/src/react/index.d.ts +14 -14
  20. package/cjs/src/react/index.d.ts.map +1 -1
  21. package/cjs/src/react/index.js +4 -2
  22. package/cjs/src/react/index.js.map +1 -1
  23. package/cjs/src/react/index.spec.js.map +1 -1
  24. package/dist/src/auth.d.ts.map +1 -1
  25. package/dist/src/embed/base.d.ts +2 -0
  26. package/dist/src/embed/base.d.ts.map +1 -1
  27. package/dist/src/embed/ts-embed.d.ts +3 -1
  28. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  29. package/dist/src/mixpanel-service.d.ts +1 -0
  30. package/dist/src/mixpanel-service.d.ts.map +1 -1
  31. package/dist/src/react/index.d.ts +14 -14
  32. package/dist/src/react/index.d.ts.map +1 -1
  33. package/dist/tsembed-react.es.js +29 -10
  34. package/dist/tsembed-react.js +29 -10
  35. package/dist/tsembed.es.js +29 -10
  36. package/dist/tsembed.js +29 -10
  37. package/dist/visual-embed-sdk-react-full.d.ts +240 -235
  38. package/dist/visual-embed-sdk-react.d.ts +240 -235
  39. package/dist/visual-embed-sdk.d.ts +5 -1
  40. package/lib/package.json +8 -7
  41. package/lib/src/.index.d.ts.swp +0 -0
  42. package/lib/src/auth.d.ts.map +1 -1
  43. package/lib/src/auth.js +3 -0
  44. package/lib/src/auth.js.map +1 -1
  45. package/lib/src/embed/base.d.ts +2 -0
  46. package/lib/src/embed/base.d.ts.map +1 -1
  47. package/lib/src/embed/base.js +4 -2
  48. package/lib/src/embed/base.js.map +1 -1
  49. package/lib/src/embed/ts-embed.d.ts +3 -1
  50. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  51. package/lib/src/embed/ts-embed.js +11 -4
  52. package/lib/src/embed/ts-embed.js.map +1 -1
  53. package/lib/src/mixpanel-service.d.ts +1 -0
  54. package/lib/src/mixpanel-service.d.ts.map +1 -1
  55. package/lib/src/mixpanel-service.js +10 -3
  56. package/lib/src/mixpanel-service.js.map +1 -1
  57. package/lib/src/mixpanel-service.spec.js +12 -3
  58. package/lib/src/mixpanel-service.spec.js.map +1 -1
  59. package/lib/src/react/index.d.ts +14 -14
  60. package/lib/src/react/index.d.ts.map +1 -1
  61. package/lib/src/react/index.js +4 -2
  62. package/lib/src/react/index.js.map +1 -1
  63. package/lib/src/react/index.spec.js +1 -1
  64. package/lib/src/react/index.spec.js.map +1 -1
  65. package/lib/src/visual-embed-sdk.d.ts +5 -1
  66. package/package.json +8 -7
  67. package/src/auth.ts +6 -3
  68. package/src/embed/base.ts +7 -5
  69. package/src/embed/ts-embed.ts +15 -3
  70. package/src/mixpanel-service.spec.ts +12 -3
  71. package/src/mixpanel-service.ts +10 -3
  72. package/src/react/index.spec.tsx +4 -2
  73. package/src/react/index.tsx +35 -26
@@ -280,11 +280,13 @@ declare module '@thoughtspot/visual-embed-sdk/embed/base' {
280
280
  */
281
281
  export const renderInQueue: (fn: (next?: (val?: any) => void) => Promise<any>) => Promise<any>;
282
282
  /**
283
+ * Imports TML representation of the metadata objects into ThoughtSpot.
283
284
  * @param data
284
285
  * @version SDK: 1.23.0 | ThoughtSpot: 9.4.0.cl
285
286
  */
286
287
  export const executeTML: (data: executeTMLInput) => Promise<any>;
287
288
  /**
289
+ * Exports TML representation of the metadata objects from ThoughtSpot in JSON or YAML format.
288
290
  * @param data
289
291
  * @version SDK: 1.23.0 | ThoughtSpot: 9.4.0.cl
290
292
  */
@@ -4259,6 +4261,8 @@ declare module '@thoughtspot/visual-embed-sdk/embed/ts-embed' {
4259
4261
  * @param messageType The message type
4260
4262
  * @param callback A callback as a function
4261
4263
  * @param options The message options
4264
+ * @param isSelf
4265
+ * @param isRegisteredBySDK
4262
4266
  * @example
4263
4267
  * ```js
4264
4268
  * tsEmbed.on(EmbedEvent.Error, (data) => {
@@ -4274,7 +4278,7 @@ declare module '@thoughtspot/visual-embed-sdk/embed/ts-embed' {
4274
4278
  * });
4275
4279
  * ```
4276
4280
  */
4277
- on(messageType: EmbedEvent, callback: MessageCallback, options?: MessageOptions): typeof TsEmbed.prototype;
4281
+ on(messageType: EmbedEvent, callback: MessageCallback, options?: MessageOptions, isRegisteredBySDK?: boolean): typeof TsEmbed.prototype;
4278
4282
  /**
4279
4283
  * Removes an event listener for a particular event type.
4280
4284
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thoughtspot/visual-embed-sdk",
3
- "version": "1.23.2",
3
+ "version": "1.23.3",
4
4
  "description": "ThoughtSpot Embed SDK",
5
5
  "module": "lib/src/index.js",
6
6
  "main": "dist/tsembed.js",
@@ -35,13 +35,12 @@
35
35
  ]
36
36
  }
37
37
  },
38
- "typesVersions": {
39
- "*": {
40
- "react": [
41
- "./lib/src/react/index.d.ts"
42
- ]
38
+ "size-limit": [
39
+ {
40
+ "path": "dist/tsembed.js",
41
+ "limit": "40 kB"
43
42
  }
44
- },
43
+ ],
45
44
  "scripts": {
46
45
  "lint": "eslint 'src/**'",
47
46
  "lint:fix": "eslint 'src/**/*.*' --fix",
@@ -66,6 +65,7 @@
66
65
  "posttest": "cat ./coverage/sdk/lcov.info | coveralls",
67
66
  "is-publish-allowed": "node scripts/is-publish-allowed.js",
68
67
  "prepublishOnly": "npm run is-publish-allowed && npm run test && npm run tsc && npm run bundle-dts-file && npm run bundle-dts && npm run bundle-dts-react && npm run bundle-dts-react-full && npm run build",
68
+ "check-size": "npm run build && size-limit",
69
69
  "publish-dev": "npm publish --tag dev",
70
70
  "publish-prod": "npm publish --tag latest"
71
71
  },
@@ -96,6 +96,7 @@
96
96
  "@rollup/plugin-json": "^4.1.0",
97
97
  "@rollup/plugin-node-resolve": "^11.2.1",
98
98
  "@rollup/plugin-replace": "^5.0.2",
99
+ "@size-limit/preset-big-lib": "^8.2.6",
99
100
  "@testing-library/dom": "^7.31.0",
100
101
  "@testing-library/jest-dom": "^5.14.1",
101
102
  "@testing-library/react": "^11.2.7",
package/src/auth.ts CHANGED
@@ -22,7 +22,7 @@ export let samlAuthWindow: Window = null;
22
22
  export let samlCompletionPromise: Promise<void> = null;
23
23
  let sessionInfo: sessionInfoInterface = null;
24
24
  let sessionInfoResolver: (value: sessionInfoInterface) => void = null;
25
- const sessionInfoPromise = new Promise((resolve:(value: sessionInfoInterface) => void) => {
25
+ const sessionInfoPromise = new Promise((resolve: (value: sessionInfoInterface) => void) => {
26
26
  sessionInfoResolver = resolve;
27
27
  });
28
28
  let releaseVersion = '';
@@ -44,7 +44,7 @@ interface sessionInfoInterface {
44
44
  userGUID: any;
45
45
  isPublicUser: any;
46
46
  mixpanelToken: any;
47
- [key:string]:any;
47
+ [key: string]: any;
48
48
  }
49
49
 
50
50
  /**
@@ -213,7 +213,7 @@ export const initSession = (sessionDetails: sessionInfoInterface) => {
213
213
  }
214
214
  };
215
215
 
216
- export const getSessionDetails = (sessionInfoResp: any):sessionInfoInterface => {
216
+ export const getSessionDetails = (sessionInfoResp: any): sessionInfoInterface => {
217
217
  const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
218
218
  const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
219
219
  const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
@@ -223,6 +223,9 @@ export const getSessionDetails = (sessionInfoResp: any):sessionInfoInterface =>
223
223
  userGUID: sessionInfoResp.userGUID,
224
224
  mixpanelToken,
225
225
  isPublicUser: sessionInfoResp.configInfo.isPublicUser,
226
+ releaseVersion: sessionInfoResp.releaseVersion,
227
+ clusterId: sessionInfoResp.configInfo.selfClusterId,
228
+ clusterName: sessionInfoResp.configInfo.selfClusterName,
226
229
  ...sessionInfoResp,
227
230
  };
228
231
  };
package/src/embed/base.ts CHANGED
@@ -44,13 +44,13 @@ export interface executeTMLInput {
44
44
 
45
45
  export interface exportTMLInput {
46
46
  metadata: {
47
- identifier: string;
48
- type?: 'LIVEBOARD' | 'ANSWER' | 'LOGICAL_TABLE' | 'CONNECTION';
47
+ identifier: string;
48
+ type?: 'LIVEBOARD' | 'ANSWER' | 'LOGICAL_TABLE' | 'CONNECTION';
49
49
  }[];
50
50
  export_associated?: boolean;
51
51
  export_fqn?: boolean;
52
52
  edoc_format?: 'YAML' | 'JSON';
53
- }
53
+ }
54
54
 
55
55
  export let authPromise: Promise<boolean>;
56
56
  /**
@@ -192,9 +192,9 @@ export const init = (embedConfig: EmbedConfig): AuthEventEmitter => {
192
192
  setAuthEE(authEE);
193
193
  handleAuth();
194
194
 
195
+ const { password, ...configToTrack } = config;
195
196
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_CALLED_INIT, {
196
- authType: config.authType,
197
- host: config.thoughtSpotHost,
197
+ ...configToTrack,
198
198
  usedCustomizationSheet: embedConfig.customizations?.style?.customCSSUrl != null,
199
199
  usedCustomizationVariables: embedConfig.customizations?.style?.customCSS?.variables != null,
200
200
  usedCustomizationRules:
@@ -257,6 +257,7 @@ export const renderInQueue = (fn: (next?: (val?: any) => void) => Promise<any>):
257
257
  };
258
258
 
259
259
  /**
260
+ * Imports TML representation of the metadata objects into ThoughtSpot.
260
261
  * @param data
261
262
  * @version SDK: 1.23.0 | ThoughtSpot: 9.4.0.cl
262
263
  */
@@ -304,6 +305,7 @@ export const executeTML = async (data: executeTMLInput): Promise<any> => {
304
305
  };
305
306
 
306
307
  /**
308
+ * Exports TML representation of the metadata objects from ThoughtSpot in JSON or YAML format.
307
309
  * @param data
308
310
  * @version SDK: 1.23.0 | ThoughtSpot: 9.4.0.cl
309
311
  */
@@ -156,6 +156,9 @@ export class TsEmbed {
156
156
  this.viewConfig = viewConfig;
157
157
  this.shouldEncodeUrlQueryParams = this.embedConfig.shouldEncodeUrlQueryParams;
158
158
  this.registerAppInit();
159
+ uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_EMBED_CREATE, {
160
+ ...viewConfig,
161
+ });
159
162
  }
160
163
 
161
164
  /**
@@ -299,8 +302,12 @@ export class TsEmbed {
299
302
  * Register APP_INIT event and sendback init payload
300
303
  */
301
304
  private registerAppInit = () => {
302
- this.on(EmbedEvent.APP_INIT, this.appInitCb);
303
- this.on(EmbedEvent.AuthExpire, this.updateAuthToken);
305
+ this.on(
306
+ EmbedEvent.APP_INIT, this.appInitCb, { start: false }, true,
307
+ );
308
+ this.on(
309
+ EmbedEvent.AuthExpire, this.updateAuthToken, { start: false }, true,
310
+ );
304
311
  };
305
312
 
306
313
  /**
@@ -711,6 +718,8 @@ export class TsEmbed {
711
718
  * @param messageType The message type
712
719
  * @param callback A callback as a function
713
720
  * @param options The message options
721
+ * @param isSelf
722
+ * @param isRegisteredBySDK
714
723
  * @example
715
724
  * ```js
716
725
  * tsEmbed.on(EmbedEvent.Error, (data) => {
@@ -730,7 +739,11 @@ export class TsEmbed {
730
739
  messageType: EmbedEvent,
731
740
  callback: MessageCallback,
732
741
  options: MessageOptions = { start: false },
742
+ isRegisteredBySDK = false,
733
743
  ): typeof TsEmbed.prototype {
744
+ uploadMixpanelEvent(`${MIXPANEL_EVENT.VISUAL_SDK_ON}-${messageType}`, {
745
+ isRegisteredBySDK,
746
+ });
734
747
  if (this.isRendered) {
735
748
  this.handleError('Please register event handlers before calling render');
736
749
  }
@@ -929,7 +942,6 @@ export class V1Embed extends TsEmbed {
929
942
  options: MessageOptions = { start: false },
930
943
  ): typeof TsEmbed.prototype {
931
944
  const eventType = this.getCompatibleEventType(messageType);
932
- uploadMixpanelEvent(`${MIXPANEL_EVENT.VISUAL_SDK_ON}-${messageType}`);
933
945
  return super.on(eventType, callback, options);
934
946
  }
935
947
  }
@@ -14,9 +14,10 @@ const config = {
14
14
 
15
15
  jest.mock('mixpanel-browser', () => ({
16
16
  __esModule: true,
17
- init: jest.fn(),
17
+ init: jest.fn().mockReturnThis(),
18
18
  identify: jest.fn(),
19
19
  track: jest.fn(),
20
+ register_once: jest.fn(),
20
21
  }));
21
22
 
22
23
  describe('Unit test for mixpanel', () => {
@@ -30,7 +31,7 @@ describe('Unit test for mixpanel', () => {
30
31
  isPublicUser: false,
31
32
  };
32
33
  initMixpanel(sessionInfo);
33
- expect(mixpanel.init).toHaveBeenCalledWith(sessionInfo.mixpanelToken);
34
+ expect(mixpanel.init).toHaveBeenCalledWith(sessionInfo.mixpanelToken, undefined, 'tsEmbed');
34
35
  expect(mixpanel.identify).toHaveBeenCalledWith(sessionInfo.userGUID);
35
36
 
36
37
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_CALLED_INIT, {
@@ -45,10 +46,18 @@ describe('Unit test for mixpanel', () => {
45
46
  mixpanelToken: 'newToken',
46
47
  isPublicUser: true,
47
48
  userGUID: 'newUser',
49
+ clusterId: 'newClusterId',
50
+ clusterName: 'newClusterName',
51
+ releaseVersion: 'newReleaseVersion',
48
52
  };
49
53
  initMixpanel(sessionInfo);
50
54
 
51
- expect(mixpanel.init).toHaveBeenCalledWith(sessionInfo.mixpanelToken);
55
+ expect(mixpanel.init).toHaveBeenCalledWith(sessionInfo.mixpanelToken, undefined, 'tsEmbed');
56
+ expect(mixpanel.register_once).toHaveBeenCalledWith({
57
+ clusterId: sessionInfo.clusterId,
58
+ clusterName: sessionInfo.clusterName,
59
+ releaseVersion: sessionInfo.releaseVersion,
60
+ });
52
61
  expect(mixpanel.identify).not.toHaveBeenCalledWith(sessionInfo.userGUID);
53
62
  });
54
63
 
@@ -6,6 +6,7 @@ export const EndPoints = {
6
6
 
7
7
  // Needed to avoid error in CJS builds on some bundlers.
8
8
  const mixpanelLib = mixpanel.default || mixpanel;
9
+ let mixpanelInstance: mixpanel.Mixpanel;
9
10
 
10
11
  export const MIXPANEL_EVENT = {
11
12
  VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
@@ -15,6 +16,7 @@ export const MIXPANEL_EVENT = {
15
16
  VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
16
17
  VISUAL_SDK_ON: 'visual-sdk-on',
17
18
  VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
19
+ VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
18
20
  };
19
21
 
20
22
  let isMixpanelInitialized = false;
@@ -31,7 +33,7 @@ export function uploadMixpanelEvent(eventId: string, eventProps = {}): void {
31
33
  eventQueue.push({ eventId, eventProps });
32
34
  return;
33
35
  }
34
- mixpanelLib.track(eventId, eventProps);
36
+ mixpanelInstance.track(eventId, eventProps);
35
37
  }
36
38
 
37
39
  /**
@@ -61,10 +63,15 @@ export function initMixpanel(sessionInfo: any): void {
61
63
  const token = sessionInfo.mixpanelToken;
62
64
  try {
63
65
  if (token) {
64
- mixpanelLib.init(token);
66
+ mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
65
67
  if (!isPublicCluster) {
66
- mixpanelLib.identify(sessionInfo.userGUID);
68
+ mixpanelInstance.identify(sessionInfo.userGUID);
67
69
  }
70
+ mixpanelInstance.register_once({
71
+ clusterId: sessionInfo.clusterId,
72
+ clusterName: sessionInfo.clusterName,
73
+ releaseVersion: sessionInfo.releaseVersion,
74
+ });
68
75
  isMixpanelInitialized = true;
69
76
  emptyQueue();
70
77
  }
@@ -18,7 +18,9 @@ import {
18
18
  SearchEmbed, AppEmbed, LiveboardEmbed, useEmbedRef, SearchBarEmbed,
19
19
  } from './index';
20
20
  import * as allExports from './index';
21
- import { AuthType, init } from '../index';
21
+ import {
22
+ AuthType, init,
23
+ } from '../index';
22
24
 
23
25
  import { version } from '../../package.json';
24
26
 
@@ -85,7 +87,7 @@ describe('React Components', () => {
85
87
  it('Should be able to trigger events on the embed using refs', async () => {
86
88
  mockMessageChannel();
87
89
  const TestComponent = () => {
88
- const embedRef = useEmbedRef();
90
+ const embedRef = useEmbedRef<typeof LiveboardEmbed>();
89
91
  const onLiveboardRendered = () => {
90
92
  embedRef.current.trigger(HostEvent.SetVisibleVizs, ['viz1', 'viz2']);
91
93
  };
@@ -13,33 +13,33 @@ import { EmbedProps, getViewPropsAndListeners } from './util';
13
13
 
14
14
  const componentFactory = <T extends typeof TsEmbed, U extends EmbedProps, V extends ViewConfig>(
15
15
  EmbedConstructor: T,
16
- ) => React.forwardRef<TsEmbed, U>(
17
- (props: U, forwardedRef: React.MutableRefObject<TsEmbed>) => {
16
+ ) => React.forwardRef<InstanceType<T>, U>(
17
+ (props: U, forwardedRef: React.MutableRefObject<InstanceType<T>>) => {
18
18
  const ref = React.useRef<HTMLDivElement>(null);
19
19
  const { className, ...embedProps } = props;
20
20
  const { viewConfig, listeners } = getViewPropsAndListeners<
21
- Omit<U, 'className'>,
22
- V
23
- >(embedProps);
21
+ Omit<U, 'className'>,
22
+ V
23
+ >(embedProps);
24
24
  useDeepCompareEffect(() => {
25
25
  const tsEmbed = new EmbedConstructor(
26
- ref!.current,
27
- deepMerge(
28
- {
29
- insertAsSibling: viewConfig.insertAsSibling,
30
- frameParams: {
31
- class: viewConfig.insertAsSibling
32
- ? className || ''
33
- : '',
34
- },
26
+ ref!.current,
27
+ deepMerge(
28
+ {
29
+ insertAsSibling: viewConfig.insertAsSibling,
30
+ frameParams: {
31
+ class: viewConfig.insertAsSibling
32
+ ? className || ''
33
+ : '',
35
34
  },
36
- viewConfig,
37
- ),
38
- );
35
+ },
36
+ viewConfig,
37
+ ),
38
+ ) as InstanceType<T>;
39
39
  Object.keys(listeners).forEach((eventName) => {
40
40
  tsEmbed.on(
41
- eventName as EmbedEvent,
42
- listeners[eventName as EmbedEvent],
41
+ eventName as EmbedEvent,
42
+ listeners[eventName as EmbedEvent],
43
43
  );
44
44
  });
45
45
  tsEmbed.render();
@@ -68,7 +68,7 @@ const componentFactory = <T extends typeof TsEmbed, U extends EmbedProps, V exte
68
68
  },
69
69
  );
70
70
 
71
- interface SearchProps extends EmbedProps, SearchViewConfig {}
71
+ interface SearchProps extends EmbedProps, SearchViewConfig { }
72
72
 
73
73
  /**
74
74
  * React component for Search Embed.
@@ -87,7 +87,7 @@ export const SearchEmbed = componentFactory<typeof _SearchEmbed, SearchProps, Se
87
87
  _SearchEmbed,
88
88
  );
89
89
 
90
- interface AppProps extends EmbedProps, AppViewConfig {}
90
+ interface AppProps extends EmbedProps, AppViewConfig { }
91
91
 
92
92
  /**
93
93
  * React component for Full app Embed.
@@ -105,7 +105,7 @@ interface AppProps extends EmbedProps, AppViewConfig {}
105
105
  */
106
106
  export const AppEmbed = componentFactory<typeof _AppEmbed, AppProps, AppViewConfig>(_AppEmbed);
107
107
 
108
- interface LiveboardProps extends EmbedProps, LiveboardViewConfig {}
108
+ interface LiveboardProps extends EmbedProps, LiveboardViewConfig { }
109
109
 
110
110
  /**
111
111
  * React component for Liveboard embed.
@@ -130,7 +130,7 @@ export const LiveboardEmbed = componentFactory<
130
130
 
131
131
  export const PinboardEmbed = LiveboardEmbed;
132
132
 
133
- interface SearchBarEmbedProps extends EmbedProps, SearchBarViewConfig {}
133
+ interface SearchBarEmbedProps extends EmbedProps, SearchBarViewConfig { }
134
134
 
135
135
  /**
136
136
  * React component for Search bar embed.
@@ -151,7 +151,7 @@ export const SearchBarEmbed = componentFactory<
151
151
  SearchBarViewConfig
152
152
  >(_SearchBarEmbed);
153
153
 
154
- interface SageEmbedProps extends EmbedProps, SageViewConfig {}
154
+ interface SageEmbedProps extends EmbedProps, SageViewConfig { }
155
155
 
156
156
  /**
157
157
  * React component for LLM based search Sage embed.
@@ -172,6 +172,12 @@ export const SageEmbed = componentFactory<
172
172
  SageViewConfig
173
173
  >(_SageEmbed);
174
174
 
175
+ type EmbedComponent = typeof SearchEmbed
176
+ | typeof AppEmbed
177
+ | typeof LiveboardEmbed
178
+ | typeof SearchBarEmbed
179
+ | typeof SageEmbed;
180
+
175
181
  /**
176
182
  * Get a reference to the embed component to trigger events on the component.
177
183
  *
@@ -187,9 +193,12 @@ export const SageEmbed = componentFactory<
187
193
  * return <LiveboardEmbed ref={ref} liveboardId={<id>} />
188
194
  * }
189
195
  * ```
190
- * @returns {React.MutableRefObject<TsEmbed>} ref
196
+ * @returns {React.MutableRefObject<T extends TsEmbed>} ref
191
197
  */
192
- export const useEmbedRef = (): React.MutableRefObject<TsEmbed> => React.useRef<TsEmbed>(null);
198
+ export function useEmbedRef<T extends EmbedComponent>():
199
+ React.MutableRefObject<React.ComponentRef<T>> {
200
+ return React.useRef<React.ComponentRef<T>>(null);
201
+ }
193
202
 
194
203
  export {
195
204
  LiveboardViewConfig,