@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/angular.js
CHANGED
|
@@ -572,14 +572,16 @@ class IframeManager {
|
|
|
572
572
|
const container = document.createElement('div');
|
|
573
573
|
container.className = 'weld-launcher-frame';
|
|
574
574
|
container.setAttribute('data-state', 'visible');
|
|
575
|
+
// Container is larger than the button to allow hover animations (scale, shadow) without clipping
|
|
576
|
+
const launcherPadding = 10;
|
|
575
577
|
container.style.cssText = `
|
|
576
578
|
position: fixed;
|
|
577
|
-
bottom: ${launcher.position.bottom};
|
|
578
|
-
right: ${launcher.position.right};
|
|
579
|
-
width: ${launcher.size};
|
|
580
|
-
height: ${launcher.size};
|
|
579
|
+
bottom: calc(${launcher.position.bottom} - ${launcherPadding}px);
|
|
580
|
+
right: calc(${launcher.position.right} - ${launcherPadding}px);
|
|
581
|
+
width: calc(${launcher.size} + ${launcherPadding * 2}px);
|
|
582
|
+
height: calc(${launcher.size} + ${launcherPadding * 2}px);
|
|
581
583
|
z-index: 2147483003;
|
|
582
|
-
pointer-events:
|
|
584
|
+
pointer-events: none;
|
|
583
585
|
display: block;
|
|
584
586
|
`;
|
|
585
587
|
// Create iframe
|
|
@@ -593,6 +595,7 @@ class IframeManager {
|
|
|
593
595
|
border: none;
|
|
594
596
|
background: transparent;
|
|
595
597
|
display: block;
|
|
598
|
+
pointer-events: auto;
|
|
596
599
|
`;
|
|
597
600
|
iframe.setAttribute('allow', 'clipboard-write');
|
|
598
601
|
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups');
|
|
@@ -713,43 +716,10 @@ class IframeManager {
|
|
|
713
716
|
this.logger.debug('Widget iframe created');
|
|
714
717
|
}
|
|
715
718
|
/**
|
|
716
|
-
* Create backdrop iframe
|
|
719
|
+
* Create backdrop iframe — disabled, widget stays non-modal so users can interact with the page
|
|
717
720
|
*/
|
|
718
721
|
async createBackdropIframe() {
|
|
719
|
-
|
|
720
|
-
this.logger.debug('Backdrop disabled, skipping creation');
|
|
721
|
-
return;
|
|
722
|
-
}
|
|
723
|
-
// Create container
|
|
724
|
-
const container = document.createElement('div');
|
|
725
|
-
container.className = 'weld-backdrop-frame';
|
|
726
|
-
container.setAttribute('data-state', 'hidden');
|
|
727
|
-
container.style.cssText = `
|
|
728
|
-
position: fixed;
|
|
729
|
-
top: 0;
|
|
730
|
-
left: 0;
|
|
731
|
-
right: 0;
|
|
732
|
-
bottom: 0;
|
|
733
|
-
z-index: 2147483000;
|
|
734
|
-
background: transparent;
|
|
735
|
-
pointer-events: none;
|
|
736
|
-
opacity: 0;
|
|
737
|
-
transition: opacity 200ms ease;
|
|
738
|
-
`;
|
|
739
|
-
this.appContainer?.appendChild(container);
|
|
740
|
-
// Store metadata (backdrop doesn't have an iframe, just a div)
|
|
741
|
-
// We'll create a minimal "iframe" reference for consistency
|
|
742
|
-
const dummyIframe = document.createElement('iframe');
|
|
743
|
-
dummyIframe.style.display = 'none';
|
|
744
|
-
this.iframes.set(IframeType.BACKDROP, {
|
|
745
|
-
type: IframeType.BACKDROP,
|
|
746
|
-
element: dummyIframe,
|
|
747
|
-
container,
|
|
748
|
-
ready: true, // Backdrop is always ready
|
|
749
|
-
visible: false,
|
|
750
|
-
createdAt: Date.now(),
|
|
751
|
-
});
|
|
752
|
-
this.logger.debug('Backdrop created');
|
|
722
|
+
this.logger.debug('Backdrop disabled, skipping creation');
|
|
753
723
|
}
|
|
754
724
|
/**
|
|
755
725
|
* Build iframe URL with parameters
|
|
@@ -1087,11 +1057,7 @@ class SecurityManager {
|
|
|
1087
1057
|
* Validate message origin
|
|
1088
1058
|
*/
|
|
1089
1059
|
isOriginAllowed(origin) {
|
|
1090
|
-
//
|
|
1091
|
-
if (this.config.allowedOrigins?.length === 0) {
|
|
1092
|
-
return origin === window.location.origin;
|
|
1093
|
-
}
|
|
1094
|
-
// Check if origin is in allowed list
|
|
1060
|
+
// Check if origin is in allowed list (includes same-origin and programmatically added origins)
|
|
1095
1061
|
if (this.allowedOrigins.has(origin)) {
|
|
1096
1062
|
return true;
|
|
1097
1063
|
}
|
|
@@ -2254,7 +2220,7 @@ class StateCoordinator {
|
|
|
2254
2220
|
}
|
|
2255
2221
|
}
|
|
2256
2222
|
|
|
2257
|
-
var version = "1.0.
|
|
2223
|
+
var version = "1.0.16";
|
|
2258
2224
|
var packageJson = {
|
|
2259
2225
|
version: version};
|
|
2260
2226
|
|
|
@@ -2337,6 +2303,242 @@ class WeldSDK {
|
|
|
2337
2303
|
console.log('[Weld SDK] Widget close requested');
|
|
2338
2304
|
this.close();
|
|
2339
2305
|
}
|
|
2306
|
+
if (event.data?.type === 'weld:image:open' && event.data?.url) {
|
|
2307
|
+
this.showImageLightbox(event.data.url);
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
/**
|
|
2311
|
+
* Show fullscreen image lightbox on the parent page
|
|
2312
|
+
*/
|
|
2313
|
+
showImageLightbox(url) {
|
|
2314
|
+
// Remove existing lightbox if any
|
|
2315
|
+
const existing = document.getElementById('weld-image-lightbox');
|
|
2316
|
+
if (existing)
|
|
2317
|
+
existing.remove();
|
|
2318
|
+
// Zoom / pan state
|
|
2319
|
+
let scale = 1;
|
|
2320
|
+
let translateX = 0;
|
|
2321
|
+
let translateY = 0;
|
|
2322
|
+
let isDragging = false;
|
|
2323
|
+
let dragStartX = 0;
|
|
2324
|
+
let dragStartY = 0;
|
|
2325
|
+
let lastTranslateX = 0;
|
|
2326
|
+
let lastTranslateY = 0;
|
|
2327
|
+
const applyTransform = () => {
|
|
2328
|
+
img.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`;
|
|
2329
|
+
};
|
|
2330
|
+
const resetTransform = () => {
|
|
2331
|
+
scale = 1;
|
|
2332
|
+
translateX = 0;
|
|
2333
|
+
translateY = 0;
|
|
2334
|
+
applyTransform();
|
|
2335
|
+
img.style.cursor = 'zoom-in';
|
|
2336
|
+
};
|
|
2337
|
+
const overlay = document.createElement('div');
|
|
2338
|
+
overlay.id = 'weld-image-lightbox';
|
|
2339
|
+
overlay.style.cssText = `
|
|
2340
|
+
position: fixed;
|
|
2341
|
+
inset: 0;
|
|
2342
|
+
z-index: 2147483647;
|
|
2343
|
+
background: rgba(0, 0, 0, 0.92);
|
|
2344
|
+
display: flex;
|
|
2345
|
+
align-items: center;
|
|
2346
|
+
justify-content: center;
|
|
2347
|
+
padding: 16px;
|
|
2348
|
+
cursor: pointer;
|
|
2349
|
+
overflow: hidden;
|
|
2350
|
+
`;
|
|
2351
|
+
// Close button
|
|
2352
|
+
const closeBtn = document.createElement('button');
|
|
2353
|
+
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>`;
|
|
2354
|
+
closeBtn.style.cssText = `
|
|
2355
|
+
position: absolute;
|
|
2356
|
+
top: 16px;
|
|
2357
|
+
right: 16px;
|
|
2358
|
+
width: 40px;
|
|
2359
|
+
height: 40px;
|
|
2360
|
+
border-radius: 50%;
|
|
2361
|
+
border: none;
|
|
2362
|
+
background: rgba(255, 255, 255, 0.1);
|
|
2363
|
+
color: white;
|
|
2364
|
+
cursor: pointer;
|
|
2365
|
+
display: flex;
|
|
2366
|
+
align-items: center;
|
|
2367
|
+
justify-content: center;
|
|
2368
|
+
transition: background 0.15s;
|
|
2369
|
+
`;
|
|
2370
|
+
closeBtn.onmouseenter = () => { closeBtn.style.background = 'rgba(255, 255, 255, 0.2)'; };
|
|
2371
|
+
closeBtn.onmouseleave = () => { closeBtn.style.background = 'rgba(255, 255, 255, 0.1)'; };
|
|
2372
|
+
// Download button
|
|
2373
|
+
const downloadBtn = document.createElement('a');
|
|
2374
|
+
downloadBtn.href = url;
|
|
2375
|
+
downloadBtn.download = '';
|
|
2376
|
+
downloadBtn.target = '_blank';
|
|
2377
|
+
downloadBtn.rel = 'noopener noreferrer';
|
|
2378
|
+
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>`;
|
|
2379
|
+
downloadBtn.style.cssText = `
|
|
2380
|
+
position: absolute;
|
|
2381
|
+
top: 16px;
|
|
2382
|
+
right: 64px;
|
|
2383
|
+
width: 40px;
|
|
2384
|
+
height: 40px;
|
|
2385
|
+
border-radius: 50%;
|
|
2386
|
+
border: none;
|
|
2387
|
+
background: rgba(255, 255, 255, 0.1);
|
|
2388
|
+
color: white;
|
|
2389
|
+
cursor: pointer;
|
|
2390
|
+
display: flex;
|
|
2391
|
+
align-items: center;
|
|
2392
|
+
justify-content: center;
|
|
2393
|
+
transition: background 0.15s;
|
|
2394
|
+
text-decoration: none;
|
|
2395
|
+
`;
|
|
2396
|
+
downloadBtn.onmouseenter = () => { downloadBtn.style.background = 'rgba(255, 255, 255, 0.2)'; };
|
|
2397
|
+
downloadBtn.onmouseleave = () => { downloadBtn.style.background = 'rgba(255, 255, 255, 0.1)'; };
|
|
2398
|
+
// Image
|
|
2399
|
+
const img = document.createElement('img');
|
|
2400
|
+
img.src = url;
|
|
2401
|
+
img.alt = 'Full size';
|
|
2402
|
+
img.draggable = false;
|
|
2403
|
+
img.style.cssText = `
|
|
2404
|
+
max-width: 100%;
|
|
2405
|
+
max-height: 100%;
|
|
2406
|
+
object-fit: contain;
|
|
2407
|
+
border-radius: 8px;
|
|
2408
|
+
cursor: zoom-in;
|
|
2409
|
+
transition: transform 0.2s ease;
|
|
2410
|
+
user-select: none;
|
|
2411
|
+
`;
|
|
2412
|
+
// Click to toggle zoom
|
|
2413
|
+
img.addEventListener('click', (e) => {
|
|
2414
|
+
e.stopPropagation();
|
|
2415
|
+
if (scale === 1) {
|
|
2416
|
+
// Zoom in to 2.5x centered on click position
|
|
2417
|
+
const rect = img.getBoundingClientRect();
|
|
2418
|
+
const clickX = e.clientX - rect.left - rect.width / 2;
|
|
2419
|
+
const clickY = e.clientY - rect.top - rect.height / 2;
|
|
2420
|
+
scale = 2.5;
|
|
2421
|
+
translateX = -clickX * 1.5;
|
|
2422
|
+
translateY = -clickY * 1.5;
|
|
2423
|
+
applyTransform();
|
|
2424
|
+
img.style.cursor = 'zoom-out';
|
|
2425
|
+
}
|
|
2426
|
+
else {
|
|
2427
|
+
// Zoom out - reset
|
|
2428
|
+
resetTransform();
|
|
2429
|
+
}
|
|
2430
|
+
});
|
|
2431
|
+
// Mouse wheel zoom
|
|
2432
|
+
overlay.addEventListener('wheel', (e) => {
|
|
2433
|
+
e.preventDefault();
|
|
2434
|
+
const delta = e.deltaY > 0 ? -0.25 : 0.25;
|
|
2435
|
+
const newScale = Math.min(Math.max(scale + delta, 1), 5);
|
|
2436
|
+
if (newScale === 1) {
|
|
2437
|
+
resetTransform();
|
|
2438
|
+
}
|
|
2439
|
+
else {
|
|
2440
|
+
scale = newScale;
|
|
2441
|
+
applyTransform();
|
|
2442
|
+
img.style.cursor = 'zoom-out';
|
|
2443
|
+
}
|
|
2444
|
+
}, { passive: false });
|
|
2445
|
+
// Drag to pan when zoomed
|
|
2446
|
+
img.addEventListener('mousedown', (e) => {
|
|
2447
|
+
if (scale <= 1)
|
|
2448
|
+
return;
|
|
2449
|
+
e.preventDefault();
|
|
2450
|
+
isDragging = true;
|
|
2451
|
+
dragStartX = e.clientX;
|
|
2452
|
+
dragStartY = e.clientY;
|
|
2453
|
+
lastTranslateX = translateX;
|
|
2454
|
+
lastTranslateY = translateY;
|
|
2455
|
+
img.style.cursor = 'grabbing';
|
|
2456
|
+
img.style.transition = 'none';
|
|
2457
|
+
});
|
|
2458
|
+
window.addEventListener('mousemove', (e) => {
|
|
2459
|
+
if (!isDragging)
|
|
2460
|
+
return;
|
|
2461
|
+
translateX = lastTranslateX + (e.clientX - dragStartX);
|
|
2462
|
+
translateY = lastTranslateY + (e.clientY - dragStartY);
|
|
2463
|
+
applyTransform();
|
|
2464
|
+
});
|
|
2465
|
+
window.addEventListener('mouseup', () => {
|
|
2466
|
+
if (!isDragging)
|
|
2467
|
+
return;
|
|
2468
|
+
isDragging = false;
|
|
2469
|
+
img.style.cursor = scale > 1 ? 'zoom-out' : 'zoom-in';
|
|
2470
|
+
img.style.transition = 'transform 0.2s ease';
|
|
2471
|
+
});
|
|
2472
|
+
// Touch: pinch to zoom + drag to pan
|
|
2473
|
+
let lastTouchDist = 0;
|
|
2474
|
+
let lastTouchScale = 1;
|
|
2475
|
+
overlay.addEventListener('touchstart', (e) => {
|
|
2476
|
+
if (e.touches.length === 2) {
|
|
2477
|
+
e.preventDefault();
|
|
2478
|
+
const dx = e.touches[0].clientX - e.touches[1].clientX;
|
|
2479
|
+
const dy = e.touches[0].clientY - e.touches[1].clientY;
|
|
2480
|
+
lastTouchDist = Math.hypot(dx, dy);
|
|
2481
|
+
lastTouchScale = scale;
|
|
2482
|
+
}
|
|
2483
|
+
else if (e.touches.length === 1 && scale > 1) {
|
|
2484
|
+
isDragging = true;
|
|
2485
|
+
dragStartX = e.touches[0].clientX;
|
|
2486
|
+
dragStartY = e.touches[0].clientY;
|
|
2487
|
+
lastTranslateX = translateX;
|
|
2488
|
+
lastTranslateY = translateY;
|
|
2489
|
+
img.style.transition = 'none';
|
|
2490
|
+
}
|
|
2491
|
+
}, { passive: false });
|
|
2492
|
+
overlay.addEventListener('touchmove', (e) => {
|
|
2493
|
+
if (e.touches.length === 2) {
|
|
2494
|
+
e.preventDefault();
|
|
2495
|
+
const dx = e.touches[0].clientX - e.touches[1].clientX;
|
|
2496
|
+
const dy = e.touches[0].clientY - e.touches[1].clientY;
|
|
2497
|
+
const dist = Math.hypot(dx, dy);
|
|
2498
|
+
scale = Math.min(Math.max(lastTouchScale * (dist / lastTouchDist), 1), 5);
|
|
2499
|
+
if (scale === 1) {
|
|
2500
|
+
translateX = 0;
|
|
2501
|
+
translateY = 0;
|
|
2502
|
+
}
|
|
2503
|
+
applyTransform();
|
|
2504
|
+
}
|
|
2505
|
+
else if (e.touches.length === 1 && isDragging) {
|
|
2506
|
+
e.preventDefault();
|
|
2507
|
+
translateX = lastTranslateX + (e.touches[0].clientX - dragStartX);
|
|
2508
|
+
translateY = lastTranslateY + (e.touches[0].clientY - dragStartY);
|
|
2509
|
+
applyTransform();
|
|
2510
|
+
}
|
|
2511
|
+
}, { passive: false });
|
|
2512
|
+
overlay.addEventListener('touchend', (e) => {
|
|
2513
|
+
if (e.touches.length < 2) {
|
|
2514
|
+
lastTouchDist = 0;
|
|
2515
|
+
}
|
|
2516
|
+
if (e.touches.length === 0) {
|
|
2517
|
+
isDragging = false;
|
|
2518
|
+
img.style.transition = 'transform 0.2s ease';
|
|
2519
|
+
}
|
|
2520
|
+
});
|
|
2521
|
+
const close = () => {
|
|
2522
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
2523
|
+
overlay.remove();
|
|
2524
|
+
};
|
|
2525
|
+
// Only close on backdrop click when not zoomed (prevent accidental close while panning)
|
|
2526
|
+
overlay.addEventListener('click', (e) => {
|
|
2527
|
+
if (e.target === overlay && scale <= 1)
|
|
2528
|
+
close();
|
|
2529
|
+
});
|
|
2530
|
+
downloadBtn.addEventListener('click', (e) => e.stopPropagation());
|
|
2531
|
+
closeBtn.addEventListener('click', (e) => { e.stopPropagation(); close(); });
|
|
2532
|
+
// Close on Escape
|
|
2533
|
+
const handleKeyDown = (e) => {
|
|
2534
|
+
if (e.key === 'Escape')
|
|
2535
|
+
close();
|
|
2536
|
+
};
|
|
2537
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
2538
|
+
overlay.appendChild(closeBtn);
|
|
2539
|
+
overlay.appendChild(downloadBtn);
|
|
2540
|
+
overlay.appendChild(img);
|
|
2541
|
+
document.body.appendChild(overlay);
|
|
2340
2542
|
}
|
|
2341
2543
|
/**
|
|
2342
2544
|
* Initialize the SDK and render widget
|
|
@@ -2448,8 +2650,6 @@ class WeldSDK {
|
|
|
2448
2650
|
console.log('[Weld SDK] Opening widget...');
|
|
2449
2651
|
this.stateCoordinator.openWidget();
|
|
2450
2652
|
this.iframeManager.showIframe(IframeType.WIDGET);
|
|
2451
|
-
this.iframeManager.showIframe(IframeType.BACKDROP);
|
|
2452
|
-
// Keep launcher visible so user can click it to close the widget
|
|
2453
2653
|
// Send open message to the widget iframe
|
|
2454
2654
|
const widgetIframe = this.iframeManager.getIframe(IframeType.WIDGET);
|
|
2455
2655
|
if (widgetIframe?.element?.contentWindow) {
|
|
@@ -2470,8 +2670,6 @@ class WeldSDK {
|
|
|
2470
2670
|
console.log('[Weld SDK] Closing widget...');
|
|
2471
2671
|
this.stateCoordinator.closeWidget();
|
|
2472
2672
|
this.iframeManager.hideIframe(IframeType.WIDGET);
|
|
2473
|
-
this.iframeManager.hideIframe(IframeType.BACKDROP);
|
|
2474
|
-
// Launcher stays visible
|
|
2475
2673
|
// Send close message to the widget iframe
|
|
2476
2674
|
const widgetIframe = this.iframeManager.getIframe(IframeType.WIDGET);
|
|
2477
2675
|
if (widgetIframe?.element?.contentWindow) {
|