@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/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 {
@@ -5335,7 +5362,10 @@ function LangSwitcher({ activeLocale: current, onSelect }) {
5335
5362
  position: "fixed",
5336
5363
  top: pos.top,
5337
5364
  right: pos.right,
5338
- zIndex: 9999999
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
- const p = profileDetail;
5590
- const measurements = [
5591
- { label: t("Height"), value: p.heightCm, unit: t("cm") },
5592
- { label: t("Weight"), value: p.weightKg, unit: t("kg") },
5593
- { label: t("Chest"), value: p.chest, unit: t("cm") },
5594
- { label: t("Bust"), value: p.bust, unit: t("cm") },
5595
- { label: t("Waist"), value: p.waist, unit: t("cm") },
5596
- { label: t("Hips"), value: p.hips, unit: t("cm") },
5597
- { label: t("Shoulders"), value: p.shoulderWidth, unit: t("cm") },
5598
- { label: t("Sleeve"), value: p.sleeveLength, unit: t("cm") },
5599
- { label: t("Inseam"), value: p.inseam, unit: t("cm") },
5600
- { label: t("Neck"), value: p.neckCircumference, unit: t("cm") },
5601
- { label: t("Foot"), value: p.footLengthCm, unit: t("cm") },
5602
- { label: t("Shoe EU"), value: p.shoeEU ? Number(p.shoeEU) : void 0, unit: "" },
5603
- { label: t("Shoe US"), value: p.shoeUS ? Number(p.shoeUS) : void 0, unit: "" },
5604
- { label: t("Shoe UK"), value: p.shoeUK ? Number(p.shoeUK) : void 0, unit: "" }
5605
- ].filter((m) => m.value);
5606
- return /* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-overlay", onClick: (e) => {
5607
- if (e.target === e.currentTarget) setProfileDetail(null);
5608
- }, children: /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-modal", children: [
5609
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-header", children: [
5610
- /* @__PURE__ */ jsx("span", { children: p.name }),
5611
- /* @__PURE__ */ jsx("button", { onClick: () => setProfileDetail(null), children: /* @__PURE__ */ jsx(XIcon, { size: 18 }) })
5612
- ] }),
5613
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-body", children: [
5614
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-gender", children: [
5615
- /* @__PURE__ */ jsx(UserIcon, { size: 18 }),
5616
- " ",
5617
- p.gender === "female" ? t("Women's Profile") : t("Men's Profile")
5618
- ] }),
5619
- measurements.length > 0 && /* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-grid", children: measurements.map((m) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-cell", children: [
5620
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-cell-label", children: m.label }),
5621
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-cell-value", children: [
5622
- Math.round(m.value),
5623
- 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
+ ) })
5624
5666
  ] })
5625
- ] }, m.label)) }),
5626
- p.createdAt && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-date", children: [
5627
- t("Saved"),
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(