xactsize-webcomponents 1.0.45 → 1.0.46
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/{body-measurer-1cpY5UlE.mjs → body-measurer-B0eqi15q.mjs} +79 -57
- package/dist/body-measurer.d.ts +1 -0
- package/dist/body-measurer.es.js +1 -1
- package/dist/body-measurer.umd.js +20 -11
- package/dist/{es-MX-DJ2nEJ2L.mjs → es-MX-Bgbw_iNw.mjs} +1 -1
- package/dist/{pt-BR-CXZ-7FaF.mjs → pt-BR-s0pF3Tuk.mjs} +1 -1
- package/package.json +1 -1
|
@@ -17,7 +17,7 @@ const Yt = (i, t, e) => {
|
|
|
17
17
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
18
18
|
*/
|
|
19
19
|
const X = globalThis, yt = X.ShadowRoot && (X.ShadyCSS === void 0 || X.ShadyCSS.nativeShadow) && "adoptedStyleSheets" in Document.prototype && "replace" in CSSStyleSheet.prototype, _t = Symbol(), bt = /* @__PURE__ */ new WeakMap();
|
|
20
|
-
let
|
|
20
|
+
let Pt = class {
|
|
21
21
|
constructor(t, e, s) {
|
|
22
22
|
if (this._$cssResult$ = !0, s !== _t) throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");
|
|
23
23
|
this.cssText = t, this.t = e;
|
|
@@ -35,13 +35,13 @@ let Ut = class {
|
|
|
35
35
|
return this.cssText;
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
|
-
const Kt = (i) => new
|
|
38
|
+
const Kt = (i) => new Pt(typeof i == "string" ? i : i + "", void 0, _t), P = (i, ...t) => {
|
|
39
39
|
const e = i.length === 1 ? i[0] : t.reduce((s, o, n) => s + ((r) => {
|
|
40
40
|
if (r._$cssResult$ === !0) return r.cssText;
|
|
41
41
|
if (typeof r == "number") return r;
|
|
42
42
|
throw Error("Value passed to 'css' function must be a 'css' function result: " + r + ". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.");
|
|
43
43
|
})(o) + i[n + 1], i[0]);
|
|
44
|
-
return new
|
|
44
|
+
return new Pt(e, i, _t);
|
|
45
45
|
}, Qt = (i, t) => {
|
|
46
46
|
if (yt) i.adoptedStyleSheets = t.map((e) => e instanceof CSSStyleSheet ? e : e.styleSheet);
|
|
47
47
|
else for (const e of t) {
|
|
@@ -296,8 +296,8 @@ I.elementStyles = [], I.shadowRootOptions = { mode: "open" }, I[z("elementProper
|
|
|
296
296
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
297
297
|
*/
|
|
298
298
|
const N = globalThis, tt = N.trustedTypes, $t = tt ? tt.createPolicy("lit-html", { createHTML: (i) => i }) : void 0, Vt = "$lit$", A = `lit$${Math.random().toFixed(9).slice(2)}$`, Ft = "?" + A, ne = `<${Ft}>`, R = document, B = () => R.createComment(""), Z = (i) => i === null || typeof i != "object" && typeof i != "function", Ct = Array.isArray, re = (i) => Ct(i) || typeof (i == null ? void 0 : i[Symbol.iterator]) == "function", at = `[
|
|
299
|
-
\f\r]`, F = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,
|
|
300
|
-
\f\r"'\`<>=]|("|')|))|$)`, "g"),
|
|
299
|
+
\f\r]`, F = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g, Mt = /-->/g, St = />/g, M = RegExp(`>|${at}(?:([^\\s"'>=/]+)(${at}*=${at}*(?:[^
|
|
300
|
+
\f\r"'\`<>=]|("|')|))|$)`, "g"), Lt = /'/g, kt = /"/g, zt = /^(?:script|style|textarea|title)$/i, ae = (i) => (t, ...e) => ({ _$litType$: i, strings: t, values: e }), g = ae(1), T = Symbol.for("lit-noChange"), y = Symbol.for("lit-nothing"), Rt = /* @__PURE__ */ new WeakMap(), L = R.createTreeWalker(R, 129);
|
|
301
301
|
function Nt(i, t) {
|
|
302
302
|
if (!Ct(i) || !i.hasOwnProperty("raw")) throw Error("invalid template strings array");
|
|
303
303
|
return $t !== void 0 ? $t.createHTML(t) : t;
|
|
@@ -308,8 +308,8 @@ const le = (i, t) => {
|
|
|
308
308
|
for (let l = 0; l < e; l++) {
|
|
309
309
|
const h = i[l];
|
|
310
310
|
let u, f, m = -1, b = 0;
|
|
311
|
-
for (; b < h.length && (r.lastIndex = b, f = r.exec(h), f !== null); ) b = r.lastIndex, r === F ? f[1] === "!--" ? r =
|
|
312
|
-
const E = r ===
|
|
311
|
+
for (; b < h.length && (r.lastIndex = b, f = r.exec(h), f !== null); ) b = r.lastIndex, r === F ? f[1] === "!--" ? r = Mt : f[1] !== void 0 ? r = St : f[2] !== void 0 ? (zt.test(f[2]) && (o = RegExp("</" + f[2], "g")), r = M) : f[3] !== void 0 && (r = M) : r === M ? f[0] === ">" ? (r = o ?? F, m = -1) : f[1] === void 0 ? m = -2 : (m = r.lastIndex - f[2].length, u = f[1], r = f[3] === void 0 ? M : f[3] === '"' ? kt : Lt) : r === kt || r === Lt ? r = M : r === Mt || r === St ? r = F : (r = M, o = void 0);
|
|
312
|
+
const E = r === M && i[l + 1].startsWith("/>") ? " " : "";
|
|
313
313
|
n += r === F ? h + ne : m >= 0 ? (s.push(u), h.slice(0, m) + Vt + h.slice(m) + A + E) : h + A + (m === -2 ? l : E);
|
|
314
314
|
}
|
|
315
315
|
return [Nt(i, n + (i[e] || "<?>") + (t === 2 ? "</svg>" : t === 3 ? "</math>" : "")), s];
|
|
@@ -320,11 +320,11 @@ class j {
|
|
|
320
320
|
this.parts = [];
|
|
321
321
|
let n = 0, r = 0;
|
|
322
322
|
const l = t.length - 1, h = this.parts, [u, f] = le(t, e);
|
|
323
|
-
if (this.el = j.createElement(u, s),
|
|
323
|
+
if (this.el = j.createElement(u, s), L.currentNode = this.el.content, e === 2 || e === 3) {
|
|
324
324
|
const m = this.el.content.firstChild;
|
|
325
325
|
m.replaceWith(...m.childNodes);
|
|
326
326
|
}
|
|
327
|
-
for (; (o =
|
|
327
|
+
for (; (o = L.nextNode()) !== null && h.length < l; ) {
|
|
328
328
|
if (o.nodeType === 1) {
|
|
329
329
|
if (o.hasAttributes()) for (const m of o.getAttributeNames()) if (m.endsWith(Vt)) {
|
|
330
330
|
const b = f[r++], E = o.getAttribute(m).split(A), K = /([.?@])?(.*)/.exec(b);
|
|
@@ -334,7 +334,7 @@ class j {
|
|
|
334
334
|
const m = o.textContent.split(A), b = m.length - 1;
|
|
335
335
|
if (b > 0) {
|
|
336
336
|
o.textContent = tt ? tt.emptyScript : "";
|
|
337
|
-
for (let E = 0; E < b; E++) o.append(m[E], B()),
|
|
337
|
+
for (let E = 0; E < b; E++) o.append(m[E], B()), L.nextNode(), h.push({ type: 2, index: ++n });
|
|
338
338
|
o.append(m[b], B());
|
|
339
339
|
}
|
|
340
340
|
}
|
|
@@ -370,16 +370,16 @@ class he {
|
|
|
370
370
|
}
|
|
371
371
|
u(t) {
|
|
372
372
|
const { el: { content: e }, parts: s } = this._$AD, o = ((t == null ? void 0 : t.creationScope) ?? R).importNode(e, !0);
|
|
373
|
-
|
|
374
|
-
let n =
|
|
373
|
+
L.currentNode = o;
|
|
374
|
+
let n = L.nextNode(), r = 0, l = 0, h = s[0];
|
|
375
375
|
for (; h !== void 0; ) {
|
|
376
376
|
if (r === h.index) {
|
|
377
377
|
let u;
|
|
378
378
|
h.type === 2 ? u = new W(n, n.nextSibling, this, t) : h.type === 1 ? u = new h.ctor(n, h.name, h.strings, this, t) : h.type === 6 && (u = new ue(n, this, t)), this._$AV.push(u), h = s[++l];
|
|
379
379
|
}
|
|
380
|
-
r !== (h == null ? void 0 : h.index) && (n =
|
|
380
|
+
r !== (h == null ? void 0 : h.index) && (n = L.nextNode(), r++);
|
|
381
381
|
}
|
|
382
|
-
return
|
|
382
|
+
return L.currentNode = R, o;
|
|
383
383
|
}
|
|
384
384
|
p(t) {
|
|
385
385
|
let e = 0;
|
|
@@ -557,8 +557,8 @@ let C = class extends I {
|
|
|
557
557
|
return T;
|
|
558
558
|
}
|
|
559
559
|
};
|
|
560
|
-
var
|
|
561
|
-
C._$litElement$ = !0, C.finalized = !0, (
|
|
560
|
+
var Ut;
|
|
561
|
+
C._$litElement$ = !0, C.finalized = !0, (Ut = k.litElementHydrateSupport) == null || Ut.call(k, { LitElement: C });
|
|
562
562
|
const ht = k.litElementPolyfillSupport;
|
|
563
563
|
ht == null || ht({ LitElement: C });
|
|
564
564
|
(k.litElementVersions ?? (k.litElementVersions = [])).push("4.2.0");
|
|
@@ -707,9 +707,9 @@ function Ee(i) {
|
|
|
707
707
|
* Copyright 2020 Google LLC
|
|
708
708
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
709
709
|
*/
|
|
710
|
-
const Ae = "", $e = "h",
|
|
711
|
-
function
|
|
712
|
-
return (t ? $e :
|
|
710
|
+
const Ae = "", $e = "h", Me = "s";
|
|
711
|
+
function Se(i, t) {
|
|
712
|
+
return (t ? $e : Me) + Ee(typeof i == "string" ? i : i.join(Ae));
|
|
713
713
|
}
|
|
714
714
|
/**
|
|
715
715
|
* @license
|
|
@@ -717,7 +717,7 @@ function Le(i, t) {
|
|
|
717
717
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
718
718
|
*/
|
|
719
719
|
const Ot = /* @__PURE__ */ new WeakMap(), It = /* @__PURE__ */ new Map();
|
|
720
|
-
function
|
|
720
|
+
function Le(i, t, e) {
|
|
721
721
|
if (i) {
|
|
722
722
|
const s = (e == null ? void 0 : e.id) ?? ke(t), o = i[s];
|
|
723
723
|
if (o) {
|
|
@@ -745,7 +745,7 @@ function Me(i, t, e) {
|
|
|
745
745
|
function ke(i) {
|
|
746
746
|
const t = typeof i == "string" ? i : i.strings;
|
|
747
747
|
let e = It.get(t);
|
|
748
|
-
return e === void 0 && (e =
|
|
748
|
+
return e === void 0 && (e = Se(t, typeof i != "string" && !("strTag" in i)), It.set(t, e)), e;
|
|
749
749
|
}
|
|
750
750
|
/**
|
|
751
751
|
* @license
|
|
@@ -755,32 +755,32 @@ function ke(i) {
|
|
|
755
755
|
function ct(i) {
|
|
756
756
|
window.dispatchEvent(new CustomEvent(pt, { detail: i }));
|
|
757
757
|
}
|
|
758
|
-
let et = "", dt, Gt, it, ut, Wt,
|
|
759
|
-
|
|
758
|
+
let et = "", dt, Gt, it, ut, Wt, S = new jt();
|
|
759
|
+
S.resolve();
|
|
760
760
|
let Q = 0;
|
|
761
|
-
const Re = (i) => (Ce((t, e) =>
|
|
761
|
+
const Re = (i) => (Ce((t, e) => Le(Wt, t, e)), et = Gt = i.sourceLocale, it = new Set(i.targetLocales), it.add(i.sourceLocale), ut = i.loadLocale, { getLocale: Te, setLocale: Oe }), Te = () => et, Oe = (i) => {
|
|
762
762
|
if (i === (dt ?? et))
|
|
763
|
-
return
|
|
763
|
+
return S.promise;
|
|
764
764
|
if (!it || !ut)
|
|
765
765
|
throw new Error("Internal error");
|
|
766
766
|
if (!it.has(i))
|
|
767
767
|
throw new Error("Invalid locale code");
|
|
768
768
|
Q++;
|
|
769
769
|
const t = Q;
|
|
770
|
-
return dt = i,
|
|
770
|
+
return dt = i, S.settled && (S = new jt()), ct({ status: "loading", loadingLocale: i }), (i === Gt ? (
|
|
771
771
|
// We could switch to the source locale synchronously, but we prefer to
|
|
772
772
|
// queue it on a microtask so that switching locales is consistently
|
|
773
773
|
// asynchronous.
|
|
774
774
|
Promise.resolve({ templates: void 0 })
|
|
775
775
|
) : ut(i)).then((s) => {
|
|
776
|
-
Q === t && (et = i, dt = void 0, Wt = s.templates, ct({ status: "ready", readyLocale: i }),
|
|
776
|
+
Q === t && (et = i, dt = void 0, Wt = s.templates, ct({ status: "ready", readyLocale: i }), S.resolve());
|
|
777
777
|
}, (s) => {
|
|
778
778
|
Q === t && (ct({
|
|
779
779
|
status: "error",
|
|
780
780
|
errorLocale: i,
|
|
781
781
|
errorMessage: s.toString()
|
|
782
|
-
}),
|
|
783
|
-
}),
|
|
782
|
+
}), S.reject(s));
|
|
783
|
+
}), S.promise;
|
|
784
784
|
}, qt = "en", Ie = [
|
|
785
785
|
"es-MX",
|
|
786
786
|
"pt-BR"
|
|
@@ -791,7 +791,7 @@ const Re = (i) => (Ce((t, e) => Me(Wt, t, e)), et = Gt = i.sourceLocale, it = ne
|
|
|
791
791
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
792
792
|
*/
|
|
793
793
|
const De = { ATTRIBUTE: 1 }, He = (i) => (...t) => ({ _$litDirective$: i, values: t });
|
|
794
|
-
class
|
|
794
|
+
class Ue {
|
|
795
795
|
constructor(t) {
|
|
796
796
|
}
|
|
797
797
|
get _$AU() {
|
|
@@ -812,7 +812,7 @@ class Pe {
|
|
|
812
812
|
* Copyright 2018 Google LLC
|
|
813
813
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
814
814
|
*/
|
|
815
|
-
const
|
|
815
|
+
const Pe = He(class extends Ue {
|
|
816
816
|
constructor(i) {
|
|
817
817
|
var t;
|
|
818
818
|
if (super(i), i.type !== De.ATTRIBUTE || i.name !== "class" || ((t = i.strings) == null ? void 0 : t.length) > 2) throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.");
|
|
@@ -860,7 +860,7 @@ let O = class extends C {
|
|
|
860
860
|
`;
|
|
861
861
|
}
|
|
862
862
|
};
|
|
863
|
-
O.styles =
|
|
863
|
+
O.styles = P`
|
|
864
864
|
:host {
|
|
865
865
|
display: block;
|
|
866
866
|
width: 100%;
|
|
@@ -961,7 +961,7 @@ var ze = Object.defineProperty, Ne = Object.getOwnPropertyDescriptor, nt = (i, t
|
|
|
961
961
|
(r = i[n]) && (o = (s ? r(t, e, o) : r(o)) || o);
|
|
962
962
|
return s && o && ze(t, e, o), o;
|
|
963
963
|
};
|
|
964
|
-
let
|
|
964
|
+
let U = class extends C {
|
|
965
965
|
constructor() {
|
|
966
966
|
super(...arguments), this.height = 0, this.brandName = "", this.handleStart = () => {
|
|
967
967
|
var t;
|
|
@@ -1033,7 +1033,7 @@ let P = class extends C {
|
|
|
1033
1033
|
`;
|
|
1034
1034
|
}
|
|
1035
1035
|
};
|
|
1036
|
-
|
|
1036
|
+
U.styles = P`
|
|
1037
1037
|
:host {
|
|
1038
1038
|
display: block;
|
|
1039
1039
|
font-family: 'Inter', 'Helvetica', Arial, sans-serif;
|
|
@@ -1211,17 +1211,17 @@ P.styles = U`
|
|
|
1211
1211
|
`;
|
|
1212
1212
|
nt([
|
|
1213
1213
|
d({ type: Number })
|
|
1214
|
-
],
|
|
1214
|
+
], U.prototype, "height", 2);
|
|
1215
1215
|
nt([
|
|
1216
1216
|
d({ type: String })
|
|
1217
|
-
],
|
|
1217
|
+
], U.prototype, "brandName", 2);
|
|
1218
1218
|
nt([
|
|
1219
1219
|
d({ type: Function })
|
|
1220
|
-
],
|
|
1221
|
-
|
|
1220
|
+
], U.prototype, "onStartMeasurement", 2);
|
|
1221
|
+
U = nt([
|
|
1222
1222
|
V("xact-step-one"),
|
|
1223
1223
|
q()
|
|
1224
|
-
],
|
|
1224
|
+
], U);
|
|
1225
1225
|
var Be = Object.getOwnPropertyDescriptor, Ze = (i, t, e, s) => {
|
|
1226
1226
|
for (var o = s > 1 ? void 0 : s ? Be(t, e) : t, n = i.length - 1, r; n >= 0; n--)
|
|
1227
1227
|
(r = i[n]) && (o = r(o) || o);
|
|
@@ -1275,7 +1275,7 @@ let ft = class extends C {
|
|
|
1275
1275
|
`;
|
|
1276
1276
|
}
|
|
1277
1277
|
};
|
|
1278
|
-
ft.styles =
|
|
1278
|
+
ft.styles = P`
|
|
1279
1279
|
.modal-footer {
|
|
1280
1280
|
text-align: center;
|
|
1281
1281
|
font-size: 12px;
|
|
@@ -1444,7 +1444,7 @@ let x = class extends C {
|
|
|
1444
1444
|
`;
|
|
1445
1445
|
}
|
|
1446
1446
|
};
|
|
1447
|
-
x.styles =
|
|
1447
|
+
x.styles = P`
|
|
1448
1448
|
:host {
|
|
1449
1449
|
display: flex;
|
|
1450
1450
|
flex-direction: column;
|
|
@@ -1722,7 +1722,7 @@ let G = class extends C {
|
|
|
1722
1722
|
`;
|
|
1723
1723
|
}
|
|
1724
1724
|
};
|
|
1725
|
-
G.styles =
|
|
1725
|
+
G.styles = P`
|
|
1726
1726
|
:host {
|
|
1727
1727
|
display: flex;
|
|
1728
1728
|
justify-content: center;
|
|
@@ -2111,7 +2111,7 @@ var Qe = Object.defineProperty, Xe = Object.getOwnPropertyDescriptor, p = (i, t,
|
|
|
2111
2111
|
const { getLocale: ii, setLocale: Ht } = Re({
|
|
2112
2112
|
sourceLocale: qt,
|
|
2113
2113
|
targetLocales: Ie,
|
|
2114
|
-
loadLocale: (i) => Yt(/* @__PURE__ */ Object.assign({ "./generated/locales/es-MX.ts": () => import("./es-MX-
|
|
2114
|
+
loadLocale: (i) => Yt(/* @__PURE__ */ Object.assign({ "./generated/locales/es-MX.ts": () => import("./es-MX-Bgbw_iNw.mjs"), "./generated/locales/pt-BR.ts": () => import("./pt-BR-s0pF3Tuk.mjs") }), `./generated/locales/${i}.ts`, 4)
|
|
2115
2115
|
});
|
|
2116
2116
|
let c = class extends C {
|
|
2117
2117
|
constructor() {
|
|
@@ -2286,6 +2286,9 @@ let c = class extends C {
|
|
|
2286
2286
|
var i;
|
|
2287
2287
|
this.showModal = !1, this.onMeasurementCanceled && typeof this.onMeasurementCanceled == "function" && this.onMeasurementCanceled(), this.stopPolling(), (i = this.aiSession) == null || i.disconnect(), this.dispatchEvent(new CustomEvent("measurementCanceled", { detail: {} }));
|
|
2288
2288
|
}
|
|
2289
|
+
handleDialogClose() {
|
|
2290
|
+
this.showModal && this.closeModal();
|
|
2291
|
+
}
|
|
2289
2292
|
async step2advancement() {
|
|
2290
2293
|
if (this.height < 50 || this.height > 300) {
|
|
2291
2294
|
this.errorMessage = this.getTranslatedMessage("ERR_HEIGHT_INVALID");
|
|
@@ -2297,7 +2300,13 @@ let c = class extends C {
|
|
|
2297
2300
|
this.step = 3, this.errorMessage = "", this.shouldStartMeasurement = !0;
|
|
2298
2301
|
}
|
|
2299
2302
|
updated(i) {
|
|
2300
|
-
|
|
2303
|
+
var t;
|
|
2304
|
+
if (super.updated(i), i.has("step") && this.step === 3 && this.shouldStartMeasurement && (this.initializeMeasurement(), this.shouldStartMeasurement = !1), i.has("showModal")) {
|
|
2305
|
+
const e = (t = this.shadowRoot) == null ? void 0 : t.getElementById(
|
|
2306
|
+
"measurer-dialog"
|
|
2307
|
+
);
|
|
2308
|
+
e && (this.showModal && !e.open ? e.showModal() : !this.showModal && e.open && e.close());
|
|
2309
|
+
}
|
|
2301
2310
|
}
|
|
2302
2311
|
async initializeMeasurement() {
|
|
2303
2312
|
if (!this.apiKey)
|
|
@@ -2314,7 +2323,11 @@ let c = class extends C {
|
|
|
2314
2323
|
throw new Error("VTON URL is required");
|
|
2315
2324
|
this.videoElement = this.shadowRoot.querySelector("video");
|
|
2316
2325
|
try {
|
|
2317
|
-
this.stream = await navigator.mediaDevices.getUserMedia({ video: !0 }), this.videoElement && (this.videoElement.srcObject = this.stream, await this.videoElement.play(), await this.loadCameras(), this.aiSession = new gt(
|
|
2326
|
+
this.stream = await navigator.mediaDevices.getUserMedia({ video: !0 }), this.videoElement && (this.videoElement.srcObject = this.stream, await this.videoElement.play(), await this.loadCameras(), this.aiSession = new gt(
|
|
2327
|
+
this.baseUrl,
|
|
2328
|
+
this.apiKey,
|
|
2329
|
+
this.culture
|
|
2330
|
+
), await this.aiSession.connect(), this.aiSession.startMicrophone(), this.startPolling());
|
|
2318
2331
|
} catch {
|
|
2319
2332
|
this.errorMessage = a("Error accessing webcam");
|
|
2320
2333
|
}
|
|
@@ -2485,7 +2498,7 @@ let c = class extends C {
|
|
|
2485
2498
|
></xact-button>
|
|
2486
2499
|
|
|
2487
2500
|
${this.showModal ? g`
|
|
2488
|
-
<
|
|
2501
|
+
<dialog class="modal" id="measurer-dialog" @close=${this.handleDialogClose}>
|
|
2489
2502
|
<div class="modal-content">
|
|
2490
2503
|
<div
|
|
2491
2504
|
style="display: flex; justify-content: space-between"
|
|
@@ -2546,7 +2559,7 @@ let c = class extends C {
|
|
|
2546
2559
|
</div>
|
|
2547
2560
|
|
|
2548
2561
|
<video
|
|
2549
|
-
class=${
|
|
2562
|
+
class=${Pe({
|
|
2550
2563
|
error: !this.errorMessage,
|
|
2551
2564
|
success: !!this.errorMessage
|
|
2552
2565
|
})}
|
|
@@ -2594,12 +2607,12 @@ let c = class extends C {
|
|
|
2594
2607
|
` : ""}
|
|
2595
2608
|
<xact-footer></xact-footer>
|
|
2596
2609
|
</div>
|
|
2597
|
-
</
|
|
2610
|
+
</dialog>
|
|
2598
2611
|
` : ""}
|
|
2599
2612
|
`;
|
|
2600
2613
|
}
|
|
2601
2614
|
};
|
|
2602
|
-
c.styles =
|
|
2615
|
+
c.styles = P`
|
|
2603
2616
|
:host {
|
|
2604
2617
|
display: block;
|
|
2605
2618
|
font-family: Arial, sans-serif;
|
|
@@ -2636,18 +2649,27 @@ c.styles = U`
|
|
|
2636
2649
|
}
|
|
2637
2650
|
|
|
2638
2651
|
/* Modal Styles */
|
|
2639
|
-
.modal {
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2652
|
+
dialog.modal {
|
|
2653
|
+
border: none;
|
|
2654
|
+
background: transparent;
|
|
2655
|
+
padding: 0;
|
|
2656
|
+
margin: 0;
|
|
2657
|
+
width: 100vw;
|
|
2658
|
+
height: 100vh;
|
|
2659
|
+
max-width: 100vw;
|
|
2660
|
+
max-height: 100vh;
|
|
2661
|
+
overflow: hidden;
|
|
2662
|
+
}
|
|
2663
|
+
|
|
2664
|
+
dialog.modal[open] {
|
|
2646
2665
|
display: flex;
|
|
2647
2666
|
flex-direction: column;
|
|
2648
2667
|
justify-content: center;
|
|
2649
2668
|
align-items: center;
|
|
2650
|
-
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
dialog.modal::backdrop {
|
|
2672
|
+
background: rgba(0, 0, 0, 0.5);
|
|
2651
2673
|
}
|
|
2652
2674
|
|
|
2653
2675
|
.modal-content {
|
package/dist/body-measurer.d.ts
CHANGED
|
@@ -56,6 +56,7 @@ export declare class BodyMeasurer extends LitElement {
|
|
|
56
56
|
private handleEscKey;
|
|
57
57
|
private openModal;
|
|
58
58
|
private closeModal;
|
|
59
|
+
private handleDialogClose;
|
|
59
60
|
private step2advancement;
|
|
60
61
|
private startMeasurement;
|
|
61
62
|
updated(changedProperties: Map<string, any>): void;
|
package/dist/body-measurer.es.js
CHANGED
|
@@ -1001,7 +1001,7 @@
|
|
|
1001
1001
|
50% { transform: translateX(22px); }
|
|
1002
1002
|
}
|
|
1003
1003
|
|
|
1004
|
-
`,Ce([p({type:Number})],K.prototype,"height",2),Ce([p({type:Function})],K.prototype,"onStep2advancement",2),K=Ce([P("xact-step-informs"),Y()],K);const We="data:image/svg+xml,%3csvg%20width='22'%20height='40'%20viewBox='0%200%2022%2040'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M21.517%200L0%2013.3362V0H21.517Z'%20fill='white'/%3e%3cpath%20d='M21.517%2013.339L0%2026.6724V13.3362H21.517V13.339Z'%20fill='white'/%3e%3cpath%20d='M21.517%2026.6755L0%2040.0089V26.6726H21.517V26.6755Z'%20fill='%231C28BA'/%3e%3c/svg%3e",qt="data:image/svg+xml,%3csvg%20width='22'%20height='41'%20viewBox='0%200%2022%2041'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M21.517%200.00878906L0%2013.345V0.00878906H21.517Z'%20fill='white'/%3e%3cpath%20d='M21.517%2013.3478L0%2026.6812V13.345H21.517V13.3478Z'%20fill='%231C28BA'/%3e%3cpath%20d='M21.517%2026.6843L0%2040.0176V26.6814H21.517V26.6843Z'%20fill='white'/%3e%3c/svg%3e",Yt="data:image/svg+xml,%3csvg%20width='22'%20height='41'%20viewBox='0%200%2022%2041'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M21.517%200.0204381L0%2013.3538V0.0175781H21.517V0.0204381Z'%20fill='%231C28BA'/%3e%3cpath%20d='M21.517%2013.3538L0%2026.69V13.3538H21.517Z'%20fill='white'/%3e%3cpath%20d='M21.517%2026.693L0%2040.0264V26.6902H21.517V26.693Z'%20fill='white'/%3e%3c/svg%3e",N=class N{constructor(){this.audioContext=null,this.playbackCtx=null,this.stream=null,this.processor=null,this.source=null,this.audioPlaybackQueue=[],this.isPlaying=!1,this.isUserSpeaking=!1,this.speechTimeout=null}get isPlaybackActive(){return this.isPlaying||this.audioPlaybackQueue.length>0}async startMicrophone(e){try{this.stream=await navigator.mediaDevices.getUserMedia({audio:{sampleRate:16e3,channelCount:1,echoCancellation:!0}}),this.audioContext=new AudioContext({sampleRate:16e3}),this.source=this.audioContext.createMediaStreamSource(this.stream),this.processor=this.audioContext.createScriptProcessor(4096,1,1),this.processor.onaudioprocess=t=>{const i=t.inputBuffer.getChannelData(0);let s=0;for(let d=0;d<i.length;d++)s+=i[d]*i[d];Math.sqrt(s/i.length)>N.SPEECH_THRESHOLD&&(this.isUserSpeaking=!0,this.speechTimeout&&clearTimeout(this.speechTimeout),this.speechTimeout=window.setTimeout(()=>{this.isUserSpeaking=!1},N.SPEECH_HOLD_TIME));const r=this.float32ToInt16(i);e(r.buffer)},this.source.connect(this.processor),this.processor.connect(this.audioContext.destination)}catch(t){console.error("Microphone access denied or error:",t)}}float32ToInt16(e){const t=new Int16Array(e.length);for(let i=0;i<e.length;i++){const s=Math.max(-1,Math.min(1,e[i]));t[i]=s<0?s*32768:s*32767}return t}initPlayback(){this.playbackCtx||(this.playbackCtx=new AudioContext({sampleRate:24e3}))}queueAudio(e){this.audioPlaybackQueue.push(e),this.playNextChunk()}playNextChunk(){if(this.isPlaying||this.audioPlaybackQueue.length===0)return;this.initPlayback();const e=this.audioPlaybackQueue.shift();this.isPlaying=!0;const t=new Int16Array(e),i=new Float32Array(t.length);for(let r=0;r<t.length;r++)i[r]=t[r]/32767;const s=this.playbackCtx.createBuffer(1,i.length,24e3);s.copyToChannel(i,0);const o=this.playbackCtx.createBufferSource();o.buffer=s,o.connect(this.playbackCtx.destination),o.onended=()=>{this.isPlaying=!1,this.audioPlaybackQueue.length===0&&this.onQueueDrained&&this.onQueueDrained(),this.playNextChunk()},o.start()}clearPlaybackQueue(){this.audioPlaybackQueue=[]}stopAll(){this.clearPlaybackQueue(),this.processor&&this.source&&(this.processor.disconnect(),this.source.disconnect()),this.stream&&(this.stream.getTracks().forEach(e=>e.stop()),this.stream=null),this.audioContext&&(this.audioContext.close(),this.audioContext=null),this.playbackCtx&&(this.playbackCtx.close(),this.playbackCtx=null)}};N.SPEECH_THRESHOLD=.02,N.SPEECH_HOLD_TIME=1500;let ve=N;const oe=class oe{constructor(e,t,i="en"){this.ws=null,this.introSent=!1,this.introComplete=!1,this.lastCvError="",this.lastCvErrorTime=0,this.measurementComplete=!1,this.isDisconnected=!1,this.apiUrl=e,this.apiKey=t,this.localeCode=i,this.audioManager=new ve}async connect(){try{const e=await fetch(`${this.apiUrl}/api/ConversationalAI/ticket`,{method:"POST",headers:{"Content-Type":"application/json","X-Api-Key":this.apiKey}});if(this.isDisconnected){console.log("AI session was disconnected before ticket response.");return}if(!e.ok){console.error("Failed to get ticket",e.statusText);return}const t=await e.json();if(!t||!t.ticket_id){console.error("Invalid ticket response");return}if(this.isDisconnected){console.log("AI session was disconnected before websocket could be opened.");return}const i="wss://conversational-ai-service-923169850574.southamerica-east1.run.app",s=crypto.randomUUID(),o=`${i}/ws/chat/${s}/${t.ticket_id}`;this.ws=new WebSocket(o),this.ws.binaryType="arraybuffer",this.ws.onopen=()=>{console.log("AI session connected."),!this.introSent&&this.ws&&this.ws.readyState===WebSocket.OPEN&&(this.introSent=!0,this.ws.send(JSON.stringify({cv_alert:`Measurement process started! The user speaks ${this.localeCode}.`})))},this.ws.onmessage=r=>{if(r.data instanceof ArrayBuffer){this.audioManager.queueAudio(r.data);return}try{const d=JSON.parse(r.data);switch(d.type){case"user":break;case"gemini":break;case"interrupted":this.audioManager.clearPlaybackQueue();break;case"error":console.error("AI session error:",d.error);break;case"turn_complete":this.handleTurnComplete();break}}catch(d){console.error("Error parsing WS message:",d)}},this.ws.onclose=r=>{r.code===4003&&console.error("Ticket was invalid or expired"),console.log("AI session disconnected.")},this.ws.onerror=r=>{console.error("AI Session WebSocket Error:",r)}}catch(e){console.error("Failed to connect to AI session:",e)}}handleTurnComplete(){if(!this.introComplete){this.audioManager.onQueueDrained=()=>{this.audioManager.onQueueDrained=void 0,this.introComplete=!0,console.log("AI introduction audio finished. CV errors now enabled.")},this.audioManager.isPlaybackActive||(this.audioManager.onQueueDrained=void 0,this.introComplete=!0,console.log("AI introduction complete (no audio). CV errors now enabled."));return}if(this.measurementComplete){this.audioManager.onQueueDrained=()=>{this.audioManager.onQueueDrained=void 0,console.log("AI goodbye audio finished. Disconnecting session."),this.onTurnComplete&&this.onTurnComplete(),this.disconnect()},this.audioManager.isPlaybackActive||(this.audioManager.onQueueDrained=void 0,console.log("AI goodbye complete (no audio). Disconnecting session."),this.onTurnComplete&&this.onTurnComplete(),this.disconnect());return}}startMicrophone(){this.measurementComplete||(this.audioManager.initPlayback(),this.audioManager.startMicrophone(e=>{this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.send(e)}))}forwardCvError(e){if(!this.introComplete||this.measurementComplete||this.audioManager.isUserSpeaking)return;const t=Date.now(),i=e===this.lastCvError,s=t-this.lastCvErrorTime<oe.CV_ERROR_THROTTLE_MS;i&&s||(this.lastCvError=e,this.lastCvErrorTime=t,this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify({cv_alert:e})))}notifySuccess(e,t=""){this.measurementComplete=!0,this.audioManager.clearPlaybackQueue(),console.log("Sending success message to AI session",e,t),this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify({cv_alert:`SYSTEM ALERT: Measurement is complete! Recommended size: ${e}. ${t?`Extra context: ${t}. `:""}INSTRUCTION: Embody your persona! Enthusiastically reveal their size, offer a quick fashion compliment, and gracefully say goodbye.`}))}disconnect(){this.isDisconnected=!0,this.audioManager.stopAll(),this.ws&&(this.ws.close(1e3,"Measurement complete"),this.ws=null)}};oe.CV_ERROR_THROTTLE_MS=6e3;let xe=oe;var Wt=Object.defineProperty,Kt=Object.getOwnPropertyDescriptor,u=(a,e,t,i)=>{for(var s=i>1?void 0:i?Kt(e,t):e,o=a.length-1,r;o>=0;o--)(r=a[o])&&(s=(i?r(e,t,s):r(s))||s);return i&&s&&Wt(e,t,s),s};const{getLocale:Qt,setLocale:we}=Lt({sourceLocale:Ye,targetLocales:Ot,loadLocale:a=>V(Object.assign({"./generated/locales/es-MX.ts":()=>Promise.resolve().then(()=>Jt),"./generated/locales/pt-BR.ts":()=>Promise.resolve().then(()=>ti)}),`./generated/locales/${a}.ts`,4)});c.BodyMeasurer=class extends C{constructor(){super(...arguments),this.spinnerFrame=0,this.apiKey="",this.tenantId="1",this.productSku="123456",this.baseUrl="https://xactsize-dotnet-api-923169850574.southamerica-east1.run.app",this.apiUrl=this.baseUrl+"/api/measurer/measure/body",this.vtonUrl=this.baseUrl+"/api/VirtualTryOn/generate",this.garmentUrl="",this.vton=!1,this.brandName=void 0,this.buttonText="",this._culture="pt-BR",this.measurerKey="",this._isLocaleLoading=!1,this.showModal=!1,this.step=1,this.height=0,this.recommendedSize="",this.measurements={},this.errorMessage="",this.instructionMessage=n("Position yourself in front of the camera"),this.shouldStartMeasurement=!1,this.isLoading=!1,this.isFetching=!1,this.generatedImageUrl="",this.isVtonFetching=!1,this.vtonError=!1,this.videoElement=null,this.stream=null,this.poolingTimeout=null,this.instructionMessageTimeout=null,this.aiSession=null,this.cameras=[],this.currentCameraId=null,this.snowflakesCache=null}firstUpdated(){this.startSpinnerAnimation()}startSpinnerAnimation(){const e=[Yt,qt,We];this.spinnerInterval=setInterval(()=>{var i;const t=(i=this.shadowRoot)==null?void 0:i.querySelector(".spinner");t&&(t.src=e[this.spinnerFrame],this.spinnerFrame=(this.spinnerFrame+1)%e.length)},300)}get culture(){return this._culture}set culture(e){const t=this._culture;this._culture=e,this.requestUpdate("culture",t),this._applyLocale(e).catch(console.error)}async _applyLocale(e){try{this._isLocaleLoading=!0,this.requestUpdate(),await we(e)}catch(t){console.error("Failed to load locale",e,t),await we(Ye)}finally{this._isLocaleLoading=!1,this.requestUpdate()}}get errorMap(){return{ERR_RIGHT_ARM_TOO_HIGH:n("Lower your right arm",{id:"ERR_RIGHT_ARM_TOO_HIGH"}),ERR_LEFT_ARM_TOO_HIGH:n("Lower your left arm",{id:"ERR_LEFT_ARM_TOO_HIGH"}),ERR_ARMS_NOT_RAISED:n("Raise both arms to a 45-degree angle",{id:"ERR_ARMS_NOT_RAISED"}),ERR_RIGHT_ARM_NOT_RAISED:n("Raise your right arm to a 45-degree angle",{id:"ERR_RIGHT_ARM_NOT_RAISED"}),ERR_LEFT_ARM_NOT_RAISED:n("Raise your left arm to a 45-degree angle",{id:"ERR_LEFT_ARM_NOT_RAISED"}),ERR_BODY_LANDMARKS_NOT_DETECTED:n("Ensure your full body is visible in the camera",{id:"ERR_BODY_LANDMARKS_NOT_DETECTED"}),ERR_HIPS_NOT_VISIBLE:n("Adjust your position to show your hips",{id:"ERR_HIPS_NOT_VISIBLE"}),ERR_TOO_CLOSE_TO_CAMERA:n("Step back from the camera",{id:"ERR_TOO_CLOSE_TO_CAMERA"}),ERR_NOT_SIDE_VIEW:n("Turn to show your side profile",{id:"ERR_NOT_SIDE_VIEW"}),ERR_INVALID_CLOTHING_TYPE:n("This clothing type is not supported; please contact support",{id:"ERR_INVALID_CLOTHING_TYPE"}),ERR_UPPER_BODY_NOT_VISIBLE:n("Adjust your position to show your upper body",{id:"ERR_UPPER_BODY_NOT_VISIBLE"}),ERR_HEAD_TOO_CLOSE_TO_EDGE:n("Move your head away from the edge of the frame",{id:"ERR_HEAD_TOO_CLOSE_TO_EDGE"}),ERR_LOWER_BODY_NOT_VISIBLE:n("Adjust your position to show your lower body",{id:"ERR_LOWER_BODY_NOT_VISIBLE"}),ERR_FEET_TOO_CLOSE_TO_EDGE:n("Move your feet away from the edge of the frame",{id:"ERR_FEET_TOO_CLOSE_TO_EDGE"}),ERR_BODY_TOO_CLOSE_TO_EDGE:n("Move your body away from the edge of the frame",{id:"ERR_BODY_TOO_CLOSE_TO_EDGE"}),ERR_BODY_TOO_CLOSE_TO_EDGE_MOVE_LEFT:n("Move to the left to center your body",{id:"ERR_BODY_TOO_CLOSE_TO_EDGE_MOVE_LEFT"}),ERR_BODY_TOO_CLOSE_TO_EDGE_MOVE_RIGHT:n("Move to the right to center your body",{id:"ERR_BODY_TOO_CLOSE_TO_EDGE_MOVE_RIGHT"}),ERR_SHOULDERS_NOT_VISIBLE:n("Adjust your position to show your shoulders",{id:"ERR_SHOULDERS_NOT_VISIBLE"}),ERR_HEIGHT_MEASUREMENT_FAILED:n("Stand straight and ensure your full body is visible",{id:"ERR_HEIGHT_MEASUREMENT_FAILED"}),ERR_HEAD_POINT_NOT_DETECTED:n("Ensure your head is fully visible in the frame",{id:"ERR_HEAD_POINT_NOT_DETECTED"}),ERR_INCORRECT_POSTURE:n("Stand straight with your shoulders back",{id:"ERR_INCORRECT_POSTURE"}),ERR_HEM_MEASUREMENT_FAILED:n("Ensure your clothing hem is visible and clear",{id:"ERR_HEM_MEASUREMENT_FAILED"}),ERR_SHOULDER_MEASUREMENT_FAILED:n("Keep your shoulders relaxed and visible",{id:"ERR_SHOULDER_MEASUREMENT_FAILED"}),ERR_ARM_NOT_STRETCHED:n("Stretch your arms fully",{id:"ERR_ARM_NOT_STRETCHED"}),ERR_LEGS_NOT_DETECTED:n("Ensure your legs are fully visible in the frame",{id:"ERR_LEGS_NOT_DETECTED"}),ERR_HIPS_MEASUREMENT_FAILED:n("Stand straight and ensure your hips are visible",{id:"ERR_HIPS_MEASUREMENT_FAILED"}),ERR_WAIST_MEASUREMENT_FAILED:n("Stand straight and ensure your waist is visible",{id:"ERR_WAIST_MEASUREMENT_FAILED"}),ERR_INVALID_MEASURE_SIDE_VIEW:n("Turn to show a clear side profile",{id:"ERR_INVALID_MEASURE_SIDE_VIEW"}),ERR_INVALID_BODY_HEIGHT_TYPE:n("Ensure your full body is visible for height measurement",{id:"ERR_INVALID_BODY_HEIGHT_TYPE"}),ERR_IMAGE_LOAD_FAILED:n("Try again later; the image could not be processed",{id:"ERR_IMAGE_LOAD_FAILED"}),ERR_HEIGHT_INVALID:n("Height must be between 50 and 300 cm",{id:"ERR_HEIGHT_INVALID"})}}getTranslatedMessage(e){const t=this.errorMap[e];return t||(console.info("Error code is missing",e),n("An unexpected error occurred"))}connectedCallback(){super.connectedCallback(),console.log("New code loaded Jan 27 11:57am"),document.addEventListener("keydown",this.handleEscKey.bind(this)),this.snowflakesCache=this.generateSnowflakes()}disconnectedCallback(){var e;super.disconnectedCallback(),document.removeEventListener("keydown",this.handleEscKey.bind(this)),this.stopPolling(),clearInterval(this.spinnerInterval),(e=this.aiSession)==null||e.disconnect()}handleEscKey(e){e.key==="Escape"&&this.showModal&&this.closeModal()}openModal(){this.showModal=!0,this.step=1,this.height=0,this.instructionMessage=n("Position yourself in front of the camera")}closeModal(){var e;this.showModal=!1,this.onMeasurementCanceled&&typeof this.onMeasurementCanceled=="function"&&this.onMeasurementCanceled(),this.stopPolling(),(e=this.aiSession)==null||e.disconnect(),this.dispatchEvent(new CustomEvent("measurementCanceled",{detail:{}}))}async step2advancement(){if(this.height<50||this.height>300){this.errorMessage=this.getTranslatedMessage("ERR_HEIGHT_INVALID");return}this.step=3,this.errorMessage=""}async startMeasurement(){this.step=3,this.errorMessage="",this.shouldStartMeasurement=!0}updated(e){super.updated(e),e.has("step")&&this.step===3&&this.shouldStartMeasurement&&(this.initializeMeasurement(),this.shouldStartMeasurement=!1)}async initializeMeasurement(){if(!this.apiKey)throw new Error("API key is required");if(!this.tenantId)throw new Error("Tenant ID is required");if(!this.productSku)throw new Error("Product SKU is required");if(!this.baseUrl)throw new Error("Base URL is required");if(!this.apiUrl)throw new Error("API URL is required");if(!this.vtonUrl)throw new Error("VTON URL is required");this.videoElement=this.shadowRoot.querySelector("video");try{this.stream=await navigator.mediaDevices.getUserMedia({video:!0}),this.videoElement&&(this.videoElement.srcObject=this.stream,await this.videoElement.play(),await this.loadCameras(),this.aiSession=new xe(this.baseUrl,this.apiKey,this.culture),await this.aiSession.connect(),this.aiSession.startMicrophone(),this.startPolling())}catch{this.errorMessage=n("Error accessing webcam")}}async loadCameras(){try{const e=await navigator.mediaDevices.enumerateDevices();this.cameras=e.filter(t=>t.kind==="videoinput"),this.cameras.length>0&&(this.currentCameraId=this.cameras[0].deviceId)}catch(e){console.error("Error enumerating devices:",e)}}async flipCamera(){if(this.cameras.length<2)return;this.isLoading=!0,this.stopPolling();const t=(this.cameras.findIndex(i=>i.deviceId===this.currentCameraId)+1)%this.cameras.length;this.currentCameraId=this.cameras[t].deviceId;try{this.stream&&this.stream.getTracks().forEach(i=>i.stop()),this.stream=await navigator.mediaDevices.getUserMedia({video:{deviceId:{exact:this.currentCameraId}}}),this.videoElement&&(this.videoElement.srcObject=this.stream,await this.videoElement.play(),this.startPolling())}catch{this.errorMessage=n("Error switching camera")}finally{this.isLoading=!1}}async startPolling(){const t=[],i=async()=>{var f;if(!this.videoElement||!this.stream||this.isFetching)return;const s=document.createElement("canvas");s.width=this.videoElement.videoWidth,s.height=this.videoElement.videoHeight;const o=s.getContext("2d");o==null||o.drawImage(this.videoElement,0,0,s.width,s.height);const r=await new Promise(m=>s.toBlob(h=>m(h),"image/jpeg")),d=new File([r],"frame.jpg",{type:"image/jpeg"}),l=new FormData;l.append("image",d),l.append("height",this.height.toString()),l.append("productSku",this.productSku),this.measurerKey&&l.append("measurerKey",this.measurerKey);try{this.isFetching=!0,this.isLoading=!0,this.poolingTimeout&&clearTimeout(this.poolingTimeout),this.instructionMessageTimeout&&clearTimeout(this.instructionMessageTimeout);const h=await(await fetch(this.apiUrl,{method:"POST",body:l,headers:{Accept:"application/json","Cache-Control":"no-store",Pragma:"no-cache","X-Api-Key":this.apiKey}})).json();if(this.isFetching=!1,this.isLoading=!1,h.success&&h.chosenSize){this.generateVtonImage(d),t.push(h);const b=t.length;this.instructionMessage=n(ge`Scanning... ${b}/${3}`),b>=3?(this.processFinalResults(t),this.stopPolling(),this.step=4):this.poolingTimeout=setTimeout(i,500)}else this.instructionMessage=this.getTranslatedMessage(h.message||"UNKNOWN_ERROR"),h.message&&((f=this.aiSession)==null||f.forwardCvError(this.instructionMessage)),this.instructionMessageTimeout=setTimeout(()=>{t.length<3&&(this.poolingTimeout=setTimeout(i,0))},2e3)}catch{this.isFetching=!1,this.isLoading=!1,this.instructionMessage=n("Error processing measurement"),this.instructionMessageTimeout=setTimeout(()=>{this.poolingTimeout=setTimeout(i,0)},2e3)}};i()}async generateVtonImage(e){if(!this.vton||!this.garmentUrl||this.isVtonFetching||this.generatedImageUrl)return;this.isVtonFetching=!0,this.vtonError=!1;const t=new FormData;t.append("PersonImage",e),t.append("GarmentUrl",this.garmentUrl);try{const s=await(await fetch(this.vtonUrl,{method:"POST",body:t,headers:{Accept:"application/json","X-Api-Key":this.apiKey}})).json();s.result_urls&&s.result_urls.length>0?(this.generatedImageUrl=s.result_urls[0],this.isVtonFetching=!1):(this.vtonError=!0,this.isVtonFetching=!1)}catch(i){console.error("Error generating VTON image",i),this.vtonError=!0,this.isVtonFetching=!1}}processFinalResults(e){console.group("Scan Debug Report"),console.log(`✅ Collected ${e.length} successful scans.`),e.forEach((d,l)=>{console.log(`Scan #${l+1}: Size [${d.chosenSize}] | Chest: ${d.measurements.chest} | Waist: ${d.measurements.waist}`)});const t={};Object.keys(e[0].measurements||{}).forEach(d=>{let l=0,f=0;e.forEach(m=>{const h=m.measurements[d];typeof h=="number"&&(l+=h,f++)}),t[d]=f>0?Math.round(l/f*100)/100:0}),console.log("📏 Final Averaged Measurements:",t);const s={};e.forEach(d=>{const l=d.chosenSize;l&&(s[l]=(s[l]||0)+1)}),console.log("🗳️ Voting Results:",s);let o="",r=0;for(const[d,l]of Object.entries(s))l>r&&(r=l,o=d);if(console.log(`🏆 WINNER: ${o}`),console.groupEnd(),this.measurements=t,this.recommendedSize=o,this.instructionMessage=n("Measurement successful!"),this.aiSession){this.aiSession.onTurnComplete=()=>{this.aiSession=null};let d="";this.vton&&(this.isVtonFetching?d="An image of the user wearing the garment is currently being generated. TELL USER THEIR IMAGE IS GENERATING.":this.generatedImageUrl&&(d="The image has successfully generated. TELL USER: 'Here is your image in the garment'.")),this.aiSession.notifySuccess(o,d)}}stopPolling(){this.poolingTimeout!==null&&(clearTimeout(this.poolingTimeout),this.poolingTimeout=null),this.instructionMessageTimeout!==null&&(clearTimeout(this.instructionMessageTimeout),this.instructionMessageTimeout=null),this.stream&&(this.stream.getTracks().forEach(e=>e.stop()),this.stream=null)}acceptMeasurement(){var e;this.dispatchEvent(new CustomEvent("measurementAccepted",{detail:{size:this.recommendedSize}})),this.onMeasurementAccepted&&typeof this.onMeasurementAccepted=="function"&&this.onMeasurementAccepted(),this.showModal=!1,this.stopPolling(),(e=this.aiSession)==null||e.disconnect(),this.aiSession=null}resetMeasurement(){var e;this.step=1,this.height=0,this.recommendedSize="",this.measurements={},this.generatedImageUrl="",this.isVtonFetching=!1,this.vtonError=!1,this.stopPolling(),(e=this.aiSession)==null||e.disconnect(),this.aiSession=null}stopMeasurement(){this.resetMeasurement(),this.showModal=!1}generateSnowflakes(){const e=[];for(let i=0;i<80;i++){const s=Math.random()*100,o=8+Math.random()*17,r=-Math.random()*30;e.push(g`<span
|
|
1004
|
+
`,Ce([p({type:Number})],K.prototype,"height",2),Ce([p({type:Function})],K.prototype,"onStep2advancement",2),K=Ce([P("xact-step-informs"),Y()],K);const We="data:image/svg+xml,%3csvg%20width='22'%20height='40'%20viewBox='0%200%2022%2040'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M21.517%200L0%2013.3362V0H21.517Z'%20fill='white'/%3e%3cpath%20d='M21.517%2013.339L0%2026.6724V13.3362H21.517V13.339Z'%20fill='white'/%3e%3cpath%20d='M21.517%2026.6755L0%2040.0089V26.6726H21.517V26.6755Z'%20fill='%231C28BA'/%3e%3c/svg%3e",qt="data:image/svg+xml,%3csvg%20width='22'%20height='41'%20viewBox='0%200%2022%2041'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M21.517%200.00878906L0%2013.345V0.00878906H21.517Z'%20fill='white'/%3e%3cpath%20d='M21.517%2013.3478L0%2026.6812V13.345H21.517V13.3478Z'%20fill='%231C28BA'/%3e%3cpath%20d='M21.517%2026.6843L0%2040.0176V26.6814H21.517V26.6843Z'%20fill='white'/%3e%3c/svg%3e",Yt="data:image/svg+xml,%3csvg%20width='22'%20height='41'%20viewBox='0%200%2022%2041'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M21.517%200.0204381L0%2013.3538V0.0175781H21.517V0.0204381Z'%20fill='%231C28BA'/%3e%3cpath%20d='M21.517%2013.3538L0%2026.69V13.3538H21.517Z'%20fill='white'/%3e%3cpath%20d='M21.517%2026.693L0%2040.0264V26.6902H21.517V26.693Z'%20fill='white'/%3e%3c/svg%3e",N=class N{constructor(){this.audioContext=null,this.playbackCtx=null,this.stream=null,this.processor=null,this.source=null,this.audioPlaybackQueue=[],this.isPlaying=!1,this.isUserSpeaking=!1,this.speechTimeout=null}get isPlaybackActive(){return this.isPlaying||this.audioPlaybackQueue.length>0}async startMicrophone(e){try{this.stream=await navigator.mediaDevices.getUserMedia({audio:{sampleRate:16e3,channelCount:1,echoCancellation:!0}}),this.audioContext=new AudioContext({sampleRate:16e3}),this.source=this.audioContext.createMediaStreamSource(this.stream),this.processor=this.audioContext.createScriptProcessor(4096,1,1),this.processor.onaudioprocess=t=>{const i=t.inputBuffer.getChannelData(0);let s=0;for(let d=0;d<i.length;d++)s+=i[d]*i[d];Math.sqrt(s/i.length)>N.SPEECH_THRESHOLD&&(this.isUserSpeaking=!0,this.speechTimeout&&clearTimeout(this.speechTimeout),this.speechTimeout=window.setTimeout(()=>{this.isUserSpeaking=!1},N.SPEECH_HOLD_TIME));const r=this.float32ToInt16(i);e(r.buffer)},this.source.connect(this.processor),this.processor.connect(this.audioContext.destination)}catch(t){console.error("Microphone access denied or error:",t)}}float32ToInt16(e){const t=new Int16Array(e.length);for(let i=0;i<e.length;i++){const s=Math.max(-1,Math.min(1,e[i]));t[i]=s<0?s*32768:s*32767}return t}initPlayback(){this.playbackCtx||(this.playbackCtx=new AudioContext({sampleRate:24e3}))}queueAudio(e){this.audioPlaybackQueue.push(e),this.playNextChunk()}playNextChunk(){if(this.isPlaying||this.audioPlaybackQueue.length===0)return;this.initPlayback();const e=this.audioPlaybackQueue.shift();this.isPlaying=!0;const t=new Int16Array(e),i=new Float32Array(t.length);for(let r=0;r<t.length;r++)i[r]=t[r]/32767;const s=this.playbackCtx.createBuffer(1,i.length,24e3);s.copyToChannel(i,0);const o=this.playbackCtx.createBufferSource();o.buffer=s,o.connect(this.playbackCtx.destination),o.onended=()=>{this.isPlaying=!1,this.audioPlaybackQueue.length===0&&this.onQueueDrained&&this.onQueueDrained(),this.playNextChunk()},o.start()}clearPlaybackQueue(){this.audioPlaybackQueue=[]}stopAll(){this.clearPlaybackQueue(),this.processor&&this.source&&(this.processor.disconnect(),this.source.disconnect()),this.stream&&(this.stream.getTracks().forEach(e=>e.stop()),this.stream=null),this.audioContext&&(this.audioContext.close(),this.audioContext=null),this.playbackCtx&&(this.playbackCtx.close(),this.playbackCtx=null)}};N.SPEECH_THRESHOLD=.02,N.SPEECH_HOLD_TIME=1500;let ve=N;const oe=class oe{constructor(e,t,i="en"){this.ws=null,this.introSent=!1,this.introComplete=!1,this.lastCvError="",this.lastCvErrorTime=0,this.measurementComplete=!1,this.isDisconnected=!1,this.apiUrl=e,this.apiKey=t,this.localeCode=i,this.audioManager=new ve}async connect(){try{const e=await fetch(`${this.apiUrl}/api/ConversationalAI/ticket`,{method:"POST",headers:{"Content-Type":"application/json","X-Api-Key":this.apiKey}});if(this.isDisconnected){console.log("AI session was disconnected before ticket response.");return}if(!e.ok){console.error("Failed to get ticket",e.statusText);return}const t=await e.json();if(!t||!t.ticket_id){console.error("Invalid ticket response");return}if(this.isDisconnected){console.log("AI session was disconnected before websocket could be opened.");return}const i="wss://conversational-ai-service-923169850574.southamerica-east1.run.app",s=crypto.randomUUID(),o=`${i}/ws/chat/${s}/${t.ticket_id}`;this.ws=new WebSocket(o),this.ws.binaryType="arraybuffer",this.ws.onopen=()=>{console.log("AI session connected."),!this.introSent&&this.ws&&this.ws.readyState===WebSocket.OPEN&&(this.introSent=!0,this.ws.send(JSON.stringify({cv_alert:`Measurement process started! The user speaks ${this.localeCode}.`})))},this.ws.onmessage=r=>{if(r.data instanceof ArrayBuffer){this.audioManager.queueAudio(r.data);return}try{const d=JSON.parse(r.data);switch(d.type){case"user":break;case"gemini":break;case"interrupted":this.audioManager.clearPlaybackQueue();break;case"error":console.error("AI session error:",d.error);break;case"turn_complete":this.handleTurnComplete();break}}catch(d){console.error("Error parsing WS message:",d)}},this.ws.onclose=r=>{r.code===4003&&console.error("Ticket was invalid or expired"),console.log("AI session disconnected.")},this.ws.onerror=r=>{console.error("AI Session WebSocket Error:",r)}}catch(e){console.error("Failed to connect to AI session:",e)}}handleTurnComplete(){if(!this.introComplete){this.audioManager.onQueueDrained=()=>{this.audioManager.onQueueDrained=void 0,this.introComplete=!0,console.log("AI introduction audio finished. CV errors now enabled.")},this.audioManager.isPlaybackActive||(this.audioManager.onQueueDrained=void 0,this.introComplete=!0,console.log("AI introduction complete (no audio). CV errors now enabled."));return}if(this.measurementComplete){this.audioManager.onQueueDrained=()=>{this.audioManager.onQueueDrained=void 0,console.log("AI goodbye audio finished. Disconnecting session."),this.onTurnComplete&&this.onTurnComplete(),this.disconnect()},this.audioManager.isPlaybackActive||(this.audioManager.onQueueDrained=void 0,console.log("AI goodbye complete (no audio). Disconnecting session."),this.onTurnComplete&&this.onTurnComplete(),this.disconnect());return}}startMicrophone(){this.measurementComplete||(this.audioManager.initPlayback(),this.audioManager.startMicrophone(e=>{this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.send(e)}))}forwardCvError(e){if(!this.introComplete||this.measurementComplete||this.audioManager.isUserSpeaking)return;const t=Date.now(),i=e===this.lastCvError,s=t-this.lastCvErrorTime<oe.CV_ERROR_THROTTLE_MS;i&&s||(this.lastCvError=e,this.lastCvErrorTime=t,this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify({cv_alert:e})))}notifySuccess(e,t=""){this.measurementComplete=!0,this.audioManager.clearPlaybackQueue(),console.log("Sending success message to AI session",e,t),this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify({cv_alert:`SYSTEM ALERT: Measurement is complete! Recommended size: ${e}. ${t?`Extra context: ${t}. `:""}INSTRUCTION: Embody your persona! Enthusiastically reveal their size, offer a quick fashion compliment, and gracefully say goodbye.`}))}disconnect(){this.isDisconnected=!0,this.audioManager.stopAll(),this.ws&&(this.ws.close(1e3,"Measurement complete"),this.ws=null)}};oe.CV_ERROR_THROTTLE_MS=6e3;let xe=oe;var Wt=Object.defineProperty,Kt=Object.getOwnPropertyDescriptor,u=(a,e,t,i)=>{for(var s=i>1?void 0:i?Kt(e,t):e,o=a.length-1,r;o>=0;o--)(r=a[o])&&(s=(i?r(e,t,s):r(s))||s);return i&&s&&Wt(e,t,s),s};const{getLocale:Qt,setLocale:we}=Lt({sourceLocale:Ye,targetLocales:Ot,loadLocale:a=>V(Object.assign({"./generated/locales/es-MX.ts":()=>Promise.resolve().then(()=>Jt),"./generated/locales/pt-BR.ts":()=>Promise.resolve().then(()=>ti)}),`./generated/locales/${a}.ts`,4)});c.BodyMeasurer=class extends C{constructor(){super(...arguments),this.spinnerFrame=0,this.apiKey="",this.tenantId="1",this.productSku="123456",this.baseUrl="https://xactsize-dotnet-api-923169850574.southamerica-east1.run.app",this.apiUrl=this.baseUrl+"/api/measurer/measure/body",this.vtonUrl=this.baseUrl+"/api/VirtualTryOn/generate",this.garmentUrl="",this.vton=!1,this.brandName=void 0,this.buttonText="",this._culture="pt-BR",this.measurerKey="",this._isLocaleLoading=!1,this.showModal=!1,this.step=1,this.height=0,this.recommendedSize="",this.measurements={},this.errorMessage="",this.instructionMessage=n("Position yourself in front of the camera"),this.shouldStartMeasurement=!1,this.isLoading=!1,this.isFetching=!1,this.generatedImageUrl="",this.isVtonFetching=!1,this.vtonError=!1,this.videoElement=null,this.stream=null,this.poolingTimeout=null,this.instructionMessageTimeout=null,this.aiSession=null,this.cameras=[],this.currentCameraId=null,this.snowflakesCache=null}firstUpdated(){this.startSpinnerAnimation()}startSpinnerAnimation(){const e=[Yt,qt,We];this.spinnerInterval=setInterval(()=>{var i;const t=(i=this.shadowRoot)==null?void 0:i.querySelector(".spinner");t&&(t.src=e[this.spinnerFrame],this.spinnerFrame=(this.spinnerFrame+1)%e.length)},300)}get culture(){return this._culture}set culture(e){const t=this._culture;this._culture=e,this.requestUpdate("culture",t),this._applyLocale(e).catch(console.error)}async _applyLocale(e){try{this._isLocaleLoading=!0,this.requestUpdate(),await we(e)}catch(t){console.error("Failed to load locale",e,t),await we(Ye)}finally{this._isLocaleLoading=!1,this.requestUpdate()}}get errorMap(){return{ERR_RIGHT_ARM_TOO_HIGH:n("Lower your right arm",{id:"ERR_RIGHT_ARM_TOO_HIGH"}),ERR_LEFT_ARM_TOO_HIGH:n("Lower your left arm",{id:"ERR_LEFT_ARM_TOO_HIGH"}),ERR_ARMS_NOT_RAISED:n("Raise both arms to a 45-degree angle",{id:"ERR_ARMS_NOT_RAISED"}),ERR_RIGHT_ARM_NOT_RAISED:n("Raise your right arm to a 45-degree angle",{id:"ERR_RIGHT_ARM_NOT_RAISED"}),ERR_LEFT_ARM_NOT_RAISED:n("Raise your left arm to a 45-degree angle",{id:"ERR_LEFT_ARM_NOT_RAISED"}),ERR_BODY_LANDMARKS_NOT_DETECTED:n("Ensure your full body is visible in the camera",{id:"ERR_BODY_LANDMARKS_NOT_DETECTED"}),ERR_HIPS_NOT_VISIBLE:n("Adjust your position to show your hips",{id:"ERR_HIPS_NOT_VISIBLE"}),ERR_TOO_CLOSE_TO_CAMERA:n("Step back from the camera",{id:"ERR_TOO_CLOSE_TO_CAMERA"}),ERR_NOT_SIDE_VIEW:n("Turn to show your side profile",{id:"ERR_NOT_SIDE_VIEW"}),ERR_INVALID_CLOTHING_TYPE:n("This clothing type is not supported; please contact support",{id:"ERR_INVALID_CLOTHING_TYPE"}),ERR_UPPER_BODY_NOT_VISIBLE:n("Adjust your position to show your upper body",{id:"ERR_UPPER_BODY_NOT_VISIBLE"}),ERR_HEAD_TOO_CLOSE_TO_EDGE:n("Move your head away from the edge of the frame",{id:"ERR_HEAD_TOO_CLOSE_TO_EDGE"}),ERR_LOWER_BODY_NOT_VISIBLE:n("Adjust your position to show your lower body",{id:"ERR_LOWER_BODY_NOT_VISIBLE"}),ERR_FEET_TOO_CLOSE_TO_EDGE:n("Move your feet away from the edge of the frame",{id:"ERR_FEET_TOO_CLOSE_TO_EDGE"}),ERR_BODY_TOO_CLOSE_TO_EDGE:n("Move your body away from the edge of the frame",{id:"ERR_BODY_TOO_CLOSE_TO_EDGE"}),ERR_BODY_TOO_CLOSE_TO_EDGE_MOVE_LEFT:n("Move to the left to center your body",{id:"ERR_BODY_TOO_CLOSE_TO_EDGE_MOVE_LEFT"}),ERR_BODY_TOO_CLOSE_TO_EDGE_MOVE_RIGHT:n("Move to the right to center your body",{id:"ERR_BODY_TOO_CLOSE_TO_EDGE_MOVE_RIGHT"}),ERR_SHOULDERS_NOT_VISIBLE:n("Adjust your position to show your shoulders",{id:"ERR_SHOULDERS_NOT_VISIBLE"}),ERR_HEIGHT_MEASUREMENT_FAILED:n("Stand straight and ensure your full body is visible",{id:"ERR_HEIGHT_MEASUREMENT_FAILED"}),ERR_HEAD_POINT_NOT_DETECTED:n("Ensure your head is fully visible in the frame",{id:"ERR_HEAD_POINT_NOT_DETECTED"}),ERR_INCORRECT_POSTURE:n("Stand straight with your shoulders back",{id:"ERR_INCORRECT_POSTURE"}),ERR_HEM_MEASUREMENT_FAILED:n("Ensure your clothing hem is visible and clear",{id:"ERR_HEM_MEASUREMENT_FAILED"}),ERR_SHOULDER_MEASUREMENT_FAILED:n("Keep your shoulders relaxed and visible",{id:"ERR_SHOULDER_MEASUREMENT_FAILED"}),ERR_ARM_NOT_STRETCHED:n("Stretch your arms fully",{id:"ERR_ARM_NOT_STRETCHED"}),ERR_LEGS_NOT_DETECTED:n("Ensure your legs are fully visible in the frame",{id:"ERR_LEGS_NOT_DETECTED"}),ERR_HIPS_MEASUREMENT_FAILED:n("Stand straight and ensure your hips are visible",{id:"ERR_HIPS_MEASUREMENT_FAILED"}),ERR_WAIST_MEASUREMENT_FAILED:n("Stand straight and ensure your waist is visible",{id:"ERR_WAIST_MEASUREMENT_FAILED"}),ERR_INVALID_MEASURE_SIDE_VIEW:n("Turn to show a clear side profile",{id:"ERR_INVALID_MEASURE_SIDE_VIEW"}),ERR_INVALID_BODY_HEIGHT_TYPE:n("Ensure your full body is visible for height measurement",{id:"ERR_INVALID_BODY_HEIGHT_TYPE"}),ERR_IMAGE_LOAD_FAILED:n("Try again later; the image could not be processed",{id:"ERR_IMAGE_LOAD_FAILED"}),ERR_HEIGHT_INVALID:n("Height must be between 50 and 300 cm",{id:"ERR_HEIGHT_INVALID"})}}getTranslatedMessage(e){const t=this.errorMap[e];return t||(console.info("Error code is missing",e),n("An unexpected error occurred"))}connectedCallback(){super.connectedCallback(),console.log("New code loaded Jan 27 11:57am"),document.addEventListener("keydown",this.handleEscKey.bind(this)),this.snowflakesCache=this.generateSnowflakes()}disconnectedCallback(){var e;super.disconnectedCallback(),document.removeEventListener("keydown",this.handleEscKey.bind(this)),this.stopPolling(),clearInterval(this.spinnerInterval),(e=this.aiSession)==null||e.disconnect()}handleEscKey(e){e.key==="Escape"&&this.showModal&&this.closeModal()}openModal(){this.showModal=!0,this.step=1,this.height=0,this.instructionMessage=n("Position yourself in front of the camera")}closeModal(){var e;this.showModal=!1,this.onMeasurementCanceled&&typeof this.onMeasurementCanceled=="function"&&this.onMeasurementCanceled(),this.stopPolling(),(e=this.aiSession)==null||e.disconnect(),this.dispatchEvent(new CustomEvent("measurementCanceled",{detail:{}}))}handleDialogClose(){this.showModal&&this.closeModal()}async step2advancement(){if(this.height<50||this.height>300){this.errorMessage=this.getTranslatedMessage("ERR_HEIGHT_INVALID");return}this.step=3,this.errorMessage=""}async startMeasurement(){this.step=3,this.errorMessage="",this.shouldStartMeasurement=!0}updated(e){var t;if(super.updated(e),e.has("step")&&this.step===3&&this.shouldStartMeasurement&&(this.initializeMeasurement(),this.shouldStartMeasurement=!1),e.has("showModal")){const i=(t=this.shadowRoot)==null?void 0:t.getElementById("measurer-dialog");i&&(this.showModal&&!i.open?i.showModal():!this.showModal&&i.open&&i.close())}}async initializeMeasurement(){if(!this.apiKey)throw new Error("API key is required");if(!this.tenantId)throw new Error("Tenant ID is required");if(!this.productSku)throw new Error("Product SKU is required");if(!this.baseUrl)throw new Error("Base URL is required");if(!this.apiUrl)throw new Error("API URL is required");if(!this.vtonUrl)throw new Error("VTON URL is required");this.videoElement=this.shadowRoot.querySelector("video");try{this.stream=await navigator.mediaDevices.getUserMedia({video:!0}),this.videoElement&&(this.videoElement.srcObject=this.stream,await this.videoElement.play(),await this.loadCameras(),this.aiSession=new xe(this.baseUrl,this.apiKey,this.culture),await this.aiSession.connect(),this.aiSession.startMicrophone(),this.startPolling())}catch{this.errorMessage=n("Error accessing webcam")}}async loadCameras(){try{const e=await navigator.mediaDevices.enumerateDevices();this.cameras=e.filter(t=>t.kind==="videoinput"),this.cameras.length>0&&(this.currentCameraId=this.cameras[0].deviceId)}catch(e){console.error("Error enumerating devices:",e)}}async flipCamera(){if(this.cameras.length<2)return;this.isLoading=!0,this.stopPolling();const t=(this.cameras.findIndex(i=>i.deviceId===this.currentCameraId)+1)%this.cameras.length;this.currentCameraId=this.cameras[t].deviceId;try{this.stream&&this.stream.getTracks().forEach(i=>i.stop()),this.stream=await navigator.mediaDevices.getUserMedia({video:{deviceId:{exact:this.currentCameraId}}}),this.videoElement&&(this.videoElement.srcObject=this.stream,await this.videoElement.play(),this.startPolling())}catch{this.errorMessage=n("Error switching camera")}finally{this.isLoading=!1}}async startPolling(){const t=[],i=async()=>{var f;if(!this.videoElement||!this.stream||this.isFetching)return;const s=document.createElement("canvas");s.width=this.videoElement.videoWidth,s.height=this.videoElement.videoHeight;const o=s.getContext("2d");o==null||o.drawImage(this.videoElement,0,0,s.width,s.height);const r=await new Promise(m=>s.toBlob(h=>m(h),"image/jpeg")),d=new File([r],"frame.jpg",{type:"image/jpeg"}),l=new FormData;l.append("image",d),l.append("height",this.height.toString()),l.append("productSku",this.productSku),this.measurerKey&&l.append("measurerKey",this.measurerKey);try{this.isFetching=!0,this.isLoading=!0,this.poolingTimeout&&clearTimeout(this.poolingTimeout),this.instructionMessageTimeout&&clearTimeout(this.instructionMessageTimeout);const h=await(await fetch(this.apiUrl,{method:"POST",body:l,headers:{Accept:"application/json","Cache-Control":"no-store",Pragma:"no-cache","X-Api-Key":this.apiKey}})).json();if(this.isFetching=!1,this.isLoading=!1,h.success&&h.chosenSize){this.generateVtonImage(d),t.push(h);const b=t.length;this.instructionMessage=n(ge`Scanning... ${b}/${3}`),b>=3?(this.processFinalResults(t),this.stopPolling(),this.step=4):this.poolingTimeout=setTimeout(i,500)}else this.instructionMessage=this.getTranslatedMessage(h.message||"UNKNOWN_ERROR"),h.message&&((f=this.aiSession)==null||f.forwardCvError(this.instructionMessage)),this.instructionMessageTimeout=setTimeout(()=>{t.length<3&&(this.poolingTimeout=setTimeout(i,0))},2e3)}catch{this.isFetching=!1,this.isLoading=!1,this.instructionMessage=n("Error processing measurement"),this.instructionMessageTimeout=setTimeout(()=>{this.poolingTimeout=setTimeout(i,0)},2e3)}};i()}async generateVtonImage(e){if(!this.vton||!this.garmentUrl||this.isVtonFetching||this.generatedImageUrl)return;this.isVtonFetching=!0,this.vtonError=!1;const t=new FormData;t.append("PersonImage",e),t.append("GarmentUrl",this.garmentUrl);try{const s=await(await fetch(this.vtonUrl,{method:"POST",body:t,headers:{Accept:"application/json","X-Api-Key":this.apiKey}})).json();s.result_urls&&s.result_urls.length>0?(this.generatedImageUrl=s.result_urls[0],this.isVtonFetching=!1):(this.vtonError=!0,this.isVtonFetching=!1)}catch(i){console.error("Error generating VTON image",i),this.vtonError=!0,this.isVtonFetching=!1}}processFinalResults(e){console.group("Scan Debug Report"),console.log(`✅ Collected ${e.length} successful scans.`),e.forEach((d,l)=>{console.log(`Scan #${l+1}: Size [${d.chosenSize}] | Chest: ${d.measurements.chest} | Waist: ${d.measurements.waist}`)});const t={};Object.keys(e[0].measurements||{}).forEach(d=>{let l=0,f=0;e.forEach(m=>{const h=m.measurements[d];typeof h=="number"&&(l+=h,f++)}),t[d]=f>0?Math.round(l/f*100)/100:0}),console.log("📏 Final Averaged Measurements:",t);const s={};e.forEach(d=>{const l=d.chosenSize;l&&(s[l]=(s[l]||0)+1)}),console.log("🗳️ Voting Results:",s);let o="",r=0;for(const[d,l]of Object.entries(s))l>r&&(r=l,o=d);if(console.log(`🏆 WINNER: ${o}`),console.groupEnd(),this.measurements=t,this.recommendedSize=o,this.instructionMessage=n("Measurement successful!"),this.aiSession){this.aiSession.onTurnComplete=()=>{this.aiSession=null};let d="";this.vton&&(this.isVtonFetching?d="An image of the user wearing the garment is currently being generated. TELL USER THEIR IMAGE IS GENERATING.":this.generatedImageUrl&&(d="The image has successfully generated. TELL USER: 'Here is your image in the garment'.")),this.aiSession.notifySuccess(o,d)}}stopPolling(){this.poolingTimeout!==null&&(clearTimeout(this.poolingTimeout),this.poolingTimeout=null),this.instructionMessageTimeout!==null&&(clearTimeout(this.instructionMessageTimeout),this.instructionMessageTimeout=null),this.stream&&(this.stream.getTracks().forEach(e=>e.stop()),this.stream=null)}acceptMeasurement(){var e;this.dispatchEvent(new CustomEvent("measurementAccepted",{detail:{size:this.recommendedSize}})),this.onMeasurementAccepted&&typeof this.onMeasurementAccepted=="function"&&this.onMeasurementAccepted(),this.showModal=!1,this.stopPolling(),(e=this.aiSession)==null||e.disconnect(),this.aiSession=null}resetMeasurement(){var e;this.step=1,this.height=0,this.recommendedSize="",this.measurements={},this.generatedImageUrl="",this.isVtonFetching=!1,this.vtonError=!1,this.stopPolling(),(e=this.aiSession)==null||e.disconnect(),this.aiSession=null}stopMeasurement(){this.resetMeasurement(),this.showModal=!1}generateSnowflakes(){const e=[];for(let i=0;i<80;i++){const s=Math.random()*100,o=8+Math.random()*17,r=-Math.random()*30;e.push(g`<span
|
|
1005
1005
|
class="snowflake"
|
|
1006
1006
|
style="left:${s}%; animation-duration:${o.toFixed(2)}s; animation-delay:${r.toFixed(2)}s;"
|
|
1007
1007
|
></span>`)}return g`${e}`}renderSnowflakes(){return this.snowflakesCache||g``}render(){return this._isLocaleLoading?g`<div hidden></div>`:g`
|
|
@@ -1013,7 +1013,7 @@
|
|
|
1013
1013
|
></xact-button>
|
|
1014
1014
|
|
|
1015
1015
|
${this.showModal?g`
|
|
1016
|
-
<
|
|
1016
|
+
<dialog class="modal" id="measurer-dialog" @close=${this.handleDialogClose}>
|
|
1017
1017
|
<div class="modal-content">
|
|
1018
1018
|
<div
|
|
1019
1019
|
style="display: flex; justify-content: space-between"
|
|
@@ -1113,7 +1113,7 @@
|
|
|
1113
1113
|
`:""}
|
|
1114
1114
|
<xact-footer></xact-footer>
|
|
1115
1115
|
</div>
|
|
1116
|
-
</
|
|
1116
|
+
</dialog>
|
|
1117
1117
|
`:""}
|
|
1118
1118
|
`}},c.BodyMeasurer.styles=k`
|
|
1119
1119
|
:host {
|
|
@@ -1152,18 +1152,27 @@
|
|
|
1152
1152
|
}
|
|
1153
1153
|
|
|
1154
1154
|
/* Modal Styles */
|
|
1155
|
-
.modal {
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1155
|
+
dialog.modal {
|
|
1156
|
+
border: none;
|
|
1157
|
+
background: transparent;
|
|
1158
|
+
padding: 0;
|
|
1159
|
+
margin: 0;
|
|
1160
|
+
width: 100vw;
|
|
1161
|
+
height: 100vh;
|
|
1162
|
+
max-width: 100vw;
|
|
1163
|
+
max-height: 100vh;
|
|
1164
|
+
overflow: hidden;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
dialog.modal[open] {
|
|
1162
1168
|
display: flex;
|
|
1163
1169
|
flex-direction: column;
|
|
1164
1170
|
justify-content: center;
|
|
1165
1171
|
align-items: center;
|
|
1166
|
-
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
dialog.modal::backdrop {
|
|
1175
|
+
background: rgba(0, 0, 0, 0.5);
|
|
1167
1176
|
}
|
|
1168
1177
|
|
|
1169
1178
|
.modal-content {
|
package/package.json
CHANGED