@primestyleai/tryon 1.2.1 → 1.3.0
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 +13 -13
- package/dist/PrimeStyleTryon.d.ts +3 -0
- package/dist/{image-utils-usff6Qu8.js → image-utils-DtJVYQIA.js} +1 -1
- package/dist/primestyle-tryon.js +25 -3
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +145 -29
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<a href="https://
|
|
2
|
+
<a href="https://myaifitting.com">
|
|
3
3
|
<img src="https://cdn.jsdelivr.net/npm/@primestyleai/tryon/logo.svg" alt="PrimeStyle AI" width="180" />
|
|
4
4
|
</a>
|
|
5
5
|
</p>
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
</p>
|
|
23
23
|
|
|
24
24
|
<p align="center">
|
|
25
|
-
<a href="https://
|
|
26
|
-
<a href="https://
|
|
27
|
-
<a href="https://
|
|
28
|
-
<a href="https://
|
|
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
29
|
</p>
|
|
30
30
|
|
|
31
31
|
---
|
|
@@ -51,7 +51,7 @@ npm install @primestyleai/tryon
|
|
|
51
51
|
|
|
52
52
|
### 2. Set Your API Key
|
|
53
53
|
|
|
54
|
-
Get your key from the [Developer Dashboard](https://
|
|
54
|
+
Get your key from the [Developer Dashboard](https://myaifitting.com/developer/dashboard/keys) and add it to your `.env.local`:
|
|
55
55
|
|
|
56
56
|
```env
|
|
57
57
|
NEXT_PUBLIC_PRIMESTYLE_API_KEY=ps_live_your_key_here
|
|
@@ -324,7 +324,7 @@ Priority: Tailwind/classNames classes > CSS variables (buttonStyles/modalStyles)
|
|
|
324
324
|
| Variable | Required | Default | Description |
|
|
325
325
|
|----------|----------|---------|-------------|
|
|
326
326
|
| `NEXT_PUBLIC_PRIMESTYLE_API_KEY` | Yes | — | Your PrimeStyle API key |
|
|
327
|
-
| `NEXT_PUBLIC_PRIMESTYLE_API_URL` | No | `https://
|
|
327
|
+
| `NEXT_PUBLIC_PRIMESTYLE_API_URL` | No | `https://myaifitting.com` | Custom API endpoint |
|
|
328
328
|
|
|
329
329
|
The component reads these automatically — no need to pass them as props.
|
|
330
330
|
|
|
@@ -340,7 +340,7 @@ Each virtual try-on consumes **tokens** from your account balance.
|
|
|
340
340
|
| **Token packs** | Pay-as-you-go, never expire |
|
|
341
341
|
| **Monthly plans** | Volume discounts for high-traffic stores |
|
|
342
342
|
|
|
343
|
-
Manage your balance and purchase tokens at [primestyleai.com/dashboard/billing](https://
|
|
343
|
+
Manage your balance and purchase tokens at [primestyleai.com/developer/dashboard/billing](https://myaifitting.com/developer/dashboard/billing).
|
|
344
344
|
|
|
345
345
|
If a try-on fails, tokens are **automatically refunded** to your account.
|
|
346
346
|
|
|
@@ -357,7 +357,7 @@ onComplete={(result) => {
|
|
|
357
357
|
|
|
358
358
|
## API Key Management
|
|
359
359
|
|
|
360
|
-
Create and manage your API keys at the [Developer Dashboard](https://
|
|
360
|
+
Create and manage your API keys at the [Developer Dashboard](https://myaifitting.com/developer/dashboard/keys).
|
|
361
361
|
|
|
362
362
|
- Keys start with `ps_live_` and are shown **once** at creation
|
|
363
363
|
- Set **allowed domains** to restrict where your key can be used
|
|
@@ -421,13 +421,13 @@ export default function ProductPage({ product }) {
|
|
|
421
421
|
|
|
422
422
|
## Need Help?
|
|
423
423
|
|
|
424
|
-
- [Live Demo](https://
|
|
425
|
-
- [Documentation](https://
|
|
426
|
-
- [Dashboard](https://
|
|
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
427
|
- [Contact](mailto:support@primestyleai.com) — We're here to help
|
|
428
428
|
|
|
429
429
|
---
|
|
430
430
|
|
|
431
431
|
<p align="center">
|
|
432
|
-
Built with care by <a href="https://
|
|
432
|
+
Built with care by <a href="https://myaifitting.com">PrimeStyle AI</a>
|
|
433
433
|
</p>
|
|
@@ -22,6 +22,9 @@ export declare class PrimeStyleTryon extends HTMLElement {
|
|
|
22
22
|
setButtonStyles(styles: ButtonStyles): void;
|
|
23
23
|
/** Configure modal appearance programmatically */
|
|
24
24
|
setModalStyles(styles: ModalStyles): void;
|
|
25
|
+
private savedScrollY;
|
|
26
|
+
private lockBodyScroll;
|
|
27
|
+
private unlockBodyScroll;
|
|
25
28
|
/** Open the try-on modal */
|
|
26
29
|
open(): void;
|
|
27
30
|
/** Close the try-on modal */
|
package/dist/primestyle-tryon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as ApiClient, S as SseClient, i as isValidImageFile, c as compressImage } from "./image-utils-
|
|
2
|
-
import { P } from "./image-utils-
|
|
1
|
+
import { A as ApiClient, S as SseClient, i as isValidImageFile, c as compressImage } from "./image-utils-DtJVYQIA.js";
|
|
2
|
+
import { P } from "./image-utils-DtJVYQIA.js";
|
|
3
3
|
function detectProductImage() {
|
|
4
4
|
const ogImage = document.querySelector(
|
|
5
5
|
'meta[property="og:image"]'
|
|
@@ -459,6 +459,7 @@ class PrimeStyleTryon extends HTMLElement {
|
|
|
459
459
|
this.productImageUrl = null;
|
|
460
460
|
this.buttonStyles = {};
|
|
461
461
|
this.modalStyles = {};
|
|
462
|
+
this.savedScrollY = 0;
|
|
462
463
|
this.shadow = this.attachShadow({ mode: "open" });
|
|
463
464
|
}
|
|
464
465
|
static get observedAttributes() {
|
|
@@ -512,15 +513,33 @@ class PrimeStyleTryon extends HTMLElement {
|
|
|
512
513
|
this.modalStyles = { ...this.modalStyles, ...styles };
|
|
513
514
|
this.applyModalStyles();
|
|
514
515
|
}
|
|
516
|
+
lockBodyScroll() {
|
|
517
|
+
this.savedScrollY = window.scrollY;
|
|
518
|
+
document.body.style.overflow = "hidden";
|
|
519
|
+
document.body.style.position = "fixed";
|
|
520
|
+
document.body.style.top = `-${this.savedScrollY}px`;
|
|
521
|
+
document.body.style.left = "0";
|
|
522
|
+
document.body.style.right = "0";
|
|
523
|
+
}
|
|
524
|
+
unlockBodyScroll() {
|
|
525
|
+
document.body.style.overflow = "";
|
|
526
|
+
document.body.style.position = "";
|
|
527
|
+
document.body.style.top = "";
|
|
528
|
+
document.body.style.left = "";
|
|
529
|
+
document.body.style.right = "";
|
|
530
|
+
window.scrollTo(0, this.savedScrollY);
|
|
531
|
+
}
|
|
515
532
|
/** Open the try-on modal */
|
|
516
533
|
open() {
|
|
517
534
|
this.state = "upload";
|
|
535
|
+
this.lockBodyScroll();
|
|
518
536
|
this.render();
|
|
519
537
|
this.emit("ps:open");
|
|
520
538
|
}
|
|
521
539
|
/** Close the try-on modal */
|
|
522
540
|
close() {
|
|
523
541
|
this.state = "idle";
|
|
542
|
+
this.unlockBodyScroll();
|
|
524
543
|
this.resetUpload();
|
|
525
544
|
this.render();
|
|
526
545
|
this.emit("ps:close");
|
|
@@ -567,6 +586,9 @@ class PrimeStyleTryon extends HTMLElement {
|
|
|
567
586
|
this.sseClient = new SseClient(this.apiClient.getStreamUrl());
|
|
568
587
|
}
|
|
569
588
|
cleanup() {
|
|
589
|
+
if (this.state !== "idle") {
|
|
590
|
+
this.unlockBodyScroll();
|
|
591
|
+
}
|
|
570
592
|
if (this.sseUnsubscribe) {
|
|
571
593
|
this.sseUnsubscribe();
|
|
572
594
|
this.sseUnsubscribe = null;
|
|
@@ -653,7 +675,7 @@ class PrimeStyleTryon extends HTMLElement {
|
|
|
653
675
|
if (this.showPoweredBy) {
|
|
654
676
|
const powered = document.createElement("div");
|
|
655
677
|
powered.className = "ps-powered";
|
|
656
|
-
powered.innerHTML = `Powered by <a href="https://
|
|
678
|
+
powered.innerHTML = `Powered by <a href="https://myaifitting.com" target="_blank" rel="noopener">PrimeStyle AI</a>`;
|
|
657
679
|
modal.appendChild(powered);
|
|
658
680
|
}
|
|
659
681
|
overlay.appendChild(modal);
|
package/dist/react/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export interface PrimeStyleTryonProps {
|
|
|
5
5
|
productImage: string;
|
|
6
6
|
/** Button text (defaults to "Virtual Try-On") */
|
|
7
7
|
buttonText?: string;
|
|
8
|
-
/** API base URL — defaults to NEXT_PUBLIC_PRIMESTYLE_API_URL env or https://
|
|
8
|
+
/** API base URL — defaults to NEXT_PUBLIC_PRIMESTYLE_API_URL env or https://myaifitting.com */
|
|
9
9
|
apiUrl?: string;
|
|
10
10
|
/** Show "Powered by PrimeStyle" in modal footer (defaults to true) */
|
|
11
11
|
showPoweredBy?: boolean;
|
package/dist/react/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useRef, useEffect, useCallback } from "react";
|
|
4
|
-
import { A as ApiClient, S as SseClient, i as isValidImageFile, c as compressImage, P as PrimeStyleError } from "../image-utils-
|
|
4
|
+
import { A as ApiClient, S as SseClient, i as isValidImageFile, c as compressImage, P as PrimeStyleError } from "../image-utils-DtJVYQIA.js";
|
|
5
5
|
function cx(base, override) {
|
|
6
6
|
return override ? `${base} ${override}` : base;
|
|
7
7
|
}
|
|
@@ -94,7 +94,7 @@ function getApiKey() {
|
|
|
94
94
|
return key;
|
|
95
95
|
}
|
|
96
96
|
function getApiUrl(override) {
|
|
97
|
-
return override || process.env.NEXT_PUBLIC_PRIMESTYLE_API_URL || "https://
|
|
97
|
+
return override || process.env.NEXT_PUBLIC_PRIMESTYLE_API_URL || "https://myaifitting.com";
|
|
98
98
|
}
|
|
99
99
|
function PrimeStyleTryon({
|
|
100
100
|
productImage,
|
|
@@ -119,6 +119,7 @@ function PrimeStyleTryon({
|
|
|
119
119
|
const [resultImageUrl, setResultImageUrl] = useState(null);
|
|
120
120
|
const [errorMessage, setErrorMessage] = useState(null);
|
|
121
121
|
const [dragOver, setDragOver] = useState(false);
|
|
122
|
+
const [countdown, setCountdown] = useState(20);
|
|
122
123
|
const fileInputRef = useRef(null);
|
|
123
124
|
const apiRef = useRef(null);
|
|
124
125
|
const sseRef = useRef(null);
|
|
@@ -138,11 +139,44 @@ function PrimeStyleTryon({
|
|
|
138
139
|
if (pollingRef.current) clearInterval(pollingRef.current);
|
|
139
140
|
};
|
|
140
141
|
}, [apiUrl]);
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
if (view === "processing") {
|
|
144
|
+
setCountdown(20);
|
|
145
|
+
const interval = setInterval(() => {
|
|
146
|
+
setCountdown((prev) => {
|
|
147
|
+
if (prev <= 1) {
|
|
148
|
+
clearInterval(interval);
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
return prev - 1;
|
|
152
|
+
});
|
|
153
|
+
}, 1e3);
|
|
154
|
+
return () => clearInterval(interval);
|
|
155
|
+
}
|
|
156
|
+
}, [view]);
|
|
141
157
|
useEffect(() => {
|
|
142
158
|
return () => {
|
|
143
159
|
if (previewUrl) URL.revokeObjectURL(previewUrl);
|
|
144
160
|
};
|
|
145
161
|
}, [previewUrl]);
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
if (view !== "idle") {
|
|
164
|
+
const scrollY = window.scrollY;
|
|
165
|
+
document.body.style.overflow = "hidden";
|
|
166
|
+
document.body.style.position = "fixed";
|
|
167
|
+
document.body.style.top = `-${scrollY}px`;
|
|
168
|
+
document.body.style.left = "0";
|
|
169
|
+
document.body.style.right = "0";
|
|
170
|
+
return () => {
|
|
171
|
+
document.body.style.overflow = "";
|
|
172
|
+
document.body.style.position = "";
|
|
173
|
+
document.body.style.top = "";
|
|
174
|
+
document.body.style.left = "";
|
|
175
|
+
document.body.style.right = "";
|
|
176
|
+
window.scrollTo(0, scrollY);
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}, [view]);
|
|
146
180
|
const handleOpen = useCallback(() => {
|
|
147
181
|
setView("upload");
|
|
148
182
|
onOpen?.();
|
|
@@ -187,26 +221,41 @@ function PrimeStyleTryon({
|
|
|
187
221
|
if (previewUrl) URL.revokeObjectURL(previewUrl);
|
|
188
222
|
setPreviewUrl(null);
|
|
189
223
|
}, [previewUrl]);
|
|
224
|
+
const completedRef = useRef(false);
|
|
225
|
+
const cleanupJob = useCallback(() => {
|
|
226
|
+
if (pollingRef.current) {
|
|
227
|
+
clearInterval(pollingRef.current);
|
|
228
|
+
pollingRef.current = null;
|
|
229
|
+
}
|
|
230
|
+
unsubRef.current?.();
|
|
231
|
+
unsubRef.current = null;
|
|
232
|
+
}, []);
|
|
190
233
|
const handleVtoUpdate = useCallback(
|
|
191
|
-
(update
|
|
234
|
+
(update) => {
|
|
192
235
|
if (update.status === "completed" && update.imageUrl) {
|
|
193
236
|
setResultImageUrl((prev) => {
|
|
194
|
-
if (prev
|
|
237
|
+
if (!prev || prev.startsWith("data:")) return update.imageUrl;
|
|
195
238
|
if (!update.imageUrl.startsWith("data:")) return update.imageUrl;
|
|
196
239
|
return prev;
|
|
197
240
|
});
|
|
198
|
-
if (
|
|
241
|
+
if (!completedRef.current) {
|
|
242
|
+
completedRef.current = true;
|
|
243
|
+
cleanupJob();
|
|
199
244
|
setView("result");
|
|
200
245
|
onComplete?.({ jobId: update.galleryId, imageUrl: update.imageUrl });
|
|
201
246
|
}
|
|
202
247
|
} else if (update.status === "failed") {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
248
|
+
if (!completedRef.current) {
|
|
249
|
+
completedRef.current = true;
|
|
250
|
+
cleanupJob();
|
|
251
|
+
const msg = update.error || "Try-on generation failed";
|
|
252
|
+
setErrorMessage(msg);
|
|
253
|
+
setView("error");
|
|
254
|
+
onError?.({ message: msg });
|
|
255
|
+
}
|
|
207
256
|
}
|
|
208
257
|
},
|
|
209
|
-
[onComplete, onError]
|
|
258
|
+
[onComplete, onError, cleanupJob]
|
|
210
259
|
);
|
|
211
260
|
const handleSubmit = useCallback(async () => {
|
|
212
261
|
if (!selectedFile || !apiRef.current || !sseRef.current) {
|
|
@@ -216,6 +265,7 @@ function PrimeStyleTryon({
|
|
|
216
265
|
onError?.({ message: msg, code: "SDK_NOT_CONFIGURED" });
|
|
217
266
|
return;
|
|
218
267
|
}
|
|
268
|
+
completedRef.current = false;
|
|
219
269
|
setView("processing");
|
|
220
270
|
try {
|
|
221
271
|
const modelImage = await compressImage(selectedFile);
|
|
@@ -226,33 +276,35 @@ function PrimeStyleTryon({
|
|
|
226
276
|
onProcessing?.(response.jobId);
|
|
227
277
|
unsubRef.current = sseRef.current.onJob(
|
|
228
278
|
response.jobId,
|
|
229
|
-
(update) => handleVtoUpdate(update
|
|
279
|
+
(update) => handleVtoUpdate(update)
|
|
230
280
|
);
|
|
231
281
|
let attempts = 0;
|
|
232
282
|
pollingRef.current = setInterval(async () => {
|
|
283
|
+
if (completedRef.current) {
|
|
284
|
+
if (pollingRef.current) clearInterval(pollingRef.current);
|
|
285
|
+
pollingRef.current = null;
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
233
288
|
attempts++;
|
|
234
289
|
if (attempts > 60) {
|
|
235
290
|
if (pollingRef.current) clearInterval(pollingRef.current);
|
|
291
|
+
pollingRef.current = null;
|
|
236
292
|
return;
|
|
237
293
|
}
|
|
238
294
|
try {
|
|
239
295
|
const status = await apiRef.current.getStatus(response.jobId);
|
|
240
296
|
if (status.status === "completed" || status.status === "failed") {
|
|
241
|
-
handleVtoUpdate(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
},
|
|
249
|
-
view
|
|
250
|
-
);
|
|
251
|
-
if (pollingRef.current) clearInterval(pollingRef.current);
|
|
297
|
+
handleVtoUpdate({
|
|
298
|
+
galleryId: response.jobId,
|
|
299
|
+
status: status.status,
|
|
300
|
+
imageUrl: status.imageUrl,
|
|
301
|
+
error: status.status === "failed" ? status.message : null,
|
|
302
|
+
timestamp: Date.now()
|
|
303
|
+
});
|
|
252
304
|
}
|
|
253
305
|
} catch {
|
|
254
306
|
}
|
|
255
|
-
},
|
|
307
|
+
}, 3e3);
|
|
256
308
|
} catch (err) {
|
|
257
309
|
const message = err instanceof Error ? err.message : "Failed to start try-on";
|
|
258
310
|
const code = err instanceof PrimeStyleError ? err.code : void 0;
|
|
@@ -260,7 +312,7 @@ function PrimeStyleTryon({
|
|
|
260
312
|
setView("error");
|
|
261
313
|
onError?.({ message, code });
|
|
262
314
|
}
|
|
263
|
-
}, [selectedFile, productImage, onProcessing, onError, handleVtoUpdate
|
|
315
|
+
}, [selectedFile, productImage, onProcessing, onError, handleVtoUpdate]);
|
|
264
316
|
const handleDownload = useCallback(() => {
|
|
265
317
|
if (!resultImageUrl) return;
|
|
266
318
|
if (resultImageUrl.startsWith("data:")) {
|
|
@@ -280,13 +332,15 @@ function PrimeStyleTryon({
|
|
|
280
332
|
}
|
|
281
333
|
}, [resultImageUrl]);
|
|
282
334
|
const handleRetry = useCallback(() => {
|
|
335
|
+
completedRef.current = false;
|
|
336
|
+
cleanupJob();
|
|
283
337
|
setSelectedFile(null);
|
|
284
338
|
if (previewUrl) URL.revokeObjectURL(previewUrl);
|
|
285
339
|
setPreviewUrl(null);
|
|
286
340
|
setResultImageUrl(null);
|
|
287
341
|
setErrorMessage(null);
|
|
288
342
|
setView("upload");
|
|
289
|
-
}, [previewUrl]);
|
|
343
|
+
}, [previewUrl, cleanupJob]);
|
|
290
344
|
const rootVars = {
|
|
291
345
|
"--ps-btn-bg": btnS.backgroundColor,
|
|
292
346
|
"--ps-btn-color": btnS.textColor,
|
|
@@ -426,13 +480,38 @@ function PrimeStyleTryon({
|
|
|
426
480
|
}
|
|
427
481
|
),
|
|
428
482
|
/* @__PURE__ */ jsx(UploadIcon, {}),
|
|
429
|
-
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-upload-text", cn.uploadText), children: "Drop
|
|
483
|
+
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-upload-text", cn.uploadText), children: "Drop or upload your full body photo!" }),
|
|
430
484
|
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-upload-hint", cn.uploadHint), children: "JPEG, PNG or WebP (max 10MB)" })
|
|
431
485
|
]
|
|
432
486
|
}
|
|
433
487
|
) }),
|
|
434
488
|
view === "processing" && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-processing", children: [
|
|
435
|
-
/* @__PURE__ */
|
|
489
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-countdown-ring", children: [
|
|
490
|
+
/* @__PURE__ */ jsxs("svg", { viewBox: "0 0 120 120", children: [
|
|
491
|
+
/* @__PURE__ */ jsx(
|
|
492
|
+
"circle",
|
|
493
|
+
{
|
|
494
|
+
className: "ps-tryon-countdown-track",
|
|
495
|
+
cx: "60",
|
|
496
|
+
cy: "60",
|
|
497
|
+
r: "52"
|
|
498
|
+
}
|
|
499
|
+
),
|
|
500
|
+
/* @__PURE__ */ jsx(
|
|
501
|
+
"circle",
|
|
502
|
+
{
|
|
503
|
+
className: "ps-tryon-countdown-progress",
|
|
504
|
+
cx: "60",
|
|
505
|
+
cy: "60",
|
|
506
|
+
r: "52",
|
|
507
|
+
style: {
|
|
508
|
+
strokeDashoffset: `${countdown / 20 * 326.73}`
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
)
|
|
512
|
+
] }),
|
|
513
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-countdown-number", children: countdown })
|
|
514
|
+
] }),
|
|
436
515
|
/* @__PURE__ */ jsx(
|
|
437
516
|
"p",
|
|
438
517
|
{
|
|
@@ -450,7 +529,7 @@ function PrimeStyleTryon({
|
|
|
450
529
|
"ps-tryon-processing-sub",
|
|
451
530
|
cn.processingSubText
|
|
452
531
|
),
|
|
453
|
-
children: "This usually takes 15-20 seconds"
|
|
532
|
+
children: countdown > 0 ? "This usually takes 15-20 seconds" : "Almost there..."
|
|
454
533
|
}
|
|
455
534
|
)
|
|
456
535
|
] }),
|
|
@@ -510,7 +589,7 @@ function PrimeStyleTryon({
|
|
|
510
589
|
/* @__PURE__ */ jsx(
|
|
511
590
|
"a",
|
|
512
591
|
{
|
|
513
|
-
href: "https://
|
|
592
|
+
href: "https://myaifitting.com",
|
|
514
593
|
target: "_blank",
|
|
515
594
|
rel: "noopener noreferrer",
|
|
516
595
|
children: "PrimeStyle AI"
|
|
@@ -712,6 +791,43 @@ function PrimeStyleTryon({
|
|
|
712
791
|
margin: 0 auto 16px;
|
|
713
792
|
}
|
|
714
793
|
@keyframes ps-spin { to { transform: rotate(360deg); } }
|
|
794
|
+
|
|
795
|
+
.ps-tryon-countdown-ring {
|
|
796
|
+
position: relative;
|
|
797
|
+
width: 100px;
|
|
798
|
+
height: 100px;
|
|
799
|
+
margin: 0 auto 20px;
|
|
800
|
+
}
|
|
801
|
+
.ps-tryon-countdown-ring svg {
|
|
802
|
+
width: 100%;
|
|
803
|
+
height: 100%;
|
|
804
|
+
transform: rotate(-90deg);
|
|
805
|
+
}
|
|
806
|
+
.ps-tryon-countdown-track {
|
|
807
|
+
fill: none;
|
|
808
|
+
stroke: #333;
|
|
809
|
+
stroke-width: 4;
|
|
810
|
+
}
|
|
811
|
+
.ps-tryon-countdown-progress {
|
|
812
|
+
fill: none;
|
|
813
|
+
stroke: var(--ps-loader, #bb945c);
|
|
814
|
+
stroke-width: 4;
|
|
815
|
+
stroke-linecap: round;
|
|
816
|
+
stroke-dasharray: 326.73;
|
|
817
|
+
transition: stroke-dashoffset 1s linear;
|
|
818
|
+
}
|
|
819
|
+
.ps-tryon-countdown-number {
|
|
820
|
+
position: absolute;
|
|
821
|
+
inset: 0;
|
|
822
|
+
display: flex;
|
|
823
|
+
align-items: center;
|
|
824
|
+
justify-content: center;
|
|
825
|
+
font-size: 28px;
|
|
826
|
+
font-weight: 700;
|
|
827
|
+
color: #fff;
|
|
828
|
+
font-variant-numeric: tabular-nums;
|
|
829
|
+
}
|
|
830
|
+
|
|
715
831
|
.ps-tryon-processing-text { font-size: 14px; color: #fff; margin: 0 0 4px; }
|
|
716
832
|
.ps-tryon-processing-sub { font-size: 12px; color: #999; margin: 0; }
|
|
717
833
|
|
package/dist/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export interface PrimeStyleConfig {
|
|
3
3
|
/** Your API key (starts with ps_live_) */
|
|
4
4
|
apiKey: string;
|
|
5
|
-
/** API base URL (defaults to https://
|
|
5
|
+
/** API base URL (defaults to https://myaifitting.com) */
|
|
6
6
|
apiUrl?: string;
|
|
7
7
|
/** Product image URL to try on */
|
|
8
8
|
productImage?: string;
|