limbo-component 1.6.6 → 1.8.0
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/README.md +4 -5
- package/dist/limbo.cjs.js +5 -5
- package/dist/limbo.cjs.map +1 -1
- package/dist/limbo.css +1 -1
- package/dist/limbo.es.js +2164 -689
- package/dist/limbo.es.map +1 -1
- package/dist/limbo.min.js +6 -6
- package/dist/limbo.min.js.map +1 -1
- package/dist/limbo.umd.js +8 -8
- package/dist/limbo.umd.js.map +1 -1
- package/dist/types/App.d.ts.map +1 -1
- package/dist/types/components/CropperView.d.ts +2 -1
- package/dist/types/components/CropperView.d.ts.map +1 -1
- package/dist/types/components/Gallery.d.ts +18 -3
- package/dist/types/components/Gallery.d.ts.map +1 -1
- package/dist/types/components/ImageCard.d.ts.map +1 -1
- package/dist/types/components/ImageCardSkeleton.d.ts +6 -0
- package/dist/types/components/ImageCardSkeleton.d.ts.map +1 -0
- package/dist/types/components/ImageVariantsModal.d.ts.map +1 -1
- package/dist/types/core/ConfigManager.d.ts +143 -12
- package/dist/types/core/ConfigManager.d.ts.map +1 -1
- package/dist/types/core/LimboCore.d.ts +123 -0
- package/dist/types/core/LimboCore.d.ts.map +1 -1
- package/dist/types/hooks/useDebounce.d.ts +18 -0
- package/dist/types/hooks/useDebounce.d.ts.map +1 -0
- package/dist/types/services/responseAdapters.d.ts.map +1 -1
- package/dist/types/utils/CropperManager.d.ts +1 -0
- package/dist/types/utils/CropperManager.d.ts.map +1 -1
- package/dist/types/utils/downloadImage.d.ts +47 -0
- package/dist/types/utils/downloadImage.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/limbo.es.js
CHANGED
|
@@ -31,7 +31,7 @@ const DEFAULT_MESSAGES = {
|
|
|
31
31
|
"message.no_images": "No hay imágenes disponibles",
|
|
32
32
|
"message.upload_success": "Imagen subida correctamente",
|
|
33
33
|
"message.upload_error": "Error al subir la imagen",
|
|
34
|
-
"message.delete_confirm": "¿Estás seguro de que
|
|
34
|
+
"message.delete_confirm": "¿Estás seguro de que deseas eliminar esta imagen? Esta acción también eliminará todos sus recortes.",
|
|
35
35
|
"message.copy_success": "URL copiada al portapapeles",
|
|
36
36
|
"message.copy_error": "Error al copiar URL",
|
|
37
37
|
// Errores
|
|
@@ -219,17 +219,70 @@ class ConfigManager {
|
|
|
219
219
|
// libre por defecto
|
|
220
220
|
lockAspectRatio: false,
|
|
221
221
|
// Aspect ratios permitidos - formato: { label, value, ratio }
|
|
222
|
-
|
|
223
|
-
{ label: "📐 Libre", value: "", ratio: null },
|
|
224
|
-
{ label: "⬜ 1:1 (Cuadrado)", value: "1", ratio: 1 },
|
|
225
|
-
{ label: "📺 4:3 (Clásico)", value: "4/3", ratio: 4 / 3 },
|
|
226
|
-
{ label: "🖥️ 16:9 (Widescreen)", value: "16/9", ratio: 16 / 9 },
|
|
227
|
-
{ label: "📷 3:2 (Foto)", value: "3/2", ratio: 3 / 2 },
|
|
228
|
-
{ label: "📱 2:3 (Retrato)", value: "2/3", ratio: 2 / 3 },
|
|
229
|
-
{ label: "📲 9:16 (Stories)", value: "9/16", ratio: 9 / 16 }
|
|
230
|
-
],
|
|
231
|
-
showFreeAspectRatio: true
|
|
222
|
+
showFreeAspectRatio: true,
|
|
232
223
|
// Permitir aspecto libre
|
|
224
|
+
// Nuevas opciones avanzadas
|
|
225
|
+
showDimensionInputs: false,
|
|
226
|
+
// Si true, muestra inputs width x height en lugar de aspect ratio
|
|
227
|
+
enableEditMode: true,
|
|
228
|
+
// Si permite editar variantes existentes
|
|
229
|
+
showDownloadInCropper: false,
|
|
230
|
+
// Si muestra botón de descarga en el cropper
|
|
231
|
+
showCropName: false,
|
|
232
|
+
// Si muestra campo de nombre de recorte editable
|
|
233
|
+
// Recortes obligatorios - Array de objetos con {label, width, height, required}
|
|
234
|
+
mandatoryCrops: [],
|
|
235
|
+
/* Ejemplo de mandatoryCrops:
|
|
236
|
+
[
|
|
237
|
+
{ label: "Thumbnail", width: 300, height: 300, required: true },
|
|
238
|
+
{ label: "Header", width: 1920, height: 400, required: true },
|
|
239
|
+
{ label: "Mobile", width: 750, height: 1334, required: false }
|
|
240
|
+
]
|
|
241
|
+
*/
|
|
242
|
+
allowCustomCrops: true
|
|
243
|
+
// Permitir que el usuario añada recortes personalizados además de los obligatorios
|
|
244
|
+
},
|
|
245
|
+
// Configuración de galería
|
|
246
|
+
gallery: {
|
|
247
|
+
// Configuración de filtros
|
|
248
|
+
filters: {
|
|
249
|
+
showNameFilter: true,
|
|
250
|
+
// Mostrar filtro por nombre de archivo
|
|
251
|
+
showUploadedByFilter: false,
|
|
252
|
+
// Mostrar filtro por usuario que subió (oculto por defecto)
|
|
253
|
+
showDateFilter: true,
|
|
254
|
+
// Mostrar filtros de rango de fechas
|
|
255
|
+
enabledFilters: ["name", "date"],
|
|
256
|
+
// Filtros activos por defecto
|
|
257
|
+
// Filtros personalizados adicionales
|
|
258
|
+
customFilters: []
|
|
259
|
+
/* Ejemplo de customFilters:
|
|
260
|
+
[
|
|
261
|
+
{
|
|
262
|
+
key: "tag",
|
|
263
|
+
label: "Etiqueta",
|
|
264
|
+
type: "select", // select | text | date | range
|
|
265
|
+
options: ["producto", "banner", "avatar"]
|
|
266
|
+
}
|
|
267
|
+
]
|
|
268
|
+
*/
|
|
269
|
+
},
|
|
270
|
+
// Configuración de carga
|
|
271
|
+
loading: {
|
|
272
|
+
showPlaceholders: true,
|
|
273
|
+
// Mostrar placeholders mientras carga
|
|
274
|
+
placeholderCount: 10,
|
|
275
|
+
// Número de placeholders a mostrar
|
|
276
|
+
showSpinner: true
|
|
277
|
+
// Mostrar spinner de carga
|
|
278
|
+
},
|
|
279
|
+
// Configuración de paginación
|
|
280
|
+
pagination: {
|
|
281
|
+
itemsPerPage: 20,
|
|
282
|
+
// Elementos por página
|
|
283
|
+
showPageSize: true
|
|
284
|
+
// Permitir cambiar el tamaño de página
|
|
285
|
+
}
|
|
233
286
|
},
|
|
234
287
|
// Validación de archivos
|
|
235
288
|
validation: {
|
|
@@ -240,6 +293,9 @@ class ConfigManager {
|
|
|
240
293
|
maxWidth: null,
|
|
241
294
|
maxHeight: null
|
|
242
295
|
},
|
|
296
|
+
// Configuración de descarga
|
|
297
|
+
downloadFormat: "webp",
|
|
298
|
+
// webp | jpeg | jpg | png - Format for downloaded images
|
|
243
299
|
// Configuración de retorno
|
|
244
300
|
return: {
|
|
245
301
|
format: "url",
|
|
@@ -290,9 +346,33 @@ class ConfigManager {
|
|
|
290
346
|
showCloseButton: true
|
|
291
347
|
},
|
|
292
348
|
// Callbacks por defecto
|
|
293
|
-
callbacks: {
|
|
349
|
+
callbacks: {
|
|
350
|
+
// Callback cuando se sube una imagen
|
|
351
|
+
onUpload: null,
|
|
352
|
+
// (data) => { assetId, url, fileName, mime, width, height, instanceId }
|
|
353
|
+
// Callback cuando se selecciona una imagen
|
|
354
|
+
onSelect: null,
|
|
355
|
+
// (data) => { assetId, url, fileName, mime, width, height, instanceId }
|
|
356
|
+
// Callback cuando se elimina una imagen
|
|
357
|
+
onDelete: null,
|
|
358
|
+
// (assetId, instanceId) => void
|
|
359
|
+
// NUEVO: Callback cuando se guardan recortes/variantes
|
|
360
|
+
onCropsSaved: null,
|
|
361
|
+
// (data) => { crops: Array, assetId, instanceId }
|
|
362
|
+
// NUEVO: Callback cuando se completa el cropper (modo crop-only)
|
|
363
|
+
onCropperComplete: null,
|
|
364
|
+
// (data) => { crops: Array, instanceId }
|
|
365
|
+
// NUEVO: Callback cuando se cancela el cropper sin guardar
|
|
366
|
+
onCropperCancelled: null,
|
|
367
|
+
// (data) => { assetId?, instanceId }
|
|
368
|
+
// NUEVO: Callback cuando ocurre un error en el cropper
|
|
369
|
+
onCropperError: null
|
|
370
|
+
// (error, instanceId) => void
|
|
371
|
+
},
|
|
294
372
|
// Configuración avanzada
|
|
295
373
|
autoDestroy: false,
|
|
374
|
+
autoHideOnComplete: false,
|
|
375
|
+
// Si true, oculta el componente al completar (solo embed mode)
|
|
296
376
|
debug: false,
|
|
297
377
|
apiEndpoint: null,
|
|
298
378
|
// ========== CONFIGURACIÓN DE AUTENTICACIÓN JWT V2 ==========
|
|
@@ -453,17 +533,34 @@ class ConfigManager {
|
|
|
453
533
|
aspectRatio: null,
|
|
454
534
|
lockAspectRatio: false,
|
|
455
535
|
// Aspect ratios permitidos - formato: { label, value, ratio }
|
|
456
|
-
|
|
457
|
-
{ label: "📐 Libre", value: "", ratio: null },
|
|
458
|
-
{ label: "⬜ 1:1 (Cuadrado)", value: "1", ratio: 1 },
|
|
459
|
-
{ label: "📺 4:3 (Clásico)", value: "4/3", ratio: 4 / 3 },
|
|
460
|
-
{ label: "🖥️ 16:9 (Widescreen)", value: "16/9", ratio: 16 / 9 },
|
|
461
|
-
{ label: "📷 3:2 (Foto)", value: "3/2", ratio: 3 / 2 },
|
|
462
|
-
{ label: "📱 2:3 (Retrato)", value: "2/3", ratio: 2 / 3 },
|
|
463
|
-
{ label: "📲 9:16 (Stories)", value: "9/16", ratio: 9 / 16 }
|
|
464
|
-
],
|
|
465
|
-
showFreeAspectRatio: true
|
|
536
|
+
showFreeAspectRatio: true,
|
|
466
537
|
// Permitir aspecto libre
|
|
538
|
+
// Nuevas opciones avanzadas
|
|
539
|
+
showDimensionInputs: false,
|
|
540
|
+
enableEditMode: true,
|
|
541
|
+
showDownloadInCropper: false,
|
|
542
|
+
showCropName: false,
|
|
543
|
+
mandatoryCrops: [],
|
|
544
|
+
allowCustomCrops: true
|
|
545
|
+
},
|
|
546
|
+
// Configuración de galería
|
|
547
|
+
gallery: {
|
|
548
|
+
filters: {
|
|
549
|
+
showNameFilter: true,
|
|
550
|
+
showUploadedByFilter: false,
|
|
551
|
+
showDateFilter: true,
|
|
552
|
+
enabledFilters: ["name", "date"],
|
|
553
|
+
customFilters: []
|
|
554
|
+
},
|
|
555
|
+
loading: {
|
|
556
|
+
showPlaceholders: true,
|
|
557
|
+
placeholderCount: 10,
|
|
558
|
+
showSpinner: true
|
|
559
|
+
},
|
|
560
|
+
pagination: {
|
|
561
|
+
itemsPerPage: 20,
|
|
562
|
+
showPageSize: true
|
|
563
|
+
}
|
|
467
564
|
},
|
|
468
565
|
// Validación de archivos
|
|
469
566
|
validation: {
|
|
@@ -517,9 +614,33 @@ class ConfigManager {
|
|
|
517
614
|
customProperties: {}
|
|
518
615
|
},
|
|
519
616
|
// Callbacks por defecto
|
|
520
|
-
callbacks: {
|
|
617
|
+
callbacks: {
|
|
618
|
+
// Callback cuando se sube una imagen
|
|
619
|
+
onUpload: null,
|
|
620
|
+
// (data) => { assetId, url, fileName, mime, width, height, instanceId }
|
|
621
|
+
// Callback cuando se selecciona una imagen
|
|
622
|
+
onSelect: null,
|
|
623
|
+
// (data) => { assetId, url, fileName, mime, width, height, instanceId }
|
|
624
|
+
// Callback cuando se elimina una imagen
|
|
625
|
+
onDelete: null,
|
|
626
|
+
// (assetId, instanceId) => void
|
|
627
|
+
// NUEVO: Callback cuando se guardan recortes/variantes
|
|
628
|
+
onCropsSaved: null,
|
|
629
|
+
// (data) => { crops: Array, assetId, instanceId }
|
|
630
|
+
// NUEVO: Callback cuando se completa el cropper (modo crop-only)
|
|
631
|
+
onCropperComplete: null,
|
|
632
|
+
// (data) => { crops: Array, instanceId }
|
|
633
|
+
// NUEVO: Callback cuando se cancela el cropper sin guardar
|
|
634
|
+
onCropperCancelled: null,
|
|
635
|
+
// (data) => { assetId?, instanceId }
|
|
636
|
+
// NUEVO: Callback cuando ocurre un error en el cropper
|
|
637
|
+
onCropperError: null
|
|
638
|
+
// (error, instanceId) => void
|
|
639
|
+
},
|
|
521
640
|
// Configuración avanzada
|
|
522
641
|
autoDestroy: false,
|
|
642
|
+
autoHideOnComplete: false,
|
|
643
|
+
// Si true, oculta el componente al completar (solo embed mode)
|
|
523
644
|
debug: false,
|
|
524
645
|
apiEndpoint: null,
|
|
525
646
|
// ========== CONFIGURACIÓN DE AUTENTICACIÓN JWT V2 ==========
|
|
@@ -726,6 +847,128 @@ class ConfigManager {
|
|
|
726
847
|
this.setJWTAuth(apiKey);
|
|
727
848
|
return this;
|
|
728
849
|
}
|
|
850
|
+
/**
|
|
851
|
+
* ========================================
|
|
852
|
+
* HELPERS PARA CONFIGURACIÓN DE CROPPER
|
|
853
|
+
* ========================================
|
|
854
|
+
*/
|
|
855
|
+
/**
|
|
856
|
+
* Obtener recortes obligatorios configurados
|
|
857
|
+
*/
|
|
858
|
+
getMandatoryCrops(config = null) {
|
|
859
|
+
const mergedConfig = config || this.merge();
|
|
860
|
+
return mergedConfig.cropper?.mandatoryCrops || [];
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Verificar si hay recortes obligatorios configurados
|
|
864
|
+
*/
|
|
865
|
+
hasMandatoryCrops(config = null) {
|
|
866
|
+
const crops = this.getMandatoryCrops(config);
|
|
867
|
+
return crops.length > 0;
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Verificar si está habilitado el modo de edición de variantes
|
|
871
|
+
*/
|
|
872
|
+
isEditModeEnabled(config = null) {
|
|
873
|
+
const mergedConfig = config || this.merge();
|
|
874
|
+
return mergedConfig.cropper?.enableEditMode !== false;
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* Verificar si se muestran inputs de dimensiones en lugar de aspect ratio
|
|
878
|
+
*/
|
|
879
|
+
showDimensionInputs(config = null) {
|
|
880
|
+
const mergedConfig = config || this.merge();
|
|
881
|
+
return mergedConfig.cropper?.showDimensionInputs === true;
|
|
882
|
+
}
|
|
883
|
+
/**
|
|
884
|
+
* Verificar si se muestra botón de descarga en el cropper
|
|
885
|
+
*/
|
|
886
|
+
showDownloadInCropper(config = null) {
|
|
887
|
+
const mergedConfig = config || this.merge();
|
|
888
|
+
return mergedConfig.cropper?.showDownloadInCropper === true;
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Verificar si se muestra campo de nombre de recorte
|
|
892
|
+
*/
|
|
893
|
+
showCropName(config = null) {
|
|
894
|
+
const mergedConfig = config || this.merge();
|
|
895
|
+
return mergedConfig.cropper?.showCropName === true;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Verificar si se permiten recortes personalizados
|
|
899
|
+
*/
|
|
900
|
+
allowCustomCrops(config = null) {
|
|
901
|
+
const mergedConfig = config || this.merge();
|
|
902
|
+
return mergedConfig.cropper?.allowCustomCrops !== false;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* ========================================
|
|
906
|
+
* HELPERS PARA CONFIGURACIÓN DE GALERÍA
|
|
907
|
+
* ========================================
|
|
908
|
+
*/
|
|
909
|
+
/**
|
|
910
|
+
* Obtener configuración de filtros de galería
|
|
911
|
+
*/
|
|
912
|
+
getGalleryFilters(config = null) {
|
|
913
|
+
const mergedConfig = config || this.merge();
|
|
914
|
+
return mergedConfig.gallery?.filters || this.defaults.gallery.filters;
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* Verificar si un filtro específico está habilitado
|
|
918
|
+
*/
|
|
919
|
+
isGalleryFilterEnabled(filterName, config = null) {
|
|
920
|
+
const filters = this.getGalleryFilters(config);
|
|
921
|
+
return filters.enabledFilters?.includes(filterName) || false;
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* Obtener filtros personalizados de galería
|
|
925
|
+
*/
|
|
926
|
+
getCustomGalleryFilters(config = null) {
|
|
927
|
+
const filters = this.getGalleryFilters(config);
|
|
928
|
+
return filters.customFilters || [];
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Obtener configuración de carga de galería
|
|
932
|
+
*/
|
|
933
|
+
getGalleryLoadingConfig(config = null) {
|
|
934
|
+
const mergedConfig = config || this.merge();
|
|
935
|
+
return mergedConfig.gallery?.loading || this.defaults.gallery.loading;
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Verificar si se muestran placeholders en la galería
|
|
939
|
+
*/
|
|
940
|
+
showGalleryPlaceholders(config = null) {
|
|
941
|
+
const loading = this.getGalleryLoadingConfig(config);
|
|
942
|
+
return loading.showPlaceholders !== false;
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* Obtener número de placeholders a mostrar
|
|
946
|
+
*/
|
|
947
|
+
getPlaceholderCount(config = null) {
|
|
948
|
+
const loading = this.getGalleryLoadingConfig(config);
|
|
949
|
+
return loading.placeholderCount || 10;
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Verificar si se muestra spinner de carga en galería
|
|
953
|
+
*/
|
|
954
|
+
showGallerySpinner(config = null) {
|
|
955
|
+
const loading = this.getGalleryLoadingConfig(config);
|
|
956
|
+
return loading.showSpinner !== false;
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* Obtener configuración de paginación de galería
|
|
960
|
+
*/
|
|
961
|
+
getGalleryPagination(config = null) {
|
|
962
|
+
const mergedConfig = config || this.merge();
|
|
963
|
+
return mergedConfig.gallery?.pagination || this.defaults.gallery.pagination;
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Obtener items por página
|
|
967
|
+
*/
|
|
968
|
+
getItemsPerPage(config = null) {
|
|
969
|
+
const pagination = this.getGalleryPagination(config);
|
|
970
|
+
return pagination.itemsPerPage || 20;
|
|
971
|
+
}
|
|
729
972
|
}
|
|
730
973
|
var client = { exports: {} };
|
|
731
974
|
var reactDomClient_production = {};
|
|
@@ -30628,6 +30871,8 @@ function adaptAssetsListFromV2(v2Response) {
|
|
|
30628
30871
|
height: asset.height,
|
|
30629
30872
|
upload_date: asset.upload_date || asset.created_at,
|
|
30630
30873
|
processing_status: asset.processing_status || asset.status,
|
|
30874
|
+
// Variantes
|
|
30875
|
+
variants: asset.variants_count ? adaptVariantsFromV2(asset.variants) || adaptVariantsFromV2(asset.image_variants) || [] : [],
|
|
30631
30876
|
// URL principal - handle multiple URL formats from different backend responses
|
|
30632
30877
|
url: makeAbsoluteUrl(
|
|
30633
30878
|
asset.master_url || asset.master?.url_signed || asset.urls?.original || asset.url
|
|
@@ -30681,6 +30926,23 @@ function adaptVariantsListFromV2(v2Response) {
|
|
|
30681
30926
|
});
|
|
30682
30927
|
return { result: legacyVariants };
|
|
30683
30928
|
}
|
|
30929
|
+
function adaptVariantsFromV2(v2Variants) {
|
|
30930
|
+
if (!Array.isArray(v2Variants)) {
|
|
30931
|
+
return [];
|
|
30932
|
+
}
|
|
30933
|
+
return v2Variants.map((variant) => ({
|
|
30934
|
+
id: variant.id,
|
|
30935
|
+
name: variant.name,
|
|
30936
|
+
width: variant.width,
|
|
30937
|
+
height: variant.height,
|
|
30938
|
+
format: variant.output_format,
|
|
30939
|
+
file_size: variant.file_size,
|
|
30940
|
+
crop_params: variant.crop_params,
|
|
30941
|
+
url: makeAbsoluteUrl(variant.url),
|
|
30942
|
+
expires_at: variant.expires_at,
|
|
30943
|
+
created_at: variant.created_at
|
|
30944
|
+
}));
|
|
30945
|
+
}
|
|
30684
30946
|
function adaptUploadFromV2(v2Response) {
|
|
30685
30947
|
if (!v2Response?.success || !v2Response?.data) {
|
|
30686
30948
|
return { result: null };
|
|
@@ -30998,31 +31260,33 @@ function ImageVariantsModal({
|
|
|
30998
31260
|
parent_asset_id: image.id,
|
|
30999
31261
|
variant_info: variant
|
|
31000
31262
|
};
|
|
31001
|
-
accessibilityManager?.announce(`
|
|
31263
|
+
accessibilityManager?.announce(`Recorte seleccionado: ${variant.name}`);
|
|
31002
31264
|
onSelect?.(variantAsImage);
|
|
31003
31265
|
onClose?.();
|
|
31004
31266
|
};
|
|
31005
31267
|
const handleCopyVariantUrl = async (variant) => {
|
|
31006
31268
|
try {
|
|
31007
31269
|
await navigator.clipboard.writeText(variant.url);
|
|
31008
|
-
accessibilityManager?.announce(`URL de
|
|
31270
|
+
accessibilityManager?.announce(`URL de recorte ${variant.name} copiada`);
|
|
31009
31271
|
} catch (err) {
|
|
31010
31272
|
console.error("Error copying variant URL:", err);
|
|
31011
|
-
accessibilityManager?.announceError("Error al copiar URL de
|
|
31273
|
+
accessibilityManager?.announceError("Error al copiar URL de recorte");
|
|
31012
31274
|
}
|
|
31013
31275
|
};
|
|
31014
|
-
const handleDownloadVariant = (variant) => {
|
|
31015
|
-
|
|
31016
|
-
|
|
31017
|
-
|
|
31018
|
-
|
|
31019
|
-
|
|
31020
|
-
|
|
31021
|
-
|
|
31276
|
+
const handleDownloadVariant = async (variant) => {
|
|
31277
|
+
const { downloadImage: downloadImage2 } = await Promise.resolve().then(() => downloadImage$1);
|
|
31278
|
+
await downloadImage2(
|
|
31279
|
+
variant.url,
|
|
31280
|
+
variant.name || "limbo-variant",
|
|
31281
|
+
{
|
|
31282
|
+
originalFormat: variant.format || variant.output_format,
|
|
31283
|
+
accessibilityManager
|
|
31284
|
+
}
|
|
31285
|
+
);
|
|
31022
31286
|
};
|
|
31023
31287
|
const handleViewVariant = (variant) => {
|
|
31024
31288
|
accessibilityManager?.announce(
|
|
31025
|
-
`Abriendo
|
|
31289
|
+
`Abriendo recorte ${variant.name} en nueva pestaña`
|
|
31026
31290
|
);
|
|
31027
31291
|
window.open(variant.url, "_blank");
|
|
31028
31292
|
};
|
|
@@ -31041,21 +31305,21 @@ function ImageVariantsModal({
|
|
|
31041
31305
|
accessibilityManager?.announceError("Error al copiar URL");
|
|
31042
31306
|
}
|
|
31043
31307
|
};
|
|
31044
|
-
const handleDownloadOriginal = () => {
|
|
31045
|
-
|
|
31046
|
-
|
|
31308
|
+
const handleDownloadOriginal = async () => {
|
|
31309
|
+
const { downloadImage: downloadImage2 } = await Promise.resolve().then(() => downloadImage$1);
|
|
31310
|
+
await downloadImage2(
|
|
31311
|
+
image.url || image.path,
|
|
31312
|
+
image.filename || "limbo-image",
|
|
31313
|
+
{
|
|
31314
|
+
originalFormat: image.format,
|
|
31315
|
+
accessibilityManager
|
|
31316
|
+
}
|
|
31047
31317
|
);
|
|
31048
|
-
const a = document.createElement("a");
|
|
31049
|
-
a.href = image.url;
|
|
31050
|
-
a.download = image.filename;
|
|
31051
|
-
document.body.appendChild(a);
|
|
31052
|
-
a.click();
|
|
31053
|
-
document.body.removeChild(a);
|
|
31054
31318
|
};
|
|
31055
31319
|
const handleDeleteOriginal = async () => {
|
|
31056
31320
|
if (!onDelete) return;
|
|
31057
31321
|
const confirmed = window.confirm(
|
|
31058
|
-
`¿Estás seguro de que deseas eliminar "${image.filename}"? Esta acción también eliminará
|
|
31322
|
+
`¿Estás seguro de que deseas eliminar "${image.filename}"? Esta acción también eliminará todos sus recortes.`
|
|
31059
31323
|
);
|
|
31060
31324
|
if (confirmed) {
|
|
31061
31325
|
accessibilityManager?.announce(`Eliminando imagen ${image.filename}`);
|
|
@@ -31073,27 +31337,27 @@ function ImageVariantsModal({
|
|
|
31073
31337
|
};
|
|
31074
31338
|
const handleDeleteVariant = async (variant) => {
|
|
31075
31339
|
const confirmed = window.confirm(
|
|
31076
|
-
`¿Estás seguro de que deseas eliminar
|
|
31340
|
+
`¿Estás seguro de que deseas eliminar el recorte "${variant.name || variant.filename}"?`
|
|
31077
31341
|
);
|
|
31078
31342
|
if (confirmed) {
|
|
31079
31343
|
accessibilityManager?.announce(
|
|
31080
|
-
`Eliminando
|
|
31344
|
+
`Eliminando recorte ${variant.name || variant.filename}`
|
|
31081
31345
|
);
|
|
31082
31346
|
const result = await removeVariant(image.id, variant.id);
|
|
31083
31347
|
if (result.success) {
|
|
31084
|
-
setDeleteMessage("
|
|
31348
|
+
setDeleteMessage("Recorte eliminado correctamente");
|
|
31085
31349
|
setDeleteMessageType("success");
|
|
31086
|
-
accessibilityManager?.announce(`
|
|
31350
|
+
accessibilityManager?.announce(`Recorte eliminado correctamente`);
|
|
31087
31351
|
onVariantDeleted?.();
|
|
31088
31352
|
setTimeout(() => {
|
|
31089
31353
|
setDeleteMessage(null);
|
|
31090
31354
|
setDeleteMessageType(null);
|
|
31091
31355
|
}, 3e3);
|
|
31092
31356
|
} else {
|
|
31093
|
-
setDeleteMessage(`Error al eliminar
|
|
31357
|
+
setDeleteMessage(`Error al eliminar recorte: ${result.error}`);
|
|
31094
31358
|
setDeleteMessageType("error");
|
|
31095
31359
|
accessibilityManager?.announceError(
|
|
31096
|
-
`Error al eliminar
|
|
31360
|
+
`Error al eliminar recorte: ${result.error}`
|
|
31097
31361
|
);
|
|
31098
31362
|
setTimeout(() => {
|
|
31099
31363
|
setDeleteMessage(null);
|
|
@@ -31118,7 +31382,7 @@ function ImageVariantsModal({
|
|
|
31118
31382
|
children: [
|
|
31119
31383
|
/* @__PURE__ */ jsxs("div", { className: "limbo-modal-header", children: [
|
|
31120
31384
|
/* @__PURE__ */ jsxs("h2", { id: "variants-modal-title", children: [
|
|
31121
|
-
"
|
|
31385
|
+
"Recortes de ",
|
|
31122
31386
|
image?.filename
|
|
31123
31387
|
] }),
|
|
31124
31388
|
/* @__PURE__ */ jsx(
|
|
@@ -31126,7 +31390,7 @@ function ImageVariantsModal({
|
|
|
31126
31390
|
{
|
|
31127
31391
|
className: "limbo-modal-close",
|
|
31128
31392
|
onClick: onClose,
|
|
31129
|
-
"aria-label": "Cerrar modal de
|
|
31393
|
+
"aria-label": "Cerrar modal de recortes",
|
|
31130
31394
|
children: "✕"
|
|
31131
31395
|
}
|
|
31132
31396
|
)
|
|
@@ -31149,10 +31413,10 @@ function ImageVariantsModal({
|
|
|
31149
31413
|
),
|
|
31150
31414
|
/* @__PURE__ */ jsx("div", { className: "limbo-modal-body", children: loading ? /* @__PURE__ */ jsxs("div", { className: "limbo-variants-loading", children: [
|
|
31151
31415
|
/* @__PURE__ */ jsx("div", { className: "limbo-loader" }),
|
|
31152
|
-
/* @__PURE__ */ jsx("p", { children: "Cargando
|
|
31416
|
+
/* @__PURE__ */ jsx("p", { children: "Cargando recortes..." })
|
|
31153
31417
|
] }) : error ? /* @__PURE__ */ jsxs("div", { className: "limbo-variants-error", children: [
|
|
31154
31418
|
/* @__PURE__ */ jsxs("p", { children: [
|
|
31155
|
-
"Error al cargar
|
|
31419
|
+
"Error al cargar recortes: ",
|
|
31156
31420
|
error
|
|
31157
31421
|
] }),
|
|
31158
31422
|
/* @__PURE__ */ jsx(
|
|
@@ -31164,8 +31428,8 @@ function ImageVariantsModal({
|
|
|
31164
31428
|
}
|
|
31165
31429
|
)
|
|
31166
31430
|
] }) : variants.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "limbo-variants-empty", children: [
|
|
31167
|
-
/* @__PURE__ */ jsx("p", { children: "Esta imagen no tiene
|
|
31168
|
-
/* @__PURE__ */ jsx("small", { children: "
|
|
31431
|
+
/* @__PURE__ */ jsx("p", { children: "Esta imagen no tiene recortes aún." }),
|
|
31432
|
+
/* @__PURE__ */ jsx("small", { children: "Los recortes aparecerán aquí después de hacer recortes o redimensionados." })
|
|
31169
31433
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
31170
31434
|
/* @__PURE__ */ jsxs("div", { className: "limbo-variant-section", children: [
|
|
31171
31435
|
/* @__PURE__ */ jsx("h3", { children: "Imagen original" }),
|
|
@@ -31259,7 +31523,7 @@ function ImageVariantsModal({
|
|
|
31259
31523
|
] }),
|
|
31260
31524
|
/* @__PURE__ */ jsxs("div", { className: "limbo-variant-section", children: [
|
|
31261
31525
|
/* @__PURE__ */ jsxs("h3", { children: [
|
|
31262
|
-
"
|
|
31526
|
+
"Recortes (",
|
|
31263
31527
|
variants.length,
|
|
31264
31528
|
")"
|
|
31265
31529
|
] }),
|
|
@@ -31277,7 +31541,7 @@ function ImageVariantsModal({
|
|
|
31277
31541
|
{
|
|
31278
31542
|
src: variant.url,
|
|
31279
31543
|
alt: variant.name || variant.filename || `Variante ${variant.id}`,
|
|
31280
|
-
loading: "
|
|
31544
|
+
loading: "eager",
|
|
31281
31545
|
onError: () => handleVariantImageError(variant.id),
|
|
31282
31546
|
style: {
|
|
31283
31547
|
display: hasImageError ? "none" : "block"
|
|
@@ -31398,7 +31662,7 @@ function ImageCard({
|
|
|
31398
31662
|
delete: true,
|
|
31399
31663
|
crop: true,
|
|
31400
31664
|
variants: true
|
|
31401
|
-
// Nueva acción para ver
|
|
31665
|
+
// Nueva acción para ver recortes
|
|
31402
31666
|
}
|
|
31403
31667
|
}) {
|
|
31404
31668
|
const [copied, setCopied] = useState(false);
|
|
@@ -31453,22 +31717,18 @@ function ImageCard({
|
|
|
31453
31717
|
);
|
|
31454
31718
|
}
|
|
31455
31719
|
};
|
|
31456
|
-
const handleDownload = (e) => {
|
|
31720
|
+
const handleDownload = async (e) => {
|
|
31457
31721
|
e.preventDefault();
|
|
31458
31722
|
e.stopPropagation();
|
|
31459
|
-
|
|
31460
|
-
|
|
31461
|
-
|
|
31462
|
-
|
|
31463
|
-
|
|
31464
|
-
|
|
31465
|
-
|
|
31466
|
-
|
|
31467
|
-
|
|
31468
|
-
window.URL.revokeObjectURL(url);
|
|
31469
|
-
document.body.removeChild(a);
|
|
31470
|
-
}, 100);
|
|
31471
|
-
});
|
|
31723
|
+
const { downloadImage: downloadImage2 } = await Promise.resolve().then(() => downloadImage$1);
|
|
31724
|
+
await downloadImage2(
|
|
31725
|
+
image.url || image.path,
|
|
31726
|
+
image.filename || "limbo-image",
|
|
31727
|
+
{
|
|
31728
|
+
originalFormat: image.format,
|
|
31729
|
+
accessibilityManager
|
|
31730
|
+
}
|
|
31731
|
+
);
|
|
31472
31732
|
};
|
|
31473
31733
|
const handleCrop = (e) => {
|
|
31474
31734
|
e.stopPropagation();
|
|
@@ -31485,7 +31745,7 @@ function ImageCard({
|
|
|
31485
31745
|
}, [image.variants_count]);
|
|
31486
31746
|
const handleShowVariants = (e) => {
|
|
31487
31747
|
e.stopPropagation();
|
|
31488
|
-
accessibilityManager?.announce(`Mostrando
|
|
31748
|
+
accessibilityManager?.announce(`Mostrando recortes de ${image.filename}`);
|
|
31489
31749
|
setShowVariants(true);
|
|
31490
31750
|
};
|
|
31491
31751
|
const handleSelect = (e) => {
|
|
@@ -31552,7 +31812,7 @@ function ImageCard({
|
|
|
31552
31812
|
className: `limbo-image-card flex flex-col items-center cursor-pointer relative transition ${isDeleting ? "opacity-50" : ""} ${isMobile ? "limbo-image-card--mobile" : ""}`,
|
|
31553
31813
|
onClick: handleImageClick,
|
|
31554
31814
|
onKeyDown: handleKeyDown,
|
|
31555
|
-
title: isMobile ? "Toque para ver imagen" : "Haga click en la imagen para ver preview en nueva pestaña
|
|
31815
|
+
title: isMobile ? "Toque para ver imagen" : "Haga click en la imagen para ver preview en nueva pestaña",
|
|
31556
31816
|
role: "button",
|
|
31557
31817
|
tabIndex: 0,
|
|
31558
31818
|
"aria-label": `Imagen ${image.filename}. ${image.width}x${image.height} px`,
|
|
@@ -31573,7 +31833,7 @@ function ImageCard({
|
|
|
31573
31833
|
"button",
|
|
31574
31834
|
{
|
|
31575
31835
|
type: "button",
|
|
31576
|
-
title: `Ver ${variantsCount}
|
|
31836
|
+
title: `Ver ${variantsCount} recorte${variantsCount !== 1 ? "s" : ""}`,
|
|
31577
31837
|
className: `btn btn-variants border border-brand-blue-050/50 ${isMobile ? "btn--touch" : ""}`,
|
|
31578
31838
|
onClick: handleShowVariants,
|
|
31579
31839
|
tabIndex: -1,
|
|
@@ -31743,7 +32003,8 @@ function ImageCard({
|
|
|
31743
32003
|
"img",
|
|
31744
32004
|
{
|
|
31745
32005
|
src: image.url || image.path,
|
|
31746
|
-
|
|
32006
|
+
loading: "eager",
|
|
32007
|
+
alt: image.filename.split(".")[0] ?? image.filename,
|
|
31747
32008
|
className: "w-full object-cover rounded aspect-square",
|
|
31748
32009
|
sizes: `height: ${thumbnailSize * 6}px,width: ${thumbnailSize * 6}px`,
|
|
31749
32010
|
draggable: false,
|
|
@@ -31775,7 +32036,7 @@ function ImageCard({
|
|
|
31775
32036
|
fontWeight: "500"
|
|
31776
32037
|
}
|
|
31777
32038
|
},
|
|
31778
|
-
children: image.filename
|
|
32039
|
+
children: image.filename.split(".")[0] ?? image.filename
|
|
31779
32040
|
}
|
|
31780
32041
|
)
|
|
31781
32042
|
]
|
|
@@ -31802,6 +32063,38 @@ function ImageCard({
|
|
|
31802
32063
|
)
|
|
31803
32064
|
] });
|
|
31804
32065
|
}
|
|
32066
|
+
function ImageCardSkeleton() {
|
|
32067
|
+
return /* @__PURE__ */ jsxs(
|
|
32068
|
+
"div",
|
|
32069
|
+
{
|
|
32070
|
+
className: "limbo-image-card animate-pulse",
|
|
32071
|
+
role: "status",
|
|
32072
|
+
"aria-label": "Cargando imagen...",
|
|
32073
|
+
children: [
|
|
32074
|
+
/* @__PURE__ */ jsx("div", { className: "w-full aspect-square bg-neutral-gray-200 rounded-md flex items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
32075
|
+
"svg",
|
|
32076
|
+
{
|
|
32077
|
+
className: "w-12 h-12 text-neutral-gray-300",
|
|
32078
|
+
fill: "currentColor",
|
|
32079
|
+
viewBox: "0 0 20 20",
|
|
32080
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
32081
|
+
"aria-hidden": "true",
|
|
32082
|
+
children: /* @__PURE__ */ jsx(
|
|
32083
|
+
"path",
|
|
32084
|
+
{
|
|
32085
|
+
fillRule: "evenodd",
|
|
32086
|
+
d: "M4 3a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4zm12 12H4l4-8 3 6 2-4 3 6z",
|
|
32087
|
+
clipRule: "evenodd"
|
|
32088
|
+
}
|
|
32089
|
+
)
|
|
32090
|
+
}
|
|
32091
|
+
) }),
|
|
32092
|
+
/* @__PURE__ */ jsx("div", { className: "limbo-image-card-name opacity-100 position-relative bottom-0 p-2", children: /* @__PURE__ */ jsx("div", { className: "h-4 bg-neutral-gray-200 rounded w-3/4" }) }),
|
|
32093
|
+
/* @__PURE__ */ jsx("span", { className: "limbo-sr-only", children: "Cargando imagen..." })
|
|
32094
|
+
]
|
|
32095
|
+
}
|
|
32096
|
+
);
|
|
32097
|
+
}
|
|
31805
32098
|
function Loader({ text = "Cargando..." }) {
|
|
31806
32099
|
return /* @__PURE__ */ jsxs(
|
|
31807
32100
|
"div",
|
|
@@ -31847,50 +32140,7 @@ function Loader({ text = "Cargando..." }) {
|
|
|
31847
32140
|
}
|
|
31848
32141
|
);
|
|
31849
32142
|
}
|
|
31850
|
-
const cache$5 = /* @__PURE__ */ new Map();
|
|
31851
|
-
const CACHE_TTL$5 = 5 * 60 * 1e3;
|
|
31852
|
-
function useIsAllowedAll() {
|
|
31853
|
-
const [allowed, setAllowed] = useState(null);
|
|
31854
|
-
const [loading, setLoading] = useState(true);
|
|
31855
|
-
const [error, setError] = useState(null);
|
|
31856
|
-
useEffect(() => {
|
|
31857
|
-
const cacheKey = "auth-status";
|
|
31858
|
-
const cached = cache$5.get(cacheKey);
|
|
31859
|
-
const now = Date.now();
|
|
31860
|
-
if (cached && now - cached.timestamp < CACHE_TTL$5) {
|
|
31861
|
-
setAllowed(cached.data);
|
|
31862
|
-
setLoading(false);
|
|
31863
|
-
return;
|
|
31864
|
-
}
|
|
31865
|
-
let isMounted = true;
|
|
31866
|
-
const checkAuthStatus = async () => {
|
|
31867
|
-
try {
|
|
31868
|
-
const isAuthenticated = true;
|
|
31869
|
-
if (!isMounted) return;
|
|
31870
|
-
cache$5.set(cacheKey, { data: isAuthenticated, timestamp: Date.now() });
|
|
31871
|
-
setAllowed(isAuthenticated);
|
|
31872
|
-
} catch (err) {
|
|
31873
|
-
if (isMounted) {
|
|
31874
|
-
setError(err.message);
|
|
31875
|
-
setAllowed(false);
|
|
31876
|
-
}
|
|
31877
|
-
} finally {
|
|
31878
|
-
if (isMounted) setLoading(false);
|
|
31879
|
-
}
|
|
31880
|
-
};
|
|
31881
|
-
checkAuthStatus();
|
|
31882
|
-
return () => {
|
|
31883
|
-
isMounted = false;
|
|
31884
|
-
};
|
|
31885
|
-
}, []);
|
|
31886
|
-
const invalidateCache = () => {
|
|
31887
|
-
cache$5.delete("auth-status");
|
|
31888
|
-
};
|
|
31889
|
-
return { allowed, loading, error, invalidateCache };
|
|
31890
|
-
}
|
|
31891
32143
|
function Gallery({
|
|
31892
|
-
apiKey,
|
|
31893
|
-
prod,
|
|
31894
32144
|
onSelect,
|
|
31895
32145
|
onCrop,
|
|
31896
32146
|
// Nueva prop separada para cropping
|
|
@@ -31899,6 +32149,24 @@ function Gallery({
|
|
|
31899
32149
|
images,
|
|
31900
32150
|
loading,
|
|
31901
32151
|
error,
|
|
32152
|
+
filters = {
|
|
32153
|
+
name: "",
|
|
32154
|
+
dateFrom: "",
|
|
32155
|
+
dateTo: "",
|
|
32156
|
+
uploadedBy: ""
|
|
32157
|
+
},
|
|
32158
|
+
onFiltersChange,
|
|
32159
|
+
filterConfig = {
|
|
32160
|
+
showNameFilter: true,
|
|
32161
|
+
showUploadedByFilter: false,
|
|
32162
|
+
// Oculto por defecto según especificaciones
|
|
32163
|
+
showDateFilter: true
|
|
32164
|
+
},
|
|
32165
|
+
loadingConfig = {
|
|
32166
|
+
showPlaceholders: true,
|
|
32167
|
+
placeholderCount: 10,
|
|
32168
|
+
showSpinner: true
|
|
32169
|
+
},
|
|
31902
32170
|
allowedActions = {
|
|
31903
32171
|
select: true,
|
|
31904
32172
|
download: true,
|
|
@@ -31906,18 +32174,13 @@ function Gallery({
|
|
|
31906
32174
|
delete: true,
|
|
31907
32175
|
crop: true,
|
|
31908
32176
|
variants: true
|
|
31909
|
-
// Nueva acción para ver
|
|
32177
|
+
// Nueva acción para ver recortes
|
|
31910
32178
|
}
|
|
31911
32179
|
}) {
|
|
31912
|
-
const
|
|
31913
|
-
|
|
31914
|
-
|
|
31915
|
-
dateTo: "",
|
|
31916
|
-
originPortal: "",
|
|
31917
|
-
uploadedBy: ""
|
|
31918
|
-
});
|
|
32180
|
+
const showNameFilter = filterConfig.showNameFilter !== false;
|
|
32181
|
+
const showUploadedByFilter = filterConfig.showUploadedByFilter === true;
|
|
32182
|
+
const showDateFilter = filterConfig.showDateFilter !== false;
|
|
31919
32183
|
const galleryRef = useRef(null);
|
|
31920
|
-
const showOriginPortal = useIsAllowedAll();
|
|
31921
32184
|
const accessibilityManager = window.limboCore?.accessibilityManager;
|
|
31922
32185
|
useEffect(() => {
|
|
31923
32186
|
if (galleryRef.current && window.limboCore?.keyboardManager) {
|
|
@@ -31944,7 +32207,9 @@ function Gallery({
|
|
|
31944
32207
|
}, [loading, error, images.length, accessibilityManager]);
|
|
31945
32208
|
const handleChange = (e) => {
|
|
31946
32209
|
const { name, value } = e.target;
|
|
31947
|
-
|
|
32210
|
+
if (onFiltersChange) {
|
|
32211
|
+
onFiltersChange({ ...filters, [name]: value });
|
|
32212
|
+
}
|
|
31948
32213
|
};
|
|
31949
32214
|
return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
|
|
31950
32215
|
/* @__PURE__ */ jsx("div", { className: "limbo-card mb-6 p-4 bg-brand-blue-050 shadow-md", children: /* @__PURE__ */ jsxs(
|
|
@@ -31954,16 +32219,16 @@ function Gallery({
|
|
|
31954
32219
|
onSubmit: (e) => e.preventDefault(),
|
|
31955
32220
|
"aria-label": "Filtrar imágenes",
|
|
31956
32221
|
children: [
|
|
31957
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col w-full sm:min-w-[180px] sm:flex-1", children: [
|
|
31958
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "
|
|
32222
|
+
showNameFilter && /* @__PURE__ */ jsxs("div", { className: "flex flex-col w-full sm:min-w-[180px] sm:flex-1", children: [
|
|
32223
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "name", className: "form-label mb-1", children: "Nombre" }),
|
|
31959
32224
|
/* @__PURE__ */ jsx(
|
|
31960
32225
|
"input",
|
|
31961
32226
|
{
|
|
31962
32227
|
type: "text",
|
|
31963
|
-
name: "
|
|
31964
|
-
id: "
|
|
32228
|
+
name: "name",
|
|
32229
|
+
id: "name",
|
|
31965
32230
|
placeholder: "Buscar por nombre...",
|
|
31966
|
-
value: filters.
|
|
32231
|
+
value: filters.name,
|
|
31967
32232
|
onChange: handleChange,
|
|
31968
32233
|
className: "form-control",
|
|
31969
32234
|
autoComplete: "off"
|
|
@@ -31971,50 +32236,37 @@ function Gallery({
|
|
|
31971
32236
|
)
|
|
31972
32237
|
] }),
|
|
31973
32238
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row flex-wrap gap-2 justify-between items-start sm:items-end w-full sm:w-auto", children: [
|
|
31974
|
-
/* @__PURE__ */ jsxs(
|
|
31975
|
-
/* @__PURE__ */
|
|
31976
|
-
|
|
31977
|
-
|
|
31978
|
-
|
|
31979
|
-
|
|
31980
|
-
|
|
31981
|
-
|
|
31982
|
-
|
|
31983
|
-
|
|
31984
|
-
|
|
31985
|
-
|
|
31986
|
-
|
|
31987
|
-
|
|
31988
|
-
|
|
31989
|
-
/* @__PURE__ */
|
|
31990
|
-
|
|
31991
|
-
|
|
31992
|
-
|
|
31993
|
-
|
|
31994
|
-
|
|
31995
|
-
|
|
31996
|
-
|
|
31997
|
-
|
|
31998
|
-
|
|
31999
|
-
|
|
32000
|
-
|
|
32001
|
-
|
|
32002
|
-
|
|
32003
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "originPortal", className: "form-label mb-1", children: "Portal de origen" }),
|
|
32004
|
-
/* @__PURE__ */ jsx(
|
|
32005
|
-
"input",
|
|
32006
|
-
{
|
|
32007
|
-
type: "text",
|
|
32008
|
-
name: "originPortal",
|
|
32009
|
-
id: "originPortal",
|
|
32010
|
-
placeholder: "Portal de origen",
|
|
32011
|
-
value: filters.originPortal,
|
|
32012
|
-
onChange: handleChange,
|
|
32013
|
-
className: "form-control"
|
|
32014
|
-
}
|
|
32015
|
-
)
|
|
32239
|
+
showDateFilter && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
32240
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col w-full sm:w-auto", children: [
|
|
32241
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "dateFrom", className: "form-label mb-1", children: "Desde" }),
|
|
32242
|
+
/* @__PURE__ */ jsx(
|
|
32243
|
+
"input",
|
|
32244
|
+
{
|
|
32245
|
+
type: "date",
|
|
32246
|
+
name: "dateFrom",
|
|
32247
|
+
id: "dateFrom",
|
|
32248
|
+
value: filters.dateFrom,
|
|
32249
|
+
onChange: handleChange,
|
|
32250
|
+
className: "form-control"
|
|
32251
|
+
}
|
|
32252
|
+
)
|
|
32253
|
+
] }),
|
|
32254
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col w-full sm:w-auto", children: [
|
|
32255
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "dateTo", className: "form-label mb-1", children: "Hasta" }),
|
|
32256
|
+
/* @__PURE__ */ jsx(
|
|
32257
|
+
"input",
|
|
32258
|
+
{
|
|
32259
|
+
type: "date",
|
|
32260
|
+
name: "dateTo",
|
|
32261
|
+
id: "dateTo",
|
|
32262
|
+
value: filters.dateTo,
|
|
32263
|
+
onChange: handleChange,
|
|
32264
|
+
className: "form-control"
|
|
32265
|
+
}
|
|
32266
|
+
)
|
|
32267
|
+
] })
|
|
32016
32268
|
] }),
|
|
32017
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col w-full sm:w-auto", children: [
|
|
32269
|
+
showUploadedByFilter && /* @__PURE__ */ jsxs("div", { className: "flex flex-col w-full sm:w-auto", children: [
|
|
32018
32270
|
/* @__PURE__ */ jsx("label", { htmlFor: "uploadedBy", className: "form-label mb-1", children: "Subido por" }),
|
|
32019
32271
|
/* @__PURE__ */ jsx(
|
|
32020
32272
|
"input",
|
|
@@ -32033,7 +32285,27 @@ function Gallery({
|
|
|
32033
32285
|
]
|
|
32034
32286
|
}
|
|
32035
32287
|
) }),
|
|
32036
|
-
loading ?
|
|
32288
|
+
loading ? loadingConfig.showPlaceholders ? /* @__PURE__ */ jsx(
|
|
32289
|
+
"div",
|
|
32290
|
+
{
|
|
32291
|
+
ref: galleryRef,
|
|
32292
|
+
className: "limbo-gallery mt-4",
|
|
32293
|
+
"data-limbo-responsive": true,
|
|
32294
|
+
role: "grid",
|
|
32295
|
+
"aria-label": "Cargando imágenes de la galería",
|
|
32296
|
+
"aria-busy": "true",
|
|
32297
|
+
children: Array.from({ length: loadingConfig.placeholderCount }).map((_, index) => /* @__PURE__ */ jsx(
|
|
32298
|
+
"div",
|
|
32299
|
+
{
|
|
32300
|
+
role: "gridcell",
|
|
32301
|
+
"aria-posinset": index + 1,
|
|
32302
|
+
"aria-setsize": loadingConfig.placeholderCount,
|
|
32303
|
+
children: /* @__PURE__ */ jsx(ImageCardSkeleton, {})
|
|
32304
|
+
},
|
|
32305
|
+
`skeleton-${index}`
|
|
32306
|
+
))
|
|
32307
|
+
}
|
|
32308
|
+
) : loadingConfig.showSpinner ? /* @__PURE__ */ jsx(Loader, { text: "Cargando imágenes..." }) : null : error ? /* @__PURE__ */ jsx("div", { className: "alert alert-danger text-center", children: error }) : /* @__PURE__ */ jsx(
|
|
32037
32309
|
"div",
|
|
32038
32310
|
{
|
|
32039
32311
|
ref: galleryRef,
|
|
@@ -36565,6 +36837,21 @@ class CropperManager {
|
|
|
36565
36837
|
return false;
|
|
36566
36838
|
}
|
|
36567
36839
|
},
|
|
36840
|
+
// Establecer posición y tamaño directamente
|
|
36841
|
+
set: (x, y, width, height) => {
|
|
36842
|
+
if (!this.selectionElement) return false;
|
|
36843
|
+
try {
|
|
36844
|
+
this.selectionElement.x = x;
|
|
36845
|
+
this.selectionElement.y = y;
|
|
36846
|
+
this.selectionElement.width = width;
|
|
36847
|
+
this.selectionElement.height = height;
|
|
36848
|
+
this.selectionElement.$render();
|
|
36849
|
+
return true;
|
|
36850
|
+
} catch (error) {
|
|
36851
|
+
console.warn("Error setting selection:", error);
|
|
36852
|
+
return false;
|
|
36853
|
+
}
|
|
36854
|
+
},
|
|
36568
36855
|
// Exportar a canvas
|
|
36569
36856
|
toCanvas: async (options = {}) => {
|
|
36570
36857
|
if (!this.selectionElement) return null;
|
|
@@ -36966,11 +37253,136 @@ const useCropper = (image, options = {}) => {
|
|
|
36966
37253
|
manager: managerRef.current
|
|
36967
37254
|
};
|
|
36968
37255
|
};
|
|
37256
|
+
async function downloadImage(imageSource, filename, options = {}) {
|
|
37257
|
+
const {
|
|
37258
|
+
format = null,
|
|
37259
|
+
originalFormat = "webp",
|
|
37260
|
+
onSuccess = null,
|
|
37261
|
+
onError = null,
|
|
37262
|
+
accessibilityManager = null
|
|
37263
|
+
} = options;
|
|
37264
|
+
try {
|
|
37265
|
+
const globalConfig2 = window.limboCore?.config?.getGlobal();
|
|
37266
|
+
const downloadFormat = format || globalConfig2?.downloadFormat || originalFormat || "webp";
|
|
37267
|
+
const cleanFilename = filename.split(".")[0];
|
|
37268
|
+
const finalFilename = `${cleanFilename}.${downloadFormat}`;
|
|
37269
|
+
if (accessibilityManager) {
|
|
37270
|
+
accessibilityManager.announce(`Descargando ${finalFilename}`);
|
|
37271
|
+
}
|
|
37272
|
+
if (imageSource.startsWith("data:image/")) {
|
|
37273
|
+
downloadFromBase64(imageSource, finalFilename);
|
|
37274
|
+
if (onSuccess) {
|
|
37275
|
+
onSuccess(finalFilename);
|
|
37276
|
+
}
|
|
37277
|
+
if (accessibilityManager) {
|
|
37278
|
+
accessibilityManager.announce(`${finalFilename} descargado correctamente`);
|
|
37279
|
+
}
|
|
37280
|
+
return true;
|
|
37281
|
+
}
|
|
37282
|
+
const response = await fetch(imageSource, { mode: "cors" });
|
|
37283
|
+
if (!response.ok) {
|
|
37284
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
37285
|
+
}
|
|
37286
|
+
const blob = await response.blob();
|
|
37287
|
+
let finalBlob = blob;
|
|
37288
|
+
const sourceMimeType = blob.type;
|
|
37289
|
+
const targetMimeType = `image/${downloadFormat === "jpg" ? "jpeg" : downloadFormat}`;
|
|
37290
|
+
if (sourceMimeType !== targetMimeType && shouldConvertFormat(downloadFormat)) {
|
|
37291
|
+
finalBlob = await convertBlobFormat(blob, downloadFormat);
|
|
37292
|
+
}
|
|
37293
|
+
const blobUrl = window.URL.createObjectURL(finalBlob);
|
|
37294
|
+
const link = document.createElement("a");
|
|
37295
|
+
link.href = blobUrl;
|
|
37296
|
+
link.download = finalFilename;
|
|
37297
|
+
link.style.display = "none";
|
|
37298
|
+
document.body.appendChild(link);
|
|
37299
|
+
link.click();
|
|
37300
|
+
setTimeout(() => {
|
|
37301
|
+
window.URL.revokeObjectURL(blobUrl);
|
|
37302
|
+
document.body.removeChild(link);
|
|
37303
|
+
}, 100);
|
|
37304
|
+
if (onSuccess) {
|
|
37305
|
+
onSuccess(finalFilename);
|
|
37306
|
+
}
|
|
37307
|
+
if (accessibilityManager) {
|
|
37308
|
+
accessibilityManager.announce(`${finalFilename} descargado correctamente`);
|
|
37309
|
+
}
|
|
37310
|
+
return true;
|
|
37311
|
+
} catch (error) {
|
|
37312
|
+
console.error("Error downloading image:", error);
|
|
37313
|
+
if (onError) {
|
|
37314
|
+
onError(error);
|
|
37315
|
+
}
|
|
37316
|
+
if (accessibilityManager) {
|
|
37317
|
+
accessibilityManager.announce(`Error al descargar la imagen: ${error.message}`);
|
|
37318
|
+
}
|
|
37319
|
+
return false;
|
|
37320
|
+
}
|
|
37321
|
+
}
|
|
37322
|
+
function downloadFromBase64(dataUri, filename) {
|
|
37323
|
+
const link = document.createElement("a");
|
|
37324
|
+
link.href = dataUri;
|
|
37325
|
+
link.download = filename;
|
|
37326
|
+
link.style.display = "none";
|
|
37327
|
+
document.body.appendChild(link);
|
|
37328
|
+
link.click();
|
|
37329
|
+
setTimeout(() => {
|
|
37330
|
+
document.body.removeChild(link);
|
|
37331
|
+
}, 100);
|
|
37332
|
+
}
|
|
37333
|
+
function shouldConvertFormat(format) {
|
|
37334
|
+
const supportedConversions = ["webp", "jpeg", "jpg", "png"];
|
|
37335
|
+
return supportedConversions.includes(format.toLowerCase());
|
|
37336
|
+
}
|
|
37337
|
+
async function convertBlobFormat(blob, targetFormat) {
|
|
37338
|
+
return new Promise((resolve, reject) => {
|
|
37339
|
+
const img = new Image();
|
|
37340
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
37341
|
+
img.onload = () => {
|
|
37342
|
+
try {
|
|
37343
|
+
const canvas = document.createElement("canvas");
|
|
37344
|
+
canvas.width = img.width;
|
|
37345
|
+
canvas.height = img.height;
|
|
37346
|
+
const ctx = canvas.getContext("2d");
|
|
37347
|
+
ctx.drawImage(img, 0, 0);
|
|
37348
|
+
const mimeType = `image/${targetFormat === "jpg" ? "jpeg" : targetFormat}`;
|
|
37349
|
+
const quality = targetFormat === "png" ? void 0 : 0.92;
|
|
37350
|
+
canvas.toBlob(
|
|
37351
|
+
(convertedBlob) => {
|
|
37352
|
+
URL.revokeObjectURL(objectUrl);
|
|
37353
|
+
if (convertedBlob) {
|
|
37354
|
+
resolve(convertedBlob);
|
|
37355
|
+
} else {
|
|
37356
|
+
resolve(blob);
|
|
37357
|
+
}
|
|
37358
|
+
},
|
|
37359
|
+
mimeType,
|
|
37360
|
+
quality
|
|
37361
|
+
);
|
|
37362
|
+
} catch (error) {
|
|
37363
|
+
URL.revokeObjectURL(objectUrl);
|
|
37364
|
+
resolve(blob);
|
|
37365
|
+
}
|
|
37366
|
+
};
|
|
37367
|
+
img.onerror = () => {
|
|
37368
|
+
URL.revokeObjectURL(objectUrl);
|
|
37369
|
+
resolve(blob);
|
|
37370
|
+
};
|
|
37371
|
+
img.src = objectUrl;
|
|
37372
|
+
});
|
|
37373
|
+
}
|
|
37374
|
+
const downloadImage$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
37375
|
+
__proto__: null,
|
|
37376
|
+
default: downloadImage,
|
|
37377
|
+
downloadImage
|
|
37378
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
36969
37379
|
function CropperView({
|
|
36970
37380
|
image,
|
|
36971
37381
|
onSave,
|
|
36972
37382
|
onCancel,
|
|
36973
37383
|
onDelete,
|
|
37384
|
+
onError = null,
|
|
37385
|
+
// Callback para manejar errores
|
|
36974
37386
|
deleting = false,
|
|
36975
37387
|
onVariantCreated = null
|
|
36976
37388
|
// Callback cuando se crea una variante
|
|
@@ -36978,7 +37390,6 @@ function CropperView({
|
|
|
36978
37390
|
const [showPreview, setShowPreview] = useState(false);
|
|
36979
37391
|
const [previewUrl, setPreviewUrl] = useState(null);
|
|
36980
37392
|
const [previewLoading, setPreviewLoading] = useState(false);
|
|
36981
|
-
const [aspectRatio, setAspectRatio] = useState("");
|
|
36982
37393
|
const [showGrid, setShowGrid] = useState(true);
|
|
36983
37394
|
const [shade, setShade] = useState(true);
|
|
36984
37395
|
const [flipStates, setFlipStates] = useState({
|
|
@@ -36986,27 +37397,88 @@ function CropperView({
|
|
|
36986
37397
|
vertical: false
|
|
36987
37398
|
});
|
|
36988
37399
|
const [showTips, setShowTips] = useState(false);
|
|
37400
|
+
const [showVisualOptions, setShowVisualOptions] = useState(true);
|
|
37401
|
+
const [showSelectorOptions, setShowSelectorOptions] = useState(true);
|
|
37402
|
+
const [showImageOptions, setShowImageOptions] = useState(true);
|
|
36989
37403
|
const [zoomInfo, setZoomInfo] = useState({ current: 1, percentage: 100 });
|
|
36990
|
-
const
|
|
36991
|
-
|
|
37404
|
+
const [editableFilename] = useState(() => {
|
|
37405
|
+
const [name] = image.filename.split(".");
|
|
37406
|
+
return name;
|
|
37407
|
+
});
|
|
37408
|
+
const cropConfig = useMemo(() => {
|
|
36992
37409
|
const config = window.limboCore?.config?.getGlobal() || {};
|
|
36993
|
-
|
|
36994
|
-
|
|
36995
|
-
|
|
36996
|
-
|
|
36997
|
-
|
|
36998
|
-
|
|
36999
|
-
|
|
37000
|
-
|
|
37001
|
-
];
|
|
37410
|
+
const mandatoryCrops = config.cropper?.mandatoryCrops || [];
|
|
37411
|
+
const allowCustomCrops = config.cropper?.allowCustomCrops !== false;
|
|
37412
|
+
const showDimensionInputs = config.cropper?.showDimensionInputs === true;
|
|
37413
|
+
return {
|
|
37414
|
+
mandatoryCrops,
|
|
37415
|
+
allowCustomCrops,
|
|
37416
|
+
showDimensionInputs
|
|
37417
|
+
};
|
|
37002
37418
|
}, []);
|
|
37419
|
+
const [crops, setCrops] = useState(() => {
|
|
37420
|
+
if (cropConfig.mandatoryCrops.length > 0) {
|
|
37421
|
+
return cropConfig.mandatoryCrops.map((crop, index) => ({
|
|
37422
|
+
id: `crop-${index}`,
|
|
37423
|
+
label: crop.label,
|
|
37424
|
+
width: crop.width,
|
|
37425
|
+
height: crop.height,
|
|
37426
|
+
required: crop.required !== false,
|
|
37427
|
+
// Por defecto son obligatorios
|
|
37428
|
+
isCustom: false,
|
|
37429
|
+
confirmed: false,
|
|
37430
|
+
// Estado del crop (se guarda al cambiar de crop)
|
|
37431
|
+
savedState: null
|
|
37432
|
+
// {cropData, transforms: {zoom, rotation, flip}}
|
|
37433
|
+
}));
|
|
37434
|
+
} else {
|
|
37435
|
+
return [
|
|
37436
|
+
{
|
|
37437
|
+
id: "crop-default-0",
|
|
37438
|
+
label: editableFilename,
|
|
37439
|
+
width: image.width || 1920,
|
|
37440
|
+
height: image.height || 1080,
|
|
37441
|
+
required: false,
|
|
37442
|
+
isCustom: true,
|
|
37443
|
+
confirmed: false,
|
|
37444
|
+
savedState: null
|
|
37445
|
+
}
|
|
37446
|
+
];
|
|
37447
|
+
}
|
|
37448
|
+
});
|
|
37449
|
+
const [activeCropIndex, setActiveCropIndex] = useState(0);
|
|
37450
|
+
const activeCrop = crops[activeCropIndex];
|
|
37451
|
+
const [shouldCenter, setShouldCenter] = useState(false);
|
|
37452
|
+
const calculatedAspectRatio = useMemo(() => {
|
|
37453
|
+
if (!activeCrop || !activeCrop.width || !activeCrop.height) return "";
|
|
37454
|
+
return activeCrop.width / activeCrop.height;
|
|
37455
|
+
}, [activeCrop]);
|
|
37456
|
+
const minCropSizes = useMemo(() => {
|
|
37457
|
+
const MIN_SIZE = 50;
|
|
37458
|
+
if (!calculatedAspectRatio || calculatedAspectRatio === "") {
|
|
37459
|
+
return { minWidth: MIN_SIZE, minHeight: MIN_SIZE };
|
|
37460
|
+
}
|
|
37461
|
+
if (calculatedAspectRatio >= 1) {
|
|
37462
|
+
const minWidth = MIN_SIZE;
|
|
37463
|
+
const minHeight = MIN_SIZE / calculatedAspectRatio;
|
|
37464
|
+
return { minWidth, minHeight };
|
|
37465
|
+
} else {
|
|
37466
|
+
const minHeight = MIN_SIZE;
|
|
37467
|
+
const minWidth = MIN_SIZE * calculatedAspectRatio;
|
|
37468
|
+
return { minWidth, minHeight };
|
|
37469
|
+
}
|
|
37470
|
+
}, [calculatedAspectRatio]);
|
|
37471
|
+
const [showConfirmModal, setShowConfirmModal] = useState(false);
|
|
37472
|
+
const [selectedCropsForAction, setSelectedCropsForAction] = useState([]);
|
|
37473
|
+
const [pendingAction, setPendingAction] = useState(null);
|
|
37474
|
+
const accessibilityManager = window.limboCore?.accessibilityManager;
|
|
37003
37475
|
const {
|
|
37004
37476
|
createCropVariant,
|
|
37005
37477
|
loading: creatingVariant,
|
|
37006
37478
|
error: variantError
|
|
37007
37479
|
} = useCreateVariant();
|
|
37008
37480
|
const cropper = useCropper(image, {
|
|
37009
|
-
aspectRatio,
|
|
37481
|
+
aspectRatio: calculatedAspectRatio || null,
|
|
37010
37482
|
showGrid,
|
|
37011
37483
|
shade,
|
|
37012
37484
|
initialCoverage: 0.5,
|
|
@@ -37015,31 +37487,37 @@ function CropperView({
|
|
|
37015
37487
|
const { refs, state, transform, selection, utils } = cropper;
|
|
37016
37488
|
const { canvasRef, imageRef, selectionRef } = refs;
|
|
37017
37489
|
const { cropData, imageInfo, canExport, transformVersion } = state;
|
|
37018
|
-
const effectiveImageInfo = useMemo(
|
|
37019
|
-
|
|
37020
|
-
|
|
37021
|
-
|
|
37022
|
-
|
|
37023
|
-
|
|
37024
|
-
|
|
37490
|
+
const effectiveImageInfo = useMemo(
|
|
37491
|
+
() => imageInfo || {
|
|
37492
|
+
naturalWidth: image.width || 1920,
|
|
37493
|
+
// Usar dimensiones de la imagen prop como fallback
|
|
37494
|
+
naturalHeight: image.height || 1080,
|
|
37495
|
+
currentWidth: image.width || 1920,
|
|
37496
|
+
currentHeight: image.height || 1080
|
|
37497
|
+
},
|
|
37498
|
+
[imageInfo, image.width, image.height]
|
|
37499
|
+
);
|
|
37025
37500
|
const toggleGrid = useCallback(() => setShowGrid((v) => !v), []);
|
|
37026
37501
|
const toggleShade = useCallback(() => setShade((v) => !v), []);
|
|
37027
37502
|
const toggleTips = useCallback(() => setShowTips((v) => !v), []);
|
|
37503
|
+
const toggleVisualOptions = useCallback(
|
|
37504
|
+
() => setShowVisualOptions((v) => !v),
|
|
37505
|
+
[]
|
|
37506
|
+
);
|
|
37507
|
+
const toggleSelectorOptions = useCallback(
|
|
37508
|
+
() => setShowSelectorOptions((v) => !v),
|
|
37509
|
+
[]
|
|
37510
|
+
);
|
|
37511
|
+
const toggleImageOptions = useCallback(
|
|
37512
|
+
() => setShowImageOptions((v) => !v),
|
|
37513
|
+
[]
|
|
37514
|
+
);
|
|
37028
37515
|
const centerImage = useCallback(() => transform.center(), [transform]);
|
|
37029
37516
|
const centerSelection = useCallback(() => selection.center(), [selection]);
|
|
37030
37517
|
const resetSelection = useCallback(() => selection.reset(), [selection]);
|
|
37031
37518
|
const move = useCallback((x, y) => transform.move(x, y), [transform]);
|
|
37032
37519
|
const zoom = useCallback((factor) => transform.zoom(factor), [transform]);
|
|
37033
37520
|
const rotate = useCallback((deg) => transform.rotate(deg), [transform]);
|
|
37034
|
-
const resetAll = useCallback(() => {
|
|
37035
|
-
utils.resetAll();
|
|
37036
|
-
setAspectRatio("");
|
|
37037
|
-
setShowGrid(true);
|
|
37038
|
-
setShade(true);
|
|
37039
|
-
setFlipStates({ horizontal: false, vertical: false });
|
|
37040
|
-
setShowPreview(false);
|
|
37041
|
-
setPreviewUrl(null);
|
|
37042
|
-
}, [utils]);
|
|
37043
37521
|
const setSelectionCoverage = useCallback(
|
|
37044
37522
|
(coverage) => {
|
|
37045
37523
|
selection.setCoverage(coverage);
|
|
@@ -37061,16 +37539,188 @@ function CropperView({
|
|
|
37061
37539
|
return { ...prev, vertical: newVertical };
|
|
37062
37540
|
});
|
|
37063
37541
|
}, [transform]);
|
|
37064
|
-
const
|
|
37065
|
-
(
|
|
37066
|
-
|
|
37067
|
-
const
|
|
37068
|
-
|
|
37542
|
+
const saveCurrentCropState = useCallback(() => {
|
|
37543
|
+
if (!cropper.manager || !state.isReady) return;
|
|
37544
|
+
try {
|
|
37545
|
+
const currentCropData = cropData ? { ...cropData } : null;
|
|
37546
|
+
const currentZoom = cropper.manager.transform.getZoom();
|
|
37547
|
+
const currentRotation = cropper.manager.transform.getRotation();
|
|
37548
|
+
const savedState = {
|
|
37549
|
+
cropData: currentCropData,
|
|
37550
|
+
transforms: {
|
|
37551
|
+
zoom: currentZoom,
|
|
37552
|
+
rotation: currentRotation,
|
|
37553
|
+
flipHorizontal: flipStates.horizontal,
|
|
37554
|
+
flipVertical: flipStates.vertical
|
|
37555
|
+
}
|
|
37556
|
+
};
|
|
37557
|
+
setCrops(
|
|
37558
|
+
(prevCrops) => prevCrops.map(
|
|
37559
|
+
(crop, index) => index === activeCropIndex ? { ...crop, savedState } : crop
|
|
37560
|
+
)
|
|
37069
37561
|
);
|
|
37070
|
-
|
|
37071
|
-
|
|
37562
|
+
return savedState;
|
|
37563
|
+
} catch (error) {
|
|
37564
|
+
console.warn("Error saving crop state:", error);
|
|
37565
|
+
return null;
|
|
37566
|
+
}
|
|
37567
|
+
}, [cropper.manager, state.isReady, cropData, flipStates, activeCropIndex]);
|
|
37568
|
+
const restoreCropState = useCallback(
|
|
37569
|
+
(cropState) => {
|
|
37570
|
+
if (!cropper.manager || !state.isReady || !cropState) return;
|
|
37571
|
+
try {
|
|
37572
|
+
const { cropData: savedCropData, transforms } = cropState;
|
|
37573
|
+
if (transforms) {
|
|
37574
|
+
utils.resetAll();
|
|
37575
|
+
if (transforms.zoom && transforms.zoom !== 1) {
|
|
37576
|
+
cropper.manager.transform.setZoom(transforms.zoom);
|
|
37577
|
+
}
|
|
37578
|
+
if (transforms.rotation && transforms.rotation !== 0) {
|
|
37579
|
+
cropper.manager.transform.setRotation(transforms.rotation);
|
|
37580
|
+
}
|
|
37581
|
+
if (transforms.flipHorizontal) {
|
|
37582
|
+
cropper.manager.transform.flipHorizontal();
|
|
37583
|
+
}
|
|
37584
|
+
if (transforms.flipVertical) {
|
|
37585
|
+
cropper.manager.transform.flipVertical();
|
|
37586
|
+
}
|
|
37587
|
+
setFlipStates({
|
|
37588
|
+
horizontal: transforms.flipHorizontal || false,
|
|
37589
|
+
vertical: transforms.flipVertical || false
|
|
37590
|
+
});
|
|
37591
|
+
}
|
|
37592
|
+
if (savedCropData) {
|
|
37593
|
+
const { x, y, width, height } = savedCropData;
|
|
37594
|
+
selection.set(x, y, width, height);
|
|
37595
|
+
}
|
|
37596
|
+
} catch (error) {
|
|
37597
|
+
console.warn("Error restoring crop state:", error);
|
|
37598
|
+
}
|
|
37599
|
+
},
|
|
37600
|
+
[cropper.manager, state.isReady, selection, utils]
|
|
37601
|
+
);
|
|
37602
|
+
const validateCropNames = useCallback(() => {
|
|
37603
|
+
for (let i = 0; i < crops.length; i++) {
|
|
37604
|
+
const crop = crops[i];
|
|
37605
|
+
if (!crop.label || crop.label.trim() === "") {
|
|
37606
|
+
return i;
|
|
37607
|
+
}
|
|
37608
|
+
}
|
|
37609
|
+
return -1;
|
|
37610
|
+
}, [crops]);
|
|
37611
|
+
const switchToCrop = useCallback(
|
|
37612
|
+
(newIndex) => {
|
|
37613
|
+
if (newIndex === activeCropIndex) return;
|
|
37614
|
+
saveCurrentCropState();
|
|
37615
|
+
setActiveCropIndex(newIndex);
|
|
37616
|
+
setShouldCenter(true);
|
|
37617
|
+
},
|
|
37618
|
+
[activeCropIndex, saveCurrentCropState]
|
|
37619
|
+
);
|
|
37620
|
+
const addCustomCrop = useCallback(() => {
|
|
37621
|
+
if (!cropConfig.allowCustomCrops) {
|
|
37622
|
+
alert("No se pueden añadir recortes personalizados en este modo.");
|
|
37623
|
+
return;
|
|
37624
|
+
}
|
|
37625
|
+
saveCurrentCropState();
|
|
37626
|
+
const newCropId = `crop-custom-${Date.now()}`;
|
|
37627
|
+
const newCrop = {
|
|
37628
|
+
id: newCropId,
|
|
37629
|
+
label: `Recorte ${crops.length + 1}`,
|
|
37630
|
+
width: image.width || 1920,
|
|
37631
|
+
height: image.height || 1080,
|
|
37632
|
+
required: false,
|
|
37633
|
+
isCustom: true,
|
|
37634
|
+
confirmed: false,
|
|
37635
|
+
savedState: null
|
|
37636
|
+
};
|
|
37637
|
+
setCrops((prevCrops) => [...prevCrops, newCrop]);
|
|
37638
|
+
setActiveCropIndex(crops.length);
|
|
37639
|
+
accessibilityManager?.announce(
|
|
37640
|
+
`Nuevo recorte personalizado añadido: ${newCrop.label}`
|
|
37641
|
+
);
|
|
37642
|
+
}, [cropConfig.allowCustomCrops, saveCurrentCropState, crops.length, image.width, image.height, accessibilityManager]);
|
|
37643
|
+
const updateCropDimensions = useCallback(
|
|
37644
|
+
(field, value) => {
|
|
37645
|
+
const numValue = parseInt(value, 10);
|
|
37646
|
+
if (value === "" || isNaN(numValue)) {
|
|
37647
|
+
return;
|
|
37648
|
+
}
|
|
37649
|
+
setCrops(
|
|
37650
|
+
(prevCrops) => prevCrops.map(
|
|
37651
|
+
(crop, index) => index === activeCropIndex ? { ...crop, [field]: numValue } : crop
|
|
37652
|
+
)
|
|
37653
|
+
);
|
|
37654
|
+
},
|
|
37655
|
+
[activeCropIndex]
|
|
37656
|
+
);
|
|
37657
|
+
const validateAndApplyCropDimensions = useCallback(
|
|
37658
|
+
(field) => {
|
|
37659
|
+
const currentValue = activeCrop[field];
|
|
37660
|
+
let minValue = 100;
|
|
37661
|
+
if (canvasRef.current && imageInfo) {
|
|
37662
|
+
const canvasRect = canvasRef.current.getBoundingClientRect();
|
|
37663
|
+
const canvasMinSize = Math.min(canvasRect.width, canvasRect.height);
|
|
37664
|
+
minValue = Math.max(100, Math.round(canvasMinSize * 0.05));
|
|
37665
|
+
}
|
|
37666
|
+
const clampedValue = Math.max(minValue, Math.min(5e3, currentValue));
|
|
37667
|
+
if (clampedValue !== currentValue) {
|
|
37668
|
+
setCrops(
|
|
37669
|
+
(prevCrops) => prevCrops.map(
|
|
37670
|
+
(crop, index) => index === activeCropIndex ? { ...crop, [field]: clampedValue } : crop
|
|
37671
|
+
)
|
|
37672
|
+
);
|
|
37673
|
+
}
|
|
37674
|
+
const updatedCrop = { ...activeCrop, [field]: clampedValue };
|
|
37675
|
+
const newRatio = updatedCrop.width / updatedCrop.height;
|
|
37676
|
+
const currentSelection = selection.getData?.();
|
|
37677
|
+
selection.setAspectRatio(newRatio);
|
|
37678
|
+
if (currentSelection && currentSelection.x !== void 0) {
|
|
37679
|
+
setTimeout(() => {
|
|
37680
|
+
selection.set?.(
|
|
37681
|
+
currentSelection.x,
|
|
37682
|
+
currentSelection.y,
|
|
37683
|
+
currentSelection.width,
|
|
37684
|
+
currentSelection.height
|
|
37685
|
+
);
|
|
37686
|
+
}, 50);
|
|
37687
|
+
}
|
|
37688
|
+
},
|
|
37689
|
+
[activeCropIndex, activeCrop, selection, canvasRef, imageInfo]
|
|
37690
|
+
);
|
|
37691
|
+
const updateCropLabel = useCallback(
|
|
37692
|
+
(newLabel) => {
|
|
37693
|
+
setCrops(
|
|
37694
|
+
(prevCrops) => prevCrops.map(
|
|
37695
|
+
(crop, index) => index === activeCropIndex ? { ...crop, label: newLabel } : crop
|
|
37696
|
+
)
|
|
37697
|
+
);
|
|
37698
|
+
},
|
|
37699
|
+
[activeCropIndex]
|
|
37700
|
+
);
|
|
37701
|
+
const removeCustomCrop = useCallback(
|
|
37702
|
+
(cropIndex) => {
|
|
37703
|
+
const cropToRemove = crops[cropIndex];
|
|
37704
|
+
if (cropToRemove.required) {
|
|
37705
|
+
alert("No se puede eliminar un recorte obligatorio.");
|
|
37706
|
+
return;
|
|
37707
|
+
}
|
|
37708
|
+
if (crops.length === 1) {
|
|
37709
|
+
alert("Debe haber al menos un recorte.");
|
|
37710
|
+
return;
|
|
37711
|
+
}
|
|
37712
|
+
setCrops(
|
|
37713
|
+
(prevCrops) => prevCrops.filter((_, index) => index !== cropIndex)
|
|
37714
|
+
);
|
|
37715
|
+
if (cropIndex === activeCropIndex) {
|
|
37716
|
+
const newIndex = Math.max(0, cropIndex - 1);
|
|
37717
|
+
setActiveCropIndex(newIndex);
|
|
37718
|
+
} else if (cropIndex < activeCropIndex) {
|
|
37719
|
+
setActiveCropIndex((prev) => prev - 1);
|
|
37720
|
+
}
|
|
37721
|
+
accessibilityManager?.announce(`Recorte ${cropToRemove.label} eliminado`);
|
|
37072
37722
|
},
|
|
37073
|
-
[
|
|
37723
|
+
[crops, activeCropIndex, accessibilityManager]
|
|
37074
37724
|
);
|
|
37075
37725
|
const generatePreview = useCallback(async () => {
|
|
37076
37726
|
if (!canExport) return null;
|
|
@@ -37081,12 +37731,15 @@ function CropperView({
|
|
|
37081
37731
|
imageSmoothingEnabled: true,
|
|
37082
37732
|
imageSmoothingQuality: "high"
|
|
37083
37733
|
});
|
|
37084
|
-
return canvas ? canvas.toDataURL(
|
|
37734
|
+
return canvas ? canvas.toDataURL(
|
|
37735
|
+
`image/${globalThis.downloadFormat || image.mime_type.split("/")[1] || "webp"}`,
|
|
37736
|
+
0.9
|
|
37737
|
+
) : null;
|
|
37085
37738
|
} catch (error) {
|
|
37086
37739
|
console.warn("Error generating preview:", error);
|
|
37087
37740
|
return null;
|
|
37088
37741
|
}
|
|
37089
|
-
}, [canExport, selection]);
|
|
37742
|
+
}, [canExport, image.mime_type, selection]);
|
|
37090
37743
|
const preview = useCallback(async () => {
|
|
37091
37744
|
if (showPreview) {
|
|
37092
37745
|
setShowPreview(false);
|
|
@@ -37116,7 +37769,7 @@ function CropperView({
|
|
|
37116
37769
|
setPreviewLoading(false);
|
|
37117
37770
|
}
|
|
37118
37771
|
}, [canExport, generatePreview, showPreview]);
|
|
37119
|
-
const
|
|
37772
|
+
const performSaveCrop = useCallback(async () => {
|
|
37120
37773
|
if (!canExport) {
|
|
37121
37774
|
const errorMsg = "No se puede exportar el recorte por restricciones de CORS en la imagen original.";
|
|
37122
37775
|
accessibilityManager?.announceError(errorMsg);
|
|
@@ -37129,19 +37782,25 @@ function CropperView({
|
|
|
37129
37782
|
alert(errorMsg);
|
|
37130
37783
|
return;
|
|
37131
37784
|
}
|
|
37132
|
-
accessibilityManager?.announce("Creando
|
|
37785
|
+
accessibilityManager?.announce("Creando recorte de la imagen");
|
|
37133
37786
|
try {
|
|
37134
37787
|
if (!cropData || !effectiveImageInfo) {
|
|
37135
37788
|
console.error("❌ Datos faltantes:", { cropData, effectiveImageInfo });
|
|
37136
|
-
throw new Error(
|
|
37789
|
+
throw new Error(
|
|
37790
|
+
`No hay datos de recorte disponibles. CropData: ${!!cropData}, ImageInfo: ${!!effectiveImageInfo}`
|
|
37791
|
+
);
|
|
37137
37792
|
}
|
|
37138
37793
|
if (!cropData.x && cropData.x !== 0 || !cropData.y && cropData.y !== 0 || !cropData.width || !cropData.height) {
|
|
37139
37794
|
console.error("❌ CropData inválido:", cropData);
|
|
37140
|
-
throw new Error(
|
|
37795
|
+
throw new Error(
|
|
37796
|
+
"Los datos de recorte no tienen las propiedades esperadas"
|
|
37797
|
+
);
|
|
37141
37798
|
}
|
|
37142
37799
|
if (!effectiveImageInfo.naturalWidth || !effectiveImageInfo.naturalHeight) {
|
|
37143
37800
|
console.error("❌ ImageInfo inválido:", effectiveImageInfo);
|
|
37144
|
-
throw new Error(
|
|
37801
|
+
throw new Error(
|
|
37802
|
+
"Los datos de imagen no tienen las dimensiones esperadas"
|
|
37803
|
+
);
|
|
37145
37804
|
}
|
|
37146
37805
|
const { x, y, width, height } = cropData;
|
|
37147
37806
|
const { naturalWidth, naturalHeight } = effectiveImageInfo;
|
|
@@ -37151,61 +37810,181 @@ function CropperView({
|
|
|
37151
37810
|
width: width / naturalWidth,
|
|
37152
37811
|
height: height / naturalHeight
|
|
37153
37812
|
};
|
|
37154
|
-
const
|
|
37155
|
-
|
|
37156
|
-
const maxDimension = 1200;
|
|
37157
|
-
if (cropAspectRatio > 1) {
|
|
37158
|
-
variantWidth = Math.min(width, maxDimension);
|
|
37159
|
-
variantHeight = Math.round(variantWidth / cropAspectRatio);
|
|
37160
|
-
} else {
|
|
37161
|
-
variantHeight = Math.min(height, maxDimension);
|
|
37162
|
-
variantWidth = Math.round(variantHeight * cropAspectRatio);
|
|
37163
|
-
}
|
|
37813
|
+
const variantWidth = Math.min(activeCrop.width, 5e3);
|
|
37814
|
+
const variantHeight = Math.min(activeCrop.height, 5e3);
|
|
37164
37815
|
const ts = Date.now();
|
|
37165
|
-
const
|
|
37166
|
-
const variantName = `${name}_crop_${ts}`;
|
|
37816
|
+
const variantName = `${editableFilename}_${activeCrop.label || "crop"}_${ts}`;
|
|
37167
37817
|
const result = await createCropVariant(image.id, cropParams, {
|
|
37168
37818
|
name: variantName,
|
|
37169
37819
|
width: variantWidth,
|
|
37170
37820
|
height: variantHeight,
|
|
37171
|
-
format: "webp",
|
|
37821
|
+
format: globalThis.downloadFormat || "webp",
|
|
37172
37822
|
quality: 90
|
|
37173
37823
|
});
|
|
37174
37824
|
if (result) {
|
|
37175
|
-
accessibilityManager?.announceSuccess(
|
|
37176
|
-
`Variante recortada creada: ${variantName}`
|
|
37177
|
-
);
|
|
37825
|
+
accessibilityManager?.announceSuccess(`Recorte creado: ${variantName}`);
|
|
37178
37826
|
onVariantCreated?.(image.id, result);
|
|
37179
37827
|
onSave(result);
|
|
37180
37828
|
}
|
|
37181
37829
|
} catch (error) {
|
|
37182
37830
|
console.warn("Error creating crop variant:", error);
|
|
37183
|
-
const errorMsg = "No se pudo crear
|
|
37831
|
+
const errorMsg = "No se pudo crear el recorte. Inténtalo de nuevo.";
|
|
37184
37832
|
accessibilityManager?.announceError(errorMsg);
|
|
37185
37833
|
alert(errorMsg);
|
|
37834
|
+
onError?.(error);
|
|
37186
37835
|
}
|
|
37187
37836
|
}, [
|
|
37188
37837
|
canExport,
|
|
37838
|
+
state.isReady,
|
|
37839
|
+
accessibilityManager,
|
|
37189
37840
|
cropData,
|
|
37190
|
-
imageInfo,
|
|
37191
37841
|
effectiveImageInfo,
|
|
37192
|
-
|
|
37193
|
-
|
|
37842
|
+
editableFilename,
|
|
37843
|
+
activeCrop.label,
|
|
37844
|
+
activeCrop.width,
|
|
37845
|
+
activeCrop.height,
|
|
37194
37846
|
createCropVariant,
|
|
37195
|
-
|
|
37847
|
+
image.id,
|
|
37196
37848
|
onVariantCreated,
|
|
37849
|
+
onSave,
|
|
37850
|
+
onError
|
|
37851
|
+
]);
|
|
37852
|
+
const saveCrop = useCallback(async () => {
|
|
37853
|
+
const invalidCropIndex = validateCropNames();
|
|
37854
|
+
if (invalidCropIndex !== -1) {
|
|
37855
|
+
const cropWithoutName = crops[invalidCropIndex];
|
|
37856
|
+
alert(`El recorte "${cropWithoutName.label || cropWithoutName || "(sin nombre)"}" debe tener un nombre válido.`);
|
|
37857
|
+
setActiveCropIndex(invalidCropIndex);
|
|
37858
|
+
return;
|
|
37859
|
+
}
|
|
37860
|
+
if (crops.length > 1) {
|
|
37861
|
+
setPendingAction("save");
|
|
37862
|
+
setSelectedCropsForAction(crops.map((_, index) => index));
|
|
37863
|
+
setShowConfirmModal(true);
|
|
37864
|
+
return;
|
|
37865
|
+
}
|
|
37866
|
+
await performSaveCrop();
|
|
37867
|
+
}, [validateCropNames, crops, performSaveCrop]);
|
|
37868
|
+
const performDownload = useCallback(async () => {
|
|
37869
|
+
if (!canExport) {
|
|
37870
|
+
const errorMsg = "No se puede descargar el recorte por restricciones de CORS en la imagen original.";
|
|
37871
|
+
accessibilityManager?.announceError(errorMsg);
|
|
37872
|
+
alert(errorMsg);
|
|
37873
|
+
return;
|
|
37874
|
+
}
|
|
37875
|
+
try {
|
|
37876
|
+
accessibilityManager?.announce("Preparando descarga del recorte");
|
|
37877
|
+
let downloadUrl = previewUrl;
|
|
37878
|
+
if (!downloadUrl) {
|
|
37879
|
+
downloadUrl = await generatePreview();
|
|
37880
|
+
}
|
|
37881
|
+
if (!downloadUrl) {
|
|
37882
|
+
throw new Error("No se pudo generar la imagen para descargar");
|
|
37883
|
+
}
|
|
37884
|
+
const cropName = activeCrop.label.replace(/\.[^/.]+$/, " ").replace(" ", "-").trim();
|
|
37885
|
+
const filename = `${editableFilename}_${cropName || "crop"}`;
|
|
37886
|
+
await downloadImage(downloadUrl, filename, {
|
|
37887
|
+
accessibilityManager,
|
|
37888
|
+
onSuccess: (finalFilename) => {
|
|
37889
|
+
accessibilityManager?.announce(
|
|
37890
|
+
`Recorte descargado como ${finalFilename}`
|
|
37891
|
+
);
|
|
37892
|
+
},
|
|
37893
|
+
onError: (error) => {
|
|
37894
|
+
accessibilityManager?.announceError(
|
|
37895
|
+
`Error al descargar: ${error.message}`
|
|
37896
|
+
);
|
|
37897
|
+
alert(`Error al descargar la imagen: ${error.message}`);
|
|
37898
|
+
}
|
|
37899
|
+
});
|
|
37900
|
+
} catch (error) {
|
|
37901
|
+
console.error("Error downloading crop:", error);
|
|
37902
|
+
accessibilityManager?.announceError(
|
|
37903
|
+
`Error al descargar el recorte: ${error.message}`
|
|
37904
|
+
);
|
|
37905
|
+
alert(`Error al descargar el recorte: ${error.message}`);
|
|
37906
|
+
}
|
|
37907
|
+
}, [
|
|
37908
|
+
canExport,
|
|
37197
37909
|
accessibilityManager,
|
|
37198
|
-
|
|
37910
|
+
previewUrl,
|
|
37911
|
+
activeCrop.label,
|
|
37912
|
+
editableFilename,
|
|
37913
|
+
generatePreview
|
|
37199
37914
|
]);
|
|
37915
|
+
const handleDownload = useCallback(async () => {
|
|
37916
|
+
const invalidCropIndex = validateCropNames();
|
|
37917
|
+
if (invalidCropIndex !== -1) {
|
|
37918
|
+
const cropWithoutName = crops[invalidCropIndex];
|
|
37919
|
+
alert(`El recorte "${cropWithoutName.label || cropWithoutName || "(sin nombre)"}" debe tener un nombre válido.`);
|
|
37920
|
+
setActiveCropIndex(invalidCropIndex);
|
|
37921
|
+
return;
|
|
37922
|
+
}
|
|
37923
|
+
if (crops.length > 1) {
|
|
37924
|
+
setPendingAction("download");
|
|
37925
|
+
setSelectedCropsForAction(crops.map((_, index) => index));
|
|
37926
|
+
setShowConfirmModal(true);
|
|
37927
|
+
return;
|
|
37928
|
+
}
|
|
37929
|
+
await performDownload();
|
|
37930
|
+
}, [validateCropNames, crops, performDownload]);
|
|
37200
37931
|
useEffect(() => {
|
|
37201
37932
|
setShowPreview(false);
|
|
37202
37933
|
setPreviewUrl(null);
|
|
37203
37934
|
}, [image]);
|
|
37204
37935
|
useEffect(() => {
|
|
37205
37936
|
if (!cropper.manager) return;
|
|
37206
|
-
|
|
37937
|
+
if (calculatedAspectRatio) {
|
|
37938
|
+
selection.setAspectRatio(calculatedAspectRatio);
|
|
37939
|
+
}
|
|
37207
37940
|
utils.setBackground(shade);
|
|
37208
|
-
}, [
|
|
37941
|
+
}, [calculatedAspectRatio, shade, cropper.manager, selection, utils]);
|
|
37942
|
+
useEffect(() => {
|
|
37943
|
+
if (!cropper.manager || !state.isReady) return;
|
|
37944
|
+
const cropState = activeCrop?.savedState;
|
|
37945
|
+
if (cropState) {
|
|
37946
|
+
restoreCropState(cropState);
|
|
37947
|
+
setShouldCenter(false);
|
|
37948
|
+
} else {
|
|
37949
|
+
if (calculatedAspectRatio) {
|
|
37950
|
+
selection.setAspectRatio(calculatedAspectRatio);
|
|
37951
|
+
if (shouldCenter) {
|
|
37952
|
+
setTimeout(() => {
|
|
37953
|
+
selection.center();
|
|
37954
|
+
setShouldCenter(false);
|
|
37955
|
+
}, 100);
|
|
37956
|
+
}
|
|
37957
|
+
}
|
|
37958
|
+
}
|
|
37959
|
+
}, [
|
|
37960
|
+
activeCropIndex,
|
|
37961
|
+
activeCrop,
|
|
37962
|
+
calculatedAspectRatio,
|
|
37963
|
+
cropper.manager,
|
|
37964
|
+
state.isReady,
|
|
37965
|
+
restoreCropState,
|
|
37966
|
+
selection,
|
|
37967
|
+
shouldCenter
|
|
37968
|
+
]);
|
|
37969
|
+
useEffect(() => {
|
|
37970
|
+
if (!imageInfo || !state.isReady || cropConfig.mandatoryCrops.length > 0)
|
|
37971
|
+
return;
|
|
37972
|
+
const defaultCrop = crops[0];
|
|
37973
|
+
if (defaultCrop && defaultCrop.id === "crop-default-0" && (defaultCrop.width === 1920 || defaultCrop.height === 1080)) {
|
|
37974
|
+
const newWidth = Math.min(imageInfo.naturalWidth, 5e3);
|
|
37975
|
+
const newHeight = Math.min(imageInfo.naturalHeight, 5e3);
|
|
37976
|
+
setCrops([
|
|
37977
|
+
{
|
|
37978
|
+
...defaultCrop,
|
|
37979
|
+
width: newWidth,
|
|
37980
|
+
height: newHeight
|
|
37981
|
+
}
|
|
37982
|
+
]);
|
|
37983
|
+
console.log(
|
|
37984
|
+
`[CropperView] Crop por defecto actualizado a ${newWidth}×${newHeight}px`
|
|
37985
|
+
);
|
|
37986
|
+
}
|
|
37987
|
+
}, [imageInfo, state.isReady, cropConfig.mandatoryCrops.length, crops]);
|
|
37209
37988
|
useEffect(() => {
|
|
37210
37989
|
if (!cropper.manager || !cropper.manager.utils) return;
|
|
37211
37990
|
try {
|
|
@@ -37249,7 +38028,7 @@ function CropperView({
|
|
|
37249
38028
|
showPreview,
|
|
37250
38029
|
canExport,
|
|
37251
38030
|
generatePreview,
|
|
37252
|
-
|
|
38031
|
+
calculatedAspectRatio,
|
|
37253
38032
|
flipStates,
|
|
37254
38033
|
previewUrl
|
|
37255
38034
|
]);
|
|
@@ -37282,19 +38061,27 @@ function CropperView({
|
|
|
37282
38061
|
};
|
|
37283
38062
|
}, [canvasRef]);
|
|
37284
38063
|
if (!image) return null;
|
|
37285
|
-
return /* @__PURE__ */ jsxs("div", { className: "limbo-cropper-view px-2 border-2 border-gray-200/50 rounded-lg min-w-fit max-w-7xl mx-auto h-
|
|
37286
|
-
/* @__PURE__ */ jsxs("div", { className: "limbo-cropper-header flex flex-col sm:flex-row justify-between items-start sm:items-center p-4
|
|
37287
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
37288
|
-
/* @__PURE__ */
|
|
37289
|
-
|
|
38064
|
+
return /* @__PURE__ */ jsxs("div", { className: "limbo-cropper-view px-2 border-2 border-gray-200/50 rounded-lg min-w-fit max-w-7xl mx-auto h-full min-h-full flex flex-col", children: [
|
|
38065
|
+
/* @__PURE__ */ jsxs("div", { className: "limbo-cropper-header flex flex-col sm:flex-row justify-between items-start sm:items-center p-4 lg:p-6 pb-4 border-b border-gray-200 bg-white z-10 flex-shrink-0 gap-4 lg:gap-2", children: [
|
|
38066
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 space-y-2", children: [
|
|
38067
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
38068
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg sm:text-xl font-bold text-gray-800", children: "Generar recortes" }),
|
|
38069
|
+
crops.length > 1 && /* @__PURE__ */ jsx("span", { className: "px-2 py-0.5 bg-blue-100 text-blue-800 text-xs font-semibold rounded", children: activeCrop.label })
|
|
38070
|
+
] }),
|
|
38071
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
38072
|
+
/* @__PURE__ */ jsx("label", { className: "text-xs text-gray-500 whitespace-nowrap", children: "Nombre:" }),
|
|
38073
|
+
/* @__PURE__ */ jsx("div", { className: "", children: editableFilename + "." + (globalThis.downloadFormat || image.mime_type.split("/")[1] || "webp") })
|
|
38074
|
+
] })
|
|
37290
38075
|
] }),
|
|
37291
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-2 w-full sm:w-auto", children: [
|
|
38076
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-row self-end gap-2 w-full sm:w-auto", children: [
|
|
37292
38077
|
/* @__PURE__ */ jsx(
|
|
37293
38078
|
"button",
|
|
37294
38079
|
{
|
|
37295
38080
|
onClick: onCancel,
|
|
37296
38081
|
disabled: creatingVariant,
|
|
37297
|
-
className: "limbo-btn limbo-btn-secondary px-4 py-
|
|
38082
|
+
className: "limbo-btn limbo-btn-secondary px-4 sm:py-1 h-min flex-1",
|
|
38083
|
+
"aria-label": "Cancelar y volver",
|
|
38084
|
+
title: "Cancelar y volver",
|
|
37298
38085
|
children: "Cancelar"
|
|
37299
38086
|
}
|
|
37300
38087
|
),
|
|
@@ -37303,8 +38090,9 @@ function CropperView({
|
|
|
37303
38090
|
{
|
|
37304
38091
|
onClick: () => onDelete?.(image),
|
|
37305
38092
|
disabled: deleting | creatingVariant,
|
|
37306
|
-
className: "limbo-btn limbo-btn-danger px-4 py-
|
|
38093
|
+
className: "limbo-btn limbo-btn-danger px-4 sm:py-1 h-min flex-1 sm:flex-initial",
|
|
37307
38094
|
"aria-label": `Eliminar imagen ${image.filename}`,
|
|
38095
|
+
title: `Eliminar imagen ${image.filename}`,
|
|
37308
38096
|
children: deleting ? "Eliminando..." : "Eliminar"
|
|
37309
38097
|
}
|
|
37310
38098
|
)
|
|
@@ -37316,15 +38104,6 @@ function CropperView({
|
|
|
37316
38104
|
" ",
|
|
37317
38105
|
variantError
|
|
37318
38106
|
] }),
|
|
37319
|
-
cropData && cropData.width > 0 && /* @__PURE__ */ jsxs("div", { className: "alert alert-info mb-2 text-sm", role: "status", children: [
|
|
37320
|
-
/* @__PURE__ */ jsx("strong", { children: "Área:" }),
|
|
37321
|
-
" ",
|
|
37322
|
-
Math.round(cropData.width),
|
|
37323
|
-
" ×",
|
|
37324
|
-
" ",
|
|
37325
|
-
Math.round(cropData.height),
|
|
37326
|
-
" px"
|
|
37327
|
-
] }),
|
|
37328
38107
|
imageInfo && /* @__PURE__ */ jsxs("div", { className: "alert alert-secondary mb-2 text-sm", role: "status", children: [
|
|
37329
38108
|
/* @__PURE__ */ jsx("strong", { children: "Original:" }),
|
|
37330
38109
|
" ",
|
|
@@ -37342,10 +38121,135 @@ function CropperView({
|
|
|
37342
38121
|
" px)"
|
|
37343
38122
|
] })
|
|
37344
38123
|
] }),
|
|
37345
|
-
!canExport && /* @__PURE__ */ jsx("div", { className: "alert alert-warning mb-2 text-sm", role: "alert", children: "⚠️ No se puede exportar por restricciones CORS" })
|
|
38124
|
+
!canExport && /* @__PURE__ */ jsx("div", { className: "alert alert-warning mb-2 text-sm", role: "alert", children: "⚠️ No se puede exportar por restricciones CORS" }),
|
|
38125
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-white border-b border-gray-200 p-3 sm:p-4 flex-shrink-0 sticky top-0 z-10 mb-3 shadow-sm", children: [
|
|
38126
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
|
|
38127
|
+
/* @__PURE__ */ jsxs("h3", { className: "text-sm font-semibold text-gray-700", children: [
|
|
38128
|
+
"Recortes ",
|
|
38129
|
+
crops.length > 1 && `(${crops.length})`
|
|
38130
|
+
] }),
|
|
38131
|
+
cropConfig.allowCustomCrops && /* @__PURE__ */ jsxs(
|
|
38132
|
+
"button",
|
|
38133
|
+
{
|
|
38134
|
+
onClick: addCustomCrop,
|
|
38135
|
+
disabled: creatingVariant,
|
|
38136
|
+
className: "text-xs cursor-pointer px-2 py-1 bg-green-100 hover:bg-green-200 text-green-800 rounded border border-green-300 transition-colors flex items-center gap-1",
|
|
38137
|
+
title: "Añadir recorte personalizado",
|
|
38138
|
+
children: [
|
|
38139
|
+
/* @__PURE__ */ jsx("span", { className: "icon icon-add-green text-green-800 icon--xs" }),
|
|
38140
|
+
"Añadir recorte"
|
|
38141
|
+
]
|
|
38142
|
+
}
|
|
38143
|
+
)
|
|
38144
|
+
] }),
|
|
38145
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2 max-h-48 overflow-y-auto grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-2 justify-items-stretch items-start justify-stretch w-full", children: crops.map((crop, index) => /* @__PURE__ */ jsxs(
|
|
38146
|
+
"label",
|
|
38147
|
+
{
|
|
38148
|
+
className: `flex items-center gap-3 p-2 rounded border cursor-pointer transition-colors ${activeCropIndex === index ? "bg-blue-50 border-blue-300" : "bg-gray-50 border-gray-200 hover:bg-gray-100"}`,
|
|
38149
|
+
children: [
|
|
38150
|
+
/* @__PURE__ */ jsx(
|
|
38151
|
+
"input",
|
|
38152
|
+
{
|
|
38153
|
+
type: "radio",
|
|
38154
|
+
name: "active-crop",
|
|
38155
|
+
checked: activeCropIndex === index,
|
|
38156
|
+
onChange: () => switchToCrop(index),
|
|
38157
|
+
disabled: creatingVariant,
|
|
38158
|
+
className: "w-4 h-4 text-blue-600 hidden"
|
|
38159
|
+
}
|
|
38160
|
+
),
|
|
38161
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
38162
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
38163
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-800 truncate", children: activeCrop.label === crop.label && crop.required === false ? /* @__PURE__ */ jsx(
|
|
38164
|
+
"input",
|
|
38165
|
+
{
|
|
38166
|
+
type: "text",
|
|
38167
|
+
value: crop.label,
|
|
38168
|
+
onChange: (e) => updateCropLabel(e.target.value),
|
|
38169
|
+
disabled: creatingVariant || crop.required,
|
|
38170
|
+
className: "w-full text-sm px-2 py-1.5 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed",
|
|
38171
|
+
placeholder: "Nombre del recorte",
|
|
38172
|
+
required: true,
|
|
38173
|
+
maxLength: 25
|
|
38174
|
+
}
|
|
38175
|
+
) : crop.label }),
|
|
38176
|
+
crop.required && /* @__PURE__ */ jsx("span", { className: "text-xs px-1.5 py-0.5 bg-red-100 text-red-700 rounded", children: "Obligatorio" }),
|
|
38177
|
+
crop.isCustom && /* @__PURE__ */ jsx("span", { className: "text-xs px-1.5 py-0.5 bg-purple-100 text-purple-700 rounded", children: "Personalizado" })
|
|
38178
|
+
] }),
|
|
38179
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-500", children: [
|
|
38180
|
+
crop.width,
|
|
38181
|
+
" × ",
|
|
38182
|
+
crop.height,
|
|
38183
|
+
" px"
|
|
38184
|
+
] })
|
|
38185
|
+
] }),
|
|
38186
|
+
!crop.required && crops.length > 1 && /* @__PURE__ */ jsx(
|
|
38187
|
+
"button",
|
|
38188
|
+
{
|
|
38189
|
+
onClick: (e) => {
|
|
38190
|
+
e.preventDefault();
|
|
38191
|
+
removeCustomCrop(index);
|
|
38192
|
+
},
|
|
38193
|
+
className: `flex items-stretch group max-h-fit hover:bg-red-500/50 text-red-500 hover:text-red-700 p-1 rounded-full aspect-square cursor-pointer`,
|
|
38194
|
+
title: "Eliminar recorte",
|
|
38195
|
+
children: /* @__PURE__ */ jsx(
|
|
38196
|
+
"span",
|
|
38197
|
+
{
|
|
38198
|
+
className: `group-hover:bg-gray-transparent-50 icon icon-close-small icon--xs`
|
|
38199
|
+
}
|
|
38200
|
+
)
|
|
38201
|
+
}
|
|
38202
|
+
)
|
|
38203
|
+
]
|
|
38204
|
+
},
|
|
38205
|
+
crop.id
|
|
38206
|
+
)) }),
|
|
38207
|
+
activeCrop && /* @__PURE__ */ jsx("div", { className: "mt-4 pt-4 border-t border-gray-200 space-y-3", children: /* @__PURE__ */ jsxs("div", { children: [
|
|
38208
|
+
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-gray-700 block mb-1", children: "Dimensiones (px)" }),
|
|
38209
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
38210
|
+
/* @__PURE__ */ jsx(
|
|
38211
|
+
"input",
|
|
38212
|
+
{
|
|
38213
|
+
type: "number",
|
|
38214
|
+
min: "100",
|
|
38215
|
+
max: "5000",
|
|
38216
|
+
value: activeCrop.width,
|
|
38217
|
+
onChange: (e) => updateCropDimensions("width", e.target.value),
|
|
38218
|
+
onBlur: () => validateAndApplyCropDimensions("width"),
|
|
38219
|
+
disabled: creatingVariant,
|
|
38220
|
+
className: "flex-1 text-sm px-2 py-1.5 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500",
|
|
38221
|
+
placeholder: "Ancho"
|
|
38222
|
+
}
|
|
38223
|
+
),
|
|
38224
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-400 font-bold", children: "×" }),
|
|
38225
|
+
/* @__PURE__ */ jsx(
|
|
38226
|
+
"input",
|
|
38227
|
+
{
|
|
38228
|
+
type: "number",
|
|
38229
|
+
min: "100",
|
|
38230
|
+
max: "5000",
|
|
38231
|
+
value: activeCrop.height,
|
|
38232
|
+
onChange: (e) => updateCropDimensions("height", e.target.value),
|
|
38233
|
+
onBlur: () => validateAndApplyCropDimensions("height"),
|
|
38234
|
+
disabled: creatingVariant,
|
|
38235
|
+
className: "flex-1 text-sm px-2 py-1.5 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500",
|
|
38236
|
+
placeholder: "Alto"
|
|
38237
|
+
}
|
|
38238
|
+
)
|
|
38239
|
+
] }),
|
|
38240
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mt-1", children: [
|
|
38241
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-500", children: [
|
|
38242
|
+
"Proporción:",
|
|
38243
|
+
" ",
|
|
38244
|
+
calculatedAspectRatio ? calculatedAspectRatio.toFixed(2) : "N/A"
|
|
38245
|
+
] }),
|
|
38246
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400", children: "Min: 100px | Max: 5000px" })
|
|
38247
|
+
] })
|
|
38248
|
+
] }) })
|
|
38249
|
+
] })
|
|
37346
38250
|
] }),
|
|
37347
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col
|
|
37348
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 relative min-w-0 order-
|
|
38251
|
+
/* @__PURE__ */ jsxs("div", { className: "cropper-main-content-area flex flex-col lg:flex-row flex-1 overflow-hidden rounded-lg gap-4 md:gap-0 aspect-auto lg:aspect-square xl:aspect-auto w-full max-w-[95%] lg:max-w-full self-center lg:max-h-[50rem]", children: [
|
|
38252
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 relative min-w-0 order-1", children: /* @__PURE__ */ jsxs("div", { className: "limbo-cropper-container lg:absolute inset-2 sm:inset-4 bg-white rounded-lg border-2 border-gray-200 shadow-lg overflow-hidden", children: [
|
|
37349
38253
|
showPreview && /* @__PURE__ */ jsxs("div", { className: "absolute top-2 sm:top-4 right-2 sm:right-4 bg-white rounded-lg border border-gray-300 p-2 sm:p-3 z-50 shadow-xl w-48 sm:w-64 max-w-[calc(50%-1rem)] sm:max-w-[calc(50%-2rem)] md:min-w-1/4", children: [
|
|
37350
38254
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-2", children: [
|
|
37351
38255
|
/* @__PURE__ */ jsx("h3", { className: "text-xs font-semibold text-gray-700", children: "Vista previa" }),
|
|
@@ -37418,9 +38322,13 @@ function CropperView({
|
|
|
37418
38322
|
"initial-coverage": "0.5",
|
|
37419
38323
|
movable: true,
|
|
37420
38324
|
resizable: true,
|
|
37421
|
-
keyboard: "
|
|
38325
|
+
keyboard: "true",
|
|
37422
38326
|
action: "move",
|
|
37423
|
-
style: {
|
|
38327
|
+
style: {
|
|
38328
|
+
cursor: "move",
|
|
38329
|
+
minWidth: `${minCropSizes.minWidth}px`,
|
|
38330
|
+
minHeight: `${minCropSizes.minHeight}px`
|
|
38331
|
+
},
|
|
37424
38332
|
"data-prevent-delete": "true",
|
|
37425
38333
|
tabindex: "-1",
|
|
37426
38334
|
children: [
|
|
@@ -37463,61 +38371,401 @@ function CropperView({
|
|
|
37463
38371
|
}
|
|
37464
38372
|
)
|
|
37465
38373
|
] }) }),
|
|
37466
|
-
/* @__PURE__ */ jsx("div", { className: "limbo-cropper-controls w-full
|
|
37467
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4
|
|
37468
|
-
/* @__PURE__ */ jsx(
|
|
37469
|
-
|
|
38374
|
+
/* @__PURE__ */ jsx("div", { className: "flex limbo-cropper-controls w-full lg:w-80 h-full bg-white border-t md:border-t-0 md:border-l border-gray-200 lg:overflow-y-auto flex-shrink-0 order-1 max-h-none", children: /* @__PURE__ */ jsxs("div", { className: "p-3 min-h-full sm:p-4 space-y-3 sm:space-y-4 relative w-full grid grid-cols-1 lg:flex lg:flex-col", children: [
|
|
38375
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [
|
|
38376
|
+
/* @__PURE__ */ jsx(
|
|
38377
|
+
"button",
|
|
38378
|
+
{
|
|
38379
|
+
onClick: toggleVisualOptions,
|
|
38380
|
+
className: "w-full p-2 my-1 cursor-pointer hover:bg-neutral-gray-050/50 transition-colors rounded-md",
|
|
38381
|
+
"aria-expanded": showVisualOptions,
|
|
38382
|
+
"aria-label": "Mostrar/ocultar opciones de visualizción",
|
|
38383
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
38384
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-700", children: "Visualización" }),
|
|
38385
|
+
/* @__PURE__ */ jsx("div", { className: "text-center", children: /* @__PURE__ */ jsx(
|
|
38386
|
+
"span",
|
|
38387
|
+
{
|
|
38388
|
+
className: `icon ${!showVisualOptions ? "icon-chevron-down" : "icon-chevron-up"} text-center icon--xs`
|
|
38389
|
+
}
|
|
38390
|
+
) })
|
|
38391
|
+
] })
|
|
38392
|
+
}
|
|
38393
|
+
),
|
|
38394
|
+
showVisualOptions && /* @__PURE__ */ jsxs("div", { className: "pb-2 space-y-2", children: [
|
|
37470
38395
|
/* @__PURE__ */ jsxs(
|
|
37471
38396
|
"button",
|
|
37472
38397
|
{
|
|
37473
|
-
onClick:
|
|
37474
|
-
|
|
37475
|
-
|
|
37476
|
-
"aria-
|
|
38398
|
+
onClick: toggleGrid,
|
|
38399
|
+
className: `w-full flex cursor-pointer items-center justify-between p-2 rounded transition-colors ${showGrid ? "bg-blue-100 border border-blue-300 text-blue-800" : "bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200"}`,
|
|
38400
|
+
disabled: creatingVariant,
|
|
38401
|
+
"aria-pressed": showGrid,
|
|
38402
|
+
title: "Mostrar/ocultar cuadrícula de la regla de los tercios en el selector",
|
|
38403
|
+
"aria-label": "Activar/desactivar grid",
|
|
37477
38404
|
children: [
|
|
37478
|
-
/* @__PURE__ */
|
|
37479
|
-
"span",
|
|
37480
|
-
|
|
37481
|
-
|
|
37482
|
-
|
|
37483
|
-
|
|
37484
|
-
|
|
38405
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm flex items-center", children: [
|
|
38406
|
+
/* @__PURE__ */ jsx("span", { className: "icon icon-area-blue me-1" }),
|
|
38407
|
+
" ",
|
|
38408
|
+
"Cuadrícula"
|
|
38409
|
+
] }),
|
|
38410
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", children: showGrid ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38411
|
+
/* @__PURE__ */ jsx("span", { className: "icon icon-tick icon--xs align-[middle!important] -mt-0.5" }),
|
|
38412
|
+
" ",
|
|
38413
|
+
"Activo"
|
|
38414
|
+
] }) : "Inactivo" })
|
|
37485
38415
|
]
|
|
37486
38416
|
}
|
|
37487
38417
|
),
|
|
37488
|
-
/* @__PURE__ */ jsx(
|
|
37489
|
-
"button",
|
|
37490
|
-
{
|
|
37491
|
-
onClick: saveCrop,
|
|
37492
|
-
disabled: creatingVariant || !cropData || !effectiveImageInfo || !canExport || !state.isReady,
|
|
37493
|
-
className: "w-full limbo-btn limbo-btn-success min-h-10",
|
|
37494
|
-
"aria-label": "Guardar imagen recortada",
|
|
37495
|
-
children: creatingVariant ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37496
|
-
/* @__PURE__ */ jsx("span", { className: "icon icon-save-white" }),
|
|
37497
|
-
" ",
|
|
37498
|
-
"Guardando..."
|
|
37499
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37500
|
-
/* @__PURE__ */ jsx("span", { className: "icon icon-save-white" }),
|
|
37501
|
-
" Guardar recorte"
|
|
37502
|
-
] })
|
|
37503
|
-
}
|
|
37504
|
-
),
|
|
37505
38418
|
/* @__PURE__ */ jsxs(
|
|
37506
38419
|
"button",
|
|
37507
38420
|
{
|
|
37508
|
-
onClick:
|
|
38421
|
+
onClick: toggleShade,
|
|
38422
|
+
className: `w-full flex cursor-pointer items-center justify-between p-2 rounded transition-colors ${shade ? "bg-blue-100 border border-blue-300 text-blue-800" : "bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200"}`,
|
|
37509
38423
|
disabled: creatingVariant,
|
|
37510
|
-
|
|
37511
|
-
"aria-label": "
|
|
38424
|
+
"aria-pressed": shade,
|
|
38425
|
+
"aria-label": "Activar/desactivar sombreado",
|
|
37512
38426
|
children: [
|
|
37513
|
-
/* @__PURE__ */
|
|
37514
|
-
|
|
38427
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm flex items-center", children: [
|
|
38428
|
+
/* @__PURE__ */ jsx("span", { className: "icon icon-comparison-blue me-1" }),
|
|
38429
|
+
" ",
|
|
38430
|
+
"Tablero"
|
|
38431
|
+
] }),
|
|
38432
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", children: shade ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38433
|
+
/* @__PURE__ */ jsx("span", { className: "icon icon-tick icon--xs align-[middle!important] -mt-0.5" }),
|
|
38434
|
+
" ",
|
|
38435
|
+
"Activo"
|
|
38436
|
+
] }) : "Inactivo" })
|
|
37515
38437
|
]
|
|
37516
38438
|
}
|
|
37517
38439
|
)
|
|
37518
38440
|
] })
|
|
37519
38441
|
] }),
|
|
37520
|
-
/* @__PURE__ */ jsxs(
|
|
38442
|
+
/* @__PURE__ */ jsxs(
|
|
38443
|
+
"div",
|
|
38444
|
+
{
|
|
38445
|
+
className: "bg-white rounded-lg border border-gray-200 p-4" + (showSelectorOptions ? "" : " bg-neutral-gray-50/50"),
|
|
38446
|
+
children: [
|
|
38447
|
+
/* @__PURE__ */ jsx(
|
|
38448
|
+
"button",
|
|
38449
|
+
{
|
|
38450
|
+
onClick: toggleSelectorOptions,
|
|
38451
|
+
className: "w-full p-2 my-1 cursor-pointer hover:bg-neutral-gray-050/50 transition-colors rounded-md",
|
|
38452
|
+
"aria-expanded": showSelectorOptions,
|
|
38453
|
+
"aria-label": "Mostrar/ocultar opciones de visualizción",
|
|
38454
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
38455
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-700", children: "Ajustes del selector" }),
|
|
38456
|
+
/* @__PURE__ */ jsx("div", { className: "text-center", children: /* @__PURE__ */ jsx(
|
|
38457
|
+
"span",
|
|
38458
|
+
{
|
|
38459
|
+
className: `icon ${!showSelectorOptions ? "icon-chevron-down" : "icon-chevron-up"} text-center icon--xs`
|
|
38460
|
+
}
|
|
38461
|
+
) })
|
|
38462
|
+
] })
|
|
38463
|
+
}
|
|
38464
|
+
),
|
|
38465
|
+
showSelectorOptions && /* @__PURE__ */ jsxs("div", { children: [
|
|
38466
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
38467
|
+
/* @__PURE__ */ jsx(
|
|
38468
|
+
"button",
|
|
38469
|
+
{
|
|
38470
|
+
onClick: () => setSelectionCoverage(0.5),
|
|
38471
|
+
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38472
|
+
disabled: creatingVariant,
|
|
38473
|
+
"aria-label": "Selección 50%",
|
|
38474
|
+
title: "Tamaño de selector 50%",
|
|
38475
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "50%" }) })
|
|
38476
|
+
}
|
|
38477
|
+
),
|
|
38478
|
+
/* @__PURE__ */ jsx(
|
|
38479
|
+
"button",
|
|
38480
|
+
{
|
|
38481
|
+
onClick: () => setSelectionCoverage(0.7),
|
|
38482
|
+
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38483
|
+
disabled: creatingVariant,
|
|
38484
|
+
"aria-label": "Selección 70%",
|
|
38485
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "70%" }) })
|
|
38486
|
+
}
|
|
38487
|
+
),
|
|
38488
|
+
/* @__PURE__ */ jsx(
|
|
38489
|
+
"button",
|
|
38490
|
+
{
|
|
38491
|
+
onClick: () => setSelectionCoverage(0.9),
|
|
38492
|
+
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38493
|
+
disabled: creatingVariant,
|
|
38494
|
+
"aria-label": "Selección 90%",
|
|
38495
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "90%" }) })
|
|
38496
|
+
}
|
|
38497
|
+
),
|
|
38498
|
+
/* @__PURE__ */ jsx(
|
|
38499
|
+
"button",
|
|
38500
|
+
{
|
|
38501
|
+
onClick: () => setSelectionCoverage(1),
|
|
38502
|
+
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38503
|
+
disabled: creatingVariant,
|
|
38504
|
+
"aria-label": "Selección completa",
|
|
38505
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "100%" }) })
|
|
38506
|
+
}
|
|
38507
|
+
)
|
|
38508
|
+
] }) }),
|
|
38509
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 pt-2", children: [
|
|
38510
|
+
/* @__PURE__ */ jsx(
|
|
38511
|
+
"button",
|
|
38512
|
+
{
|
|
38513
|
+
onClick: centerSelection,
|
|
38514
|
+
className: "w-full p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38515
|
+
title: "Centrar selección",
|
|
38516
|
+
disabled: creatingVariant,
|
|
38517
|
+
"aria-label": "Centrar área de selección",
|
|
38518
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxs("span", { children: [
|
|
38519
|
+
/* @__PURE__ */ jsx("span", { className: "icon icon-radio-button icon--sm align-[middle!important] " }),
|
|
38520
|
+
" ",
|
|
38521
|
+
"Centrar selección"
|
|
38522
|
+
] }) })
|
|
38523
|
+
}
|
|
38524
|
+
),
|
|
38525
|
+
/* @__PURE__ */ jsx(
|
|
38526
|
+
"button",
|
|
38527
|
+
{
|
|
38528
|
+
onClick: resetSelection,
|
|
38529
|
+
className: "w-full p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38530
|
+
title: "Reiniciar selección",
|
|
38531
|
+
disabled: creatingVariant,
|
|
38532
|
+
"aria-label": "Reiniciar área de selección",
|
|
38533
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxs("span", { children: [
|
|
38534
|
+
/* @__PURE__ */ jsx("span", { className: "icon icon-refresh icon--sm lign-[middle!important] " }),
|
|
38535
|
+
" ",
|
|
38536
|
+
"Reset selección"
|
|
38537
|
+
] }) })
|
|
38538
|
+
}
|
|
38539
|
+
)
|
|
38540
|
+
] })
|
|
38541
|
+
] })
|
|
38542
|
+
]
|
|
38543
|
+
}
|
|
38544
|
+
),
|
|
38545
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [
|
|
38546
|
+
/* @__PURE__ */ jsx(
|
|
38547
|
+
"button",
|
|
38548
|
+
{
|
|
38549
|
+
onClick: toggleImageOptions,
|
|
38550
|
+
className: "w-full p-2 my-1 cursor-pointer hover:bg-neutral-gray-050/50 transition-colors rounded-md",
|
|
38551
|
+
"aria-expanded": showImageOptions,
|
|
38552
|
+
"aria-label": "Mostrar/ocultar opciones de visualizción",
|
|
38553
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
38554
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-700", children: "Transformar imagen" }),
|
|
38555
|
+
/* @__PURE__ */ jsx("div", { className: "text-center", children: /* @__PURE__ */ jsx(
|
|
38556
|
+
"span",
|
|
38557
|
+
{
|
|
38558
|
+
className: `icon ${!showImageOptions ? "icon-chevron-down" : "icon-chevron-up"} text-center icon--xs`
|
|
38559
|
+
}
|
|
38560
|
+
) })
|
|
38561
|
+
] })
|
|
38562
|
+
}
|
|
38563
|
+
),
|
|
38564
|
+
showImageOptions && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38565
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4 hidden lg:block", children: [
|
|
38566
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 mb-2", children: "Mover imagen" }),
|
|
38567
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-1", children: [
|
|
38568
|
+
/* @__PURE__ */ jsx("div", {}),
|
|
38569
|
+
/* @__PURE__ */ jsx(
|
|
38570
|
+
"button",
|
|
38571
|
+
{
|
|
38572
|
+
onClick: () => move(0, -10),
|
|
38573
|
+
className: "p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38574
|
+
title: "Mover arriba",
|
|
38575
|
+
disabled: creatingVariant,
|
|
38576
|
+
"aria-label": "Mover imagen hacia arriba",
|
|
38577
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-up-blue" }) })
|
|
38578
|
+
}
|
|
38579
|
+
),
|
|
38580
|
+
/* @__PURE__ */ jsx("div", {}),
|
|
38581
|
+
/* @__PURE__ */ jsx(
|
|
38582
|
+
"button",
|
|
38583
|
+
{
|
|
38584
|
+
onClick: () => move(-10, 0),
|
|
38585
|
+
className: "p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38586
|
+
title: "Mover izquierda",
|
|
38587
|
+
disabled: creatingVariant,
|
|
38588
|
+
"aria-label": "Mover imagen hacia la izquierda",
|
|
38589
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-left-blue" }) })
|
|
38590
|
+
}
|
|
38591
|
+
),
|
|
38592
|
+
/* @__PURE__ */ jsx(
|
|
38593
|
+
"button",
|
|
38594
|
+
{
|
|
38595
|
+
onClick: centerImage,
|
|
38596
|
+
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38597
|
+
title: "Centrar y ajustar imagen",
|
|
38598
|
+
disabled: creatingVariant,
|
|
38599
|
+
"aria-label": "Centrar y ajustar imagen",
|
|
38600
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-radio-button-blue icon-md" }) })
|
|
38601
|
+
}
|
|
38602
|
+
),
|
|
38603
|
+
/* @__PURE__ */ jsx(
|
|
38604
|
+
"button",
|
|
38605
|
+
{
|
|
38606
|
+
onClick: () => move(10, 0),
|
|
38607
|
+
className: "p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38608
|
+
title: "Mover derecha",
|
|
38609
|
+
disabled: creatingVariant,
|
|
38610
|
+
"aria-label": "Mover imagen hacia la derecha",
|
|
38611
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-right-blue" }) })
|
|
38612
|
+
}
|
|
38613
|
+
),
|
|
38614
|
+
/* @__PURE__ */ jsx("div", {}),
|
|
38615
|
+
/* @__PURE__ */ jsx(
|
|
38616
|
+
"button",
|
|
38617
|
+
{
|
|
38618
|
+
onClick: () => move(0, 10),
|
|
38619
|
+
className: "p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38620
|
+
title: "Mover abajo",
|
|
38621
|
+
disabled: creatingVariant,
|
|
38622
|
+
"aria-label": "Mover imagen hacia abajo",
|
|
38623
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-down-blue" }) })
|
|
38624
|
+
}
|
|
38625
|
+
),
|
|
38626
|
+
/* @__PURE__ */ jsx("div", {})
|
|
38627
|
+
] })
|
|
38628
|
+
] }),
|
|
38629
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
38630
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-600 mb-2", children: [
|
|
38631
|
+
"Zoom ",
|
|
38632
|
+
zoomInfo ? zoomInfo.percentage + "%" : ""
|
|
38633
|
+
] }),
|
|
38634
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
|
|
38635
|
+
/* @__PURE__ */ jsx(
|
|
38636
|
+
"button",
|
|
38637
|
+
{
|
|
38638
|
+
onClick: () => zoom(-0.2),
|
|
38639
|
+
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38640
|
+
title: "Alejar 20%",
|
|
38641
|
+
disabled: creatingVariant,
|
|
38642
|
+
"aria-label": "Alejar imagen",
|
|
38643
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-zoom-out-blue" }) })
|
|
38644
|
+
}
|
|
38645
|
+
),
|
|
38646
|
+
/* @__PURE__ */ jsx(
|
|
38647
|
+
"button",
|
|
38648
|
+
{
|
|
38649
|
+
onClick: resetZoomOnly,
|
|
38650
|
+
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38651
|
+
title: "Restablecer zoom original",
|
|
38652
|
+
disabled: creatingVariant,
|
|
38653
|
+
"aria-label": "Restablecer el zoom para que la imagen se vea con su resolución original",
|
|
38654
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-screenshot-blue" }) })
|
|
38655
|
+
}
|
|
38656
|
+
),
|
|
38657
|
+
/* @__PURE__ */ jsx(
|
|
38658
|
+
"button",
|
|
38659
|
+
{
|
|
38660
|
+
onClick: () => zoom(0.2),
|
|
38661
|
+
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38662
|
+
title: "Acercar 20%",
|
|
38663
|
+
disabled: creatingVariant,
|
|
38664
|
+
"aria-label": "Acercar imagen",
|
|
38665
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-zoom-in-blue" }) })
|
|
38666
|
+
}
|
|
38667
|
+
)
|
|
38668
|
+
] })
|
|
38669
|
+
] }),
|
|
38670
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
38671
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 mb-2", children: "Rotación" }),
|
|
38672
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-1 *:text-brand-blue-1000 *:text-sm", children: [
|
|
38673
|
+
/* @__PURE__ */ jsx(
|
|
38674
|
+
"button",
|
|
38675
|
+
{
|
|
38676
|
+
onClick: () => rotate(-90),
|
|
38677
|
+
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38678
|
+
title: "Rotar -90°",
|
|
38679
|
+
disabled: creatingVariant,
|
|
38680
|
+
"aria-label": "Rotar imagen 90 grados a la izquierda",
|
|
38681
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-reply-blue" }) })
|
|
38682
|
+
}
|
|
38683
|
+
),
|
|
38684
|
+
/* @__PURE__ */ jsx(
|
|
38685
|
+
"button",
|
|
38686
|
+
{
|
|
38687
|
+
onClick: () => rotate(-45),
|
|
38688
|
+
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38689
|
+
title: "Rotar -45°",
|
|
38690
|
+
disabled: creatingVariant,
|
|
38691
|
+
"aria-label": "Rotar imagen 45 grados a la izquierda",
|
|
38692
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "-45°" }) })
|
|
38693
|
+
}
|
|
38694
|
+
),
|
|
38695
|
+
/* @__PURE__ */ jsx(
|
|
38696
|
+
"button",
|
|
38697
|
+
{
|
|
38698
|
+
onClick: () => rotate(45),
|
|
38699
|
+
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38700
|
+
title: "Rotar +45°",
|
|
38701
|
+
disabled: creatingVariant,
|
|
38702
|
+
"aria-label": "Rotar imagen 45 grados a la derecha",
|
|
38703
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "+45°" }) })
|
|
38704
|
+
}
|
|
38705
|
+
),
|
|
38706
|
+
/* @__PURE__ */ jsx(
|
|
38707
|
+
"button",
|
|
38708
|
+
{
|
|
38709
|
+
onClick: () => rotate(90),
|
|
38710
|
+
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38711
|
+
title: "Rotar +90°",
|
|
38712
|
+
disabled: creatingVariant,
|
|
38713
|
+
"aria-label": "Rotar imagen 90 grados a la derecha",
|
|
38714
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-send-arrow-blue" }) })
|
|
38715
|
+
}
|
|
38716
|
+
)
|
|
38717
|
+
] })
|
|
38718
|
+
] }),
|
|
38719
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
38720
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 mb-2", children: "Voltear" }),
|
|
38721
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
|
|
38722
|
+
/* @__PURE__ */ jsx(
|
|
38723
|
+
"button",
|
|
38724
|
+
{
|
|
38725
|
+
onClick: flipHorizontal,
|
|
38726
|
+
className: `flex-1 p-2 rounded cursor-pointer transition-colors text-sm ${flipStates.horizontal ? "bg-blue-100 border border-blue-300 text-blue-800" : "bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200"}`,
|
|
38727
|
+
title: `Voltear horizontalmente ${flipStates.horizontal ? "(activo)" : ""}`,
|
|
38728
|
+
disabled: creatingVariant,
|
|
38729
|
+
"aria-label": "Voltear imagen horizontalmente",
|
|
38730
|
+
"aria-pressed": flipStates.horizontal,
|
|
38731
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-left-right-blue border border-brand-blue-1000 rounded" }) })
|
|
38732
|
+
}
|
|
38733
|
+
),
|
|
38734
|
+
/* @__PURE__ */ jsx(
|
|
38735
|
+
"button",
|
|
38736
|
+
{
|
|
38737
|
+
onClick: flipVertical,
|
|
38738
|
+
className: `flex-1 p-2 cursor-pointer rounded transition-colors text-sm ${flipStates.vertical ? "bg-blue-100 border border-blue-300 text-blue-800" : "bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200"}`,
|
|
38739
|
+
title: `Voltear verticalmente ${flipStates.vertical ? "(activo)" : ""}`,
|
|
38740
|
+
disabled: creatingVariant,
|
|
38741
|
+
"aria-label": "Voltear imagen verticalmente",
|
|
38742
|
+
"aria-pressed": flipStates.vertical,
|
|
38743
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-up-down-blue border border-brand-blue-1000 rounded" }) })
|
|
38744
|
+
}
|
|
38745
|
+
)
|
|
38746
|
+
] })
|
|
38747
|
+
] }),
|
|
38748
|
+
/* @__PURE__ */ jsx(
|
|
38749
|
+
"button",
|
|
38750
|
+
{
|
|
38751
|
+
onClick: () => {
|
|
38752
|
+
transform.reset();
|
|
38753
|
+
setFlipStates({ horizontal: false, vertical: false });
|
|
38754
|
+
},
|
|
38755
|
+
className: "w-full p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
38756
|
+
title: "Reiniciar transformaciones",
|
|
38757
|
+
disabled: creatingVariant,
|
|
38758
|
+
"aria-label": "Reiniciar todas las transformaciones de la imagen",
|
|
38759
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxs("span", { children: [
|
|
38760
|
+
/* @__PURE__ */ jsx("span", { className: "icon icon-refresh-blue icon--sm align-[middle!important] " }),
|
|
38761
|
+
" ",
|
|
38762
|
+
"Reiniciar ajustes"
|
|
38763
|
+
] }) })
|
|
38764
|
+
}
|
|
38765
|
+
)
|
|
38766
|
+
] })
|
|
38767
|
+
] }),
|
|
38768
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-gradient-to-br from-brand-blue-50 to-green-50 rounded-lg border border-blue-200 shadow-sm hidden lg:block", children: [
|
|
37521
38769
|
/* @__PURE__ */ jsxs(
|
|
37522
38770
|
"button",
|
|
37523
38771
|
{
|
|
@@ -37546,7 +38794,7 @@ function CropperView({
|
|
|
37546
38794
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
37547
38795
|
"• ",
|
|
37548
38796
|
/* @__PURE__ */ jsx("strong", { children: "Arrastra la imagen:" }),
|
|
37549
|
-
" Haz clic
|
|
38797
|
+
" Haz clic sobre la imagen del área de selección y arrastra"
|
|
37550
38798
|
] }),
|
|
37551
38799
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
37552
38800
|
"• ",
|
|
@@ -37578,11 +38826,6 @@ function CropperView({
|
|
|
37578
38826
|
"• ",
|
|
37579
38827
|
/* @__PURE__ */ jsx("strong", { children: "Tamaños rápidos:" }),
|
|
37580
38828
|
" Usa los botones 50%, 70%, 90%, 100%"
|
|
37581
|
-
] }),
|
|
37582
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
37583
|
-
"• ",
|
|
37584
|
-
/* @__PURE__ */ jsx("strong", { children: "Proporciones:" }),
|
|
37585
|
-
" Selecciona ratios predefinidos (1:1, 16:9, etc.)"
|
|
37586
38829
|
] })
|
|
37587
38830
|
] })
|
|
37588
38831
|
] }),
|
|
@@ -37620,9 +38863,14 @@ function CropperView({
|
|
|
37620
38863
|
] }),
|
|
37621
38864
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
37622
38865
|
"• ",
|
|
37623
|
-
/* @__PURE__ */ jsx("strong", { children: "
|
|
38866
|
+
/* @__PURE__ */ jsx("strong", { children: "Cuadricula:" }),
|
|
37624
38867
|
" Actívalo para aplicar la regla de los tercios"
|
|
37625
38868
|
] }),
|
|
38869
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
38870
|
+
"• ",
|
|
38871
|
+
/* @__PURE__ */ jsx("strong", { children: "Tablero:" }),
|
|
38872
|
+
" Actívalo para cuadrar medjor las medidas o como ayuda visual para imagenes con transparencia"
|
|
38873
|
+
] }),
|
|
37626
38874
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
37627
38875
|
"• ",
|
|
37628
38876
|
/* @__PURE__ */ jsx("strong", { children: "Transformaciones:" }),
|
|
@@ -37651,366 +38899,139 @@ function CropperView({
|
|
|
37651
38899
|
] })
|
|
37652
38900
|
] })
|
|
37653
38901
|
] })
|
|
37654
|
-
] })
|
|
37655
|
-
|
|
37656
|
-
|
|
37657
|
-
|
|
37658
|
-
|
|
37659
|
-
|
|
37660
|
-
|
|
37661
|
-
|
|
37662
|
-
|
|
37663
|
-
|
|
37664
|
-
|
|
37665
|
-
|
|
37666
|
-
|
|
37667
|
-
|
|
37668
|
-
|
|
37669
|
-
"select",
|
|
37670
|
-
{
|
|
37671
|
-
value: aspectRatio,
|
|
37672
|
-
onChange: (e) => handleAspectRatio(e.target.value),
|
|
37673
|
-
className: "w-full form-control hidden md:block",
|
|
37674
|
-
disabled: creatingVariant,
|
|
37675
|
-
"aria-label": "Seleccionar proporción de aspecto",
|
|
37676
|
-
children: allowedAspectRatios.map((ratio) => /* @__PURE__ */ jsx("option", { value: ratio.value, children: ratio.label }, ratio.value))
|
|
37677
|
-
}
|
|
37678
|
-
)
|
|
37679
|
-
] }),
|
|
37680
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [
|
|
37681
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-700 mb-3", children: "Visualización" }),
|
|
37682
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
37683
|
-
/* @__PURE__ */ jsxs(
|
|
37684
|
-
"button",
|
|
37685
|
-
{
|
|
37686
|
-
onClick: toggleGrid,
|
|
37687
|
-
className: `w-full flex cursor-pointer items-center justify-between p-2 rounded transition-colors ${showGrid ? "bg-blue-100 border border-blue-300 text-blue-800" : "bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200"}`,
|
|
37688
|
-
disabled: creatingVariant,
|
|
37689
|
-
"aria-pressed": showGrid,
|
|
37690
|
-
"aria-label": "Activar/desactivar grid",
|
|
37691
|
-
children: [
|
|
37692
|
-
/* @__PURE__ */ jsxs("span", { className: "text-sm flex items-center", children: [
|
|
37693
|
-
/* @__PURE__ */ jsx("span", { className: "icon icon-area-blue me-1" }),
|
|
37694
|
-
" Grid"
|
|
37695
|
-
] }),
|
|
37696
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs", children: showGrid ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37697
|
-
/* @__PURE__ */ jsx("span", { className: "icon icon-tick icon--xs align-[middle!important] -mt-0.5" }),
|
|
37698
|
-
" ",
|
|
37699
|
-
"Activo"
|
|
37700
|
-
] }) : "Inactivo" })
|
|
37701
|
-
]
|
|
37702
|
-
}
|
|
37703
|
-
),
|
|
37704
|
-
/* @__PURE__ */ jsxs(
|
|
37705
|
-
"button",
|
|
37706
|
-
{
|
|
37707
|
-
onClick: toggleShade,
|
|
37708
|
-
className: `w-full flex cursor-pointer items-center justify-between p-2 rounded transition-colors ${shade ? "bg-blue-100 border border-blue-300 text-blue-800" : "bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200"}`,
|
|
37709
|
-
disabled: creatingVariant,
|
|
37710
|
-
"aria-pressed": shade,
|
|
37711
|
-
"aria-label": "Activar/desactivar sombreado",
|
|
37712
|
-
children: [
|
|
37713
|
-
/* @__PURE__ */ jsxs("span", { className: "text-sm flex items-center", children: [
|
|
37714
|
-
/* @__PURE__ */ jsx("span", { className: "icon icon-comparison-blue me-1" }),
|
|
37715
|
-
" ",
|
|
37716
|
-
"Sombreado"
|
|
37717
|
-
] }),
|
|
37718
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs", children: shade ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37719
|
-
/* @__PURE__ */ jsx("span", { className: "icon icon-tick icon--xs align-[middle!important] -mt-0.5" }),
|
|
37720
|
-
" ",
|
|
37721
|
-
"Activo"
|
|
37722
|
-
] }) : "Inactivo" })
|
|
37723
|
-
]
|
|
37724
|
-
}
|
|
37725
|
-
)
|
|
38902
|
+
] })
|
|
38903
|
+
] }) })
|
|
38904
|
+
] }),
|
|
38905
|
+
/* @__PURE__ */ jsx("div", { className: "limbo-cropper-footer flex-shrink-0 border-t border-gray-200 bg-white p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-row gap-2 sm:gap-3 items-stretch sm:items-center justify-end max-w-7xl mx-auto", children: [
|
|
38906
|
+
/* @__PURE__ */ jsx(
|
|
38907
|
+
"button",
|
|
38908
|
+
{
|
|
38909
|
+
onClick: preview,
|
|
38910
|
+
disabled: creatingVariant || !canExport,
|
|
38911
|
+
className: `px-6 py-2.5 min-h-[44px] transition-colors order-2 ${showPreview ? "limbo-btn limbo-btn-danger" : "limbo-btn limbo-btn-info"}`,
|
|
38912
|
+
"aria-label": "Generar vista previa del recorte",
|
|
38913
|
+
title: "Mostar/Ocultar vista previa del recorte",
|
|
38914
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center", children: [
|
|
38915
|
+
/* @__PURE__ */ jsx("span", { className: `icon md:mr-1 icon-search-white` }),
|
|
38916
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:block text-nowrap", children: showPreview ? "Cerrar previa" : "Vista previa" })
|
|
37726
38917
|
] })
|
|
37727
|
-
|
|
37728
|
-
|
|
37729
|
-
|
|
37730
|
-
|
|
38918
|
+
}
|
|
38919
|
+
),
|
|
38920
|
+
/* @__PURE__ */ jsx(
|
|
38921
|
+
"button",
|
|
38922
|
+
{
|
|
38923
|
+
onClick: handleDownload,
|
|
38924
|
+
disabled: creatingVariant || !canExport,
|
|
38925
|
+
className: "limbo-btn limbo-btn-primary px-6 py-2.5 min-h-[44px] order-3",
|
|
38926
|
+
"aria-label": "Descargar recorte sin guardar",
|
|
38927
|
+
title: "Descargar recorte sin guardar",
|
|
38928
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center", children: [
|
|
38929
|
+
/* @__PURE__ */ jsx("span", { className: "icon icon-download-white md:mr-1" }),
|
|
38930
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:block text-nowrap", children: "Descargar" })
|
|
38931
|
+
] })
|
|
38932
|
+
}
|
|
38933
|
+
),
|
|
38934
|
+
/* @__PURE__ */ jsx(
|
|
38935
|
+
"button",
|
|
38936
|
+
{
|
|
38937
|
+
onClick: saveCrop,
|
|
38938
|
+
disabled: creatingVariant || !cropData || !effectiveImageInfo || !canExport || !state.isReady,
|
|
38939
|
+
className: "limbo-btn limbo-btn-success px-6 py-2.5 min-h-[44px] order-4",
|
|
38940
|
+
"aria-label": "Guardar imagen recortada",
|
|
38941
|
+
title: "Guardar imagen recortada",
|
|
38942
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: creatingVariant ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38943
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:block text-nowrap icon icon-save-white md:mr-1" }),
|
|
38944
|
+
"Guardando..."
|
|
38945
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38946
|
+
/* @__PURE__ */ jsx("span", { className: "icon icon-save-white md:mr-1" }),
|
|
38947
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:block text-nowrap", children: "Guardar recorte" })
|
|
38948
|
+
] }) })
|
|
38949
|
+
}
|
|
38950
|
+
)
|
|
38951
|
+
] }) }),
|
|
38952
|
+
showConfirmModal && /* @__PURE__ */ jsx("div", { className: "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-[9999] p-4", children: /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-xl max-w-lg w-full max-h-[80vh] overflow-hidden flex flex-col", children: [
|
|
38953
|
+
/* @__PURE__ */ jsxs("div", { className: "px-6 py-4 border-b border-gray-200", children: [
|
|
38954
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-800", children: pendingAction === "save" ? "Seleccionar recortes a guardar" : "Seleccionar recortes a descargar" }),
|
|
38955
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-600 mt-1", children: [
|
|
38956
|
+
"Marca los recortes que deseas ",
|
|
38957
|
+
pendingAction === "save" ? "guardar" : "descargar"
|
|
38958
|
+
] })
|
|
38959
|
+
] }),
|
|
38960
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4 overflow-y-auto flex-1", children: /* @__PURE__ */ jsx("div", { className: "space-y-2", children: crops.map((crop, index) => /* @__PURE__ */ jsxs(
|
|
38961
|
+
"label",
|
|
38962
|
+
{
|
|
38963
|
+
className: `flex items-center gap-3 p-3 rounded border cursor-pointer transition-colors ${selectedCropsForAction.includes(index) ? "bg-blue-50 border-blue-300" : "bg-gray-50 border-gray-200 hover:bg-gray-100"} ${crop.required ? "opacity-75" : ""}`,
|
|
38964
|
+
children: [
|
|
37731
38965
|
/* @__PURE__ */ jsx(
|
|
37732
|
-
"
|
|
38966
|
+
"input",
|
|
37733
38967
|
{
|
|
37734
|
-
|
|
37735
|
-
|
|
37736
|
-
|
|
37737
|
-
|
|
37738
|
-
|
|
37739
|
-
|
|
37740
|
-
|
|
37741
|
-
|
|
37742
|
-
|
|
37743
|
-
|
|
38968
|
+
type: "checkbox",
|
|
38969
|
+
checked: selectedCropsForAction.includes(index),
|
|
38970
|
+
disabled: crop.required,
|
|
38971
|
+
onChange: (e) => {
|
|
38972
|
+
if (e.target.checked) {
|
|
38973
|
+
setSelectedCropsForAction((prev) => [...prev, index]);
|
|
38974
|
+
} else {
|
|
38975
|
+
setSelectedCropsForAction((prev) => prev.filter((i) => i !== index));
|
|
38976
|
+
}
|
|
38977
|
+
},
|
|
38978
|
+
className: "w-4 h-4 text-blue-600"
|
|
37744
38979
|
}
|
|
37745
38980
|
),
|
|
37746
|
-
/* @__PURE__ */
|
|
37747
|
-
"
|
|
37748
|
-
|
|
37749
|
-
|
|
37750
|
-
|
|
37751
|
-
|
|
37752
|
-
|
|
37753
|
-
"
|
|
37754
|
-
|
|
37755
|
-
|
|
37756
|
-
|
|
37757
|
-
"Reset selección"
|
|
37758
|
-
] }) })
|
|
37759
|
-
}
|
|
37760
|
-
)
|
|
37761
|
-
] }),
|
|
37762
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-3", children: [
|
|
37763
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 mb-2", children: "Tamaños rápidos" }),
|
|
37764
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-1", children: [
|
|
37765
|
-
/* @__PURE__ */ jsx(
|
|
37766
|
-
"button",
|
|
37767
|
-
{
|
|
37768
|
-
onClick: () => setSelectionCoverage(0.5),
|
|
37769
|
-
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37770
|
-
disabled: creatingVariant,
|
|
37771
|
-
"aria-label": "Selección 50%",
|
|
37772
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "50%" }) })
|
|
37773
|
-
}
|
|
37774
|
-
),
|
|
37775
|
-
/* @__PURE__ */ jsx(
|
|
37776
|
-
"button",
|
|
37777
|
-
{
|
|
37778
|
-
onClick: () => setSelectionCoverage(0.7),
|
|
37779
|
-
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37780
|
-
disabled: creatingVariant,
|
|
37781
|
-
"aria-label": "Selección 70%",
|
|
37782
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "70%" }) })
|
|
37783
|
-
}
|
|
37784
|
-
),
|
|
37785
|
-
/* @__PURE__ */ jsx(
|
|
37786
|
-
"button",
|
|
37787
|
-
{
|
|
37788
|
-
onClick: () => setSelectionCoverage(0.9),
|
|
37789
|
-
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37790
|
-
disabled: creatingVariant,
|
|
37791
|
-
"aria-label": "Selección 90%",
|
|
37792
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "90%" }) })
|
|
37793
|
-
}
|
|
37794
|
-
),
|
|
37795
|
-
/* @__PURE__ */ jsx(
|
|
37796
|
-
"button",
|
|
37797
|
-
{
|
|
37798
|
-
onClick: () => setSelectionCoverage(1),
|
|
37799
|
-
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37800
|
-
disabled: creatingVariant,
|
|
37801
|
-
"aria-label": "Selección completa",
|
|
37802
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "100%" }) })
|
|
37803
|
-
}
|
|
37804
|
-
)
|
|
37805
|
-
] })
|
|
37806
|
-
] })
|
|
37807
|
-
] }),
|
|
37808
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [
|
|
37809
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-700 mb-3", children: "Transformar imagen" }),
|
|
37810
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
37811
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 mb-2", children: "Mover imagen" }),
|
|
37812
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-1", children: [
|
|
37813
|
-
/* @__PURE__ */ jsx("div", {}),
|
|
37814
|
-
/* @__PURE__ */ jsx(
|
|
37815
|
-
"button",
|
|
37816
|
-
{
|
|
37817
|
-
onClick: () => move(0, -10),
|
|
37818
|
-
className: "p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37819
|
-
title: "Mover arriba",
|
|
37820
|
-
disabled: creatingVariant,
|
|
37821
|
-
"aria-label": "Mover imagen hacia arriba",
|
|
37822
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-up-blue" }) })
|
|
37823
|
-
}
|
|
37824
|
-
),
|
|
37825
|
-
/* @__PURE__ */ jsx("div", {}),
|
|
37826
|
-
/* @__PURE__ */ jsx(
|
|
37827
|
-
"button",
|
|
37828
|
-
{
|
|
37829
|
-
onClick: () => move(-10, 0),
|
|
37830
|
-
className: "p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37831
|
-
title: "Mover izquierda",
|
|
37832
|
-
disabled: creatingVariant,
|
|
37833
|
-
"aria-label": "Mover imagen hacia la izquierda",
|
|
37834
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-left-blue" }) })
|
|
37835
|
-
}
|
|
37836
|
-
),
|
|
37837
|
-
/* @__PURE__ */ jsx(
|
|
37838
|
-
"button",
|
|
37839
|
-
{
|
|
37840
|
-
onClick: centerImage,
|
|
37841
|
-
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37842
|
-
title: "Centrar y ajustar imagen",
|
|
37843
|
-
disabled: creatingVariant,
|
|
37844
|
-
"aria-label": "Centrar y ajustar imagen",
|
|
37845
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-radio-button-blue icon-md" }) })
|
|
37846
|
-
}
|
|
37847
|
-
),
|
|
37848
|
-
/* @__PURE__ */ jsx(
|
|
37849
|
-
"button",
|
|
37850
|
-
{
|
|
37851
|
-
onClick: () => move(10, 0),
|
|
37852
|
-
className: "p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37853
|
-
title: "Mover derecha",
|
|
37854
|
-
disabled: creatingVariant,
|
|
37855
|
-
"aria-label": "Mover imagen hacia la derecha",
|
|
37856
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-right-blue" }) })
|
|
37857
|
-
}
|
|
37858
|
-
),
|
|
37859
|
-
/* @__PURE__ */ jsx("div", {}),
|
|
37860
|
-
/* @__PURE__ */ jsx(
|
|
37861
|
-
"button",
|
|
37862
|
-
{
|
|
37863
|
-
onClick: () => move(0, 10),
|
|
37864
|
-
className: "p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37865
|
-
title: "Mover abajo",
|
|
37866
|
-
disabled: creatingVariant,
|
|
37867
|
-
"aria-label": "Mover imagen hacia abajo",
|
|
37868
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-down-blue" }) })
|
|
37869
|
-
}
|
|
37870
|
-
),
|
|
37871
|
-
/* @__PURE__ */ jsx("div", {})
|
|
37872
|
-
] })
|
|
37873
|
-
] }),
|
|
37874
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
37875
|
-
/* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-600 mb-2", children: [
|
|
37876
|
-
"Zoom ",
|
|
37877
|
-
zoomInfo ? zoomInfo.percentage + "%" : ""
|
|
37878
|
-
] }),
|
|
37879
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
|
|
37880
|
-
/* @__PURE__ */ jsx(
|
|
37881
|
-
"button",
|
|
37882
|
-
{
|
|
37883
|
-
onClick: () => zoom(-0.2),
|
|
37884
|
-
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37885
|
-
title: "Alejar 20%",
|
|
37886
|
-
disabled: creatingVariant,
|
|
37887
|
-
"aria-label": "Alejar imagen",
|
|
37888
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-zoom-out-blue" }) })
|
|
37889
|
-
}
|
|
37890
|
-
),
|
|
37891
|
-
/* @__PURE__ */ jsx(
|
|
37892
|
-
"button",
|
|
37893
|
-
{
|
|
37894
|
-
onClick: resetZoomOnly,
|
|
37895
|
-
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37896
|
-
title: "Restablecer zoom original",
|
|
37897
|
-
disabled: creatingVariant,
|
|
37898
|
-
"aria-label": "Restablecer el zoom para que la imagen se vea con su resolución original",
|
|
37899
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-screenshot-blue" }) })
|
|
37900
|
-
}
|
|
37901
|
-
),
|
|
37902
|
-
/* @__PURE__ */ jsx(
|
|
37903
|
-
"button",
|
|
37904
|
-
{
|
|
37905
|
-
onClick: () => zoom(0.2),
|
|
37906
|
-
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37907
|
-
title: "Acercar 20%",
|
|
37908
|
-
disabled: creatingVariant,
|
|
37909
|
-
"aria-label": "Acercar imagen",
|
|
37910
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-zoom-in-blue" }) })
|
|
37911
|
-
}
|
|
37912
|
-
)
|
|
37913
|
-
] })
|
|
37914
|
-
] }),
|
|
37915
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
37916
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 mb-2", children: "Rotación" }),
|
|
37917
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-1 *:text-brand-blue-1000 *:text-sm", children: [
|
|
37918
|
-
/* @__PURE__ */ jsx(
|
|
37919
|
-
"button",
|
|
37920
|
-
{
|
|
37921
|
-
onClick: () => rotate(-90),
|
|
37922
|
-
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37923
|
-
title: "Rotar -90°",
|
|
37924
|
-
disabled: creatingVariant,
|
|
37925
|
-
"aria-label": "Rotar imagen 90 grados a la izquierda",
|
|
37926
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-reply-blue" }) })
|
|
37927
|
-
}
|
|
37928
|
-
),
|
|
37929
|
-
/* @__PURE__ */ jsx(
|
|
37930
|
-
"button",
|
|
37931
|
-
{
|
|
37932
|
-
onClick: () => rotate(-45),
|
|
37933
|
-
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37934
|
-
title: "Rotar -45°",
|
|
37935
|
-
disabled: creatingVariant,
|
|
37936
|
-
"aria-label": "Rotar imagen 45 grados a la izquierda",
|
|
37937
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "-45°" }) })
|
|
37938
|
-
}
|
|
37939
|
-
),
|
|
37940
|
-
/* @__PURE__ */ jsx(
|
|
37941
|
-
"button",
|
|
37942
|
-
{
|
|
37943
|
-
onClick: () => rotate(45),
|
|
37944
|
-
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37945
|
-
title: "Rotar +45°",
|
|
37946
|
-
disabled: creatingVariant,
|
|
37947
|
-
"aria-label": "Rotar imagen 45 grados a la derecha",
|
|
37948
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "+45°" }) })
|
|
37949
|
-
}
|
|
37950
|
-
),
|
|
37951
|
-
/* @__PURE__ */ jsx(
|
|
37952
|
-
"button",
|
|
37953
|
-
{
|
|
37954
|
-
onClick: () => rotate(90),
|
|
37955
|
-
className: "flex-1 p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37956
|
-
title: "Rotar +90°",
|
|
37957
|
-
disabled: creatingVariant,
|
|
37958
|
-
"aria-label": "Rotar imagen 90 grados a la derecha",
|
|
37959
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-send-arrow-blue" }) })
|
|
37960
|
-
}
|
|
37961
|
-
)
|
|
37962
|
-
] })
|
|
37963
|
-
] }),
|
|
37964
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
37965
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 mb-2", children: "Voltear" }),
|
|
37966
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
|
|
37967
|
-
/* @__PURE__ */ jsx(
|
|
37968
|
-
"button",
|
|
37969
|
-
{
|
|
37970
|
-
onClick: flipHorizontal,
|
|
37971
|
-
className: `flex-1 p-2 rounded cursor-pointer transition-colors text-sm ${flipStates.horizontal ? "bg-blue-100 border border-blue-300 text-blue-800" : "bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200"}`,
|
|
37972
|
-
title: `Voltear horizontalmente ${flipStates.horizontal ? "(activo)" : ""}`,
|
|
37973
|
-
disabled: creatingVariant,
|
|
37974
|
-
"aria-label": "Voltear imagen horizontalmente",
|
|
37975
|
-
"aria-pressed": flipStates.horizontal,
|
|
37976
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-left-right-blue border border-brand-blue-1000 rounded" }) })
|
|
37977
|
-
}
|
|
37978
|
-
),
|
|
37979
|
-
/* @__PURE__ */ jsx(
|
|
37980
|
-
"button",
|
|
37981
|
-
{
|
|
37982
|
-
onClick: flipVertical,
|
|
37983
|
-
className: `flex-1 p-2 cursor-pointer rounded transition-colors text-sm ${flipStates.vertical ? "bg-blue-100 border border-blue-300 text-blue-800" : "bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200"}`,
|
|
37984
|
-
title: `Voltear verticalmente ${flipStates.vertical ? "(activo)" : ""}`,
|
|
37985
|
-
disabled: creatingVariant,
|
|
37986
|
-
"aria-label": "Voltear imagen verticalmente",
|
|
37987
|
-
"aria-pressed": flipStates.vertical,
|
|
37988
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-up-down-blue border border-brand-blue-1000 rounded" }) })
|
|
37989
|
-
}
|
|
37990
|
-
)
|
|
38981
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
38982
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
38983
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-800 truncate", children: crop.label }),
|
|
38984
|
+
crop.required && /* @__PURE__ */ jsx("span", { className: "text-xs px-1.5 py-0.5 bg-red-100 text-red-700 rounded", children: "Obligatorio" })
|
|
38985
|
+
] }),
|
|
38986
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-500", children: [
|
|
38987
|
+
crop.width,
|
|
38988
|
+
" × ",
|
|
38989
|
+
crop.height,
|
|
38990
|
+
" px"
|
|
38991
|
+
] })
|
|
37991
38992
|
] })
|
|
37992
|
-
]
|
|
37993
|
-
|
|
37994
|
-
|
|
37995
|
-
|
|
37996
|
-
|
|
37997
|
-
|
|
37998
|
-
|
|
37999
|
-
|
|
38000
|
-
|
|
38001
|
-
|
|
38002
|
-
|
|
38003
|
-
|
|
38004
|
-
|
|
38005
|
-
|
|
38006
|
-
|
|
38007
|
-
|
|
38008
|
-
|
|
38009
|
-
|
|
38010
|
-
|
|
38011
|
-
|
|
38012
|
-
|
|
38013
|
-
|
|
38993
|
+
]
|
|
38994
|
+
},
|
|
38995
|
+
crop.id
|
|
38996
|
+
)) }) }),
|
|
38997
|
+
/* @__PURE__ */ jsxs("div", { className: "px-6 py-4 border-t border-gray-200 flex gap-3 justify-end", children: [
|
|
38998
|
+
/* @__PURE__ */ jsx(
|
|
38999
|
+
"button",
|
|
39000
|
+
{
|
|
39001
|
+
onClick: () => {
|
|
39002
|
+
setShowConfirmModal(false);
|
|
39003
|
+
setPendingAction(null);
|
|
39004
|
+
setSelectedCropsForAction([]);
|
|
39005
|
+
},
|
|
39006
|
+
className: "limbo-btn limbo-btn-secondary px-4 py-2",
|
|
39007
|
+
children: "Cancelar"
|
|
39008
|
+
}
|
|
39009
|
+
),
|
|
39010
|
+
/* @__PURE__ */ jsxs(
|
|
39011
|
+
"button",
|
|
39012
|
+
{
|
|
39013
|
+
onClick: async () => {
|
|
39014
|
+
setShowConfirmModal(false);
|
|
39015
|
+
if (pendingAction === "save") {
|
|
39016
|
+
await performSaveCrop();
|
|
39017
|
+
} else {
|
|
39018
|
+
await performDownload();
|
|
39019
|
+
}
|
|
39020
|
+
setPendingAction(null);
|
|
39021
|
+
setSelectedCropsForAction([]);
|
|
39022
|
+
},
|
|
39023
|
+
disabled: selectedCropsForAction.length === 0,
|
|
39024
|
+
className: "limbo-btn limbo-btn-primary px-4 py-2 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
39025
|
+
children: [
|
|
39026
|
+
pendingAction === "save" ? "Guardar" : "Descargar",
|
|
39027
|
+
" (",
|
|
39028
|
+
selectedCropsForAction.length,
|
|
39029
|
+
")"
|
|
39030
|
+
]
|
|
39031
|
+
}
|
|
39032
|
+
)
|
|
39033
|
+
] })
|
|
39034
|
+
] }) })
|
|
38014
39035
|
] });
|
|
38015
39036
|
}
|
|
38016
39037
|
function Pagination({
|
|
@@ -38256,7 +39277,7 @@ function useImages(apiKey, prod = false, params = {}) {
|
|
|
38256
39277
|
try {
|
|
38257
39278
|
const data = await listAssets(params);
|
|
38258
39279
|
if (!isMounted) return;
|
|
38259
|
-
const result = data.result || [];
|
|
39280
|
+
const result = data.result || data.data || [];
|
|
38260
39281
|
const paginationData = data.pagination || null;
|
|
38261
39282
|
setImages(result);
|
|
38262
39283
|
setPagination(paginationData);
|
|
@@ -38320,6 +39341,18 @@ function useTokenExpiration() {
|
|
|
38320
39341
|
handleTokenExpiredClose
|
|
38321
39342
|
};
|
|
38322
39343
|
}
|
|
39344
|
+
function useDebounce(value, delay = 500) {
|
|
39345
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
39346
|
+
useEffect(() => {
|
|
39347
|
+
const handler = setTimeout(() => {
|
|
39348
|
+
setDebouncedValue(value);
|
|
39349
|
+
}, delay);
|
|
39350
|
+
return () => {
|
|
39351
|
+
clearTimeout(handler);
|
|
39352
|
+
};
|
|
39353
|
+
}, [value, delay]);
|
|
39354
|
+
return debouncedValue;
|
|
39355
|
+
}
|
|
38323
39356
|
function App({
|
|
38324
39357
|
apiKey,
|
|
38325
39358
|
prod = false,
|
|
@@ -38352,6 +39385,14 @@ function App({
|
|
|
38352
39385
|
sessionStorage.removeItem("limbo_portals_images");
|
|
38353
39386
|
sessionStorage.removeItem("limbo_portals_portalResults");
|
|
38354
39387
|
sessionStorage.removeItem("limbo_portals_paginationInfo");
|
|
39388
|
+
const [galleryFilters, setGalleryFilters] = useState({
|
|
39389
|
+
name: "",
|
|
39390
|
+
uploadedBy: "",
|
|
39391
|
+
dateFrom: "",
|
|
39392
|
+
dateTo: ""
|
|
39393
|
+
});
|
|
39394
|
+
const debouncedName = useDebounce(galleryFilters.name, 500);
|
|
39395
|
+
const debouncedUploadedBy = useDebounce(galleryFilters.uploadedBy, 500);
|
|
38355
39396
|
const getFilteredFeatures = () => {
|
|
38356
39397
|
switch (modeUI) {
|
|
38357
39398
|
case "gallery-only":
|
|
@@ -38395,6 +39436,14 @@ function App({
|
|
|
38395
39436
|
error: deleteError,
|
|
38396
39437
|
reset: resetDelete
|
|
38397
39438
|
} = useDeleteImage();
|
|
39439
|
+
const apiParams = {
|
|
39440
|
+
limit: itemsPerPage,
|
|
39441
|
+
page: currentPage,
|
|
39442
|
+
...debouncedName && { name: debouncedName },
|
|
39443
|
+
...debouncedUploadedBy && { uploadedBy: debouncedUploadedBy },
|
|
39444
|
+
...galleryFilters.dateFrom && { dateFrom: galleryFilters.dateFrom },
|
|
39445
|
+
...galleryFilters.dateTo && { dateTo: galleryFilters.dateTo }
|
|
39446
|
+
};
|
|
38398
39447
|
const {
|
|
38399
39448
|
images,
|
|
38400
39449
|
loading: loadingImages,
|
|
@@ -38402,7 +39451,7 @@ function App({
|
|
|
38402
39451
|
pagination,
|
|
38403
39452
|
invalidateCache,
|
|
38404
39453
|
setImages
|
|
38405
|
-
} = useImages(apiKey, prod,
|
|
39454
|
+
} = useImages(apiKey, prod, apiParams);
|
|
38406
39455
|
const { refreshVariants } = useImageVariants();
|
|
38407
39456
|
const handleVariantCreated = (assetId, variantData) => {
|
|
38408
39457
|
refreshVariants(assetId);
|
|
@@ -38446,7 +39495,7 @@ function App({
|
|
|
38446
39495
|
}
|
|
38447
39496
|
};
|
|
38448
39497
|
const handleDelete = async (imageId) => {
|
|
38449
|
-
if (!confirm("¿Estás seguro de que
|
|
39498
|
+
if (!confirm("¿Estás seguro de que deseas eliminar esta imagen? Esta acción también eliminará todos sus recortes.")) {
|
|
38450
39499
|
return;
|
|
38451
39500
|
}
|
|
38452
39501
|
const success = await deleteImg(imageId);
|
|
@@ -38484,8 +39533,148 @@ function App({
|
|
|
38484
39533
|
if (tabId !== "upload") resetUpload();
|
|
38485
39534
|
if (tabId !== "gallery") resetDelete();
|
|
38486
39535
|
};
|
|
38487
|
-
|
|
38488
|
-
|
|
39536
|
+
const determineScenario = () => {
|
|
39537
|
+
if (modeUI === "crop-only" || activeFeatures.length === 1 && activeFeatures[0] === "cropper") {
|
|
39538
|
+
return "crop-only";
|
|
39539
|
+
}
|
|
39540
|
+
if (activeFeatures.includes("gallery")) {
|
|
39541
|
+
return "with-gallery";
|
|
39542
|
+
}
|
|
39543
|
+
if (activeFeatures.includes("upload") && !activeFeatures.includes("gallery")) {
|
|
39544
|
+
return "upload-only";
|
|
39545
|
+
}
|
|
39546
|
+
return "with-gallery";
|
|
39547
|
+
};
|
|
39548
|
+
const handleCropSave = (result) => {
|
|
39549
|
+
const scenario = determineScenario();
|
|
39550
|
+
const globalConfig2 = window.limboCore?.config?.getGlobal() || {};
|
|
39551
|
+
const mode = globalConfig2.mode || "embed";
|
|
39552
|
+
const autoHide = globalConfig2.autoHideOnComplete || false;
|
|
39553
|
+
const crops = Array.isArray(result) ? result : [result];
|
|
39554
|
+
if (scenario === "with-gallery") {
|
|
39555
|
+
invalidateCache();
|
|
39556
|
+
}
|
|
39557
|
+
if (callbacks.onCropsSaved) {
|
|
39558
|
+
callbacks.onCropsSaved({
|
|
39559
|
+
crops,
|
|
39560
|
+
assetId: selectedImage?.id,
|
|
39561
|
+
instanceId
|
|
39562
|
+
});
|
|
39563
|
+
}
|
|
39564
|
+
if (window.limboCore?.events) {
|
|
39565
|
+
window.limboCore.events.emit("cropsSaved", {
|
|
39566
|
+
crops,
|
|
39567
|
+
assetId: selectedImage?.id,
|
|
39568
|
+
instanceId
|
|
39569
|
+
});
|
|
39570
|
+
}
|
|
39571
|
+
switch (scenario) {
|
|
39572
|
+
case "with-gallery":
|
|
39573
|
+
setSelectedImage(null);
|
|
39574
|
+
setActiveTab("gallery");
|
|
39575
|
+
break;
|
|
39576
|
+
case "upload-only":
|
|
39577
|
+
if (mode === "modal") {
|
|
39578
|
+
window.limboCore?.modals?.closeAllModals();
|
|
39579
|
+
} else {
|
|
39580
|
+
setSelectedImage(null);
|
|
39581
|
+
setActiveTab("upload");
|
|
39582
|
+
}
|
|
39583
|
+
break;
|
|
39584
|
+
case "crop-only":
|
|
39585
|
+
if (mode === "modal") {
|
|
39586
|
+
if (callbacks.onCropperComplete) {
|
|
39587
|
+
callbacks.onCropperComplete({
|
|
39588
|
+
crops,
|
|
39589
|
+
instanceId
|
|
39590
|
+
});
|
|
39591
|
+
}
|
|
39592
|
+
if (window.limboCore?.events) {
|
|
39593
|
+
window.limboCore.events.emit("cropperComplete", {
|
|
39594
|
+
crops,
|
|
39595
|
+
instanceId
|
|
39596
|
+
});
|
|
39597
|
+
}
|
|
39598
|
+
window.limboCore?.modals?.closeAllModals();
|
|
39599
|
+
} else {
|
|
39600
|
+
if (callbacks.onCropperComplete) {
|
|
39601
|
+
callbacks.onCropperComplete({
|
|
39602
|
+
crops,
|
|
39603
|
+
instanceId
|
|
39604
|
+
});
|
|
39605
|
+
}
|
|
39606
|
+
if (window.limboCore?.events) {
|
|
39607
|
+
window.limboCore.events.emit("cropperComplete", {
|
|
39608
|
+
crops,
|
|
39609
|
+
instanceId
|
|
39610
|
+
});
|
|
39611
|
+
}
|
|
39612
|
+
if (autoHide) {
|
|
39613
|
+
const container = document.querySelector(`#limbo-instance-${instanceId}`);
|
|
39614
|
+
if (container) container.style.display = "none";
|
|
39615
|
+
}
|
|
39616
|
+
}
|
|
39617
|
+
break;
|
|
39618
|
+
}
|
|
39619
|
+
};
|
|
39620
|
+
const handleCropCancel = () => {
|
|
39621
|
+
const scenario = determineScenario();
|
|
39622
|
+
const globalConfig2 = window.limboCore?.config?.getGlobal() || {};
|
|
39623
|
+
const mode = globalConfig2.mode || "embed";
|
|
39624
|
+
if (callbacks.onCropperCancelled) {
|
|
39625
|
+
callbacks.onCropperCancelled({
|
|
39626
|
+
assetId: selectedImage?.id,
|
|
39627
|
+
instanceId
|
|
39628
|
+
});
|
|
39629
|
+
}
|
|
39630
|
+
if (window.limboCore?.events) {
|
|
39631
|
+
window.limboCore.events.emit("cropperCancelled", {
|
|
39632
|
+
assetId: selectedImage?.id,
|
|
39633
|
+
instanceId
|
|
39634
|
+
});
|
|
39635
|
+
}
|
|
39636
|
+
switch (scenario) {
|
|
39637
|
+
case "with-gallery":
|
|
39638
|
+
setSelectedImage(null);
|
|
39639
|
+
setActiveTab("gallery");
|
|
39640
|
+
break;
|
|
39641
|
+
case "upload-only":
|
|
39642
|
+
if (mode === "modal") {
|
|
39643
|
+
window.limboCore?.modals?.closeAllModals();
|
|
39644
|
+
} else {
|
|
39645
|
+
setSelectedImage(null);
|
|
39646
|
+
setActiveTab("upload");
|
|
39647
|
+
}
|
|
39648
|
+
break;
|
|
39649
|
+
case "crop-only":
|
|
39650
|
+
if (mode === "modal") {
|
|
39651
|
+
window.limboCore?.modals?.closeAllModals();
|
|
39652
|
+
} else {
|
|
39653
|
+
if (window.limboCore?.events) {
|
|
39654
|
+
window.limboCore.events.emit("cropperClosed", {
|
|
39655
|
+
instanceId,
|
|
39656
|
+
reason: "cancelled"
|
|
39657
|
+
});
|
|
39658
|
+
}
|
|
39659
|
+
}
|
|
39660
|
+
break;
|
|
39661
|
+
}
|
|
39662
|
+
};
|
|
39663
|
+
const handleCropError = (error) => {
|
|
39664
|
+
if (callbacks.onCropperError) {
|
|
39665
|
+
callbacks.onCropperError(error, instanceId);
|
|
39666
|
+
}
|
|
39667
|
+
if (window.limboCore?.events) {
|
|
39668
|
+
window.limboCore.events.emit("cropperError", {
|
|
39669
|
+
error,
|
|
39670
|
+
assetId: selectedImage?.id,
|
|
39671
|
+
instanceId
|
|
39672
|
+
});
|
|
39673
|
+
}
|
|
39674
|
+
console.error("Cropper error:", error);
|
|
39675
|
+
};
|
|
39676
|
+
return /* @__PURE__ */ jsxs("div", { className: "limbo-card-parent max-w-7xl mx-auto my-8 p-6 shadow-xs w-full", children: [
|
|
39677
|
+
ui.showTabs && activeTab != "cropper" && /* @__PURE__ */ jsx(Tabs, { tabs, active: activeTab, onChange: handleTabChange }),
|
|
38489
39678
|
imagesError && /* @__PURE__ */ jsxs("div", { className: "alert alert-danger", children: [
|
|
38490
39679
|
"Error al cargar imágenes: ",
|
|
38491
39680
|
imagesError
|
|
@@ -38499,8 +39688,6 @@ function App({
|
|
|
38499
39688
|
/* @__PURE__ */ jsx(
|
|
38500
39689
|
Gallery,
|
|
38501
39690
|
{
|
|
38502
|
-
apiKey,
|
|
38503
|
-
prod,
|
|
38504
39691
|
onSelect: handleImageSelect,
|
|
38505
39692
|
onCrop: handleImageCrop,
|
|
38506
39693
|
onDelete: isActionAllowed("delete") ? handleDelete : null,
|
|
@@ -38508,6 +39695,13 @@ function App({
|
|
|
38508
39695
|
images,
|
|
38509
39696
|
loading: loadingImages,
|
|
38510
39697
|
error: imagesError,
|
|
39698
|
+
filters: galleryFilters,
|
|
39699
|
+
onFiltersChange: (newFilters) => {
|
|
39700
|
+
setGalleryFilters(newFilters);
|
|
39701
|
+
setCurrentPage(1);
|
|
39702
|
+
},
|
|
39703
|
+
filterConfig: ui.galleryFilters || {},
|
|
39704
|
+
loadingConfig: ui.galleryLoading || {},
|
|
38511
39705
|
allowedActions: {
|
|
38512
39706
|
select: isActionAllowed("select"),
|
|
38513
39707
|
download: isActionAllowed("download"),
|
|
@@ -38551,16 +39745,10 @@ function App({
|
|
|
38551
39745
|
CropperView,
|
|
38552
39746
|
{
|
|
38553
39747
|
image: selectedImage,
|
|
38554
|
-
onSave:
|
|
38555
|
-
|
|
38556
|
-
setSelectedImage(null);
|
|
38557
|
-
setActiveTab("gallery");
|
|
38558
|
-
},
|
|
38559
|
-
onCancel: () => {
|
|
38560
|
-
setSelectedImage(null);
|
|
38561
|
-
setActiveTab("gallery");
|
|
38562
|
-
},
|
|
39748
|
+
onSave: handleCropSave,
|
|
39749
|
+
onCancel: handleCropCancel,
|
|
38563
39750
|
onDelete: () => handleDelete(selectedImage?.id),
|
|
39751
|
+
onError: handleCropError,
|
|
38564
39752
|
deleting,
|
|
38565
39753
|
onVariantCreated: handleVariantCreated
|
|
38566
39754
|
}
|
|
@@ -38865,7 +40053,12 @@ class LimboInstance {
|
|
|
38865
40053
|
id: `limbo-component-container-${this.id}`,
|
|
38866
40054
|
className: "limbo-instance limbo-component-container-wrapper py-3",
|
|
38867
40055
|
"data-limbo-id": this.id,
|
|
38868
|
-
"data-limbo-mode": this.config.mode
|
|
40056
|
+
"data-limbo-mode": this.config.mode,
|
|
40057
|
+
"data-limbo-version": "2.0",
|
|
40058
|
+
"data-limbo-isolated": "true",
|
|
40059
|
+
// Agregar aria-label para accesibilidad
|
|
40060
|
+
"aria-label": "Limbo Image Manager",
|
|
40061
|
+
"role": "region"
|
|
38869
40062
|
},
|
|
38870
40063
|
React.createElement(App, {
|
|
38871
40064
|
apiKey: this.config.apiKey || null,
|
|
@@ -41885,12 +43078,294 @@ class LimboCore {
|
|
|
41885
43078
|
});
|
|
41886
43079
|
modalInstance.open();
|
|
41887
43080
|
}
|
|
43081
|
+
// ========================================
|
|
43082
|
+
// MÉTODOS PREFAB - CASOS DE USO COMUNES
|
|
43083
|
+
// ========================================
|
|
43084
|
+
/**
|
|
43085
|
+
* 🎨 Abrir galería de imágenes en modal
|
|
43086
|
+
* Caso de uso: Selector rápido de imágenes existentes
|
|
43087
|
+
*
|
|
43088
|
+
* @param {Object} options - Opciones de configuración
|
|
43089
|
+
* @param {Function} options.onSelect - Callback cuando se selecciona imagen
|
|
43090
|
+
* @param {Object} options.filters - Filtros pre-aplicados
|
|
43091
|
+
* @returns {Object} Instancia del modal
|
|
43092
|
+
*
|
|
43093
|
+
* @example
|
|
43094
|
+
* Limbo.openGallery({
|
|
43095
|
+
* onSelect: (image) => console.log('Imagen seleccionada:', image)
|
|
43096
|
+
* });
|
|
43097
|
+
*/
|
|
43098
|
+
openGallery(options = {}) {
|
|
43099
|
+
const instance = this.create({
|
|
43100
|
+
mode: "modal",
|
|
43101
|
+
modeUI: "gallery-only",
|
|
43102
|
+
features: ["gallery"],
|
|
43103
|
+
autoDestroy: true,
|
|
43104
|
+
modal: {
|
|
43105
|
+
title: options.title || "Seleccionar Imagen",
|
|
43106
|
+
size: options.size || "large"
|
|
43107
|
+
},
|
|
43108
|
+
callbacks: {
|
|
43109
|
+
onSelect: (imageData) => {
|
|
43110
|
+
options.onSelect?.(imageData);
|
|
43111
|
+
if (options.autoClose !== false) {
|
|
43112
|
+
instance.close();
|
|
43113
|
+
}
|
|
43114
|
+
}
|
|
43115
|
+
},
|
|
43116
|
+
...options
|
|
43117
|
+
});
|
|
43118
|
+
instance.open();
|
|
43119
|
+
return instance;
|
|
43120
|
+
}
|
|
43121
|
+
/**
|
|
43122
|
+
* 📤 Abrir uploader en modal
|
|
43123
|
+
* Caso de uso: Subida rápida de nueva imagen
|
|
43124
|
+
*
|
|
43125
|
+
* @param {Object} options - Opciones de configuración
|
|
43126
|
+
* @param {Function} options.onUpload - Callback cuando se sube imagen
|
|
43127
|
+
* @param {Boolean} options.redirectToGallery - Si true, muestra galería tras subir
|
|
43128
|
+
* @returns {Object} Instancia del modal
|
|
43129
|
+
*
|
|
43130
|
+
* @example
|
|
43131
|
+
* Limbo.openUploader({
|
|
43132
|
+
* onUpload: (image) => console.log('Imagen subida:', image),
|
|
43133
|
+
* redirectToGallery: false
|
|
43134
|
+
* });
|
|
43135
|
+
*/
|
|
43136
|
+
openUploader(options = {}) {
|
|
43137
|
+
const features = options.redirectToGallery !== false ? ["upload", "gallery"] : ["upload"];
|
|
43138
|
+
const instance = this.create({
|
|
43139
|
+
mode: "modal",
|
|
43140
|
+
modeUI: options.redirectToGallery !== false ? "full" : "upload-only",
|
|
43141
|
+
features,
|
|
43142
|
+
autoDestroy: true,
|
|
43143
|
+
modal: {
|
|
43144
|
+
title: options.title || "Subir Imagen",
|
|
43145
|
+
size: options.size || "medium"
|
|
43146
|
+
},
|
|
43147
|
+
callbacks: {
|
|
43148
|
+
onUpload: (imageData) => {
|
|
43149
|
+
options.onUpload?.(imageData);
|
|
43150
|
+
if (options.autoClose !== false && !options.redirectToGallery) {
|
|
43151
|
+
instance.close();
|
|
43152
|
+
}
|
|
43153
|
+
}
|
|
43154
|
+
},
|
|
43155
|
+
...options
|
|
43156
|
+
});
|
|
43157
|
+
instance.open();
|
|
43158
|
+
return instance;
|
|
43159
|
+
}
|
|
43160
|
+
/**
|
|
43161
|
+
* ✂️ Abrir cropper standalone con imagen externa
|
|
43162
|
+
* Caso de uso: Recortar una imagen específica sin galería
|
|
43163
|
+
*
|
|
43164
|
+
* @param {String} imageUrl - URL de la imagen a recortar
|
|
43165
|
+
* @param {Object} options - Opciones de configuración
|
|
43166
|
+
* @param {Array} options.mandatoryCrops - Recortes obligatorios
|
|
43167
|
+
* @param {Function} options.onComplete - Callback cuando se completan los recortes
|
|
43168
|
+
* @param {Function} options.onCancelled - Callback cuando se cancela
|
|
43169
|
+
* @returns {Object} Instancia del modal
|
|
43170
|
+
*
|
|
43171
|
+
* @example
|
|
43172
|
+
* Limbo.openCropper('https://example.com/image.jpg', {
|
|
43173
|
+
* mandatoryCrops: [
|
|
43174
|
+
* { label: 'Thumbnail', width: 300, height: 300, required: true },
|
|
43175
|
+
* { label: 'Header', width: 1920, height: 400, required: true }
|
|
43176
|
+
* ],
|
|
43177
|
+
* onComplete: (crops) => console.log('Recortes:', crops),
|
|
43178
|
+
* onCancelled: () => console.log('Cancelado')
|
|
43179
|
+
* });
|
|
43180
|
+
*/
|
|
43181
|
+
openCropper(imageUrl, options = {}) {
|
|
43182
|
+
if (!imageUrl) {
|
|
43183
|
+
throw new Error("Limbo.openCropper: imageUrl es requerido");
|
|
43184
|
+
}
|
|
43185
|
+
const imageObject = {
|
|
43186
|
+
url: imageUrl,
|
|
43187
|
+
filename: options.filename || "image.jpg",
|
|
43188
|
+
width: options.width || 1920,
|
|
43189
|
+
height: options.height || 1080,
|
|
43190
|
+
mime_type: options.mimeType || "image/jpeg",
|
|
43191
|
+
id: options.assetId || `external-${Date.now()}`
|
|
43192
|
+
};
|
|
43193
|
+
const instance = this.create({
|
|
43194
|
+
mode: "modal",
|
|
43195
|
+
modeUI: "crop-only",
|
|
43196
|
+
features: ["cropper"],
|
|
43197
|
+
autoDestroy: true,
|
|
43198
|
+
modal: {
|
|
43199
|
+
title: options.title || "Recortar Imagen",
|
|
43200
|
+
size: "xlarge"
|
|
43201
|
+
},
|
|
43202
|
+
cropper: {
|
|
43203
|
+
mandatoryCrops: options.mandatoryCrops || [],
|
|
43204
|
+
allowCustomCrops: options.allowCustomCrops !== false,
|
|
43205
|
+
enforceRequiredCrops: options.enforceRequiredCrops !== false
|
|
43206
|
+
},
|
|
43207
|
+
callbacks: {
|
|
43208
|
+
onCropperComplete: (data) => {
|
|
43209
|
+
options.onComplete?.(data);
|
|
43210
|
+
if (options.autoClose !== false) {
|
|
43211
|
+
instance.close();
|
|
43212
|
+
}
|
|
43213
|
+
},
|
|
43214
|
+
onCropperCancelled: (data) => {
|
|
43215
|
+
options.onCancelled?.(data);
|
|
43216
|
+
if (options.autoClose !== false) {
|
|
43217
|
+
instance.close();
|
|
43218
|
+
}
|
|
43219
|
+
},
|
|
43220
|
+
onCropperError: (error) => {
|
|
43221
|
+
options.onError?.(error);
|
|
43222
|
+
}
|
|
43223
|
+
},
|
|
43224
|
+
// Pasar imagen al componente
|
|
43225
|
+
_externalImage: imageObject,
|
|
43226
|
+
...options
|
|
43227
|
+
});
|
|
43228
|
+
instance.open();
|
|
43229
|
+
return instance;
|
|
43230
|
+
}
|
|
43231
|
+
/**
|
|
43232
|
+
* 🖼️ Crear galería embebida en un contenedor
|
|
43233
|
+
* Caso de uso: Galería permanente en una página
|
|
43234
|
+
*
|
|
43235
|
+
* @param {String|HTMLElement} container - Selector o elemento del contenedor
|
|
43236
|
+
* @param {Object} options - Opciones de configuración
|
|
43237
|
+
* @returns {Object} Instancia del componente
|
|
43238
|
+
*
|
|
43239
|
+
* @example
|
|
43240
|
+
* Limbo.createInlineGallery('#gallery-container', {
|
|
43241
|
+
* onSelect: (image) => console.log('Seleccionada:', image)
|
|
43242
|
+
* });
|
|
43243
|
+
*/
|
|
43244
|
+
createInlineGallery(container, options = {}) {
|
|
43245
|
+
return this.create({
|
|
43246
|
+
container,
|
|
43247
|
+
mode: "embed",
|
|
43248
|
+
modeUI: "gallery-only",
|
|
43249
|
+
features: ["gallery"],
|
|
43250
|
+
callbacks: {
|
|
43251
|
+
onSelect: options.onSelect,
|
|
43252
|
+
onDelete: options.onDelete
|
|
43253
|
+
},
|
|
43254
|
+
...options
|
|
43255
|
+
});
|
|
43256
|
+
}
|
|
43257
|
+
/**
|
|
43258
|
+
* 📤 Crear uploader embebido en un contenedor
|
|
43259
|
+
* Caso de uso: Formulario de subida permanente
|
|
43260
|
+
*
|
|
43261
|
+
* @param {String|HTMLElement} container - Selector o elemento del contenedor
|
|
43262
|
+
* @param {Object} options - Opciones de configuración
|
|
43263
|
+
* @returns {Object} Instancia del componente
|
|
43264
|
+
*
|
|
43265
|
+
* @example
|
|
43266
|
+
* Limbo.createInlineUploader('#upload-container', {
|
|
43267
|
+
* onUpload: (image) => console.log('Subida:', image)
|
|
43268
|
+
* });
|
|
43269
|
+
*/
|
|
43270
|
+
createInlineUploader(container, options = {}) {
|
|
43271
|
+
return this.create({
|
|
43272
|
+
container,
|
|
43273
|
+
mode: "embed",
|
|
43274
|
+
modeUI: "upload-only",
|
|
43275
|
+
features: ["upload"],
|
|
43276
|
+
callbacks: {
|
|
43277
|
+
onUpload: options.onUpload
|
|
43278
|
+
},
|
|
43279
|
+
...options
|
|
43280
|
+
});
|
|
43281
|
+
}
|
|
43282
|
+
/**
|
|
43283
|
+
* ✂️ Crear cropper embebido con imagen externa
|
|
43284
|
+
* Caso de uso: Editor de recortes embebido en página
|
|
43285
|
+
*
|
|
43286
|
+
* @param {String|HTMLElement} container - Selector o elemento del contenedor
|
|
43287
|
+
* @param {String} imageUrl - URL de la imagen a recortar
|
|
43288
|
+
* @param {Object} options - Opciones de configuración
|
|
43289
|
+
* @returns {Object} Instancia del componente
|
|
43290
|
+
*
|
|
43291
|
+
* @example
|
|
43292
|
+
* Limbo.createStandaloneCropper('#cropper-container', 'https://example.com/image.jpg', {
|
|
43293
|
+
* mandatoryCrops: [{ label: 'Avatar', width: 200, height: 200, required: true }],
|
|
43294
|
+
* onComplete: (crops) => console.log('Recortes completados:', crops),
|
|
43295
|
+
* autoHideOnComplete: true
|
|
43296
|
+
* });
|
|
43297
|
+
*/
|
|
43298
|
+
createStandaloneCropper(container, imageUrl, options = {}) {
|
|
43299
|
+
if (!container) {
|
|
43300
|
+
throw new Error("Limbo.createStandaloneCropper: container es requerido");
|
|
43301
|
+
}
|
|
43302
|
+
if (!imageUrl) {
|
|
43303
|
+
throw new Error("Limbo.createStandaloneCropper: imageUrl es requerido");
|
|
43304
|
+
}
|
|
43305
|
+
const imageObject = {
|
|
43306
|
+
url: imageUrl,
|
|
43307
|
+
filename: options.filename || "image.jpg",
|
|
43308
|
+
width: options.width || 1920,
|
|
43309
|
+
height: options.height || 1080,
|
|
43310
|
+
mime_type: options.mimeType || "image/jpeg",
|
|
43311
|
+
id: options.assetId || `external-${Date.now()}`
|
|
43312
|
+
};
|
|
43313
|
+
return this.create({
|
|
43314
|
+
container,
|
|
43315
|
+
mode: "embed",
|
|
43316
|
+
modeUI: "crop-only",
|
|
43317
|
+
features: ["cropper"],
|
|
43318
|
+
autoHideOnComplete: options.autoHideOnComplete !== false,
|
|
43319
|
+
cropper: {
|
|
43320
|
+
mandatoryCrops: options.mandatoryCrops || [],
|
|
43321
|
+
allowCustomCrops: options.allowCustomCrops !== false,
|
|
43322
|
+
enforceRequiredCrops: options.enforceRequiredCrops !== false
|
|
43323
|
+
},
|
|
43324
|
+
callbacks: {
|
|
43325
|
+
onCropperComplete: options.onComplete,
|
|
43326
|
+
onCropperCancelled: options.onCancelled,
|
|
43327
|
+
onCropperError: options.onError
|
|
43328
|
+
},
|
|
43329
|
+
// Pasar imagen al componente
|
|
43330
|
+
_externalImage: imageObject,
|
|
43331
|
+
...options
|
|
43332
|
+
});
|
|
43333
|
+
}
|
|
43334
|
+
/**
|
|
43335
|
+
* 🎯 Crear selector completo (galería + uploader + cropper)
|
|
43336
|
+
* Caso de uso: Selector completo con todas las funcionalidades
|
|
43337
|
+
*
|
|
43338
|
+
* @param {String|HTMLElement} container - Selector o elemento del contenedor
|
|
43339
|
+
* @param {Object} options - Opciones de configuración
|
|
43340
|
+
* @returns {Object} Instancia del componente
|
|
43341
|
+
*
|
|
43342
|
+
* @example
|
|
43343
|
+
* Limbo.createFullSelector('#selector', {
|
|
43344
|
+
* onSelect: (image) => document.getElementById('preview').src = image.url,
|
|
43345
|
+
* onUpload: (image) => console.log('Nueva imagen:', image)
|
|
43346
|
+
* });
|
|
43347
|
+
*/
|
|
43348
|
+
createFullSelector(container, options = {}) {
|
|
43349
|
+
return this.create({
|
|
43350
|
+
container,
|
|
43351
|
+
mode: options.mode || "embed",
|
|
43352
|
+
modeUI: "full",
|
|
43353
|
+
features: ["gallery", "upload", "cropper"],
|
|
43354
|
+
callbacks: {
|
|
43355
|
+
onSelect: options.onSelect,
|
|
43356
|
+
onUpload: options.onUpload,
|
|
43357
|
+
onDelete: options.onDelete,
|
|
43358
|
+
onCropsSaved: options.onCropsSaved
|
|
43359
|
+
},
|
|
43360
|
+
...options
|
|
43361
|
+
});
|
|
43362
|
+
}
|
|
41888
43363
|
}
|
|
41889
43364
|
const Limbo = new LimboCore();
|
|
41890
43365
|
if (typeof window !== "undefined") {
|
|
41891
43366
|
window.Limbo = Limbo;
|
|
41892
43367
|
}
|
|
41893
|
-
const PUBLIC_KEY = "
|
|
43368
|
+
const PUBLIC_KEY = "pk_e464fd744106b7a8d63d453c4bd02582";
|
|
41894
43369
|
if (typeof window !== "undefined" && document.querySelector("#root")) {
|
|
41895
43370
|
Limbo.configure({
|
|
41896
43371
|
prod: false,
|