limbo-component 1.6.7 → 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/dist/limbo.cjs.js +5 -5
- package/dist/limbo.cjs.map +1 -1
- package/dist/limbo.css +1 -1
- package/dist/limbo.es.js +2122 -687
- 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/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 = {};
|
|
@@ -31017,37 +31260,33 @@ function ImageVariantsModal({
|
|
|
31017
31260
|
parent_asset_id: image.id,
|
|
31018
31261
|
variant_info: variant
|
|
31019
31262
|
};
|
|
31020
|
-
accessibilityManager?.announce(`
|
|
31263
|
+
accessibilityManager?.announce(`Recorte seleccionado: ${variant.name}`);
|
|
31021
31264
|
onSelect?.(variantAsImage);
|
|
31022
31265
|
onClose?.();
|
|
31023
31266
|
};
|
|
31024
31267
|
const handleCopyVariantUrl = async (variant) => {
|
|
31025
31268
|
try {
|
|
31026
31269
|
await navigator.clipboard.writeText(variant.url);
|
|
31027
|
-
accessibilityManager?.announce(`URL de
|
|
31270
|
+
accessibilityManager?.announce(`URL de recorte ${variant.name} copiada`);
|
|
31028
31271
|
} catch (err) {
|
|
31029
31272
|
console.error("Error copying variant URL:", err);
|
|
31030
|
-
accessibilityManager?.announceError("Error al copiar URL de
|
|
31273
|
+
accessibilityManager?.announceError("Error al copiar URL de recorte");
|
|
31031
31274
|
}
|
|
31032
31275
|
};
|
|
31033
|
-
const handleDownloadVariant = (variant) => {
|
|
31034
|
-
|
|
31035
|
-
|
|
31036
|
-
|
|
31037
|
-
|
|
31038
|
-
|
|
31039
|
-
|
|
31040
|
-
|
|
31041
|
-
|
|
31042
|
-
|
|
31043
|
-
window.URL.revokeObjectURL(url);
|
|
31044
|
-
document.body.removeChild(a);
|
|
31045
|
-
}, 100);
|
|
31046
|
-
});
|
|
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
|
+
);
|
|
31047
31286
|
};
|
|
31048
31287
|
const handleViewVariant = (variant) => {
|
|
31049
31288
|
accessibilityManager?.announce(
|
|
31050
|
-
`Abriendo
|
|
31289
|
+
`Abriendo recorte ${variant.name} en nueva pestaña`
|
|
31051
31290
|
);
|
|
31052
31291
|
window.open(variant.url, "_blank");
|
|
31053
31292
|
};
|
|
@@ -31066,26 +31305,21 @@ function ImageVariantsModal({
|
|
|
31066
31305
|
accessibilityManager?.announceError("Error al copiar URL");
|
|
31067
31306
|
}
|
|
31068
31307
|
};
|
|
31069
|
-
const handleDownloadOriginal = () => {
|
|
31070
|
-
|
|
31071
|
-
|
|
31072
|
-
|
|
31073
|
-
|
|
31074
|
-
|
|
31075
|
-
|
|
31076
|
-
|
|
31077
|
-
|
|
31078
|
-
|
|
31079
|
-
setTimeout(() => {
|
|
31080
|
-
window.URL.revokeObjectURL(url);
|
|
31081
|
-
document.body.removeChild(a);
|
|
31082
|
-
}, 100);
|
|
31083
|
-
});
|
|
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
|
+
}
|
|
31317
|
+
);
|
|
31084
31318
|
};
|
|
31085
31319
|
const handleDeleteOriginal = async () => {
|
|
31086
31320
|
if (!onDelete) return;
|
|
31087
31321
|
const confirmed = window.confirm(
|
|
31088
|
-
`¿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.`
|
|
31089
31323
|
);
|
|
31090
31324
|
if (confirmed) {
|
|
31091
31325
|
accessibilityManager?.announce(`Eliminando imagen ${image.filename}`);
|
|
@@ -31103,27 +31337,27 @@ function ImageVariantsModal({
|
|
|
31103
31337
|
};
|
|
31104
31338
|
const handleDeleteVariant = async (variant) => {
|
|
31105
31339
|
const confirmed = window.confirm(
|
|
31106
|
-
`¿Estás seguro de que deseas eliminar
|
|
31340
|
+
`¿Estás seguro de que deseas eliminar el recorte "${variant.name || variant.filename}"?`
|
|
31107
31341
|
);
|
|
31108
31342
|
if (confirmed) {
|
|
31109
31343
|
accessibilityManager?.announce(
|
|
31110
|
-
`Eliminando
|
|
31344
|
+
`Eliminando recorte ${variant.name || variant.filename}`
|
|
31111
31345
|
);
|
|
31112
31346
|
const result = await removeVariant(image.id, variant.id);
|
|
31113
31347
|
if (result.success) {
|
|
31114
|
-
setDeleteMessage("
|
|
31348
|
+
setDeleteMessage("Recorte eliminado correctamente");
|
|
31115
31349
|
setDeleteMessageType("success");
|
|
31116
|
-
accessibilityManager?.announce(`
|
|
31350
|
+
accessibilityManager?.announce(`Recorte eliminado correctamente`);
|
|
31117
31351
|
onVariantDeleted?.();
|
|
31118
31352
|
setTimeout(() => {
|
|
31119
31353
|
setDeleteMessage(null);
|
|
31120
31354
|
setDeleteMessageType(null);
|
|
31121
31355
|
}, 3e3);
|
|
31122
31356
|
} else {
|
|
31123
|
-
setDeleteMessage(`Error al eliminar
|
|
31357
|
+
setDeleteMessage(`Error al eliminar recorte: ${result.error}`);
|
|
31124
31358
|
setDeleteMessageType("error");
|
|
31125
31359
|
accessibilityManager?.announceError(
|
|
31126
|
-
`Error al eliminar
|
|
31360
|
+
`Error al eliminar recorte: ${result.error}`
|
|
31127
31361
|
);
|
|
31128
31362
|
setTimeout(() => {
|
|
31129
31363
|
setDeleteMessage(null);
|
|
@@ -31148,7 +31382,7 @@ function ImageVariantsModal({
|
|
|
31148
31382
|
children: [
|
|
31149
31383
|
/* @__PURE__ */ jsxs("div", { className: "limbo-modal-header", children: [
|
|
31150
31384
|
/* @__PURE__ */ jsxs("h2", { id: "variants-modal-title", children: [
|
|
31151
|
-
"
|
|
31385
|
+
"Recortes de ",
|
|
31152
31386
|
image?.filename
|
|
31153
31387
|
] }),
|
|
31154
31388
|
/* @__PURE__ */ jsx(
|
|
@@ -31156,7 +31390,7 @@ function ImageVariantsModal({
|
|
|
31156
31390
|
{
|
|
31157
31391
|
className: "limbo-modal-close",
|
|
31158
31392
|
onClick: onClose,
|
|
31159
|
-
"aria-label": "Cerrar modal de
|
|
31393
|
+
"aria-label": "Cerrar modal de recortes",
|
|
31160
31394
|
children: "✕"
|
|
31161
31395
|
}
|
|
31162
31396
|
)
|
|
@@ -31179,10 +31413,10 @@ function ImageVariantsModal({
|
|
|
31179
31413
|
),
|
|
31180
31414
|
/* @__PURE__ */ jsx("div", { className: "limbo-modal-body", children: loading ? /* @__PURE__ */ jsxs("div", { className: "limbo-variants-loading", children: [
|
|
31181
31415
|
/* @__PURE__ */ jsx("div", { className: "limbo-loader" }),
|
|
31182
|
-
/* @__PURE__ */ jsx("p", { children: "Cargando
|
|
31416
|
+
/* @__PURE__ */ jsx("p", { children: "Cargando recortes..." })
|
|
31183
31417
|
] }) : error ? /* @__PURE__ */ jsxs("div", { className: "limbo-variants-error", children: [
|
|
31184
31418
|
/* @__PURE__ */ jsxs("p", { children: [
|
|
31185
|
-
"Error al cargar
|
|
31419
|
+
"Error al cargar recortes: ",
|
|
31186
31420
|
error
|
|
31187
31421
|
] }),
|
|
31188
31422
|
/* @__PURE__ */ jsx(
|
|
@@ -31194,8 +31428,8 @@ function ImageVariantsModal({
|
|
|
31194
31428
|
}
|
|
31195
31429
|
)
|
|
31196
31430
|
] }) : variants.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "limbo-variants-empty", children: [
|
|
31197
|
-
/* @__PURE__ */ jsx("p", { children: "Esta imagen no tiene
|
|
31198
|
-
/* @__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." })
|
|
31199
31433
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
31200
31434
|
/* @__PURE__ */ jsxs("div", { className: "limbo-variant-section", children: [
|
|
31201
31435
|
/* @__PURE__ */ jsx("h3", { children: "Imagen original" }),
|
|
@@ -31289,7 +31523,7 @@ function ImageVariantsModal({
|
|
|
31289
31523
|
] }),
|
|
31290
31524
|
/* @__PURE__ */ jsxs("div", { className: "limbo-variant-section", children: [
|
|
31291
31525
|
/* @__PURE__ */ jsxs("h3", { children: [
|
|
31292
|
-
"
|
|
31526
|
+
"Recortes (",
|
|
31293
31527
|
variants.length,
|
|
31294
31528
|
")"
|
|
31295
31529
|
] }),
|
|
@@ -31428,7 +31662,7 @@ function ImageCard({
|
|
|
31428
31662
|
delete: true,
|
|
31429
31663
|
crop: true,
|
|
31430
31664
|
variants: true
|
|
31431
|
-
// Nueva acción para ver
|
|
31665
|
+
// Nueva acción para ver recortes
|
|
31432
31666
|
}
|
|
31433
31667
|
}) {
|
|
31434
31668
|
const [copied, setCopied] = useState(false);
|
|
@@ -31483,23 +31717,18 @@ function ImageCard({
|
|
|
31483
31717
|
);
|
|
31484
31718
|
}
|
|
31485
31719
|
};
|
|
31486
|
-
const handleDownload = (e) => {
|
|
31720
|
+
const handleDownload = async (e) => {
|
|
31487
31721
|
e.preventDefault();
|
|
31488
31722
|
e.stopPropagation();
|
|
31489
|
-
|
|
31490
|
-
|
|
31491
|
-
|
|
31492
|
-
|
|
31493
|
-
|
|
31494
|
-
|
|
31495
|
-
|
|
31496
|
-
|
|
31497
|
-
|
|
31498
|
-
setTimeout(() => {
|
|
31499
|
-
window.URL.revokeObjectURL(url);
|
|
31500
|
-
document.body.removeChild(a);
|
|
31501
|
-
}, 100);
|
|
31502
|
-
});
|
|
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
|
+
);
|
|
31503
31732
|
};
|
|
31504
31733
|
const handleCrop = (e) => {
|
|
31505
31734
|
e.stopPropagation();
|
|
@@ -31516,7 +31745,7 @@ function ImageCard({
|
|
|
31516
31745
|
}, [image.variants_count]);
|
|
31517
31746
|
const handleShowVariants = (e) => {
|
|
31518
31747
|
e.stopPropagation();
|
|
31519
|
-
accessibilityManager?.announce(`Mostrando
|
|
31748
|
+
accessibilityManager?.announce(`Mostrando recortes de ${image.filename}`);
|
|
31520
31749
|
setShowVariants(true);
|
|
31521
31750
|
};
|
|
31522
31751
|
const handleSelect = (e) => {
|
|
@@ -31604,7 +31833,7 @@ function ImageCard({
|
|
|
31604
31833
|
"button",
|
|
31605
31834
|
{
|
|
31606
31835
|
type: "button",
|
|
31607
|
-
title: `Ver ${variantsCount}
|
|
31836
|
+
title: `Ver ${variantsCount} recorte${variantsCount !== 1 ? "s" : ""}`,
|
|
31608
31837
|
className: `btn btn-variants border border-brand-blue-050/50 ${isMobile ? "btn--touch" : ""}`,
|
|
31609
31838
|
onClick: handleShowVariants,
|
|
31610
31839
|
tabIndex: -1,
|
|
@@ -31775,7 +32004,7 @@ function ImageCard({
|
|
|
31775
32004
|
{
|
|
31776
32005
|
src: image.url || image.path,
|
|
31777
32006
|
loading: "eager",
|
|
31778
|
-
alt: image.filename,
|
|
32007
|
+
alt: image.filename.split(".")[0] ?? image.filename,
|
|
31779
32008
|
className: "w-full object-cover rounded aspect-square",
|
|
31780
32009
|
sizes: `height: ${thumbnailSize * 6}px,width: ${thumbnailSize * 6}px`,
|
|
31781
32010
|
draggable: false,
|
|
@@ -31807,7 +32036,7 @@ function ImageCard({
|
|
|
31807
32036
|
fontWeight: "500"
|
|
31808
32037
|
}
|
|
31809
32038
|
},
|
|
31810
|
-
children: image.filename
|
|
32039
|
+
children: image.filename.split(".")[0] ?? image.filename
|
|
31811
32040
|
}
|
|
31812
32041
|
)
|
|
31813
32042
|
]
|
|
@@ -31834,6 +32063,38 @@ function ImageCard({
|
|
|
31834
32063
|
)
|
|
31835
32064
|
] });
|
|
31836
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
|
+
}
|
|
31837
32098
|
function Loader({ text = "Cargando..." }) {
|
|
31838
32099
|
return /* @__PURE__ */ jsxs(
|
|
31839
32100
|
"div",
|
|
@@ -31879,50 +32140,7 @@ function Loader({ text = "Cargando..." }) {
|
|
|
31879
32140
|
}
|
|
31880
32141
|
);
|
|
31881
32142
|
}
|
|
31882
|
-
const cache$5 = /* @__PURE__ */ new Map();
|
|
31883
|
-
const CACHE_TTL$5 = 5 * 60 * 1e3;
|
|
31884
|
-
function useIsAllowedAll() {
|
|
31885
|
-
const [allowed, setAllowed] = useState(null);
|
|
31886
|
-
const [loading, setLoading] = useState(true);
|
|
31887
|
-
const [error, setError] = useState(null);
|
|
31888
|
-
useEffect(() => {
|
|
31889
|
-
const cacheKey = "auth-status";
|
|
31890
|
-
const cached = cache$5.get(cacheKey);
|
|
31891
|
-
const now = Date.now();
|
|
31892
|
-
if (cached && now - cached.timestamp < CACHE_TTL$5) {
|
|
31893
|
-
setAllowed(cached.data);
|
|
31894
|
-
setLoading(false);
|
|
31895
|
-
return;
|
|
31896
|
-
}
|
|
31897
|
-
let isMounted = true;
|
|
31898
|
-
const checkAuthStatus = async () => {
|
|
31899
|
-
try {
|
|
31900
|
-
const isAuthenticated = true;
|
|
31901
|
-
if (!isMounted) return;
|
|
31902
|
-
cache$5.set(cacheKey, { data: isAuthenticated, timestamp: Date.now() });
|
|
31903
|
-
setAllowed(isAuthenticated);
|
|
31904
|
-
} catch (err) {
|
|
31905
|
-
if (isMounted) {
|
|
31906
|
-
setError(err.message);
|
|
31907
|
-
setAllowed(false);
|
|
31908
|
-
}
|
|
31909
|
-
} finally {
|
|
31910
|
-
if (isMounted) setLoading(false);
|
|
31911
|
-
}
|
|
31912
|
-
};
|
|
31913
|
-
checkAuthStatus();
|
|
31914
|
-
return () => {
|
|
31915
|
-
isMounted = false;
|
|
31916
|
-
};
|
|
31917
|
-
}, []);
|
|
31918
|
-
const invalidateCache = () => {
|
|
31919
|
-
cache$5.delete("auth-status");
|
|
31920
|
-
};
|
|
31921
|
-
return { allowed, loading, error, invalidateCache };
|
|
31922
|
-
}
|
|
31923
32143
|
function Gallery({
|
|
31924
|
-
apiKey,
|
|
31925
|
-
prod,
|
|
31926
32144
|
onSelect,
|
|
31927
32145
|
onCrop,
|
|
31928
32146
|
// Nueva prop separada para cropping
|
|
@@ -31931,6 +32149,24 @@ function Gallery({
|
|
|
31931
32149
|
images,
|
|
31932
32150
|
loading,
|
|
31933
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
|
+
},
|
|
31934
32170
|
allowedActions = {
|
|
31935
32171
|
select: true,
|
|
31936
32172
|
download: true,
|
|
@@ -31938,18 +32174,13 @@ function Gallery({
|
|
|
31938
32174
|
delete: true,
|
|
31939
32175
|
crop: true,
|
|
31940
32176
|
variants: true
|
|
31941
|
-
// Nueva acción para ver
|
|
32177
|
+
// Nueva acción para ver recortes
|
|
31942
32178
|
}
|
|
31943
32179
|
}) {
|
|
31944
|
-
const
|
|
31945
|
-
|
|
31946
|
-
|
|
31947
|
-
dateTo: "",
|
|
31948
|
-
originPortal: "",
|
|
31949
|
-
uploadedBy: ""
|
|
31950
|
-
});
|
|
32180
|
+
const showNameFilter = filterConfig.showNameFilter !== false;
|
|
32181
|
+
const showUploadedByFilter = filterConfig.showUploadedByFilter === true;
|
|
32182
|
+
const showDateFilter = filterConfig.showDateFilter !== false;
|
|
31951
32183
|
const galleryRef = useRef(null);
|
|
31952
|
-
const showOriginPortal = useIsAllowedAll();
|
|
31953
32184
|
const accessibilityManager = window.limboCore?.accessibilityManager;
|
|
31954
32185
|
useEffect(() => {
|
|
31955
32186
|
if (galleryRef.current && window.limboCore?.keyboardManager) {
|
|
@@ -31976,7 +32207,9 @@ function Gallery({
|
|
|
31976
32207
|
}, [loading, error, images.length, accessibilityManager]);
|
|
31977
32208
|
const handleChange = (e) => {
|
|
31978
32209
|
const { name, value } = e.target;
|
|
31979
|
-
|
|
32210
|
+
if (onFiltersChange) {
|
|
32211
|
+
onFiltersChange({ ...filters, [name]: value });
|
|
32212
|
+
}
|
|
31980
32213
|
};
|
|
31981
32214
|
return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
|
|
31982
32215
|
/* @__PURE__ */ jsx("div", { className: "limbo-card mb-6 p-4 bg-brand-blue-050 shadow-md", children: /* @__PURE__ */ jsxs(
|
|
@@ -31986,16 +32219,16 @@ function Gallery({
|
|
|
31986
32219
|
onSubmit: (e) => e.preventDefault(),
|
|
31987
32220
|
"aria-label": "Filtrar imágenes",
|
|
31988
32221
|
children: [
|
|
31989
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col w-full sm:min-w-[180px] sm:flex-1", children: [
|
|
31990
|
-
/* @__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" }),
|
|
31991
32224
|
/* @__PURE__ */ jsx(
|
|
31992
32225
|
"input",
|
|
31993
32226
|
{
|
|
31994
32227
|
type: "text",
|
|
31995
|
-
name: "
|
|
31996
|
-
id: "
|
|
32228
|
+
name: "name",
|
|
32229
|
+
id: "name",
|
|
31997
32230
|
placeholder: "Buscar por nombre...",
|
|
31998
|
-
value: filters.
|
|
32231
|
+
value: filters.name,
|
|
31999
32232
|
onChange: handleChange,
|
|
32000
32233
|
className: "form-control",
|
|
32001
32234
|
autoComplete: "off"
|
|
@@ -32003,50 +32236,37 @@ function Gallery({
|
|
|
32003
32236
|
)
|
|
32004
32237
|
] }),
|
|
32005
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: [
|
|
32006
|
-
/* @__PURE__ */ jsxs(
|
|
32007
|
-
/* @__PURE__ */
|
|
32008
|
-
|
|
32009
|
-
|
|
32010
|
-
|
|
32011
|
-
|
|
32012
|
-
|
|
32013
|
-
|
|
32014
|
-
|
|
32015
|
-
|
|
32016
|
-
|
|
32017
|
-
|
|
32018
|
-
|
|
32019
|
-
|
|
32020
|
-
|
|
32021
|
-
/* @__PURE__ */
|
|
32022
|
-
|
|
32023
|
-
|
|
32024
|
-
|
|
32025
|
-
|
|
32026
|
-
|
|
32027
|
-
|
|
32028
|
-
|
|
32029
|
-
|
|
32030
|
-
|
|
32031
|
-
|
|
32032
|
-
|
|
32033
|
-
|
|
32034
|
-
|
|
32035
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "originPortal", className: "form-label mb-1", children: "Portal de origen" }),
|
|
32036
|
-
/* @__PURE__ */ jsx(
|
|
32037
|
-
"input",
|
|
32038
|
-
{
|
|
32039
|
-
type: "text",
|
|
32040
|
-
name: "originPortal",
|
|
32041
|
-
id: "originPortal",
|
|
32042
|
-
placeholder: "Portal de origen",
|
|
32043
|
-
value: filters.originPortal,
|
|
32044
|
-
onChange: handleChange,
|
|
32045
|
-
className: "form-control"
|
|
32046
|
-
}
|
|
32047
|
-
)
|
|
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
|
+
] })
|
|
32048
32268
|
] }),
|
|
32049
|
-
/* @__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: [
|
|
32050
32270
|
/* @__PURE__ */ jsx("label", { htmlFor: "uploadedBy", className: "form-label mb-1", children: "Subido por" }),
|
|
32051
32271
|
/* @__PURE__ */ jsx(
|
|
32052
32272
|
"input",
|
|
@@ -32065,7 +32285,27 @@ function Gallery({
|
|
|
32065
32285
|
]
|
|
32066
32286
|
}
|
|
32067
32287
|
) }),
|
|
32068
|
-
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(
|
|
32069
32309
|
"div",
|
|
32070
32310
|
{
|
|
32071
32311
|
ref: galleryRef,
|
|
@@ -36597,6 +36837,21 @@ class CropperManager {
|
|
|
36597
36837
|
return false;
|
|
36598
36838
|
}
|
|
36599
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
|
+
},
|
|
36600
36855
|
// Exportar a canvas
|
|
36601
36856
|
toCanvas: async (options = {}) => {
|
|
36602
36857
|
if (!this.selectionElement) return null;
|
|
@@ -36998,11 +37253,136 @@ const useCropper = (image, options = {}) => {
|
|
|
36998
37253
|
manager: managerRef.current
|
|
36999
37254
|
};
|
|
37000
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" }));
|
|
37001
37379
|
function CropperView({
|
|
37002
37380
|
image,
|
|
37003
37381
|
onSave,
|
|
37004
37382
|
onCancel,
|
|
37005
37383
|
onDelete,
|
|
37384
|
+
onError = null,
|
|
37385
|
+
// Callback para manejar errores
|
|
37006
37386
|
deleting = false,
|
|
37007
37387
|
onVariantCreated = null
|
|
37008
37388
|
// Callback cuando se crea una variante
|
|
@@ -37010,7 +37390,6 @@ function CropperView({
|
|
|
37010
37390
|
const [showPreview, setShowPreview] = useState(false);
|
|
37011
37391
|
const [previewUrl, setPreviewUrl] = useState(null);
|
|
37012
37392
|
const [previewLoading, setPreviewLoading] = useState(false);
|
|
37013
|
-
const [aspectRatio, setAspectRatio] = useState("");
|
|
37014
37393
|
const [showGrid, setShowGrid] = useState(true);
|
|
37015
37394
|
const [shade, setShade] = useState(true);
|
|
37016
37395
|
const [flipStates, setFlipStates] = useState({
|
|
@@ -37018,27 +37397,88 @@ function CropperView({
|
|
|
37018
37397
|
vertical: false
|
|
37019
37398
|
});
|
|
37020
37399
|
const [showTips, setShowTips] = useState(false);
|
|
37400
|
+
const [showVisualOptions, setShowVisualOptions] = useState(true);
|
|
37401
|
+
const [showSelectorOptions, setShowSelectorOptions] = useState(true);
|
|
37402
|
+
const [showImageOptions, setShowImageOptions] = useState(true);
|
|
37021
37403
|
const [zoomInfo, setZoomInfo] = useState({ current: 1, percentage: 100 });
|
|
37022
|
-
const
|
|
37023
|
-
|
|
37404
|
+
const [editableFilename] = useState(() => {
|
|
37405
|
+
const [name] = image.filename.split(".");
|
|
37406
|
+
return name;
|
|
37407
|
+
});
|
|
37408
|
+
const cropConfig = useMemo(() => {
|
|
37024
37409
|
const config = window.limboCore?.config?.getGlobal() || {};
|
|
37025
|
-
|
|
37026
|
-
|
|
37027
|
-
|
|
37028
|
-
|
|
37029
|
-
|
|
37030
|
-
|
|
37031
|
-
|
|
37032
|
-
|
|
37033
|
-
];
|
|
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
|
+
};
|
|
37034
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;
|
|
37035
37475
|
const {
|
|
37036
37476
|
createCropVariant,
|
|
37037
37477
|
loading: creatingVariant,
|
|
37038
37478
|
error: variantError
|
|
37039
37479
|
} = useCreateVariant();
|
|
37040
37480
|
const cropper = useCropper(image, {
|
|
37041
|
-
aspectRatio,
|
|
37481
|
+
aspectRatio: calculatedAspectRatio || null,
|
|
37042
37482
|
showGrid,
|
|
37043
37483
|
shade,
|
|
37044
37484
|
initialCoverage: 0.5,
|
|
@@ -37060,21 +37500,24 @@ function CropperView({
|
|
|
37060
37500
|
const toggleGrid = useCallback(() => setShowGrid((v) => !v), []);
|
|
37061
37501
|
const toggleShade = useCallback(() => setShade((v) => !v), []);
|
|
37062
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
|
+
);
|
|
37063
37515
|
const centerImage = useCallback(() => transform.center(), [transform]);
|
|
37064
37516
|
const centerSelection = useCallback(() => selection.center(), [selection]);
|
|
37065
37517
|
const resetSelection = useCallback(() => selection.reset(), [selection]);
|
|
37066
37518
|
const move = useCallback((x, y) => transform.move(x, y), [transform]);
|
|
37067
37519
|
const zoom = useCallback((factor) => transform.zoom(factor), [transform]);
|
|
37068
37520
|
const rotate = useCallback((deg) => transform.rotate(deg), [transform]);
|
|
37069
|
-
const resetAll = useCallback(() => {
|
|
37070
|
-
utils.resetAll();
|
|
37071
|
-
setAspectRatio("");
|
|
37072
|
-
setShowGrid(true);
|
|
37073
|
-
setShade(true);
|
|
37074
|
-
setFlipStates({ horizontal: false, vertical: false });
|
|
37075
|
-
setShowPreview(false);
|
|
37076
|
-
setPreviewUrl(null);
|
|
37077
|
-
}, [utils]);
|
|
37078
37521
|
const setSelectionCoverage = useCallback(
|
|
37079
37522
|
(coverage) => {
|
|
37080
37523
|
selection.setCoverage(coverage);
|
|
@@ -37096,16 +37539,188 @@ function CropperView({
|
|
|
37096
37539
|
return { ...prev, vertical: newVertical };
|
|
37097
37540
|
});
|
|
37098
37541
|
}, [transform]);
|
|
37099
|
-
const
|
|
37100
|
-
(
|
|
37101
|
-
|
|
37102
|
-
const
|
|
37103
|
-
|
|
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
|
+
)
|
|
37104
37561
|
);
|
|
37105
|
-
|
|
37106
|
-
|
|
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`);
|
|
37107
37722
|
},
|
|
37108
|
-
[
|
|
37723
|
+
[crops, activeCropIndex, accessibilityManager]
|
|
37109
37724
|
);
|
|
37110
37725
|
const generatePreview = useCallback(async () => {
|
|
37111
37726
|
if (!canExport) return null;
|
|
@@ -37116,12 +37731,15 @@ function CropperView({
|
|
|
37116
37731
|
imageSmoothingEnabled: true,
|
|
37117
37732
|
imageSmoothingQuality: "high"
|
|
37118
37733
|
});
|
|
37119
|
-
return canvas ? canvas.toDataURL(
|
|
37734
|
+
return canvas ? canvas.toDataURL(
|
|
37735
|
+
`image/${globalThis.downloadFormat || image.mime_type.split("/")[1] || "webp"}`,
|
|
37736
|
+
0.9
|
|
37737
|
+
) : null;
|
|
37120
37738
|
} catch (error) {
|
|
37121
37739
|
console.warn("Error generating preview:", error);
|
|
37122
37740
|
return null;
|
|
37123
37741
|
}
|
|
37124
|
-
}, [canExport, selection]);
|
|
37742
|
+
}, [canExport, image.mime_type, selection]);
|
|
37125
37743
|
const preview = useCallback(async () => {
|
|
37126
37744
|
if (showPreview) {
|
|
37127
37745
|
setShowPreview(false);
|
|
@@ -37151,7 +37769,7 @@ function CropperView({
|
|
|
37151
37769
|
setPreviewLoading(false);
|
|
37152
37770
|
}
|
|
37153
37771
|
}, [canExport, generatePreview, showPreview]);
|
|
37154
|
-
const
|
|
37772
|
+
const performSaveCrop = useCallback(async () => {
|
|
37155
37773
|
if (!canExport) {
|
|
37156
37774
|
const errorMsg = "No se puede exportar el recorte por restricciones de CORS en la imagen original.";
|
|
37157
37775
|
accessibilityManager?.announceError(errorMsg);
|
|
@@ -37164,7 +37782,7 @@ function CropperView({
|
|
|
37164
37782
|
alert(errorMsg);
|
|
37165
37783
|
return;
|
|
37166
37784
|
}
|
|
37167
|
-
accessibilityManager?.announce("Creando
|
|
37785
|
+
accessibilityManager?.announce("Creando recorte de la imagen");
|
|
37168
37786
|
try {
|
|
37169
37787
|
if (!cropData || !effectiveImageInfo) {
|
|
37170
37788
|
console.error("❌ Datos faltantes:", { cropData, effectiveImageInfo });
|
|
@@ -37192,60 +37810,181 @@ function CropperView({
|
|
|
37192
37810
|
width: width / naturalWidth,
|
|
37193
37811
|
height: height / naturalHeight
|
|
37194
37812
|
};
|
|
37195
|
-
const
|
|
37196
|
-
|
|
37197
|
-
const maxDimension = 1200;
|
|
37198
|
-
if (cropAspectRatio > 1) {
|
|
37199
|
-
variantWidth = Math.min(width, maxDimension);
|
|
37200
|
-
variantHeight = Math.round(variantWidth / cropAspectRatio);
|
|
37201
|
-
} else {
|
|
37202
|
-
variantHeight = Math.min(height, maxDimension);
|
|
37203
|
-
variantWidth = Math.round(variantHeight * cropAspectRatio);
|
|
37204
|
-
}
|
|
37813
|
+
const variantWidth = Math.min(activeCrop.width, 5e3);
|
|
37814
|
+
const variantHeight = Math.min(activeCrop.height, 5e3);
|
|
37205
37815
|
const ts = Date.now();
|
|
37206
|
-
const
|
|
37207
|
-
const variantName = `${name}_crop_${ts}`;
|
|
37816
|
+
const variantName = `${editableFilename}_${activeCrop.label || "crop"}_${ts}`;
|
|
37208
37817
|
const result = await createCropVariant(image.id, cropParams, {
|
|
37209
37818
|
name: variantName,
|
|
37210
37819
|
width: variantWidth,
|
|
37211
37820
|
height: variantHeight,
|
|
37212
|
-
format: "webp",
|
|
37821
|
+
format: globalThis.downloadFormat || "webp",
|
|
37213
37822
|
quality: 90
|
|
37214
37823
|
});
|
|
37215
37824
|
if (result) {
|
|
37216
|
-
accessibilityManager?.announceSuccess(
|
|
37217
|
-
`Variante recortada creada: ${variantName}`
|
|
37218
|
-
);
|
|
37825
|
+
accessibilityManager?.announceSuccess(`Recorte creado: ${variantName}`);
|
|
37219
37826
|
onVariantCreated?.(image.id, result);
|
|
37220
37827
|
onSave(result);
|
|
37221
37828
|
}
|
|
37222
37829
|
} catch (error) {
|
|
37223
37830
|
console.warn("Error creating crop variant:", error);
|
|
37224
|
-
const errorMsg = "No se pudo crear
|
|
37831
|
+
const errorMsg = "No se pudo crear el recorte. Inténtalo de nuevo.";
|
|
37225
37832
|
accessibilityManager?.announceError(errorMsg);
|
|
37226
37833
|
alert(errorMsg);
|
|
37834
|
+
onError?.(error);
|
|
37227
37835
|
}
|
|
37228
37836
|
}, [
|
|
37229
37837
|
canExport,
|
|
37838
|
+
state.isReady,
|
|
37839
|
+
accessibilityManager,
|
|
37230
37840
|
cropData,
|
|
37231
37841
|
effectiveImageInfo,
|
|
37232
|
-
|
|
37233
|
-
|
|
37842
|
+
editableFilename,
|
|
37843
|
+
activeCrop.label,
|
|
37844
|
+
activeCrop.width,
|
|
37845
|
+
activeCrop.height,
|
|
37234
37846
|
createCropVariant,
|
|
37235
|
-
|
|
37847
|
+
image.id,
|
|
37236
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,
|
|
37237
37909
|
accessibilityManager,
|
|
37238
|
-
|
|
37910
|
+
previewUrl,
|
|
37911
|
+
activeCrop.label,
|
|
37912
|
+
editableFilename,
|
|
37913
|
+
generatePreview
|
|
37239
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]);
|
|
37240
37931
|
useEffect(() => {
|
|
37241
37932
|
setShowPreview(false);
|
|
37242
37933
|
setPreviewUrl(null);
|
|
37243
37934
|
}, [image]);
|
|
37244
37935
|
useEffect(() => {
|
|
37245
37936
|
if (!cropper.manager) return;
|
|
37246
|
-
|
|
37937
|
+
if (calculatedAspectRatio) {
|
|
37938
|
+
selection.setAspectRatio(calculatedAspectRatio);
|
|
37939
|
+
}
|
|
37247
37940
|
utils.setBackground(shade);
|
|
37248
|
-
}, [
|
|
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]);
|
|
37249
37988
|
useEffect(() => {
|
|
37250
37989
|
if (!cropper.manager || !cropper.manager.utils) return;
|
|
37251
37990
|
try {
|
|
@@ -37289,7 +38028,7 @@ function CropperView({
|
|
|
37289
38028
|
showPreview,
|
|
37290
38029
|
canExport,
|
|
37291
38030
|
generatePreview,
|
|
37292
|
-
|
|
38031
|
+
calculatedAspectRatio,
|
|
37293
38032
|
flipStates,
|
|
37294
38033
|
previewUrl
|
|
37295
38034
|
]);
|
|
@@ -37322,19 +38061,27 @@ function CropperView({
|
|
|
37322
38061
|
};
|
|
37323
38062
|
}, [canvasRef]);
|
|
37324
38063
|
if (!image) return null;
|
|
37325
|
-
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-
|
|
37326
|
-
/* @__PURE__ */ jsxs("div", { className: "limbo-cropper-header flex flex-col sm:flex-row justify-between items-start sm:items-center p-4
|
|
37327
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
37328
|
-
/* @__PURE__ */
|
|
37329
|
-
|
|
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
|
+
] })
|
|
37330
38075
|
] }),
|
|
37331
|
-
/* @__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: [
|
|
37332
38077
|
/* @__PURE__ */ jsx(
|
|
37333
38078
|
"button",
|
|
37334
38079
|
{
|
|
37335
38080
|
onClick: onCancel,
|
|
37336
38081
|
disabled: creatingVariant,
|
|
37337
|
-
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",
|
|
37338
38085
|
children: "Cancelar"
|
|
37339
38086
|
}
|
|
37340
38087
|
),
|
|
@@ -37343,8 +38090,9 @@ function CropperView({
|
|
|
37343
38090
|
{
|
|
37344
38091
|
onClick: () => onDelete?.(image),
|
|
37345
38092
|
disabled: deleting | creatingVariant,
|
|
37346
|
-
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",
|
|
37347
38094
|
"aria-label": `Eliminar imagen ${image.filename}`,
|
|
38095
|
+
title: `Eliminar imagen ${image.filename}`,
|
|
37348
38096
|
children: deleting ? "Eliminando..." : "Eliminar"
|
|
37349
38097
|
}
|
|
37350
38098
|
)
|
|
@@ -37356,15 +38104,6 @@ function CropperView({
|
|
|
37356
38104
|
" ",
|
|
37357
38105
|
variantError
|
|
37358
38106
|
] }),
|
|
37359
|
-
cropData && cropData.width > 0 && /* @__PURE__ */ jsxs("div", { className: "alert alert-info mb-2 text-sm", role: "status", children: [
|
|
37360
|
-
/* @__PURE__ */ jsx("strong", { children: "Área:" }),
|
|
37361
|
-
" ",
|
|
37362
|
-
Math.round(cropData.width),
|
|
37363
|
-
" ×",
|
|
37364
|
-
" ",
|
|
37365
|
-
Math.round(cropData.height),
|
|
37366
|
-
" px"
|
|
37367
|
-
] }),
|
|
37368
38107
|
imageInfo && /* @__PURE__ */ jsxs("div", { className: "alert alert-secondary mb-2 text-sm", role: "status", children: [
|
|
37369
38108
|
/* @__PURE__ */ jsx("strong", { children: "Original:" }),
|
|
37370
38109
|
" ",
|
|
@@ -37382,10 +38121,135 @@ function CropperView({
|
|
|
37382
38121
|
" px)"
|
|
37383
38122
|
] })
|
|
37384
38123
|
] }),
|
|
37385
|
-
!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
|
+
] })
|
|
37386
38250
|
] }),
|
|
37387
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col
|
|
37388
|
-
/* @__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: [
|
|
37389
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: [
|
|
37390
38254
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-2", children: [
|
|
37391
38255
|
/* @__PURE__ */ jsx("h3", { className: "text-xs font-semibold text-gray-700", children: "Vista previa" }),
|
|
@@ -37458,9 +38322,13 @@ function CropperView({
|
|
|
37458
38322
|
"initial-coverage": "0.5",
|
|
37459
38323
|
movable: true,
|
|
37460
38324
|
resizable: true,
|
|
37461
|
-
keyboard: "
|
|
38325
|
+
keyboard: "true",
|
|
37462
38326
|
action: "move",
|
|
37463
|
-
style: {
|
|
38327
|
+
style: {
|
|
38328
|
+
cursor: "move",
|
|
38329
|
+
minWidth: `${minCropSizes.minWidth}px`,
|
|
38330
|
+
minHeight: `${minCropSizes.minHeight}px`
|
|
38331
|
+
},
|
|
37464
38332
|
"data-prevent-delete": "true",
|
|
37465
38333
|
tabindex: "-1",
|
|
37466
38334
|
children: [
|
|
@@ -37503,61 +38371,401 @@ function CropperView({
|
|
|
37503
38371
|
}
|
|
37504
38372
|
)
|
|
37505
38373
|
] }) }),
|
|
37506
|
-
/* @__PURE__ */ jsx("div", { className: "limbo-cropper-controls w-full
|
|
37507
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4
|
|
37508
|
-
/* @__PURE__ */ jsx(
|
|
37509
|
-
|
|
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: [
|
|
37510
38395
|
/* @__PURE__ */ jsxs(
|
|
37511
38396
|
"button",
|
|
37512
38397
|
{
|
|
37513
|
-
onClick:
|
|
37514
|
-
|
|
37515
|
-
|
|
37516
|
-
"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",
|
|
37517
38404
|
children: [
|
|
37518
|
-
/* @__PURE__ */
|
|
37519
|
-
"span",
|
|
37520
|
-
|
|
37521
|
-
|
|
37522
|
-
|
|
37523
|
-
|
|
37524
|
-
|
|
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" })
|
|
37525
38415
|
]
|
|
37526
38416
|
}
|
|
37527
38417
|
),
|
|
37528
|
-
/* @__PURE__ */ jsx(
|
|
37529
|
-
"button",
|
|
37530
|
-
{
|
|
37531
|
-
onClick: saveCrop,
|
|
37532
|
-
disabled: creatingVariant || !cropData || !effectiveImageInfo || !canExport || !state.isReady,
|
|
37533
|
-
className: "w-full limbo-btn limbo-btn-success min-h-10",
|
|
37534
|
-
"aria-label": "Guardar imagen recortada",
|
|
37535
|
-
children: creatingVariant ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37536
|
-
/* @__PURE__ */ jsx("span", { className: "icon icon-save-white" }),
|
|
37537
|
-
" ",
|
|
37538
|
-
"Guardando..."
|
|
37539
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37540
|
-
/* @__PURE__ */ jsx("span", { className: "icon icon-save-white" }),
|
|
37541
|
-
" Guardar recorte"
|
|
37542
|
-
] })
|
|
37543
|
-
}
|
|
37544
|
-
),
|
|
37545
38418
|
/* @__PURE__ */ jsxs(
|
|
37546
38419
|
"button",
|
|
37547
38420
|
{
|
|
37548
|
-
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"}`,
|
|
37549
38423
|
disabled: creatingVariant,
|
|
37550
|
-
|
|
37551
|
-
"aria-label": "
|
|
38424
|
+
"aria-pressed": shade,
|
|
38425
|
+
"aria-label": "Activar/desactivar sombreado",
|
|
37552
38426
|
children: [
|
|
37553
|
-
/* @__PURE__ */
|
|
37554
|
-
|
|
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" })
|
|
37555
38437
|
]
|
|
37556
38438
|
}
|
|
37557
38439
|
)
|
|
37558
38440
|
] })
|
|
37559
38441
|
] }),
|
|
37560
|
-
/* @__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: [
|
|
37561
38769
|
/* @__PURE__ */ jsxs(
|
|
37562
38770
|
"button",
|
|
37563
38771
|
{
|
|
@@ -37586,7 +38794,7 @@ function CropperView({
|
|
|
37586
38794
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
37587
38795
|
"• ",
|
|
37588
38796
|
/* @__PURE__ */ jsx("strong", { children: "Arrastra la imagen:" }),
|
|
37589
|
-
" Haz clic
|
|
38797
|
+
" Haz clic sobre la imagen del área de selección y arrastra"
|
|
37590
38798
|
] }),
|
|
37591
38799
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
37592
38800
|
"• ",
|
|
@@ -37618,11 +38826,6 @@ function CropperView({
|
|
|
37618
38826
|
"• ",
|
|
37619
38827
|
/* @__PURE__ */ jsx("strong", { children: "Tamaños rápidos:" }),
|
|
37620
38828
|
" Usa los botones 50%, 70%, 90%, 100%"
|
|
37621
|
-
] }),
|
|
37622
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
37623
|
-
"• ",
|
|
37624
|
-
/* @__PURE__ */ jsx("strong", { children: "Proporciones:" }),
|
|
37625
|
-
" Selecciona ratios predefinidos (1:1, 16:9, etc.)"
|
|
37626
38829
|
] })
|
|
37627
38830
|
] })
|
|
37628
38831
|
] }),
|
|
@@ -37660,9 +38863,14 @@ function CropperView({
|
|
|
37660
38863
|
] }),
|
|
37661
38864
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
37662
38865
|
"• ",
|
|
37663
|
-
/* @__PURE__ */ jsx("strong", { children: "
|
|
38866
|
+
/* @__PURE__ */ jsx("strong", { children: "Cuadricula:" }),
|
|
37664
38867
|
" Actívalo para aplicar la regla de los tercios"
|
|
37665
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
|
+
] }),
|
|
37666
38874
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
37667
38875
|
"• ",
|
|
37668
38876
|
/* @__PURE__ */ jsx("strong", { children: "Transformaciones:" }),
|
|
@@ -37691,366 +38899,139 @@ function CropperView({
|
|
|
37691
38899
|
] })
|
|
37692
38900
|
] })
|
|
37693
38901
|
] })
|
|
37694
|
-
] })
|
|
37695
|
-
|
|
37696
|
-
|
|
37697
|
-
|
|
37698
|
-
|
|
37699
|
-
|
|
37700
|
-
|
|
37701
|
-
|
|
37702
|
-
|
|
37703
|
-
|
|
37704
|
-
|
|
37705
|
-
|
|
37706
|
-
|
|
37707
|
-
|
|
37708
|
-
|
|
37709
|
-
"select",
|
|
37710
|
-
{
|
|
37711
|
-
value: aspectRatio,
|
|
37712
|
-
onChange: (e) => handleAspectRatio(e.target.value),
|
|
37713
|
-
className: "w-full form-control hidden md:block",
|
|
37714
|
-
disabled: creatingVariant,
|
|
37715
|
-
"aria-label": "Seleccionar proporción de aspecto",
|
|
37716
|
-
children: allowedAspectRatios.map((ratio) => /* @__PURE__ */ jsx("option", { value: ratio.value, children: ratio.label }, ratio.value))
|
|
37717
|
-
}
|
|
37718
|
-
)
|
|
37719
|
-
] }),
|
|
37720
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [
|
|
37721
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-700 mb-3", children: "Visualización" }),
|
|
37722
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
37723
|
-
/* @__PURE__ */ jsxs(
|
|
37724
|
-
"button",
|
|
37725
|
-
{
|
|
37726
|
-
onClick: toggleGrid,
|
|
37727
|
-
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"}`,
|
|
37728
|
-
disabled: creatingVariant,
|
|
37729
|
-
"aria-pressed": showGrid,
|
|
37730
|
-
"aria-label": "Activar/desactivar grid",
|
|
37731
|
-
children: [
|
|
37732
|
-
/* @__PURE__ */ jsxs("span", { className: "text-sm flex items-center", children: [
|
|
37733
|
-
/* @__PURE__ */ jsx("span", { className: "icon icon-area-blue me-1" }),
|
|
37734
|
-
" Grid"
|
|
37735
|
-
] }),
|
|
37736
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs", children: showGrid ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37737
|
-
/* @__PURE__ */ jsx("span", { className: "icon icon-tick icon--xs align-[middle!important] -mt-0.5" }),
|
|
37738
|
-
" ",
|
|
37739
|
-
"Activo"
|
|
37740
|
-
] }) : "Inactivo" })
|
|
37741
|
-
]
|
|
37742
|
-
}
|
|
37743
|
-
),
|
|
37744
|
-
/* @__PURE__ */ jsxs(
|
|
37745
|
-
"button",
|
|
37746
|
-
{
|
|
37747
|
-
onClick: toggleShade,
|
|
37748
|
-
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"}`,
|
|
37749
|
-
disabled: creatingVariant,
|
|
37750
|
-
"aria-pressed": shade,
|
|
37751
|
-
"aria-label": "Activar/desactivar sombreado",
|
|
37752
|
-
children: [
|
|
37753
|
-
/* @__PURE__ */ jsxs("span", { className: "text-sm flex items-center", children: [
|
|
37754
|
-
/* @__PURE__ */ jsx("span", { className: "icon icon-comparison-blue me-1" }),
|
|
37755
|
-
" ",
|
|
37756
|
-
"Sombreado"
|
|
37757
|
-
] }),
|
|
37758
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs", children: shade ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37759
|
-
/* @__PURE__ */ jsx("span", { className: "icon icon-tick icon--xs align-[middle!important] -mt-0.5" }),
|
|
37760
|
-
" ",
|
|
37761
|
-
"Activo"
|
|
37762
|
-
] }) : "Inactivo" })
|
|
37763
|
-
]
|
|
37764
|
-
}
|
|
37765
|
-
)
|
|
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" })
|
|
37766
38917
|
] })
|
|
37767
|
-
|
|
37768
|
-
|
|
37769
|
-
|
|
37770
|
-
|
|
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: [
|
|
37771
38965
|
/* @__PURE__ */ jsx(
|
|
37772
|
-
"
|
|
38966
|
+
"input",
|
|
37773
38967
|
{
|
|
37774
|
-
|
|
37775
|
-
|
|
37776
|
-
|
|
37777
|
-
|
|
37778
|
-
|
|
37779
|
-
|
|
37780
|
-
|
|
37781
|
-
|
|
37782
|
-
|
|
37783
|
-
|
|
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"
|
|
37784
38979
|
}
|
|
37785
38980
|
),
|
|
37786
|
-
/* @__PURE__ */
|
|
37787
|
-
"
|
|
37788
|
-
|
|
37789
|
-
|
|
37790
|
-
|
|
37791
|
-
|
|
37792
|
-
|
|
37793
|
-
"
|
|
37794
|
-
|
|
37795
|
-
|
|
37796
|
-
|
|
37797
|
-
"Reset selección"
|
|
37798
|
-
] }) })
|
|
37799
|
-
}
|
|
37800
|
-
)
|
|
37801
|
-
] }),
|
|
37802
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-3", children: [
|
|
37803
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 mb-2", children: "Tamaños rápidos" }),
|
|
37804
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-1", children: [
|
|
37805
|
-
/* @__PURE__ */ jsx(
|
|
37806
|
-
"button",
|
|
37807
|
-
{
|
|
37808
|
-
onClick: () => setSelectionCoverage(0.5),
|
|
37809
|
-
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37810
|
-
disabled: creatingVariant,
|
|
37811
|
-
"aria-label": "Selección 50%",
|
|
37812
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "50%" }) })
|
|
37813
|
-
}
|
|
37814
|
-
),
|
|
37815
|
-
/* @__PURE__ */ jsx(
|
|
37816
|
-
"button",
|
|
37817
|
-
{
|
|
37818
|
-
onClick: () => setSelectionCoverage(0.7),
|
|
37819
|
-
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37820
|
-
disabled: creatingVariant,
|
|
37821
|
-
"aria-label": "Selección 70%",
|
|
37822
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "70%" }) })
|
|
37823
|
-
}
|
|
37824
|
-
),
|
|
37825
|
-
/* @__PURE__ */ jsx(
|
|
37826
|
-
"button",
|
|
37827
|
-
{
|
|
37828
|
-
onClick: () => setSelectionCoverage(0.9),
|
|
37829
|
-
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37830
|
-
disabled: creatingVariant,
|
|
37831
|
-
"aria-label": "Selección 90%",
|
|
37832
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "90%" }) })
|
|
37833
|
-
}
|
|
37834
|
-
),
|
|
37835
|
-
/* @__PURE__ */ jsx(
|
|
37836
|
-
"button",
|
|
37837
|
-
{
|
|
37838
|
-
onClick: () => setSelectionCoverage(1),
|
|
37839
|
-
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37840
|
-
disabled: creatingVariant,
|
|
37841
|
-
"aria-label": "Selección completa",
|
|
37842
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "100%" }) })
|
|
37843
|
-
}
|
|
37844
|
-
)
|
|
37845
|
-
] })
|
|
37846
|
-
] })
|
|
37847
|
-
] }),
|
|
37848
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [
|
|
37849
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-700 mb-3", children: "Transformar imagen" }),
|
|
37850
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
37851
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 mb-2", children: "Mover imagen" }),
|
|
37852
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-1", children: [
|
|
37853
|
-
/* @__PURE__ */ jsx("div", {}),
|
|
37854
|
-
/* @__PURE__ */ jsx(
|
|
37855
|
-
"button",
|
|
37856
|
-
{
|
|
37857
|
-
onClick: () => move(0, -10),
|
|
37858
|
-
className: "p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37859
|
-
title: "Mover arriba",
|
|
37860
|
-
disabled: creatingVariant,
|
|
37861
|
-
"aria-label": "Mover imagen hacia arriba",
|
|
37862
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-up-blue" }) })
|
|
37863
|
-
}
|
|
37864
|
-
),
|
|
37865
|
-
/* @__PURE__ */ jsx("div", {}),
|
|
37866
|
-
/* @__PURE__ */ jsx(
|
|
37867
|
-
"button",
|
|
37868
|
-
{
|
|
37869
|
-
onClick: () => move(-10, 0),
|
|
37870
|
-
className: "p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37871
|
-
title: "Mover izquierda",
|
|
37872
|
-
disabled: creatingVariant,
|
|
37873
|
-
"aria-label": "Mover imagen hacia la izquierda",
|
|
37874
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-left-blue" }) })
|
|
37875
|
-
}
|
|
37876
|
-
),
|
|
37877
|
-
/* @__PURE__ */ jsx(
|
|
37878
|
-
"button",
|
|
37879
|
-
{
|
|
37880
|
-
onClick: centerImage,
|
|
37881
|
-
className: "p-2 rounded cursor-pointer transition-colors text-xs bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37882
|
-
title: "Centrar y ajustar imagen",
|
|
37883
|
-
disabled: creatingVariant,
|
|
37884
|
-
"aria-label": "Centrar y ajustar imagen",
|
|
37885
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-radio-button-blue icon-md" }) })
|
|
37886
|
-
}
|
|
37887
|
-
),
|
|
37888
|
-
/* @__PURE__ */ jsx(
|
|
37889
|
-
"button",
|
|
37890
|
-
{
|
|
37891
|
-
onClick: () => move(10, 0),
|
|
37892
|
-
className: "p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37893
|
-
title: "Mover derecha",
|
|
37894
|
-
disabled: creatingVariant,
|
|
37895
|
-
"aria-label": "Mover imagen hacia la derecha",
|
|
37896
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-right-blue" }) })
|
|
37897
|
-
}
|
|
37898
|
-
),
|
|
37899
|
-
/* @__PURE__ */ jsx("div", {}),
|
|
37900
|
-
/* @__PURE__ */ jsx(
|
|
37901
|
-
"button",
|
|
37902
|
-
{
|
|
37903
|
-
onClick: () => move(0, 10),
|
|
37904
|
-
className: "p-2 rounded cursor-pointer transition-colors text-sm bg-gray-100 border border-gray-300 text-gray-700 hover:bg-gray-200",
|
|
37905
|
-
title: "Mover abajo",
|
|
37906
|
-
disabled: creatingVariant,
|
|
37907
|
-
"aria-label": "Mover imagen hacia abajo",
|
|
37908
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-arrow-down-blue" }) })
|
|
37909
|
-
}
|
|
37910
|
-
),
|
|
37911
|
-
/* @__PURE__ */ jsx("div", {})
|
|
37912
|
-
] })
|
|
37913
|
-
] }),
|
|
37914
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
37915
|
-
/* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-600 mb-2", children: [
|
|
37916
|
-
"Zoom ",
|
|
37917
|
-
zoomInfo ? zoomInfo.percentage + "%" : ""
|
|
37918
|
-
] }),
|
|
37919
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
|
|
37920
|
-
/* @__PURE__ */ jsx(
|
|
37921
|
-
"button",
|
|
37922
|
-
{
|
|
37923
|
-
onClick: () => zoom(-0.2),
|
|
37924
|
-
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",
|
|
37925
|
-
title: "Alejar 20%",
|
|
37926
|
-
disabled: creatingVariant,
|
|
37927
|
-
"aria-label": "Alejar imagen",
|
|
37928
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-zoom-out-blue" }) })
|
|
37929
|
-
}
|
|
37930
|
-
),
|
|
37931
|
-
/* @__PURE__ */ jsx(
|
|
37932
|
-
"button",
|
|
37933
|
-
{
|
|
37934
|
-
onClick: resetZoomOnly,
|
|
37935
|
-
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",
|
|
37936
|
-
title: "Restablecer zoom original",
|
|
37937
|
-
disabled: creatingVariant,
|
|
37938
|
-
"aria-label": "Restablecer el zoom para que la imagen se vea con su resolución original",
|
|
37939
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-screenshot-blue" }) })
|
|
37940
|
-
}
|
|
37941
|
-
),
|
|
37942
|
-
/* @__PURE__ */ jsx(
|
|
37943
|
-
"button",
|
|
37944
|
-
{
|
|
37945
|
-
onClick: () => zoom(0.2),
|
|
37946
|
-
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",
|
|
37947
|
-
title: "Acercar 20%",
|
|
37948
|
-
disabled: creatingVariant,
|
|
37949
|
-
"aria-label": "Acercar imagen",
|
|
37950
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-zoom-in-blue" }) })
|
|
37951
|
-
}
|
|
37952
|
-
)
|
|
37953
|
-
] })
|
|
37954
|
-
] }),
|
|
37955
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
37956
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 mb-2", children: "Rotación" }),
|
|
37957
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-1 *:text-brand-blue-1000 *:text-sm", children: [
|
|
37958
|
-
/* @__PURE__ */ jsx(
|
|
37959
|
-
"button",
|
|
37960
|
-
{
|
|
37961
|
-
onClick: () => rotate(-90),
|
|
37962
|
-
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",
|
|
37963
|
-
title: "Rotar -90°",
|
|
37964
|
-
disabled: creatingVariant,
|
|
37965
|
-
"aria-label": "Rotar imagen 90 grados a la izquierda",
|
|
37966
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-reply-blue" }) })
|
|
37967
|
-
}
|
|
37968
|
-
),
|
|
37969
|
-
/* @__PURE__ */ jsx(
|
|
37970
|
-
"button",
|
|
37971
|
-
{
|
|
37972
|
-
onClick: () => rotate(-45),
|
|
37973
|
-
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",
|
|
37974
|
-
title: "Rotar -45°",
|
|
37975
|
-
disabled: creatingVariant,
|
|
37976
|
-
"aria-label": "Rotar imagen 45 grados a la izquierda",
|
|
37977
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "-45°" }) })
|
|
37978
|
-
}
|
|
37979
|
-
),
|
|
37980
|
-
/* @__PURE__ */ jsx(
|
|
37981
|
-
"button",
|
|
37982
|
-
{
|
|
37983
|
-
onClick: () => rotate(45),
|
|
37984
|
-
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",
|
|
37985
|
-
title: "Rotar +45°",
|
|
37986
|
-
disabled: creatingVariant,
|
|
37987
|
-
"aria-label": "Rotar imagen 45 grados a la derecha",
|
|
37988
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { children: "+45°" }) })
|
|
37989
|
-
}
|
|
37990
|
-
),
|
|
37991
|
-
/* @__PURE__ */ jsx(
|
|
37992
|
-
"button",
|
|
37993
|
-
{
|
|
37994
|
-
onClick: () => rotate(90),
|
|
37995
|
-
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",
|
|
37996
|
-
title: "Rotar +90°",
|
|
37997
|
-
disabled: creatingVariant,
|
|
37998
|
-
"aria-label": "Rotar imagen 90 grados a la derecha",
|
|
37999
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "icon icon-send-arrow-blue" }) })
|
|
38000
|
-
}
|
|
38001
|
-
)
|
|
38002
|
-
] })
|
|
38003
|
-
] }),
|
|
38004
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
38005
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 mb-2", children: "Voltear" }),
|
|
38006
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
|
|
38007
|
-
/* @__PURE__ */ jsx(
|
|
38008
|
-
"button",
|
|
38009
|
-
{
|
|
38010
|
-
onClick: flipHorizontal,
|
|
38011
|
-
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"}`,
|
|
38012
|
-
title: `Voltear horizontalmente ${flipStates.horizontal ? "(activo)" : ""}`,
|
|
38013
|
-
disabled: creatingVariant,
|
|
38014
|
-
"aria-label": "Voltear imagen horizontalmente",
|
|
38015
|
-
"aria-pressed": flipStates.horizontal,
|
|
38016
|
-
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" }) })
|
|
38017
|
-
}
|
|
38018
|
-
),
|
|
38019
|
-
/* @__PURE__ */ jsx(
|
|
38020
|
-
"button",
|
|
38021
|
-
{
|
|
38022
|
-
onClick: flipVertical,
|
|
38023
|
-
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"}`,
|
|
38024
|
-
title: `Voltear verticalmente ${flipStates.vertical ? "(activo)" : ""}`,
|
|
38025
|
-
disabled: creatingVariant,
|
|
38026
|
-
"aria-label": "Voltear imagen verticalmente",
|
|
38027
|
-
"aria-pressed": flipStates.vertical,
|
|
38028
|
-
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" }) })
|
|
38029
|
-
}
|
|
38030
|
-
)
|
|
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
|
+
] })
|
|
38031
38992
|
] })
|
|
38032
|
-
]
|
|
38033
|
-
|
|
38034
|
-
|
|
38035
|
-
|
|
38036
|
-
|
|
38037
|
-
|
|
38038
|
-
|
|
38039
|
-
|
|
38040
|
-
|
|
38041
|
-
|
|
38042
|
-
|
|
38043
|
-
|
|
38044
|
-
|
|
38045
|
-
|
|
38046
|
-
|
|
38047
|
-
|
|
38048
|
-
|
|
38049
|
-
|
|
38050
|
-
|
|
38051
|
-
|
|
38052
|
-
|
|
38053
|
-
|
|
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
|
+
] }) })
|
|
38054
39035
|
] });
|
|
38055
39036
|
}
|
|
38056
39037
|
function Pagination({
|
|
@@ -38360,6 +39341,18 @@ function useTokenExpiration() {
|
|
|
38360
39341
|
handleTokenExpiredClose
|
|
38361
39342
|
};
|
|
38362
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
|
+
}
|
|
38363
39356
|
function App({
|
|
38364
39357
|
apiKey,
|
|
38365
39358
|
prod = false,
|
|
@@ -38392,6 +39385,14 @@ function App({
|
|
|
38392
39385
|
sessionStorage.removeItem("limbo_portals_images");
|
|
38393
39386
|
sessionStorage.removeItem("limbo_portals_portalResults");
|
|
38394
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);
|
|
38395
39396
|
const getFilteredFeatures = () => {
|
|
38396
39397
|
switch (modeUI) {
|
|
38397
39398
|
case "gallery-only":
|
|
@@ -38435,6 +39436,14 @@ function App({
|
|
|
38435
39436
|
error: deleteError,
|
|
38436
39437
|
reset: resetDelete
|
|
38437
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
|
+
};
|
|
38438
39447
|
const {
|
|
38439
39448
|
images,
|
|
38440
39449
|
loading: loadingImages,
|
|
@@ -38442,7 +39451,7 @@ function App({
|
|
|
38442
39451
|
pagination,
|
|
38443
39452
|
invalidateCache,
|
|
38444
39453
|
setImages
|
|
38445
|
-
} = useImages(apiKey, prod,
|
|
39454
|
+
} = useImages(apiKey, prod, apiParams);
|
|
38446
39455
|
const { refreshVariants } = useImageVariants();
|
|
38447
39456
|
const handleVariantCreated = (assetId, variantData) => {
|
|
38448
39457
|
refreshVariants(assetId);
|
|
@@ -38486,7 +39495,7 @@ function App({
|
|
|
38486
39495
|
}
|
|
38487
39496
|
};
|
|
38488
39497
|
const handleDelete = async (imageId) => {
|
|
38489
|
-
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.")) {
|
|
38490
39499
|
return;
|
|
38491
39500
|
}
|
|
38492
39501
|
const success = await deleteImg(imageId);
|
|
@@ -38524,8 +39533,148 @@ function App({
|
|
|
38524
39533
|
if (tabId !== "upload") resetUpload();
|
|
38525
39534
|
if (tabId !== "gallery") resetDelete();
|
|
38526
39535
|
};
|
|
38527
|
-
|
|
38528
|
-
|
|
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 }),
|
|
38529
39678
|
imagesError && /* @__PURE__ */ jsxs("div", { className: "alert alert-danger", children: [
|
|
38530
39679
|
"Error al cargar imágenes: ",
|
|
38531
39680
|
imagesError
|
|
@@ -38539,8 +39688,6 @@ function App({
|
|
|
38539
39688
|
/* @__PURE__ */ jsx(
|
|
38540
39689
|
Gallery,
|
|
38541
39690
|
{
|
|
38542
|
-
apiKey,
|
|
38543
|
-
prod,
|
|
38544
39691
|
onSelect: handleImageSelect,
|
|
38545
39692
|
onCrop: handleImageCrop,
|
|
38546
39693
|
onDelete: isActionAllowed("delete") ? handleDelete : null,
|
|
@@ -38548,6 +39695,13 @@ function App({
|
|
|
38548
39695
|
images,
|
|
38549
39696
|
loading: loadingImages,
|
|
38550
39697
|
error: imagesError,
|
|
39698
|
+
filters: galleryFilters,
|
|
39699
|
+
onFiltersChange: (newFilters) => {
|
|
39700
|
+
setGalleryFilters(newFilters);
|
|
39701
|
+
setCurrentPage(1);
|
|
39702
|
+
},
|
|
39703
|
+
filterConfig: ui.galleryFilters || {},
|
|
39704
|
+
loadingConfig: ui.galleryLoading || {},
|
|
38551
39705
|
allowedActions: {
|
|
38552
39706
|
select: isActionAllowed("select"),
|
|
38553
39707
|
download: isActionAllowed("download"),
|
|
@@ -38591,16 +39745,10 @@ function App({
|
|
|
38591
39745
|
CropperView,
|
|
38592
39746
|
{
|
|
38593
39747
|
image: selectedImage,
|
|
38594
|
-
onSave:
|
|
38595
|
-
|
|
38596
|
-
setSelectedImage(null);
|
|
38597
|
-
setActiveTab("gallery");
|
|
38598
|
-
},
|
|
38599
|
-
onCancel: () => {
|
|
38600
|
-
setSelectedImage(null);
|
|
38601
|
-
setActiveTab("gallery");
|
|
38602
|
-
},
|
|
39748
|
+
onSave: handleCropSave,
|
|
39749
|
+
onCancel: handleCropCancel,
|
|
38603
39750
|
onDelete: () => handleDelete(selectedImage?.id),
|
|
39751
|
+
onError: handleCropError,
|
|
38604
39752
|
deleting,
|
|
38605
39753
|
onVariantCreated: handleVariantCreated
|
|
38606
39754
|
}
|
|
@@ -38905,7 +40053,12 @@ class LimboInstance {
|
|
|
38905
40053
|
id: `limbo-component-container-${this.id}`,
|
|
38906
40054
|
className: "limbo-instance limbo-component-container-wrapper py-3",
|
|
38907
40055
|
"data-limbo-id": this.id,
|
|
38908
|
-
"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"
|
|
38909
40062
|
},
|
|
38910
40063
|
React.createElement(App, {
|
|
38911
40064
|
apiKey: this.config.apiKey || null,
|
|
@@ -41925,6 +43078,288 @@ class LimboCore {
|
|
|
41925
43078
|
});
|
|
41926
43079
|
modalInstance.open();
|
|
41927
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
|
+
}
|
|
41928
43363
|
}
|
|
41929
43364
|
const Limbo = new LimboCore();
|
|
41930
43365
|
if (typeof window !== "undefined") {
|