@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.
- package/cjs/package.json +1 -1
- package/cjs/src/config.spec.js +9 -0
- package/cjs/src/config.spec.js.map +1 -1
- package/cjs/src/embed/app.d.ts +75 -15
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +69 -9
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +374 -12
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/bodyless-conversation.d.ts +19 -7
- package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/cjs/src/embed/bodyless-conversation.js +24 -4
- package/cjs/src/embed/bodyless-conversation.js.map +1 -1
- package/cjs/src/embed/bodyless-conversation.spec.js +8 -190
- package/cjs/src/embed/bodyless-conversation.spec.js.map +1 -1
- package/cjs/src/embed/conversation.spec.js +28 -0
- package/cjs/src/embed/conversation.spec.js.map +1 -1
- package/cjs/src/embed/embedConfig.d.ts +9 -7
- package/cjs/src/embed/embedConfig.d.ts.map +1 -1
- package/cjs/src/embed/embedConfig.js +9 -7
- package/cjs/src/embed/embedConfig.js.map +1 -1
- package/cjs/src/embed/liveboard.d.ts +56 -17
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +48 -4
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/liveboard.spec.js +215 -11
- package/cjs/src/embed/liveboard.spec.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts +5 -0
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +16 -1
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +164 -0
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/errors.d.ts +1 -0
- package/cjs/src/errors.d.ts.map +1 -1
- package/cjs/src/errors.js +1 -0
- package/cjs/src/errors.js.map +1 -1
- package/cjs/src/index.d.ts +2 -2
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +2 -1
- package/cjs/src/index.js.map +1 -1
- package/cjs/src/react/all-types-export.d.ts +1 -1
- package/cjs/src/react/all-types-export.d.ts.map +1 -1
- package/cjs/src/react/all-types-export.js +3 -2
- package/cjs/src/react/all-types-export.js.map +1 -1
- package/cjs/src/react/index.d.ts +71 -20
- package/cjs/src/react/index.d.ts.map +1 -1
- package/cjs/src/react/index.js +79 -42
- package/cjs/src/react/index.js.map +1 -1
- package/cjs/src/react/index.spec.js +436 -100
- package/cjs/src/react/index.spec.js.map +1 -1
- package/cjs/src/types.d.ts +80 -6
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +45 -1
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
- package/cjs/src/utils/graphql/nlsService/conversation-service.js +2 -0
- package/cjs/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
- package/cjs/src/utils/processTrigger.js +2 -1
- package/cjs/src/utils/processTrigger.js.map +1 -1
- package/cjs/src/utils.d.ts +6 -0
- package/cjs/src/utils.d.ts.map +1 -1
- package/cjs/src/utils.js +23 -3
- package/cjs/src/utils.js.map +1 -1
- package/cjs/src/utils.spec.js +237 -1
- package/cjs/src/utils.spec.js.map +1 -1
- package/dist/{index-JaFaxrvQ.js → index-CmEQfuE3.js} +1 -1
- package/dist/index-DeFzsyFF.js +7371 -0
- package/dist/index-Dpf0rd6w.js +7371 -0
- package/dist/index-UuEbsISo.js +7447 -0
- package/dist/index-e3Uw3YFO.js +7371 -0
- package/dist/src/embed/app.d.ts +75 -15
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/bodyless-conversation.d.ts +19 -7
- package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/dist/src/embed/embedConfig.d.ts +9 -7
- package/dist/src/embed/embedConfig.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts +56 -17
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts +5 -0
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/errors.d.ts +1 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/react/all-types-export.d.ts +1 -1
- package/dist/src/react/all-types-export.d.ts.map +1 -1
- package/dist/src/react/index.d.ts +71 -20
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/types.d.ts +80 -6
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
- package/dist/src/utils.d.ts +6 -0
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +320 -78
- package/dist/tsembed-react.js +320 -76
- package/dist/tsembed.es.js +238 -31
- package/dist/tsembed.js +236 -29
- package/dist/visual-embed-sdk-react-full.d.ts +288 -72
- package/dist/visual-embed-sdk-react.d.ts +288 -72
- package/dist/visual-embed-sdk.d.ts +218 -53
- package/lib/package.json +1 -1
- package/lib/src/config.spec.js +9 -0
- package/lib/src/config.spec.js.map +1 -1
- package/lib/src/embed/app.d.ts +75 -15
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +69 -9
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +376 -14
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/bodyless-conversation.d.ts +19 -7
- package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/lib/src/embed/bodyless-conversation.js +23 -4
- package/lib/src/embed/bodyless-conversation.js.map +1 -1
- package/lib/src/embed/bodyless-conversation.spec.js +9 -191
- package/lib/src/embed/bodyless-conversation.spec.js.map +1 -1
- package/lib/src/embed/conversation.spec.js +30 -2
- package/lib/src/embed/conversation.spec.js.map +1 -1
- package/lib/src/embed/embedConfig.d.ts +9 -7
- package/lib/src/embed/embedConfig.d.ts.map +1 -1
- package/lib/src/embed/embedConfig.js +9 -7
- package/lib/src/embed/embedConfig.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts +56 -17
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +49 -5
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +215 -11
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts +5 -0
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +16 -1
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +164 -0
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/errors.d.ts +1 -0
- package/lib/src/errors.d.ts.map +1 -1
- package/lib/src/errors.js +1 -0
- package/lib/src/errors.js.map +1 -1
- package/lib/src/index.d.ts +2 -2
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +2 -2
- package/lib/src/index.js.map +1 -1
- package/lib/src/react/all-types-export.d.ts +1 -1
- package/lib/src/react/all-types-export.d.ts.map +1 -1
- package/lib/src/react/all-types-export.js +1 -1
- package/lib/src/react/all-types-export.js.map +1 -1
- package/lib/src/react/index.d.ts +71 -20
- package/lib/src/react/index.d.ts.map +1 -1
- package/lib/src/react/index.js +79 -43
- package/lib/src/react/index.js.map +1 -1
- package/lib/src/react/index.spec.js +439 -103
- package/lib/src/react/index.spec.js.map +1 -1
- package/lib/src/types.d.ts +80 -6
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +45 -1
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
- package/lib/src/utils/graphql/nlsService/conversation-service.js +2 -0
- package/lib/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
- package/lib/src/utils/processTrigger.js +2 -1
- package/lib/src/utils/processTrigger.js.map +1 -1
- package/lib/src/utils.d.ts +6 -0
- package/lib/src/utils.d.ts.map +1 -1
- package/lib/src/utils.js +21 -2
- package/lib/src/utils.js.map +1 -1
- package/lib/src/utils.spec.js +238 -2
- package/lib/src/utils.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +219 -54
- package/package.json +1 -1
- package/src/config.spec.ts +11 -0
- package/src/embed/app.spec.ts +479 -26
- package/src/embed/app.ts +133 -27
- package/src/embed/bodyless-conversation.spec.ts +9 -203
- package/src/embed/bodyless-conversation.ts +24 -10
- package/src/embed/conversation.spec.ts +40 -2
- package/src/embed/embedConfig.ts +10 -8
- package/src/embed/liveboard.spec.ts +256 -5
- package/src/embed/liveboard.ts +99 -27
- package/src/embed/ts-embed.spec.ts +225 -0
- package/src/embed/ts-embed.ts +19 -0
- package/src/errors.ts +1 -0
- package/src/index.ts +2 -0
- package/src/react/all-types-export.ts +2 -1
- package/src/react/index.spec.tsx +556 -157
- package/src/react/index.tsx +117 -51
- package/src/types.ts +117 -43
- package/src/utils/graphql/nlsService/conversation-service.ts +2 -0
- package/src/utils/processTrigger.ts +1 -1
- package/src/utils.spec.ts +279 -2
- 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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|