@weldsuite/helpdesk-widget-sdk 1.0.14 → 1.0.16
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/dist/angular.d.ts +4 -0
- package/dist/angular.esm.js +248 -50
- package/dist/angular.esm.js.map +1 -1
- package/dist/angular.js +248 -50
- package/dist/angular.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.esm.js +248 -50
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +248 -50
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +248 -50
- package/dist/index.umd.js.map +1 -1
- package/dist/react.d.ts +4 -0
- package/dist/react.esm.js +248 -50
- package/dist/react.esm.js.map +1 -1
- package/dist/react.js +248 -50
- package/dist/react.js.map +1 -1
- package/dist/vue-composables.esm.js +248 -50
- package/dist/vue-composables.esm.js.map +1 -1
- package/dist/vue-composables.js +248 -50
- package/dist/vue-composables.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -504,6 +504,10 @@ declare class WeldSDK {
|
|
|
504
504
|
* Handle launcher click messages from iframe
|
|
505
505
|
*/
|
|
506
506
|
private handleLauncherClickMessage;
|
|
507
|
+
/**
|
|
508
|
+
* Show fullscreen image lightbox on the parent page
|
|
509
|
+
*/
|
|
510
|
+
private showImageLightbox;
|
|
507
511
|
/**
|
|
508
512
|
* Initialize the SDK and render widget
|
|
509
513
|
*/
|
|
@@ -768,7 +772,7 @@ declare class IframeManager {
|
|
|
768
772
|
*/
|
|
769
773
|
private createWidgetIframe;
|
|
770
774
|
/**
|
|
771
|
-
* Create backdrop iframe
|
|
775
|
+
* Create backdrop iframe — disabled, widget stays non-modal so users can interact with the page
|
|
772
776
|
*/
|
|
773
777
|
private createBackdropIframe;
|
|
774
778
|
/**
|
package/dist/index.esm.js
CHANGED
|
@@ -508,14 +508,16 @@ class IframeManager {
|
|
|
508
508
|
const container = document.createElement('div');
|
|
509
509
|
container.className = 'weld-launcher-frame';
|
|
510
510
|
container.setAttribute('data-state', 'visible');
|
|
511
|
+
// Container is larger than the button to allow hover animations (scale, shadow) without clipping
|
|
512
|
+
const launcherPadding = 10;
|
|
511
513
|
container.style.cssText = `
|
|
512
514
|
position: fixed;
|
|
513
|
-
bottom: ${launcher.position.bottom};
|
|
514
|
-
right: ${launcher.position.right};
|
|
515
|
-
width: ${launcher.size};
|
|
516
|
-
height: ${launcher.size};
|
|
515
|
+
bottom: calc(${launcher.position.bottom} - ${launcherPadding}px);
|
|
516
|
+
right: calc(${launcher.position.right} - ${launcherPadding}px);
|
|
517
|
+
width: calc(${launcher.size} + ${launcherPadding * 2}px);
|
|
518
|
+
height: calc(${launcher.size} + ${launcherPadding * 2}px);
|
|
517
519
|
z-index: 2147483003;
|
|
518
|
-
pointer-events:
|
|
520
|
+
pointer-events: none;
|
|
519
521
|
display: block;
|
|
520
522
|
`;
|
|
521
523
|
// Create iframe
|
|
@@ -529,6 +531,7 @@ class IframeManager {
|
|
|
529
531
|
border: none;
|
|
530
532
|
background: transparent;
|
|
531
533
|
display: block;
|
|
534
|
+
pointer-events: auto;
|
|
532
535
|
`;
|
|
533
536
|
iframe.setAttribute('allow', 'clipboard-write');
|
|
534
537
|
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups');
|
|
@@ -649,43 +652,10 @@ class IframeManager {
|
|
|
649
652
|
this.logger.debug('Widget iframe created');
|
|
650
653
|
}
|
|
651
654
|
/**
|
|
652
|
-
* Create backdrop iframe
|
|
655
|
+
* Create backdrop iframe — disabled, widget stays non-modal so users can interact with the page
|
|
653
656
|
*/
|
|
654
657
|
async createBackdropIframe() {
|
|
655
|
-
|
|
656
|
-
this.logger.debug('Backdrop disabled, skipping creation');
|
|
657
|
-
return;
|
|
658
|
-
}
|
|
659
|
-
// Create container
|
|
660
|
-
const container = document.createElement('div');
|
|
661
|
-
container.className = 'weld-backdrop-frame';
|
|
662
|
-
container.setAttribute('data-state', 'hidden');
|
|
663
|
-
container.style.cssText = `
|
|
664
|
-
position: fixed;
|
|
665
|
-
top: 0;
|
|
666
|
-
left: 0;
|
|
667
|
-
right: 0;
|
|
668
|
-
bottom: 0;
|
|
669
|
-
z-index: 2147483000;
|
|
670
|
-
background: transparent;
|
|
671
|
-
pointer-events: none;
|
|
672
|
-
opacity: 0;
|
|
673
|
-
transition: opacity 200ms ease;
|
|
674
|
-
`;
|
|
675
|
-
this.appContainer?.appendChild(container);
|
|
676
|
-
// Store metadata (backdrop doesn't have an iframe, just a div)
|
|
677
|
-
// We'll create a minimal "iframe" reference for consistency
|
|
678
|
-
const dummyIframe = document.createElement('iframe');
|
|
679
|
-
dummyIframe.style.display = 'none';
|
|
680
|
-
this.iframes.set(IframeType.BACKDROP, {
|
|
681
|
-
type: IframeType.BACKDROP,
|
|
682
|
-
element: dummyIframe,
|
|
683
|
-
container,
|
|
684
|
-
ready: true, // Backdrop is always ready
|
|
685
|
-
visible: false,
|
|
686
|
-
createdAt: Date.now(),
|
|
687
|
-
});
|
|
688
|
-
this.logger.debug('Backdrop created');
|
|
658
|
+
this.logger.debug('Backdrop disabled, skipping creation');
|
|
689
659
|
}
|
|
690
660
|
/**
|
|
691
661
|
* Build iframe URL with parameters
|
|
@@ -1023,11 +993,7 @@ class SecurityManager {
|
|
|
1023
993
|
* Validate message origin
|
|
1024
994
|
*/
|
|
1025
995
|
isOriginAllowed(origin) {
|
|
1026
|
-
//
|
|
1027
|
-
if (this.config.allowedOrigins?.length === 0) {
|
|
1028
|
-
return origin === window.location.origin;
|
|
1029
|
-
}
|
|
1030
|
-
// Check if origin is in allowed list
|
|
996
|
+
// Check if origin is in allowed list (includes same-origin and programmatically added origins)
|
|
1031
997
|
if (this.allowedOrigins.has(origin)) {
|
|
1032
998
|
return true;
|
|
1033
999
|
}
|
|
@@ -2399,7 +2365,7 @@ class StateCoordinator {
|
|
|
2399
2365
|
}
|
|
2400
2366
|
}
|
|
2401
2367
|
|
|
2402
|
-
var version = "1.0.
|
|
2368
|
+
var version = "1.0.16";
|
|
2403
2369
|
var packageJson = {
|
|
2404
2370
|
version: version};
|
|
2405
2371
|
|
|
@@ -2482,6 +2448,242 @@ class WeldSDK {
|
|
|
2482
2448
|
console.log('[Weld SDK] Widget close requested');
|
|
2483
2449
|
this.close();
|
|
2484
2450
|
}
|
|
2451
|
+
if (event.data?.type === 'weld:image:open' && event.data?.url) {
|
|
2452
|
+
this.showImageLightbox(event.data.url);
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
/**
|
|
2456
|
+
* Show fullscreen image lightbox on the parent page
|
|
2457
|
+
*/
|
|
2458
|
+
showImageLightbox(url) {
|
|
2459
|
+
// Remove existing lightbox if any
|
|
2460
|
+
const existing = document.getElementById('weld-image-lightbox');
|
|
2461
|
+
if (existing)
|
|
2462
|
+
existing.remove();
|
|
2463
|
+
// Zoom / pan state
|
|
2464
|
+
let scale = 1;
|
|
2465
|
+
let translateX = 0;
|
|
2466
|
+
let translateY = 0;
|
|
2467
|
+
let isDragging = false;
|
|
2468
|
+
let dragStartX = 0;
|
|
2469
|
+
let dragStartY = 0;
|
|
2470
|
+
let lastTranslateX = 0;
|
|
2471
|
+
let lastTranslateY = 0;
|
|
2472
|
+
const applyTransform = () => {
|
|
2473
|
+
img.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`;
|
|
2474
|
+
};
|
|
2475
|
+
const resetTransform = () => {
|
|
2476
|
+
scale = 1;
|
|
2477
|
+
translateX = 0;
|
|
2478
|
+
translateY = 0;
|
|
2479
|
+
applyTransform();
|
|
2480
|
+
img.style.cursor = 'zoom-in';
|
|
2481
|
+
};
|
|
2482
|
+
const overlay = document.createElement('div');
|
|
2483
|
+
overlay.id = 'weld-image-lightbox';
|
|
2484
|
+
overlay.style.cssText = `
|
|
2485
|
+
position: fixed;
|
|
2486
|
+
inset: 0;
|
|
2487
|
+
z-index: 2147483647;
|
|
2488
|
+
background: rgba(0, 0, 0, 0.92);
|
|
2489
|
+
display: flex;
|
|
2490
|
+
align-items: center;
|
|
2491
|
+
justify-content: center;
|
|
2492
|
+
padding: 16px;
|
|
2493
|
+
cursor: pointer;
|
|
2494
|
+
overflow: hidden;
|
|
2495
|
+
`;
|
|
2496
|
+
// Close button
|
|
2497
|
+
const closeBtn = document.createElement('button');
|
|
2498
|
+
closeBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>`;
|
|
2499
|
+
closeBtn.style.cssText = `
|
|
2500
|
+
position: absolute;
|
|
2501
|
+
top: 16px;
|
|
2502
|
+
right: 16px;
|
|
2503
|
+
width: 40px;
|
|
2504
|
+
height: 40px;
|
|
2505
|
+
border-radius: 50%;
|
|
2506
|
+
border: none;
|
|
2507
|
+
background: rgba(255, 255, 255, 0.1);
|
|
2508
|
+
color: white;
|
|
2509
|
+
cursor: pointer;
|
|
2510
|
+
display: flex;
|
|
2511
|
+
align-items: center;
|
|
2512
|
+
justify-content: center;
|
|
2513
|
+
transition: background 0.15s;
|
|
2514
|
+
`;
|
|
2515
|
+
closeBtn.onmouseenter = () => { closeBtn.style.background = 'rgba(255, 255, 255, 0.2)'; };
|
|
2516
|
+
closeBtn.onmouseleave = () => { closeBtn.style.background = 'rgba(255, 255, 255, 0.1)'; };
|
|
2517
|
+
// Download button
|
|
2518
|
+
const downloadBtn = document.createElement('a');
|
|
2519
|
+
downloadBtn.href = url;
|
|
2520
|
+
downloadBtn.download = '';
|
|
2521
|
+
downloadBtn.target = '_blank';
|
|
2522
|
+
downloadBtn.rel = 'noopener noreferrer';
|
|
2523
|
+
downloadBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>`;
|
|
2524
|
+
downloadBtn.style.cssText = `
|
|
2525
|
+
position: absolute;
|
|
2526
|
+
top: 16px;
|
|
2527
|
+
right: 64px;
|
|
2528
|
+
width: 40px;
|
|
2529
|
+
height: 40px;
|
|
2530
|
+
border-radius: 50%;
|
|
2531
|
+
border: none;
|
|
2532
|
+
background: rgba(255, 255, 255, 0.1);
|
|
2533
|
+
color: white;
|
|
2534
|
+
cursor: pointer;
|
|
2535
|
+
display: flex;
|
|
2536
|
+
align-items: center;
|
|
2537
|
+
justify-content: center;
|
|
2538
|
+
transition: background 0.15s;
|
|
2539
|
+
text-decoration: none;
|
|
2540
|
+
`;
|
|
2541
|
+
downloadBtn.onmouseenter = () => { downloadBtn.style.background = 'rgba(255, 255, 255, 0.2)'; };
|
|
2542
|
+
downloadBtn.onmouseleave = () => { downloadBtn.style.background = 'rgba(255, 255, 255, 0.1)'; };
|
|
2543
|
+
// Image
|
|
2544
|
+
const img = document.createElement('img');
|
|
2545
|
+
img.src = url;
|
|
2546
|
+
img.alt = 'Full size';
|
|
2547
|
+
img.draggable = false;
|
|
2548
|
+
img.style.cssText = `
|
|
2549
|
+
max-width: 100%;
|
|
2550
|
+
max-height: 100%;
|
|
2551
|
+
object-fit: contain;
|
|
2552
|
+
border-radius: 8px;
|
|
2553
|
+
cursor: zoom-in;
|
|
2554
|
+
transition: transform 0.2s ease;
|
|
2555
|
+
user-select: none;
|
|
2556
|
+
`;
|
|
2557
|
+
// Click to toggle zoom
|
|
2558
|
+
img.addEventListener('click', (e) => {
|
|
2559
|
+
e.stopPropagation();
|
|
2560
|
+
if (scale === 1) {
|
|
2561
|
+
// Zoom in to 2.5x centered on click position
|
|
2562
|
+
const rect = img.getBoundingClientRect();
|
|
2563
|
+
const clickX = e.clientX - rect.left - rect.width / 2;
|
|
2564
|
+
const clickY = e.clientY - rect.top - rect.height / 2;
|
|
2565
|
+
scale = 2.5;
|
|
2566
|
+
translateX = -clickX * 1.5;
|
|
2567
|
+
translateY = -clickY * 1.5;
|
|
2568
|
+
applyTransform();
|
|
2569
|
+
img.style.cursor = 'zoom-out';
|
|
2570
|
+
}
|
|
2571
|
+
else {
|
|
2572
|
+
// Zoom out - reset
|
|
2573
|
+
resetTransform();
|
|
2574
|
+
}
|
|
2575
|
+
});
|
|
2576
|
+
// Mouse wheel zoom
|
|
2577
|
+
overlay.addEventListener('wheel', (e) => {
|
|
2578
|
+
e.preventDefault();
|
|
2579
|
+
const delta = e.deltaY > 0 ? -0.25 : 0.25;
|
|
2580
|
+
const newScale = Math.min(Math.max(scale + delta, 1), 5);
|
|
2581
|
+
if (newScale === 1) {
|
|
2582
|
+
resetTransform();
|
|
2583
|
+
}
|
|
2584
|
+
else {
|
|
2585
|
+
scale = newScale;
|
|
2586
|
+
applyTransform();
|
|
2587
|
+
img.style.cursor = 'zoom-out';
|
|
2588
|
+
}
|
|
2589
|
+
}, { passive: false });
|
|
2590
|
+
// Drag to pan when zoomed
|
|
2591
|
+
img.addEventListener('mousedown', (e) => {
|
|
2592
|
+
if (scale <= 1)
|
|
2593
|
+
return;
|
|
2594
|
+
e.preventDefault();
|
|
2595
|
+
isDragging = true;
|
|
2596
|
+
dragStartX = e.clientX;
|
|
2597
|
+
dragStartY = e.clientY;
|
|
2598
|
+
lastTranslateX = translateX;
|
|
2599
|
+
lastTranslateY = translateY;
|
|
2600
|
+
img.style.cursor = 'grabbing';
|
|
2601
|
+
img.style.transition = 'none';
|
|
2602
|
+
});
|
|
2603
|
+
window.addEventListener('mousemove', (e) => {
|
|
2604
|
+
if (!isDragging)
|
|
2605
|
+
return;
|
|
2606
|
+
translateX = lastTranslateX + (e.clientX - dragStartX);
|
|
2607
|
+
translateY = lastTranslateY + (e.clientY - dragStartY);
|
|
2608
|
+
applyTransform();
|
|
2609
|
+
});
|
|
2610
|
+
window.addEventListener('mouseup', () => {
|
|
2611
|
+
if (!isDragging)
|
|
2612
|
+
return;
|
|
2613
|
+
isDragging = false;
|
|
2614
|
+
img.style.cursor = scale > 1 ? 'zoom-out' : 'zoom-in';
|
|
2615
|
+
img.style.transition = 'transform 0.2s ease';
|
|
2616
|
+
});
|
|
2617
|
+
// Touch: pinch to zoom + drag to pan
|
|
2618
|
+
let lastTouchDist = 0;
|
|
2619
|
+
let lastTouchScale = 1;
|
|
2620
|
+
overlay.addEventListener('touchstart', (e) => {
|
|
2621
|
+
if (e.touches.length === 2) {
|
|
2622
|
+
e.preventDefault();
|
|
2623
|
+
const dx = e.touches[0].clientX - e.touches[1].clientX;
|
|
2624
|
+
const dy = e.touches[0].clientY - e.touches[1].clientY;
|
|
2625
|
+
lastTouchDist = Math.hypot(dx, dy);
|
|
2626
|
+
lastTouchScale = scale;
|
|
2627
|
+
}
|
|
2628
|
+
else if (e.touches.length === 1 && scale > 1) {
|
|
2629
|
+
isDragging = true;
|
|
2630
|
+
dragStartX = e.touches[0].clientX;
|
|
2631
|
+
dragStartY = e.touches[0].clientY;
|
|
2632
|
+
lastTranslateX = translateX;
|
|
2633
|
+
lastTranslateY = translateY;
|
|
2634
|
+
img.style.transition = 'none';
|
|
2635
|
+
}
|
|
2636
|
+
}, { passive: false });
|
|
2637
|
+
overlay.addEventListener('touchmove', (e) => {
|
|
2638
|
+
if (e.touches.length === 2) {
|
|
2639
|
+
e.preventDefault();
|
|
2640
|
+
const dx = e.touches[0].clientX - e.touches[1].clientX;
|
|
2641
|
+
const dy = e.touches[0].clientY - e.touches[1].clientY;
|
|
2642
|
+
const dist = Math.hypot(dx, dy);
|
|
2643
|
+
scale = Math.min(Math.max(lastTouchScale * (dist / lastTouchDist), 1), 5);
|
|
2644
|
+
if (scale === 1) {
|
|
2645
|
+
translateX = 0;
|
|
2646
|
+
translateY = 0;
|
|
2647
|
+
}
|
|
2648
|
+
applyTransform();
|
|
2649
|
+
}
|
|
2650
|
+
else if (e.touches.length === 1 && isDragging) {
|
|
2651
|
+
e.preventDefault();
|
|
2652
|
+
translateX = lastTranslateX + (e.touches[0].clientX - dragStartX);
|
|
2653
|
+
translateY = lastTranslateY + (e.touches[0].clientY - dragStartY);
|
|
2654
|
+
applyTransform();
|
|
2655
|
+
}
|
|
2656
|
+
}, { passive: false });
|
|
2657
|
+
overlay.addEventListener('touchend', (e) => {
|
|
2658
|
+
if (e.touches.length < 2) {
|
|
2659
|
+
lastTouchDist = 0;
|
|
2660
|
+
}
|
|
2661
|
+
if (e.touches.length === 0) {
|
|
2662
|
+
isDragging = false;
|
|
2663
|
+
img.style.transition = 'transform 0.2s ease';
|
|
2664
|
+
}
|
|
2665
|
+
});
|
|
2666
|
+
const close = () => {
|
|
2667
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
2668
|
+
overlay.remove();
|
|
2669
|
+
};
|
|
2670
|
+
// Only close on backdrop click when not zoomed (prevent accidental close while panning)
|
|
2671
|
+
overlay.addEventListener('click', (e) => {
|
|
2672
|
+
if (e.target === overlay && scale <= 1)
|
|
2673
|
+
close();
|
|
2674
|
+
});
|
|
2675
|
+
downloadBtn.addEventListener('click', (e) => e.stopPropagation());
|
|
2676
|
+
closeBtn.addEventListener('click', (e) => { e.stopPropagation(); close(); });
|
|
2677
|
+
// Close on Escape
|
|
2678
|
+
const handleKeyDown = (e) => {
|
|
2679
|
+
if (e.key === 'Escape')
|
|
2680
|
+
close();
|
|
2681
|
+
};
|
|
2682
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
2683
|
+
overlay.appendChild(closeBtn);
|
|
2684
|
+
overlay.appendChild(downloadBtn);
|
|
2685
|
+
overlay.appendChild(img);
|
|
2686
|
+
document.body.appendChild(overlay);
|
|
2485
2687
|
}
|
|
2486
2688
|
/**
|
|
2487
2689
|
* Initialize the SDK and render widget
|
|
@@ -2593,8 +2795,6 @@ class WeldSDK {
|
|
|
2593
2795
|
console.log('[Weld SDK] Opening widget...');
|
|
2594
2796
|
this.stateCoordinator.openWidget();
|
|
2595
2797
|
this.iframeManager.showIframe(IframeType.WIDGET);
|
|
2596
|
-
this.iframeManager.showIframe(IframeType.BACKDROP);
|
|
2597
|
-
// Keep launcher visible so user can click it to close the widget
|
|
2598
2798
|
// Send open message to the widget iframe
|
|
2599
2799
|
const widgetIframe = this.iframeManager.getIframe(IframeType.WIDGET);
|
|
2600
2800
|
if (widgetIframe?.element?.contentWindow) {
|
|
@@ -2615,8 +2815,6 @@ class WeldSDK {
|
|
|
2615
2815
|
console.log('[Weld SDK] Closing widget...');
|
|
2616
2816
|
this.stateCoordinator.closeWidget();
|
|
2617
2817
|
this.iframeManager.hideIframe(IframeType.WIDGET);
|
|
2618
|
-
this.iframeManager.hideIframe(IframeType.BACKDROP);
|
|
2619
|
-
// Launcher stays visible
|
|
2620
2818
|
// Send close message to the widget iframe
|
|
2621
2819
|
const widgetIframe = this.iframeManager.getIframe(IframeType.WIDGET);
|
|
2622
2820
|
if (widgetIframe?.element?.contentWindow) {
|