@primestyleai/tryon 3.8.0 → 3.9.0

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 CHANGED
@@ -4,3 +4,5 @@ export { SseClient } from "./sse-client";
4
4
  export { detectProductImage } from "./product-detector";
5
5
  export { compressImage, isValidImageFile } from "./image-utils";
6
6
  export type { PrimeStyleConfig, ButtonStyles, ModalStyles, TryOnResponse, TryOnStatus, VtoUpdate, PrimeStyleEvents, } from "./types";
7
+ export { registerLocale, createT, SUPPORTED_LOCALES, TRANSLATION_KEYS, detectLanguage } from "./i18n";
8
+ export type { TranslateFn } from "./i18n";
@@ -1,5 +1,5 @@
1
- import { A as ApiClient, S as SseClient, i as isValidImageFile, c as compressImage } from "./image-utils-C9bJ1zKO.js";
2
- import { P } from "./image-utils-C9bJ1zKO.js";
1
+ import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage } from "./index-B0KE3c8S.js";
2
+ import { P, b, T, d, r } from "./index-B0KE3c8S.js";
3
3
  function detectProductImage() {
4
4
  const ogImage = document.querySelector(
5
5
  'meta[property="og:image"]'
@@ -457,6 +457,7 @@ class PrimeStyleTryon extends HTMLElement {
457
457
  this.errorMessage = null;
458
458
  this.currentJobId = null;
459
459
  this.productImageUrl = null;
460
+ this.t = createT();
460
461
  this.buttonStyles = {};
461
462
  this.modalStyles = {};
462
463
  this.savedScrollY = 0;
@@ -485,6 +486,9 @@ class PrimeStyleTryon extends HTMLElement {
485
486
  if (name === "api-key" || name === "api-url") {
486
487
  this.initApi();
487
488
  }
489
+ if (name === "locale") {
490
+ this.t = createT(val || void 0);
491
+ }
488
492
  if (name === "product-image") {
489
493
  this.productImageUrl = val;
490
494
  }
@@ -569,6 +573,8 @@ class PrimeStyleTryon extends HTMLElement {
569
573
  } catch {
570
574
  }
571
575
  }
576
+ const localeAttr = this.getAttribute("locale");
577
+ if (localeAttr) this.t = createT(localeAttr);
572
578
  this.productImageUrl = this.getAttribute("product-image") || null;
573
579
  if (!this.productImageUrl) {
574
580
  this.productImageUrl = detectProductImage();
@@ -607,7 +613,7 @@ class PrimeStyleTryon extends HTMLElement {
607
613
  );
608
614
  }
609
615
  get buttonText() {
610
- return this.getAttribute("button-text") || "Virtual Try-On";
616
+ return this.getAttribute("button-text") || this.t("Virtual Try-On");
611
617
  }
612
618
  get showPoweredBy() {
613
619
  const attr = this.getAttribute("show-powered-by");
@@ -647,7 +653,7 @@ class PrimeStyleTryon extends HTMLElement {
647
653
  const header = document.createElement("div");
648
654
  header.className = "ps-header";
649
655
  header.innerHTML = `
650
- <span class="ps-header-title">Virtual Try-On</span>
656
+ <span class="ps-header-title">${this.t("Virtual Try-On")}</span>
651
657
  `;
652
658
  const closeBtn = document.createElement("button");
653
659
  closeBtn.className = "ps-close";
@@ -675,7 +681,7 @@ class PrimeStyleTryon extends HTMLElement {
675
681
  if (this.showPoweredBy) {
676
682
  const powered = document.createElement("div");
677
683
  powered.className = "ps-powered";
678
- powered.innerHTML = `Powered by <a href="https://myaifitting.com" target="_blank" rel="noopener">PrimeStyle AI</a>`;
684
+ powered.innerHTML = `${this.t("Powered by")} <a href="https://myaifitting.com" target="_blank" rel="noopener">PrimeStyle AI</a>`;
679
685
  modal.appendChild(powered);
680
686
  }
681
687
  overlay.appendChild(modal);
@@ -688,7 +694,7 @@ class PrimeStyleTryon extends HTMLElement {
688
694
  preview.className = "ps-preview";
689
695
  const img = document.createElement("img");
690
696
  img.src = this.previewUrl;
691
- img.alt = "Your photo";
697
+ img.alt = this.t("Your photo");
692
698
  preview.appendChild(img);
693
699
  const removeBtn = document.createElement("button");
694
700
  removeBtn.className = "ps-preview-remove";
@@ -701,7 +707,7 @@ class PrimeStyleTryon extends HTMLElement {
701
707
  frag.appendChild(preview);
702
708
  const submit = document.createElement("button");
703
709
  submit.className = "ps-submit";
704
- submit.textContent = "Try It On";
710
+ submit.textContent = this.t("Try It On");
705
711
  submit.addEventListener("click", () => this.handleSubmit());
706
712
  frag.appendChild(submit);
707
713
  } else {
@@ -716,8 +722,8 @@ class PrimeStyleTryon extends HTMLElement {
716
722
  });
717
723
  zone.innerHTML = `
718
724
  <svg class="ps-upload-icon" viewBox="0 0 24 24">${ICONS.upload.replace(/<\/?svg[^>]*>/g, "")}</svg>
719
- <p class="ps-upload-text">Drop your photo here or click to upload</p>
720
- <p class="ps-upload-hint">JPEG, PNG or WebP (max 10MB)</p>
725
+ <p class="ps-upload-text">${this.t("Drop your photo here or click to upload")}</p>
726
+ <p class="ps-upload-hint">${this.t("JPEG, PNG or WebP (max 10MB)")}</p>
721
727
  `;
722
728
  zone.appendChild(input);
723
729
  zone.addEventListener("click", () => input.click());
@@ -743,8 +749,8 @@ class PrimeStyleTryon extends HTMLElement {
743
749
  div.className = "ps-processing";
744
750
  div.innerHTML = `
745
751
  <div class="ps-spinner"></div>
746
- <p class="ps-processing-text">Generating your try-on...</p>
747
- <p class="ps-processing-sub">This usually takes 15-20 seconds</p>
752
+ <p class="ps-processing-text">${this.t("Generating virtual try-on...")}</p>
753
+ <p class="ps-processing-sub">${this.t("This usually takes 15-20 seconds")}</p>
748
754
  `;
749
755
  return div;
750
756
  }
@@ -754,19 +760,19 @@ class PrimeStyleTryon extends HTMLElement {
754
760
  if (this.resultImageUrl) {
755
761
  const img = document.createElement("img");
756
762
  img.src = this.resultImageUrl;
757
- img.alt = "Try-on result";
763
+ img.alt = this.t("Try-on result");
758
764
  div.appendChild(img);
759
765
  }
760
766
  const actions = document.createElement("div");
761
767
  actions.className = "ps-result-actions";
762
768
  const downloadBtn = document.createElement("button");
763
769
  downloadBtn.className = "ps-btn-download";
764
- downloadBtn.textContent = "Download";
770
+ downloadBtn.textContent = this.t("Download");
765
771
  downloadBtn.addEventListener("click", () => this.handleDownload());
766
772
  actions.appendChild(downloadBtn);
767
773
  const retryBtn = document.createElement("button");
768
774
  retryBtn.className = "ps-btn-retry";
769
- retryBtn.textContent = "Try Another";
775
+ retryBtn.textContent = this.t("Try Another");
770
776
  retryBtn.addEventListener("click", () => {
771
777
  this.resetUpload();
772
778
  this.state = "upload";
@@ -781,11 +787,11 @@ class PrimeStyleTryon extends HTMLElement {
781
787
  div.className = "ps-error";
782
788
  div.innerHTML = `
783
789
  <svg class="ps-error-icon" viewBox="0 0 24 24">${ICONS.alert.replace(/<\/?svg[^>]*>/g, "")}</svg>
784
- <p class="ps-error-text">${this.errorMessage || "Something went wrong"}</p>
790
+ <p class="ps-error-text">${this.errorMessage || this.t("Something went wrong")}</p>
785
791
  `;
786
792
  const retryBtn = document.createElement("button");
787
793
  retryBtn.className = "ps-submit";
788
- retryBtn.textContent = "Try Again";
794
+ retryBtn.textContent = this.t("Try Again");
789
795
  retryBtn.addEventListener("click", () => {
790
796
  this.state = "upload";
791
797
  this.errorMessage = null;
@@ -797,13 +803,13 @@ class PrimeStyleTryon extends HTMLElement {
797
803
  // ── Handlers ────────────────────────────────
798
804
  handleFileSelect(file) {
799
805
  if (!isValidImageFile(file)) {
800
- this.errorMessage = "Please upload a JPEG, PNG, or WebP image.";
806
+ this.errorMessage = this.t("Please upload a JPEG, PNG, or WebP image.");
801
807
  this.state = "error";
802
808
  this.render();
803
809
  return;
804
810
  }
805
811
  if (file.size > 10 * 1024 * 1024) {
806
- this.errorMessage = "Image must be under 10MB.";
812
+ this.errorMessage = this.t("Image must be under 10MB.");
807
813
  this.state = "error";
808
814
  this.render();
809
815
  return;
@@ -815,13 +821,13 @@ class PrimeStyleTryon extends HTMLElement {
815
821
  }
816
822
  async handleSubmit() {
817
823
  if (!this.selectedFile || !this.apiClient || !this.sseClient) {
818
- this.errorMessage = "SDK not configured. Please provide an API key.";
824
+ this.errorMessage = this.t("SDK not configured. Please provide an API key.");
819
825
  this.state = "error";
820
826
  this.render();
821
827
  return;
822
828
  }
823
829
  if (!this.productImageUrl) {
824
- this.errorMessage = "No product image found. Please set the product-image attribute.";
830
+ this.errorMessage = this.t("No product image found. Please set the product-image attribute.");
825
831
  this.state = "error";
826
832
  this.render();
827
833
  return;
@@ -842,7 +848,7 @@ class PrimeStyleTryon extends HTMLElement {
842
848
  );
843
849
  this.startPolling(response.jobId);
844
850
  } catch (err) {
845
- const message = err instanceof Error ? err.message : "Failed to start try-on";
851
+ const message = err instanceof Error ? err.message : this.t("Failed to start try-on");
846
852
  this.errorMessage = message;
847
853
  this.state = "error";
848
854
  this.emit("ps:error", { message, code: err?.code });
@@ -861,7 +867,7 @@ class PrimeStyleTryon extends HTMLElement {
861
867
  this.render();
862
868
  }
863
869
  } else if (update.status === "failed") {
864
- this.errorMessage = update.error || "Try-on generation failed";
870
+ this.errorMessage = update.error || this.t("Try-on generation failed");
865
871
  this.state = "error";
866
872
  this.emit("ps:error", { message: this.errorMessage });
867
873
  this.render();
@@ -918,7 +924,7 @@ class PrimeStyleTryon extends HTMLElement {
918
924
  if (this.resultImageUrl.startsWith("data:")) {
919
925
  link.click();
920
926
  } else {
921
- fetch(this.resultImageUrl).then((r) => r.blob()).then((blob) => {
927
+ fetch(this.resultImageUrl).then((r2) => r2.blob()).then((blob) => {
922
928
  const url = URL.createObjectURL(blob);
923
929
  link.href = url;
924
930
  link.click();
@@ -1007,8 +1013,13 @@ export {
1007
1013
  ApiClient,
1008
1014
  P as PrimeStyleError,
1009
1015
  PrimeStyleTryon,
1016
+ b as SUPPORTED_LOCALES,
1010
1017
  SseClient,
1018
+ T as TRANSLATION_KEYS,
1011
1019
  compressImage,
1020
+ createT,
1021
+ d as detectLanguage,
1012
1022
  detectProductImage,
1013
- isValidImageFile
1023
+ isValidImageFile,
1024
+ r as registerLocale
1014
1025
  };
@@ -10,6 +10,8 @@ export interface PrimeStyleTryonProps {
10
10
  showIcon?: boolean;
11
11
  /** Custom icon element to replace the default camera icon. Pass any React node (e.g. an <svg> or <img>). */
12
12
  buttonIcon?: React.ReactNode;
13
+ /** BCP-47 locale tag for UI translations (e.g. "en", "ja", "pt-BR"). Auto-detects from browser if omitted. */
14
+ locale?: string;
13
15
  buttonStyles?: ButtonStyles;
14
16
  modalStyles?: ModalStyles;
15
17
  classNames?: PrimeStyleClassNames;