@thoughtspot/visual-embed-sdk 1.49.1 → 1.49.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 (151) hide show
  1. package/cjs/package.json +4 -10
  2. package/cjs/src/css-variables.d.ts +17 -0
  3. package/cjs/src/css-variables.d.ts.map +1 -1
  4. package/cjs/src/embed/app.d.ts +7 -1
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +4 -1
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +97 -0
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/conversation.d.ts +8 -0
  11. package/cjs/src/embed/conversation.d.ts.map +1 -1
  12. package/cjs/src/embed/conversation.js +2 -1
  13. package/cjs/src/embed/conversation.js.map +1 -1
  14. package/cjs/src/embed/conversation.spec.js +12 -0
  15. package/cjs/src/embed/conversation.spec.js.map +1 -1
  16. package/cjs/src/embed/events.spec.js +5 -0
  17. package/cjs/src/embed/events.spec.js.map +1 -1
  18. package/cjs/src/embed/liveboard.d.ts +6 -0
  19. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  20. package/cjs/src/embed/liveboard.js +4 -1
  21. package/cjs/src/embed/liveboard.js.map +1 -1
  22. package/cjs/src/embed/liveboard.spec.js +11 -0
  23. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  24. package/cjs/src/embed/spotter-viz-utils.d.ts +29 -0
  25. package/cjs/src/embed/spotter-viz-utils.d.ts.map +1 -1
  26. package/cjs/src/embed/spotter-viz-utils.js.map +1 -1
  27. package/cjs/src/embed/ts-embed.d.ts +38 -0
  28. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  29. package/cjs/src/embed/ts-embed.js +166 -9
  30. package/cjs/src/embed/ts-embed.js.map +1 -1
  31. package/cjs/src/embed/ts-embed.spec.js +237 -0
  32. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  33. package/cjs/src/index.d.ts +2 -2
  34. package/cjs/src/index.d.ts.map +1 -1
  35. package/cjs/src/index.js.map +1 -1
  36. package/cjs/src/types.d.ts +87 -4
  37. package/cjs/src/types.d.ts.map +1 -1
  38. package/cjs/src/types.js +47 -3
  39. package/cjs/src/types.js.map +1 -1
  40. package/cjs/src/utils/graphql/answerService/answerService.spec.js +15 -0
  41. package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  42. package/cjs/src/utils/processTrigger.d.ts.map +1 -1
  43. package/cjs/src/utils/processTrigger.js +6 -5
  44. package/cjs/src/utils/processTrigger.js.map +1 -1
  45. package/cjs/src/utils/processTrigger.spec.js +13 -0
  46. package/cjs/src/utils/processTrigger.spec.js.map +1 -1
  47. package/cjs/src/utils.d.ts +10 -0
  48. package/cjs/src/utils.d.ts.map +1 -1
  49. package/cjs/src/utils.js +25 -4
  50. package/cjs/src/utils.js.map +1 -1
  51. package/cjs/src/utils.spec.js +48 -0
  52. package/cjs/src/utils.spec.js.map +1 -1
  53. package/dist/{index-B6Rn561t.js → index-DsSQndIB.js} +303 -187
  54. package/dist/src/css-variables.d.ts +17 -0
  55. package/dist/src/css-variables.d.ts.map +1 -1
  56. package/dist/src/embed/app.d.ts +7 -1
  57. package/dist/src/embed/app.d.ts.map +1 -1
  58. package/dist/src/embed/conversation.d.ts +8 -0
  59. package/dist/src/embed/conversation.d.ts.map +1 -1
  60. package/dist/src/embed/liveboard.d.ts +6 -0
  61. package/dist/src/embed/liveboard.d.ts.map +1 -1
  62. package/dist/src/embed/spotter-viz-utils.d.ts +29 -0
  63. package/dist/src/embed/spotter-viz-utils.d.ts.map +1 -1
  64. package/dist/src/embed/ts-embed.d.ts +38 -0
  65. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  66. package/dist/src/index.d.ts +2 -2
  67. package/dist/src/index.d.ts.map +1 -1
  68. package/dist/src/types.d.ts +87 -4
  69. package/dist/src/types.d.ts.map +1 -1
  70. package/dist/src/utils/processTrigger.d.ts.map +1 -1
  71. package/dist/src/utils.d.ts +10 -0
  72. package/dist/src/utils.d.ts.map +1 -1
  73. package/dist/tsembed-react.es.js +282 -35
  74. package/dist/tsembed-react.js +583 -220
  75. package/dist/tsembed.es.js +282 -35
  76. package/dist/tsembed.js +583 -220
  77. package/dist/visual-embed-sdk-react-full.d.ts +190 -4
  78. package/dist/visual-embed-sdk-react.d.ts +190 -4
  79. package/dist/visual-embed-sdk.d.ts +190 -4
  80. package/lib/package.json +4 -10
  81. package/lib/src/css-variables.d.ts +17 -0
  82. package/lib/src/css-variables.d.ts.map +1 -1
  83. package/lib/src/embed/app.d.ts +7 -1
  84. package/lib/src/embed/app.d.ts.map +1 -1
  85. package/lib/src/embed/app.js +4 -1
  86. package/lib/src/embed/app.js.map +1 -1
  87. package/lib/src/embed/app.spec.js +97 -0
  88. package/lib/src/embed/app.spec.js.map +1 -1
  89. package/lib/src/embed/conversation.d.ts +8 -0
  90. package/lib/src/embed/conversation.d.ts.map +1 -1
  91. package/lib/src/embed/conversation.js +2 -1
  92. package/lib/src/embed/conversation.js.map +1 -1
  93. package/lib/src/embed/conversation.spec.js +12 -0
  94. package/lib/src/embed/conversation.spec.js.map +1 -1
  95. package/lib/src/embed/events.spec.js +5 -0
  96. package/lib/src/embed/events.spec.js.map +1 -1
  97. package/lib/src/embed/liveboard.d.ts +6 -0
  98. package/lib/src/embed/liveboard.d.ts.map +1 -1
  99. package/lib/src/embed/liveboard.js +4 -1
  100. package/lib/src/embed/liveboard.js.map +1 -1
  101. package/lib/src/embed/liveboard.spec.js +11 -0
  102. package/lib/src/embed/liveboard.spec.js.map +1 -1
  103. package/lib/src/embed/spotter-viz-utils.d.ts +29 -0
  104. package/lib/src/embed/spotter-viz-utils.d.ts.map +1 -1
  105. package/lib/src/embed/spotter-viz-utils.js.map +1 -1
  106. package/lib/src/embed/ts-embed.d.ts +38 -0
  107. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  108. package/lib/src/embed/ts-embed.js +167 -10
  109. package/lib/src/embed/ts-embed.js.map +1 -1
  110. package/lib/src/embed/ts-embed.spec.js +237 -0
  111. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  112. package/lib/src/index.d.ts +2 -2
  113. package/lib/src/index.d.ts.map +1 -1
  114. package/lib/src/index.js.map +1 -1
  115. package/lib/src/types.d.ts +87 -4
  116. package/lib/src/types.d.ts.map +1 -1
  117. package/lib/src/types.js +47 -3
  118. package/lib/src/types.js.map +1 -1
  119. package/lib/src/utils/graphql/answerService/answerService.spec.js +15 -0
  120. package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  121. package/lib/src/utils/processTrigger.d.ts.map +1 -1
  122. package/lib/src/utils/processTrigger.js +6 -5
  123. package/lib/src/utils/processTrigger.js.map +1 -1
  124. package/lib/src/utils/processTrigger.spec.js +13 -0
  125. package/lib/src/utils/processTrigger.spec.js.map +1 -1
  126. package/lib/src/utils.d.ts +10 -0
  127. package/lib/src/utils.d.ts.map +1 -1
  128. package/lib/src/utils.js +22 -1
  129. package/lib/src/utils.js.map +1 -1
  130. package/lib/src/utils.spec.js +49 -1
  131. package/lib/src/utils.spec.js.map +1 -1
  132. package/lib/src/visual-embed-sdk.d.ts +190 -4
  133. package/package.json +4 -10
  134. package/src/css-variables.ts +20 -0
  135. package/src/embed/app.spec.ts +109 -0
  136. package/src/embed/app.ts +11 -1
  137. package/src/embed/conversation.spec.ts +17 -0
  138. package/src/embed/conversation.ts +10 -0
  139. package/src/embed/events.spec.ts +7 -0
  140. package/src/embed/liveboard.spec.ts +15 -0
  141. package/src/embed/liveboard.ts +10 -0
  142. package/src/embed/spotter-viz-utils.ts +30 -0
  143. package/src/embed/ts-embed.spec.ts +294 -0
  144. package/src/embed/ts-embed.ts +180 -9
  145. package/src/index.ts +2 -1
  146. package/src/types.ts +86 -3
  147. package/src/utils/graphql/answerService/answerService.spec.ts +18 -0
  148. package/src/utils/processTrigger.spec.ts +23 -0
  149. package/src/utils/processTrigger.ts +8 -6
  150. package/src/utils.spec.ts +63 -0
  151. package/src/utils.ts +25 -1
package/src/types.ts CHANGED
@@ -1108,6 +1108,45 @@ export interface BaseViewConfig extends ApiInterceptFlags {
1108
1108
  * ```
1109
1109
  */
1110
1110
  doNotTrackPreRenderSize?: boolean;
1111
+ /**
1112
+ * The DOM element or CSS selector string specifying the container into which
1113
+ * the pre-rendered wrapper is inserted. Defaults to `document.body` when not
1114
+ * specified.
1115
+ *
1116
+ * **When to use a target container:** set this when the pre-render should
1117
+ * live somewhere other than `document.body` — for example when `<body>` has
1118
+ * `overflow: hidden` and scrolling is handled by an inner element, or when
1119
+ * you need the wrapper to sit inside a specific stacking/positioning context.
1120
+ * The wrapper is positioned to track the embedding element within this
1121
+ * container, so choose the scrollable/positioned ancestor you want it
1122
+ * aligned to.
1123
+ *
1124
+ * **Pass a stable container:** the wrapper is mounted into the resolved
1125
+ * container once, during `preRender()`. The container must stay mounted for
1126
+ * the lifetime of the pre-render — if the host app unmounts and remounts it
1127
+ * (for example React replacing the node), the wrapper is orphaned on the
1128
+ * detached node. Mount the container above the part of the tree that
1129
+ * re-renders so its identity is stable. Prefer a CSS selector string over a
1130
+ * raw element: a selector can be re-resolved to the fresh node on the next
1131
+ * reposition, whereas an element reference cannot be recovered once detached.
1132
+ *
1133
+ * When the embed host lives inside a Shadow DOM, a selector string is
1134
+ * resolved against that shadow root as well (since `document.querySelector`
1135
+ * cannot pierce shadow boundaries); pass the element directly if the
1136
+ * container lives in a different root.
1137
+ *
1138
+ * @type {string | HTMLElement}
1139
+ * @version SDK: 1.49.2 | ThoughtSpot: *
1140
+ * @example
1141
+ * ```js
1142
+ * const embed = new LiveboardEmbed('#tsEmbed', {
1143
+ * preRenderId: 'my-liveboard',
1144
+ * // Prefer a selector for a stable, scrollable container.
1145
+ * preRenderContainer: '#my-scroll-container',
1146
+ * });
1147
+ * ```
1148
+ */
1149
+ preRenderContainer?: string | HTMLElement;
1111
1150
  /**
1112
1151
  * Enable the V2 shell. This can provide performance benefits
1113
1152
  * due to a lighter-weight shell.
@@ -4150,11 +4189,30 @@ export enum HostEvent {
4150
4189
  /**
4151
4190
  * Navigate to a specific page in the embedded ThoughtSpot application.
4152
4191
  * This is the same as calling `appEmbed.navigateToPage(path, true)`.
4153
- * @param - `path` - the path to navigate to go forward or back. The path value can
4154
- * be a number; for example, `1`, `-1`.
4192
+ *
4193
+ * Accepts either a plain value or an object with `path`
4194
+ * and an optional `replace` flag.
4195
+ *
4196
+ * @param data - A string path, a numeric history delta, or an object
4197
+ * `{ path: string | number, replace?: boolean }`.
4198
+ * - `path` — the route to navigate to, or a history delta such as `1`
4199
+ * or `-1` (calls `window.history.go()`).
4200
+ * - `replace` — when `true`, replaces the current history entry instead
4201
+ * of pushing a new one (uses `window.location.replace`).
4202
+ *
4155
4203
  * @example
4156
4204
  * ```js
4157
- * appEmbed.navigateToPage(-1)
4205
+ * // Preferred: use navigateToPage directly
4206
+ * appEmbed.navigateToPage(-1);
4207
+ *
4208
+ * // Numeric delta — go back one step
4209
+ * appEmbed.trigger(HostEvent.Navigate, -1);
4210
+ *
4211
+ * // String path — push a new history entry
4212
+ * appEmbed.trigger(HostEvent.Navigate, 'home');
4213
+ *
4214
+ * // Object format — replace current history entry
4215
+ * appEmbed.trigger(HostEvent.Navigate, { path: 'home', replace: true }); // SDK: 1.51.0 | ThoughtSpot Cloud: 26.8.0.cl
4158
4216
  * ```
4159
4217
  * @version SDK: 1.12.0 | ThoughtSpot: 8.4.0.cl, 8.4.1.sw
4160
4218
  */
@@ -6149,6 +6207,7 @@ export enum Param {
6149
6207
  EnableLiveboardDataCache = 'enableLiveboardDataCache',
6150
6208
  SpotterFileUploadEnabled = 'spotterFileUploadEnabled',
6151
6209
  SpotterFileUploadFileTypes = 'spotterFileUploadFileTypes',
6210
+ IsStarterPromptsEnabled = 'enableStarterPrompts',
6152
6211
  }
6153
6212
 
6154
6213
  /**
@@ -6801,6 +6860,16 @@ export enum Action {
6801
6860
  * @version SDK: 1.9.0 | ThoughtSpot: 8.1.0.cl, 8.4.1.sw
6802
6861
  */
6803
6862
  AddToFavorites = 'addToFavorites',
6863
+ /**
6864
+ * Remove from Favorites option in home page v3 sidebar.
6865
+ * Allows removing an object from the user's favorites list from home-page v3 sidebar.
6866
+ * @version SDK: 1.51.0 | ThoughtSpot Cloud: 26.8.0.cl
6867
+ * @example
6868
+ * ```js
6869
+ * disabledActions: [Action.RemoveFromFavorites]
6870
+ * ```
6871
+ */
6872
+ RemoveFromFavorites = 'removeFromFavorites',
6804
6873
  /**
6805
6874
  * The edit icon on Liveboards (Classic experience).
6806
6875
  * @example
@@ -7879,6 +7948,20 @@ export enum Action {
7879
7948
  * ```
7880
7949
  */
7881
7950
  SpotterViz = 'spotterViz',
7951
+ /**
7952
+ * The reference-mode toggle button inside the SpotterViz chat input.
7953
+ * When users enable reference mode, clicking tiles, filters, or
7954
+ * parameters adds them as chat context. Hide this action to remove
7955
+ * the reference-mode capability entirely.
7956
+ * Visible by default.
7957
+ * @version SDK: 1.51.0 | ThoughtSpot Cloud: 26.8.0.cl
7958
+ * @example
7959
+ * ```js
7960
+ * hiddenActions: [Action.SpotterVizReferenceMode]
7961
+ * disabledActions: [Action.SpotterVizReferenceMode]
7962
+ * ```
7963
+ */
7964
+ SpotterVizReferenceMode = 'spotterVizReferenceMode',
7882
7965
  /**
7883
7966
  * Clears browser cache and fetches new data for liveboard ChartViz Containers.
7884
7967
  * Requires `enableLiveboardDataCache` to be enabled.
@@ -707,4 +707,22 @@ describe('Answer service tests', () => {
707
707
  expect(answer.name).toBe('name');
708
708
  expect(answer.id).toBe('bar');
709
709
  });
710
+
711
+ test('getTML parses nested objects and arrays from the YAML edoc', async () => {
712
+ const edoc = [
713
+ 'answer:',
714
+ ' name: Revenue answer',
715
+ ' visualizations:',
716
+ ' - id: viz-1',
717
+ ' type: TABLE',
718
+ ].join('\n');
719
+ fetchMock.mockResponseOnce(JSON.stringify({
720
+ data: { UnsavedAnswer_getTML: { object: [{ edoc }] } },
721
+ }));
722
+
723
+ const { answer } = await createAnswerService().getTML();
724
+
725
+ expect(answer.name).toBe('Revenue answer');
726
+ expect(answer.visualizations).toEqual([{ id: 'viz-1', type: 'TABLE' }]);
727
+ });
710
728
  });
@@ -94,6 +94,29 @@ describe('Unit test for processTrigger', () => {
94
94
  await expect(triggerPromise).resolves.toEqual(null);
95
95
  });
96
96
 
97
+ test('should clear the timeout when response arrives before TRIGGER_TIMEOUT', async () => {
98
+ const messageType = HostEvent.Search;
99
+ const thoughtSpotHost = 'http://localhost:3000';
100
+ const data = {};
101
+ mockMessageChannel();
102
+ const clearTimeoutSpy = jest.spyOn(global, 'clearTimeout');
103
+
104
+ const triggerPromise = _processTriggerInstance.processTrigger(
105
+ iFrame,
106
+ messageType,
107
+ thoughtSpotHost,
108
+ data,
109
+ );
110
+
111
+ const res = { data: { test: '123' } };
112
+ messageChannelMock.port1.onmessage(res);
113
+
114
+ expect(clearTimeoutSpy).toHaveBeenCalled();
115
+ await expect(triggerPromise).resolves.toEqual(res.data);
116
+
117
+ clearTimeoutSpy.mockRestore();
118
+ });
119
+
97
120
  test('should close channel.port1 when timeout exceeds TRIGGER_TIMEOUT', async () => {
98
121
  const messageType = HostEvent.Search;
99
122
  const thoughtSpotHost = 'http://localhost:3000';
@@ -70,7 +70,15 @@ export function processTrigger(
70
70
  }
71
71
 
72
72
  const channel = new MessageChannel();
73
+
74
+ // Close the messageChannel and resolve the promise if timeout.
75
+ const timeoutId = setTimeout(() => {
76
+ channel.port1.close();
77
+ res(new Error(ERROR_MESSAGE.TRIGGER_TIMED_OUT));
78
+ }, TRIGGER_TIMEOUT);
79
+
73
80
  channel.port1.onmessage = ({ data: responseData }) => {
81
+ clearTimeout(timeoutId);
74
82
  channel.port1.close();
75
83
  const error = responseData?.error || responseData?.data?.error;
76
84
  if (error) {
@@ -80,12 +88,6 @@ export function processTrigger(
80
88
  }
81
89
  };
82
90
 
83
- // Close the messageChannel and resolve the promise if timeout.
84
- setTimeout(() => {
85
- channel.port1.close();
86
- res(new Error(ERROR_MESSAGE.TRIGGER_TIMED_OUT));
87
- }, TRIGGER_TIMEOUT);
88
-
89
91
  return postIframeMessage(iFrame, { type: messageType, data, context }, thoughtSpotHost, channel);
90
92
  });
91
93
  }
package/src/utils.spec.ts CHANGED
@@ -26,6 +26,7 @@ import {
26
26
  resetValueFromWindow,
27
27
  validateHttpUrl,
28
28
  setParamIfDefined,
29
+ querySelectorAcrossShadowRoot,
29
30
  } from './utils';
30
31
  import { RuntimeFilterOp } from './types';
31
32
  import { logger } from './utils/logger';
@@ -855,6 +856,68 @@ describe('getClippingAncestors', () => {
855
856
  });
856
857
  });
857
858
 
859
+ describe('querySelectorAcrossShadowRoot', () => {
860
+ it('should resolve a selector from the light DOM document', () => {
861
+ const el = document.createElement('div');
862
+ el.id = 'light-dom-target';
863
+ document.body.appendChild(el);
864
+
865
+ expect(querySelectorAcrossShadowRoot('#light-dom-target')).toBe(el);
866
+
867
+ el.remove();
868
+ });
869
+
870
+ it('should resolve a selector inside the reference node shadow root when the document misses', () => {
871
+ const host = document.createElement('div');
872
+ document.body.appendChild(host);
873
+ const shadow = host.attachShadow({ mode: 'open' });
874
+ const container = document.createElement('div');
875
+ container.id = 'shadow-target';
876
+ const reference = document.createElement('div');
877
+ shadow.appendChild(container);
878
+ shadow.appendChild(reference);
879
+
880
+ // document.querySelector cannot see into the shadow root.
881
+ expect(document.querySelector('#shadow-target')).toBeNull();
882
+ expect(querySelectorAcrossShadowRoot('#shadow-target', reference)).toBe(container);
883
+
884
+ host.remove();
885
+ });
886
+
887
+ it('should prefer the document match over the shadow root', () => {
888
+ const lightEl = document.createElement('div');
889
+ lightEl.id = 'shared-id';
890
+ document.body.appendChild(lightEl);
891
+
892
+ const host = document.createElement('div');
893
+ document.body.appendChild(host);
894
+ const shadow = host.attachShadow({ mode: 'open' });
895
+ const shadowEl = document.createElement('div');
896
+ shadowEl.id = 'shared-id';
897
+ const reference = document.createElement('div');
898
+ shadow.appendChild(shadowEl);
899
+ shadow.appendChild(reference);
900
+
901
+ expect(querySelectorAcrossShadowRoot('#shared-id', reference)).toBe(lightEl);
902
+
903
+ lightEl.remove();
904
+ host.remove();
905
+ });
906
+
907
+ it('should return null when nothing matches and the reference node is in the light DOM', () => {
908
+ const reference = document.createElement('div');
909
+ document.body.appendChild(reference);
910
+
911
+ expect(querySelectorAcrossShadowRoot('#does-not-exist', reference)).toBeNull();
912
+
913
+ reference.remove();
914
+ });
915
+
916
+ it('should return null when no reference node is provided and the document misses', () => {
917
+ expect(querySelectorAcrossShadowRoot('#does-not-exist')).toBeNull();
918
+ });
919
+ });
920
+
858
921
  describe('getEffectiveClippingAncestors', () => {
859
922
  it('should return an empty list when element is missing', () => {
860
923
  expect(getEffectiveClippingAncestors(null as unknown as HTMLElement)).toEqual([]);
package/src/utils.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
7
7
  */
8
8
 
9
- import merge from 'ts-deepmerge';
9
+ import { merge } from 'ts-deepmerge';
10
10
  import {
11
11
  EmbedConfig,
12
12
  QueryParams,
@@ -291,6 +291,30 @@ export function getDOMNode(domSelector: DOMSelector): HTMLElement {
291
291
  return typeof domSelector === 'string' ? document.querySelector(domSelector) : domSelector;
292
292
  }
293
293
 
294
+ /**
295
+ * Resolves a CSS selector to an element. `document.querySelector` cannot pierce
296
+ * shadow boundaries, so when the document lookup misses and a reference node is
297
+ * provided, this also searches the shadow root the reference node lives in —
298
+ * letting a selector target an element inside the same shadow root as the embed
299
+ * instead of silently falling back to the light DOM.
300
+ * @param selector CSS selector string.
301
+ * @param referenceNode Node whose shadow root is searched when the document lookup misses.
302
+ */
303
+ export function querySelectorAcrossShadowRoot(
304
+ selector: string,
305
+ referenceNode?: Node | null,
306
+ ): Element | null {
307
+ const fromDocument = document.querySelector(selector);
308
+ if (fromDocument) {
309
+ return fromDocument;
310
+ }
311
+ const rootNode = referenceNode?.getRootNode?.();
312
+ if (typeof ShadowRoot !== 'undefined' && rootNode instanceof ShadowRoot) {
313
+ return rootNode.querySelector(selector);
314
+ }
315
+ return null;
316
+ }
317
+
294
318
  export const deepMerge = (target: any, source: any) => merge(target, source);
295
319
 
296
320
  export const getOperationNameFromQuery = (query: string) => {