@pagamio/frontend-commons-lib 0.8.349 → 0.8.350

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.
@@ -13,6 +13,12 @@ export interface ImageUploaderProps {
13
13
  showPreview?: boolean;
14
14
  value?: string;
15
15
  onChange?: (url: string | null) => void;
16
+ /**
17
+ * When true (default) the image is resized to 1920×1920 and converted
18
+ * to WebP before upload — correct for photos. Set false for assets that
19
+ * must keep their exact bytes/dimensions
20
+ */
21
+ processImage?: boolean;
16
22
  }
17
23
  declare const ImageUploader: React.FC<ImageUploaderProps>;
18
24
  export default ImageUploader;
@@ -1,18 +1,21 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Image as ImageIcon, Loader2, Upload, X } from 'lucide-react';
3
3
  import { useDropzone } from 'react-dropzone';
4
- import { useCallback, useState } from 'react';
4
+ import { useCallback, useMemo, useState } from 'react';
5
5
  import { Button, cn, useToast } from '../..';
6
6
  import { useImageUpload } from '../../shared/hooks/useImageUpload';
7
7
  import { Progress } from './Progress';
8
+ const PHOTO_FILE_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
9
+ const RAW_FILE_TYPES = ['image/png', 'image/svg+xml', 'image/webp', 'image/x-icon', 'image/vnd.microsoft.icon'];
8
10
  const ImageUploader = ({ project, env, endpoint, onUploadSuccess, onError, className, disabled = false, maxFileSize = 5 * 1024 * 1024, // 5MB default
9
- acceptedFileTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'], placeholder = 'Click to upload or drag and drop an image', showPreview = true, value, onChange, }) => {
11
+ acceptedFileTypes, placeholder = 'Click to upload or drag and drop an image', showPreview = true, value, onChange, processImage = true, }) => {
12
+ const resolvedFileTypes = useMemo(() => acceptedFileTypes ?? (processImage ? PHOTO_FILE_TYPES : RAW_FILE_TYPES), [acceptedFileTypes, processImage]);
10
13
  const [previewUrl, setPreviewUrl] = useState(value || null);
11
14
  const [isUploading, setIsUploading] = useState(false);
12
15
  const [uploadProgress, setUploadProgress] = useState(0);
13
16
  const [error, setError] = useState(null);
14
17
  const { addToast } = useToast();
15
- const { uploadFile } = useImageUpload({ project, env, endpoint });
18
+ const { uploadFile } = useImageUpload({ project, env, endpoint, processImage });
16
19
  const handleFileUpload = async (file) => {
17
20
  if (disabled)
18
21
  return;
@@ -21,8 +24,8 @@ acceptedFileTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'], plac
21
24
  setUploadProgress(0);
22
25
  try {
23
26
  // Validate file type
24
- if (!acceptedFileTypes.includes(file.type)) {
25
- throw new Error(`File type not supported. Accepted types: ${acceptedFileTypes.join(', ')}`);
27
+ if (!resolvedFileTypes.includes(file.type)) {
28
+ throw new Error(`File type not supported. Accepted types: ${resolvedFileTypes.join(', ')}`);
26
29
  }
27
30
  // Validate file size
28
31
  if (file.size > maxFileSize) {
@@ -76,10 +79,10 @@ acceptedFileTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'], plac
76
79
  if (file) {
77
80
  handleFileUpload(file);
78
81
  }
79
- }, [disabled, acceptedFileTypes, maxFileSize]);
82
+ }, [disabled, resolvedFileTypes, maxFileSize]);
80
83
  const { getRootProps, getInputProps, isDragActive } = useDropzone({
81
84
  onDrop,
82
- accept: acceptedFileTypes.reduce((acc, type) => {
85
+ accept: resolvedFileTypes.reduce((acc, type) => {
83
86
  acc[type] = [];
84
87
  return acc;
85
88
  }, {}),
@@ -91,6 +94,6 @@ acceptedFileTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'], plac
91
94
  setError(null);
92
95
  onChange?.(null);
93
96
  };
94
- return (_jsxs("div", { className: cn('w-full', className), children: [previewUrl && showPreview ? (_jsxs("div", { className: "relative mb-4", children: [_jsx("img", { src: previewUrl, alt: "Preview", className: "max-h-64 w-full rounded-lg object-contain border border-border" }), !isUploading && (_jsx(Button, { type: "button", variant: "destructive", size: "sm", className: "absolute top-2 right-2", onClick: handleRemove, children: _jsx(X, { className: "h-4 w-4" }) }))] })) : (_jsxs("div", { ...getRootProps(), className: cn('border-2 border-dashed border-input rounded-lg p-8 text-center cursor-pointer transition-colors hover:border-muted-foreground', isDragActive && 'border-primary bg-primary/10', disabled && 'cursor-not-allowed opacity-50', error && 'border-red-500 bg-red-50'), children: [_jsx("input", { ...getInputProps() }), isUploading ? (_jsxs("div", { className: "flex flex-col items-center space-y-2", children: [_jsx(Loader2, { className: "h-8 w-8 animate-spin text-primary" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Uploading image..." }), _jsx(Progress, { value: uploadProgress, className: "w-full max-w-xs" })] })) : (_jsxs("div", { className: "flex flex-col items-center space-y-2", children: [isDragActive ? (_jsx(Upload, { className: "h-8 w-8 text-primary" })) : (_jsx(ImageIcon, { className: "h-8 w-8 text-muted-foreground" })), _jsx("p", { className: "text-sm text-muted-foreground", children: isDragActive ? 'Drop the image here' : placeholder }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["Supported formats: ", acceptedFileTypes.map((type) => type.split('/')[1]).join(', ')] }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["Max size: ", Math.round(maxFileSize / 1024 / 1024), "MB"] })] }))] })), error && _jsx("p", { className: "mt-2 text-sm text-red-600", children: error })] }));
97
+ return (_jsxs("div", { className: cn('w-full', className), children: [previewUrl && showPreview ? (_jsxs("div", { className: "relative mb-4", children: [_jsx("img", { src: previewUrl, alt: "Preview", className: "max-h-64 w-full rounded-lg object-contain border border-border" }), !isUploading && (_jsx(Button, { type: "button", variant: "destructive", size: "sm", className: "absolute top-2 right-2", onClick: handleRemove, children: _jsx(X, { className: "h-4 w-4" }) }))] })) : (_jsxs("div", { ...getRootProps(), className: cn('border-2 border-dashed border-input rounded-lg p-8 text-center cursor-pointer transition-colors hover:border-muted-foreground', isDragActive && 'border-primary bg-primary/10', disabled && 'cursor-not-allowed opacity-50', error && 'border-red-500 bg-red-50'), children: [_jsx("input", { ...getInputProps() }), isUploading ? (_jsxs("div", { className: "flex flex-col items-center space-y-2", children: [_jsx(Loader2, { className: "h-8 w-8 animate-spin text-primary" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Uploading image..." }), _jsx(Progress, { value: uploadProgress, className: "w-full max-w-xs" })] })) : (_jsxs("div", { className: "flex flex-col items-center space-y-2", children: [isDragActive ? (_jsx(Upload, { className: "h-8 w-8 text-primary" })) : (_jsx(ImageIcon, { className: "h-8 w-8 text-muted-foreground" })), _jsx("p", { className: "text-sm text-muted-foreground", children: isDragActive ? 'Drop the image here' : placeholder }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["Supported formats: ", resolvedFileTypes.map((type) => type.split('/')[1]).join(', ')] }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["Max size: ", Math.round(maxFileSize / 1024 / 1024), "MB"] })] }))] })), error && _jsx("p", { className: "mt-2 text-sm text-red-600", children: error })] }));
95
98
  };
96
99
  export default ImageUploader;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pagamio/frontend-commons-lib",
3
3
  "description": "Pagamio library for Frontend reusable components like the form engine and table container",
4
- "version": "0.8.349",
4
+ "version": "0.8.350",
5
5
  "publishConfig": {
6
6
  "access": "public",
7
7
  "provenance": false