@primestyleai/tryon 5.6.6 → 5.6.8
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.
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { TranslateFn } from "../../i18n";
|
|
2
2
|
import type { Profile } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Edit profile dialog — opens as a dark overlay ABOVE the main modal
|
|
5
|
+
* (z-index matches the .ps-tryon-overlay max-int so it always stacks
|
|
6
|
+
* on top). Wraps ProfileEditView so the user gets a real editable form
|
|
7
|
+
* with name + gender + units + height/weight/age + Save / Cancel.
|
|
8
|
+
*
|
|
9
|
+
* Portaled to document.body so parent stacking contexts can't clip it.
|
|
10
|
+
*/
|
|
3
11
|
export declare function ProfileDetailModal({ profileDetail, setProfileDetail, setProfiles, activeProfileId, setActiveProfileId, t, }: {
|
|
4
12
|
profileDetail: Profile | null;
|
|
5
13
|
setProfileDetail: (p: Profile | null) => void;
|
|
@@ -7,4 +15,4 @@ export declare function ProfileDetailModal({ profileDetail, setProfileDetail, se
|
|
|
7
15
|
activeProfileId: string | null;
|
|
8
16
|
setActiveProfileId: (id: string | null) => void;
|
|
9
17
|
t: TranslateFn;
|
|
10
|
-
}): import("react
|
|
18
|
+
}): import("react").ReactPortal | null;
|
package/dist/react/index.js
CHANGED
|
@@ -2805,15 +2805,28 @@ const STYLES = `
|
|
|
2805
2805
|
}
|
|
2806
2806
|
.ps-tryon-drawer-clear:hover { color: var(--ps-error-color); }
|
|
2807
2807
|
|
|
2808
|
-
/* Profile detail modal
|
|
2808
|
+
/* Profile detail modal — portaled to body, sits ABOVE the main modal
|
|
2809
|
+
overlay (which has z-index 2147483647). Equal z-index + later DOM
|
|
2810
|
+
order means this stacks on top. Same trick as the language dropdown. */
|
|
2809
2811
|
.ps-tryon-detail-overlay {
|
|
2810
2812
|
position: fixed; inset: 0; background: rgba(0,0,0,0.55);
|
|
2811
2813
|
display: flex; align-items: center; justify-content: center;
|
|
2812
|
-
z-index:
|
|
2814
|
+
z-index: 2147483647; padding: 0.83vw; animation: ps-fade-in 0.2s ease;
|
|
2815
|
+
isolation: isolate;
|
|
2816
|
+
--ps-accent: #3B82F6;
|
|
2817
|
+
--ps-accent-hover: #2563EB;
|
|
2818
|
+
--ps-text-primary: #1C1D1E;
|
|
2819
|
+
--ps-text-secondary: #454545;
|
|
2820
|
+
--ps-text-muted: #84898C;
|
|
2821
|
+
--ps-border-color: #E7E7E7;
|
|
2822
|
+
--ps-border-subtle: #F0F0F0;
|
|
2823
|
+
--ps-bg-primary: #FFFFFF;
|
|
2824
|
+
--ps-bg-secondary: #F8FAFF;
|
|
2825
|
+
--ps-error-color: #E7000B;
|
|
2813
2826
|
}
|
|
2814
2827
|
.ps-tryon-detail-modal {
|
|
2815
|
-
background: var(--ps-bg-primary); border-radius:
|
|
2816
|
-
overflow-y: auto; box-shadow: 0
|
|
2828
|
+
background: var(--ps-bg-primary); border-radius: 14px; width: 100%; max-width: 480px; max-height: 85vh;
|
|
2829
|
+
overflow-y: auto; box-shadow: 0 24px 64px rgba(0,0,0,0.3); animation: ps-slide-up 0.25s ease;
|
|
2817
2830
|
font-family: var(--ps-modal-font, system-ui, sans-serif); color: var(--ps-text-primary);
|
|
2818
2831
|
}
|
|
2819
2832
|
.ps-tryon-detail-header {
|
|
@@ -3851,6 +3864,8 @@ const STYLES = `
|
|
|
3851
3864
|
}
|
|
3852
3865
|
.ps-msp-card-photo {
|
|
3853
3866
|
width: 100%; height: 100%; object-fit: cover; display: block;
|
|
3867
|
+
/* Same head-bias crop as the profile detail avatar */
|
|
3868
|
+
object-position: 50% 12%;
|
|
3854
3869
|
}
|
|
3855
3870
|
.ps-msp-avatar {
|
|
3856
3871
|
position: relative;
|
|
@@ -4045,15 +4060,17 @@ const STYLES = `
|
|
|
4045
4060
|
════════════════════════════════════════════════════════════════ */
|
|
4046
4061
|
.ps-cpw-root {
|
|
4047
4062
|
display: flex; flex-direction: column;
|
|
4048
|
-
|
|
4063
|
+
height: 100%; min-height: 0;
|
|
4064
|
+
margin: 0 -16px;
|
|
4049
4065
|
}
|
|
4050
4066
|
|
|
4051
|
-
/* Step header —
|
|
4067
|
+
/* Step header — sticky at top */
|
|
4052
4068
|
.ps-cpw-step-head {
|
|
4053
4069
|
display: flex; align-items: flex-start; justify-content: space-between;
|
|
4054
4070
|
gap: 16px;
|
|
4055
|
-
padding
|
|
4071
|
+
padding: 4px 16px 18px;
|
|
4056
4072
|
border-bottom: 1px solid var(--ps-border-subtle);
|
|
4073
|
+
flex-shrink: 0;
|
|
4057
4074
|
}
|
|
4058
4075
|
.ps-cpw-eyebrow {
|
|
4059
4076
|
font-size: 10px; font-weight: 700;
|
|
@@ -4091,6 +4108,9 @@ const STYLES = `
|
|
|
4091
4108
|
.ps-cpw-body {
|
|
4092
4109
|
display: flex; flex-direction: column;
|
|
4093
4110
|
gap: 24px;
|
|
4111
|
+
flex: 1; min-height: 0;
|
|
4112
|
+
overflow-y: auto; -webkit-overflow-scrolling: touch;
|
|
4113
|
+
padding: 18px 16px 24px;
|
|
4094
4114
|
}
|
|
4095
4115
|
|
|
4096
4116
|
/* Step 1 — Identity form */
|
|
@@ -4177,7 +4197,8 @@ const STYLES = `
|
|
|
4177
4197
|
}
|
|
4178
4198
|
.ps-cpw-photo-upload {
|
|
4179
4199
|
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
4180
|
-
gap:
|
|
4200
|
+
gap: 8px; padding: 38px 18px;
|
|
4201
|
+
min-height: 220px;
|
|
4181
4202
|
background: var(--ps-bg-secondary);
|
|
4182
4203
|
border: 2px dashed var(--ps-border-color);
|
|
4183
4204
|
border-radius: 12px;
|
|
@@ -4282,13 +4303,14 @@ const STYLES = `
|
|
|
4282
4303
|
color: var(--ps-accent);
|
|
4283
4304
|
}
|
|
4284
4305
|
|
|
4285
|
-
/* Footer actions */
|
|
4306
|
+
/* Footer actions — sticky at the bottom */
|
|
4286
4307
|
.ps-cpw-footer {
|
|
4287
4308
|
display: flex; align-items: center; justify-content: space-between;
|
|
4288
4309
|
gap: 12px;
|
|
4289
|
-
padding
|
|
4310
|
+
padding: 16px 16px;
|
|
4290
4311
|
border-top: 1px solid var(--ps-border-subtle);
|
|
4291
|
-
|
|
4312
|
+
background: var(--ps-bg-primary);
|
|
4313
|
+
flex-shrink: 0;
|
|
4292
4314
|
}
|
|
4293
4315
|
.ps-cpw-back-btn {
|
|
4294
4316
|
background: none; border: none;
|
|
@@ -4355,6 +4377,11 @@ const STYLES = `
|
|
|
4355
4377
|
}
|
|
4356
4378
|
.ps-pmv-hero-avatar img {
|
|
4357
4379
|
width: 100%; height: 100%; object-fit: cover;
|
|
4380
|
+
/* Bias the crop toward the top of the photo so the head/face shows
|
|
4381
|
+
through the circular avatar instead of the torso. Works for any
|
|
4382
|
+
full-body or head-and-torso photo where the head is in the upper
|
|
4383
|
+
portion of the frame. */
|
|
4384
|
+
object-position: 50% 12%;
|
|
4358
4385
|
}
|
|
4359
4386
|
.ps-pmv-hero-info { flex: 1; min-width: 0; }
|
|
4360
4387
|
.ps-pmv-hero-eyebrow {
|
|
@@ -5335,7 +5362,10 @@ function LangSwitcher({ activeLocale: current, onSelect }) {
|
|
|
5335
5362
|
position: "fixed",
|
|
5336
5363
|
top: pos.top,
|
|
5337
5364
|
right: pos.right,
|
|
5338
|
-
|
|
5365
|
+
// Match the overlay's z-index (2147483647) so the dropdown sits
|
|
5366
|
+
// above it. With equal z-index, document order wins — and the
|
|
5367
|
+
// dropdown is portaled later than the overlay so it stacks on top.
|
|
5368
|
+
zIndex: 2147483647
|
|
5339
5369
|
},
|
|
5340
5370
|
children: /* @__PURE__ */ jsx("div", { className: "ps-tryon-lang-list", children: SUPPORTED_LOCALES.map((code) => /* @__PURE__ */ jsxs(
|
|
5341
5371
|
"button",
|
|
@@ -5585,60 +5615,59 @@ function ProfileDetailModal({
|
|
|
5585
5615
|
setActiveProfileId: setActiveProfileId2,
|
|
5586
5616
|
t
|
|
5587
5617
|
}) {
|
|
5618
|
+
useEffect(() => {
|
|
5619
|
+
if (!profileDetail || typeof document === "undefined") return;
|
|
5620
|
+
const prev = document.body.style.overflow;
|
|
5621
|
+
document.body.style.overflow = "hidden";
|
|
5622
|
+
return () => {
|
|
5623
|
+
document.body.style.overflow = prev;
|
|
5624
|
+
};
|
|
5625
|
+
}, [profileDetail]);
|
|
5588
5626
|
if (!profileDetail) return null;
|
|
5589
|
-
|
|
5590
|
-
const
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
return
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5627
|
+
if (typeof document === "undefined") return null;
|
|
5628
|
+
const handleSave = (updated) => {
|
|
5629
|
+
setProfiles((prev) => prev.map(
|
|
5630
|
+
(p) => p.id === profileDetail.id ? {
|
|
5631
|
+
...p,
|
|
5632
|
+
...updated,
|
|
5633
|
+
// Keep id + createdAt + sizeHistory + measurements; bump lastEditedAt
|
|
5634
|
+
id: p.id,
|
|
5635
|
+
createdAt: p.createdAt,
|
|
5636
|
+
sizeHistory: p.sizeHistory,
|
|
5637
|
+
measurements: p.measurements,
|
|
5638
|
+
lastEditedAt: Date.now()
|
|
5639
|
+
} : p
|
|
5640
|
+
));
|
|
5641
|
+
setProfileDetail(null);
|
|
5642
|
+
};
|
|
5643
|
+
const handleClose = () => setProfileDetail(null);
|
|
5644
|
+
return createPortal(
|
|
5645
|
+
/* @__PURE__ */ jsx(
|
|
5646
|
+
"div",
|
|
5647
|
+
{
|
|
5648
|
+
className: "ps-tryon-detail-overlay",
|
|
5649
|
+
onClick: (e) => {
|
|
5650
|
+
if (e.target === e.currentTarget) handleClose();
|
|
5651
|
+
},
|
|
5652
|
+
children: /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-modal", children: [
|
|
5653
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-header", children: [
|
|
5654
|
+
/* @__PURE__ */ jsx("span", { children: t("Edit Profile") }),
|
|
5655
|
+
/* @__PURE__ */ jsx("button", { onClick: handleClose, "aria-label": t("Close"), children: /* @__PURE__ */ jsx(XIcon, { size: 18 }) })
|
|
5656
|
+
] }),
|
|
5657
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-body", children: /* @__PURE__ */ jsx(
|
|
5658
|
+
ProfileEditView,
|
|
5659
|
+
{
|
|
5660
|
+
profile: profileDetail,
|
|
5661
|
+
onSave: handleSave,
|
|
5662
|
+
onCancel: handleClose,
|
|
5663
|
+
t
|
|
5664
|
+
}
|
|
5665
|
+
) })
|
|
5624
5666
|
] })
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
new Date(p.createdAt).toLocaleDateString()
|
|
5630
|
-
] }),
|
|
5631
|
-
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-detail-delete", onClick: () => {
|
|
5632
|
-
setProfiles((prev) => prev.filter((x) => x.id !== p.id));
|
|
5633
|
-
if (activeProfileId === p.id) setActiveProfileId2(null);
|
|
5634
|
-
setProfileDetail(null);
|
|
5635
|
-
}, children: [
|
|
5636
|
-
/* @__PURE__ */ jsx(TrashIcon, {}),
|
|
5637
|
-
" ",
|
|
5638
|
-
t("Delete Profile")
|
|
5639
|
-
] })
|
|
5640
|
-
] })
|
|
5641
|
-
] }) });
|
|
5667
|
+
}
|
|
5668
|
+
),
|
|
5669
|
+
document.body
|
|
5670
|
+
);
|
|
5642
5671
|
}
|
|
5643
5672
|
function WelcomeView({
|
|
5644
5673
|
productImage,
|
|
@@ -7687,6 +7716,10 @@ function ShapeSection({
|
|
|
7687
7716
|
}
|
|
7688
7717
|
function CreateProfileWizard({ onSave, onCancel, t }) {
|
|
7689
7718
|
const [step, setStep] = useState(1);
|
|
7719
|
+
const bodyScrollRef = useRef(null);
|
|
7720
|
+
useEffect(() => {
|
|
7721
|
+
if (bodyScrollRef.current) bodyScrollRef.current.scrollTop = 0;
|
|
7722
|
+
}, [step]);
|
|
7690
7723
|
const [name, setName] = useState("");
|
|
7691
7724
|
const [gender, setGender] = useState("male");
|
|
7692
7725
|
const [unit, setUnit] = useState("cm");
|
|
@@ -7804,7 +7837,7 @@ function CreateProfileWizard({ onSave, onCancel, t }) {
|
|
|
7804
7837
|
] })
|
|
7805
7838
|
] })
|
|
7806
7839
|
] }),
|
|
7807
|
-
/* @__PURE__ */ jsx("div", { className: "ps-cpw-body", children: step === 1 ? /* @__PURE__ */ jsxs("div", { className: "ps-cpw-identity", children: [
|
|
7840
|
+
/* @__PURE__ */ jsx("div", { className: "ps-cpw-body", ref: bodyScrollRef, children: step === 1 ? /* @__PURE__ */ jsxs("div", { className: "ps-cpw-identity", children: [
|
|
7808
7841
|
/* @__PURE__ */ jsxs("div", { className: "ps-cpw-field", children: [
|
|
7809
7842
|
/* @__PURE__ */ jsx("label", { className: "ps-cpw-field-label", children: t("PROFILE NAME") }),
|
|
7810
7843
|
/* @__PURE__ */ jsx(
|