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