@primestyleai/tryon 3.4.2 → 3.5.1
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/README.md +433 -433
- package/dist/react/index.js +254 -75
- package/logo.svg +46 -46
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,433 +1,433 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<a href="https://myaifitting.com">
|
|
3
|
-
<img src="https://cdn.jsdelivr.net/npm/@primestyleai/tryon/logo.svg" alt="PrimeStyle AI" width="180" />
|
|
4
|
-
</a>
|
|
5
|
-
</p>
|
|
6
|
-
|
|
7
|
-
<h1 align="center">@primestyleai/tryon</h1>
|
|
8
|
-
|
|
9
|
-
<p align="center">
|
|
10
|
-
<strong>AI-Powered Virtual Try-On for React & Next.js</strong>
|
|
11
|
-
</p>
|
|
12
|
-
|
|
13
|
-
<p align="center">
|
|
14
|
-
Add a virtual try-on button to your product pages in 3 steps. Customers upload a photo and see how clothes look on them — powered by PrimeStyle AI.
|
|
15
|
-
</p>
|
|
16
|
-
|
|
17
|
-
<p align="center">
|
|
18
|
-
<a href="https://www.npmjs.com/package/@primestyleai/tryon"><img src="https://img.shields.io/npm/v/@primestyleai/tryon?color=D6BA7D&label=npm" alt="npm version" /></a>
|
|
19
|
-
<a href="https://www.npmjs.com/package/@primestyleai/tryon"><img src="https://img.shields.io/npm/dm/@primestyleai/tryon?color=D6BA7D" alt="npm downloads" /></a>
|
|
20
|
-
<a href="https://github.com/primestyleai/tryon-sdk/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@primestyleai/tryon?color=D6BA7D" alt="license" /></a>
|
|
21
|
-
<img src="https://img.shields.io/badge/gzip-5.5kB-green" alt="bundle size" />
|
|
22
|
-
</p>
|
|
23
|
-
|
|
24
|
-
<p align="center">
|
|
25
|
-
<a href="https://myaifitting.com/developer/demo">Live Demo</a> •
|
|
26
|
-
<a href="https://myaifitting.com/docs">Documentation</a> •
|
|
27
|
-
<a href="https://myaifitting.com/developer/dashboard/keys">Get API Key</a> •
|
|
28
|
-
<a href="https://myaifitting.com/pricing">Pricing</a>
|
|
29
|
-
</p>
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## How It Works
|
|
34
|
-
|
|
35
|
-
1. Customer clicks the **"Virtual Try-On"** button on your product page
|
|
36
|
-
2. They upload a photo of themselves
|
|
37
|
-
3. PrimeStyle AI generates a realistic try-on image in ~15 seconds
|
|
38
|
-
4. Customer sees how the garment looks on them before buying
|
|
39
|
-
|
|
40
|
-
The entire flow happens inside a beautiful modal — no redirects, no iframes.
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## Quick Start
|
|
45
|
-
|
|
46
|
-
### 1. Install
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
npm install @primestyleai/tryon
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### 2. Set Your API Key
|
|
53
|
-
|
|
54
|
-
Get your key from the [Developer Dashboard](https://myaifitting.com/developer/dashboard/keys) and add it to your `.env.local`:
|
|
55
|
-
|
|
56
|
-
```env
|
|
57
|
-
NEXT_PUBLIC_PRIMESTYLE_API_KEY=ps_live_your_key_here
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### 3. Use the Component
|
|
61
|
-
|
|
62
|
-
```jsx
|
|
63
|
-
import { PrimeStyleTryon } from '@primestyleai/tryon/react';
|
|
64
|
-
|
|
65
|
-
function ProductPage({ product }) {
|
|
66
|
-
return (
|
|
67
|
-
<div>
|
|
68
|
-
<h1>{product.name}</h1>
|
|
69
|
-
<img src={product.image} alt={product.name} />
|
|
70
|
-
|
|
71
|
-
<PrimeStyleTryon
|
|
72
|
-
productImage={product.image}
|
|
73
|
-
buttonText="Try It On"
|
|
74
|
-
/>
|
|
75
|
-
</div>
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
That's it. No API key prop needed — the component reads it from your environment automatically.
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## Props
|
|
85
|
-
|
|
86
|
-
| Prop | Type | Default | Description |
|
|
87
|
-
|------|------|---------|-------------|
|
|
88
|
-
| `productImage` | `string` | **required** | URL of the garment image |
|
|
89
|
-
| `buttonText` | `string` | `"Virtual Try-On"` | Text on the trigger button |
|
|
90
|
-
| `apiUrl` | `string` | `NEXT_PUBLIC_PRIMESTYLE_API_URL` or production | API endpoint override |
|
|
91
|
-
| `showPoweredBy` | `boolean` | `true` | Show "Powered by PrimeStyle AI" in modal |
|
|
92
|
-
| `buttonStyles` | `ButtonStyles` | `{}` | Customize button via style props |
|
|
93
|
-
| `modalStyles` | `ModalStyles` | `{}` | Customize modal via style props |
|
|
94
|
-
| `classNames` | `PrimeStyleClassNames` | `{}` | Override element classes (Tailwind, CSS) |
|
|
95
|
-
| `className` | `string` | — | Additional CSS class on wrapper |
|
|
96
|
-
| `style` | `CSSProperties` | — | Inline styles on wrapper |
|
|
97
|
-
| `onOpen` | `() => void` | — | Modal opened |
|
|
98
|
-
| `onClose` | `() => void` | — | Modal closed |
|
|
99
|
-
| `onUpload` | `(file: File) => void` | — | User uploaded a photo |
|
|
100
|
-
| `onProcessing` | `(jobId: string) => void` | — | Try-on generation started |
|
|
101
|
-
| `onComplete` | `(result) => void` | — | Result ready: `{ jobId, imageUrl }` |
|
|
102
|
-
| `onError` | `(error) => void` | — | Error occurred: `{ message, code? }` |
|
|
103
|
-
|
|
104
|
-
---
|
|
105
|
-
|
|
106
|
-
## Customization
|
|
107
|
-
|
|
108
|
-
### Button Styles
|
|
109
|
-
|
|
110
|
-
```jsx
|
|
111
|
-
<PrimeStyleTryon
|
|
112
|
-
productImage={product.image}
|
|
113
|
-
buttonStyles={{
|
|
114
|
-
backgroundColor: '#000000',
|
|
115
|
-
textColor: '#ffffff',
|
|
116
|
-
borderRadius: '50px',
|
|
117
|
-
padding: '16px 32px',
|
|
118
|
-
fontSize: '16px',
|
|
119
|
-
fontWeight: '700',
|
|
120
|
-
width: '100%',
|
|
121
|
-
border: '2px solid #333',
|
|
122
|
-
hoverBackgroundColor: '#222',
|
|
123
|
-
iconSize: '20px',
|
|
124
|
-
boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
|
|
125
|
-
}}
|
|
126
|
-
/>
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
**All ButtonStyles properties:**
|
|
130
|
-
|
|
131
|
-
| Property | Description |
|
|
132
|
-
|----------|-------------|
|
|
133
|
-
| `backgroundColor` | Button background color |
|
|
134
|
-
| `textColor` | Button text color |
|
|
135
|
-
| `borderRadius` | Corner rounding |
|
|
136
|
-
| `fontSize` | Text size |
|
|
137
|
-
| `fontFamily` | Font stack |
|
|
138
|
-
| `fontWeight` | Font weight |
|
|
139
|
-
| `padding` | Inner spacing |
|
|
140
|
-
| `border` | Border style |
|
|
141
|
-
| `width` | Button width (e.g. `"100%"`) |
|
|
142
|
-
| `height` | Button height |
|
|
143
|
-
| `hoverBackgroundColor` | Background on hover |
|
|
144
|
-
| `hoverTextColor` | Text color on hover |
|
|
145
|
-
| `iconSize` | Camera icon size |
|
|
146
|
-
| `iconColor` | Camera icon color |
|
|
147
|
-
| `boxShadow` | Shadow effect |
|
|
148
|
-
|
|
149
|
-
### Modal Styles
|
|
150
|
-
|
|
151
|
-
```jsx
|
|
152
|
-
<PrimeStyleTryon
|
|
153
|
-
productImage={product.image}
|
|
154
|
-
modalStyles={{
|
|
155
|
-
backgroundColor: '#ffffff',
|
|
156
|
-
textColor: '#111111',
|
|
157
|
-
overlayColor: 'rgba(0,0,0,0.7)',
|
|
158
|
-
borderRadius: '16px',
|
|
159
|
-
maxWidth: '520px',
|
|
160
|
-
headerBackgroundColor: '#f5f5f5',
|
|
161
|
-
headerTextColor: '#111111',
|
|
162
|
-
primaryButtonBackgroundColor: '#000000',
|
|
163
|
-
primaryButtonTextColor: '#ffffff',
|
|
164
|
-
loaderColor: '#000000',
|
|
165
|
-
}}
|
|
166
|
-
/>
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
**All ModalStyles properties:**
|
|
170
|
-
|
|
171
|
-
| Property | Description |
|
|
172
|
-
|----------|-------------|
|
|
173
|
-
| `overlayColor` | Background overlay color |
|
|
174
|
-
| `backgroundColor` | Modal background |
|
|
175
|
-
| `textColor` | Modal text color |
|
|
176
|
-
| `borderRadius` | Modal corner rounding |
|
|
177
|
-
| `width` / `maxWidth` | Modal dimensions |
|
|
178
|
-
| `fontFamily` | Modal font stack |
|
|
179
|
-
| `headerBackgroundColor` | Header section background |
|
|
180
|
-
| `headerTextColor` | Header title color |
|
|
181
|
-
| `closeButtonColor` | Close (X) button color |
|
|
182
|
-
| `uploadBorderColor` | Upload drop zone border |
|
|
183
|
-
| `uploadBackgroundColor` | Upload zone background |
|
|
184
|
-
| `uploadTextColor` | Upload zone text |
|
|
185
|
-
| `uploadIconColor` | Upload icon color |
|
|
186
|
-
| `primaryButtonBackgroundColor` | Submit / download button background |
|
|
187
|
-
| `primaryButtonTextColor` | Submit / download button text |
|
|
188
|
-
| `primaryButtonBorderRadius` | Submit button rounding |
|
|
189
|
-
| `loaderColor` | Loading spinner color |
|
|
190
|
-
| `resultBorderRadius` | Result image corner rounding |
|
|
191
|
-
|
|
192
|
-
### Tailwind CSS / Custom Classes
|
|
193
|
-
|
|
194
|
-
Use the `classNames` prop to style any element with Tailwind utilities or your own CSS classes:
|
|
195
|
-
|
|
196
|
-
```jsx
|
|
197
|
-
<PrimeStyleTryon
|
|
198
|
-
productImage={product.image}
|
|
199
|
-
classNames={{
|
|
200
|
-
button: "bg-black text-white rounded-full px-8 py-4 hover:bg-gray-800",
|
|
201
|
-
modal: "bg-white rounded-2xl shadow-2xl",
|
|
202
|
-
header: "bg-gray-50 border-b border-gray-200",
|
|
203
|
-
title: "text-gray-900 text-lg",
|
|
204
|
-
closeButton: "text-gray-400 hover:text-gray-600",
|
|
205
|
-
body: "p-6",
|
|
206
|
-
uploadZone: "border-2 border-dashed border-gray-300 rounded-xl p-10 hover:border-blue-400",
|
|
207
|
-
uploadText: "text-gray-700",
|
|
208
|
-
submitButton: "bg-blue-600 text-white rounded-lg hover:bg-blue-700",
|
|
209
|
-
downloadButton: "bg-green-600 text-white rounded-lg",
|
|
210
|
-
retryButton: "bg-gray-100 text-gray-700 border border-gray-300",
|
|
211
|
-
}}
|
|
212
|
-
/>
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
**All classNames keys:**
|
|
216
|
-
|
|
217
|
-
| Key | Element |
|
|
218
|
-
|-----|---------|
|
|
219
|
-
| `root` | Root wrapper `<div>` |
|
|
220
|
-
| `button` | Trigger button |
|
|
221
|
-
| `overlay` | Modal backdrop overlay |
|
|
222
|
-
| `modal` | Modal container |
|
|
223
|
-
| `header` | Modal header bar |
|
|
224
|
-
| `title` | Modal title text |
|
|
225
|
-
| `closeButton` | Close (X) button |
|
|
226
|
-
| `body` | Modal body area |
|
|
227
|
-
| `uploadZone` | Upload drop zone |
|
|
228
|
-
| `uploadText` | "Drop your photo..." text |
|
|
229
|
-
| `uploadHint` | File type hint text |
|
|
230
|
-
| `preview` | Preview image container |
|
|
231
|
-
| `previewImage` | Preview `<img>` element |
|
|
232
|
-
| `removeButton` | Remove preview button |
|
|
233
|
-
| `submitButton` | "Try It On" / "Try Again" button |
|
|
234
|
-
| `spinner` | Loading spinner |
|
|
235
|
-
| `processingText` | "Generating..." text |
|
|
236
|
-
| `processingSubText` | "This usually takes..." text |
|
|
237
|
-
| `result` | Result container |
|
|
238
|
-
| `resultImage` | Result `<img>` element |
|
|
239
|
-
| `resultActions` | Download/retry button row |
|
|
240
|
-
| `downloadButton` | Download button |
|
|
241
|
-
| `retryButton` | "Try Another" button |
|
|
242
|
-
| `error` | Error container |
|
|
243
|
-
| `errorText` | Error message text |
|
|
244
|
-
| `poweredBy` | Footer text |
|
|
245
|
-
|
|
246
|
-
### Normal CSS
|
|
247
|
-
|
|
248
|
-
All elements use `ps-tryon-*` class names that you can target directly in your CSS:
|
|
249
|
-
|
|
250
|
-
```css
|
|
251
|
-
/* Override the trigger button */
|
|
252
|
-
.ps-tryon-btn {
|
|
253
|
-
background: #000;
|
|
254
|
-
color: #fff;
|
|
255
|
-
border-radius: 50px;
|
|
256
|
-
padding: 16px 32px;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/* Override the modal */
|
|
260
|
-
.ps-tryon-modal {
|
|
261
|
-
background: #fff;
|
|
262
|
-
color: #111;
|
|
263
|
-
border-radius: 16px;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/* Override the submit button */
|
|
267
|
-
.ps-tryon-submit {
|
|
268
|
-
background: #2563eb;
|
|
269
|
-
color: #fff;
|
|
270
|
-
}
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
### Combining Approaches
|
|
274
|
-
|
|
275
|
-
You can mix all three styling methods — they layer on top of each other:
|
|
276
|
-
|
|
277
|
-
```jsx
|
|
278
|
-
<PrimeStyleTryon
|
|
279
|
-
productImage={product.image}
|
|
280
|
-
// 1. Style props (CSS variables)
|
|
281
|
-
buttonStyles={{ width: '100%' }}
|
|
282
|
-
// 2. Tailwind classes
|
|
283
|
-
classNames={{ button: "rounded-full font-bold" }}
|
|
284
|
-
// 3. Normal CSS targets .ps-tryon-btn automatically
|
|
285
|
-
/>
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
Priority: Tailwind/classNames classes > CSS variables (buttonStyles/modalStyles) > default styles.
|
|
289
|
-
|
|
290
|
-
---
|
|
291
|
-
|
|
292
|
-
## Callbacks
|
|
293
|
-
|
|
294
|
-
```jsx
|
|
295
|
-
<PrimeStyleTryon
|
|
296
|
-
productImage={product.image}
|
|
297
|
-
onOpen={() => {
|
|
298
|
-
analytics.track('tryon_opened');
|
|
299
|
-
}}
|
|
300
|
-
onUpload={(file) => {
|
|
301
|
-
console.log('Photo uploaded:', file.name);
|
|
302
|
-
}}
|
|
303
|
-
onProcessing={(jobId) => {
|
|
304
|
-
console.log('Processing:', jobId);
|
|
305
|
-
}}
|
|
306
|
-
onComplete={(result) => {
|
|
307
|
-
console.log('Result ready:', result.imageUrl);
|
|
308
|
-
analytics.track('tryon_completed', { jobId: result.jobId });
|
|
309
|
-
}}
|
|
310
|
-
onError={(error) => {
|
|
311
|
-
console.error('Try-on failed:', error.message);
|
|
312
|
-
// error.code: 'INSUFFICIENT_TOKENS' | 'API_ERROR' | etc.
|
|
313
|
-
}}
|
|
314
|
-
onClose={() => {
|
|
315
|
-
console.log('Modal closed');
|
|
316
|
-
}}
|
|
317
|
-
/>
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
---
|
|
321
|
-
|
|
322
|
-
## Environment Variables
|
|
323
|
-
|
|
324
|
-
| Variable | Required | Default | Description |
|
|
325
|
-
|----------|----------|---------|-------------|
|
|
326
|
-
| `NEXT_PUBLIC_PRIMESTYLE_API_KEY` | Yes | — | Your PrimeStyle API key |
|
|
327
|
-
| `NEXT_PUBLIC_PRIMESTYLE_API_URL` | No | `https://myaifitting.com` | Custom API endpoint |
|
|
328
|
-
|
|
329
|
-
The component reads these automatically — no need to pass them as props.
|
|
330
|
-
|
|
331
|
-
---
|
|
332
|
-
|
|
333
|
-
## Tokens & Pricing
|
|
334
|
-
|
|
335
|
-
Each virtual try-on consumes **tokens** from your account balance.
|
|
336
|
-
|
|
337
|
-
| | |
|
|
338
|
-
|---|---|
|
|
339
|
-
| **Free trial** | Tokens included on signup |
|
|
340
|
-
| **Token packs** | Pay-as-you-go, never expire |
|
|
341
|
-
| **Monthly plans** | Volume discounts for high-traffic stores |
|
|
342
|
-
|
|
343
|
-
Manage your balance and purchase tokens at [primestyleai.com/developer/dashboard/billing](https://myaifitting.com/developer/dashboard/billing).
|
|
344
|
-
|
|
345
|
-
If a try-on fails, tokens are **automatically refunded** to your account.
|
|
346
|
-
|
|
347
|
-
The `onComplete` callback includes token info:
|
|
348
|
-
|
|
349
|
-
```jsx
|
|
350
|
-
onComplete={(result) => {
|
|
351
|
-
// result.jobId — the job ID
|
|
352
|
-
// result.imageUrl — the result image URL
|
|
353
|
-
}}
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
---
|
|
357
|
-
|
|
358
|
-
## API Key Management
|
|
359
|
-
|
|
360
|
-
Create and manage your API keys at the [Developer Dashboard](https://myaifitting.com/developer/dashboard/keys).
|
|
361
|
-
|
|
362
|
-
- Keys start with `ps_live_` and are shown **once** at creation
|
|
363
|
-
- Set **allowed domains** to restrict where your key can be used
|
|
364
|
-
- **Revoke** keys instantly if compromised
|
|
365
|
-
- Maximum 10 active keys per account
|
|
366
|
-
|
|
367
|
-
---
|
|
368
|
-
|
|
369
|
-
## Full Example
|
|
370
|
-
|
|
371
|
-
```jsx
|
|
372
|
-
// app/product/[id]/page.tsx (Next.js App Router)
|
|
373
|
-
|
|
374
|
-
import { PrimeStyleTryon } from '@primestyleai/tryon/react';
|
|
375
|
-
|
|
376
|
-
export default function ProductPage({ product }) {
|
|
377
|
-
return (
|
|
378
|
-
<div className="product-page">
|
|
379
|
-
<div className="product-gallery">
|
|
380
|
-
<img src={product.image} alt={product.name} />
|
|
381
|
-
</div>
|
|
382
|
-
|
|
383
|
-
<div className="product-info">
|
|
384
|
-
<h1>{product.name}</h1>
|
|
385
|
-
<p className="price">${product.price}</p>
|
|
386
|
-
|
|
387
|
-
{/* Virtual Try-On — reads API key from env */}
|
|
388
|
-
<PrimeStyleTryon
|
|
389
|
-
productImage={product.image}
|
|
390
|
-
buttonText="Try It On"
|
|
391
|
-
buttonStyles={{
|
|
392
|
-
width: '100%',
|
|
393
|
-
padding: '14px 24px',
|
|
394
|
-
borderRadius: '10px',
|
|
395
|
-
fontSize: '15px',
|
|
396
|
-
}}
|
|
397
|
-
onComplete={(result) => {
|
|
398
|
-
// Show success toast, track analytics, etc.
|
|
399
|
-
toast.success('Your try-on is ready!');
|
|
400
|
-
}}
|
|
401
|
-
onError={(error) => {
|
|
402
|
-
toast.error(error.message);
|
|
403
|
-
}}
|
|
404
|
-
/>
|
|
405
|
-
|
|
406
|
-
<button className="add-to-cart">Add to Cart</button>
|
|
407
|
-
</div>
|
|
408
|
-
</div>
|
|
409
|
-
);
|
|
410
|
-
}
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
---
|
|
414
|
-
|
|
415
|
-
## Requirements
|
|
416
|
-
|
|
417
|
-
- React 18+
|
|
418
|
-
- Next.js 13+ (App Router or Pages Router)
|
|
419
|
-
|
|
420
|
-
---
|
|
421
|
-
|
|
422
|
-
## Need Help?
|
|
423
|
-
|
|
424
|
-
- [Live Demo](https://myaifitting.com/developer/demo) — See it in action
|
|
425
|
-
- [Documentation](https://myaifitting.com/docs) — Full API reference
|
|
426
|
-
- [Dashboard](https://myaifitting.com/developer/dashboard/keys) — Manage keys & tokens
|
|
427
|
-
- [Contact](mailto:support@primestyleai.com) — We're here to help
|
|
428
|
-
|
|
429
|
-
---
|
|
430
|
-
|
|
431
|
-
<p align="center">
|
|
432
|
-
Built with care by <a href="https://myaifitting.com">PrimeStyle AI</a>
|
|
433
|
-
</p>
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://myaifitting.com">
|
|
3
|
+
<img src="https://cdn.jsdelivr.net/npm/@primestyleai/tryon/logo.svg" alt="PrimeStyle AI" width="180" />
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<h1 align="center">@primestyleai/tryon</h1>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<strong>AI-Powered Virtual Try-On for React & Next.js</strong>
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
Add a virtual try-on button to your product pages in 3 steps. Customers upload a photo and see how clothes look on them — powered by PrimeStyle AI.
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<a href="https://www.npmjs.com/package/@primestyleai/tryon"><img src="https://img.shields.io/npm/v/@primestyleai/tryon?color=D6BA7D&label=npm" alt="npm version" /></a>
|
|
19
|
+
<a href="https://www.npmjs.com/package/@primestyleai/tryon"><img src="https://img.shields.io/npm/dm/@primestyleai/tryon?color=D6BA7D" alt="npm downloads" /></a>
|
|
20
|
+
<a href="https://github.com/primestyleai/tryon-sdk/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@primestyleai/tryon?color=D6BA7D" alt="license" /></a>
|
|
21
|
+
<img src="https://img.shields.io/badge/gzip-5.5kB-green" alt="bundle size" />
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
<p align="center">
|
|
25
|
+
<a href="https://myaifitting.com/developer/demo">Live Demo</a> •
|
|
26
|
+
<a href="https://myaifitting.com/docs">Documentation</a> •
|
|
27
|
+
<a href="https://myaifitting.com/developer/dashboard/keys">Get API Key</a> •
|
|
28
|
+
<a href="https://myaifitting.com/pricing">Pricing</a>
|
|
29
|
+
</p>
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## How It Works
|
|
34
|
+
|
|
35
|
+
1. Customer clicks the **"Virtual Try-On"** button on your product page
|
|
36
|
+
2. They upload a photo of themselves
|
|
37
|
+
3. PrimeStyle AI generates a realistic try-on image in ~15 seconds
|
|
38
|
+
4. Customer sees how the garment looks on them before buying
|
|
39
|
+
|
|
40
|
+
The entire flow happens inside a beautiful modal — no redirects, no iframes.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
### 1. Install
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install @primestyleai/tryon
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Set Your API Key
|
|
53
|
+
|
|
54
|
+
Get your key from the [Developer Dashboard](https://myaifitting.com/developer/dashboard/keys) and add it to your `.env.local`:
|
|
55
|
+
|
|
56
|
+
```env
|
|
57
|
+
NEXT_PUBLIC_PRIMESTYLE_API_KEY=ps_live_your_key_here
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 3. Use the Component
|
|
61
|
+
|
|
62
|
+
```jsx
|
|
63
|
+
import { PrimeStyleTryon } from '@primestyleai/tryon/react';
|
|
64
|
+
|
|
65
|
+
function ProductPage({ product }) {
|
|
66
|
+
return (
|
|
67
|
+
<div>
|
|
68
|
+
<h1>{product.name}</h1>
|
|
69
|
+
<img src={product.image} alt={product.name} />
|
|
70
|
+
|
|
71
|
+
<PrimeStyleTryon
|
|
72
|
+
productImage={product.image}
|
|
73
|
+
buttonText="Try It On"
|
|
74
|
+
/>
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
That's it. No API key prop needed — the component reads it from your environment automatically.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Props
|
|
85
|
+
|
|
86
|
+
| Prop | Type | Default | Description |
|
|
87
|
+
|------|------|---------|-------------|
|
|
88
|
+
| `productImage` | `string` | **required** | URL of the garment image |
|
|
89
|
+
| `buttonText` | `string` | `"Virtual Try-On"` | Text on the trigger button |
|
|
90
|
+
| `apiUrl` | `string` | `NEXT_PUBLIC_PRIMESTYLE_API_URL` or production | API endpoint override |
|
|
91
|
+
| `showPoweredBy` | `boolean` | `true` | Show "Powered by PrimeStyle AI" in modal |
|
|
92
|
+
| `buttonStyles` | `ButtonStyles` | `{}` | Customize button via style props |
|
|
93
|
+
| `modalStyles` | `ModalStyles` | `{}` | Customize modal via style props |
|
|
94
|
+
| `classNames` | `PrimeStyleClassNames` | `{}` | Override element classes (Tailwind, CSS) |
|
|
95
|
+
| `className` | `string` | — | Additional CSS class on wrapper |
|
|
96
|
+
| `style` | `CSSProperties` | — | Inline styles on wrapper |
|
|
97
|
+
| `onOpen` | `() => void` | — | Modal opened |
|
|
98
|
+
| `onClose` | `() => void` | — | Modal closed |
|
|
99
|
+
| `onUpload` | `(file: File) => void` | — | User uploaded a photo |
|
|
100
|
+
| `onProcessing` | `(jobId: string) => void` | — | Try-on generation started |
|
|
101
|
+
| `onComplete` | `(result) => void` | — | Result ready: `{ jobId, imageUrl }` |
|
|
102
|
+
| `onError` | `(error) => void` | — | Error occurred: `{ message, code? }` |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Customization
|
|
107
|
+
|
|
108
|
+
### Button Styles
|
|
109
|
+
|
|
110
|
+
```jsx
|
|
111
|
+
<PrimeStyleTryon
|
|
112
|
+
productImage={product.image}
|
|
113
|
+
buttonStyles={{
|
|
114
|
+
backgroundColor: '#000000',
|
|
115
|
+
textColor: '#ffffff',
|
|
116
|
+
borderRadius: '50px',
|
|
117
|
+
padding: '16px 32px',
|
|
118
|
+
fontSize: '16px',
|
|
119
|
+
fontWeight: '700',
|
|
120
|
+
width: '100%',
|
|
121
|
+
border: '2px solid #333',
|
|
122
|
+
hoverBackgroundColor: '#222',
|
|
123
|
+
iconSize: '20px',
|
|
124
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
|
|
125
|
+
}}
|
|
126
|
+
/>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**All ButtonStyles properties:**
|
|
130
|
+
|
|
131
|
+
| Property | Description |
|
|
132
|
+
|----------|-------------|
|
|
133
|
+
| `backgroundColor` | Button background color |
|
|
134
|
+
| `textColor` | Button text color |
|
|
135
|
+
| `borderRadius` | Corner rounding |
|
|
136
|
+
| `fontSize` | Text size |
|
|
137
|
+
| `fontFamily` | Font stack |
|
|
138
|
+
| `fontWeight` | Font weight |
|
|
139
|
+
| `padding` | Inner spacing |
|
|
140
|
+
| `border` | Border style |
|
|
141
|
+
| `width` | Button width (e.g. `"100%"`) |
|
|
142
|
+
| `height` | Button height |
|
|
143
|
+
| `hoverBackgroundColor` | Background on hover |
|
|
144
|
+
| `hoverTextColor` | Text color on hover |
|
|
145
|
+
| `iconSize` | Camera icon size |
|
|
146
|
+
| `iconColor` | Camera icon color |
|
|
147
|
+
| `boxShadow` | Shadow effect |
|
|
148
|
+
|
|
149
|
+
### Modal Styles
|
|
150
|
+
|
|
151
|
+
```jsx
|
|
152
|
+
<PrimeStyleTryon
|
|
153
|
+
productImage={product.image}
|
|
154
|
+
modalStyles={{
|
|
155
|
+
backgroundColor: '#ffffff',
|
|
156
|
+
textColor: '#111111',
|
|
157
|
+
overlayColor: 'rgba(0,0,0,0.7)',
|
|
158
|
+
borderRadius: '16px',
|
|
159
|
+
maxWidth: '520px',
|
|
160
|
+
headerBackgroundColor: '#f5f5f5',
|
|
161
|
+
headerTextColor: '#111111',
|
|
162
|
+
primaryButtonBackgroundColor: '#000000',
|
|
163
|
+
primaryButtonTextColor: '#ffffff',
|
|
164
|
+
loaderColor: '#000000',
|
|
165
|
+
}}
|
|
166
|
+
/>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**All ModalStyles properties:**
|
|
170
|
+
|
|
171
|
+
| Property | Description |
|
|
172
|
+
|----------|-------------|
|
|
173
|
+
| `overlayColor` | Background overlay color |
|
|
174
|
+
| `backgroundColor` | Modal background |
|
|
175
|
+
| `textColor` | Modal text color |
|
|
176
|
+
| `borderRadius` | Modal corner rounding |
|
|
177
|
+
| `width` / `maxWidth` | Modal dimensions |
|
|
178
|
+
| `fontFamily` | Modal font stack |
|
|
179
|
+
| `headerBackgroundColor` | Header section background |
|
|
180
|
+
| `headerTextColor` | Header title color |
|
|
181
|
+
| `closeButtonColor` | Close (X) button color |
|
|
182
|
+
| `uploadBorderColor` | Upload drop zone border |
|
|
183
|
+
| `uploadBackgroundColor` | Upload zone background |
|
|
184
|
+
| `uploadTextColor` | Upload zone text |
|
|
185
|
+
| `uploadIconColor` | Upload icon color |
|
|
186
|
+
| `primaryButtonBackgroundColor` | Submit / download button background |
|
|
187
|
+
| `primaryButtonTextColor` | Submit / download button text |
|
|
188
|
+
| `primaryButtonBorderRadius` | Submit button rounding |
|
|
189
|
+
| `loaderColor` | Loading spinner color |
|
|
190
|
+
| `resultBorderRadius` | Result image corner rounding |
|
|
191
|
+
|
|
192
|
+
### Tailwind CSS / Custom Classes
|
|
193
|
+
|
|
194
|
+
Use the `classNames` prop to style any element with Tailwind utilities or your own CSS classes:
|
|
195
|
+
|
|
196
|
+
```jsx
|
|
197
|
+
<PrimeStyleTryon
|
|
198
|
+
productImage={product.image}
|
|
199
|
+
classNames={{
|
|
200
|
+
button: "bg-black text-white rounded-full px-8 py-4 hover:bg-gray-800",
|
|
201
|
+
modal: "bg-white rounded-2xl shadow-2xl",
|
|
202
|
+
header: "bg-gray-50 border-b border-gray-200",
|
|
203
|
+
title: "text-gray-900 text-lg",
|
|
204
|
+
closeButton: "text-gray-400 hover:text-gray-600",
|
|
205
|
+
body: "p-6",
|
|
206
|
+
uploadZone: "border-2 border-dashed border-gray-300 rounded-xl p-10 hover:border-blue-400",
|
|
207
|
+
uploadText: "text-gray-700",
|
|
208
|
+
submitButton: "bg-blue-600 text-white rounded-lg hover:bg-blue-700",
|
|
209
|
+
downloadButton: "bg-green-600 text-white rounded-lg",
|
|
210
|
+
retryButton: "bg-gray-100 text-gray-700 border border-gray-300",
|
|
211
|
+
}}
|
|
212
|
+
/>
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**All classNames keys:**
|
|
216
|
+
|
|
217
|
+
| Key | Element |
|
|
218
|
+
|-----|---------|
|
|
219
|
+
| `root` | Root wrapper `<div>` |
|
|
220
|
+
| `button` | Trigger button |
|
|
221
|
+
| `overlay` | Modal backdrop overlay |
|
|
222
|
+
| `modal` | Modal container |
|
|
223
|
+
| `header` | Modal header bar |
|
|
224
|
+
| `title` | Modal title text |
|
|
225
|
+
| `closeButton` | Close (X) button |
|
|
226
|
+
| `body` | Modal body area |
|
|
227
|
+
| `uploadZone` | Upload drop zone |
|
|
228
|
+
| `uploadText` | "Drop your photo..." text |
|
|
229
|
+
| `uploadHint` | File type hint text |
|
|
230
|
+
| `preview` | Preview image container |
|
|
231
|
+
| `previewImage` | Preview `<img>` element |
|
|
232
|
+
| `removeButton` | Remove preview button |
|
|
233
|
+
| `submitButton` | "Try It On" / "Try Again" button |
|
|
234
|
+
| `spinner` | Loading spinner |
|
|
235
|
+
| `processingText` | "Generating..." text |
|
|
236
|
+
| `processingSubText` | "This usually takes..." text |
|
|
237
|
+
| `result` | Result container |
|
|
238
|
+
| `resultImage` | Result `<img>` element |
|
|
239
|
+
| `resultActions` | Download/retry button row |
|
|
240
|
+
| `downloadButton` | Download button |
|
|
241
|
+
| `retryButton` | "Try Another" button |
|
|
242
|
+
| `error` | Error container |
|
|
243
|
+
| `errorText` | Error message text |
|
|
244
|
+
| `poweredBy` | Footer text |
|
|
245
|
+
|
|
246
|
+
### Normal CSS
|
|
247
|
+
|
|
248
|
+
All elements use `ps-tryon-*` class names that you can target directly in your CSS:
|
|
249
|
+
|
|
250
|
+
```css
|
|
251
|
+
/* Override the trigger button */
|
|
252
|
+
.ps-tryon-btn {
|
|
253
|
+
background: #000;
|
|
254
|
+
color: #fff;
|
|
255
|
+
border-radius: 50px;
|
|
256
|
+
padding: 16px 32px;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* Override the modal */
|
|
260
|
+
.ps-tryon-modal {
|
|
261
|
+
background: #fff;
|
|
262
|
+
color: #111;
|
|
263
|
+
border-radius: 16px;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/* Override the submit button */
|
|
267
|
+
.ps-tryon-submit {
|
|
268
|
+
background: #2563eb;
|
|
269
|
+
color: #fff;
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Combining Approaches
|
|
274
|
+
|
|
275
|
+
You can mix all three styling methods — they layer on top of each other:
|
|
276
|
+
|
|
277
|
+
```jsx
|
|
278
|
+
<PrimeStyleTryon
|
|
279
|
+
productImage={product.image}
|
|
280
|
+
// 1. Style props (CSS variables)
|
|
281
|
+
buttonStyles={{ width: '100%' }}
|
|
282
|
+
// 2. Tailwind classes
|
|
283
|
+
classNames={{ button: "rounded-full font-bold" }}
|
|
284
|
+
// 3. Normal CSS targets .ps-tryon-btn automatically
|
|
285
|
+
/>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Priority: Tailwind/classNames classes > CSS variables (buttonStyles/modalStyles) > default styles.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Callbacks
|
|
293
|
+
|
|
294
|
+
```jsx
|
|
295
|
+
<PrimeStyleTryon
|
|
296
|
+
productImage={product.image}
|
|
297
|
+
onOpen={() => {
|
|
298
|
+
analytics.track('tryon_opened');
|
|
299
|
+
}}
|
|
300
|
+
onUpload={(file) => {
|
|
301
|
+
console.log('Photo uploaded:', file.name);
|
|
302
|
+
}}
|
|
303
|
+
onProcessing={(jobId) => {
|
|
304
|
+
console.log('Processing:', jobId);
|
|
305
|
+
}}
|
|
306
|
+
onComplete={(result) => {
|
|
307
|
+
console.log('Result ready:', result.imageUrl);
|
|
308
|
+
analytics.track('tryon_completed', { jobId: result.jobId });
|
|
309
|
+
}}
|
|
310
|
+
onError={(error) => {
|
|
311
|
+
console.error('Try-on failed:', error.message);
|
|
312
|
+
// error.code: 'INSUFFICIENT_TOKENS' | 'API_ERROR' | etc.
|
|
313
|
+
}}
|
|
314
|
+
onClose={() => {
|
|
315
|
+
console.log('Modal closed');
|
|
316
|
+
}}
|
|
317
|
+
/>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## Environment Variables
|
|
323
|
+
|
|
324
|
+
| Variable | Required | Default | Description |
|
|
325
|
+
|----------|----------|---------|-------------|
|
|
326
|
+
| `NEXT_PUBLIC_PRIMESTYLE_API_KEY` | Yes | — | Your PrimeStyle API key |
|
|
327
|
+
| `NEXT_PUBLIC_PRIMESTYLE_API_URL` | No | `https://myaifitting.com` | Custom API endpoint |
|
|
328
|
+
|
|
329
|
+
The component reads these automatically — no need to pass them as props.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Tokens & Pricing
|
|
334
|
+
|
|
335
|
+
Each virtual try-on consumes **tokens** from your account balance.
|
|
336
|
+
|
|
337
|
+
| | |
|
|
338
|
+
|---|---|
|
|
339
|
+
| **Free trial** | Tokens included on signup |
|
|
340
|
+
| **Token packs** | Pay-as-you-go, never expire |
|
|
341
|
+
| **Monthly plans** | Volume discounts for high-traffic stores |
|
|
342
|
+
|
|
343
|
+
Manage your balance and purchase tokens at [primestyleai.com/developer/dashboard/billing](https://myaifitting.com/developer/dashboard/billing).
|
|
344
|
+
|
|
345
|
+
If a try-on fails, tokens are **automatically refunded** to your account.
|
|
346
|
+
|
|
347
|
+
The `onComplete` callback includes token info:
|
|
348
|
+
|
|
349
|
+
```jsx
|
|
350
|
+
onComplete={(result) => {
|
|
351
|
+
// result.jobId — the job ID
|
|
352
|
+
// result.imageUrl — the result image URL
|
|
353
|
+
}}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## API Key Management
|
|
359
|
+
|
|
360
|
+
Create and manage your API keys at the [Developer Dashboard](https://myaifitting.com/developer/dashboard/keys).
|
|
361
|
+
|
|
362
|
+
- Keys start with `ps_live_` and are shown **once** at creation
|
|
363
|
+
- Set **allowed domains** to restrict where your key can be used
|
|
364
|
+
- **Revoke** keys instantly if compromised
|
|
365
|
+
- Maximum 10 active keys per account
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## Full Example
|
|
370
|
+
|
|
371
|
+
```jsx
|
|
372
|
+
// app/product/[id]/page.tsx (Next.js App Router)
|
|
373
|
+
|
|
374
|
+
import { PrimeStyleTryon } from '@primestyleai/tryon/react';
|
|
375
|
+
|
|
376
|
+
export default function ProductPage({ product }) {
|
|
377
|
+
return (
|
|
378
|
+
<div className="product-page">
|
|
379
|
+
<div className="product-gallery">
|
|
380
|
+
<img src={product.image} alt={product.name} />
|
|
381
|
+
</div>
|
|
382
|
+
|
|
383
|
+
<div className="product-info">
|
|
384
|
+
<h1>{product.name}</h1>
|
|
385
|
+
<p className="price">${product.price}</p>
|
|
386
|
+
|
|
387
|
+
{/* Virtual Try-On — reads API key from env */}
|
|
388
|
+
<PrimeStyleTryon
|
|
389
|
+
productImage={product.image}
|
|
390
|
+
buttonText="Try It On"
|
|
391
|
+
buttonStyles={{
|
|
392
|
+
width: '100%',
|
|
393
|
+
padding: '14px 24px',
|
|
394
|
+
borderRadius: '10px',
|
|
395
|
+
fontSize: '15px',
|
|
396
|
+
}}
|
|
397
|
+
onComplete={(result) => {
|
|
398
|
+
// Show success toast, track analytics, etc.
|
|
399
|
+
toast.success('Your try-on is ready!');
|
|
400
|
+
}}
|
|
401
|
+
onError={(error) => {
|
|
402
|
+
toast.error(error.message);
|
|
403
|
+
}}
|
|
404
|
+
/>
|
|
405
|
+
|
|
406
|
+
<button className="add-to-cart">Add to Cart</button>
|
|
407
|
+
</div>
|
|
408
|
+
</div>
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
415
|
+
## Requirements
|
|
416
|
+
|
|
417
|
+
- React 18+
|
|
418
|
+
- Next.js 13+ (App Router or Pages Router)
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## Need Help?
|
|
423
|
+
|
|
424
|
+
- [Live Demo](https://myaifitting.com/developer/demo) — See it in action
|
|
425
|
+
- [Documentation](https://myaifitting.com/docs) — Full API reference
|
|
426
|
+
- [Dashboard](https://myaifitting.com/developer/dashboard/keys) — Manage keys & tokens
|
|
427
|
+
- [Contact](mailto:support@primestyleai.com) — We're here to help
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
<p align="center">
|
|
432
|
+
Built with care by <a href="https://myaifitting.com">PrimeStyle AI</a>
|
|
433
|
+
</p>
|