@primestyleai/tryon 5.6.7 → 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/jsx-runtime").JSX.Element | null;
18
+ }): import("react").ReactPortal | null;
@@ -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: 9999999; padding: 0.83vw; animation: ps-fade-in 0.2s ease;
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: 0.83vw; width: 100%; max-width: 23vw; max-height: 85vh;
2816
- overflow-y: auto; box-shadow: 0 1.67vw 3.33vw rgba(0,0,0,0.3); animation: ps-slide-up 0.25s ease;
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
- gap: 20px; padding: 4px 4px 24px;
4063
+ height: 100%; min-height: 0;
4064
+ margin: 0 -16px;
4049
4065
  }
4050
4066
 
4051
- /* Step header — eyebrow + title + progress */
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-bottom: 18px;
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: 6px; padding: 22px;
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-top: 18px;
4310
+ padding: 16px 16px;
4290
4311
  border-top: 1px solid var(--ps-border-subtle);
4291
- margin-top: 4px;
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 {
@@ -5588,60 +5615,59 @@ function ProfileDetailModal({
5588
5615
  setActiveProfileId: setActiveProfileId2,
5589
5616
  t
5590
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]);
5591
5626
  if (!profileDetail) return null;
5592
- const p = profileDetail;
5593
- const measurements = [
5594
- { label: t("Height"), value: p.heightCm, unit: t("cm") },
5595
- { label: t("Weight"), value: p.weightKg, unit: t("kg") },
5596
- { label: t("Chest"), value: p.chest, unit: t("cm") },
5597
- { label: t("Bust"), value: p.bust, unit: t("cm") },
5598
- { label: t("Waist"), value: p.waist, unit: t("cm") },
5599
- { label: t("Hips"), value: p.hips, unit: t("cm") },
5600
- { label: t("Shoulders"), value: p.shoulderWidth, unit: t("cm") },
5601
- { label: t("Sleeve"), value: p.sleeveLength, unit: t("cm") },
5602
- { label: t("Inseam"), value: p.inseam, unit: t("cm") },
5603
- { label: t("Neck"), value: p.neckCircumference, unit: t("cm") },
5604
- { label: t("Foot"), value: p.footLengthCm, unit: t("cm") },
5605
- { label: t("Shoe EU"), value: p.shoeEU ? Number(p.shoeEU) : void 0, unit: "" },
5606
- { label: t("Shoe US"), value: p.shoeUS ? Number(p.shoeUS) : void 0, unit: "" },
5607
- { label: t("Shoe UK"), value: p.shoeUK ? Number(p.shoeUK) : void 0, unit: "" }
5608
- ].filter((m) => m.value);
5609
- return /* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-overlay", onClick: (e) => {
5610
- if (e.target === e.currentTarget) setProfileDetail(null);
5611
- }, children: /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-modal", children: [
5612
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-header", children: [
5613
- /* @__PURE__ */ jsx("span", { children: p.name }),
5614
- /* @__PURE__ */ jsx("button", { onClick: () => setProfileDetail(null), children: /* @__PURE__ */ jsx(XIcon, { size: 18 }) })
5615
- ] }),
5616
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-body", children: [
5617
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-gender", children: [
5618
- /* @__PURE__ */ jsx(UserIcon, { size: 18 }),
5619
- " ",
5620
- p.gender === "female" ? t("Women's Profile") : t("Men's Profile")
5621
- ] }),
5622
- measurements.length > 0 && /* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-grid", children: measurements.map((m) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-cell", children: [
5623
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-cell-label", children: m.label }),
5624
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-cell-value", children: [
5625
- Math.round(m.value),
5626
- m.unit ? ` ${m.unit}` : ""
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
+ ) })
5627
5666
  ] })
5628
- ] }, m.label)) }),
5629
- p.createdAt && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-date", children: [
5630
- t("Saved"),
5631
- " ",
5632
- new Date(p.createdAt).toLocaleDateString()
5633
- ] }),
5634
- /* @__PURE__ */ jsxs("button", { className: "ps-tryon-detail-delete", onClick: () => {
5635
- setProfiles((prev) => prev.filter((x) => x.id !== p.id));
5636
- if (activeProfileId === p.id) setActiveProfileId2(null);
5637
- setProfileDetail(null);
5638
- }, children: [
5639
- /* @__PURE__ */ jsx(TrashIcon, {}),
5640
- " ",
5641
- t("Delete Profile")
5642
- ] })
5643
- ] })
5644
- ] }) });
5667
+ }
5668
+ ),
5669
+ document.body
5670
+ );
5645
5671
  }
5646
5672
  function WelcomeView({
5647
5673
  productImage,
@@ -7690,6 +7716,10 @@ function ShapeSection({
7690
7716
  }
7691
7717
  function CreateProfileWizard({ onSave, onCancel, t }) {
7692
7718
  const [step, setStep] = useState(1);
7719
+ const bodyScrollRef = useRef(null);
7720
+ useEffect(() => {
7721
+ if (bodyScrollRef.current) bodyScrollRef.current.scrollTop = 0;
7722
+ }, [step]);
7693
7723
  const [name, setName] = useState("");
7694
7724
  const [gender, setGender] = useState("male");
7695
7725
  const [unit, setUnit] = useState("cm");
@@ -7807,7 +7837,7 @@ function CreateProfileWizard({ onSave, onCancel, t }) {
7807
7837
  ] })
7808
7838
  ] })
7809
7839
  ] }),
7810
- /* @__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: [
7811
7841
  /* @__PURE__ */ jsxs("div", { className: "ps-cpw-field", children: [
7812
7842
  /* @__PURE__ */ jsx("label", { className: "ps-cpw-field-label", children: t("PROFILE NAME") }),
7813
7843
  /* @__PURE__ */ jsx(