@wewear/virtual-try-on 1.4.26 → 1.4.28
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/index.d.ts +3 -2
- package/dist/index.esm.js +84 -96
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +84 -95
- package/dist/index.js.map +1 -1
- package/dist/installer.d.ts +1 -0
- package/dist/widget.d.ts +6 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -26,12 +26,6 @@
|
|
|
26
26
|
return "right: 20px; bottom: 20px;";
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
function removeElements(selector) {
|
|
30
|
-
const elements = document.querySelectorAll(selector);
|
|
31
|
-
elements.forEach((element) => {
|
|
32
|
-
element.remove();
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
29
|
|
|
36
30
|
function createButtonContainer(buttonPosition, hasVirtualTryOn = false, onCameraClick, onRefreshClick, onToggleClick, isShowingVirtualTryOn = false) {
|
|
37
31
|
const container = document.createElement("div");
|
|
@@ -401,7 +395,9 @@
|
|
|
401
395
|
this.isShowingVirtualTryOn = false;
|
|
402
396
|
this.lastModelImage = null;
|
|
403
397
|
this.cameraButton = null;
|
|
398
|
+
this.modalElement = null;
|
|
404
399
|
this.iframeMessageListener = null;
|
|
400
|
+
this.instanceId = ++VirtualTryOnWidget.instanceCounter;
|
|
405
401
|
this.config = {
|
|
406
402
|
baseUrl: config.baseUrl,
|
|
407
403
|
productPageSelector: config.productPageSelector,
|
|
@@ -409,10 +405,19 @@
|
|
|
409
405
|
productImageSelector: config.productImageSelector,
|
|
410
406
|
buttonPosition: config.buttonPosition,
|
|
411
407
|
modelTier: config.modelTier,
|
|
412
|
-
greenSuit: config.greenSuit,
|
|
413
408
|
outfitID: config.outfitID,
|
|
409
|
+
singleton: config.singleton,
|
|
410
|
+
galleryElement: config.galleryElement,
|
|
414
411
|
};
|
|
415
412
|
}
|
|
413
|
+
getContainer() {
|
|
414
|
+
const configContainer = this.config.galleryElement;
|
|
415
|
+
if (configContainer && configContainer.isConnected) {
|
|
416
|
+
return configContainer;
|
|
417
|
+
}
|
|
418
|
+
const queriedContainer = document.querySelector(this.config.gallerySelector);
|
|
419
|
+
return queriedContainer instanceof HTMLElement ? queriedContainer : null;
|
|
420
|
+
}
|
|
416
421
|
async init() {
|
|
417
422
|
try {
|
|
418
423
|
const selectors = this.config.productPageSelector;
|
|
@@ -421,8 +426,8 @@
|
|
|
421
426
|
if (!matches) {
|
|
422
427
|
return;
|
|
423
428
|
}
|
|
424
|
-
const container =
|
|
425
|
-
if (!container
|
|
429
|
+
const container = this.getContainer();
|
|
430
|
+
if (!container) {
|
|
426
431
|
console.warn("[WeWear VTO] Gallery container not found:", this.config.gallerySelector);
|
|
427
432
|
return;
|
|
428
433
|
}
|
|
@@ -469,7 +474,10 @@
|
|
|
469
474
|
}
|
|
470
475
|
}
|
|
471
476
|
getAllProductImages() {
|
|
472
|
-
const
|
|
477
|
+
const container = this.getContainer();
|
|
478
|
+
const scopedElements = container === null || container === void 0 ? void 0 : container.querySelectorAll(this.config.productImageSelector);
|
|
479
|
+
const fallbackElements = document.querySelectorAll(this.config.productImageSelector);
|
|
480
|
+
const productImageElements = ((scopedElements === null || scopedElements === void 0 ? void 0 : scopedElements.length) ? scopedElements : fallbackElements);
|
|
473
481
|
const images = [];
|
|
474
482
|
productImageElements.forEach((img) => {
|
|
475
483
|
const imageUrl = img.src ||
|
|
@@ -485,7 +493,8 @@
|
|
|
485
493
|
return images;
|
|
486
494
|
}
|
|
487
495
|
showPhotoUploadModal(url) {
|
|
488
|
-
|
|
496
|
+
this.closeModal();
|
|
497
|
+
VirtualTryOnWidget.activeWidgetId = this.instanceId;
|
|
489
498
|
const modal = document.createElement("div");
|
|
490
499
|
modal.className = CSS_CLASSES.MODAL;
|
|
491
500
|
modal.style.cssText = `
|
|
@@ -579,7 +588,7 @@
|
|
|
579
588
|
modal.style.opacity = "0";
|
|
580
589
|
iframeContainer.style.transform = "scale(0.95)";
|
|
581
590
|
iframeContainer.style.opacity = "0";
|
|
582
|
-
setTimeout(() =>
|
|
591
|
+
setTimeout(() => this.closeModal(), 300);
|
|
583
592
|
};
|
|
584
593
|
iframeContainer.appendChild(iframe);
|
|
585
594
|
iframeContainer.appendChild(closeButton);
|
|
@@ -590,12 +599,25 @@
|
|
|
590
599
|
closeButton.click();
|
|
591
600
|
}
|
|
592
601
|
};
|
|
602
|
+
this.modalElement = modal;
|
|
603
|
+
}
|
|
604
|
+
closeModal() {
|
|
605
|
+
if (this.modalElement) {
|
|
606
|
+
this.modalElement.remove();
|
|
607
|
+
this.modalElement = null;
|
|
608
|
+
}
|
|
609
|
+
if (VirtualTryOnWidget.activeWidgetId === this.instanceId) {
|
|
610
|
+
VirtualTryOnWidget.activeWidgetId = null;
|
|
611
|
+
}
|
|
593
612
|
}
|
|
594
613
|
setupIframeListener() {
|
|
595
614
|
if (this.iframeMessageListener) {
|
|
596
615
|
window.removeEventListener("message", this.iframeMessageListener);
|
|
597
616
|
}
|
|
598
617
|
this.iframeMessageListener = (event) => {
|
|
618
|
+
if (VirtualTryOnWidget.activeWidgetId !== this.instanceId) {
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
599
621
|
if (event.origin !== new URL(this.config.baseUrl).origin) {
|
|
600
622
|
return;
|
|
601
623
|
}
|
|
@@ -607,7 +629,7 @@
|
|
|
607
629
|
}
|
|
608
630
|
break;
|
|
609
631
|
case "CLOSE_MODAL":
|
|
610
|
-
|
|
632
|
+
this.closeModal();
|
|
611
633
|
break;
|
|
612
634
|
}
|
|
613
635
|
};
|
|
@@ -632,58 +654,18 @@
|
|
|
632
654
|
if (modal && modal instanceof HTMLElement) {
|
|
633
655
|
modal.style.display = "none";
|
|
634
656
|
}
|
|
635
|
-
const container =
|
|
636
|
-
if (container
|
|
657
|
+
const container = this.getContainer();
|
|
658
|
+
if (container) {
|
|
637
659
|
showProductLoading(container, "Preparing your personalized look");
|
|
638
660
|
}
|
|
639
|
-
let hasPreview = false;
|
|
640
661
|
try {
|
|
641
662
|
const submitResponse = await this.callVtoApi(this.lastModelImage, this.originalProductImages);
|
|
642
663
|
let status = await this.fetchJobStatus(submitResponse.job_id);
|
|
643
|
-
let lastPreviewCount = 0;
|
|
644
664
|
while (status.status !== "COMPLETED" && status.status !== "FAILED") {
|
|
645
|
-
if (
|
|
646
|
-
|
|
647
|
-
if (status.current_iteration === 1) {
|
|
648
|
-
statusMessage = "Refining your look";
|
|
649
|
-
}
|
|
650
|
-
else if (status.current_iteration && status.current_iteration > 1) {
|
|
651
|
-
statusMessage = "Finalizing your look";
|
|
652
|
-
}
|
|
665
|
+
if (container instanceof HTMLElement) {
|
|
666
|
+
const statusMessage = "Preparing your personalized look";
|
|
653
667
|
showProductLoading(container, statusMessage);
|
|
654
668
|
}
|
|
655
|
-
else if (hasPreview && container instanceof HTMLElement) {
|
|
656
|
-
let statusMessage = "Refining your look";
|
|
657
|
-
if (status.current_iteration && status.current_iteration > 1) {
|
|
658
|
-
statusMessage = "Finalizing your look";
|
|
659
|
-
}
|
|
660
|
-
showStatusBadge(container, statusMessage);
|
|
661
|
-
this.hideButtonContainer(container);
|
|
662
|
-
}
|
|
663
|
-
if (status.preview_count > lastPreviewCount) {
|
|
664
|
-
try {
|
|
665
|
-
const previewUrl = await this.fetchJobImage(submitResponse.job_id);
|
|
666
|
-
if (!hasPreview && container instanceof HTMLElement) {
|
|
667
|
-
this.replaceProductImage(previewUrl);
|
|
668
|
-
let statusMessage = "Refining your look";
|
|
669
|
-
if (status.current_iteration && status.current_iteration > 1) {
|
|
670
|
-
statusMessage = "Finalizing your look";
|
|
671
|
-
}
|
|
672
|
-
showStatusBadge(container, statusMessage);
|
|
673
|
-
this.hideButtonContainer(container);
|
|
674
|
-
removeProductLoading(container);
|
|
675
|
-
hasPreview = true;
|
|
676
|
-
}
|
|
677
|
-
else if (hasPreview) {
|
|
678
|
-
this.replaceProductImage(previewUrl);
|
|
679
|
-
}
|
|
680
|
-
lastPreviewCount = status.preview_count;
|
|
681
|
-
}
|
|
682
|
-
catch (e) {
|
|
683
|
-
if (!(e instanceof Error && e.message === "202_PROCESSING"))
|
|
684
|
-
throw e;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
669
|
await new Promise((r) => setTimeout(r, 3000));
|
|
688
670
|
status = await this.fetchJobStatus(submitResponse.job_id);
|
|
689
671
|
}
|
|
@@ -700,12 +682,7 @@
|
|
|
700
682
|
if (status.status === "FAILED") {
|
|
701
683
|
console.error("[WeWear VTO] VTO process failed:", status.message);
|
|
702
684
|
if (container instanceof HTMLElement) {
|
|
703
|
-
|
|
704
|
-
showProductLoading(container, "We are experiencing some technical issues and apologise for any inconvenience caused. Please come back later again");
|
|
705
|
-
}
|
|
706
|
-
else {
|
|
707
|
-
showStatusBadge(container, "We are experiencing some technical issues and apologise for any inconvenience caused. Please come back later again");
|
|
708
|
-
}
|
|
685
|
+
showStatusBadge(container, "We are experiencing some technical issues and apologise for any inconvenience caused. Please come back later again");
|
|
709
686
|
}
|
|
710
687
|
await new Promise((r) => setTimeout(r, 5000));
|
|
711
688
|
}
|
|
@@ -713,12 +690,7 @@
|
|
|
713
690
|
catch (error) {
|
|
714
691
|
console.error("[WeWear VTO] Error during virtual try-on process:", error);
|
|
715
692
|
if (container instanceof HTMLElement) {
|
|
716
|
-
|
|
717
|
-
showProductLoading(container, "We are experiencing technical issues and apologise for any inconvenience caused. Please come back later again");
|
|
718
|
-
}
|
|
719
|
-
else {
|
|
720
|
-
showStatusBadge(container, "We are experiencing technical issues. Please try again later.");
|
|
721
|
-
}
|
|
693
|
+
showProductLoading(container, "We are experiencing technical issues and apologise for any inconvenience caused. Please come back later again");
|
|
722
694
|
}
|
|
723
695
|
await new Promise((r) => setTimeout(r, 5000));
|
|
724
696
|
}
|
|
@@ -728,7 +700,7 @@
|
|
|
728
700
|
removeStatusBadge(container);
|
|
729
701
|
this.showButtonContainer(container);
|
|
730
702
|
}
|
|
731
|
-
|
|
703
|
+
this.closeModal();
|
|
732
704
|
}
|
|
733
705
|
}
|
|
734
706
|
async callVtoApi(modelImage, productImages) {
|
|
@@ -738,7 +710,6 @@
|
|
|
738
710
|
formData.append("product_image_urls", JSON.stringify(productImages));
|
|
739
711
|
formData.append("page_url", window.location.href);
|
|
740
712
|
formData.append("model_tier", this.config.modelTier);
|
|
741
|
-
formData.append("green_suit", this.config.greenSuit);
|
|
742
713
|
const outfitID = (_a = this.config.outfitID) === null || _a === void 0 ? void 0 : _a.trim();
|
|
743
714
|
if (outfitID)
|
|
744
715
|
formData.append("outfit_id", outfitID);
|
|
@@ -775,8 +746,8 @@
|
|
|
775
746
|
replaceProductImage(imageUrl) {
|
|
776
747
|
try {
|
|
777
748
|
this.virtualTryOnImageUrl = imageUrl;
|
|
778
|
-
const container =
|
|
779
|
-
if (!container
|
|
749
|
+
const container = this.getContainer();
|
|
750
|
+
if (!container) {
|
|
780
751
|
console.warn("[WeWear VTO] Gallery container not found for image replacement:", this.config.gallerySelector);
|
|
781
752
|
return;
|
|
782
753
|
}
|
|
@@ -813,12 +784,6 @@
|
|
|
813
784
|
console.error("[WeWear VTO] Error replacing product image:", error);
|
|
814
785
|
}
|
|
815
786
|
}
|
|
816
|
-
hideButtonContainer(container) {
|
|
817
|
-
const buttonContainer = container.querySelector(`.${CSS_CLASSES.BUTTON_CONTAINER}`);
|
|
818
|
-
if (buttonContainer) {
|
|
819
|
-
buttonContainer.style.display = "none";
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
787
|
showButtonContainer(container) {
|
|
823
788
|
const buttonContainer = container.querySelector(`.${CSS_CLASSES.BUTTON_CONTAINER}`);
|
|
824
789
|
if (buttonContainer) {
|
|
@@ -907,8 +872,12 @@
|
|
|
907
872
|
}
|
|
908
873
|
destroy() {
|
|
909
874
|
try {
|
|
910
|
-
|
|
911
|
-
|
|
875
|
+
const container = this.getContainer();
|
|
876
|
+
if (container) {
|
|
877
|
+
const existingButtons = container.querySelectorAll(`.${CSS_CLASSES.BUTTON_CONTAINER}`);
|
|
878
|
+
existingButtons.forEach((btn) => btn.remove());
|
|
879
|
+
}
|
|
880
|
+
this.closeModal();
|
|
912
881
|
this.cameraButton = null;
|
|
913
882
|
if (this.iframeMessageListener) {
|
|
914
883
|
window.removeEventListener("message", this.iframeMessageListener);
|
|
@@ -926,30 +895,45 @@
|
|
|
926
895
|
}
|
|
927
896
|
}
|
|
928
897
|
}
|
|
898
|
+
VirtualTryOnWidget.instanceCounter = 0;
|
|
899
|
+
VirtualTryOnWidget.activeWidgetId = null;
|
|
929
900
|
|
|
930
|
-
let
|
|
901
|
+
let widgetInstances = [];
|
|
931
902
|
function initVirtualTryOn(config) {
|
|
932
903
|
try {
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
widgetInstance = null;
|
|
936
|
-
}
|
|
904
|
+
widgetInstances.forEach((instance) => instance.destroy());
|
|
905
|
+
widgetInstances = [];
|
|
937
906
|
if (!config) {
|
|
938
907
|
console.log("[WeWear VTO] Missing configuration. Widget not initialized.");
|
|
939
908
|
return;
|
|
940
909
|
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
});
|
|
910
|
+
const allContainers = Array.from(document.querySelectorAll(config.gallerySelector)).filter((container) => container instanceof HTMLElement);
|
|
911
|
+
const shouldUseSingleton = config.singleton !== false;
|
|
912
|
+
if (allContainers.length > 1 && !shouldUseSingleton) {
|
|
913
|
+
widgetInstances = allContainers.map((galleryElement) => {
|
|
914
|
+
return new VirtualTryOnWidget(Object.assign(Object.assign({}, config), { galleryElement }));
|
|
947
915
|
});
|
|
948
916
|
}
|
|
949
917
|
else {
|
|
950
|
-
|
|
951
|
-
|
|
918
|
+
const firstContainer = allContainers[0];
|
|
919
|
+
widgetInstances = [
|
|
920
|
+
new VirtualTryOnWidget(Object.assign(Object.assign({}, config), { galleryElement: firstContainer })),
|
|
921
|
+
];
|
|
922
|
+
}
|
|
923
|
+
const initializeWidgets = () => {
|
|
924
|
+
widgetInstances.forEach((widget) => {
|
|
925
|
+
widget.init().catch((error) => {
|
|
926
|
+
console.error("[WeWear VTO] Failed to initialize:", error);
|
|
927
|
+
});
|
|
952
928
|
});
|
|
929
|
+
};
|
|
930
|
+
if (document.readyState === "loading") {
|
|
931
|
+
document.addEventListener("DOMContentLoaded", initializeWidgets, {
|
|
932
|
+
once: true,
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
else {
|
|
936
|
+
initializeWidgets();
|
|
953
937
|
}
|
|
954
938
|
}
|
|
955
939
|
catch (error) {
|
|
@@ -957,7 +941,11 @@
|
|
|
957
941
|
}
|
|
958
942
|
}
|
|
959
943
|
function getWidgetInstance() {
|
|
960
|
-
|
|
944
|
+
var _a;
|
|
945
|
+
return (_a = widgetInstances[0]) !== null && _a !== void 0 ? _a : null;
|
|
946
|
+
}
|
|
947
|
+
function getWidgetInstances() {
|
|
948
|
+
return [...widgetInstances];
|
|
961
949
|
}
|
|
962
950
|
if (typeof window !== "undefined") {
|
|
963
951
|
initVirtualTryOn();
|
|
@@ -965,6 +953,7 @@
|
|
|
965
953
|
|
|
966
954
|
exports.VirtualTryOnWidget = VirtualTryOnWidget;
|
|
967
955
|
exports.getWidgetInstance = getWidgetInstance;
|
|
956
|
+
exports.getWidgetInstances = getWidgetInstances;
|
|
968
957
|
exports.initVirtualTryOn = initVirtualTryOn;
|
|
969
958
|
|
|
970
959
|
}));
|