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