allaw-ui 5.2.5 → 5.2.7

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.
@@ -264,16 +264,10 @@ var FileUploader = function (_a) {
264
264
  */
265
265
  var cropImageToBlob = function (imageUrl, cropMetadata, outputWidth, outputHeight) { return __awaiter(void 0, void 0, void 0, function () {
266
266
  return __generator(this, function (_a) {
267
- console.log("🔪 [FileUploader] cropImageToBlob appelé");
268
- console.log(" - imageUrl:", imageUrl);
269
- console.log(" - cropMetadata:", cropMetadata);
270
- console.log(" - outputWidth:", outputWidth, "outputHeight:", outputHeight);
271
267
  return [2 /*return*/, new Promise(function (resolve, reject) {
272
268
  var img = new window.Image();
273
269
  img.crossOrigin = "anonymous";
274
270
  img.onload = function () {
275
- console.log("✅ [FileUploader] Image chargée dans cropImageToBlob");
276
- console.log(" - img.width:", img.width, "img.height:", img.height);
277
271
  try {
278
272
  // Créer un canvas aux dimensions de sortie
279
273
  var canvas = document.createElement("canvas");
@@ -284,18 +278,32 @@ var FileUploader = function (_a) {
284
278
  reject(new Error("Impossible de créer le contexte canvas"));
285
279
  return;
286
280
  }
287
- // Dimensions de la zone de crop dans le modal (selon le CSS)
288
- // Ces dimensions correspondent exactement à celles utilisées dans ImageCropperModal.module.css
289
- var cropAreaWidth = 280; // Dimensions réelles du cadre de crop pour square/circle
290
- var cropAreaHeight = 280;
291
- if (cropMetadata.shape === "banner") {
292
- cropAreaWidth = 360;
293
- cropAreaHeight = 120;
281
+ // Dimensions de la zone de crop dans le modal
282
+ // Utiliser les dimensions réelles si disponibles dans les métadonnées,
283
+ // sinon utiliser les valeurs par défaut du CSS
284
+ var cropAreaWidth = cropMetadata.cropWidth || 280; // Dimensions réelles du cadre de crop
285
+ var cropAreaHeight = cropMetadata.cropHeight || 280;
286
+ // Si les dimensions ne sont pas dans les métadonnées, utiliser les valeurs par défaut selon la shape
287
+ if (!cropMetadata.cropWidth || !cropMetadata.cropHeight) {
288
+ if (cropMetadata.shape === "banner") {
289
+ cropAreaWidth = 360;
290
+ cropAreaHeight = 120;
291
+ }
292
+ else {
293
+ cropAreaWidth = 280;
294
+ cropAreaHeight = 280;
295
+ }
294
296
  }
295
- // Le zoom dans cropMetadata est le zoom total (baseZoom * zoom relatif)
296
- // baseZoom est calculé dans le modal comme Math.max(cropWidth / imgWidth, cropHeight / imgHeight)
297
+ // Le zoom dans cropMetadata est le zoom total (baseZoom * zoom relatif * marge)
298
+ // baseZoom est calculé dans le modal comme Math.max(cropWidth / imgWidth, cropHeight / imgHeight) * 1.01
297
299
  // puis multiplié par le zoom relatif (1-3) pour obtenir le zoom total
298
300
  var totalZoom = cropMetadata.zoom;
301
+ // S'assurer que le zoom est valide (éviter division par zéro ou valeurs négatives)
302
+ if (totalZoom <= 0 || !isFinite(totalZoom)) {
303
+ console.error("❌ [FileUploader] Zoom invalide:", totalZoom);
304
+ reject(new Error("Zoom invalide"));
305
+ return;
306
+ }
299
307
  // Dans le modal, la transform CSS est appliquée sur le container de l'image :
300
308
  // transform: translate(offsetX, offsetY) scale(totalZoom)
301
309
  // transform-origin: center
@@ -323,16 +331,23 @@ var FileUploader = function (_a) {
323
331
  // Dimensions de la zone de crop dans l'image originale
324
332
  var cropWidthInOriginal = cropAreaWidth / totalZoom;
325
333
  var cropHeightInOriginal = cropAreaHeight / totalZoom;
334
+ // S'assurer que les dimensions calculées sont valides (éviter les valeurs négatives ou nulles)
335
+ if (cropWidthInOriginal <= 0 || cropHeightInOriginal <= 0) {
336
+ console.error("❌ [FileUploader] Dimensions de crop invalides:", cropWidthInOriginal, cropHeightInOriginal);
337
+ reject(new Error("Dimensions de crop invalides: ".concat(cropWidthInOriginal, "x").concat(cropHeightInOriginal)));
338
+ return;
339
+ }
326
340
  // Coordonnées du coin supérieur gauche de la zone à cropper dans l'image originale
327
341
  var sourceX = cropCenterXInOriginal - cropWidthInOriginal / 2;
328
342
  var sourceY = cropCenterYInOriginal - cropHeightInOriginal / 2;
329
343
  var sourceWidth = cropWidthInOriginal;
330
344
  var sourceHeight = cropHeightInOriginal;
331
345
  // S'assurer que les coordonnées sont valides (pas en dehors de l'image)
332
- var clampedSourceX = Math.max(0, Math.min(sourceX, img.width - 1));
333
- var clampedSourceY = Math.max(0, Math.min(sourceY, img.height - 1));
334
- var clampedSourceWidth = Math.min(sourceWidth, img.width - clampedSourceX);
335
- var clampedSourceHeight = Math.min(sourceHeight, img.height - clampedSourceY);
346
+ // Utiliser Math.floor pour éviter les problèmes de précision avec les pixels
347
+ var clampedSourceX = Math.max(0, Math.min(Math.floor(sourceX), img.width - 1));
348
+ var clampedSourceY = Math.max(0, Math.min(Math.floor(sourceY), img.height - 1));
349
+ var clampedSourceWidth = Math.max(1, Math.min(Math.ceil(sourceWidth), img.width - clampedSourceX));
350
+ var clampedSourceHeight = Math.max(1, Math.min(Math.ceil(sourceHeight), img.height - clampedSourceY));
336
351
  // Dessiner l'image croppée sur le canvas
337
352
  ctx.drawImage(img, clampedSourceX, clampedSourceY, clampedSourceWidth, clampedSourceHeight, 0, 0, outputWidth, outputHeight);
338
353
  // Si c'est un cercle, appliquer un masque
@@ -354,10 +369,8 @@ var FileUploader = function (_a) {
354
369
  ctx.putImageData(imageData, 0, 0);
355
370
  }
356
371
  // Convertir en Blob PNG
357
- console.log("🖼️ [FileUploader] Conversion canvas vers Blob...");
358
372
  canvas.toBlob(function (blob) {
359
373
  if (blob) {
360
- console.log("✅ [FileUploader] Blob créé avec succès, taille:", blob.size);
361
374
  resolve(blob);
362
375
  }
363
376
  else {
@@ -371,13 +384,10 @@ var FileUploader = function (_a) {
371
384
  reject(error);
372
385
  }
373
386
  };
374
- img.onerror = function (error) {
387
+ img.onerror = function () {
375
388
  console.error("❌ [FileUploader] Erreur de chargement de l'image");
376
- console.error(" - imageUrl:", imageUrl);
377
- console.error(" - error:", error);
378
389
  reject(new Error("Échec du chargement de l'image"));
379
390
  };
380
- console.log("📤 [FileUploader] Définition de img.src:", imageUrl);
381
391
  img.src = imageUrl;
382
392
  })];
383
393
  });
@@ -387,17 +397,9 @@ var FileUploader = function (_a) {
387
397
  };
388
398
  var handleCropConfirm = function (cropMetadata) { return __awaiter(void 0, void 0, void 0, function () {
389
399
  var dimensions, fileToUse, imageToCropUrl, croppedBlob, croppedFile, croppedContent, croppedUrl, error_2;
390
- var _a, _b;
391
- return __generator(this, function (_c) {
392
- switch (_c.label) {
400
+ return __generator(this, function (_a) {
401
+ switch (_a.label) {
393
402
  case 0:
394
- console.log("✂️ [FileUploader] handleCropConfirm appelé");
395
- console.log(" - cropMetadata:", cropMetadata);
396
- console.log(" - clientSideCrop:", clientSideCrop);
397
- console.log(" - selectedFile:", selectedFile === null || selectedFile === void 0 ? void 0 : selectedFile.name, "size:", selectedFile === null || selectedFile === void 0 ? void 0 : selectedFile.size);
398
- console.log(" - originalFileRef.current:", (_a = originalFileRef.current) === null || _a === void 0 ? void 0 : _a.name, "size:", (_b = originalFileRef.current) === null || _b === void 0 ? void 0 : _b.size);
399
- console.log(" - originalImageUrlRef.current:", originalImageUrlRef.current);
400
- console.log(" - previewUrl:", previewUrl);
401
403
  setShowCropper(false);
402
404
  setCropMetadata(cropMetadata);
403
405
  if (autoManageProgress) {
@@ -405,36 +407,26 @@ var FileUploader = function (_a) {
405
407
  }
406
408
  if (!(selectedFile && fileContent)) return [3 /*break*/, 10];
407
409
  if (!clientSideCrop) return [3 /*break*/, 9];
408
- _c.label = 1;
410
+ _a.label = 1;
409
411
  case 1:
410
- _c.trys.push([1, 7, , 8]);
412
+ _a.trys.push([1, 7, , 8]);
411
413
  dimensions = cropOutputDimensions[cropMetadata.shape] ||
412
414
  cropOutputDimensions.square || { width: 200, height: 200 };
413
- console.log("📐 [FileUploader] Dimensions de sortie:", dimensions);
414
415
  fileToUse = originalFileRef.current || selectedFile;
415
- console.log("📁 [FileUploader] Fichier à utiliser pour le crop:", fileToUse.name, "size:", fileToUse.size, "type:", fileToUse.type);
416
416
  imageToCropUrl = URL.createObjectURL(fileToUse);
417
- console.log("🔗 [FileUploader] URL blob créée pour le crop:", imageToCropUrl);
418
- _c.label = 2;
417
+ _a.label = 2;
419
418
  case 2:
420
- _c.trys.push([2, , 5, 6]);
421
- // Cropper l'image côté client
422
- console.log("🔄 [FileUploader] Appel de cropImageToBlob...");
419
+ _a.trys.push([2, , 5, 6]);
423
420
  return [4 /*yield*/, cropImageToBlob(imageToCropUrl, cropMetadata, dimensions.width, dimensions.height)];
424
421
  case 3:
425
- croppedBlob = _c.sent();
426
- console.log("✅ [FileUploader] cropImageToBlob terminé, blob size:", croppedBlob.size);
422
+ croppedBlob = _a.sent();
427
423
  croppedFile = new File([croppedBlob], fileToUse.name.replace(/\.[^/.]+$/, ".png"), // Remplacer l'extension par .png
428
424
  { type: "image/png" });
429
- console.log("📄 [FileUploader] File croppé créé:", croppedFile.name, "size:", croppedFile.size);
430
425
  return [4 /*yield*/, croppedFile.arrayBuffer()];
431
426
  case 4:
432
- croppedContent = _c.sent();
433
- console.log("📦 [FileUploader] Contenu du fichier croppé lu, size:", croppedContent.byteLength);
427
+ croppedContent = _a.sent();
434
428
  croppedUrl = URL.createObjectURL(croppedBlob);
435
- console.log("🖼️ [FileUploader] URL blob créée pour la preview:", croppedUrl);
436
429
  if (previewUrl && !initialPreviewUrl) {
437
- console.log("🗑️ [FileUploader] Révoquement de l'ancienne previewUrl:", previewUrl);
438
430
  URL.revokeObjectURL(previewUrl);
439
431
  }
440
432
  setPreviewUrl(croppedUrl);
@@ -445,28 +437,24 @@ var FileUploader = function (_a) {
445
437
  // Plus besoin d'appliquer les transformations CSS
446
438
  setCropMetadata(null);
447
439
  // Appeler onFileRead avec le fichier croppé (pas de cropMetadata car déjà croppé)
448
- console.log("📞 [FileUploader] Appel de onFileRead avec le fichier croppé");
449
440
  onFileRead === null || onFileRead === void 0 ? void 0 : onFileRead(croppedFile, croppedContent);
450
441
  return [3 /*break*/, 6];
451
442
  case 5:
452
443
  // Toujours nettoyer l'URL blob temporaire créée pour le crop
453
- console.log("🗑️ [FileUploader] Révoquement de l'URL blob temporaire:", imageToCropUrl);
454
444
  URL.revokeObjectURL(imageToCropUrl);
455
445
  return [7 /*endfinally*/];
456
446
  case 6: return [3 /*break*/, 8];
457
447
  case 7:
458
- error_2 = _c.sent();
448
+ error_2 = _a.sent();
459
449
  console.error("❌ [FileUploader] Erreur lors du crop de l'image:", error_2);
460
- console.error(" - error details:", error_2);
461
450
  // En cas d'erreur, fallback sur l'image originale avec métadonnées
462
- console.log("🔄 [FileUploader] Fallback sur l'image originale");
463
451
  onFileRead === null || onFileRead === void 0 ? void 0 : onFileRead(selectedFile, fileContent, cropMetadata);
464
452
  return [3 /*break*/, 8];
465
453
  case 8: return [3 /*break*/, 10];
466
454
  case 9:
467
455
  // Passer l'image originale avec les métadonnées au serveur
468
456
  onFileRead === null || onFileRead === void 0 ? void 0 : onFileRead(selectedFile, fileContent, cropMetadata);
469
- _c.label = 10;
457
+ _a.label = 10;
470
458
  case 10: return [2 /*return*/];
471
459
  }
472
460
  });
@@ -4,6 +4,8 @@ export interface CropMetadata {
4
4
  offsetX: number;
5
5
  offsetY: number;
6
6
  shape: "circle" | "square" | "banner";
7
+ cropWidth?: number;
8
+ cropHeight?: number;
7
9
  }
8
10
  interface ImageCropperModalProps {
9
11
  file: File;
@@ -29,7 +29,10 @@ var ImageCropperModal = function (_a) {
29
29
  // Calcul du zoom pour que l'image couvre complètement le cadre
30
30
  // On utilise max pour assurer que l'image couvre tout le cadre, sans espace vide
31
31
  var fitZoom = Math.max(cropWidth / imgWidth, cropHeight / imgHeight);
32
- return fitZoom;
32
+ // Ajouter une marge minimale (1%) pour éviter les problèmes de précision
33
+ // quand le zoom est exactement à 1, garantissant toujours un peu d'espace pour ajuster
34
+ var MIN_ZOOM_MARGIN = 1.01;
35
+ return fitZoom * MIN_ZOOM_MARGIN;
33
36
  };
34
37
  // Calcule les limites de déplacement pour éviter les zones vides
35
38
  var calculateBoundaries = function () {
@@ -200,12 +203,19 @@ var ImageCropperModal = function (_a) {
200
203
  React.createElement("div", { className: styles.action_buttons },
201
204
  React.createElement("button", { className: styles.cancel_button, onClick: onCancel }, "Annuler"),
202
205
  React.createElement("button", { className: styles.confirm_button, onClick: function () {
203
- // Retourner les métadonnées de cadrage avec le zoom total
206
+ var _a;
207
+ // Récupérer les dimensions réelles du cadre de crop
208
+ var cropRect = (_a = cropAreaRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
209
+ var cropWidth = (cropRect === null || cropRect === void 0 ? void 0 : cropRect.width) || 280;
210
+ var cropHeight = (cropRect === null || cropRect === void 0 ? void 0 : cropRect.height) || 280;
211
+ // Retourner les métadonnées de cadrage avec le zoom total et les dimensions réelles
204
212
  onConfirm({
205
213
  zoom: baseZoom * zoom,
206
214
  offsetX: position.x,
207
215
  offsetY: position.y,
208
216
  shape: shape,
217
+ cropWidth: cropWidth,
218
+ cropHeight: cropHeight,
209
219
  });
210
220
  } }, "Valider"))))));
211
221
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allaw-ui",
3
- "version": "5.2.5",
3
+ "version": "5.2.7",
4
4
  "description": "Composants UI pour l'application Allaw",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",