@thoughtspot/visual-embed-sdk 1.39.1 → 1.39.2-alpha.2

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 (190) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/config.spec.js +9 -0
  3. package/cjs/src/config.spec.js.map +1 -1
  4. package/cjs/src/embed/app.d.ts +75 -15
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +69 -9
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +374 -12
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/bodyless-conversation.d.ts +19 -7
  11. package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
  12. package/cjs/src/embed/bodyless-conversation.js +24 -4
  13. package/cjs/src/embed/bodyless-conversation.js.map +1 -1
  14. package/cjs/src/embed/bodyless-conversation.spec.js +8 -190
  15. package/cjs/src/embed/bodyless-conversation.spec.js.map +1 -1
  16. package/cjs/src/embed/conversation.spec.js +28 -0
  17. package/cjs/src/embed/conversation.spec.js.map +1 -1
  18. package/cjs/src/embed/embedConfig.d.ts +9 -7
  19. package/cjs/src/embed/embedConfig.d.ts.map +1 -1
  20. package/cjs/src/embed/embedConfig.js +9 -7
  21. package/cjs/src/embed/embedConfig.js.map +1 -1
  22. package/cjs/src/embed/liveboard.d.ts +56 -17
  23. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  24. package/cjs/src/embed/liveboard.js +48 -4
  25. package/cjs/src/embed/liveboard.js.map +1 -1
  26. package/cjs/src/embed/liveboard.spec.js +215 -11
  27. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  28. package/cjs/src/embed/ts-embed.d.ts +5 -0
  29. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  30. package/cjs/src/embed/ts-embed.js +16 -1
  31. package/cjs/src/embed/ts-embed.js.map +1 -1
  32. package/cjs/src/embed/ts-embed.spec.js +164 -0
  33. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  34. package/cjs/src/errors.d.ts +1 -0
  35. package/cjs/src/errors.d.ts.map +1 -1
  36. package/cjs/src/errors.js +1 -0
  37. package/cjs/src/errors.js.map +1 -1
  38. package/cjs/src/index.d.ts +2 -2
  39. package/cjs/src/index.d.ts.map +1 -1
  40. package/cjs/src/index.js +2 -1
  41. package/cjs/src/index.js.map +1 -1
  42. package/cjs/src/react/all-types-export.d.ts +1 -1
  43. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  44. package/cjs/src/react/all-types-export.js +3 -2
  45. package/cjs/src/react/all-types-export.js.map +1 -1
  46. package/cjs/src/react/index.d.ts +71 -20
  47. package/cjs/src/react/index.d.ts.map +1 -1
  48. package/cjs/src/react/index.js +79 -42
  49. package/cjs/src/react/index.js.map +1 -1
  50. package/cjs/src/react/index.spec.js +436 -100
  51. package/cjs/src/react/index.spec.js.map +1 -1
  52. package/cjs/src/types.d.ts +80 -6
  53. package/cjs/src/types.d.ts.map +1 -1
  54. package/cjs/src/types.js +45 -1
  55. package/cjs/src/types.js.map +1 -1
  56. package/cjs/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
  57. package/cjs/src/utils/graphql/nlsService/conversation-service.js +2 -0
  58. package/cjs/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
  59. package/cjs/src/utils/processTrigger.js +2 -1
  60. package/cjs/src/utils/processTrigger.js.map +1 -1
  61. package/cjs/src/utils.d.ts +6 -0
  62. package/cjs/src/utils.d.ts.map +1 -1
  63. package/cjs/src/utils.js +23 -3
  64. package/cjs/src/utils.js.map +1 -1
  65. package/cjs/src/utils.spec.js +237 -1
  66. package/cjs/src/utils.spec.js.map +1 -1
  67. package/dist/{index-JaFaxrvQ.js → index-CmEQfuE3.js} +1 -1
  68. package/dist/index-DeFzsyFF.js +7371 -0
  69. package/dist/index-Dpf0rd6w.js +7371 -0
  70. package/dist/index-UuEbsISo.js +7447 -0
  71. package/dist/index-e3Uw3YFO.js +7371 -0
  72. package/dist/src/embed/app.d.ts +75 -15
  73. package/dist/src/embed/app.d.ts.map +1 -1
  74. package/dist/src/embed/bodyless-conversation.d.ts +19 -7
  75. package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
  76. package/dist/src/embed/embedConfig.d.ts +9 -7
  77. package/dist/src/embed/embedConfig.d.ts.map +1 -1
  78. package/dist/src/embed/liveboard.d.ts +56 -17
  79. package/dist/src/embed/liveboard.d.ts.map +1 -1
  80. package/dist/src/embed/ts-embed.d.ts +5 -0
  81. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  82. package/dist/src/errors.d.ts +1 -0
  83. package/dist/src/errors.d.ts.map +1 -1
  84. package/dist/src/index.d.ts +2 -2
  85. package/dist/src/index.d.ts.map +1 -1
  86. package/dist/src/react/all-types-export.d.ts +1 -1
  87. package/dist/src/react/all-types-export.d.ts.map +1 -1
  88. package/dist/src/react/index.d.ts +71 -20
  89. package/dist/src/react/index.d.ts.map +1 -1
  90. package/dist/src/types.d.ts +80 -6
  91. package/dist/src/types.d.ts.map +1 -1
  92. package/dist/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
  93. package/dist/src/utils.d.ts +6 -0
  94. package/dist/src/utils.d.ts.map +1 -1
  95. package/dist/tsembed-react.es.js +320 -78
  96. package/dist/tsembed-react.js +320 -76
  97. package/dist/tsembed.es.js +238 -31
  98. package/dist/tsembed.js +236 -29
  99. package/dist/visual-embed-sdk-react-full.d.ts +288 -72
  100. package/dist/visual-embed-sdk-react.d.ts +288 -72
  101. package/dist/visual-embed-sdk.d.ts +218 -53
  102. package/lib/package.json +1 -1
  103. package/lib/src/config.spec.js +9 -0
  104. package/lib/src/config.spec.js.map +1 -1
  105. package/lib/src/embed/app.d.ts +75 -15
  106. package/lib/src/embed/app.d.ts.map +1 -1
  107. package/lib/src/embed/app.js +69 -9
  108. package/lib/src/embed/app.js.map +1 -1
  109. package/lib/src/embed/app.spec.js +376 -14
  110. package/lib/src/embed/app.spec.js.map +1 -1
  111. package/lib/src/embed/bodyless-conversation.d.ts +19 -7
  112. package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
  113. package/lib/src/embed/bodyless-conversation.js +23 -4
  114. package/lib/src/embed/bodyless-conversation.js.map +1 -1
  115. package/lib/src/embed/bodyless-conversation.spec.js +9 -191
  116. package/lib/src/embed/bodyless-conversation.spec.js.map +1 -1
  117. package/lib/src/embed/conversation.spec.js +30 -2
  118. package/lib/src/embed/conversation.spec.js.map +1 -1
  119. package/lib/src/embed/embedConfig.d.ts +9 -7
  120. package/lib/src/embed/embedConfig.d.ts.map +1 -1
  121. package/lib/src/embed/embedConfig.js +9 -7
  122. package/lib/src/embed/embedConfig.js.map +1 -1
  123. package/lib/src/embed/liveboard.d.ts +56 -17
  124. package/lib/src/embed/liveboard.d.ts.map +1 -1
  125. package/lib/src/embed/liveboard.js +49 -5
  126. package/lib/src/embed/liveboard.js.map +1 -1
  127. package/lib/src/embed/liveboard.spec.js +215 -11
  128. package/lib/src/embed/liveboard.spec.js.map +1 -1
  129. package/lib/src/embed/ts-embed.d.ts +5 -0
  130. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  131. package/lib/src/embed/ts-embed.js +16 -1
  132. package/lib/src/embed/ts-embed.js.map +1 -1
  133. package/lib/src/embed/ts-embed.spec.js +164 -0
  134. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  135. package/lib/src/errors.d.ts +1 -0
  136. package/lib/src/errors.d.ts.map +1 -1
  137. package/lib/src/errors.js +1 -0
  138. package/lib/src/errors.js.map +1 -1
  139. package/lib/src/index.d.ts +2 -2
  140. package/lib/src/index.d.ts.map +1 -1
  141. package/lib/src/index.js +2 -2
  142. package/lib/src/index.js.map +1 -1
  143. package/lib/src/react/all-types-export.d.ts +1 -1
  144. package/lib/src/react/all-types-export.d.ts.map +1 -1
  145. package/lib/src/react/all-types-export.js +1 -1
  146. package/lib/src/react/all-types-export.js.map +1 -1
  147. package/lib/src/react/index.d.ts +71 -20
  148. package/lib/src/react/index.d.ts.map +1 -1
  149. package/lib/src/react/index.js +79 -43
  150. package/lib/src/react/index.js.map +1 -1
  151. package/lib/src/react/index.spec.js +439 -103
  152. package/lib/src/react/index.spec.js.map +1 -1
  153. package/lib/src/types.d.ts +80 -6
  154. package/lib/src/types.d.ts.map +1 -1
  155. package/lib/src/types.js +45 -1
  156. package/lib/src/types.js.map +1 -1
  157. package/lib/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
  158. package/lib/src/utils/graphql/nlsService/conversation-service.js +2 -0
  159. package/lib/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
  160. package/lib/src/utils/processTrigger.js +2 -1
  161. package/lib/src/utils/processTrigger.js.map +1 -1
  162. package/lib/src/utils.d.ts +6 -0
  163. package/lib/src/utils.d.ts.map +1 -1
  164. package/lib/src/utils.js +21 -2
  165. package/lib/src/utils.js.map +1 -1
  166. package/lib/src/utils.spec.js +238 -2
  167. package/lib/src/utils.spec.js.map +1 -1
  168. package/lib/src/visual-embed-sdk.d.ts +219 -54
  169. package/package.json +1 -1
  170. package/src/config.spec.ts +11 -0
  171. package/src/embed/app.spec.ts +479 -26
  172. package/src/embed/app.ts +133 -27
  173. package/src/embed/bodyless-conversation.spec.ts +9 -203
  174. package/src/embed/bodyless-conversation.ts +24 -10
  175. package/src/embed/conversation.spec.ts +40 -2
  176. package/src/embed/embedConfig.ts +10 -8
  177. package/src/embed/liveboard.spec.ts +256 -5
  178. package/src/embed/liveboard.ts +99 -27
  179. package/src/embed/ts-embed.spec.ts +225 -0
  180. package/src/embed/ts-embed.ts +19 -0
  181. package/src/errors.ts +1 -0
  182. package/src/index.ts +2 -0
  183. package/src/react/all-types-export.ts +2 -1
  184. package/src/react/index.spec.tsx +556 -157
  185. package/src/react/index.tsx +117 -51
  186. package/src/types.ts +117 -43
  187. package/src/utils/graphql/nlsService/conversation-service.ts +2 -0
  188. package/src/utils/processTrigger.ts +1 -1
  189. package/src/utils.spec.ts +279 -2
  190. package/src/utils.ts +28 -2
@@ -31,7 +31,7 @@ function postIframeMessage(
31
31
  thoughtSpotHost: string,
32
32
  channel?: MessageChannel,
33
33
  ) {
34
- return iFrame.contentWindow.postMessage(message, thoughtSpotHost, [channel?.port2]);
34
+ return iFrame.contentWindow?.postMessage(message, thoughtSpotHost, [channel?.port2]);
35
35
  }
36
36
 
37
37
  export const TRIGGER_TIMEOUT = 30000;
package/src/utils.spec.ts CHANGED
@@ -15,6 +15,8 @@ import {
15
15
  getValueFromWindow,
16
16
  handlePresentEvent,
17
17
  handleExitPresentMode,
18
+ getTypeFromValue,
19
+ calculateVisibleElementData,
18
20
  } from './utils';
19
21
  import { RuntimeFilterOp } from './types';
20
22
  import { logger } from './utils/logger';
@@ -284,6 +286,27 @@ describe('unit test for utils', () => {
284
286
  test('isUndefined', () => {
285
287
  expect(isUndefined(undefined)).toBe(true);
286
288
  expect(isUndefined({})).toBe(false);
289
+ expect(isUndefined(null)).toBe(false);
290
+ expect(isUndefined('')).toBe(false);
291
+ expect(isUndefined(0)).toBe(false);
292
+ });
293
+
294
+ test('removeTypename should handle edge cases', () => {
295
+ expect(removeTypename(null)).toBe(null);
296
+ expect(removeTypename(undefined)).toBe(undefined);
297
+ expect(removeTypename('string')).toBe('string');
298
+ expect(removeTypename(123)).toBe(123);
299
+ });
300
+
301
+ test('getTypeFromValue should return correct types', () => {
302
+ expect(getTypeFromValue('test')).toEqual(['char', 'string']);
303
+ expect(getTypeFromValue(123)).toEqual(['double', 'double']);
304
+ expect(getTypeFromValue(true)).toEqual(['boolean', 'boolean']);
305
+ expect(getTypeFromValue(false)).toEqual(['boolean', 'boolean']);
306
+ expect(getTypeFromValue(null)).toEqual(['', '']);
307
+ expect(getTypeFromValue(undefined)).toEqual(['', '']);
308
+ expect(getTypeFromValue({})).toEqual(['', '']);
309
+ expect(getTypeFromValue([])).toEqual(['', '']);
287
310
  });
288
311
 
289
312
  describe('getValueFromWindow and storeValueInWindow', () => {
@@ -293,7 +316,7 @@ describe('unit test for utils', () => {
293
316
  });
294
317
 
295
318
  test('Object should be set if not', () => {
296
- // eslint-disable-next-line no-underscore-dangle
319
+
297
320
  (window as any)._tsEmbedSDK = null;
298
321
 
299
322
  storeValueInWindow('test', 'testValue');
@@ -303,6 +326,13 @@ describe('unit test for utils', () => {
303
326
  test('Return undefined if key is not found', () => {
304
327
  expect(getValueFromWindow('notFound')).toBe(undefined);
305
328
  });
329
+
330
+ test('Store with ignoreIfAlreadyExists option', () => {
331
+ storeValueInWindow('test2', 'firstValue');
332
+ const result = storeValueInWindow('test2', 'secondValue', { ignoreIfAlreadyExists: true });
333
+ expect(result).toBe('firstValue');
334
+ expect(getValueFromWindow('test2')).toBe('firstValue');
335
+ });
306
336
  });
307
337
  });
308
338
 
@@ -312,7 +342,7 @@ describe('Fullscreen Utility Functions', () => {
312
342
 
313
343
  beforeEach(() => {
314
344
  jest.clearAllMocks();
315
-
345
+
316
346
  // Store and mock exitFullscreen
317
347
  originalExitFullscreen = document.exitFullscreen;
318
348
  document.exitFullscreen = jest.fn();
@@ -407,3 +437,250 @@ describe('Fullscreen Utility Functions', () => {
407
437
  });
408
438
  });
409
439
  });
440
+
441
+ describe('calculateVisibleElementData', () => {
442
+ let mockElement: HTMLElement;
443
+ let originalInnerHeight: number;
444
+ let originalInnerWidth: number;
445
+
446
+ beforeEach(() => {
447
+ // Store original window dimensions
448
+ originalInnerHeight = window.innerHeight;
449
+ originalInnerWidth = window.innerWidth;
450
+
451
+ // Mock window dimensions
452
+ Object.defineProperty(window, 'innerHeight', {
453
+ writable: true,
454
+ configurable: true,
455
+ value: 800,
456
+ });
457
+ Object.defineProperty(window, 'innerWidth', {
458
+ writable: true,
459
+ configurable: true,
460
+ value: 1200,
461
+ });
462
+
463
+ // Create mock element
464
+ mockElement = document.createElement('div');
465
+ });
466
+
467
+ afterEach(() => {
468
+ // Restore original window dimensions
469
+ Object.defineProperty(window, 'innerHeight', {
470
+ value: originalInnerHeight,
471
+ });
472
+ Object.defineProperty(window, 'innerWidth', {
473
+ value: originalInnerWidth,
474
+ });
475
+ });
476
+
477
+ it('should calculate data for fully visible element', () => {
478
+ // Mock getBoundingClientRect for element fully within viewport
479
+ jest.spyOn(mockElement, 'getBoundingClientRect').mockReturnValue({
480
+ top: 100,
481
+ left: 150,
482
+ bottom: 300,
483
+ right: 400,
484
+ width: 250,
485
+ height: 200,
486
+ } as DOMRect);
487
+
488
+ const result = calculateVisibleElementData(mockElement);
489
+
490
+ expect(result).toEqual({
491
+ top: 0, // Not clipped from top
492
+ height: 200, // Full height visible
493
+ left: 0, // Not clipped from left
494
+ width: 250, // Full width visible
495
+ });
496
+ });
497
+
498
+ it('should calculate data for element clipped from top', () => {
499
+ // Mock getBoundingClientRect for element partially above viewport
500
+ jest.spyOn(mockElement, 'getBoundingClientRect').mockReturnValue({
501
+ top: -50,
502
+ left: 100,
503
+ bottom: 150,
504
+ right: 400,
505
+ width: 300,
506
+ height: 200,
507
+ } as DOMRect);
508
+
509
+ const result = calculateVisibleElementData(mockElement);
510
+
511
+ expect(result).toEqual({
512
+ top: 50, // Clipped 50px from top
513
+ height: 150, // 150px visible height (0 to 150)
514
+ left: 0, // Not clipped from left
515
+ width: 300, // Full width visible
516
+ });
517
+ });
518
+
519
+ it('should calculate data for element clipped from left', () => {
520
+ // Mock getBoundingClientRect for element partially left of viewport
521
+ jest.spyOn(mockElement, 'getBoundingClientRect').mockReturnValue({
522
+ top: 100,
523
+ left: -80,
524
+ bottom: 300,
525
+ right: 200,
526
+ width: 280,
527
+ height: 200,
528
+ } as DOMRect);
529
+
530
+ const result = calculateVisibleElementData(mockElement);
531
+
532
+ expect(result).toEqual({
533
+ top: 0, // Not clipped from top
534
+ height: 200, // Full height visible
535
+ left: 80, // Clipped 80px from left
536
+ width: 200, // 200px visible width (0 to 200)
537
+ });
538
+ });
539
+
540
+ it('should calculate data for element clipped from bottom', () => {
541
+ // Mock getBoundingClientRect for element extending below viewport
542
+ jest.spyOn(mockElement, 'getBoundingClientRect').mockReturnValue({
543
+ top: 600,
544
+ left: 100,
545
+ bottom: 950, // Extends beyond window height of 800
546
+ right: 400,
547
+ width: 300,
548
+ height: 350,
549
+ } as DOMRect);
550
+
551
+ const result = calculateVisibleElementData(mockElement);
552
+
553
+ expect(result).toEqual({
554
+ top: 0, // Not clipped from top
555
+ height: 200, // Only 200px visible (600 to 800)
556
+ left: 0, // Not clipped from left
557
+ width: 300, // Full width visible
558
+ });
559
+ });
560
+
561
+ it('should calculate data for element clipped from right', () => {
562
+ // Mock getBoundingClientRect for element extending beyond right edge
563
+ jest.spyOn(mockElement, 'getBoundingClientRect').mockReturnValue({
564
+ top: 100,
565
+ left: 1000,
566
+ bottom: 300,
567
+ right: 1400, // Extends beyond window width of 1200
568
+ width: 400,
569
+ height: 200,
570
+ } as DOMRect);
571
+
572
+ const result = calculateVisibleElementData(mockElement);
573
+
574
+ expect(result).toEqual({
575
+ top: 0, // Not clipped from top
576
+ height: 200, // Full height visible
577
+ left: 0, // Not clipped from left
578
+ width: 200, // Only 200px visible width (1000 to 1200)
579
+ });
580
+ });
581
+
582
+ it('should calculate data for element clipped from multiple sides', () => {
583
+ // Mock getBoundingClientRect for element clipped from top and left
584
+ jest.spyOn(mockElement, 'getBoundingClientRect').mockReturnValue({
585
+ top: -100,
586
+ left: -50,
587
+ bottom: 200,
588
+ right: 300,
589
+ width: 350,
590
+ height: 300,
591
+ } as DOMRect);
592
+
593
+ const result = calculateVisibleElementData(mockElement);
594
+
595
+ expect(result).toEqual({
596
+ top: 100, // Clipped 100px from top
597
+ height: 200, // 200px visible height (0 to 200)
598
+ left: 50, // Clipped 50px from left
599
+ width: 300, // 300px visible width (0 to 300)
600
+ });
601
+ });
602
+
603
+ it('should handle element completely outside viewport (above)', () => {
604
+ // Mock getBoundingClientRect for element completely above viewport
605
+ jest.spyOn(mockElement, 'getBoundingClientRect').mockReturnValue({
606
+ top: -300,
607
+ left: 100,
608
+ bottom: -100,
609
+ right: 400,
610
+ width: 300,
611
+ height: 200,
612
+ } as DOMRect);
613
+
614
+ const result = calculateVisibleElementData(mockElement);
615
+
616
+ expect(result).toEqual({
617
+ top: 300, // Clipped 300px from top
618
+ height: 0, // No visible height (clamped from negative)
619
+ left: 0, // Not clipped from left
620
+ width: 300, // Full width would be visible if in viewport
621
+ });
622
+ });
623
+
624
+ it('should handle element completely outside viewport (left)', () => {
625
+ // Mock getBoundingClientRect for element completely left of viewport
626
+ jest.spyOn(mockElement, 'getBoundingClientRect').mockReturnValue({
627
+ top: 100,
628
+ left: -400,
629
+ bottom: 300,
630
+ right: -100,
631
+ width: 300,
632
+ height: 200,
633
+ } as DOMRect);
634
+
635
+ const result = calculateVisibleElementData(mockElement);
636
+
637
+ expect(result).toEqual({
638
+ top: 0, // Not clipped from top
639
+ height: 200, // Full height would be visible if in viewport
640
+ left: 400, // Clipped 400px from left
641
+ width: 0, // No visible width (min(1200, -100) - max(-400, 0) = -100 - 0 = -100, but clamped)
642
+ });
643
+ });
644
+
645
+ it('should handle element larger than viewport', () => {
646
+ // Mock getBoundingClientRect for element larger than viewport
647
+ jest.spyOn(mockElement, 'getBoundingClientRect').mockReturnValue({
648
+ top: -200,
649
+ left: -300,
650
+ bottom: 1000,
651
+ right: 1500,
652
+ width: 1800,
653
+ height: 1200,
654
+ } as DOMRect);
655
+
656
+ const result = calculateVisibleElementData(mockElement);
657
+
658
+ expect(result).toEqual({
659
+ top: 200, // Clipped 200px from top
660
+ height: 800, // Visible height equals window height
661
+ left: 300, // Clipped 300px from left
662
+ width: 1200, // Visible width equals window width
663
+ });
664
+ });
665
+
666
+ it('should handle element exactly at viewport boundaries', () => {
667
+ // Mock getBoundingClientRect for element at exact viewport boundaries
668
+ jest.spyOn(mockElement, 'getBoundingClientRect').mockReturnValue({
669
+ top: 0,
670
+ left: 0,
671
+ bottom: 800,
672
+ right: 1200,
673
+ width: 1200,
674
+ height: 800,
675
+ } as DOMRect);
676
+
677
+ const result = calculateVisibleElementData(mockElement);
678
+
679
+ expect(result).toEqual({
680
+ top: 0, // Not clipped from top
681
+ height: 800, // Full viewport height
682
+ left: 0, // Not clipped from left
683
+ width: 1200, // Full viewport width
684
+ });
685
+ });
686
+ });
package/src/utils.ts CHANGED
@@ -269,7 +269,7 @@ export const getOperationNameFromQuery = (query: string) => {
269
269
  export function removeTypename(obj: any) {
270
270
  if (!obj || typeof obj !== 'object') return obj;
271
271
 
272
- // eslint-disable-next-line no-restricted-syntax
272
+
273
273
  for (const key in obj) {
274
274
  if (key === '__typename') {
275
275
  delete obj[key];
@@ -300,7 +300,11 @@ export const setStyleProperties = (
300
300
  ): void => {
301
301
  if (!element?.style) return;
302
302
  Object.keys(styleProperties).forEach((styleProperty) => {
303
- element.style[styleProperty] = styleProperties[styleProperty].toString();
303
+ const styleKey = styleProperty as keyof CSSStyleDeclaration;
304
+ const value = styleProperties[styleKey];
305
+ if (value !== undefined) {
306
+ (element.style as any)[styleKey] = value.toString();
307
+ }
304
308
  });
305
309
  };
306
310
  /**
@@ -463,3 +467,25 @@ export const handleExitPresentMode = async (): Promise<void> => {
463
467
 
464
468
  logger.warn('Exit fullscreen API is not supported by this browser.');
465
469
  };
470
+
471
+ export const calculateVisibleElementData = (element: HTMLElement) => {
472
+ const rect = element.getBoundingClientRect();
473
+
474
+ const windowHeight = window.innerHeight;
475
+ const windowWidth = window.innerWidth;
476
+
477
+ const frameRelativeTop = Math.max(rect.top, 0);
478
+ const frameRelativeLeft = Math.max(rect.left, 0);
479
+
480
+ const frameRelativeBottom = Math.min(windowHeight, rect.bottom);
481
+ const frameRelativeRight = Math.min(windowWidth, rect.right);
482
+
483
+ const data = {
484
+ top: Math.max(0, rect.top * -1),
485
+ height: Math.max(0, frameRelativeBottom - frameRelativeTop),
486
+ left: Math.max(0, rect.left * -1),
487
+ width: Math.max(0, frameRelativeRight - frameRelativeLeft),
488
+ };
489
+
490
+ return data;
491
+ }