@zauru-sdk/components 2.0.200 → 2.0.202
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
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [2.0.202](https://github.com/intuitiva/zauru-typescript-sdk/compare/v2.0.201...v2.0.202) (2025-03-20)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @zauru-sdk/components
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [2.0.201](https://github.com/intuitiva/zauru-typescript-sdk/compare/v2.0.200...v2.0.201) (2025-03-20)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @zauru-sdk/components
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
## [2.0.200](https://github.com/intuitiva/zauru-typescript-sdk/compare/v2.0.199...v2.0.200) (2025-03-19)
|
|
7
23
|
|
|
8
24
|
**Note:** Version bump only for package @zauru-sdk/components
|
|
@@ -14,6 +14,8 @@ type Props = {
|
|
|
14
14
|
defaultValue?: string | File;
|
|
15
15
|
download?: boolean;
|
|
16
16
|
required?: boolean;
|
|
17
|
+
optimizeImages?: boolean;
|
|
18
|
+
zauruBaseURL?: string;
|
|
17
19
|
};
|
|
18
20
|
export declare const FileUploadField: (props: Props) => import("react/jsx-runtime").JSX.Element;
|
|
19
21
|
export {};
|
|
@@ -3,7 +3,7 @@ import { DownloadIconSVG, IdeaIconSVG } from "@zauru-sdk/icons";
|
|
|
3
3
|
import { useState, useEffect, useRef } from "react";
|
|
4
4
|
import { useFormContext } from "react-hook-form";
|
|
5
5
|
export const FileUploadField = (props) => {
|
|
6
|
-
const { id, name, title, helpText, hint, onChange, readOnly = false, fileTypes = [], showAvailableTypes = false, className, defaultValue, download = false, required = false, } = props;
|
|
6
|
+
const { id, name, title, helpText, hint, onChange, readOnly = false, fileTypes = [], showAvailableTypes = false, className, defaultValue, download = false, required = false, optimizeImages = true, zauruBaseURL = "https://zauru.herokuapp.com", } = props;
|
|
7
7
|
const { register: tempRegister, setValue, formState: { errors }, } = useFormContext() || { formState: {} };
|
|
8
8
|
const error = errors ? errors[name] : undefined;
|
|
9
9
|
const register = tempRegister ? tempRegister(name, { required }) : undefined;
|
|
@@ -31,26 +31,59 @@ export const FileUploadField = (props) => {
|
|
|
31
31
|
const borderColor = error ? "border-red-500" : `border-${color}-500`;
|
|
32
32
|
/**
|
|
33
33
|
* Función que se dispara cuando el usuario selecciona un archivo.
|
|
34
|
-
*
|
|
34
|
+
* Si optimizeImages está activo y se trata de una imagen, la convierte a WebP
|
|
35
|
+
* usando la librería browser-image-compression.
|
|
35
36
|
*/
|
|
36
|
-
const handleInputChange = (event) => {
|
|
37
|
-
onChange && onChange(event);
|
|
38
|
-
setFileDeleted(false);
|
|
37
|
+
const handleInputChange = async (event) => {
|
|
39
38
|
if (event.target.files && event.target.files.length > 0) {
|
|
40
|
-
|
|
41
|
-
//
|
|
42
|
-
if (file && file.type.startsWith("image/")) {
|
|
39
|
+
let file = event.target.files[0];
|
|
40
|
+
// Si se activa la optimización y es imagen, se convierte a WebP
|
|
41
|
+
if (file && file.type.startsWith("image/") && optimizeImages) {
|
|
42
|
+
try {
|
|
43
|
+
/*
|
|
44
|
+
const options: Options = {
|
|
45
|
+
fileType: "image/webp", // Especificamos el formato WebP
|
|
46
|
+
initialQuality: 0.7, // Calidad inicial (puedes ajustar este valor)
|
|
47
|
+
maxSizeMB: 1, // Tamaño máximo (opcional)
|
|
48
|
+
maxWidthOrHeight: 1920, // Dimensión máxima (opcional)
|
|
49
|
+
useWebWorker: true,
|
|
50
|
+
};
|
|
51
|
+
// Después de la compresión, renombramos el archivo:
|
|
52
|
+
const compressedFile = await imageCompression(file, options);
|
|
53
|
+
const newFile = new File(
|
|
54
|
+
[compressedFile],
|
|
55
|
+
file.name.replace(/\.[^.]+$/, ".webp"),
|
|
56
|
+
{
|
|
57
|
+
type: file.type,
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
file = newFile;
|
|
61
|
+
*/
|
|
62
|
+
console.log("Archivo convertido:", file.name, file.type);
|
|
63
|
+
const objectUrl = URL.createObjectURL(file);
|
|
64
|
+
setPreviewSrc(objectUrl);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
console.error("Error al convertir la imagen a WebP:", error);
|
|
68
|
+
const objectUrl = URL.createObjectURL(file);
|
|
69
|
+
setPreviewSrc(objectUrl);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else if (file && file.type.startsWith("image/")) {
|
|
43
73
|
const objectUrl = URL.createObjectURL(file);
|
|
44
74
|
setPreviewSrc(objectUrl);
|
|
45
75
|
}
|
|
46
76
|
else {
|
|
47
77
|
setPreviewSrc(null);
|
|
48
78
|
}
|
|
79
|
+
// Actualizamos el input para que contenga el archivo convertido
|
|
80
|
+
const dataTransfer = new DataTransfer();
|
|
81
|
+
dataTransfer.items.add(file);
|
|
82
|
+
event.target.files = dataTransfer.files;
|
|
49
83
|
// Importamos dinámicamente DirectUpload solo en el cliente
|
|
50
84
|
import("@rails/activestorage")
|
|
51
85
|
.then(({ DirectUpload }) => {
|
|
52
|
-
const uploadUrl =
|
|
53
|
-
// Inicializamos el progreso y activamos el estado de subida
|
|
86
|
+
const uploadUrl = `${zauruBaseURL}/api/direct_uploads`;
|
|
54
87
|
setUploading(true);
|
|
55
88
|
setUploadProgress(0);
|
|
56
89
|
const directUpload = new DirectUpload(file, uploadUrl, {
|
|
@@ -67,17 +100,36 @@ export const FileUploadField = (props) => {
|
|
|
67
100
|
setUploading(false);
|
|
68
101
|
if (error) {
|
|
69
102
|
console.error("Error al subir el archivo:", error);
|
|
70
|
-
// Manejo de error según tus necesidades
|
|
71
103
|
}
|
|
72
104
|
else {
|
|
73
|
-
// blob.signed_id es el identificador que debes enviar a tu API
|
|
74
|
-
console.log("Archivo subido exitosamente. Blob:", blob);
|
|
75
105
|
setValue(name, blob.signed_id);
|
|
106
|
+
setValue(`${name}_file_type`, blob.content_type);
|
|
107
|
+
// Input hidden para el signed_id
|
|
108
|
+
const hiddenField = document.createElement("input");
|
|
109
|
+
hiddenField.setAttribute("type", "hidden");
|
|
110
|
+
hiddenField.setAttribute("value", blob.signed_id);
|
|
111
|
+
hiddenField.setAttribute("name", name);
|
|
112
|
+
// Input hidden para el content_type
|
|
113
|
+
const typeHiddenField = document.createElement("input");
|
|
114
|
+
typeHiddenField.setAttribute("type", "hidden");
|
|
115
|
+
typeHiddenField.setAttribute("value", blob.content_type);
|
|
116
|
+
typeHiddenField.setAttribute("name", `${name}_file_type`);
|
|
117
|
+
const formElement = document.querySelector("form");
|
|
118
|
+
if (formElement) {
|
|
119
|
+
formElement.appendChild(hiddenField);
|
|
120
|
+
formElement.appendChild(typeHiddenField);
|
|
121
|
+
}
|
|
122
|
+
// Removemos el atributo "name" del input file para evitar enviar el archivo
|
|
123
|
+
if (fileInputRef.current) {
|
|
124
|
+
fileInputRef.current.removeAttribute("name");
|
|
125
|
+
}
|
|
76
126
|
}
|
|
77
127
|
});
|
|
78
128
|
})
|
|
79
129
|
.catch((err) => console.error("Error al cargar DirectUpload:", err));
|
|
80
130
|
}
|
|
131
|
+
onChange && onChange(event);
|
|
132
|
+
setFileDeleted(false);
|
|
81
133
|
};
|
|
82
134
|
/**
|
|
83
135
|
* Función para eliminar el archivo. Además de limpiar la vista previa,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zauru-sdk/components",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.202",
|
|
4
4
|
"description": "Componentes reutilizables en las WebApps de Zauru.",
|
|
5
5
|
"main": "./dist/esm/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
"@zauru-sdk/hooks": "^2.0.198",
|
|
40
40
|
"@zauru-sdk/icons": "^2.0.188",
|
|
41
41
|
"@zauru-sdk/types": "^2.0.197",
|
|
42
|
-
"@zauru-sdk/utils": "^2.0.
|
|
42
|
+
"@zauru-sdk/utils": "^2.0.202",
|
|
43
|
+
"browser-image-compression": "^2.0.2",
|
|
43
44
|
"framer-motion": "^11.7.0",
|
|
44
45
|
"jsonwebtoken": "^9.0.2",
|
|
45
46
|
"react": "^18.2.0",
|
|
@@ -51,5 +52,5 @@
|
|
|
51
52
|
"styled-components": "^5.3.5",
|
|
52
53
|
"zod": "^3.23.8"
|
|
53
54
|
},
|
|
54
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "02024107088737551a72e04666cfd3d297547c95"
|
|
55
56
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { DownloadIconSVG, IdeaIconSVG } from "@zauru-sdk/icons";
|
|
2
2
|
import React, { useState, useEffect, useRef } from "react";
|
|
3
3
|
import { useFormContext } from "react-hook-form";
|
|
4
|
+
/*
|
|
5
|
+
import imageCompression from "browser-image-compression";
|
|
6
|
+
import type { Options } from "browser-image-compression";
|
|
7
|
+
*/
|
|
4
8
|
|
|
5
9
|
type Props = {
|
|
6
10
|
id?: string;
|
|
@@ -17,6 +21,8 @@ type Props = {
|
|
|
17
21
|
defaultValue?: string | File;
|
|
18
22
|
download?: boolean;
|
|
19
23
|
required?: boolean;
|
|
24
|
+
optimizeImages?: boolean;
|
|
25
|
+
zauruBaseURL?: string;
|
|
20
26
|
};
|
|
21
27
|
|
|
22
28
|
export const FileUploadField = (props: Props) => {
|
|
@@ -34,6 +40,8 @@ export const FileUploadField = (props: Props) => {
|
|
|
34
40
|
defaultValue,
|
|
35
41
|
download = false,
|
|
36
42
|
required = false,
|
|
43
|
+
optimizeImages = true,
|
|
44
|
+
zauruBaseURL = "https://zauru.herokuapp.com",
|
|
37
45
|
} = props;
|
|
38
46
|
|
|
39
47
|
const {
|
|
@@ -73,30 +81,62 @@ export const FileUploadField = (props: Props) => {
|
|
|
73
81
|
|
|
74
82
|
/**
|
|
75
83
|
* Función que se dispara cuando el usuario selecciona un archivo.
|
|
76
|
-
*
|
|
84
|
+
* Si optimizeImages está activo y se trata de una imagen, la convierte a WebP
|
|
85
|
+
* usando la librería browser-image-compression.
|
|
77
86
|
*/
|
|
78
|
-
const handleInputChange = (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
87
|
+
const handleInputChange = async (
|
|
88
|
+
event: React.ChangeEvent<HTMLInputElement>
|
|
89
|
+
) => {
|
|
82
90
|
if (event.target.files && event.target.files.length > 0) {
|
|
83
|
-
|
|
91
|
+
let file = event.target.files[0];
|
|
84
92
|
|
|
85
|
-
//
|
|
86
|
-
if (file && file.type.startsWith("image/")) {
|
|
93
|
+
// Si se activa la optimización y es imagen, se convierte a WebP
|
|
94
|
+
if (file && file.type.startsWith("image/") && optimizeImages) {
|
|
95
|
+
try {
|
|
96
|
+
/*
|
|
97
|
+
const options: Options = {
|
|
98
|
+
fileType: "image/webp", // Especificamos el formato WebP
|
|
99
|
+
initialQuality: 0.7, // Calidad inicial (puedes ajustar este valor)
|
|
100
|
+
maxSizeMB: 1, // Tamaño máximo (opcional)
|
|
101
|
+
maxWidthOrHeight: 1920, // Dimensión máxima (opcional)
|
|
102
|
+
useWebWorker: true,
|
|
103
|
+
};
|
|
104
|
+
// Después de la compresión, renombramos el archivo:
|
|
105
|
+
const compressedFile = await imageCompression(file, options);
|
|
106
|
+
const newFile = new File(
|
|
107
|
+
[compressedFile],
|
|
108
|
+
file.name.replace(/\.[^.]+$/, ".webp"),
|
|
109
|
+
{
|
|
110
|
+
type: file.type,
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
file = newFile;
|
|
114
|
+
*/
|
|
115
|
+
console.log("Archivo convertido:", file.name, file.type);
|
|
116
|
+
const objectUrl = URL.createObjectURL(file);
|
|
117
|
+
setPreviewSrc(objectUrl);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error("Error al convertir la imagen a WebP:", error);
|
|
120
|
+
const objectUrl = URL.createObjectURL(file);
|
|
121
|
+
setPreviewSrc(objectUrl);
|
|
122
|
+
}
|
|
123
|
+
} else if (file && file.type.startsWith("image/")) {
|
|
87
124
|
const objectUrl = URL.createObjectURL(file);
|
|
88
125
|
setPreviewSrc(objectUrl);
|
|
89
126
|
} else {
|
|
90
127
|
setPreviewSrc(null);
|
|
91
128
|
}
|
|
92
129
|
|
|
130
|
+
// Actualizamos el input para que contenga el archivo convertido
|
|
131
|
+
const dataTransfer = new DataTransfer();
|
|
132
|
+
dataTransfer.items.add(file);
|
|
133
|
+
event.target.files = dataTransfer.files;
|
|
134
|
+
|
|
93
135
|
// Importamos dinámicamente DirectUpload solo en el cliente
|
|
94
136
|
import("@rails/activestorage")
|
|
95
137
|
.then(({ DirectUpload }) => {
|
|
96
|
-
const uploadUrl =
|
|
97
|
-
"https://zauru.herokuapp.com/rails/active_storage/direct_uploads";
|
|
138
|
+
const uploadUrl = `${zauruBaseURL}/api/direct_uploads`;
|
|
98
139
|
|
|
99
|
-
// Inicializamos el progreso y activamos el estado de subida
|
|
100
140
|
setUploading(true);
|
|
101
141
|
setUploadProgress(0);
|
|
102
142
|
|
|
@@ -117,16 +157,39 @@ export const FileUploadField = (props: Props) => {
|
|
|
117
157
|
setUploading(false);
|
|
118
158
|
if (error) {
|
|
119
159
|
console.error("Error al subir el archivo:", error);
|
|
120
|
-
// Manejo de error según tus necesidades
|
|
121
160
|
} else {
|
|
122
|
-
// blob.signed_id es el identificador que debes enviar a tu API
|
|
123
|
-
console.log("Archivo subido exitosamente. Blob:", blob);
|
|
124
161
|
setValue(name, blob.signed_id);
|
|
162
|
+
setValue(`${name}_file_type`, blob.content_type);
|
|
163
|
+
|
|
164
|
+
// Input hidden para el signed_id
|
|
165
|
+
const hiddenField = document.createElement("input");
|
|
166
|
+
hiddenField.setAttribute("type", "hidden");
|
|
167
|
+
hiddenField.setAttribute("value", blob.signed_id);
|
|
168
|
+
hiddenField.setAttribute("name", name);
|
|
169
|
+
// Input hidden para el content_type
|
|
170
|
+
const typeHiddenField = document.createElement("input");
|
|
171
|
+
typeHiddenField.setAttribute("type", "hidden");
|
|
172
|
+
typeHiddenField.setAttribute("value", blob.content_type);
|
|
173
|
+
typeHiddenField.setAttribute("name", `${name}_file_type`);
|
|
174
|
+
|
|
175
|
+
const formElement = document.querySelector("form");
|
|
176
|
+
if (formElement) {
|
|
177
|
+
formElement.appendChild(hiddenField);
|
|
178
|
+
formElement.appendChild(typeHiddenField);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Removemos el atributo "name" del input file para evitar enviar el archivo
|
|
182
|
+
if (fileInputRef.current) {
|
|
183
|
+
fileInputRef.current.removeAttribute("name");
|
|
184
|
+
}
|
|
125
185
|
}
|
|
126
186
|
});
|
|
127
187
|
})
|
|
128
188
|
.catch((err) => console.error("Error al cargar DirectUpload:", err));
|
|
129
189
|
}
|
|
190
|
+
|
|
191
|
+
onChange && onChange(event);
|
|
192
|
+
setFileDeleted(false);
|
|
130
193
|
};
|
|
131
194
|
|
|
132
195
|
/**
|