@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.
@@ -0,0 +1,2 @@
1
+ export declare function showAlert(container: HTMLElement, message: string, type: 'error' | 'warning'): void;
2
+ export declare function removeAlert(container: HTMLElement): void;
@@ -0,0 +1,2 @@
1
+ export declare function showAlert(container: HTMLElement, message: string, type?: 'error' | 'success' | 'info' | 'warning'): void;
2
+ export declare function removeAlert(container: HTMLElement): void;
@@ -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(text?: string): void;
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, gallerySelector: string): void;
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
- try {
3
- const formData = new FormData();
4
- formData.append("ww_user_id", ww_user_id);
5
- formData.append("ww_product_image", ww_product_image);
6
- formData.append("ww_image", ww_image, "captured-image.jpg");
7
- formData.append("ww_access_token", ww_access_token);
8
- const response = await fetch(`${baseUrl}/api/virtual-try-on`, {
9
- method: "POST",
10
- body: formData,
11
- });
12
- if (!response.ok) {
13
- console.error("[WeWear VTO] API request failed:", response.status, response.statusText);
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
- const result = await response.json();
17
- console.log("[WeWear VTO] API response:", result);
18
- return result;
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(text = "Processing...") {
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
- const loadingOverlay = createLoadingOverlay(text);
440
- modal.appendChild(loadingOverlay);
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 modal = document.querySelector(`.${CSS_CLASSES.MODAL}`);
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
- var loadingOverlay = /*#__PURE__*/Object.freeze({
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
+ &times;
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, this.config.gallerySelector);
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("Processing image...");
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
- console.error("[WeWear VTO] Invalid API response:", result);
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