@primestyleai/tryon 3.9.1 → 3.10.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.
@@ -15,6 +15,8 @@ export type TranslateFn = (key: string) => string;
15
15
  export declare const SUPPORTED_LOCALES: string[];
16
16
  /** Master list of translatable keys (= the English dictionary). */
17
17
  export declare const TRANSLATION_KEYS: string[];
18
+ /** Human-readable labels for each bundled locale (in the locale's own language). */
19
+ export declare const LOCALE_LABELS: Record<string, string>;
18
20
  /**
19
21
  * Register an external dictionary at runtime.
20
22
  * Useful for custom / community translations not bundled in the SDK.
@@ -2917,6 +2917,28 @@ const DICTIONARIES = {
2917
2917
  };
2918
2918
  const SUPPORTED_LOCALES = Object.keys(DICTIONARIES);
2919
2919
  const TRANSLATION_KEYS = Object.keys(en);
2920
+ const LOCALE_LABELS = {
2921
+ en: "English",
2922
+ es: "Español",
2923
+ fr: "Français",
2924
+ de: "Deutsch",
2925
+ it: "Italiano",
2926
+ sv: "Svenska",
2927
+ ja: "日本語",
2928
+ cs: "Čeština",
2929
+ da: "Dansk",
2930
+ nl: "Nederlands",
2931
+ nb: "Norsk",
2932
+ pl: "Polski",
2933
+ "pt-br": "Português (BR)",
2934
+ "pt-pt": "Português (PT)",
2935
+ fi: "Suomi",
2936
+ tr: "Türkçe",
2937
+ th: "ไทย",
2938
+ "zh-cn": "中文 (简体)",
2939
+ "zh-tw": "中文 (繁體)",
2940
+ ko: "한국어"
2941
+ };
2920
2942
  function registerLocale(locale, dict) {
2921
2943
  DICTIONARIES[locale.toLowerCase()] = dict;
2922
2944
  }
@@ -2939,6 +2961,7 @@ function createT(locale) {
2939
2961
  }
2940
2962
  export {
2941
2963
  ApiClient as A,
2964
+ LOCALE_LABELS as L,
2942
2965
  PrimeStyleError as P,
2943
2966
  SseClient as S,
2944
2967
  TRANSLATION_KEYS as T,
@@ -1,5 +1,5 @@
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";
1
+ import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage } from "./index-71-uiSXC.js";
2
+ import { P, b, T, d, r } from "./index-71-uiSXC.js";
3
3
  function detectProductImage() {
4
4
  const ogImage = document.querySelector(
5
5
  'meta[property="og:image"]'
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
3
3
  import { useState, useEffect, useMemo, useRef, useCallback } from "react";
4
- import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage, P as PrimeStyleError } from "../index-B0KE3c8S.js";
4
+ import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage, P as PrimeStyleError, b as SUPPORTED_LOCALES, L as LOCALE_LABELS } from "../index-71-uiSXC.js";
5
5
  const HEADER_ALIASES = {
6
6
  // ── Size label columns (skipped during field derivation) ──
7
7
  size: "__size__",
@@ -515,6 +515,13 @@ function ChevronRightIcon() {
515
515
  function CheckIcon({ size = 14 }) {
516
516
  return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 3, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" }) });
517
517
  }
518
+ function GlobeIcon({ size = 16 }) {
519
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
520
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
521
+ /* @__PURE__ */ jsx("path", { d: "M2 12h20" }),
522
+ /* @__PURE__ */ jsx("path", { d: "M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" })
523
+ ] });
524
+ }
518
525
  function getApiKey() {
519
526
  const key = process.env.NEXT_PUBLIC_PRIMESTYLE_API_KEY ?? "";
520
527
  if (!key) throw new PrimeStyleError("Missing NEXT_PUBLIC_PRIMESTYLE_API_KEY", "MISSING_API_KEY");
@@ -553,7 +560,11 @@ function PrimeStyleTryonInner({
553
560
  onError,
554
561
  sizeGuideData
555
562
  }) {
556
- const t = useMemo(() => createT(locale), [locale]);
563
+ const [activeLocale, setActiveLocale] = useState(() => locale || "");
564
+ useEffect(() => {
565
+ if (locale !== void 0) setActiveLocale(locale);
566
+ }, [locale]);
567
+ const t = useMemo(() => createT(activeLocale || void 0), [activeLocale]);
557
568
  const resolvedButtonText = buttonText ?? t("Virtual Try-On");
558
569
  const [view, setView] = useState("idle");
559
570
  const [selectedFile, setSelectedFile] = useState(null);
@@ -1729,6 +1740,18 @@ function PrimeStyleTryonInner({
1729
1740
  /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-header", cn.header), children: [
1730
1741
  /* @__PURE__ */ jsx("span", { className: cx("ps-tryon-title", cn.title), children: t("Virtual Try-On") }),
1731
1742
  /* @__PURE__ */ jsxs("div", { className: "ps-tryon-header-actions", children: [
1743
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-lang-switcher", children: [
1744
+ /* @__PURE__ */ jsx(GlobeIcon, {}),
1745
+ /* @__PURE__ */ jsx(
1746
+ "select",
1747
+ {
1748
+ value: activeLocale,
1749
+ onChange: (e) => setActiveLocale(e.target.value),
1750
+ className: "ps-tryon-lang-select",
1751
+ children: SUPPORTED_LOCALES.map((code) => /* @__PURE__ */ jsx("option", { value: code, children: LOCALE_LABELS[code] || code }, code))
1752
+ }
1753
+ )
1754
+ ] }),
1732
1755
  profiles.length > 0 && /* @__PURE__ */ jsx("button", { className: "ps-tryon-header-icon", title: t("Profiles"), onClick: () => setDrawer(drawer === "profiles" ? null : "profiles"), children: /* @__PURE__ */ jsx(UserIcon, {}) }),
1733
1756
  history.length > 0 && /* @__PURE__ */ jsx("button", { className: "ps-tryon-header-icon", title: t("History"), onClick: () => setDrawer(drawer === "history" ? null : "history"), children: /* @__PURE__ */ jsx(ClockIcon, {}) }),
1734
1757
  /* @__PURE__ */ jsx("button", { onClick: handleClose, className: cx("ps-tryon-close", cn.closeButton), children: /* @__PURE__ */ jsx(XIcon, {}) })
@@ -1813,6 +1836,23 @@ const STYLES = `
1813
1836
  }
1814
1837
  .ps-tryon-close:hover { background: rgba(255,255,255,0.1); }
1815
1838
 
1839
+ /* Language switcher */
1840
+ .ps-tryon-lang-switcher {
1841
+ position: relative; display: flex; align-items: center; gap: clamp(3px, 0.21vw, 4px);
1842
+ padding: clamp(3px, 0.26vw, 5px) clamp(6px, 0.52vw, 10px);
1843
+ border: 1.5px solid #333; border-radius: clamp(6px, 0.52vw, 10px);
1844
+ background: transparent; cursor: pointer; color: #999; transition: all 0.2s;
1845
+ }
1846
+ .ps-tryon-lang-switcher:hover { border-color: #bb945c; color: #bb945c; }
1847
+ .ps-tryon-lang-switcher svg { stroke: currentColor; fill: none; flex-shrink: 0; }
1848
+ .ps-tryon-lang-select {
1849
+ appearance: none; -webkit-appearance: none; background: transparent; border: none;
1850
+ color: inherit; font-size: clamp(9px, 0.57vw, 11px); font-family: inherit;
1851
+ cursor: pointer; outline: none; padding-right: clamp(8px, 0.52vw, 10px);
1852
+ max-width: clamp(70px, 5.2vw, 100px);
1853
+ }
1854
+ .ps-tryon-lang-select option { background: #1a1b1a; color: #fff; }
1855
+
1816
1856
  /* Stepper */
1817
1857
  .ps-tryon-stepper { padding: clamp(12px, 1.04vw, 20px) clamp(14px, 1.25vw, 24px) clamp(7px, 0.63vw, 12px); }
1818
1858
  .ps-tryon-stepper-track { display: flex; align-items: flex-start; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primestyleai/tryon",
3
- "version": "3.9.1",
3
+ "version": "3.10.0",
4
4
  "description": "PrimeStyle Virtual Try-On SDK — React component & Web Component",
5
5
  "type": "module",
6
6
  "main": "dist/primestyle-tryon.js",