@akinon/pz-virtual-try-on 2.0.0-beta.16 → 2.0.0-beta.18

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/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @akinon/pz-virtual-try-on
2
2
 
3
+ ## 2.0.0-beta.18
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [929374c5]
8
+ - Updated dependencies [71f8011d]
9
+ - Updated dependencies [9be2c081]
10
+ - Updated dependencies [bd431e36]
11
+ - Updated dependencies [54eac86b]
12
+ - @akinon/next@2.0.0-beta.18
13
+
14
+ ## 2.0.0-beta.17
15
+
16
+ ### Minor Changes
17
+
18
+ - 36143125: ZERO-3987: Add barcode scanner functionality with modal and button
19
+ - 5fb34b5c: ZERO-3955: Add aspect ratio validation and error handling for image cropping
20
+
21
+ ### Patch Changes
22
+
23
+ - Updated dependencies [8218dafa]
24
+ - Updated dependencies [2a8ddcf6]
25
+ - Updated dependencies [8a7fd0f4]
26
+ - Updated dependencies [36143125]
27
+ - Updated dependencies [f7e0f646]
28
+ - Updated dependencies [94a86fcc]
29
+ - Updated dependencies [bcaad120]
30
+ - @akinon/next@2.0.0-beta.17
31
+
3
32
  ## 2.0.0-beta.16
4
33
 
5
34
  ### Minor Changes
package/README.md CHANGED
@@ -17,6 +17,7 @@
17
17
  - [Customization Strategies](#markdown-header-customization-strategies)
18
18
  - [Professional Examples](#markdown-header-professional-examples)
19
19
  - [Usage Blueprints](#markdown-header-usage-blueprints)
20
+ - [Upload Modal Content Customization](#markdown-header-upload-modal-content-customization)
20
21
  - [Styling Reference](#markdown-header-styling-reference)
21
22
  - [Workflow & Caching](#markdown-header-workflow-caching)
22
23
  - [Best Practices](#markdown-header-best-practices)
@@ -92,8 +93,10 @@
92
93
  - **⚙️ Per-Component Control**: Independent customization for each modal and component
93
94
  - **🔒 Type Safety**: Full TypeScript support for all customization options
94
95
  - **🌍 Localization Support**: Built-in `useLocalization` hook integration in every component for multi-language UI
96
+ - **🖼️ Upload Modal Images**: Replace rule example images with custom branded assets via `customStyles.uploadModalImages`
97
+ - **📝 Upload Modal Texts**: Customize all modal text content via `customStyles.uploadModalTexts`
95
98
 
96
- **Customizable Components (10/10 - 100%):**
99
+ **Customizable Components (12/12 - 100%):**
97
100
 
98
101
  - ✅ `VirtualTryOnUploadModal` - 30+ render functions, 80+ style points, CSS variables, cropping UI
99
102
  - ✅ `VirtualTryOnResultModal` - 15+ render functions, 50+ style points, mobile-optimized feedback
@@ -103,9 +106,24 @@
103
106
  - ✅ `VirtualTryOnProductSelector` - 3 render functions, 30+ style points, max selection UI
104
107
  - ✅ `VirtualTryOnAsyncModal` - 5 render functions, 35+ style points, async feedback system
105
108
  - ✅ `BasketVirtualTryOn` - 2 render functions, 4 style points, eligibility filtering
109
+ - ✅ `BarcodeScannerPlugin` - Complete VTO flow orchestration with customization pass-through
110
+ - ✅ `BarcodeScannerButton` - 2 render functions, 2 style points, floating button
111
+ - ✅ `BarcodeScannerModal` - 30+ render functions, 50+ style points, scanner UI
106
112
  - ✅ `BasketAsyncModal` - 3 render functions, 25+ style points, real-time polling
107
113
  - ✅ `VirtualTryOnButton` - 4 render functions, 10+ style points, variant support
108
114
 
115
+ ### 🆕 NEW: Barcode Scanner Integration
116
+
117
+ - **📷 Barcode Scanning**: Scan product barcodes with your mobile camera to find and try on products instantly
118
+ - **🔍 Universal Barcode Support**: Supports all major formats (EAN-13, EAN-8, UPC-A, UPC-E, Code-128, Code-39, QR Code, and more)
119
+ - **📱 Homepage Only**: Floating button visible only on mobile devices and only on homepage
120
+ - **⚡ Real-time Search**: Instantly searches products by barcode number
121
+ - **🛒 Multi-Product Scanning**: Scan multiple products before continuing to VTO
122
+ - **🎨 Fully Customizable**: 50+ style points, 30+ render functions, theme support, CSS variables
123
+ - **📳 Haptic Feedback**: Optional vibration on successful scan
124
+ - **🔒 Permission Handling**: Graceful camera permission requests and error handling
125
+ - **⏱️ Auto-dismiss Errors**: Error messages automatically dismiss after 2 seconds
126
+
109
127
  ### 🆕 NEW: Multiple Product Try-On (Basket Integration)
110
128
 
111
129
  - **🛒 Basket Integration**: Try on multiple products from basket simultaneously (max 3 products)
@@ -127,6 +145,240 @@ Select `pz-virtual-try-on` when prompted. In existing monorepos run `yarn instal
127
145
 
128
146
  ## Quick Start
129
147
 
148
+ ### 🆕 Barcode Scanner Integration (Mobile Homepage)
149
+
150
+ **NEW**: Scan product barcodes to instantly find and try on products!
151
+
152
+ #### Method 1: Using PluginModule (Recommended)
153
+
154
+ The barcode scanner is automatically available via the PluginModule system. Add it to your **homepage only** (not client-root, as it should only appear on the homepage):
155
+
156
+ ```tsx
157
+ // In src/app/[commerce]/[locale]/[currency]/home-client.tsx
158
+ 'use client';
159
+
160
+ import PluginModule, { Component } from '@akinon/next/components/plugin-module';
161
+
162
+ export function HomeClient() {
163
+ return (
164
+ <>
165
+ {/* Barcode Scanner Plugin - Mobile only floating button */}
166
+ <PluginModule component={Component.BarcodeScannerPlugin} />
167
+ </>
168
+ );
169
+ }
170
+ ```
171
+
172
+ Then use it in your homepage:
173
+
174
+ ```tsx
175
+ // In src/app/[commerce]/[locale]/[currency]/page.tsx
176
+ import { HomeClient } from './home-client';
177
+
178
+ async function Page() {
179
+ return (
180
+ <>
181
+ {/* Your homepage widgets */}
182
+ <HomeClient />
183
+ </>
184
+ );
185
+ }
186
+ ```
187
+
188
+ #### Method 2: Direct Component Import
189
+
190
+ ```tsx
191
+ import { BarcodeScannerPlugin } from '@akinon/pz-virtual-try-on';
192
+ import type {
193
+ BarcodeScannerSettings,
194
+ VirtualTryOnPluginSettings
195
+ } from '@akinon/pz-virtual-try-on';
196
+
197
+ // Full customization example with styles and renderers
198
+ const barcodeScannerSettings: BarcodeScannerSettings = {
199
+ maxProducts: 5,
200
+ vibrateOnScan: true,
201
+ // Theme customization
202
+ theme: {
203
+ colors: {
204
+ primary: '#3b82f6',
205
+ background: '#ffffff',
206
+ text: '#1f2937',
207
+ success: '#10b981',
208
+ error: '#ef4444',
209
+ scannerOverlay: 'rgba(0, 0, 0, 0.6)',
210
+ scannerFrame: '#3b82f6',
211
+ scannerCorner: '#3b82f6'
212
+ },
213
+ borderRadius: {
214
+ sm: '4px',
215
+ md: '8px',
216
+ lg: '16px'
217
+ }
218
+ },
219
+ // 50+ Custom style points
220
+ customStyles: {
221
+ // Floating button
222
+ floatingButton: 'bg-blue-600 shadow-xl hover:bg-blue-700',
223
+ floatingButtonIcon: 'text-white w-7 h-7',
224
+ // Modal
225
+ modalOverlay: 'bg-black/80',
226
+ modalContainer: 'bg-white rounded-2xl',
227
+ modalHeader: 'border-b border-gray-100',
228
+ modalCloseButton: 'hover:bg-gray-100 rounded-full',
229
+ // Scanner
230
+ scannerContainer: 'rounded-lg overflow-hidden',
231
+ scannerFrame: 'border-2 border-blue-500',
232
+ scannerHelpText: 'text-white text-sm',
233
+ // Products
234
+ productCard: 'rounded-lg shadow-sm',
235
+ productImage: 'object-cover',
236
+ productRemoveButton: 'bg-red-500 hover:bg-red-600',
237
+ // Actions
238
+ continueButton: 'bg-blue-600 hover:bg-blue-700 text-white font-semibold',
239
+ // Error states
240
+ errorContainer: 'bg-red-500/90 rounded-lg',
241
+ errorMessage: 'text-white',
242
+ // Loading
243
+ loadingSpinner: 'text-blue-500',
244
+ // Permission denied
245
+ permissionDeniedButton: 'bg-blue-600 text-white'
246
+ },
247
+ // 30+ Custom render functions
248
+ customRenderers: {
249
+ // Custom floating button
250
+ renderFloatingButton: ({ onClick }) => (
251
+ <button
252
+ onClick={onClick}
253
+ className="fixed bottom-20 right-4 z-50 md:hidden w-16 h-16 rounded-full bg-gradient-to-r from-blue-500 to-purple-500 text-white shadow-xl"
254
+ >
255
+ 📷
256
+ </button>
257
+ ),
258
+ // Custom modal header
259
+ renderModalHeader: ({ title, onClose }) => (
260
+ <div className="flex justify-between items-center p-4 bg-gradient-to-r from-blue-500 to-purple-500">
261
+ <h2 className="text-white font-bold text-lg">{title}</h2>
262
+ <button onClick={onClose} className="text-white">
263
+
264
+ </button>
265
+ </div>
266
+ ),
267
+ // Custom product card
268
+ renderProductCard: ({ product, onRemove }) => (
269
+ <div className="relative p-2 bg-white rounded-lg shadow">
270
+ <img
271
+ src={product.productimage_set?.[0]?.image}
272
+ alt={product.name}
273
+ className="w-16 h-16 object-cover rounded"
274
+ />
275
+ <button
276
+ onClick={() => onRemove?.(product)}
277
+ className="absolute -top-2 -right-2 w-5 h-5 bg-red-500 text-white rounded-full text-xs"
278
+ >
279
+ ×
280
+ </button>
281
+ </div>
282
+ ),
283
+ // Custom continue button
284
+ renderContinueButton: ({ onClick, disabled, text }) => (
285
+ <button
286
+ onClick={onClick}
287
+ disabled={disabled}
288
+ className={`w-full py-3 rounded-full font-bold transition ${
289
+ disabled
290
+ ? 'bg-gray-300'
291
+ : 'bg-gradient-to-r from-blue-500 to-purple-500 text-white'
292
+ }`}
293
+ >
294
+ {text}
295
+ </button>
296
+ ),
297
+ // Custom error display
298
+ renderError: ({ error, onRetry }) => (
299
+ <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
300
+ <span>{error}</span>
301
+ {onRetry && (
302
+ <button onClick={onRetry} className="ml-2 underline">
303
+ Retry
304
+ </button>
305
+ )}
306
+ </div>
307
+ )
308
+ }
309
+ };
310
+
311
+ export function HomePage() {
312
+ return (
313
+ <div>
314
+ {/* Your homepage content */}
315
+
316
+ {/* Barcode Scanner Button (shows on mobile only) */}
317
+ <BarcodeScannerPlugin
318
+ barcodeScannerSettings={barcodeScannerSettings}
319
+ onProductsScanned={(products) => {
320
+ // Handle scanned products
321
+ }}
322
+ onVTOComplete={(result) => {
323
+ // Handle VTO completion
324
+ }}
325
+ />
326
+ </div>
327
+ );
328
+ }
329
+ ```
330
+
331
+ #### Method 3: Configure via settings.js
332
+
333
+ You can also configure the barcode scanner via `settings.js`:
334
+
335
+ ```javascript
336
+ // settings.js
337
+ module.exports = {
338
+ // ... other settings
339
+ plugins: {
340
+ 'pz-virtual-try-on': {
341
+ barcodeScanner: {
342
+ maxProducts: 5,
343
+ vibrateOnScan: true,
344
+ customStyles: {
345
+ floatingButton: 'bg-black shadow-xl',
346
+ continueButton: 'bg-black hover:bg-gray-800'
347
+ }
348
+ },
349
+ vto: {
350
+ theme: {
351
+ colors: {
352
+ primary: '#000000'
353
+ }
354
+ }
355
+ }
356
+ }
357
+ }
358
+ };
359
+ ```
360
+
361
+ **How it works:**
362
+
363
+ 1. Floating button appears in bottom-right corner (mobile only)
364
+ 2. Click opens fullscreen barcode scanner
365
+ 3. Point camera at product barcode
366
+ 4. Product is searched and displayed automatically
367
+ 5. Scan more products or click "Sanal Kabine Devam Et" (Continue to Virtual Cabin)
368
+ 6. Upload photo and see VTO results for all scanned products
369
+
370
+ **Supported Barcode Formats:**
371
+
372
+ - EAN-13 / EAN-8 (European Article Number)
373
+ - UPC-A / UPC-E (Universal Product Code)
374
+ - Code-128 / Code-39 / Code-93
375
+ - QR Code
376
+ - Data Matrix
377
+ - PDF-417
378
+ - Codabar
379
+ - ITF (Interleaved 2 of 5)
380
+ - Aztec
381
+
130
382
  ### 🆕 Basket Integration (Multiple Products)
131
383
 
132
384
  **NEW**: Try on multiple products from basket page!
@@ -226,10 +478,10 @@ const virtualTryOnSettings: VirtualTryOnPluginSettings = {
226
478
  {step === 'upload'
227
479
  ? ' 01'
228
480
  : step === 'crop'
229
- ? ' 02'
230
- : step === 'processing'
231
- ? ' 03'
232
- : ' 04'}
481
+ ? ' 02'
482
+ : step === 'processing'
483
+ ? ' 03'
484
+ : ' 04'}
233
485
  </p>
234
486
  <h2 className="text-xl font-semibold text-gray-900">{title}</h2>
235
487
  </div>
@@ -648,7 +900,17 @@ type VirtualTryOnPluginSettings = {
648
900
  buttonSize?: 'sm' | 'md' | 'lg';
649
901
  legal_text?: string;
650
902
  instructions?: string;
651
- customStyles?: Record<string, string | undefined>;
903
+ customStyles?: {
904
+ // CSS class overrides (300+ slots)
905
+ button?: string;
906
+ uploadModal?: string;
907
+ resultModal?: string;
908
+ // ... and many more
909
+
910
+ // Upload Modal Content Customization
911
+ uploadModalImages?: VirtualTryOnModalImages;
912
+ uploadModalTexts?: VirtualTryOnModalTexts;
913
+ };
652
914
  customRenderers?: {
653
915
  UploadModal?: React.ComponentType<VirtualTryOnUploadModalProps>;
654
916
  ResultModal?: React.ComponentType<VirtualTryOnResultModalProps>;
@@ -672,7 +934,7 @@ type VirtualTryOnPluginSettings = {
672
934
  };
673
935
  ```
674
936
 
675
- > `customStyles` exposes 300+ slots (see [Styling Reference](#markdown-header-styling-reference)); `CustomRendererProps` provides 60+ render callbacks across all 10 components with full localization support.
937
+ > `customStyles` exposes 300+ slots for CSS classes plus `uploadModalImages` and `uploadModalTexts` for content customization (see [Upload Modal Content Customization](#markdown-header-upload-modal-content-customization) and [Styling Reference](#markdown-header-styling-reference)); `CustomRendererProps` provides 60+ render callbacks across all 10 components with full localization support.
676
938
 
677
939
  ### Service Endpoints
678
940
 
@@ -1695,6 +1957,140 @@ Customize modal overlays, sizes, and button styles for brand consistency.
1695
1957
  />
1696
1958
  ```
1697
1959
 
1960
+ ## Upload Modal Content Customization
1961
+
1962
+ The upload modal images and texts can be fully customized via `customStyles.uploadModalImages` and `customStyles.uploadModalTexts`. This is useful for:
1963
+
1964
+ - Replacing default rule images with custom branded examples
1965
+ - Translating or customizing all modal text content
1966
+ - Providing localized photo guidelines with custom imagery
1967
+ - A/B testing different upload instructions
1968
+
1969
+ ### Available Image Slots
1970
+
1971
+ | Property | Description | Default |
1972
+ |----------|-------------|---------|
1973
+ | `ruleGoodExample` | Good photo example (rule 1 image) | Built-in asset |
1974
+ | `ruleBadExample1` | Bad example: cluttered background | Built-in asset |
1975
+ | `ruleBadExample2` | Bad example: poor lighting | Built-in asset |
1976
+ | `ruleBadExample3` | Bad example: cropped body | Built-in asset |
1977
+ | `ruleBadExample4` | Bad example: multiple people | Built-in asset |
1978
+ | `uploadIcon` | Upload area icon | Built-in SVG |
1979
+
1980
+ ### Available Text Slots
1981
+
1982
+ | Property | Description | Fallback Localization Key |
1983
+ |----------|-------------|---------------------------|
1984
+ | `title` | Modal header title | `product.virtual_try_on.title` |
1985
+ | `editPhotoTitle` | Title when editing/cropping photo | `product.virtual_try_on.edit_photo_title` |
1986
+ | `uploadPrompt` | Main upload prompt text | `product.virtual_try_on.upload_prompt` |
1987
+ | `uploadRequirements` | File requirements text | `product.virtual_try_on.upload_requirements` |
1988
+ | `uploadInfo` | Additional upload info | `product.virtual_try_on.upload_info` |
1989
+ | `rule1` | Rule 1 description | `product.virtual_try_on.rule_1` |
1990
+ | `rule2` | Rule 2 description | `product.virtual_try_on.rule_2` |
1991
+ | `rule3` | Rule 3 description | `product.virtual_try_on.rule_3` |
1992
+ | `rule4` | Rule 4 description | `product.virtual_try_on.rule_4` |
1993
+ | `rule5` | Rule 5 description | `product.virtual_try_on.rule_5` |
1994
+ | `rule6` | Rule 6 description | `product.virtual_try_on.rule_6` |
1995
+ | `processingTitle` | Processing overlay title | `product.virtual_try_on.processing` |
1996
+ | `processingMessage` | Processing overlay message | `product.virtual_try_on.processing_message` |
1997
+ | `retryUpload` | Retry upload button text | `product.virtual_try_on.retry` |
1998
+
1999
+ ### Example: Custom Images and Texts
2000
+
2001
+ ```tsx
2002
+ import PluginModule, { Component } from '@akinon/next/components/plugin-module';
2003
+
2004
+ <PluginModule
2005
+ component={Component.VirtualTryOnPlugin}
2006
+ props={{
2007
+ product: data.product,
2008
+ settings: {
2009
+ customStyles: {
2010
+ // Custom button styling
2011
+ button: 'bg-purple-600 hover:bg-purple-700 text-white font-bold px-6 py-3 rounded-lg',
2012
+
2013
+ // Custom Upload Modal Images
2014
+ uploadModalImages: {
2015
+ ruleGoodExample: 'https://cdn.example.com/vto/good-example.jpg',
2016
+ ruleBadExample1: 'https://cdn.example.com/vto/bad-background.jpg',
2017
+ ruleBadExample2: 'https://cdn.example.com/vto/bad-lighting.jpg',
2018
+ ruleBadExample3: 'https://cdn.example.com/vto/bad-cropped.jpg',
2019
+ ruleBadExample4: 'https://cdn.example.com/vto/bad-multiple.jpg',
2020
+ uploadIcon: 'https://cdn.example.com/vto/upload-icon.svg'
2021
+ },
2022
+
2023
+ // Custom Upload Modal Texts
2024
+ uploadModalTexts: {
2025
+ title: '🎭 Virtual Try-On Studio',
2026
+ editPhotoTitle: '✂️ Adjust Your Photo',
2027
+ uploadPrompt: '📸 Drag & drop your photo here',
2028
+ uploadRequirements: 'JPEG or PNG, max 5MB',
2029
+ uploadInfo: 'Your photo will be processed securely',
2030
+ rule1: '🌟 Use a plain background',
2031
+ rule2: '💡 Ensure good lighting',
2032
+ rule3: '👤 Show your full body',
2033
+ rule4: '🚫 No multiple people',
2034
+ rule5: '📐 Face the camera directly',
2035
+ rule6: '👔 Wear fitted clothing',
2036
+ processingTitle: '✨ Creating your look...',
2037
+ processingMessage: 'Our AI is working its magic!',
2038
+ retryUpload: '🔄 Try another photo'
2039
+ }
2040
+ }
2041
+ }
2042
+ }}
2043
+ />
2044
+ ```
2045
+
2046
+ ### TypeScript Interfaces
2047
+
2048
+ ```ts
2049
+ interface VirtualTryOnModalImages {
2050
+ ruleGoodExample?: string;
2051
+ ruleBadExample1?: string;
2052
+ ruleBadExample2?: string;
2053
+ ruleBadExample3?: string;
2054
+ ruleBadExample4?: string;
2055
+ uploadIcon?: string;
2056
+ }
2057
+
2058
+ interface VirtualTryOnModalTexts {
2059
+ title?: string;
2060
+ editPhotoTitle?: string;
2061
+ uploadPrompt?: string;
2062
+ uploadRequirements?: string;
2063
+ uploadInfo?: string;
2064
+ rule1?: string;
2065
+ rule2?: string;
2066
+ rule3?: string;
2067
+ rule4?: string;
2068
+ rule5?: string;
2069
+ rule6?: string;
2070
+ processingTitle?: string;
2071
+ processingMessage?: string;
2072
+ retryUpload?: string;
2073
+ }
2074
+
2075
+ // Usage in VirtualTryOnPluginSettings
2076
+ interface VirtualTryOnPluginSettings {
2077
+ customStyles?: {
2078
+ // ... other style slots
2079
+ uploadModalImages?: VirtualTryOnModalImages;
2080
+ uploadModalTexts?: VirtualTryOnModalTexts;
2081
+ };
2082
+ }
2083
+ ```
2084
+
2085
+ ### Fallback Behavior
2086
+
2087
+ If a custom image or text is not provided, the component automatically falls back to:
2088
+
2089
+ 1. **Images**: Built-in default assets from the package
2090
+ 2. **Texts**: Localized strings via `useLocalization()` hook with the corresponding translation key
2091
+
2092
+ This allows partial customization - you can override only the images or texts you need while keeping defaults for the rest.
2093
+
1698
2094
  ## Styling Reference
1699
2095
 
1700
2096
  ### Button Targets
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akinon/pz-virtual-try-on",
3
- "version": "2.0.0-beta.16",
3
+ "version": "2.0.0-beta.18",
4
4
  "license": "MIT",
5
5
  "main": "src/index.ts",
6
6
  "peerDependencies": {
@@ -8,10 +8,11 @@
8
8
  "react-dom": "^18.0.0 || ^19.0.0"
9
9
  },
10
10
  "dependencies": {
11
- "@akinon/next": "2.0.0-beta.16",
11
+ "@akinon/next": "2.0.0-beta.18",
12
12
  "clsx": "^2.0.0",
13
13
  "tailwind-merge": "^2.0.0",
14
- "react-image-crop": "^11.0.5"
14
+ "react-image-crop": "^11.0.5",
15
+ "html5-qrcode": "^2.3.8"
15
16
  },
16
17
  "devDependencies": {
17
18
  "@types/node": "^18.7.8",