@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/react.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/react.esm.js
CHANGED
|
@@ -510,14 +510,16 @@ class IframeManager {
|
|
|
510
510
|
const container = document.createElement('div');
|
|
511
511
|
container.className = 'weld-launcher-frame';
|
|
512
512
|
container.setAttribute('data-state', 'visible');
|
|
513
|
+
// Container is larger than the button to allow hover animations (scale, shadow) without clipping
|
|
514
|
+
const launcherPadding = 10;
|
|
513
515
|
container.style.cssText = `
|
|
514
516
|
position: fixed;
|
|
515
|
-
bottom: ${launcher.position.bottom};
|
|
516
|
-
right: ${launcher.position.right};
|
|
517
|
-
width: ${launcher.size};
|
|
518
|
-
height: ${launcher.size};
|
|
517
|
+
bottom: calc(${launcher.position.bottom} - ${launcherPadding}px);
|
|
518
|
+
right: calc(${launcher.position.right} - ${launcherPadding}px);
|
|
519
|
+
width: calc(${launcher.size} + ${launcherPadding * 2}px);
|
|
520
|
+
height: calc(${launcher.size} + ${launcherPadding * 2}px);
|
|
519
521
|
z-index: 2147483003;
|
|
520
|
-
pointer-events:
|
|
522
|
+
pointer-events: none;
|
|
521
523
|
display: block;
|
|
522
524
|
`;
|
|
523
525
|
// Create iframe
|
|
@@ -531,6 +533,7 @@ class IframeManager {
|
|
|
531
533
|
border: none;
|
|
532
534
|
background: transparent;
|
|
533
535
|
display: block;
|
|
536
|
+
pointer-events: auto;
|
|
534
537
|
`;
|
|
535
538
|
iframe.setAttribute('allow', 'clipboard-write');
|
|
536
539
|
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups');
|
|
@@ -651,43 +654,10 @@ class IframeManager {
|
|
|
651
654
|
this.logger.debug('Widget iframe created');
|
|
652
655
|
}
|
|
653
656
|
/**
|
|
654
|
-
* Create backdrop iframe
|
|
657
|
+
* Create backdrop iframe — disabled, widget stays non-modal so users can interact with the page
|
|
655
658
|
*/
|
|
656
659
|
async createBackdropIframe() {
|
|
657
|
-
|
|
658
|
-
this.logger.debug('Backdrop disabled, skipping creation');
|
|
659
|
-
return;
|
|
660
|
-
}
|
|
661
|
-
// Create container
|
|
662
|
-
const container = document.createElement('div');
|
|
663
|
-
container.className = 'weld-backdrop-frame';
|
|
664
|
-
container.setAttribute('data-state', 'hidden');
|
|
665
|
-
container.style.cssText = `
|
|
666
|
-
position: fixed;
|
|
667
|
-
top: 0;
|
|
668
|
-
left: 0;
|
|
669
|
-
right: 0;
|
|
670
|
-
bottom: 0;
|
|
671
|
-
z-index: 2147483000;
|
|
672
|
-
background: transparent;
|
|
673
|
-
pointer-events: none;
|
|
674
|
-
opacity: 0;
|
|
675
|
-
transition: opacity 200ms ease;
|
|
676
|
-
`;
|
|
677
|
-
this.appContainer?.appendChild(container);
|
|
678
|
-
// Store metadata (backdrop doesn't have an iframe, just a div)
|
|
679
|
-
// We'll create a minimal "iframe" reference for consistency
|
|
680
|
-
const dummyIframe = document.createElement('iframe');
|
|
681
|
-
dummyIframe.style.display = 'none';
|
|
682
|
-
this.iframes.set(IframeType.BACKDROP, {
|
|
683
|
-
type: IframeType.BACKDROP,
|
|
684
|
-
element: dummyIframe,
|
|
685
|
-
container,
|
|
686
|
-
ready: true, // Backdrop is always ready
|
|
687
|
-
visible: false,
|
|
688
|
-
createdAt: Date.now(),
|
|
689
|
-
});
|
|
690
|
-
this.logger.debug('Backdrop created');
|
|
660
|
+
this.logger.debug('Backdrop disabled, skipping creation');
|
|
691
661
|
}
|
|
692
662
|
/**
|
|
693
663
|
* Build iframe URL with parameters
|
|
@@ -2188,7 +2158,7 @@ class StateCoordinator {
|
|
|
2188
2158
|
}
|
|
2189
2159
|
}
|
|
2190
2160
|
|
|
2191
|
-
var version = "1.0.
|
|
2161
|
+
var version = "1.0.16";
|
|
2192
2162
|
var packageJson = {
|
|
2193
2163
|
version: version};
|
|
2194
2164
|
|
|
@@ -2271,6 +2241,242 @@ class WeldSDK {
|
|
|
2271
2241
|
console.log('[Weld SDK] Widget close requested');
|
|
2272
2242
|
this.close();
|
|
2273
2243
|
}
|
|
2244
|
+
if (event.data?.type === 'weld:image:open' && event.data?.url) {
|
|
2245
|
+
this.showImageLightbox(event.data.url);
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
/**
|
|
2249
|
+
* Show fullscreen image lightbox on the parent page
|
|
2250
|
+
*/
|
|
2251
|
+
showImageLightbox(url) {
|
|
2252
|
+
// Remove existing lightbox if any
|
|
2253
|
+
const existing = document.getElementById('weld-image-lightbox');
|
|
2254
|
+
if (existing)
|
|
2255
|
+
existing.remove();
|
|
2256
|
+
// Zoom / pan state
|
|
2257
|
+
let scale = 1;
|
|
2258
|
+
let translateX = 0;
|
|
2259
|
+
let translateY = 0;
|
|
2260
|
+
let isDragging = false;
|
|
2261
|
+
let dragStartX = 0;
|
|
2262
|
+
let dragStartY = 0;
|
|
2263
|
+
let lastTranslateX = 0;
|
|
2264
|
+
let lastTranslateY = 0;
|
|
2265
|
+
const applyTransform = () => {
|
|
2266
|
+
img.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`;
|
|
2267
|
+
};
|
|
2268
|
+
const resetTransform = () => {
|
|
2269
|
+
scale = 1;
|
|
2270
|
+
translateX = 0;
|
|
2271
|
+
translateY = 0;
|
|
2272
|
+
applyTransform();
|
|
2273
|
+
img.style.cursor = 'zoom-in';
|
|
2274
|
+
};
|
|
2275
|
+
const overlay = document.createElement('div');
|
|
2276
|
+
overlay.id = 'weld-image-lightbox';
|
|
2277
|
+
overlay.style.cssText = `
|
|
2278
|
+
position: fixed;
|
|
2279
|
+
inset: 0;
|
|
2280
|
+
z-index: 2147483647;
|
|
2281
|
+
background: rgba(0, 0, 0, 0.92);
|
|
2282
|
+
display: flex;
|
|
2283
|
+
align-items: center;
|
|
2284
|
+
justify-content: center;
|
|
2285
|
+
padding: 16px;
|
|
2286
|
+
cursor: pointer;
|
|
2287
|
+
overflow: hidden;
|
|
2288
|
+
`;
|
|
2289
|
+
// Close button
|
|
2290
|
+
const closeBtn = document.createElement('button');
|
|
2291
|
+
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>`;
|
|
2292
|
+
closeBtn.style.cssText = `
|
|
2293
|
+
position: absolute;
|
|
2294
|
+
top: 16px;
|
|
2295
|
+
right: 16px;
|
|
2296
|
+
width: 40px;
|
|
2297
|
+
height: 40px;
|
|
2298
|
+
border-radius: 50%;
|
|
2299
|
+
border: none;
|
|
2300
|
+
background: rgba(255, 255, 255, 0.1);
|
|
2301
|
+
color: white;
|
|
2302
|
+
cursor: pointer;
|
|
2303
|
+
display: flex;
|
|
2304
|
+
align-items: center;
|
|
2305
|
+
justify-content: center;
|
|
2306
|
+
transition: background 0.15s;
|
|
2307
|
+
`;
|
|
2308
|
+
closeBtn.onmouseenter = () => { closeBtn.style.background = 'rgba(255, 255, 255, 0.2)'; };
|
|
2309
|
+
closeBtn.onmouseleave = () => { closeBtn.style.background = 'rgba(255, 255, 255, 0.1)'; };
|
|
2310
|
+
// Download button
|
|
2311
|
+
const downloadBtn = document.createElement('a');
|
|
2312
|
+
downloadBtn.href = url;
|
|
2313
|
+
downloadBtn.download = '';
|
|
2314
|
+
downloadBtn.target = '_blank';
|
|
2315
|
+
downloadBtn.rel = 'noopener noreferrer';
|
|
2316
|
+
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>`;
|
|
2317
|
+
downloadBtn.style.cssText = `
|
|
2318
|
+
position: absolute;
|
|
2319
|
+
top: 16px;
|
|
2320
|
+
right: 64px;
|
|
2321
|
+
width: 40px;
|
|
2322
|
+
height: 40px;
|
|
2323
|
+
border-radius: 50%;
|
|
2324
|
+
border: none;
|
|
2325
|
+
background: rgba(255, 255, 255, 0.1);
|
|
2326
|
+
color: white;
|
|
2327
|
+
cursor: pointer;
|
|
2328
|
+
display: flex;
|
|
2329
|
+
align-items: center;
|
|
2330
|
+
justify-content: center;
|
|
2331
|
+
transition: background 0.15s;
|
|
2332
|
+
text-decoration: none;
|
|
2333
|
+
`;
|
|
2334
|
+
downloadBtn.onmouseenter = () => { downloadBtn.style.background = 'rgba(255, 255, 255, 0.2)'; };
|
|
2335
|
+
downloadBtn.onmouseleave = () => { downloadBtn.style.background = 'rgba(255, 255, 255, 0.1)'; };
|
|
2336
|
+
// Image
|
|
2337
|
+
const img = document.createElement('img');
|
|
2338
|
+
img.src = url;
|
|
2339
|
+
img.alt = 'Full size';
|
|
2340
|
+
img.draggable = false;
|
|
2341
|
+
img.style.cssText = `
|
|
2342
|
+
max-width: 100%;
|
|
2343
|
+
max-height: 100%;
|
|
2344
|
+
object-fit: contain;
|
|
2345
|
+
border-radius: 8px;
|
|
2346
|
+
cursor: zoom-in;
|
|
2347
|
+
transition: transform 0.2s ease;
|
|
2348
|
+
user-select: none;
|
|
2349
|
+
`;
|
|
2350
|
+
// Click to toggle zoom
|
|
2351
|
+
img.addEventListener('click', (e) => {
|
|
2352
|
+
e.stopPropagation();
|
|
2353
|
+
if (scale === 1) {
|
|
2354
|
+
// Zoom in to 2.5x centered on click position
|
|
2355
|
+
const rect = img.getBoundingClientRect();
|
|
2356
|
+
const clickX = e.clientX - rect.left - rect.width / 2;
|
|
2357
|
+
const clickY = e.clientY - rect.top - rect.height / 2;
|
|
2358
|
+
scale = 2.5;
|
|
2359
|
+
translateX = -clickX * 1.5;
|
|
2360
|
+
translateY = -clickY * 1.5;
|
|
2361
|
+
applyTransform();
|
|
2362
|
+
img.style.cursor = 'zoom-out';
|
|
2363
|
+
}
|
|
2364
|
+
else {
|
|
2365
|
+
// Zoom out - reset
|
|
2366
|
+
resetTransform();
|
|
2367
|
+
}
|
|
2368
|
+
});
|
|
2369
|
+
// Mouse wheel zoom
|
|
2370
|
+
overlay.addEventListener('wheel', (e) => {
|
|
2371
|
+
e.preventDefault();
|
|
2372
|
+
const delta = e.deltaY > 0 ? -0.25 : 0.25;
|
|
2373
|
+
const newScale = Math.min(Math.max(scale + delta, 1), 5);
|
|
2374
|
+
if (newScale === 1) {
|
|
2375
|
+
resetTransform();
|
|
2376
|
+
}
|
|
2377
|
+
else {
|
|
2378
|
+
scale = newScale;
|
|
2379
|
+
applyTransform();
|
|
2380
|
+
img.style.cursor = 'zoom-out';
|
|
2381
|
+
}
|
|
2382
|
+
}, { passive: false });
|
|
2383
|
+
// Drag to pan when zoomed
|
|
2384
|
+
img.addEventListener('mousedown', (e) => {
|
|
2385
|
+
if (scale <= 1)
|
|
2386
|
+
return;
|
|
2387
|
+
e.preventDefault();
|
|
2388
|
+
isDragging = true;
|
|
2389
|
+
dragStartX = e.clientX;
|
|
2390
|
+
dragStartY = e.clientY;
|
|
2391
|
+
lastTranslateX = translateX;
|
|
2392
|
+
lastTranslateY = translateY;
|
|
2393
|
+
img.style.cursor = 'grabbing';
|
|
2394
|
+
img.style.transition = 'none';
|
|
2395
|
+
});
|
|
2396
|
+
window.addEventListener('mousemove', (e) => {
|
|
2397
|
+
if (!isDragging)
|
|
2398
|
+
return;
|
|
2399
|
+
translateX = lastTranslateX + (e.clientX - dragStartX);
|
|
2400
|
+
translateY = lastTranslateY + (e.clientY - dragStartY);
|
|
2401
|
+
applyTransform();
|
|
2402
|
+
});
|
|
2403
|
+
window.addEventListener('mouseup', () => {
|
|
2404
|
+
if (!isDragging)
|
|
2405
|
+
return;
|
|
2406
|
+
isDragging = false;
|
|
2407
|
+
img.style.cursor = scale > 1 ? 'zoom-out' : 'zoom-in';
|
|
2408
|
+
img.style.transition = 'transform 0.2s ease';
|
|
2409
|
+
});
|
|
2410
|
+
// Touch: pinch to zoom + drag to pan
|
|
2411
|
+
let lastTouchDist = 0;
|
|
2412
|
+
let lastTouchScale = 1;
|
|
2413
|
+
overlay.addEventListener('touchstart', (e) => {
|
|
2414
|
+
if (e.touches.length === 2) {
|
|
2415
|
+
e.preventDefault();
|
|
2416
|
+
const dx = e.touches[0].clientX - e.touches[1].clientX;
|
|
2417
|
+
const dy = e.touches[0].clientY - e.touches[1].clientY;
|
|
2418
|
+
lastTouchDist = Math.hypot(dx, dy);
|
|
2419
|
+
lastTouchScale = scale;
|
|
2420
|
+
}
|
|
2421
|
+
else if (e.touches.length === 1 && scale > 1) {
|
|
2422
|
+
isDragging = true;
|
|
2423
|
+
dragStartX = e.touches[0].clientX;
|
|
2424
|
+
dragStartY = e.touches[0].clientY;
|
|
2425
|
+
lastTranslateX = translateX;
|
|
2426
|
+
lastTranslateY = translateY;
|
|
2427
|
+
img.style.transition = 'none';
|
|
2428
|
+
}
|
|
2429
|
+
}, { passive: false });
|
|
2430
|
+
overlay.addEventListener('touchmove', (e) => {
|
|
2431
|
+
if (e.touches.length === 2) {
|
|
2432
|
+
e.preventDefault();
|
|
2433
|
+
const dx = e.touches[0].clientX - e.touches[1].clientX;
|
|
2434
|
+
const dy = e.touches[0].clientY - e.touches[1].clientY;
|
|
2435
|
+
const dist = Math.hypot(dx, dy);
|
|
2436
|
+
scale = Math.min(Math.max(lastTouchScale * (dist / lastTouchDist), 1), 5);
|
|
2437
|
+
if (scale === 1) {
|
|
2438
|
+
translateX = 0;
|
|
2439
|
+
translateY = 0;
|
|
2440
|
+
}
|
|
2441
|
+
applyTransform();
|
|
2442
|
+
}
|
|
2443
|
+
else if (e.touches.length === 1 && isDragging) {
|
|
2444
|
+
e.preventDefault();
|
|
2445
|
+
translateX = lastTranslateX + (e.touches[0].clientX - dragStartX);
|
|
2446
|
+
translateY = lastTranslateY + (e.touches[0].clientY - dragStartY);
|
|
2447
|
+
applyTransform();
|
|
2448
|
+
}
|
|
2449
|
+
}, { passive: false });
|
|
2450
|
+
overlay.addEventListener('touchend', (e) => {
|
|
2451
|
+
if (e.touches.length < 2) {
|
|
2452
|
+
lastTouchDist = 0;
|
|
2453
|
+
}
|
|
2454
|
+
if (e.touches.length === 0) {
|
|
2455
|
+
isDragging = false;
|
|
2456
|
+
img.style.transition = 'transform 0.2s ease';
|
|
2457
|
+
}
|
|
2458
|
+
});
|
|
2459
|
+
const close = () => {
|
|
2460
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
2461
|
+
overlay.remove();
|
|
2462
|
+
};
|
|
2463
|
+
// Only close on backdrop click when not zoomed (prevent accidental close while panning)
|
|
2464
|
+
overlay.addEventListener('click', (e) => {
|
|
2465
|
+
if (e.target === overlay && scale <= 1)
|
|
2466
|
+
close();
|
|
2467
|
+
});
|
|
2468
|
+
downloadBtn.addEventListener('click', (e) => e.stopPropagation());
|
|
2469
|
+
closeBtn.addEventListener('click', (e) => { e.stopPropagation(); close(); });
|
|
2470
|
+
// Close on Escape
|
|
2471
|
+
const handleKeyDown = (e) => {
|
|
2472
|
+
if (e.key === 'Escape')
|
|
2473
|
+
close();
|
|
2474
|
+
};
|
|
2475
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
2476
|
+
overlay.appendChild(closeBtn);
|
|
2477
|
+
overlay.appendChild(downloadBtn);
|
|
2478
|
+
overlay.appendChild(img);
|
|
2479
|
+
document.body.appendChild(overlay);
|
|
2274
2480
|
}
|
|
2275
2481
|
/**
|
|
2276
2482
|
* Initialize the SDK and render widget
|
|
@@ -2382,8 +2588,6 @@ class WeldSDK {
|
|
|
2382
2588
|
console.log('[Weld SDK] Opening widget...');
|
|
2383
2589
|
this.stateCoordinator.openWidget();
|
|
2384
2590
|
this.iframeManager.showIframe(IframeType.WIDGET);
|
|
2385
|
-
this.iframeManager.showIframe(IframeType.BACKDROP);
|
|
2386
|
-
// Keep launcher visible so user can click it to close the widget
|
|
2387
2591
|
// Send open message to the widget iframe
|
|
2388
2592
|
const widgetIframe = this.iframeManager.getIframe(IframeType.WIDGET);
|
|
2389
2593
|
if (widgetIframe?.element?.contentWindow) {
|
|
@@ -2404,8 +2608,6 @@ class WeldSDK {
|
|
|
2404
2608
|
console.log('[Weld SDK] Closing widget...');
|
|
2405
2609
|
this.stateCoordinator.closeWidget();
|
|
2406
2610
|
this.iframeManager.hideIframe(IframeType.WIDGET);
|
|
2407
|
-
this.iframeManager.hideIframe(IframeType.BACKDROP);
|
|
2408
|
-
// Launcher stays visible
|
|
2409
2611
|
// Send close message to the widget iframe
|
|
2410
2612
|
const widgetIframe = this.iframeManager.getIframe(IframeType.WIDGET);
|
|
2411
2613
|
if (widgetIframe?.element?.contentWindow) {
|