@primestyleai/tryon 5.10.135 → 5.10.137
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/react/index.js +3002 -2925
- package/dist/react/index.js.map +1 -1
- package/dist/react/styles.d.ts +1 -1
- package/dist/react/views/MobileScanningView.d.ts +4 -2
- package/dist/react/views/MultiSectionMobile.d.ts +4 -1
- package/dist/storefront/primestyle-tryon.js +249 -169
- package/package.json +1 -1
|
@@ -19,8 +19,10 @@ interface MobileScanningViewProps {
|
|
|
19
19
|
productDescription?: string;
|
|
20
20
|
/** Optional cancel handler shown as a text link under the cards. */
|
|
21
21
|
onCancelTryOn?: () => void;
|
|
22
|
-
|
|
22
|
+
/** No longer rendered (tabs removed mid-scan), kept for backwards-compat
|
|
23
|
+
* with the photo-step caller that passes it down. */
|
|
24
|
+
onSwitchToManual?: () => void;
|
|
23
25
|
t: TranslateFn;
|
|
24
26
|
}
|
|
25
|
-
export declare function MobileScanningView({ previewUrl, productImage, bodyLandmarks, sizingDone, tryOnProcessing, productMaterial, productDescription, onCancelTryOn,
|
|
27
|
+
export declare function MobileScanningView({ previewUrl, productImage, bodyLandmarks, sizingDone, tryOnProcessing, productMaterial, productDescription, onCancelTryOn, t, }: MobileScanningViewProps): import("react/jsx-runtime").JSX.Element;
|
|
26
28
|
export {};
|
|
@@ -24,6 +24,9 @@ export interface MultiSectionMobileProps {
|
|
|
24
24
|
onSelectSection: (name: string) => void;
|
|
25
25
|
onTryOn: () => void;
|
|
26
26
|
tryOnProcessing?: boolean;
|
|
27
|
+
/** Epoch ms timestamp the try-on request started — drives the
|
|
28
|
+
* TryOnGenerationBadge's progress + ETA copy. */
|
|
29
|
+
tryOnStartedAt?: number | null;
|
|
27
30
|
/** When set, the image area shows the try-on result instead of productImage. */
|
|
28
31
|
resultImageUrl?: string | null;
|
|
29
32
|
/** Try-on has finished and result is ready. Switches the bottom CTA into
|
|
@@ -44,4 +47,4 @@ export interface MultiSectionMobileProps {
|
|
|
44
47
|
onImageLoad?: (e: React.SyntheticEvent<HTMLImageElement>) => void;
|
|
45
48
|
t: TranslateFn;
|
|
46
49
|
}
|
|
47
|
-
export declare function MultiSectionMobile({ productImage, productTitle, sizingResult, sizeGuide, sectionEntries, pendingCustomSizes, onSelectSection, onTryOn, tryOnProcessing, resultImageUrl, tryOnDone, onTryAgain, onClose, overlayNode, showLines, onToggleLines, onImageLoad, t, }: MultiSectionMobileProps): import("react/jsx-runtime").JSX.Element;
|
|
50
|
+
export declare function MultiSectionMobile({ productImage, productTitle, sizingResult, sizeGuide, sectionEntries, pendingCustomSizes, onSelectSection, onTryOn, tryOnProcessing, tryOnStartedAt, resultImageUrl, tryOnDone, onTryAgain, onClose, overlayNode, showLines, onToggleLines, onImageLoad, t, }: MultiSectionMobileProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -11563,6 +11563,22 @@ const STYLES$1 = `
|
|
|
11563
11563
|
@keyframes ps-tryon-badge-spin {
|
|
11564
11564
|
to { transform: rotate(360deg); }
|
|
11565
11565
|
}
|
|
11566
|
+
/* Mobile sizing for the try-on badge — desktop's max-width: 420px lives
|
|
11567
|
+
inside a roughly 360 px image hero, leaving the pill awkwardly clipped.
|
|
11568
|
+
Stretch it edge-to-edge with smaller text so it always fits. */
|
|
11569
|
+
@media (max-width: 768px) {
|
|
11570
|
+
.ps-tryon-badge {
|
|
11571
|
+
left: 12px; right: 12px; bottom: 12px;
|
|
11572
|
+
max-width: none;
|
|
11573
|
+
padding: 12px 14px;
|
|
11574
|
+
gap: 8px;
|
|
11575
|
+
border-radius: 12px;
|
|
11576
|
+
}
|
|
11577
|
+
.ps-tryon-badge-row { gap: 10px; }
|
|
11578
|
+
.ps-tryon-badge-title { font-size: 13px; }
|
|
11579
|
+
.ps-tryon-badge-pct { font-size: 11px; padding: 3px 9px; }
|
|
11580
|
+
.ps-tryon-badge-foot { font-size: 11px; gap: 8px; }
|
|
11581
|
+
}
|
|
11566
11582
|
|
|
11567
11583
|
/* ── Product photo strip (single-garment, below the size card) ──
|
|
11568
11584
|
Three thumbnails per slide, evenly spaced, auto-advances. Lives at
|
|
@@ -15316,9 +15332,12 @@ const STYLES$1 = `
|
|
|
15316
15332
|
text-align: center; padding: 4px 12px;
|
|
15317
15333
|
min-height: 64px;
|
|
15318
15334
|
/* Lock width so the cycling stage text (shorter/longer strings every
|
|
15319
|
-
~2s) doesn't reflow the sibling TryOnProgress bar.
|
|
15335
|
+
~2s) doesn't reflow the sibling TryOnProgress bar. align-self:
|
|
15336
|
+
center centers the 320px container inside the flex column — without
|
|
15337
|
+
it the container sat at the left edge of the screen on mobile. */
|
|
15320
15338
|
width: 320px;
|
|
15321
15339
|
max-width: 100%;
|
|
15340
|
+
align-self: center;
|
|
15322
15341
|
overflow: hidden;
|
|
15323
15342
|
}
|
|
15324
15343
|
.ps-msc-stage-slot {
|
|
@@ -15403,11 +15422,23 @@ const STYLES$1 = `
|
|
|
15403
15422
|
.ps-msr-fit-toggle[aria-pressed="true"] {
|
|
15404
15423
|
background: var(--ps-accent); color: #FFFFFF;
|
|
15405
15424
|
}
|
|
15406
|
-
/* Bottom action row when try-on finished — Try Again + Continue Shopping
|
|
15425
|
+
/* Bottom action row when try-on finished — Try Again + Continue Shopping.
|
|
15426
|
+
min-width: 0 lets each button actually shrink to share the row equally
|
|
15427
|
+
on narrow viewports; white-space: nowrap stops "Continue Shopping"
|
|
15428
|
+
from wrapping to a second line. */
|
|
15407
15429
|
.ps-msr-bottom-row {
|
|
15408
|
-
display: flex; gap:
|
|
15430
|
+
display: flex; gap: 8px; align-items: stretch;
|
|
15431
|
+
}
|
|
15432
|
+
.ps-msr-bottom-row .ps-msr-tryon-cta {
|
|
15433
|
+
flex: 1 1 0; min-width: 0;
|
|
15434
|
+
padding: 14px 12px; font-size: 13px;
|
|
15435
|
+
white-space: nowrap;
|
|
15436
|
+
}
|
|
15437
|
+
@media (max-width: 360px) {
|
|
15438
|
+
.ps-msr-bottom-row .ps-msr-tryon-cta {
|
|
15439
|
+
padding: 12px 10px; font-size: 12px;
|
|
15440
|
+
}
|
|
15409
15441
|
}
|
|
15410
|
-
.ps-msr-bottom-row .ps-msr-tryon-cta { flex: 1; }
|
|
15411
15442
|
.ps-msr-tryon-cta.ps-secondary {
|
|
15412
15443
|
background: transparent;
|
|
15413
15444
|
color: var(--ps-text-primary);
|
|
@@ -17477,6 +17508,11 @@ const STYLES$1 = `
|
|
|
17477
17508
|
|
|
17478
17509
|
/* Big product / try-on image */
|
|
17479
17510
|
.ps-msd-image {
|
|
17511
|
+
/* position: relative is required so the absolute children
|
|
17512
|
+
(.ps-msr-fit-toggle, .ps-tryon-badge) anchor to the image instead of
|
|
17513
|
+
the viewport. Without it the Show Fit pill rendered bottom-left of
|
|
17514
|
+
the screen on mobile. */
|
|
17515
|
+
position: relative;
|
|
17480
17516
|
width: 100%; height: 420px;
|
|
17481
17517
|
border-radius: 12px; overflow: hidden;
|
|
17482
17518
|
background: var(--ps-bg-secondary);
|
|
@@ -17517,6 +17553,18 @@ const STYLES$1 = `
|
|
|
17517
17553
|
letter-spacing: 0.05em;
|
|
17518
17554
|
color: var(--ps-text-muted);
|
|
17519
17555
|
}
|
|
17556
|
+
/* Mobile: long labels like "MISSY 12 / Standard" wrap to a second line
|
|
17557
|
+
at 36 px in a ~280 px card. Drop further to 28 px and let the size
|
|
17558
|
+
pill take the full card width so wrapping doesn't strand the meta
|
|
17559
|
+
value awkwardly to the side. */
|
|
17560
|
+
@media (max-width: 768px) {
|
|
17561
|
+
.ps-msd-card-size {
|
|
17562
|
+
font-size: 28px;
|
|
17563
|
+
letter-spacing: -0.015em;
|
|
17564
|
+
line-height: 1.1;
|
|
17565
|
+
}
|
|
17566
|
+
.ps-msd-card-size-meta { font-size: 11px; }
|
|
17567
|
+
}
|
|
17520
17568
|
.ps-msd-card-divider {
|
|
17521
17569
|
height: 1px; background: var(--ps-border-subtle);
|
|
17522
17570
|
margin: 6px 0;
|
|
@@ -17885,6 +17933,34 @@ const STYLES$1 = `
|
|
|
17885
17933
|
color: var(--ps-accent);
|
|
17886
17934
|
}
|
|
17887
17935
|
|
|
17936
|
+
/* Mobile px-based override — desktop rules use vw units which collapse
|
|
17937
|
+
to 1–4 px on a 375 px viewport. */
|
|
17938
|
+
@media (max-width: 768px) {
|
|
17939
|
+
.ps-bp-mini-select-trigger {
|
|
17940
|
+
padding: 10px 14px;
|
|
17941
|
+
font-size: 14px;
|
|
17942
|
+
border-radius: 8px;
|
|
17943
|
+
gap: 8px;
|
|
17944
|
+
min-width: 0;
|
|
17945
|
+
}
|
|
17946
|
+
.ps-bp-mini-select-arrow { font-size: 10px; }
|
|
17947
|
+
.ps-bp-mini-select-panel {
|
|
17948
|
+
max-height: 240px;
|
|
17949
|
+
border-radius: 10px;
|
|
17950
|
+
padding: 4px;
|
|
17951
|
+
box-shadow:
|
|
17952
|
+
0 4px 12px rgba(15, 23, 42, 0.10),
|
|
17953
|
+
0 12px 32px rgba(15, 23, 42, 0.16);
|
|
17954
|
+
}
|
|
17955
|
+
.ps-bp-mini-select[data-dir="down"] .ps-bp-mini-select-panel { top: calc(100% + 6px); }
|
|
17956
|
+
.ps-bp-mini-select[data-dir="up"] .ps-bp-mini-select-panel { bottom: calc(100% + 6px); }
|
|
17957
|
+
.ps-bp-mini-select-item {
|
|
17958
|
+
padding: 10px 12px;
|
|
17959
|
+
font-size: 14px;
|
|
17960
|
+
border-radius: 6px;
|
|
17961
|
+
}
|
|
17962
|
+
}
|
|
17963
|
+
|
|
17888
17964
|
.ps-bp-bra-region-wrap { position: relative; z-index: 100; }
|
|
17889
17965
|
.ps-bp-bra-region-trigger {
|
|
17890
17966
|
display: flex; align-items: center; gap: 0.35vw;
|
|
@@ -18998,47 +19074,11 @@ function useIsMobile() {
|
|
|
18998
19074
|
}, []);
|
|
18999
19075
|
return isMobile;
|
|
19000
19076
|
}
|
|
19001
|
-
function RulerIcon() {
|
|
19002
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "13", height: "13", children: [
|
|
19003
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M3 17l6 6 12-12-6-6z" }),
|
|
19004
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9 11l2 2M11 9l2 2M13 7l2 2M7 13l2 2" })
|
|
19005
|
-
] });
|
|
19006
|
-
}
|
|
19007
|
-
function ScanIcon() {
|
|
19008
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "13", height: "13", children: [
|
|
19009
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M3 7V5a2 2 0 0 1 2-2h2M17 3h2a2 2 0 0 1 2 2v2M21 17v2a2 2 0 0 1-2 2h-2M7 21H5a2 2 0 0 1-2-2v-2" }),
|
|
19010
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "3" })
|
|
19011
|
-
] });
|
|
19012
|
-
}
|
|
19013
|
-
function MobileBottomTabs({ mode, onSwitchToManual, onSwitchToScan, t: t2 }) {
|
|
19014
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bpm-bottom-tabs", children: [
|
|
19015
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
19016
|
-
"button",
|
|
19017
|
-
{
|
|
19018
|
-
type: "button",
|
|
19019
|
-
className: `ps-bpm-bottom-tab${mode === "manual" ? " ps-active" : ""}`,
|
|
19020
|
-
onClick: onSwitchToManual,
|
|
19021
|
-
children: [
|
|
19022
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(RulerIcon, {}),
|
|
19023
|
-
t2("MANUAL FIT")
|
|
19024
|
-
]
|
|
19025
|
-
}
|
|
19026
|
-
),
|
|
19027
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
19028
|
-
"button",
|
|
19029
|
-
{
|
|
19030
|
-
type: "button",
|
|
19031
|
-
className: `ps-bpm-bottom-tab${mode === "scan" ? " ps-active" : ""}`,
|
|
19032
|
-
onClick: onSwitchToScan,
|
|
19033
|
-
children: [
|
|
19034
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(ScanIcon, {}),
|
|
19035
|
-
t2("AI SCAN")
|
|
19036
|
-
]
|
|
19037
|
-
}
|
|
19038
|
-
)
|
|
19039
|
-
] });
|
|
19040
|
-
}
|
|
19041
19077
|
const SKELETON_CONNECTIONS$1 = [
|
|
19078
|
+
// Head → torso. Bridges the gap between the nose dot and the shoulder
|
|
19079
|
+
// line — without these the head reads as floating above the body.
|
|
19080
|
+
["nose", "leftShoulder"],
|
|
19081
|
+
["nose", "rightShoulder"],
|
|
19042
19082
|
["leftShoulder", "rightShoulder"],
|
|
19043
19083
|
["leftShoulder", "leftElbow"],
|
|
19044
19084
|
["leftElbow", "leftWrist"],
|
|
@@ -19052,6 +19092,14 @@ const SKELETON_CONNECTIONS$1 = [
|
|
|
19052
19092
|
["rightHip", "rightKnee"],
|
|
19053
19093
|
["rightKnee", "rightAnkle"]
|
|
19054
19094
|
];
|
|
19095
|
+
function isVisible(p2) {
|
|
19096
|
+
if (!p2 || typeof p2 !== "object") return false;
|
|
19097
|
+
const pt2 = p2;
|
|
19098
|
+
if (typeof pt2.x !== "number" || typeof pt2.y !== "number") return false;
|
|
19099
|
+
if (typeof pt2.visibility === "number" && pt2.visibility < 0.3) return false;
|
|
19100
|
+
if (pt2.x < 1e-3 && pt2.y < 1e-3) return false;
|
|
19101
|
+
return true;
|
|
19102
|
+
}
|
|
19055
19103
|
function MobileSkeleton({ landmarks, w: w2, h }) {
|
|
19056
19104
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
19057
19105
|
"svg",
|
|
@@ -19063,7 +19111,7 @@ function MobileSkeleton({ landmarks, w: w2, h }) {
|
|
|
19063
19111
|
SKELETON_CONNECTIONS$1.map(([a, b], i) => {
|
|
19064
19112
|
const pa2 = landmarks[a];
|
|
19065
19113
|
const pb2 = landmarks[b];
|
|
19066
|
-
if (!pa2 || !pb2) return null;
|
|
19114
|
+
if (!isVisible(pa2) || !isVisible(pb2)) return null;
|
|
19067
19115
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
19068
19116
|
"line",
|
|
19069
19117
|
{
|
|
@@ -19073,14 +19121,12 @@ function MobileSkeleton({ landmarks, w: w2, h }) {
|
|
|
19073
19121
|
y2: pb2.y * h,
|
|
19074
19122
|
stroke: "rgba(100,210,255,0.9)",
|
|
19075
19123
|
strokeWidth: "4",
|
|
19076
|
-
strokeLinecap: "round"
|
|
19077
|
-
opacity: 0,
|
|
19078
|
-
style: { animation: `ps-msc-fade 0.4s ease ${i * 0.05}s forwards` }
|
|
19124
|
+
strokeLinecap: "round"
|
|
19079
19125
|
},
|
|
19080
19126
|
`l-${i}`
|
|
19081
19127
|
);
|
|
19082
19128
|
}),
|
|
19083
|
-
Object.entries(landmarks).filter(([, v2]) => v2
|
|
19129
|
+
Object.entries(landmarks).filter(([, v2]) => isVisible(v2)).map(([key, v2]) => {
|
|
19084
19130
|
const p2 = v2;
|
|
19085
19131
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("g", { children: [
|
|
19086
19132
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -19088,10 +19134,8 @@ function MobileSkeleton({ landmarks, w: w2, h }) {
|
|
|
19088
19134
|
{
|
|
19089
19135
|
cx: p2.x * w2,
|
|
19090
19136
|
cy: p2.y * h,
|
|
19091
|
-
r:
|
|
19092
|
-
fill: "rgba(100,210,255,0.
|
|
19093
|
-
opacity: 0,
|
|
19094
|
-
style: { animation: `ps-msc-fade 0.3s ease ${i * 0.04}s forwards` }
|
|
19137
|
+
r: 14,
|
|
19138
|
+
fill: "rgba(100,210,255,0.30)"
|
|
19095
19139
|
}
|
|
19096
19140
|
),
|
|
19097
19141
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -19099,10 +19143,8 @@ function MobileSkeleton({ landmarks, w: w2, h }) {
|
|
|
19099
19143
|
{
|
|
19100
19144
|
cx: p2.x * w2,
|
|
19101
19145
|
cy: p2.y * h,
|
|
19102
|
-
r:
|
|
19103
|
-
fill: "rgba(100,210,255,0.95)"
|
|
19104
|
-
opacity: 0,
|
|
19105
|
-
style: { animation: `ps-msc-fade 0.3s ease ${i * 0.04}s forwards` }
|
|
19146
|
+
r: 9,
|
|
19147
|
+
fill: "rgba(100,210,255,0.95)"
|
|
19106
19148
|
}
|
|
19107
19149
|
)
|
|
19108
19150
|
] }, key);
|
|
@@ -19120,7 +19162,8 @@ function MobileScanningView({
|
|
|
19120
19162
|
productMaterial,
|
|
19121
19163
|
productDescription,
|
|
19122
19164
|
onCancelTryOn,
|
|
19123
|
-
onSwitchToManual
|
|
19165
|
+
// onSwitchToManual is intentionally not destructured — bottom tabs are
|
|
19166
|
+
// hidden during analysis and the prop is kept on the type for callers.
|
|
19124
19167
|
t: t2
|
|
19125
19168
|
}) {
|
|
19126
19169
|
const displayImage = previewUrl || productImage || "";
|
|
@@ -19179,17 +19222,100 @@ function MobileScanningView({
|
|
|
19179
19222
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-title", children: current.title }),
|
|
19180
19223
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-desc", children: current.desc })
|
|
19181
19224
|
] }, stageIdx) }),
|
|
19182
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bpm-spacer" })
|
|
19183
|
-
|
|
19184
|
-
|
|
19185
|
-
|
|
19186
|
-
|
|
19187
|
-
|
|
19188
|
-
|
|
19189
|
-
|
|
19190
|
-
|
|
19191
|
-
|
|
19192
|
-
)
|
|
19225
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bpm-spacer" })
|
|
19226
|
+
] });
|
|
19227
|
+
}
|
|
19228
|
+
const TARGET_SECONDS = 22;
|
|
19229
|
+
function TryOnGenerationBadge({
|
|
19230
|
+
tryOnStartedAt,
|
|
19231
|
+
t: t2
|
|
19232
|
+
}) {
|
|
19233
|
+
const [, force] = reactExports.useState(0);
|
|
19234
|
+
reactExports.useEffect(() => {
|
|
19235
|
+
if (tryOnStartedAt == null) return;
|
|
19236
|
+
const id2 = setInterval(() => force((v2) => v2 + 1), 200);
|
|
19237
|
+
return () => clearInterval(id2);
|
|
19238
|
+
}, [tryOnStartedAt]);
|
|
19239
|
+
if (tryOnStartedAt == null) return null;
|
|
19240
|
+
const elapsed = (Date.now() - tryOnStartedAt) / 1e3;
|
|
19241
|
+
const pct = Math.min(95, elapsed / TARGET_SECONDS * 100);
|
|
19242
|
+
const pctRounded = Math.round(pct);
|
|
19243
|
+
const remaining = Math.max(0, TARGET_SECONDS - Math.floor(elapsed));
|
|
19244
|
+
const etaText = elapsed >= TARGET_SECONDS ? t2("almost done") : `~${remaining}s ${t2("left")}`;
|
|
19245
|
+
const statuses = [
|
|
19246
|
+
t2("Preparing your image"),
|
|
19247
|
+
t2("Analyzing body proportions"),
|
|
19248
|
+
t2("Mapping garment to body"),
|
|
19249
|
+
t2("Refining drape and shadows"),
|
|
19250
|
+
t2("Almost done")
|
|
19251
|
+
];
|
|
19252
|
+
const stepIdx = Math.min(
|
|
19253
|
+
statuses.length - 1,
|
|
19254
|
+
Math.floor(elapsed / TARGET_SECONDS * statuses.length)
|
|
19255
|
+
);
|
|
19256
|
+
const status = statuses[stepIdx];
|
|
19257
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-badge", role: "status", "aria-live": "polite", children: [
|
|
19258
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-badge-row", children: [
|
|
19259
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-badge-spinner", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", width: "22", height: "22", children: [
|
|
19260
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("defs", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("linearGradient", { id: "ps-tryon-badge-grad", x1: "0", y1: "0", x2: "1", y2: "1", children: [
|
|
19261
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "0%", stopColor: "#3B82F6" }),
|
|
19262
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "100%", stopColor: "#2563EB" })
|
|
19263
|
+
] }) }),
|
|
19264
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "9", fill: "none", stroke: "rgba(59,130,246,0.18)", strokeWidth: "2.4" }),
|
|
19265
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
19266
|
+
"circle",
|
|
19267
|
+
{
|
|
19268
|
+
cx: "12",
|
|
19269
|
+
cy: "12",
|
|
19270
|
+
r: "9",
|
|
19271
|
+
fill: "none",
|
|
19272
|
+
stroke: "url(#ps-tryon-badge-grad)",
|
|
19273
|
+
strokeWidth: "2.4",
|
|
19274
|
+
strokeLinecap: "round",
|
|
19275
|
+
strokeDasharray: "56.5",
|
|
19276
|
+
strokeDashoffset: "38"
|
|
19277
|
+
}
|
|
19278
|
+
)
|
|
19279
|
+
] }) }),
|
|
19280
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-badge-title", children: t2("Generating your look...") }),
|
|
19281
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-badge-pct", children: [
|
|
19282
|
+
pctRounded,
|
|
19283
|
+
"%"
|
|
19284
|
+
] })
|
|
19285
|
+
] }),
|
|
19286
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-badge-bar", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-badge-bar-fill", style: { width: `${pctRounded}%` } }) }),
|
|
19287
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-badge-foot", children: [
|
|
19288
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-badge-status", children: [
|
|
19289
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-badge-status-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
19290
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6", y1: "10", x2: "6", y2: "14" }),
|
|
19291
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "6", x2: "10", y2: "18" }),
|
|
19292
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "9", x2: "14", y2: "15" }),
|
|
19293
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "18", y1: "11", x2: "18", y2: "13" })
|
|
19294
|
+
] }) }),
|
|
19295
|
+
status
|
|
19296
|
+
] }),
|
|
19297
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-badge-eta", children: [
|
|
19298
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
19299
|
+
"svg",
|
|
19300
|
+
{
|
|
19301
|
+
width: "11",
|
|
19302
|
+
height: "11",
|
|
19303
|
+
viewBox: "0 0 24 24",
|
|
19304
|
+
fill: "none",
|
|
19305
|
+
stroke: "currentColor",
|
|
19306
|
+
strokeWidth: "2",
|
|
19307
|
+
strokeLinecap: "round",
|
|
19308
|
+
strokeLinejoin: "round",
|
|
19309
|
+
"aria-hidden": "true",
|
|
19310
|
+
children: [
|
|
19311
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
19312
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("polyline", { points: "12 6 12 12 16 14" })
|
|
19313
|
+
]
|
|
19314
|
+
}
|
|
19315
|
+
),
|
|
19316
|
+
etaText
|
|
19317
|
+
] })
|
|
19318
|
+
] })
|
|
19193
19319
|
] });
|
|
19194
19320
|
}
|
|
19195
19321
|
function garmentIconForSection$1(name) {
|
|
@@ -19223,6 +19349,7 @@ function MultiSectionMobile({
|
|
|
19223
19349
|
onSelectSection,
|
|
19224
19350
|
onTryOn,
|
|
19225
19351
|
tryOnProcessing,
|
|
19352
|
+
tryOnStartedAt,
|
|
19226
19353
|
resultImageUrl,
|
|
19227
19354
|
tryOnDone,
|
|
19228
19355
|
onTryAgain,
|
|
@@ -19268,6 +19395,7 @@ function MultiSectionMobile({
|
|
|
19268
19395
|
}
|
|
19269
19396
|
),
|
|
19270
19397
|
showLines && overlayNode,
|
|
19398
|
+
tryOnProcessing && tryOnStartedAt != null && /* @__PURE__ */ jsxRuntimeExports.jsx(TryOnGenerationBadge, { tryOnStartedAt, t: t2 }),
|
|
19271
19399
|
showingTryOn && onToggleLines && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
19272
19400
|
"button",
|
|
19273
19401
|
{
|
|
@@ -19388,99 +19516,6 @@ function MultiSectionMobile({
|
|
|
19388
19516
|
sizeGuide ? null : null
|
|
19389
19517
|
] });
|
|
19390
19518
|
}
|
|
19391
|
-
const TARGET_SECONDS = 22;
|
|
19392
|
-
function TryOnGenerationBadge({
|
|
19393
|
-
tryOnStartedAt,
|
|
19394
|
-
t: t2
|
|
19395
|
-
}) {
|
|
19396
|
-
const [, force] = reactExports.useState(0);
|
|
19397
|
-
reactExports.useEffect(() => {
|
|
19398
|
-
if (tryOnStartedAt == null) return;
|
|
19399
|
-
const id2 = setInterval(() => force((v2) => v2 + 1), 200);
|
|
19400
|
-
return () => clearInterval(id2);
|
|
19401
|
-
}, [tryOnStartedAt]);
|
|
19402
|
-
if (tryOnStartedAt == null) return null;
|
|
19403
|
-
const elapsed = (Date.now() - tryOnStartedAt) / 1e3;
|
|
19404
|
-
const pct = Math.min(95, elapsed / TARGET_SECONDS * 100);
|
|
19405
|
-
const pctRounded = Math.round(pct);
|
|
19406
|
-
const remaining = Math.max(0, TARGET_SECONDS - Math.floor(elapsed));
|
|
19407
|
-
const etaText = elapsed >= TARGET_SECONDS ? t2("almost done") : `~${remaining}s ${t2("left")}`;
|
|
19408
|
-
const statuses = [
|
|
19409
|
-
t2("Preparing your image"),
|
|
19410
|
-
t2("Analyzing body proportions"),
|
|
19411
|
-
t2("Mapping garment to body"),
|
|
19412
|
-
t2("Refining drape and shadows"),
|
|
19413
|
-
t2("Almost done")
|
|
19414
|
-
];
|
|
19415
|
-
const stepIdx = Math.min(
|
|
19416
|
-
statuses.length - 1,
|
|
19417
|
-
Math.floor(elapsed / TARGET_SECONDS * statuses.length)
|
|
19418
|
-
);
|
|
19419
|
-
const status = statuses[stepIdx];
|
|
19420
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-badge", role: "status", "aria-live": "polite", children: [
|
|
19421
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-badge-row", children: [
|
|
19422
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-badge-spinner", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", width: "22", height: "22", children: [
|
|
19423
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("defs", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("linearGradient", { id: "ps-tryon-badge-grad", x1: "0", y1: "0", x2: "1", y2: "1", children: [
|
|
19424
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "0%", stopColor: "#3B82F6" }),
|
|
19425
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "100%", stopColor: "#2563EB" })
|
|
19426
|
-
] }) }),
|
|
19427
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "9", fill: "none", stroke: "rgba(59,130,246,0.18)", strokeWidth: "2.4" }),
|
|
19428
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
19429
|
-
"circle",
|
|
19430
|
-
{
|
|
19431
|
-
cx: "12",
|
|
19432
|
-
cy: "12",
|
|
19433
|
-
r: "9",
|
|
19434
|
-
fill: "none",
|
|
19435
|
-
stroke: "url(#ps-tryon-badge-grad)",
|
|
19436
|
-
strokeWidth: "2.4",
|
|
19437
|
-
strokeLinecap: "round",
|
|
19438
|
-
strokeDasharray: "56.5",
|
|
19439
|
-
strokeDashoffset: "38"
|
|
19440
|
-
}
|
|
19441
|
-
)
|
|
19442
|
-
] }) }),
|
|
19443
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-badge-title", children: t2("Generating your look...") }),
|
|
19444
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-badge-pct", children: [
|
|
19445
|
-
pctRounded,
|
|
19446
|
-
"%"
|
|
19447
|
-
] })
|
|
19448
|
-
] }),
|
|
19449
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-badge-bar", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-badge-bar-fill", style: { width: `${pctRounded}%` } }) }),
|
|
19450
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-badge-foot", children: [
|
|
19451
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-badge-status", children: [
|
|
19452
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-badge-status-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
19453
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6", y1: "10", x2: "6", y2: "14" }),
|
|
19454
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "6", x2: "10", y2: "18" }),
|
|
19455
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "9", x2: "14", y2: "15" }),
|
|
19456
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "18", y1: "11", x2: "18", y2: "13" })
|
|
19457
|
-
] }) }),
|
|
19458
|
-
status
|
|
19459
|
-
] }),
|
|
19460
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-badge-eta", children: [
|
|
19461
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
19462
|
-
"svg",
|
|
19463
|
-
{
|
|
19464
|
-
width: "11",
|
|
19465
|
-
height: "11",
|
|
19466
|
-
viewBox: "0 0 24 24",
|
|
19467
|
-
fill: "none",
|
|
19468
|
-
stroke: "currentColor",
|
|
19469
|
-
strokeWidth: "2",
|
|
19470
|
-
strokeLinecap: "round",
|
|
19471
|
-
strokeLinejoin: "round",
|
|
19472
|
-
"aria-hidden": "true",
|
|
19473
|
-
children: [
|
|
19474
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
19475
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("polyline", { points: "12 6 12 12 16 14" })
|
|
19476
|
-
]
|
|
19477
|
-
}
|
|
19478
|
-
),
|
|
19479
|
-
etaText
|
|
19480
|
-
] })
|
|
19481
|
-
] })
|
|
19482
|
-
] });
|
|
19483
|
-
}
|
|
19484
19519
|
const PER_SLIDE = 3;
|
|
19485
19520
|
const CYCLE_MS = 4e3;
|
|
19486
19521
|
function ProductPhotoCarouselCard({
|
|
@@ -20253,6 +20288,7 @@ function SectionDetailView({
|
|
|
20253
20288
|
}
|
|
20254
20289
|
),
|
|
20255
20290
|
showLines && overlayNode,
|
|
20291
|
+
tryOnProcessing && tryOnStartedAt != null && /* @__PURE__ */ jsxRuntimeExports.jsx(TryOnGenerationBadge, { tryOnStartedAt, t: t2 }),
|
|
20256
20292
|
isTryOnImage && onToggleLines && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
20257
20293
|
"button",
|
|
20258
20294
|
{
|
|
@@ -20437,14 +20473,14 @@ function SectionDetailView({
|
|
|
20437
20473
|
" ",
|
|
20438
20474
|
t2("based on your measurements and the garment's tailoring chart.")
|
|
20439
20475
|
] }),
|
|
20440
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", gap: 10, padding: "12px 0 4px", flexShrink: 0 }, children: [
|
|
20476
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", gap: 10, padding: "12px 0 4px", flexShrink: 0, alignItems: "center" }, children: [
|
|
20441
20477
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
20442
20478
|
"button",
|
|
20443
20479
|
{
|
|
20444
20480
|
type: "button",
|
|
20445
20481
|
className: "ps-bp-back-btn",
|
|
20446
20482
|
onClick: onBack,
|
|
20447
|
-
style: { fontSize: 13, padding: "10px 6px" },
|
|
20483
|
+
style: { fontSize: 13, padding: "10px 6px", flexShrink: 0 },
|
|
20448
20484
|
children: [
|
|
20449
20485
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-back-arrow", children: "←" }),
|
|
20450
20486
|
" ",
|
|
@@ -20452,7 +20488,6 @@ function SectionDetailView({
|
|
|
20452
20488
|
]
|
|
20453
20489
|
}
|
|
20454
20490
|
),
|
|
20455
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { flex: 1 } }),
|
|
20456
20491
|
onTryOn ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
20457
20492
|
"button",
|
|
20458
20493
|
{
|
|
@@ -20460,7 +20495,8 @@ function SectionDetailView({
|
|
|
20460
20495
|
onClick: onTryOn,
|
|
20461
20496
|
disabled: tryOnProcessing,
|
|
20462
20497
|
style: {
|
|
20463
|
-
flex: 1,
|
|
20498
|
+
flex: "1 1 0",
|
|
20499
|
+
minWidth: 0,
|
|
20464
20500
|
padding: "12px 16px",
|
|
20465
20501
|
borderRadius: 10,
|
|
20466
20502
|
background: "var(--ps-accent)",
|
|
@@ -20474,7 +20510,8 @@ function SectionDetailView({
|
|
|
20474
20510
|
display: "flex",
|
|
20475
20511
|
alignItems: "center",
|
|
20476
20512
|
justifyContent: "center",
|
|
20477
|
-
gap: 6
|
|
20513
|
+
gap: 6,
|
|
20514
|
+
whiteSpace: "nowrap"
|
|
20478
20515
|
},
|
|
20479
20516
|
children: [
|
|
20480
20517
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CameraIcon$1, { size: 14 }),
|
|
@@ -20487,7 +20524,8 @@ function SectionDetailView({
|
|
|
20487
20524
|
type: "button",
|
|
20488
20525
|
onClick: onBack,
|
|
20489
20526
|
style: {
|
|
20490
|
-
flex: 1,
|
|
20527
|
+
flex: "1 1 0",
|
|
20528
|
+
minWidth: 0,
|
|
20491
20529
|
padding: "12px 16px",
|
|
20492
20530
|
borderRadius: 10,
|
|
20493
20531
|
background: "var(--ps-accent)",
|
|
@@ -20500,7 +20538,8 @@ function SectionDetailView({
|
|
|
20500
20538
|
display: "flex",
|
|
20501
20539
|
alignItems: "center",
|
|
20502
20540
|
justifyContent: "center",
|
|
20503
|
-
gap: 6
|
|
20541
|
+
gap: 6,
|
|
20542
|
+
whiteSpace: "nowrap"
|
|
20504
20543
|
},
|
|
20505
20544
|
children: [
|
|
20506
20545
|
continueLabel || t2("Continue"),
|
|
@@ -21295,6 +21334,7 @@ function SizeResultView({
|
|
|
21295
21334
|
setShowPhotoGuide(true);
|
|
21296
21335
|
},
|
|
21297
21336
|
tryOnProcessing,
|
|
21337
|
+
tryOnStartedAt,
|
|
21298
21338
|
resultImageUrl,
|
|
21299
21339
|
tryOnDone: !!resultImageUrl && !tryOnProcessing,
|
|
21300
21340
|
onTryAgain: () => {
|
|
@@ -24708,6 +24748,46 @@ function ResultView({ setView }) {
|
|
|
24708
24748
|
}, []);
|
|
24709
24749
|
return null;
|
|
24710
24750
|
}
|
|
24751
|
+
function RulerIcon() {
|
|
24752
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "13", height: "13", children: [
|
|
24753
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M3 17l6 6 12-12-6-6z" }),
|
|
24754
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9 11l2 2M11 9l2 2M13 7l2 2M7 13l2 2" })
|
|
24755
|
+
] });
|
|
24756
|
+
}
|
|
24757
|
+
function ScanIcon() {
|
|
24758
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "13", height: "13", children: [
|
|
24759
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M3 7V5a2 2 0 0 1 2-2h2M17 3h2a2 2 0 0 1 2 2v2M21 17v2a2 2 0 0 1-2 2h-2M7 21H5a2 2 0 0 1-2-2v-2" }),
|
|
24760
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "3" })
|
|
24761
|
+
] });
|
|
24762
|
+
}
|
|
24763
|
+
function MobileBottomTabs({ mode, onSwitchToManual, onSwitchToScan, t: t2 }) {
|
|
24764
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bpm-bottom-tabs", children: [
|
|
24765
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
24766
|
+
"button",
|
|
24767
|
+
{
|
|
24768
|
+
type: "button",
|
|
24769
|
+
className: `ps-bpm-bottom-tab${mode === "manual" ? " ps-active" : ""}`,
|
|
24770
|
+
onClick: onSwitchToManual,
|
|
24771
|
+
children: [
|
|
24772
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RulerIcon, {}),
|
|
24773
|
+
t2("MANUAL FIT")
|
|
24774
|
+
]
|
|
24775
|
+
}
|
|
24776
|
+
),
|
|
24777
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
24778
|
+
"button",
|
|
24779
|
+
{
|
|
24780
|
+
type: "button",
|
|
24781
|
+
className: `ps-bpm-bottom-tab${mode === "scan" ? " ps-active" : ""}`,
|
|
24782
|
+
onClick: onSwitchToScan,
|
|
24783
|
+
children: [
|
|
24784
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ScanIcon, {}),
|
|
24785
|
+
t2("AI SCAN")
|
|
24786
|
+
]
|
|
24787
|
+
}
|
|
24788
|
+
)
|
|
24789
|
+
] });
|
|
24790
|
+
}
|
|
24711
24791
|
function CameraSmallIcon({ size = 16 }) {
|
|
24712
24792
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", width: size, height: size, children: [
|
|
24713
24793
|
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" }),
|