@primestyleai/tryon 5.10.173 → 5.10.175
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/api-client.d.ts +8 -3
- package/dist/image-utils.d.ts +1 -0
- package/dist/{index-B1_VQgps.js → index-D4yjnBvO.js} +147 -82
- package/dist/index-D4yjnBvO.js.map +1 -0
- package/dist/primestyle-tryon.js +6 -5
- package/dist/primestyle-tryon.js.map +1 -1
- package/dist/react/PrimeStyleTryonInner.d.ts +7 -2
- package/dist/react/components/LangSwitcher.d.ts +2 -1
- package/dist/react/components/ProfileDetailModal.d.ts +2 -1
- package/dist/react/icons.d.ts +3 -0
- package/dist/react/index.js +9334 -6250
- package/dist/react/index.js.map +1 -1
- package/dist/react/recommendForProduct.d.ts +6 -0
- package/dist/react/styles.d.ts +1 -1
- package/dist/react/types.d.ts +56 -0
- package/dist/react/utils/locale.d.ts +3 -1
- package/dist/react/utils/product-fit.d.ts +19 -0
- package/dist/react/utils/profile-auth.d.ts +10 -0
- package/dist/react/utils/profile-image.d.ts +3 -0
- package/dist/react/utils/remote-profiles.d.ts +7 -0
- package/dist/react/utils/shoe-reference.d.ts +39 -0
- package/dist/react/views/AccessorySizeView.d.ts +1 -0
- package/dist/react/views/BasicsStepMobile.d.ts +3 -1
- package/dist/react/views/BodyProfileView.d.ts +11 -3
- package/dist/react/views/CreateProfileWizard.d.ts +4 -2
- package/dist/react/views/ErrorView.d.ts +4 -3
- package/dist/react/views/FootSizeView.d.ts +1 -0
- package/dist/react/views/MobileScanningView.d.ts +5 -1
- package/dist/react/views/MultiSectionMobile.d.ts +7 -2
- package/dist/react/views/MySizingProfilesView.d.ts +5 -2
- package/dist/react/views/PhotoGuideView.d.ts +1 -1
- package/dist/react/views/PhotoStepMobile.d.ts +3 -1
- package/dist/react/views/ProductPhotoCarouselCard.d.ts +8 -2
- package/dist/react/views/SizeResultView.d.ts +8 -2
- package/dist/react/views/SocialProfileAuthView.d.ts +10 -0
- package/dist/react/views/WristSizeView.d.ts +28 -0
- package/dist/sizing/fit-compute.d.ts +8 -0
- package/dist/storefront/cart-hook.d.ts +4 -4
- package/dist/storefront/events.d.ts +6 -0
- package/dist/storefront/primestyle-tryon.js +4755 -1046
- package/dist/types.d.ts +5 -0
- package/package.json +2 -3
- package/dist/index-B1_VQgps.js.map +0 -1
package/dist/react/types.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export interface ProfileMeasurements {
|
|
|
18
18
|
inseam?: number;
|
|
19
19
|
neckCircumference?: number;
|
|
20
20
|
thighCircumference?: number;
|
|
21
|
+
wristCircumference?: number;
|
|
21
22
|
footLengthCm?: number;
|
|
22
23
|
height?: number;
|
|
23
24
|
/** Allow other fields the backend may return */
|
|
@@ -60,7 +61,10 @@ export interface Profile {
|
|
|
60
61
|
hipProfile?: HipProfile;
|
|
61
62
|
bandSize?: string;
|
|
62
63
|
cupSize?: string;
|
|
64
|
+
braSizeRegion?: string;
|
|
63
65
|
photoBase64?: string;
|
|
66
|
+
/** Optional uploaded profile photo URL/data URL used by remote profile sync. */
|
|
67
|
+
photoUrl?: string;
|
|
64
68
|
measurements?: ProfileMeasurements;
|
|
65
69
|
measurementsUnit?: "cm" | "in";
|
|
66
70
|
sizeHistory?: SizeHistoryEntry[];
|
|
@@ -87,10 +91,37 @@ export interface Profile {
|
|
|
87
91
|
/** Bumped any time measurements/answers change — used to invalidate sizeHistory cache */
|
|
88
92
|
lastEditedAt?: number;
|
|
89
93
|
}
|
|
94
|
+
export interface ProfileCompletionDraft {
|
|
95
|
+
source?: "size-result" | string;
|
|
96
|
+
createdAt?: number;
|
|
97
|
+
productId?: string;
|
|
98
|
+
productTitle?: string;
|
|
99
|
+
gender?: "male" | "female";
|
|
100
|
+
height?: number;
|
|
101
|
+
weight?: number;
|
|
102
|
+
heightUnit?: "cm" | "in" | "ft" | string;
|
|
103
|
+
weightUnit?: "kg" | "lbs" | string;
|
|
104
|
+
sizingUnit?: "cm" | "in" | string;
|
|
105
|
+
age?: number;
|
|
106
|
+
chestProfile?: ChestProfile;
|
|
107
|
+
midsectionProfile?: MidsectionProfile;
|
|
108
|
+
hipProfile?: HipProfile;
|
|
109
|
+
bandSize?: string;
|
|
110
|
+
cupSize?: string;
|
|
111
|
+
braSizeRegion?: string;
|
|
112
|
+
customMeasurements?: Record<string, number>;
|
|
113
|
+
}
|
|
90
114
|
export interface HistoryEntry {
|
|
91
115
|
id: string;
|
|
116
|
+
productId?: string;
|
|
92
117
|
productTitle?: string;
|
|
93
118
|
productImage?: string;
|
|
119
|
+
productImages?: string[];
|
|
120
|
+
productCarouselItems?: Array<{
|
|
121
|
+
image: string;
|
|
122
|
+
title?: string;
|
|
123
|
+
href?: string;
|
|
124
|
+
}>;
|
|
94
125
|
resultImageUrl?: string;
|
|
95
126
|
recommendedSize?: string;
|
|
96
127
|
confidence?: string;
|
|
@@ -154,6 +185,13 @@ export interface PrimeStyleTryonProps {
|
|
|
154
185
|
* score ~0 and are skipped. The first image still shows in the UI
|
|
155
186
|
* unchanged. */
|
|
156
187
|
productImages?: string[];
|
|
188
|
+
/** Optional carousel items shown in the size-result card.
|
|
189
|
+
* Used for "complete the look" recommendations. Falls back to productImages. */
|
|
190
|
+
productCarouselItems?: Array<{
|
|
191
|
+
image: string;
|
|
192
|
+
title?: string;
|
|
193
|
+
href?: string;
|
|
194
|
+
}>;
|
|
157
195
|
/** Optional explicit override — if you already know which image in the
|
|
158
196
|
* gallery is the model-wearing-the-garment shot, pass it here and the
|
|
159
197
|
* SDK skips the MediaPipe-based auto-pick. Falls through to auto-pick
|
|
@@ -162,6 +200,22 @@ export interface PrimeStyleTryonProps {
|
|
|
162
200
|
productTitle?: string;
|
|
163
201
|
/** Stable product identifier — used to cache size recommendations per (profile, product) */
|
|
164
202
|
productId?: string;
|
|
203
|
+
/** Optional product category metadata used to select the correct sizing flow. */
|
|
204
|
+
productCategory?: string;
|
|
205
|
+
/** Optional target product gender metadata. Prevents AI fallback when the host already knows it. */
|
|
206
|
+
productGender?: string;
|
|
207
|
+
/** Optional product subcategory metadata used to select accessory flows like belts, hats, and eyewear. */
|
|
208
|
+
productSubcategory?: string;
|
|
209
|
+
/** Merchant/product-type label used before keyword fallback. */
|
|
210
|
+
productType?: string;
|
|
211
|
+
/** Optional product vendor/brand metadata forwarded to backend context. */
|
|
212
|
+
productVendor?: string;
|
|
213
|
+
/** Explicit fit category override, e.g. apparel, belt, shoe, hat, sunglasses. */
|
|
214
|
+
productFitType?: string;
|
|
215
|
+
/** Product tags used as sizing-flow detection signals. */
|
|
216
|
+
productTags?: string[] | string;
|
|
217
|
+
/** Alias for productTags for hosts that already use a `tags` property. */
|
|
218
|
+
tags?: string[] | string;
|
|
165
219
|
/** Free-text product description (e.g. "Brown slip maxi dress with spaghetti straps").
|
|
166
220
|
* Forwarded to the backend try-on prompt so Gemini knows the garment context. */
|
|
167
221
|
productDescription?: string;
|
|
@@ -183,6 +237,8 @@ export interface PrimeStyleTryonProps {
|
|
|
183
237
|
classNames?: PrimeStyleClassNames;
|
|
184
238
|
className?: string;
|
|
185
239
|
style?: CSSProperties;
|
|
240
|
+
/** Optional portal target for modal/dropdown overlays. */
|
|
241
|
+
portalContainer?: Element | DocumentFragment | null;
|
|
186
242
|
onOpen?: () => void;
|
|
187
243
|
onClose?: () => void;
|
|
188
244
|
onUpload?: (file: File) => void;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export declare function detectLocale(): string;
|
|
2
2
|
/**
|
|
3
|
-
* Read `process.env.NEXT_PUBLIC_PRIMESTYLE_API_KEY
|
|
3
|
+
* Read `process.env.NEXT_PUBLIC_PRIMESTYLE_API_KEY` when a host still uses
|
|
4
|
+
* the legacy browser-key flow. First-party/proxy integrations can leave it
|
|
5
|
+
* empty; request helpers will simply omit the Authorization header.
|
|
4
6
|
*
|
|
5
7
|
* IMPORTANT: this MUST be a literal `process.env.X` access, NOT a
|
|
6
8
|
* dynamic property read like `process.env[key]`. Bundlers (Next.js
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type ProductFitType = "apparel" | "shoe" | "bag" | "hat" | "sunglasses" | "earring" | "necklace" | "bracelet" | "ring" | "belt" | "watch" | "accessory" | "unknown";
|
|
2
|
+
export type ProductMeasurementType = "body" | "foot" | "head" | "face" | "wrist" | "body-basic";
|
|
3
|
+
export type ProductGender = "male" | "female" | "unisex";
|
|
4
|
+
interface ProductFitInput {
|
|
5
|
+
productFitType?: string | null;
|
|
6
|
+
productGender?: string | null;
|
|
7
|
+
productTitle?: string | null;
|
|
8
|
+
productCategory?: string | null;
|
|
9
|
+
productSubcategory?: string | null;
|
|
10
|
+
productDescription?: string | null;
|
|
11
|
+
productType?: string | null;
|
|
12
|
+
productTags?: string[] | string | null;
|
|
13
|
+
}
|
|
14
|
+
export declare function normalizeProductFitType(value?: string | null): ProductFitType | null;
|
|
15
|
+
export declare function normalizeProductGender(value?: string | null): ProductGender | null;
|
|
16
|
+
export declare function detectProductFitType(input: ProductFitInput): ProductFitType;
|
|
17
|
+
export declare function detectProductGender(input: ProductFitInput, sizeGuide?: unknown): ProductGender | null;
|
|
18
|
+
export declare function productFitTypeToMeasurementType(fitType: ProductFitType): ProductMeasurementType;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type SocialProvider = "google" | "apple" | "facebook" | "linkedin";
|
|
2
|
+
export interface ProfileAuthSession {
|
|
3
|
+
accessToken: string;
|
|
4
|
+
isNewUser?: boolean;
|
|
5
|
+
signedInAt: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function getStoredProfileSession(): ProfileAuthSession | null;
|
|
8
|
+
export declare function setStoredProfileSession(session: ProfileAuthSession): void;
|
|
9
|
+
export declare function clearStoredProfileSession(): void;
|
|
10
|
+
export declare function startSocialProfileLogin(provider: SocialProvider, apiUrl?: string): Promise<ProfileAuthSession>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Profile } from "../types";
|
|
2
|
+
export interface RemoteProfileStore {
|
|
3
|
+
profiles: Profile[];
|
|
4
|
+
activeProfileId: string | null;
|
|
5
|
+
}
|
|
6
|
+
export declare function fetchRemoteProfiles(apiUrl: string | undefined, accessToken: string): Promise<RemoteProfileStore>;
|
|
7
|
+
export declare function saveRemoteProfiles(apiUrl: string | undefined, accessToken: string, profiles: Profile[], activeProfileId: string | null): Promise<RemoteProfileStore>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type ShoeBrandId = "nike" | "adidas" | "new-balance" | "puma" | "reebok" | "converse" | "vans" | "asics" | "jordan" | "skechers";
|
|
2
|
+
export interface ShoeBrandOption {
|
|
3
|
+
id: ShoeBrandId;
|
|
4
|
+
label: string;
|
|
5
|
+
logoSrc: string;
|
|
6
|
+
hint: string;
|
|
7
|
+
adjustmentCm: number;
|
|
8
|
+
}
|
|
9
|
+
export type ShoeSizeSystem = "US" | "UK" | "EU" | "JP";
|
|
10
|
+
export type ShoeGender = "male" | "female";
|
|
11
|
+
export interface ShoeSizeSystemOption {
|
|
12
|
+
value: ShoeSizeSystem;
|
|
13
|
+
label: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ShoeReferenceEstimate {
|
|
16
|
+
brandId: ShoeBrandId;
|
|
17
|
+
brandLabel: string;
|
|
18
|
+
selectedSize: string;
|
|
19
|
+
selectedSizeSystem: ShoeSizeSystem;
|
|
20
|
+
gender: ShoeGender;
|
|
21
|
+
shoeUS: string;
|
|
22
|
+
shoeUK: string;
|
|
23
|
+
shoeEU: string;
|
|
24
|
+
footLengthCm: number;
|
|
25
|
+
footLengthIn: number;
|
|
26
|
+
}
|
|
27
|
+
export declare const SHOE_BRANDS: ShoeBrandOption[];
|
|
28
|
+
export declare const SHOE_SIZE_SYSTEM_OPTIONS: ShoeSizeSystemOption[];
|
|
29
|
+
export declare function getDefaultShoeSizeSystem(country?: string): ShoeSizeSystem;
|
|
30
|
+
export declare function getShoeSizeOptions(system: ShoeSizeSystem): string[];
|
|
31
|
+
export declare function inferShoeGender(productTitle?: string, fallbackIsWomen?: boolean): ShoeGender;
|
|
32
|
+
export declare function formatShoeFootLength(footLengthCm: number, unit: "cm" | "in"): string;
|
|
33
|
+
export declare function estimateShoeReference(input: {
|
|
34
|
+
brandId: string;
|
|
35
|
+
size: string;
|
|
36
|
+
sizeSystem: ShoeSizeSystem;
|
|
37
|
+
productTitle?: string;
|
|
38
|
+
gender?: ShoeGender;
|
|
39
|
+
}): ShoeReferenceEstimate | null;
|
|
@@ -36,8 +36,10 @@ interface BasicsStepMobileProps {
|
|
|
36
36
|
* photo upload step when their saved profile already has everything we
|
|
37
37
|
* need to call /sizing/recommend. */
|
|
38
38
|
hidePhotoOptions?: boolean;
|
|
39
|
+
/** Accessories like bags only need height + weight, not age/body-shape questions. */
|
|
40
|
+
showAge?: boolean;
|
|
39
41
|
error: string;
|
|
40
42
|
t: TranslateFn;
|
|
41
43
|
}
|
|
42
|
-
export declare function BasicsStepMobile({ hUnit, wUnit, isImperialMode, height, setHeight, heightFeet, setHeightFeet, heightInches, setHeightInches, weight, setWeight, age, setAge, switchToMetric, switchToImperial, onUploadPhoto, onSwitchToScan, onNext, canProceed, fastPathLabel, activeProfileName, onStartFresh, hidePhotoOptions, error, t, }: BasicsStepMobileProps): import("react/jsx-runtime").JSX.Element;
|
|
44
|
+
export declare function BasicsStepMobile({ hUnit, wUnit, isImperialMode, height, setHeight, heightFeet, setHeightFeet, heightInches, setHeightInches, weight, setWeight, age, setAge, switchToMetric, switchToImperial, onUploadPhoto, onSwitchToScan, onNext, canProceed, fastPathLabel, activeProfileName, onStartFresh, hidePhotoOptions, showAge, error, t, }: BasicsStepMobileProps): import("react/jsx-runtime").JSX.Element;
|
|
43
45
|
export {};
|
|
@@ -4,6 +4,12 @@ interface BodyProfileViewProps {
|
|
|
4
4
|
productImage: string;
|
|
5
5
|
productTitle: string;
|
|
6
6
|
isWomen: boolean;
|
|
7
|
+
basicOnly?: boolean;
|
|
8
|
+
/** Optional entry step for recovery flows, such as falling back from an error to manual measurements. */
|
|
9
|
+
initialStep?: "photo" | "basics";
|
|
10
|
+
/** Use the default upload screen with only height/weight questions. */
|
|
11
|
+
simplePhotoOnly?: boolean;
|
|
12
|
+
simpleQuestionMode?: "heightWeight" | "shoeReference";
|
|
7
13
|
formRef: React.MutableRefObject<Record<string, string>>;
|
|
8
14
|
sizingCountry: string;
|
|
9
15
|
heightUnit: string;
|
|
@@ -23,11 +29,12 @@ interface BodyProfileViewProps {
|
|
|
23
29
|
gender: string;
|
|
24
30
|
age?: number;
|
|
25
31
|
chestProfile?: ChestProfile;
|
|
26
|
-
midsectionProfile
|
|
27
|
-
hipProfile
|
|
32
|
+
midsectionProfile?: MidsectionProfile;
|
|
33
|
+
hipProfile?: HipProfile;
|
|
28
34
|
bodyImage?: string;
|
|
29
35
|
bandSize?: string;
|
|
30
36
|
cupSize?: string;
|
|
37
|
+
braSizeRegion?: string;
|
|
31
38
|
}) => void;
|
|
32
39
|
onSnapSubmit: (data: {
|
|
33
40
|
photoFile: File;
|
|
@@ -43,6 +50,7 @@ interface BodyProfileViewProps {
|
|
|
43
50
|
cup: string;
|
|
44
51
|
region: string;
|
|
45
52
|
};
|
|
53
|
+
extraMeasurements?: Record<string, string | number>;
|
|
46
54
|
}) => void;
|
|
47
55
|
/** True if the user has an active profile with stored measurements —
|
|
48
56
|
* changes the basics step Next button to "Find My Best Fit" */
|
|
@@ -62,5 +70,5 @@ interface BodyProfileViewProps {
|
|
|
62
70
|
onBack: () => void;
|
|
63
71
|
t: TranslateFn;
|
|
64
72
|
}
|
|
65
|
-
export declare function BodyProfileView({ productImage, productTitle, isWomen, formRef, sizingCountry, heightUnit, setHeightUnit, weightUnit, setWeightUnit, sizingUnit, setSizingUnit, apiUrl, apiKey, onComplete, onSnapSubmit, hasActiveProfileWithMeasurements, onUseActiveProfile, activeProfileName, onStartFresh, activeProfile, onBack, t, }: BodyProfileViewProps): import("react/jsx-runtime").JSX.Element;
|
|
73
|
+
export declare function BodyProfileView({ productImage, productTitle, isWomen, basicOnly, initialStep, simplePhotoOnly, simpleQuestionMode, formRef, sizingCountry, heightUnit, setHeightUnit, weightUnit, setWeightUnit, sizingUnit, setSizingUnit, apiUrl, apiKey, onComplete, onSnapSubmit, hasActiveProfileWithMeasurements, onUseActiveProfile, activeProfileName, onStartFresh, activeProfile, onBack, t, }: BodyProfileViewProps): import("react/jsx-runtime").JSX.Element;
|
|
66
74
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TranslateFn } from "../../i18n";
|
|
2
|
-
import type { Profile } from "../types";
|
|
2
|
+
import type { Profile, ProfileCompletionDraft } from "../types";
|
|
3
3
|
/**
|
|
4
4
|
* Multi-step profile creation wizard.
|
|
5
5
|
*
|
|
@@ -36,6 +36,8 @@ import type { Profile } from "../types";
|
|
|
36
36
|
interface CreateProfileWizardProps {
|
|
37
37
|
onSave: (data: Omit<Profile, "id" | "createdAt">) => void;
|
|
38
38
|
onCancel: () => void;
|
|
39
|
+
initialMode?: "manual" | "image";
|
|
40
|
+
initialDraft?: ProfileCompletionDraft | null;
|
|
39
41
|
/** Backend URL + API key — required for the pre-upload age check call. */
|
|
40
42
|
apiUrl?: string;
|
|
41
43
|
apiKey?: string;
|
|
@@ -59,5 +61,5 @@ interface CreateProfileWizardProps {
|
|
|
59
61
|
} | null>;
|
|
60
62
|
t: TranslateFn;
|
|
61
63
|
}
|
|
62
|
-
export declare function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview, onEstimate, t }: CreateProfileWizardProps): import("react/jsx-runtime").JSX.Element;
|
|
64
|
+
export declare function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, apiUrl, apiKey, onPhotoPreview, onEstimate, t }: CreateProfileWizardProps): import("react/jsx-runtime").JSX.Element;
|
|
63
65
|
export {};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { PrimeStyleClassNames } from "../../types";
|
|
2
2
|
import type { TranslateFn } from "../../i18n";
|
|
3
|
-
export declare function ErrorView({
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
export declare function ErrorView({ productImage, productTitle, onManualMeasurements, cn, t, }: {
|
|
4
|
+
productImage?: string;
|
|
5
|
+
productTitle?: string;
|
|
6
|
+
onManualMeasurements: () => void;
|
|
6
7
|
cn: PrimeStyleClassNames;
|
|
7
8
|
t: TranslateFn;
|
|
8
9
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { TranslateFn } from "../../i18n";
|
|
2
|
+
import type { FaceLandmarks } from "../../face-detect";
|
|
2
3
|
import type { BodyLandmarks } from "../../pose-detect";
|
|
4
|
+
type MeasurementType = "body" | "face" | "head" | "foot" | "wrist";
|
|
3
5
|
interface MobileScanningViewProps {
|
|
4
6
|
/** User's photo URL for snap mode. Omit for text-mode sizing — the
|
|
5
7
|
* product image is shown instead and the MediaPipe skeleton overlay
|
|
@@ -8,6 +10,8 @@ interface MobileScanningViewProps {
|
|
|
8
10
|
/** Falls back to this image when previewUrl is not provided */
|
|
9
11
|
productImage?: string;
|
|
10
12
|
bodyLandmarks: BodyLandmarks | null | undefined;
|
|
13
|
+
faceLandmarks?: FaceLandmarks | null | undefined;
|
|
14
|
+
measurementType?: MeasurementType;
|
|
11
15
|
sizingDone: boolean;
|
|
12
16
|
/** True while VTO is running — swaps to the engaging try-on UI
|
|
13
17
|
* (progress ring + WHILE YOU WAIT cards) instead of the cycling
|
|
@@ -24,5 +28,5 @@ interface MobileScanningViewProps {
|
|
|
24
28
|
onSwitchToManual?: () => void;
|
|
25
29
|
t: TranslateFn;
|
|
26
30
|
}
|
|
27
|
-
export declare function MobileScanningView({ previewUrl, productImage, bodyLandmarks, sizingDone, tryOnProcessing, productMaterial, productDescription, onCancelTryOn, t, }: MobileScanningViewProps): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
export declare function MobileScanningView({ previewUrl, productImage, bodyLandmarks, faceLandmarks, measurementType, sizingDone, tryOnProcessing, productMaterial, productDescription, onCancelTryOn, t, }: MobileScanningViewProps): import("react/jsx-runtime").JSX.Element;
|
|
28
32
|
export {};
|
|
@@ -30,7 +30,7 @@ export interface MultiSectionMobileProps {
|
|
|
30
30
|
/** When set, the image area shows the try-on result instead of productImage. */
|
|
31
31
|
resultImageUrl?: string | null;
|
|
32
32
|
/** Try-on has finished and result is ready. Switches the bottom CTA into
|
|
33
|
-
* "Try Again" + "
|
|
33
|
+
* "Try Again" + "Done" mode. */
|
|
34
34
|
tryOnDone?: boolean;
|
|
35
35
|
/** Reset try-on state and reopen the photo guide for another attempt. */
|
|
36
36
|
onTryAgain?: () => void;
|
|
@@ -43,8 +43,13 @@ export interface MultiSectionMobileProps {
|
|
|
43
43
|
showLines?: boolean;
|
|
44
44
|
/** Toggle the mediapipe lines overlay. */
|
|
45
45
|
onToggleLines?: () => void;
|
|
46
|
+
/** Open the generated try-on image in the full-size preview. */
|
|
47
|
+
onOpenImage?: () => void;
|
|
48
|
+
/** Download the generated try-on image. */
|
|
49
|
+
onDownload?: () => void;
|
|
46
50
|
/** Bubble image natural dimensions up to the parent (for the overlay sizing). */
|
|
47
51
|
onImageLoad?: (e: React.SyntheticEvent<HTMLImageElement>) => void;
|
|
52
|
+
profileCompletionCta?: ReactNode;
|
|
48
53
|
t: TranslateFn;
|
|
49
54
|
}
|
|
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;
|
|
55
|
+
export declare function MultiSectionMobile({ productImage, productTitle, sizingResult, sizeGuide, sectionEntries, pendingCustomSizes, onSelectSection, onTryOn, tryOnProcessing, tryOnStartedAt, resultImageUrl, tryOnDone, onTryAgain, onClose, overlayNode, showLines, onToggleLines, onOpenImage, onDownload, onImageLoad, profileCompletionCta, t, }: MultiSectionMobileProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TranslateFn } from "../../i18n";
|
|
2
|
-
import type { Profile, ProfileMeasurements } from "../types";
|
|
2
|
+
import type { Profile, ProfileCompletionDraft, ProfileMeasurements } from "../types";
|
|
3
3
|
interface MySizingProfilesViewProps {
|
|
4
4
|
profiles: Profile[];
|
|
5
5
|
activeProfileId: string | null;
|
|
@@ -17,6 +17,9 @@ interface MySizingProfilesViewProps {
|
|
|
17
17
|
apiKey?: string;
|
|
18
18
|
/** Forwarded to CreateProfileWizard — called when a photo is selected or removed */
|
|
19
19
|
onPhotoPreview?: (base64: string | null) => void;
|
|
20
|
+
/** Draft saved from a size result before auth. Starts the photo profile flow after login. */
|
|
21
|
+
initialCreateDraft?: ProfileCompletionDraft | null;
|
|
22
|
+
onProfileDraftConsumed?: () => void;
|
|
20
23
|
/** Forwarded to CreateProfileWizard — called during image path to estimate measurements */
|
|
21
24
|
onEstimateFromPhoto?: (data: {
|
|
22
25
|
photoBase64: string;
|
|
@@ -44,5 +47,5 @@ export declare function DeleteConfirmModal({ onConfirm, onCancel, t, }: {
|
|
|
44
47
|
onCancel: () => void;
|
|
45
48
|
t: TranslateFn;
|
|
46
49
|
}): import("react/jsx-runtime").JSX.Element;
|
|
47
|
-
export declare function MySizingProfilesView({ profiles, activeProfileId, onSelectProfile, onEditProfile, onSaveNewProfile, onSaveProfileMeasurements, onSaveBraSize, onRequestDelete, onClose, apiUrl, apiKey, onPhotoPreview, onEstimateFromPhoto, estimatingProfileIds, t, onRegisterBackInterceptor, }: MySizingProfilesViewProps): import("react/jsx-runtime").JSX.Element;
|
|
50
|
+
export declare function MySizingProfilesView({ profiles, activeProfileId, onSelectProfile, onEditProfile, onSaveNewProfile, onSaveProfileMeasurements, onSaveBraSize, onRequestDelete, onClose, apiUrl, apiKey, onPhotoPreview, initialCreateDraft, onProfileDraftConsumed, onEstimateFromPhoto, estimatingProfileIds, t, onRegisterBackInterceptor, }: MySizingProfilesViewProps): import("react/jsx-runtime").JSX.Element;
|
|
48
51
|
export {};
|
|
@@ -8,7 +8,7 @@ import type { TranslateFn } from "../../i18n";
|
|
|
8
8
|
* Mobile: stacked — title + preview + checklist + START TRY-ON.
|
|
9
9
|
*/
|
|
10
10
|
export declare function PhotoGuideView({ measurementType, apiUrl, apiKey, onBack, onSubmit, t, }: {
|
|
11
|
-
measurementType?: "body" | "face" | "head" | "foot";
|
|
11
|
+
measurementType?: "body" | "face" | "head" | "foot" | "wrist";
|
|
12
12
|
/** Backend URL for the age-check call (passed through to PhotoUploadZone). */
|
|
13
13
|
apiUrl?: string;
|
|
14
14
|
apiKey?: string;
|
|
@@ -17,7 +17,9 @@ interface PhotoStepMobileProps {
|
|
|
17
17
|
photoStatus?: string;
|
|
18
18
|
photoRejection?: string | null;
|
|
19
19
|
onClearRejection?: () => void;
|
|
20
|
+
bodyContextSlot?: React.ReactNode;
|
|
21
|
+
hideTabs?: boolean;
|
|
20
22
|
t: TranslateFn;
|
|
21
23
|
}
|
|
22
|
-
export declare function PhotoStepMobile({ photoPreview, handlePhotoSelect, handleRemovePhoto, onAnalyze, onSwitchToManual, error, photoVariant, photoStepHeight, onPhotoStepHeightChange, ageConfirmed, onAgeConfirmedChange, primaryLabel, compactAgeGate, photoProcessing, photoStatus, photoRejection, onClearRejection, t, }: PhotoStepMobileProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export declare function PhotoStepMobile({ photoPreview, handlePhotoSelect, handleRemovePhoto, onAnalyze, onSwitchToManual, error, photoVariant, photoStepHeight, onPhotoStepHeightChange, ageConfirmed, onAgeConfirmedChange, primaryLabel, compactAgeGate, photoProcessing, photoStatus, photoRejection, onClearRejection, bodyContextSlot, hideTabs, t, }: PhotoStepMobileProps): import("react/jsx-runtime").JSX.Element;
|
|
23
25
|
export {};
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import type { TranslateFn } from "../../i18n";
|
|
2
|
+
export type ProductPhotoCarouselItem = {
|
|
3
|
+
image: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
href?: string;
|
|
6
|
+
};
|
|
2
7
|
/**
|
|
3
8
|
* Photo strip — shows PER_SLIDE images per row with even spacing, advances
|
|
4
9
|
* to the next group every CYCLE_MS, dot indicators below. Lives at the
|
|
5
10
|
* bottom of the single-garment right panel to entertain users while the
|
|
6
11
|
* try-on is generating.
|
|
7
12
|
*/
|
|
8
|
-
export declare function ProductPhotoCarouselCard({ photos, productTitle, t, }: {
|
|
9
|
-
photos
|
|
13
|
+
export declare function ProductPhotoCarouselCard({ photos, items, productTitle, t, }: {
|
|
14
|
+
photos?: string[];
|
|
15
|
+
items?: ProductPhotoCarouselItem[];
|
|
10
16
|
productTitle?: string;
|
|
11
17
|
t: TranslateFn;
|
|
12
18
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { TranslateFn } from "../../i18n";
|
|
2
2
|
import type { ViewState, SizeGuide, SizingResult } from "../types";
|
|
3
3
|
import type { BodyLandmarks } from "../../pose-detect";
|
|
4
|
-
|
|
4
|
+
import { type ProductPhotoCarouselItem } from "./ProductPhotoCarouselCard";
|
|
5
|
+
export declare function SizeResultView({ sizingLoading, sizingResult, sizeGuide, resultImageUrl, productImage, productImages, productCarouselItems, productTitle, productMaterial, productDescription, sizingUnit, setView, handleDownload, selectedFile, previewUrl, handleFileSelect, handleRemovePreview, handleTryOnSubmit, tryOnProcessing, tryOnStartedAt, bodyLandmarks, faceLandmarks, measurementType, estimationDone, activeSection, setActiveSection, onResetTryOn, onClose, userHeightCm, pendingCustomSizes: pendingCustomSizesProp, onPendingCustomSizeChange, tryOnAvailable, showProfileCompletionCta, onProfileCompletionCta, portalContainer, t, }: {
|
|
5
6
|
estimationDone?: boolean;
|
|
6
7
|
sizingLoading: boolean;
|
|
7
8
|
sizingResult: SizingResult | null;
|
|
@@ -12,6 +13,8 @@ export declare function SizeResultView({ sizingLoading, sizingResult, sizeGuide,
|
|
|
12
13
|
* auto-cycling carousel card on the single-garment desktop layout while
|
|
13
14
|
* try-on is processing. */
|
|
14
15
|
productImages?: string[];
|
|
16
|
+
/** Preferred carousel items, typically complete-the-look products. */
|
|
17
|
+
productCarouselItems?: ProductPhotoCarouselItem[];
|
|
15
18
|
productTitle: string;
|
|
16
19
|
/** Garment material/fabric — feeds the "Garment Spotlight" card on
|
|
17
20
|
* the engaging try-on processing UI. */
|
|
@@ -32,7 +35,7 @@ export declare function SizeResultView({ sizingLoading, sizingResult, sizeGuide,
|
|
|
32
35
|
tryOnStartedAt?: number | null;
|
|
33
36
|
bodyLandmarks?: BodyLandmarks | null;
|
|
34
37
|
faceLandmarks?: import("../../face-detect").FaceLandmarks | null;
|
|
35
|
-
measurementType?: "body" | "face" | "head" | "foot";
|
|
38
|
+
measurementType?: "body" | "face" | "head" | "foot" | "wrist";
|
|
36
39
|
activeSection: string | null;
|
|
37
40
|
setActiveSection: (s: string | null) => void;
|
|
38
41
|
/** Clear try-on result + uploaded photo so the user can retry from the photo guide. */
|
|
@@ -74,5 +77,8 @@ export declare function SizeResultView({ sizingLoading, sizingResult, sizeGuide,
|
|
|
74
77
|
* shows "Continue Shopping" instead. Set to false when sizing came in
|
|
75
78
|
* via the manual measurements path (no photo collected upstream). */
|
|
76
79
|
tryOnAvailable?: boolean;
|
|
80
|
+
showProfileCompletionCta?: boolean;
|
|
81
|
+
onProfileCompletionCta?: () => void;
|
|
82
|
+
portalContainer?: Element | DocumentFragment;
|
|
77
83
|
t: TranslateFn;
|
|
78
84
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TranslateFn } from "../../i18n";
|
|
2
|
+
import type { SocialProvider } from "../utils/profile-auth";
|
|
3
|
+
interface SocialProfileAuthViewProps {
|
|
4
|
+
loadingProvider: SocialProvider | null;
|
|
5
|
+
error: string | null;
|
|
6
|
+
onLogin: (provider: SocialProvider) => void;
|
|
7
|
+
t: TranslateFn;
|
|
8
|
+
}
|
|
9
|
+
export declare function SocialProfileAuthView({ loadingProvider, error, onLogin, t }: SocialProfileAuthViewProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TranslateFn } from "../../i18n";
|
|
2
|
+
import type { ViewState, SizeGuide } from "../types";
|
|
3
|
+
export declare function WristSizeView(props: {
|
|
4
|
+
productImage: string;
|
|
5
|
+
productTitle: string;
|
|
6
|
+
formRef: React.MutableRefObject<Record<string, string>>;
|
|
7
|
+
sizingUnit: string;
|
|
8
|
+
setSizingUnit: (u: string) => void;
|
|
9
|
+
setSizingMethod: (m: "exact" | "quick" | null) => void;
|
|
10
|
+
setSizingLoading: (v: boolean) => void;
|
|
11
|
+
setView: (v: ViewState) => void;
|
|
12
|
+
submitSizing: (mode: "exact" | "quick") => void;
|
|
13
|
+
onSnapSubmit: (data: {
|
|
14
|
+
photoFile: File;
|
|
15
|
+
photoBase64: string;
|
|
16
|
+
height: number;
|
|
17
|
+
weight: number;
|
|
18
|
+
heightUnit: string;
|
|
19
|
+
weightUnit: string;
|
|
20
|
+
gender: string;
|
|
21
|
+
age?: number;
|
|
22
|
+
}) => void;
|
|
23
|
+
onBack: () => void;
|
|
24
|
+
apiUrl?: string;
|
|
25
|
+
apiKey?: string;
|
|
26
|
+
sizeGuide?: SizeGuide | null;
|
|
27
|
+
t: TranslateFn;
|
|
28
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -40,6 +40,8 @@ export declare function buildSilhouetteContext(sizingResult: {
|
|
|
40
40
|
userValue: string;
|
|
41
41
|
chartRange: string;
|
|
42
42
|
}>;
|
|
43
|
+
/** Backend-formatted matched row text, e.g. "Chest (in) 40, Chest (cm) 102". Single-section. */
|
|
44
|
+
matchedRowText?: string;
|
|
43
45
|
sections?: Record<string, {
|
|
44
46
|
recommendedSize?: string;
|
|
45
47
|
matchDetails?: Array<{
|
|
@@ -47,10 +49,16 @@ export declare function buildSilhouetteContext(sizingResult: {
|
|
|
47
49
|
userValue: string;
|
|
48
50
|
chartRange: string;
|
|
49
51
|
}>;
|
|
52
|
+
/** Backend-formatted matched row text for this section. */
|
|
53
|
+
matchedRowText?: string;
|
|
50
54
|
}>;
|
|
51
55
|
} | null | undefined, sizeGuide: {
|
|
52
56
|
headers?: string[];
|
|
53
57
|
rows?: string[][];
|
|
58
|
+
sections?: Record<string, {
|
|
59
|
+
headers: string[];
|
|
60
|
+
rows: string[][];
|
|
61
|
+
}>;
|
|
54
62
|
} | null | undefined,
|
|
55
63
|
/** Optional override — when the user manually picks a different size in
|
|
56
64
|
* the result view and hits "Apply this size", we want Gemini to reason
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shopify cart attribution hook.
|
|
3
3
|
*
|
|
4
|
-
* Intercepts the storefront's Ajax cart API (`/cart/add.js`,
|
|
5
|
-
* `/cart/add
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Intercepts the storefront's Ajax cart-add API (`/cart/add.js`,
|
|
5
|
+
* `/cart/add`) and stamps every request with
|
|
6
|
+
* `attributes[ps_session]: <sessionId>`. Shopify exposes cart
|
|
7
|
+
* attributes as order note attributes, so when the
|
|
8
8
|
* `orders/create` webhook fires we can match the purchase back to the
|
|
9
9
|
* customer's try-on session on our backend.
|
|
10
10
|
*
|
|
@@ -15,3 +15,9 @@ export declare function logSizeAccepted(input: {
|
|
|
15
15
|
size?: string;
|
|
16
16
|
recommendedSize?: string;
|
|
17
17
|
}): void;
|
|
18
|
+
export declare function logSizeShown(input: {
|
|
19
|
+
productId?: string;
|
|
20
|
+
productTitle?: string;
|
|
21
|
+
recommendedSize?: string;
|
|
22
|
+
fromCache?: boolean;
|
|
23
|
+
}): void;
|