@zauru-sdk/components 2.0.200 → 2.0.201

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,14 @@
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.201](https://github.com/intuitiva/zauru-typescript-sdk/compare/v2.0.200...v2.0.201) (2025-03-20)
7
+
8
+ **Note:** Version bump only for package @zauru-sdk/components
9
+
10
+
11
+
12
+
13
+
6
14
  ## [2.0.200](https://github.com/intuitiva/zauru-typescript-sdk/compare/v2.0.199...v2.0.200) (2025-03-19)
7
15
 
8
16
  **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
- * Además de actualizar la vista previa, inicia la subida directa a AWS.
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
- const file = event.target.files[0];
41
- // Actualizamos la vista previa para imágenes
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 = "https://zauru.herokuapp.com/rails/active_storage/direct_uploads";
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.200",
3
+ "version": "2.0.201",
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.200",
42
+ "@zauru-sdk/utils": "^2.0.201",
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": "03df85eff31f6d868ffd76806e59b32e214a821e"
55
+ "gitHead": "d5492dc01a6a06dbf6f94b6a273a3a5116147cac"
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
- * Además de actualizar la vista previa, inicia la subida directa a AWS.
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 = (event: React.ChangeEvent<HTMLInputElement>) => {
79
- onChange && onChange(event);
80
- setFileDeleted(false);
81
-
87
+ const handleInputChange = async (
88
+ event: React.ChangeEvent<HTMLInputElement>
89
+ ) => {
82
90
  if (event.target.files && event.target.files.length > 0) {
83
- const file = event.target.files[0];
91
+ let file = event.target.files[0];
84
92
 
85
- // Actualizamos la vista previa para imágenes
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
  /**