@primestyleai/tryon 5.10.195 → 5.10.196
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/PrimeStyleTryon.d.ts +1 -0
- package/dist/api-client.d.ts +12 -0
- package/dist/clarity.d.ts +13 -0
- package/dist/{index-D_9-KLXy.js → index-8lZs7T93.js} +252 -164
- package/dist/index-8lZs7T93.js.map +1 -0
- package/dist/primestyle-tryon.js +162 -151
- package/dist/primestyle-tryon.js.map +1 -1
- package/dist/react/PrimeStyleTryonInner.d.ts +1 -1
- package/dist/react/index.js +4996 -4863
- package/dist/react/index.js.map +1 -1
- package/dist/react/styles.d.ts +1 -1
- package/dist/react/types.d.ts +2 -0
- package/dist/replay.d.ts +9 -0
- package/dist/storefront/primestyle-tryon.js +309 -19
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
- package/dist/index-D_9-KLXy.js.map +0 -1
package/dist/primestyle-tryon.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { c as l, A as c,
|
|
3
|
-
import { P as
|
|
4
|
-
function
|
|
2
|
+
import { c as l, A as c, s as h, t as u, i as m, a as g, S as y } from "./index-8lZs7T93.js";
|
|
3
|
+
import { P as C, b as S, T as k, d as E, e as U, r as I } from "./index-8lZs7T93.js";
|
|
4
|
+
function p() {
|
|
5
5
|
const i = document.querySelector(
|
|
6
6
|
'meta[property="og:image"]'
|
|
7
7
|
);
|
|
8
8
|
if (i?.content) return i.content;
|
|
9
|
-
const
|
|
9
|
+
const t = document.querySelectorAll(
|
|
10
10
|
'script[type="application/ld+json"]'
|
|
11
11
|
);
|
|
12
|
-
for (const r of
|
|
12
|
+
for (const r of t)
|
|
13
13
|
try {
|
|
14
|
-
const s = JSON.parse(r.textContent || ""), o =
|
|
14
|
+
const s = JSON.parse(r.textContent || ""), o = d(s);
|
|
15
15
|
if (o) return o;
|
|
16
16
|
} catch {
|
|
17
17
|
}
|
|
18
|
-
const
|
|
18
|
+
const e = [
|
|
19
19
|
"[data-product-image] img",
|
|
20
20
|
"[data-product-image]",
|
|
21
21
|
".product-image img",
|
|
@@ -26,7 +26,7 @@ function d() {
|
|
|
26
26
|
".woocommerce-product-gallery img",
|
|
27
27
|
".product-media img"
|
|
28
28
|
];
|
|
29
|
-
for (const r of
|
|
29
|
+
for (const r of e) {
|
|
30
30
|
const s = document.querySelector(r);
|
|
31
31
|
if (s) {
|
|
32
32
|
const o = s.src || s.dataset.src || s.dataset.zoom;
|
|
@@ -35,29 +35,29 @@ function d() {
|
|
|
35
35
|
}
|
|
36
36
|
return null;
|
|
37
37
|
}
|
|
38
|
-
function
|
|
38
|
+
function d(i) {
|
|
39
39
|
if (!i || typeof i != "object") return null;
|
|
40
40
|
if (Array.isArray(i)) {
|
|
41
|
-
for (const
|
|
42
|
-
const r =
|
|
41
|
+
for (const e of i) {
|
|
42
|
+
const r = d(e);
|
|
43
43
|
if (r) return r;
|
|
44
44
|
}
|
|
45
45
|
return null;
|
|
46
46
|
}
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
49
|
-
const
|
|
50
|
-
if (typeof
|
|
51
|
-
if (Array.isArray(
|
|
52
|
-
if (
|
|
53
|
-
const r =
|
|
47
|
+
const t = i;
|
|
48
|
+
if (t["@type"] === "Product" || t["@type"] === "IndividualProduct") {
|
|
49
|
+
const e = t.image;
|
|
50
|
+
if (typeof e == "string") return e;
|
|
51
|
+
if (Array.isArray(e) && typeof e[0] == "string") return e[0];
|
|
52
|
+
if (e && typeof e == "object") {
|
|
53
|
+
const r = e;
|
|
54
54
|
if (typeof r.url == "string") return r.url;
|
|
55
55
|
if (typeof r.contentUrl == "string") return r.contentUrl;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
return Array.isArray(
|
|
58
|
+
return Array.isArray(t["@graph"]) ? d(t["@graph"]) : null;
|
|
59
59
|
}
|
|
60
|
-
function
|
|
60
|
+
function b() {
|
|
61
61
|
return `
|
|
62
62
|
:host {
|
|
63
63
|
display: inline-block;
|
|
@@ -440,7 +440,7 @@ const n = {
|
|
|
440
440
|
x: '<svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',
|
|
441
441
|
alert: '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>'
|
|
442
442
|
};
|
|
443
|
-
class
|
|
443
|
+
class v extends HTMLElement {
|
|
444
444
|
constructor() {
|
|
445
445
|
super(), this.apiClient = null, this.sseClient = null, this.sseUnsubscribe = null, this.state = "idle", this.selectedFile = null, this.previewUrl = null, this.resultImageUrl = null, this.errorMessage = null, this.currentJobId = null, this.productImageUrl = null, this.productViewReportedFor = null, this.t = l(), this.buttonStyles = {}, this.modalStyles = {}, this.savedScrollY = 0, this.shadow = this.attachShadow({ mode: "open" });
|
|
446
446
|
}
|
|
@@ -452,6 +452,7 @@ class b extends HTMLElement {
|
|
|
452
452
|
"button-text",
|
|
453
453
|
"locale",
|
|
454
454
|
"show-powered-by",
|
|
455
|
+
"clarity-project-id",
|
|
455
456
|
"button-styles",
|
|
456
457
|
"modal-styles"
|
|
457
458
|
];
|
|
@@ -462,13 +463,13 @@ class b extends HTMLElement {
|
|
|
462
463
|
disconnectedCallback() {
|
|
463
464
|
this.cleanup();
|
|
464
465
|
}
|
|
465
|
-
attributeChangedCallback(
|
|
466
|
-
if ((
|
|
466
|
+
attributeChangedCallback(t, e, r) {
|
|
467
|
+
if ((t === "api-key" || t === "api-url") && this.initApi(), t === "locale" && (this.t = l(r || void 0)), t === "product-image" && (this.productImageUrl = r), t === "button-styles")
|
|
467
468
|
try {
|
|
468
469
|
this.buttonStyles = JSON.parse(r);
|
|
469
470
|
} catch {
|
|
470
471
|
}
|
|
471
|
-
if (
|
|
472
|
+
if (t === "modal-styles")
|
|
472
473
|
try {
|
|
473
474
|
this.modalStyles = JSON.parse(r);
|
|
474
475
|
} catch {
|
|
@@ -477,12 +478,12 @@ class b extends HTMLElement {
|
|
|
477
478
|
}
|
|
478
479
|
// ── Public API ──────────────────────────────
|
|
479
480
|
/** Configure button appearance programmatically */
|
|
480
|
-
setButtonStyles(
|
|
481
|
-
this.buttonStyles = { ...this.buttonStyles, ...
|
|
481
|
+
setButtonStyles(t) {
|
|
482
|
+
this.buttonStyles = { ...this.buttonStyles, ...t }, this.applyButtonStyles();
|
|
482
483
|
}
|
|
483
484
|
/** Configure modal appearance programmatically */
|
|
484
|
-
setModalStyles(
|
|
485
|
-
this.modalStyles = { ...this.modalStyles, ...
|
|
485
|
+
setModalStyles(t) {
|
|
486
|
+
this.modalStyles = { ...this.modalStyles, ...t }, this.applyModalStyles();
|
|
486
487
|
}
|
|
487
488
|
lockBodyScroll() {
|
|
488
489
|
this.savedScrollY = window.scrollY, document.body.style.overflow = "hidden", document.body.style.position = "fixed", document.body.style.top = `-${this.savedScrollY}px`, document.body.style.left = "0", document.body.style.right = "0";
|
|
@@ -492,7 +493,7 @@ class b extends HTMLElement {
|
|
|
492
493
|
}
|
|
493
494
|
/** Open the try-on modal */
|
|
494
495
|
open() {
|
|
495
|
-
this.reportEvent("SDK_OPENED", { metadata: { component: "PrimeStyleTryonElement" } }), this.state = "upload", this.lockBodyScroll(), this.render(), this.emit("ps:open");
|
|
496
|
+
this.reportEvent("SDK_OPENED", { metadata: { component: "PrimeStyleTryonElement" } }), this.state = "upload", this.tagClarity("upload"), this.lockBodyScroll(), this.render(), this.emit("ps:open");
|
|
496
497
|
}
|
|
497
498
|
/** Close the try-on modal */
|
|
498
499
|
close() {
|
|
@@ -500,36 +501,36 @@ class b extends HTMLElement {
|
|
|
500
501
|
}
|
|
501
502
|
/** Detect product image from the current page */
|
|
502
503
|
detectProduct() {
|
|
503
|
-
const
|
|
504
|
-
return
|
|
504
|
+
const t = p();
|
|
505
|
+
return t && (this.productImageUrl = t, this.emit("ps:product-detected", { imageUrl: t })), t;
|
|
505
506
|
}
|
|
506
507
|
// ── Private ─────────────────────────────────
|
|
507
508
|
init() {
|
|
508
|
-
const
|
|
509
|
-
if (
|
|
509
|
+
const t = this.getAttribute("button-styles");
|
|
510
|
+
if (t)
|
|
510
511
|
try {
|
|
511
|
-
this.buttonStyles = JSON.parse(
|
|
512
|
+
this.buttonStyles = JSON.parse(t);
|
|
512
513
|
} catch {
|
|
513
514
|
}
|
|
514
|
-
const
|
|
515
|
-
if (
|
|
515
|
+
const e = this.getAttribute("modal-styles");
|
|
516
|
+
if (e)
|
|
516
517
|
try {
|
|
517
|
-
this.modalStyles = JSON.parse(
|
|
518
|
+
this.modalStyles = JSON.parse(e);
|
|
518
519
|
} catch {
|
|
519
520
|
}
|
|
520
521
|
const r = this.getAttribute("locale");
|
|
521
|
-
r && (this.t = l(r)), this.productImageUrl = this.getAttribute("product-image") || null, this.productImageUrl || (this.productImageUrl =
|
|
522
|
+
r && (this.t = l(r)), this.productImageUrl = this.getAttribute("product-image") || null, this.productImageUrl || (this.productImageUrl = p(), this.productImageUrl && this.emit("ps:product-detected", { imageUrl: this.productImageUrl })), this.initApi(), this.reportProductView();
|
|
522
523
|
}
|
|
523
524
|
initApi() {
|
|
524
|
-
const
|
|
525
|
-
this.apiClient = new c(
|
|
525
|
+
const t = this.getAttribute("api-key") || void 0, e = this.getAttribute("api-url") || void 0;
|
|
526
|
+
this.apiClient = new c(t, e), this.sseClient = null;
|
|
526
527
|
}
|
|
527
528
|
cleanup() {
|
|
528
529
|
this.state !== "idle" && this.unlockBodyScroll(), this.sseUnsubscribe && (this.sseUnsubscribe(), this.sseUnsubscribe = null), this.sseClient && (this.sseClient.disconnect(), this.sseClient = null), this.previewUrl && URL.revokeObjectURL(this.previewUrl);
|
|
529
530
|
}
|
|
530
|
-
emit(
|
|
531
|
+
emit(t, e) {
|
|
531
532
|
this.dispatchEvent(
|
|
532
|
-
new CustomEvent(
|
|
533
|
+
new CustomEvent(t, { bubbles: !0, composed: !0, detail: e })
|
|
533
534
|
);
|
|
534
535
|
}
|
|
535
536
|
get eventProductContext() {
|
|
@@ -540,21 +541,31 @@ class b extends HTMLElement {
|
|
|
540
541
|
};
|
|
541
542
|
}
|
|
542
543
|
reportProductView() {
|
|
543
|
-
const
|
|
544
|
-
!
|
|
544
|
+
const t = `${this.eventProductContext.productId || ""}|${this.eventProductContext.productUrl || ""}`;
|
|
545
|
+
!t.trim() || this.productViewReportedFor === t || (this.productViewReportedFor = t, this.tagClarity("idle"), this.reportEvent("PRODUCT_VIEW", { metadata: { component: "PrimeStyleTryonElement" } }));
|
|
545
546
|
}
|
|
546
|
-
|
|
547
|
+
tagClarity(t, e) {
|
|
548
|
+
const r = {
|
|
549
|
+
projectId: this.getAttribute("clarity-project-id"),
|
|
550
|
+
...this.eventProductContext,
|
|
551
|
+
view: t,
|
|
552
|
+
jobId: e,
|
|
553
|
+
source: "custom-element-sdk"
|
|
554
|
+
};
|
|
555
|
+
h(r), u(r);
|
|
556
|
+
}
|
|
557
|
+
reportEvent(t, e = {}) {
|
|
547
558
|
this.apiClient?.reportEvent({
|
|
548
|
-
eventType:
|
|
559
|
+
eventType: t,
|
|
549
560
|
...this.eventProductContext,
|
|
550
|
-
...
|
|
561
|
+
...e
|
|
551
562
|
}).catch(() => {
|
|
552
563
|
});
|
|
553
564
|
}
|
|
554
|
-
reportClientError(
|
|
565
|
+
reportClientError(t) {
|
|
555
566
|
this.apiClient?.reportClientError({
|
|
556
567
|
...this.eventProductContext,
|
|
557
|
-
...
|
|
568
|
+
...t
|
|
558
569
|
}).catch(() => {
|
|
559
570
|
});
|
|
560
571
|
}
|
|
@@ -567,34 +578,34 @@ class b extends HTMLElement {
|
|
|
567
578
|
// ── Rendering ───────────────────────────────
|
|
568
579
|
render() {
|
|
569
580
|
this.shadow.innerHTML = "";
|
|
570
|
-
const
|
|
571
|
-
|
|
572
|
-
const
|
|
573
|
-
if (this.shadow.appendChild(
|
|
581
|
+
const t = document.createElement("style");
|
|
582
|
+
t.textContent = b(), this.shadow.appendChild(t);
|
|
583
|
+
const e = this.createButton();
|
|
584
|
+
if (this.shadow.appendChild(e), this.state !== "idle") {
|
|
574
585
|
const r = this.createModal();
|
|
575
586
|
this.shadow.appendChild(r), requestAnimationFrame(() => r.classList.add("ps-open"));
|
|
576
587
|
}
|
|
577
588
|
this.applyButtonStyles(), this.applyModalStyles();
|
|
578
589
|
}
|
|
579
590
|
createButton() {
|
|
580
|
-
const
|
|
581
|
-
return
|
|
591
|
+
const t = document.createElement("button");
|
|
592
|
+
return t.className = "ps-button", t.innerHTML = `${n.camera}<span>${this.buttonText}</span>`, t.addEventListener("click", () => this.open()), t;
|
|
582
593
|
}
|
|
583
594
|
createModal() {
|
|
584
|
-
const e = document.createElement("div");
|
|
585
|
-
e.className = "ps-overlay", e.addEventListener("click", (a) => {
|
|
586
|
-
a.target === e && this.close();
|
|
587
|
-
});
|
|
588
595
|
const t = document.createElement("div");
|
|
589
|
-
t.className = "ps-
|
|
596
|
+
t.className = "ps-overlay", t.setAttribute("data-clarity-unmask", "true"), t.addEventListener("click", (a) => {
|
|
597
|
+
a.target === t && this.close();
|
|
598
|
+
});
|
|
599
|
+
const e = document.createElement("div");
|
|
600
|
+
e.className = "ps-modal", e.setAttribute("data-clarity-unmask", "true");
|
|
590
601
|
const r = document.createElement("div");
|
|
591
602
|
r.className = "ps-header", r.innerHTML = `
|
|
592
603
|
<span class="ps-header-title">${this.t("Virtual Try-On")}</span>
|
|
593
604
|
`;
|
|
594
605
|
const s = document.createElement("button");
|
|
595
|
-
s.className = "ps-close", s.innerHTML = n.x, s.addEventListener("click", () => this.close()), r.appendChild(s),
|
|
606
|
+
s.className = "ps-close", s.innerHTML = n.x, s.addEventListener("click", () => this.close()), r.appendChild(s), e.appendChild(r);
|
|
596
607
|
const o = document.createElement("div");
|
|
597
|
-
switch (o.className = "ps-body", this.state) {
|
|
608
|
+
switch (o.className = "ps-body", o.setAttribute("data-clarity-unmask", "true"), this.state) {
|
|
598
609
|
case "upload":
|
|
599
610
|
o.appendChild(this.createUploadView());
|
|
600
611
|
break;
|
|
@@ -608,109 +619,109 @@ class b extends HTMLElement {
|
|
|
608
619
|
o.appendChild(this.createErrorView());
|
|
609
620
|
break;
|
|
610
621
|
}
|
|
611
|
-
if (
|
|
622
|
+
if (e.appendChild(o), this.showPoweredBy) {
|
|
612
623
|
const a = document.createElement("div");
|
|
613
|
-
a.className = "ps-powered", a.innerHTML = `${this.t("Powered by")} <a href="https://myaifitting.com" target="_blank" rel="noopener">PrimeStyle AI</a>`,
|
|
624
|
+
a.className = "ps-powered", a.innerHTML = `${this.t("Powered by")} <a href="https://myaifitting.com" target="_blank" rel="noopener">PrimeStyle AI</a>`, e.appendChild(a);
|
|
614
625
|
}
|
|
615
|
-
return
|
|
626
|
+
return t.appendChild(e), t;
|
|
616
627
|
}
|
|
617
628
|
createUploadView() {
|
|
618
|
-
const
|
|
629
|
+
const t = document.createDocumentFragment();
|
|
619
630
|
if (this.selectedFile && this.previewUrl) {
|
|
620
|
-
const
|
|
621
|
-
|
|
631
|
+
const e = document.createElement("div");
|
|
632
|
+
e.className = "ps-preview";
|
|
622
633
|
const r = document.createElement("img");
|
|
623
|
-
r.src = this.previewUrl, r.alt = this.t("Your photo"),
|
|
634
|
+
r.src = this.previewUrl, r.alt = this.t("Your photo"), e.appendChild(r);
|
|
624
635
|
const s = document.createElement("button");
|
|
625
636
|
s.className = "ps-preview-remove", s.textContent = "×", s.addEventListener("click", () => {
|
|
626
637
|
this.resetUpload(), this.render();
|
|
627
|
-
}),
|
|
638
|
+
}), e.appendChild(s), t.appendChild(e);
|
|
628
639
|
const o = document.createElement("button");
|
|
629
|
-
o.className = "ps-submit", o.textContent = this.t("Try It On"), o.addEventListener("click", () => this.handleSubmit()),
|
|
640
|
+
o.className = "ps-submit", o.textContent = this.t("Try It On"), o.addEventListener("click", () => this.handleSubmit()), t.appendChild(o);
|
|
630
641
|
} else {
|
|
631
|
-
const
|
|
632
|
-
|
|
642
|
+
const e = document.createElement("div");
|
|
643
|
+
e.className = "ps-upload-zone";
|
|
633
644
|
const r = document.createElement("input");
|
|
634
645
|
r.type = "file", r.accept = "image/jpeg,image/png,image/webp", r.addEventListener("change", (s) => {
|
|
635
646
|
const o = s.target.files?.[0];
|
|
636
647
|
o && this.handleFileSelect(o);
|
|
637
|
-
}),
|
|
648
|
+
}), e.innerHTML = `
|
|
638
649
|
<svg class="ps-upload-icon" viewBox="0 0 24 24">${n.upload.replace(/<\/?svg[^>]*>/g, "")}</svg>
|
|
639
650
|
<p class="ps-upload-text">${this.t("Drop your photo here or click to upload")}</p>
|
|
640
651
|
<p class="ps-upload-hint">${this.t("JPEG, PNG or WebP (max 10MB)")}</p>
|
|
641
|
-
`,
|
|
642
|
-
s.preventDefault(),
|
|
643
|
-
}),
|
|
644
|
-
|
|
645
|
-
}),
|
|
646
|
-
s.preventDefault(),
|
|
652
|
+
`, e.appendChild(r), e.addEventListener("click", () => r.click()), e.addEventListener("dragover", (s) => {
|
|
653
|
+
s.preventDefault(), e.classList.add("ps-drag-over");
|
|
654
|
+
}), e.addEventListener("dragleave", () => {
|
|
655
|
+
e.classList.remove("ps-drag-over");
|
|
656
|
+
}), e.addEventListener("drop", (s) => {
|
|
657
|
+
s.preventDefault(), e.classList.remove("ps-drag-over");
|
|
647
658
|
const o = s.dataTransfer?.files?.[0];
|
|
648
659
|
o && this.handleFileSelect(o);
|
|
649
|
-
}),
|
|
660
|
+
}), t.appendChild(e);
|
|
650
661
|
}
|
|
651
|
-
return
|
|
662
|
+
return t;
|
|
652
663
|
}
|
|
653
664
|
createProcessingView() {
|
|
654
|
-
const
|
|
655
|
-
return
|
|
665
|
+
const t = document.createElement("div");
|
|
666
|
+
return t.className = "ps-processing", t.innerHTML = `
|
|
656
667
|
<div class="ps-spinner"></div>
|
|
657
668
|
<p class="ps-processing-text">${this.t("Generating virtual try-on...")}</p>
|
|
658
669
|
<p class="ps-processing-sub">${this.t("This usually takes 15-20 seconds")}</p>
|
|
659
|
-
`,
|
|
670
|
+
`, t;
|
|
660
671
|
}
|
|
661
672
|
createResultView() {
|
|
662
|
-
const
|
|
663
|
-
if (
|
|
673
|
+
const t = document.createElement("div");
|
|
674
|
+
if (t.className = "ps-result", this.resultImageUrl) {
|
|
664
675
|
const o = document.createElement("img");
|
|
665
|
-
o.src = this.resultImageUrl, o.alt = this.t("Try-on result"),
|
|
676
|
+
o.src = this.resultImageUrl, o.alt = this.t("Try-on result"), t.appendChild(o);
|
|
666
677
|
}
|
|
667
|
-
const
|
|
668
|
-
|
|
678
|
+
const e = document.createElement("div");
|
|
679
|
+
e.className = "ps-result-actions";
|
|
669
680
|
const r = document.createElement("button");
|
|
670
|
-
r.className = "ps-btn-download", r.textContent = this.t("Download"), r.addEventListener("click", () => this.handleDownload()),
|
|
681
|
+
r.className = "ps-btn-download", r.textContent = this.t("Download"), r.addEventListener("click", () => this.handleDownload()), e.appendChild(r);
|
|
671
682
|
const s = document.createElement("button");
|
|
672
683
|
return s.className = "ps-btn-retry", s.textContent = this.t("Try Another"), s.addEventListener("click", () => {
|
|
673
684
|
this.resetUpload(), this.state = "upload", this.render();
|
|
674
|
-
}),
|
|
685
|
+
}), e.appendChild(s), t.appendChild(e), t;
|
|
675
686
|
}
|
|
676
687
|
createErrorView() {
|
|
677
|
-
const
|
|
678
|
-
|
|
688
|
+
const t = document.createElement("div");
|
|
689
|
+
t.className = "ps-error", t.innerHTML = `
|
|
679
690
|
<svg class="ps-error-icon" viewBox="0 0 24 24">${n.alert.replace(/<\/?svg[^>]*>/g, "")}</svg>
|
|
680
691
|
<p class="ps-error-text">${this.errorMessage || this.t("Something went wrong")}</p>
|
|
681
692
|
`;
|
|
682
|
-
const
|
|
683
|
-
return
|
|
693
|
+
const e = document.createElement("button");
|
|
694
|
+
return e.className = "ps-submit", e.textContent = this.t("Try Again"), e.addEventListener("click", () => {
|
|
684
695
|
this.state = "upload", this.errorMessage = null, this.render();
|
|
685
|
-
}),
|
|
696
|
+
}), t.appendChild(e), t;
|
|
686
697
|
}
|
|
687
698
|
// ── Handlers ────────────────────────────────
|
|
688
|
-
handleFileSelect(
|
|
689
|
-
if (!
|
|
699
|
+
handleFileSelect(t) {
|
|
700
|
+
if (!m(t)) {
|
|
690
701
|
this.errorMessage = this.t("Please upload a JPEG, PNG, or WebP image."), this.state = "error", this.reportClientError({
|
|
691
702
|
message: "Invalid image file type",
|
|
692
703
|
code: "INVALID_FILE",
|
|
693
704
|
component: "PrimeStyleTryonElement",
|
|
694
705
|
view: "upload",
|
|
695
706
|
severity: "low",
|
|
696
|
-
metadata: { fileType:
|
|
707
|
+
metadata: { fileType: t.type, fileSize: t.size }
|
|
697
708
|
}), this.render();
|
|
698
709
|
return;
|
|
699
710
|
}
|
|
700
|
-
if (
|
|
711
|
+
if (t.size > 10 * 1024 * 1024) {
|
|
701
712
|
this.errorMessage = this.t("Image must be under 10MB."), this.state = "error", this.reportClientError({
|
|
702
713
|
message: "Image file too large",
|
|
703
714
|
code: "FILE_TOO_LARGE",
|
|
704
715
|
component: "PrimeStyleTryonElement",
|
|
705
716
|
view: "upload",
|
|
706
717
|
severity: "low",
|
|
707
|
-
metadata: { fileType:
|
|
718
|
+
metadata: { fileType: t.type, fileSize: t.size }
|
|
708
719
|
}), this.render();
|
|
709
720
|
return;
|
|
710
721
|
}
|
|
711
|
-
this.selectedFile =
|
|
712
|
-
metadata: { fileType:
|
|
713
|
-
}), this.emit("ps:upload", { file:
|
|
722
|
+
this.selectedFile = t, this.previewUrl = URL.createObjectURL(t), this.reportEvent("PHOTO_UPLOADED", {
|
|
723
|
+
metadata: { fileType: t.type, fileSize: t.size, component: "PrimeStyleTryonElement" }
|
|
724
|
+
}), this.emit("ps:upload", { file: t }), this.render();
|
|
714
725
|
}
|
|
715
726
|
async handleSubmit() {
|
|
716
727
|
if (!this.selectedFile || !this.apiClient) {
|
|
@@ -733,45 +744,45 @@ class b extends HTMLElement {
|
|
|
733
744
|
}), this.render();
|
|
734
745
|
return;
|
|
735
746
|
}
|
|
736
|
-
this.state = "processing", this.render();
|
|
747
|
+
this.state = "processing", this.tagClarity("processing"), this.render();
|
|
737
748
|
try {
|
|
738
|
-
const
|
|
739
|
-
|
|
749
|
+
const t = await g(this.selectedFile), e = await this.apiClient.submitTryOn(
|
|
750
|
+
t,
|
|
740
751
|
this.productImageUrl
|
|
741
752
|
);
|
|
742
|
-
this.currentJobId =
|
|
743
|
-
|
|
753
|
+
this.currentJobId = e.jobId, this.tagClarity("processing", e.jobId), this.emit("ps:processing", { jobId: e.jobId }), this.sseClient?.disconnect(), this.sseClient = new y(e.streamUrl || this.apiClient.getStreamUrl(e.jobId)), this.sseUnsubscribe = this.sseClient.onJob(
|
|
754
|
+
e.jobId,
|
|
744
755
|
(r) => this.handleVtoUpdate(r)
|
|
745
|
-
), this.startPolling(
|
|
746
|
-
} catch (
|
|
747
|
-
const
|
|
748
|
-
this.errorMessage =
|
|
749
|
-
message:
|
|
750
|
-
code:
|
|
751
|
-
stack:
|
|
756
|
+
), this.startPolling(e.jobId);
|
|
757
|
+
} catch (t) {
|
|
758
|
+
const e = t instanceof Error ? t.message : this.t("Failed to start try-on");
|
|
759
|
+
this.errorMessage = e, this.state = "error", this.reportClientError({
|
|
760
|
+
message: e,
|
|
761
|
+
code: t?.code || "TRYON_SUBMIT_FAILED",
|
|
762
|
+
stack: t instanceof Error ? t.stack : void 0,
|
|
752
763
|
component: "PrimeStyleTryonElement",
|
|
753
764
|
view: "processing",
|
|
754
765
|
severity: "medium"
|
|
755
|
-
}), this.emit("ps:error", { message:
|
|
766
|
+
}), this.emit("ps:error", { message: e, code: t?.code }), this.render();
|
|
756
767
|
}
|
|
757
768
|
}
|
|
758
|
-
handleVtoUpdate(
|
|
759
|
-
|
|
760
|
-
jobId:
|
|
761
|
-
imageUrl:
|
|
762
|
-
}), this.render()) :
|
|
769
|
+
handleVtoUpdate(t) {
|
|
770
|
+
t.status === "completed" && t.imageUrl ? (this.state !== "result" || this.resultImageUrl?.startsWith("data:") && !t.imageUrl.startsWith("data:")) && (this.resultImageUrl = t.imageUrl, this.state = "result", this.tagClarity("result", t.galleryId), this.emit("ps:complete", {
|
|
771
|
+
jobId: t.galleryId,
|
|
772
|
+
imageUrl: t.imageUrl
|
|
773
|
+
}), this.render()) : t.status === "failed" && (this.errorMessage = t.error || this.t("Try-on generation failed"), this.state = "error", this.tagClarity("error", t.galleryId), this.reportClientError({
|
|
763
774
|
message: this.errorMessage,
|
|
764
775
|
code: "TRYON_GENERATION_FAILED",
|
|
765
776
|
component: "PrimeStyleTryonElement",
|
|
766
777
|
view: "processing",
|
|
767
778
|
severity: "medium",
|
|
768
|
-
jobId:
|
|
779
|
+
jobId: t.galleryId
|
|
769
780
|
}), this.emit("ps:error", { message: this.errorMessage }), this.render());
|
|
770
781
|
}
|
|
771
|
-
startPolling(
|
|
772
|
-
let
|
|
782
|
+
startPolling(t) {
|
|
783
|
+
let e = 0;
|
|
773
784
|
const r = 60, s = setInterval(async () => {
|
|
774
|
-
if (
|
|
785
|
+
if (e++, e > r || this.state === "result" || this.state === "idle") {
|
|
775
786
|
clearInterval(s);
|
|
776
787
|
return;
|
|
777
788
|
}
|
|
@@ -780,15 +791,15 @@ class b extends HTMLElement {
|
|
|
780
791
|
return;
|
|
781
792
|
}
|
|
782
793
|
try {
|
|
783
|
-
const o = await this.apiClient.getStatus(
|
|
794
|
+
const o = await this.apiClient.getStatus(t);
|
|
784
795
|
o.status === "completed" && o.imageUrl ? (this.state === "processing" && this.handleVtoUpdate({
|
|
785
|
-
galleryId:
|
|
796
|
+
galleryId: t,
|
|
786
797
|
status: "completed",
|
|
787
798
|
imageUrl: o.imageUrl,
|
|
788
799
|
error: null,
|
|
789
800
|
timestamp: Date.now()
|
|
790
801
|
}), clearInterval(s)) : o.status === "failed" && (this.state === "processing" && this.handleVtoUpdate({
|
|
791
|
-
galleryId:
|
|
802
|
+
galleryId: t,
|
|
792
803
|
status: "failed",
|
|
793
804
|
imageUrl: null,
|
|
794
805
|
error: o.message,
|
|
@@ -800,10 +811,10 @@ class b extends HTMLElement {
|
|
|
800
811
|
}
|
|
801
812
|
handleDownload() {
|
|
802
813
|
if (!this.resultImageUrl) return;
|
|
803
|
-
const
|
|
804
|
-
|
|
805
|
-
const r = URL.createObjectURL(
|
|
806
|
-
|
|
814
|
+
const t = document.createElement("a");
|
|
815
|
+
t.href = this.resultImageUrl, t.download = `primestyle-tryon-${Date.now()}.png`, t.target = "_blank", this.resultImageUrl.startsWith("data:") ? t.click() : fetch(this.resultImageUrl).then((e) => e.blob()).then((e) => {
|
|
816
|
+
const r = URL.createObjectURL(e);
|
|
817
|
+
t.href = r, t.click(), setTimeout(() => URL.revokeObjectURL(r), 100);
|
|
807
818
|
}).catch(() => {
|
|
808
819
|
window.open(this.resultImageUrl, "_blank");
|
|
809
820
|
});
|
|
@@ -814,7 +825,7 @@ class b extends HTMLElement {
|
|
|
814
825
|
// ── Custom Style Application ────────────────
|
|
815
826
|
applyButtonStyles() {
|
|
816
827
|
if (!this.shadow.querySelector(".ps-button")) return;
|
|
817
|
-
const
|
|
828
|
+
const e = {
|
|
818
829
|
backgroundColor: "--ps-btn-bg",
|
|
819
830
|
textColor: "--ps-btn-color",
|
|
820
831
|
borderRadius: "--ps-btn-radius",
|
|
@@ -838,13 +849,13 @@ class b extends HTMLElement {
|
|
|
838
849
|
iconColor: "--ps-btn-icon-color",
|
|
839
850
|
boxShadow: "--ps-btn-shadow"
|
|
840
851
|
};
|
|
841
|
-
for (const [r, s] of Object.entries(
|
|
852
|
+
for (const [r, s] of Object.entries(e)) {
|
|
842
853
|
const o = this.buttonStyles[r];
|
|
843
854
|
o && this.style.setProperty(s, o);
|
|
844
855
|
}
|
|
845
856
|
}
|
|
846
857
|
applyModalStyles() {
|
|
847
|
-
const
|
|
858
|
+
const t = {
|
|
848
859
|
overlayColor: "--ps-modal-overlay",
|
|
849
860
|
backgroundColor: "--ps-modal-bg",
|
|
850
861
|
textColor: "--ps-modal-color",
|
|
@@ -876,26 +887,26 @@ class b extends HTMLElement {
|
|
|
876
887
|
successColor: "--ps-success-color",
|
|
877
888
|
logoHeight: "--ps-logo-height"
|
|
878
889
|
};
|
|
879
|
-
for (const [
|
|
880
|
-
const s = this.modalStyles[
|
|
890
|
+
for (const [e, r] of Object.entries(t)) {
|
|
891
|
+
const s = this.modalStyles[e];
|
|
881
892
|
s && this.style.setProperty(r, s);
|
|
882
893
|
}
|
|
883
894
|
}
|
|
884
895
|
}
|
|
885
|
-
typeof window < "u" && !customElements.get("primestyle-tryon") && customElements.define("primestyle-tryon",
|
|
896
|
+
typeof window < "u" && !customElements.get("primestyle-tryon") && customElements.define("primestyle-tryon", v);
|
|
886
897
|
export {
|
|
887
898
|
c as ApiClient,
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
899
|
+
C as PrimeStyleError,
|
|
900
|
+
v as PrimeStyleTryon,
|
|
901
|
+
S as SUPPORTED_LOCALES,
|
|
902
|
+
y as SseClient,
|
|
903
|
+
k as TRANSLATION_KEYS,
|
|
904
|
+
E as checkAgeBeforeUpload,
|
|
905
|
+
g as compressImage,
|
|
895
906
|
l as createT,
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
907
|
+
U as detectLanguage,
|
|
908
|
+
p as detectProductImage,
|
|
909
|
+
m as isValidImageFile,
|
|
910
|
+
I as registerLocale
|
|
900
911
|
};
|
|
901
912
|
//# sourceMappingURL=primestyle-tryon.js.map
|