@akinon/pz-virtual-try-on 1.119.0-rc.3 → 2.0.0-beta.13
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 +3 -75
- package/README.md +7 -403
- package/package.json +5 -6
- package/src/hooks/use-image-cropper.ts +8 -58
- package/src/hooks/use-virtual-try-on-async.ts +0 -1
- package/src/hooks/use-virtual-try-on.ts +4 -30
- package/src/index.ts +1 -26
- package/src/types/index.ts +0 -32
- package/src/utils/error-mapping.ts +1 -3
- package/src/utils/index.ts +0 -115
- package/src/views/basket-async-modal.tsx +2 -7
- package/src/views/main.tsx +1 -15
- package/src/views/virtual-try-on-upload-modal.tsx +44 -62
- package/src/components/barcode-scanner.tsx +0 -422
- package/src/data/barcode-endpoints.ts +0 -34
- package/src/hooks/use-barcode-search.ts +0 -172
- package/src/types/barcode.ts +0 -308
- package/src/views/barcode-scanner-button.tsx +0 -63
- package/src/views/barcode-scanner-modal.tsx +0 -632
- package/src/views/barcode-scanner-plugin.tsx +0 -232
package/src/types/barcode.ts
DELETED
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Product, Pagination, Facet, SortOption } from '@akinon/next/types';
|
|
3
|
-
|
|
4
|
-
// ==================== BARCODE SCANNER TYPES ====================
|
|
5
|
-
|
|
6
|
-
export type BarcodeFormat =
|
|
7
|
-
| 'QR_CODE'
|
|
8
|
-
| 'DATA_MATRIX'
|
|
9
|
-
| 'AZTEC'
|
|
10
|
-
| 'PDF_417'
|
|
11
|
-
| 'EAN_8'
|
|
12
|
-
| 'EAN_13'
|
|
13
|
-
| 'UPC_A'
|
|
14
|
-
| 'UPC_E'
|
|
15
|
-
| 'CODE_39'
|
|
16
|
-
| 'CODE_93'
|
|
17
|
-
| 'CODE_128'
|
|
18
|
-
| 'CODABAR'
|
|
19
|
-
| 'ITF'
|
|
20
|
-
| 'RSS_14'
|
|
21
|
-
| 'RSS_EXPANDED';
|
|
22
|
-
|
|
23
|
-
export interface BarcodeScanResult {
|
|
24
|
-
text: string;
|
|
25
|
-
format: BarcodeFormat;
|
|
26
|
-
timestamp: number;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface BarcodeSearchResponse {
|
|
30
|
-
pagination: Pagination;
|
|
31
|
-
facets: Facet[];
|
|
32
|
-
sorters: SortOption[];
|
|
33
|
-
search_text: string | null;
|
|
34
|
-
products: Product[];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface BarcodeSearchRequest {
|
|
38
|
-
barcode: string;
|
|
39
|
-
page?: number;
|
|
40
|
-
limit?: number;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface BarcodeScannerState {
|
|
44
|
-
isScanning: boolean;
|
|
45
|
-
hasPermission: boolean | null;
|
|
46
|
-
error: string | null;
|
|
47
|
-
lastScanResult: BarcodeScanResult | null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface ScannedProductState {
|
|
51
|
-
products: Product[];
|
|
52
|
-
isLoading: boolean;
|
|
53
|
-
error: string | null;
|
|
54
|
-
searchedBarcode: string | null;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// ==================== BARCODE COMPONENT PROPS ====================
|
|
58
|
-
|
|
59
|
-
export interface BarcodeScannerButtonProps {
|
|
60
|
-
onClick: () => void;
|
|
61
|
-
className?: string;
|
|
62
|
-
disabled?: boolean;
|
|
63
|
-
settings?: BarcodeScannerSettings;
|
|
64
|
-
style?: React.CSSProperties;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export interface BarcodeScannerModalProps {
|
|
68
|
-
isOpen: boolean;
|
|
69
|
-
onClose: () => void;
|
|
70
|
-
onProductFound?: (products: Product[]) => void;
|
|
71
|
-
onContinueToVTO?: (products: Product[]) => void;
|
|
72
|
-
className?: string;
|
|
73
|
-
settings?: BarcodeScannerSettings;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export interface BarcodeScannerProps {
|
|
77
|
-
onScan: (result: BarcodeScanResult) => void;
|
|
78
|
-
onError?: (error: Error) => void;
|
|
79
|
-
onPermissionDenied?: () => void;
|
|
80
|
-
isActive: boolean;
|
|
81
|
-
className?: string;
|
|
82
|
-
settings?: BarcodeScannerSettings;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export interface ScannedProductCardProps {
|
|
86
|
-
product: Product;
|
|
87
|
-
isSelected?: boolean;
|
|
88
|
-
onSelect?: (product: Product) => void;
|
|
89
|
-
onRemove?: (product: Product) => void;
|
|
90
|
-
className?: string;
|
|
91
|
-
settings?: BarcodeScannerSettings;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// ==================== BARCODE SETTINGS ====================
|
|
95
|
-
|
|
96
|
-
export interface BarcodeScannerSettings {
|
|
97
|
-
customStyles?: BarcodeScannerCustomStyles;
|
|
98
|
-
customRenderers?: BarcodeScannerCustomRenderers;
|
|
99
|
-
theme?: BarcodeScannerTheme;
|
|
100
|
-
cssVariables?: Record<string, string>;
|
|
101
|
-
// Supported barcode formats - defaults to all
|
|
102
|
-
supportedFormats?: BarcodeFormat[];
|
|
103
|
-
// Maximum number of products that can be scanned
|
|
104
|
-
maxProducts?: number;
|
|
105
|
-
// Whether to show the continue to VTO button
|
|
106
|
-
showContinueToVTO?: boolean;
|
|
107
|
-
// Sound on successful scan
|
|
108
|
-
playScanSound?: boolean;
|
|
109
|
-
// Vibrate on successful scan (mobile)
|
|
110
|
-
vibrateOnScan?: boolean;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export interface BarcodeScannerTheme {
|
|
114
|
-
colors?: {
|
|
115
|
-
primary?: string;
|
|
116
|
-
secondary?: string;
|
|
117
|
-
background?: string;
|
|
118
|
-
text?: string;
|
|
119
|
-
border?: string;
|
|
120
|
-
success?: string;
|
|
121
|
-
error?: string;
|
|
122
|
-
scannerOverlay?: string;
|
|
123
|
-
scannerFrame?: string;
|
|
124
|
-
scannerCorner?: string;
|
|
125
|
-
};
|
|
126
|
-
spacing?: {
|
|
127
|
-
xs?: string;
|
|
128
|
-
sm?: string;
|
|
129
|
-
md?: string;
|
|
130
|
-
lg?: string;
|
|
131
|
-
xl?: string;
|
|
132
|
-
};
|
|
133
|
-
borderRadius?: {
|
|
134
|
-
sm?: string;
|
|
135
|
-
md?: string;
|
|
136
|
-
lg?: string;
|
|
137
|
-
full?: string;
|
|
138
|
-
};
|
|
139
|
-
fonts?: {
|
|
140
|
-
primary?: string;
|
|
141
|
-
secondary?: string;
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export interface BarcodeScannerCustomStyles {
|
|
146
|
-
// Button styles
|
|
147
|
-
floatingButton?: string;
|
|
148
|
-
floatingButtonIcon?: string;
|
|
149
|
-
|
|
150
|
-
// Modal styles
|
|
151
|
-
modalOverlay?: string;
|
|
152
|
-
modalContainer?: string;
|
|
153
|
-
modalHeader?: string;
|
|
154
|
-
modalTitle?: string;
|
|
155
|
-
modalCloseButton?: string;
|
|
156
|
-
modalCloseIcon?: string;
|
|
157
|
-
modalContent?: string;
|
|
158
|
-
|
|
159
|
-
// Scanner styles
|
|
160
|
-
scannerContainer?: string;
|
|
161
|
-
scannerVideo?: string;
|
|
162
|
-
scannerOverlay?: string;
|
|
163
|
-
scannerFrame?: string;
|
|
164
|
-
scannerCornerTopLeft?: string;
|
|
165
|
-
scannerCornerTopRight?: string;
|
|
166
|
-
scannerCornerBottomLeft?: string;
|
|
167
|
-
scannerCornerBottomRight?: string;
|
|
168
|
-
scannerHelpText?: string;
|
|
169
|
-
scannerLine?: string;
|
|
170
|
-
|
|
171
|
-
// Product display styles
|
|
172
|
-
productListContainer?: string;
|
|
173
|
-
productList?: string;
|
|
174
|
-
productCard?: string;
|
|
175
|
-
productCardSelected?: string;
|
|
176
|
-
productImage?: string;
|
|
177
|
-
productImageWrapper?: string;
|
|
178
|
-
productInfo?: string;
|
|
179
|
-
productName?: string;
|
|
180
|
-
productPrice?: string;
|
|
181
|
-
productCheckmark?: string;
|
|
182
|
-
productRemoveButton?: string;
|
|
183
|
-
|
|
184
|
-
// Actions styles
|
|
185
|
-
actionsContainer?: string;
|
|
186
|
-
continueButton?: string;
|
|
187
|
-
continueButtonDisabled?: string;
|
|
188
|
-
scanMoreText?: string;
|
|
189
|
-
|
|
190
|
-
// Error and loading styles
|
|
191
|
-
errorContainer?: string;
|
|
192
|
-
errorMessage?: string;
|
|
193
|
-
errorIcon?: string;
|
|
194
|
-
errorRetryButton?: string;
|
|
195
|
-
loadingContainer?: string;
|
|
196
|
-
loadingSpinner?: string;
|
|
197
|
-
loadingText?: string;
|
|
198
|
-
|
|
199
|
-
// Permission denied styles
|
|
200
|
-
permissionDeniedContainer?: string;
|
|
201
|
-
permissionDeniedIcon?: string;
|
|
202
|
-
permissionDeniedTitle?: string;
|
|
203
|
-
permissionDeniedMessage?: string;
|
|
204
|
-
permissionDeniedButton?: string;
|
|
205
|
-
|
|
206
|
-
// Empty state styles
|
|
207
|
-
emptyStateContainer?: string;
|
|
208
|
-
emptyStateIcon?: string;
|
|
209
|
-
emptyStateTitle?: string;
|
|
210
|
-
emptyStateMessage?: string;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export interface BarcodeScannerCustomRenderers {
|
|
214
|
-
// Button renderers
|
|
215
|
-
renderFloatingButton?: (props: {
|
|
216
|
-
onClick: () => void;
|
|
217
|
-
className?: string;
|
|
218
|
-
}) => React.ReactNode;
|
|
219
|
-
renderFloatingButtonIcon?: () => React.ReactNode;
|
|
220
|
-
|
|
221
|
-
// Modal renderers
|
|
222
|
-
renderModal?: (props: BarcodeScannerModalProps) => React.ReactNode;
|
|
223
|
-
renderModalHeader?: (props: {
|
|
224
|
-
title: string;
|
|
225
|
-
onClose: () => void;
|
|
226
|
-
}) => React.ReactNode;
|
|
227
|
-
renderModalCloseButton?: (props: {
|
|
228
|
-
onClick: () => void;
|
|
229
|
-
}) => React.ReactNode;
|
|
230
|
-
renderModalCloseIcon?: () => React.ReactNode;
|
|
231
|
-
|
|
232
|
-
// Scanner renderers
|
|
233
|
-
renderScanner?: (props: BarcodeScannerProps) => React.ReactNode;
|
|
234
|
-
renderScannerOverlay?: (props: {
|
|
235
|
-
isScanning: boolean;
|
|
236
|
-
}) => React.ReactNode;
|
|
237
|
-
renderScannerFrame?: () => React.ReactNode;
|
|
238
|
-
renderScannerCorners?: () => React.ReactNode;
|
|
239
|
-
renderScannerHelpText?: (props: { text: string }) => React.ReactNode;
|
|
240
|
-
renderScannerLine?: () => React.ReactNode;
|
|
241
|
-
|
|
242
|
-
// Product renderers
|
|
243
|
-
renderProductList?: (props: {
|
|
244
|
-
products: Product[];
|
|
245
|
-
onRemove: (product: Product) => void;
|
|
246
|
-
}) => React.ReactNode;
|
|
247
|
-
renderProductCard?: (props: ScannedProductCardProps) => React.ReactNode;
|
|
248
|
-
renderProductImage?: (props: {
|
|
249
|
-
imageUrl: string;
|
|
250
|
-
alt: string;
|
|
251
|
-
className?: string;
|
|
252
|
-
}) => React.ReactNode;
|
|
253
|
-
renderProductInfo?: (props: {
|
|
254
|
-
product: Product;
|
|
255
|
-
}) => React.ReactNode;
|
|
256
|
-
renderProductCheckmark?: () => React.ReactNode;
|
|
257
|
-
renderProductRemoveButton?: (props: {
|
|
258
|
-
onClick: () => void;
|
|
259
|
-
}) => React.ReactNode;
|
|
260
|
-
|
|
261
|
-
// Actions renderers
|
|
262
|
-
renderActionsContainer?: (props: {
|
|
263
|
-
children: React.ReactNode;
|
|
264
|
-
}) => React.ReactNode;
|
|
265
|
-
renderContinueButton?: (props: {
|
|
266
|
-
onClick: () => void;
|
|
267
|
-
disabled: boolean;
|
|
268
|
-
text: string;
|
|
269
|
-
}) => React.ReactNode;
|
|
270
|
-
renderScanMoreText?: (props: { text: string }) => React.ReactNode;
|
|
271
|
-
|
|
272
|
-
// Error renderers
|
|
273
|
-
renderError?: (props: {
|
|
274
|
-
error: string;
|
|
275
|
-
onRetry?: () => void;
|
|
276
|
-
}) => React.ReactNode;
|
|
277
|
-
renderErrorIcon?: () => React.ReactNode;
|
|
278
|
-
renderErrorMessage?: (props: { message: string }) => React.ReactNode;
|
|
279
|
-
renderErrorRetryButton?: (props: {
|
|
280
|
-
onClick: () => void;
|
|
281
|
-
text: string;
|
|
282
|
-
}) => React.ReactNode;
|
|
283
|
-
|
|
284
|
-
// Loading renderers
|
|
285
|
-
renderLoading?: (props: { text?: string }) => React.ReactNode;
|
|
286
|
-
renderLoadingSpinner?: () => React.ReactNode;
|
|
287
|
-
renderLoadingText?: (props: { text: string }) => React.ReactNode;
|
|
288
|
-
|
|
289
|
-
// Permission denied renderers
|
|
290
|
-
renderPermissionDenied?: (props: {
|
|
291
|
-
onRequestPermission?: () => void;
|
|
292
|
-
}) => React.ReactNode;
|
|
293
|
-
renderPermissionDeniedIcon?: () => React.ReactNode;
|
|
294
|
-
renderPermissionDeniedTitle?: (props: { title: string }) => React.ReactNode;
|
|
295
|
-
renderPermissionDeniedMessage?: (props: {
|
|
296
|
-
message: string;
|
|
297
|
-
}) => React.ReactNode;
|
|
298
|
-
renderPermissionDeniedButton?: (props: {
|
|
299
|
-
onClick: () => void;
|
|
300
|
-
text: string;
|
|
301
|
-
}) => React.ReactNode;
|
|
302
|
-
|
|
303
|
-
// Empty state renderers
|
|
304
|
-
renderEmptyState?: () => React.ReactNode;
|
|
305
|
-
renderEmptyStateIcon?: () => React.ReactNode;
|
|
306
|
-
renderEmptyStateTitle?: (props: { title: string }) => React.ReactNode;
|
|
307
|
-
renderEmptyStateMessage?: (props: { message: string }) => React.ReactNode;
|
|
308
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { twMerge } from 'tailwind-merge';
|
|
5
|
-
import { useLocalization } from '@akinon/next/hooks';
|
|
6
|
-
import type { BarcodeScannerButtonProps } from '../types/barcode';
|
|
7
|
-
|
|
8
|
-
export function BarcodeScannerButton({
|
|
9
|
-
onClick,
|
|
10
|
-
className,
|
|
11
|
-
disabled = false,
|
|
12
|
-
settings,
|
|
13
|
-
style
|
|
14
|
-
}: BarcodeScannerButtonProps) {
|
|
15
|
-
const { t } = useLocalization();
|
|
16
|
-
|
|
17
|
-
// Custom button renderer
|
|
18
|
-
if (settings?.customRenderers?.renderFloatingButton) {
|
|
19
|
-
return settings.customRenderers.renderFloatingButton({
|
|
20
|
-
onClick,
|
|
21
|
-
className
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<button
|
|
27
|
-
onClick={onClick}
|
|
28
|
-
disabled={disabled}
|
|
29
|
-
aria-label={t('product.barcode_scanner.button_label')}
|
|
30
|
-
style={style}
|
|
31
|
-
className={twMerge(
|
|
32
|
-
// Base styles - fixed position bottom right, mobile only
|
|
33
|
-
'fixed bottom-20 right-4 z-50 md:hidden',
|
|
34
|
-
// Button appearance
|
|
35
|
-
'px-4 py-3 rounded-full',
|
|
36
|
-
'bg-black text-white',
|
|
37
|
-
'flex items-center justify-center',
|
|
38
|
-
'shadow-lg hover:shadow-xl',
|
|
39
|
-
'transition-all duration-200',
|
|
40
|
-
'hover:scale-105 active:scale-95',
|
|
41
|
-
'text-sm font-medium whitespace-nowrap',
|
|
42
|
-
// Disabled state
|
|
43
|
-
disabled && 'opacity-50 cursor-not-allowed hover:scale-100',
|
|
44
|
-
// Custom styles
|
|
45
|
-
settings?.customStyles?.floatingButton,
|
|
46
|
-
className
|
|
47
|
-
)}
|
|
48
|
-
>
|
|
49
|
-
{settings?.customRenderers?.renderFloatingButtonIcon ? (
|
|
50
|
-
settings.customRenderers.renderFloatingButtonIcon()
|
|
51
|
-
) : (
|
|
52
|
-
<span
|
|
53
|
-
className={twMerge(
|
|
54
|
-
'text-sm font-medium',
|
|
55
|
-
settings?.customStyles?.floatingButtonIcon
|
|
56
|
-
)}
|
|
57
|
-
>
|
|
58
|
-
{t('product.barcode_scanner.button_text')}
|
|
59
|
-
</span>
|
|
60
|
-
)}
|
|
61
|
-
</button>
|
|
62
|
-
);
|
|
63
|
-
}
|