allaw-ui 5.1.3 → 5.1.5

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.
@@ -56,15 +56,29 @@ var FileUploader = function (_a) {
56
56
  var progressIntervalRef = useRef(null);
57
57
  var fileInputRef = useRef(null);
58
58
  var _z = useState(originalFileName), currentFileName = _z[0], setCurrentFileName = _z[1];
59
+ // Garder une référence à l'image originale pour permettre les recrops
60
+ var originalImageUrlRef = useRef(null);
61
+ var originalFileRef = useRef(null);
59
62
  useEffect(function () {
60
63
  if (initialFile) {
61
64
  setSelectedFile(initialFile);
65
+ originalFileRef.current = initialFile;
62
66
  initialFile.arrayBuffer().then(function (content) {
63
67
  setFileContent(content);
64
68
  });
69
+ // Créer une URL pour l'image originale si c'est une image
70
+ if (isImageFile(initialFile) && !originalImageUrlRef.current) {
71
+ var url = URL.createObjectURL(initialFile);
72
+ originalImageUrlRef.current = url;
73
+ }
65
74
  }
66
75
  if (initialPreviewUrl) {
67
76
  setPreviewUrl(initialPreviewUrl);
77
+ // Pour initialPreviewUrl, on ne peut pas créer de File depuis l'URL
78
+ // originalFileRef restera null, mais on peut utiliser l'URL pour le crop
79
+ if (!originalImageUrlRef.current) {
80
+ originalImageUrlRef.current = initialPreviewUrl;
81
+ }
68
82
  }
69
83
  if (initialCropMetadata) {
70
84
  setCropMetadata(initialCropMetadata);
@@ -78,6 +92,10 @@ var FileUploader = function (_a) {
78
92
  if (previewUrl && !initialPreviewUrl) {
79
93
  URL.revokeObjectURL(previewUrl);
80
94
  }
95
+ // Nettoyer aussi la référence à l'image originale
96
+ if (originalImageUrlRef.current && !initialPreviewUrl) {
97
+ URL.revokeObjectURL(originalImageUrlRef.current);
98
+ }
81
99
  };
82
100
  }, [previewUrl, initialPreviewUrl]);
83
101
  var startProgressSimulation = function () {
@@ -169,6 +187,12 @@ var FileUploader = function (_a) {
169
187
  if (isImageFile(file)) {
170
188
  url = URL.createObjectURL(file);
171
189
  setPreviewUrl(url);
190
+ // Conserver la référence à l'image originale pour les recrops
191
+ if (originalImageUrlRef.current && !initialPreviewUrl) {
192
+ URL.revokeObjectURL(originalImageUrlRef.current);
193
+ }
194
+ originalImageUrlRef.current = url;
195
+ originalFileRef.current = file;
172
196
  if (!enableCropping) {
173
197
  setCropMetadata({
174
198
  zoom: 1,
@@ -181,6 +205,10 @@ var FileUploader = function (_a) {
181
205
  else {
182
206
  setPreviewUrl(null);
183
207
  setCropMetadata(null);
208
+ if (originalImageUrlRef.current && !initialPreviewUrl) {
209
+ URL.revokeObjectURL(originalImageUrlRef.current);
210
+ }
211
+ originalImageUrlRef.current = null;
184
212
  }
185
213
  if (autoManageProgress && !(enableCropping && isImageFile(file))) {
186
214
  startProgressSimulation();
@@ -207,9 +235,28 @@ var FileUploader = function (_a) {
207
235
  });
208
236
  }); };
209
237
  var openCropModal = function () {
210
- if (selectedFile && isImageFile(selectedFile)) {
238
+ var _a, _b;
239
+ // Si on a un fichier original, ouvrir le modal de crop pour recropper
240
+ // Sinon, si on n'a pas de fichier original (image déjà croppée), ouvrir le sélecteur de fichier
241
+ if (originalFileRef.current && isImageFile(originalFileRef.current)) {
242
+ // S'assurer qu'on a une URL pour l'image originale
243
+ if (!originalImageUrlRef.current) {
244
+ var url = URL.createObjectURL(originalFileRef.current);
245
+ originalImageUrlRef.current = url;
246
+ }
247
+ // Utiliser le fichier original pour le modal de crop
248
+ setSelectedFile(originalFileRef.current);
211
249
  setShowCropper(true);
212
250
  }
251
+ else if (selectedFile && isImageFile(selectedFile)) {
252
+ // Si on a un selectedFile mais pas d'original, c'est probablement une image déjà croppée
253
+ // Ouvrir le sélecteur de fichier pour charger une nouvelle image
254
+ (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
255
+ }
256
+ else {
257
+ // Pas de fichier, ouvrir le sélecteur
258
+ (_b = fileInputRef.current) === null || _b === void 0 ? void 0 : _b.click();
259
+ }
213
260
  };
214
261
  /**
215
262
  * Crop l'image côté client et retourne un Blob
@@ -239,35 +286,45 @@ var FileUploader = function (_a) {
239
286
  cropAreaWidth = 320;
240
287
  cropAreaHeight = 60;
241
288
  }
242
- // Le zoom dans cropMetadata est déjà le zoom total (baseZoom * zoom relatif)
243
- // Comme calculé dans ImageCropperModal ligne 318: zoom: baseZoom * zoom
289
+ // Le zoom dans cropMetadata est le zoom total (baseZoom * zoom relatif)
290
+ // baseZoom est calculé dans le modal comme Math.max(cropWidth / imgWidth, cropHeight / imgHeight)
291
+ // puis multiplié par le zoom relatif (1-3) pour obtenir le zoom total
244
292
  var totalZoom = cropMetadata.zoom;
245
- // Dimensions de l'image après zoom
246
- var scaledImgWidth = img.width * totalZoom;
247
- var scaledImgHeight = img.height * totalZoom;
248
- // Dans le modal, l'image est centrée dans le container
249
- // Le container a les mêmes dimensions que le viewport du modal
250
- // La cropArea est centrée dans ce container
251
- // Les offsets (offsetX, offsetY) représentent le déplacement de l'image depuis le centre
252
- // Position du centre de l'image zoomée (qui correspond au centre du container)
253
- var imgCenterX = scaledImgWidth / 2;
254
- var imgCenterY = scaledImgHeight / 2;
255
- // Position du centre de la cropArea dans l'image zoomée
256
- // Les offsets sont la position de l'image par rapport au centre du container
257
- // Donc le centre de la cropArea dans l'image zoomée est :
258
- var cropCenterX = imgCenterX - cropMetadata.offsetX;
259
- var cropCenterY = imgCenterY - cropMetadata.offsetY;
260
- // Coordonnées du coin supérieur gauche de la zone à cropper dans l'image zoomée
261
- var cropXInScaledImg = cropCenterX - cropAreaWidth / 2;
262
- var cropYInScaledImg = cropCenterY - cropAreaHeight / 2;
263
- // Convertir ces coordonnées en coordonnées de l'image originale (diviser par le zoom)
264
- var sourceX = cropXInScaledImg / totalZoom;
265
- var sourceY = cropYInScaledImg / totalZoom;
266
- var sourceWidth = cropAreaWidth / totalZoom;
267
- var sourceHeight = cropAreaHeight / totalZoom;
268
- // S'assurer que les coordonnées sont valides
269
- var clampedSourceX = Math.max(0, Math.min(sourceX, img.width - sourceWidth));
270
- var clampedSourceY = Math.max(0, Math.min(sourceY, img.height - sourceHeight));
293
+ // Dans le modal, la transform CSS est appliquée sur le container de l'image :
294
+ // transform: translate(offsetX, offsetY) scale(totalZoom)
295
+ // transform-origin: center
296
+ //
297
+ // L'ordre d'application est : scale d'abord (depuis le centre), puis translate
298
+ // Géométriquement, cela signifie :
299
+ // 1. L'image est agrandie avec scale(totalZoom) depuis son centre
300
+ // 2. L'image agrandie est déplacée de (offsetX, offsetY)
301
+ //
302
+ // La cropArea est fixe et centrée dans le container
303
+ // Pour trouver quelle partie de l'image originale correspond à la cropArea :
304
+ // - Le centre de la cropArea correspond au point (0, 0) dans le système de coordonnées du container
305
+ // - Ce point (0, 0) dans l'image transformée correspond à (-offsetX, -offsetY) dans l'image agrandie
306
+ // - Ce point dans l'image agrandie correspond à (-offsetX/totalZoom, -offsetY/totalZoom) dans l'image originale
307
+ // Centre de l'image originale
308
+ var imgCenterX = img.width / 2;
309
+ var imgCenterY = img.height / 2;
310
+ // Position du centre de la cropArea dans l'image originale
311
+ // Si l'image transformée est déplacée de offsetX vers la droite,
312
+ // alors le centre de la cropArea (qui reste au centre du container)
313
+ // correspond à un point qui est offsetX pixels à gauche du centre de l'image transformée
314
+ // Converti en coordonnées de l'image originale :
315
+ var cropCenterXInOriginal = imgCenterX - cropMetadata.offsetX / totalZoom;
316
+ var cropCenterYInOriginal = imgCenterY - cropMetadata.offsetY / totalZoom;
317
+ // Dimensions de la zone de crop dans l'image originale
318
+ var cropWidthInOriginal = cropAreaWidth / totalZoom;
319
+ var cropHeightInOriginal = cropAreaHeight / totalZoom;
320
+ // Coordonnées du coin supérieur gauche de la zone à cropper dans l'image originale
321
+ var sourceX = cropCenterXInOriginal - cropWidthInOriginal / 2;
322
+ var sourceY = cropCenterYInOriginal - cropHeightInOriginal / 2;
323
+ var sourceWidth = cropWidthInOriginal;
324
+ var sourceHeight = cropHeightInOriginal;
325
+ // S'assurer que les coordonnées sont valides (pas en dehors de l'image)
326
+ var clampedSourceX = Math.max(0, Math.min(sourceX, img.width - 1));
327
+ var clampedSourceY = Math.max(0, Math.min(sourceY, img.height - 1));
271
328
  var clampedSourceWidth = Math.min(sourceWidth, img.width - clampedSourceX);
272
329
  var clampedSourceHeight = Math.min(sourceHeight, img.height - clampedSourceY);
273
330
  // Dessiner l'image croppée sur le canvas
@@ -315,7 +372,7 @@ var FileUploader = function (_a) {
315
372
  setShowCropper(false);
316
373
  };
317
374
  var handleCropConfirm = function (cropMetadata) { return __awaiter(void 0, void 0, void 0, function () {
318
- var dimensions, croppedBlob, croppedFile, croppedContent, croppedUrl, error_2;
375
+ var dimensions, imageToCrop, croppedBlob, croppedFile, croppedContent, croppedUrl, error_2;
319
376
  return __generator(this, function (_a) {
320
377
  switch (_a.label) {
321
378
  case 0:
@@ -330,9 +387,9 @@ var FileUploader = function (_a) {
330
387
  case 1:
331
388
  _a.trys.push([1, 4, , 5]);
332
389
  dimensions = cropOutputDimensions[cropMetadata.shape] ||
333
- cropOutputDimensions.square ||
334
- { width: 200, height: 200 };
335
- return [4 /*yield*/, cropImageToBlob(previewUrl, cropMetadata, dimensions.width, dimensions.height)];
390
+ cropOutputDimensions.square || { width: 200, height: 200 };
391
+ imageToCrop = originalImageUrlRef.current || previewUrl;
392
+ return [4 /*yield*/, cropImageToBlob(imageToCrop, cropMetadata, dimensions.width, dimensions.height)];
336
393
  case 2:
337
394
  croppedBlob = _a.sent();
338
395
  croppedFile = new File([croppedBlob], selectedFile.name.replace(/\.[^/.]+$/, ".png"), // Remplacer l'extension par .png
@@ -348,6 +405,9 @@ var FileUploader = function (_a) {
348
405
  setSelectedFile(croppedFile);
349
406
  setFileContent(croppedContent);
350
407
  setCurrentFileName(croppedFile.name);
408
+ // Réinitialiser cropMetadata car l'image est déjà croppée
409
+ // Plus besoin d'appliquer les transformations CSS
410
+ setCropMetadata(null);
351
411
  // Appeler onFileRead avec le fichier croppé (pas de cropMetadata car déjà croppé)
352
412
  onFileRead === null || onFileRead === void 0 ? void 0 : onFileRead(croppedFile, croppedContent);
353
413
  return [3 /*break*/, 5];
@@ -370,6 +430,12 @@ var FileUploader = function (_a) {
370
430
  if (previewUrl && !initialPreviewUrl) {
371
431
  URL.revokeObjectURL(previewUrl);
372
432
  }
433
+ // Nettoyer la référence à l'image originale
434
+ if (originalImageUrlRef.current && !initialPreviewUrl) {
435
+ URL.revokeObjectURL(originalImageUrlRef.current);
436
+ }
437
+ originalImageUrlRef.current = null;
438
+ originalFileRef.current = null;
373
439
  if (autoManageProgress) {
374
440
  stopProgressSimulation();
375
441
  setInternalProgress(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allaw-ui",
3
- "version": "5.1.3",
3
+ "version": "5.1.5",
4
4
  "description": "Composants UI pour l'application Allaw",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",