@wewear/virtual-try-on 1.3.5 → 1.3.7
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/components/alert-overlay.d.ts +2 -0
- package/dist/components/dom-alert.d.ts +2 -0
- package/dist/components/loading-overlay.d.ts +1 -1
- package/dist/components/review-modal.d.ts +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.esm.js +106 -58
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +106 -58
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ export declare function createLoadingOverlay(text?: string): HTMLElement;
|
|
|
5
5
|
/**
|
|
6
6
|
* Shows a loading overlay in a modal container
|
|
7
7
|
*/
|
|
8
|
-
export declare function showModalLoading(
|
|
8
|
+
export declare function showModalLoading(container: HTMLElement): void;
|
|
9
9
|
/**
|
|
10
10
|
* Removes loading overlay from modal
|
|
11
11
|
*/
|
|
@@ -2,4 +2,4 @@ export interface ReviewModalCallbacks {
|
|
|
2
2
|
onRetake: () => void;
|
|
3
3
|
onAccept: (imageBlob: Blob) => Promise<void>;
|
|
4
4
|
}
|
|
5
|
-
export declare function showReviewModal(imageBlob: Blob, callbacks: ReviewModalCallbacks
|
|
5
|
+
export declare function showReviewModal(imageBlob: Blob, callbacks: ReviewModalCallbacks): void;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,11 @@ export interface VirtualTryOnConfig {
|
|
|
6
6
|
buttonPosition: "bottom-right" | "bottom-left" | "top-right" | "top-left";
|
|
7
7
|
}
|
|
8
8
|
export interface VirtualTryOnResult {
|
|
9
|
-
imageUrl: string;
|
|
9
|
+
imageUrl: string | null;
|
|
10
|
+
error?: {
|
|
11
|
+
message: string;
|
|
12
|
+
type: 'error' | 'warning';
|
|
13
|
+
};
|
|
10
14
|
}
|
|
11
15
|
export interface VirtualTryOnAPIRequest {
|
|
12
16
|
ww_access_token: string;
|
package/dist/index.esm.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
async function callVirtualTryOnApi(baseUrl, ww_access_token, ww_user_id, ww_product_image, ww_image) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return null;
|
|
2
|
+
const formData = new FormData();
|
|
3
|
+
formData.append("ww_user_id", ww_user_id);
|
|
4
|
+
formData.append("ww_product_image", ww_product_image);
|
|
5
|
+
formData.append("ww_image", ww_image, "captured-image.jpg");
|
|
6
|
+
formData.append("ww_access_token", ww_access_token);
|
|
7
|
+
const response = await fetch(`${baseUrl}/api/virtual-try-on`, {
|
|
8
|
+
method: "POST",
|
|
9
|
+
body: formData,
|
|
10
|
+
});
|
|
11
|
+
if (!response.ok) {
|
|
12
|
+
console.error("[WeWear VTO] API request failed:", response.status, response.statusText);
|
|
13
|
+
if (response.status === 500) {
|
|
14
|
+
return { "imageUrl": null, "error": { message: `Service unavailable. Please try again later.`, type: 'error' } };
|
|
15
15
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
catch (error) {
|
|
21
|
-
console.error("[WeWear VTO] API call failed:", error);
|
|
22
|
-
return null;
|
|
16
|
+
else if (response.status === 503) {
|
|
17
|
+
return { "imageUrl": null, "error": { message: `Service overloaded. Please try again later.`, type: 'warning' } };
|
|
18
|
+
}
|
|
19
|
+
return { "imageUrl": null, "error": { message: `${response.statusText}`, type: 'warning' } };
|
|
23
20
|
}
|
|
21
|
+
const result = await response.json();
|
|
22
|
+
console.log("[WeWear VTO] API response:", result);
|
|
23
|
+
return result;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/** CSS class names for consistent styling */
|
|
@@ -430,23 +430,17 @@ function createLoadingOverlay(text = "Processing...") {
|
|
|
430
430
|
/**
|
|
431
431
|
* Shows a loading overlay in a modal container
|
|
432
432
|
*/
|
|
433
|
-
function showModalLoading(
|
|
434
|
-
const modal = document.querySelector(`.${CSS_CLASSES.MODAL}`);
|
|
435
|
-
if (!modal)
|
|
436
|
-
return;
|
|
433
|
+
function showModalLoading(container) {
|
|
437
434
|
// Remove any existing loading overlays
|
|
438
435
|
removeModalLoading();
|
|
439
|
-
|
|
440
|
-
|
|
436
|
+
// Show loading in the product area
|
|
437
|
+
showProductLoading(container);
|
|
441
438
|
}
|
|
442
439
|
/**
|
|
443
440
|
* Removes loading overlay from modal
|
|
444
441
|
*/
|
|
445
442
|
function removeModalLoading() {
|
|
446
|
-
const
|
|
447
|
-
if (!modal)
|
|
448
|
-
return;
|
|
449
|
-
const existingOverlay = modal.querySelector(".ww-loading-overlay");
|
|
443
|
+
const existingOverlay = document.body.querySelector(".ww-loading-overlay");
|
|
450
444
|
if (existingOverlay) {
|
|
451
445
|
existingOverlay.remove();
|
|
452
446
|
}
|
|
@@ -475,16 +469,7 @@ function removeProductLoading(container) {
|
|
|
475
469
|
}
|
|
476
470
|
}
|
|
477
471
|
|
|
478
|
-
|
|
479
|
-
__proto__: null,
|
|
480
|
-
createLoadingOverlay: createLoadingOverlay,
|
|
481
|
-
removeModalLoading: removeModalLoading,
|
|
482
|
-
removeProductLoading: removeProductLoading,
|
|
483
|
-
showModalLoading: showModalLoading,
|
|
484
|
-
showProductLoading: showProductLoading
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
function showReviewModal(imageBlob, callbacks, gallerySelector) {
|
|
472
|
+
function showReviewModal(imageBlob, callbacks) {
|
|
488
473
|
console.log("[WeWear VTO] Opening review modal...");
|
|
489
474
|
// Remove any existing modals first
|
|
490
475
|
removeElements(`.${CSS_CLASSES.MODAL}`);
|
|
@@ -601,10 +586,6 @@ function showReviewModal(imageBlob, callbacks, gallerySelector) {
|
|
|
601
586
|
callbacks.onRetake();
|
|
602
587
|
};
|
|
603
588
|
usePhotoButton.onclick = async () => {
|
|
604
|
-
Promise.resolve().then(function () { return loadingOverlay; }).then(({ showProductLoading }) => {
|
|
605
|
-
const container = document.querySelector(gallerySelector);
|
|
606
|
-
showProductLoading(container, "Generating new virtual try-on...");
|
|
607
|
-
});
|
|
608
589
|
URL.revokeObjectURL(imageUrl); // Clean up
|
|
609
590
|
modal.remove();
|
|
610
591
|
await callbacks.onAccept(imageBlob);
|
|
@@ -620,6 +601,74 @@ function showReviewModal(imageBlob, callbacks, gallerySelector) {
|
|
|
620
601
|
console.log("[WeWear VTO] Review modal added to DOM");
|
|
621
602
|
}
|
|
622
603
|
|
|
604
|
+
function showAlert(container, message, type) {
|
|
605
|
+
var _a;
|
|
606
|
+
removeAlert(container); // Remove any existing alert
|
|
607
|
+
const alertDiv = document.createElement('div');
|
|
608
|
+
alertDiv.className = `ww-alert ww-alert-${type}`;
|
|
609
|
+
alertDiv.setAttribute('role', type === 'error' ? 'alert' : 'status');
|
|
610
|
+
alertDiv.setAttribute('aria-live', 'assertive');
|
|
611
|
+
alertDiv.style.cssText = `
|
|
612
|
+
position: absolute;
|
|
613
|
+
top: 16px;
|
|
614
|
+
left: 50%;
|
|
615
|
+
transform: translateX(-50%) translateY(-10px);
|
|
616
|
+
background: ${type === 'error' ? '#FEE2E2' : '#FEF9C3'};
|
|
617
|
+
color: ${type === 'error' ? '#B91C1C' : '#92400E'};
|
|
618
|
+
border: 1px solid ${type === 'error' ? '#F87171' : '#FBBF24'};
|
|
619
|
+
border-radius: 8px;
|
|
620
|
+
padding: 12px 16px;
|
|
621
|
+
z-index: 9999;
|
|
622
|
+
font-size: 15px;
|
|
623
|
+
font-weight: 500;
|
|
624
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
625
|
+
display: flex;
|
|
626
|
+
align-items: center;
|
|
627
|
+
min-width: 220px;
|
|
628
|
+
max-width: 90%;
|
|
629
|
+
opacity: 0;
|
|
630
|
+
transition: opacity 0.3s ease, transform 0.3s ease;
|
|
631
|
+
`;
|
|
632
|
+
alertDiv.innerHTML = `
|
|
633
|
+
<span style="flex: 1; line-height: 1.4;">${message}</span>
|
|
634
|
+
<button type="button" aria-label="Close alert"
|
|
635
|
+
style="
|
|
636
|
+
background: none;
|
|
637
|
+
border: none;
|
|
638
|
+
font-size: 20px;
|
|
639
|
+
color: inherit;
|
|
640
|
+
cursor: pointer;
|
|
641
|
+
margin-left: 12px;
|
|
642
|
+
padding: 0;
|
|
643
|
+
line-height: 1;
|
|
644
|
+
">
|
|
645
|
+
×
|
|
646
|
+
</button>
|
|
647
|
+
`;
|
|
648
|
+
// Close on button click
|
|
649
|
+
(_a = alertDiv.querySelector('button')) === null || _a === void 0 ? void 0 : _a.addEventListener('click', () => {
|
|
650
|
+
fadeOutAndRemove(alertDiv);
|
|
651
|
+
});
|
|
652
|
+
container.appendChild(alertDiv);
|
|
653
|
+
// Animate in
|
|
654
|
+
requestAnimationFrame(() => {
|
|
655
|
+
alertDiv.style.opacity = '1';
|
|
656
|
+
alertDiv.style.transform = 'translateX(-50%) translateY(0)';
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
function fadeOutAndRemove(element) {
|
|
660
|
+
element.style.opacity = '0';
|
|
661
|
+
element.style.transform = 'translateX(-50%) translateY(-10px)';
|
|
662
|
+
setTimeout(() => {
|
|
663
|
+
element.remove();
|
|
664
|
+
}, 300);
|
|
665
|
+
}
|
|
666
|
+
function removeAlert(container) {
|
|
667
|
+
const alert = container.querySelector('.ww-alert');
|
|
668
|
+
if (alert)
|
|
669
|
+
fadeOutAndRemove(alert);
|
|
670
|
+
}
|
|
671
|
+
|
|
623
672
|
class VirtualTryOnWidget {
|
|
624
673
|
constructor(config) {
|
|
625
674
|
this.virtualTryOnImageUrl = null;
|
|
@@ -764,20 +813,20 @@ class VirtualTryOnWidget {
|
|
|
764
813
|
this.showCameraModalWithCallbacks(ww_access_token, ww_user_id, ww_product_image);
|
|
765
814
|
},
|
|
766
815
|
onAccept: async (acceptedImageBlob) => {
|
|
767
|
-
await this.processAcceptedImage(acceptedImageBlob, ww_access_token, ww_user_id, ww_product_image);
|
|
816
|
+
await this.processAcceptedImage(acceptedImageBlob, ww_access_token, ww_user_id, ww_product_image, document.querySelector(this.config.gallerySelector));
|
|
768
817
|
},
|
|
769
818
|
};
|
|
770
|
-
showReviewModal(imageBlob, callbacks
|
|
819
|
+
showReviewModal(imageBlob, callbacks);
|
|
771
820
|
}
|
|
772
821
|
/**
|
|
773
822
|
* Processes the accepted image by calling the API
|
|
774
823
|
* @private
|
|
775
824
|
*/
|
|
776
|
-
async processAcceptedImage(imageBlob, ww_access_token, ww_user_id, ww_product_image) {
|
|
825
|
+
async processAcceptedImage(imageBlob, ww_access_token, ww_user_id, ww_product_image, container) {
|
|
777
826
|
try {
|
|
778
827
|
console.log("[WeWear VTO] Processing accepted image...");
|
|
779
828
|
// Show loading in the review modal first
|
|
780
|
-
showModalLoading(
|
|
829
|
+
showModalLoading(container);
|
|
781
830
|
// Store the API parameters for potential refresh
|
|
782
831
|
this.lastApiParams = {
|
|
783
832
|
imageBlob,
|
|
@@ -793,8 +842,8 @@ class VirtualTryOnWidget {
|
|
|
793
842
|
if (result === null || result === void 0 ? void 0 : result.imageUrl) {
|
|
794
843
|
this.replaceProductImage(result.imageUrl);
|
|
795
844
|
}
|
|
796
|
-
else {
|
|
797
|
-
|
|
845
|
+
else if (result === null || result === void 0 ? void 0 : result.error) {
|
|
846
|
+
showAlert(container, result.error.message, result.error.type);
|
|
798
847
|
}
|
|
799
848
|
}
|
|
800
849
|
catch (error) {
|
|
@@ -831,12 +880,11 @@ class VirtualTryOnWidget {
|
|
|
831
880
|
this.updateButtonContainer(container);
|
|
832
881
|
}
|
|
833
882
|
}
|
|
834
|
-
else {
|
|
835
|
-
console.error("[WeWear VTO] Invalid API response on refresh:", result);
|
|
836
|
-
// Remove loading on error
|
|
883
|
+
else if (result === null || result === void 0 ? void 0 : result.error) {
|
|
837
884
|
const container = document.querySelector(this.config.gallerySelector);
|
|
838
885
|
if (container instanceof HTMLElement) {
|
|
839
886
|
removeProductLoading(container);
|
|
887
|
+
showAlert(container, result.error.message, result.error.type);
|
|
840
888
|
}
|
|
841
889
|
}
|
|
842
890
|
}
|
|
@@ -950,11 +998,11 @@ class VirtualTryOnWidget {
|
|
|
950
998
|
else if (originalRectHeight && originalRectHeight !== '0') {
|
|
951
999
|
heightStyle = `${originalRectHeight}px`;
|
|
952
1000
|
}
|
|
953
|
-
image.style.cssText = `
|
|
954
|
-
width: ${widthStyle};
|
|
955
|
-
height: ${heightStyle};
|
|
956
|
-
object-fit: cover;
|
|
957
|
-
border-radius: 8px;
|
|
1001
|
+
image.style.cssText = `
|
|
1002
|
+
width: ${widthStyle};
|
|
1003
|
+
height: ${heightStyle};
|
|
1004
|
+
object-fit: cover;
|
|
1005
|
+
border-radius: 8px;
|
|
958
1006
|
`;
|
|
959
1007
|
container.appendChild(image);
|
|
960
1008
|
// Re-add buttons
|