@bebranded/bb-contents 1.0.104 → 1.0.106

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.
Files changed (2) hide show
  1. package/bb-contents.js +62 -114
  2. package/package.json +1 -1
package/bb-contents.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * BeBranded Contents
3
3
  * Contenus additionnels français pour Webflow
4
- * @version 1.0.104
4
+ * @version 1.0.106
5
5
  * @author BeBranded
6
6
  * @license MIT
7
7
  * @website https://www.bebranded.xyz
@@ -32,11 +32,11 @@
32
32
  window._bbContentsInitialized = true;
33
33
 
34
34
  // Log de démarrage simple (une seule fois)
35
- console.log('bb-contents | v1.0.104');
35
+ console.log('bb-contents | v1.0.106');
36
36
 
37
37
  // Configuration
38
38
  const config = {
39
- version: '1.0.104',
39
+ version: '1.0.106',
40
40
  debug: false, // Debug désactivé pour rendu propre
41
41
  prefix: 'bb-', // utilisé pour générer les sélecteurs (data-bb-*)
42
42
  youtubeEndpoint: null, // URL du worker YouTube (à définir par l'utilisateur)
@@ -320,9 +320,13 @@
320
320
  ${isVertical ? 'min-height: 100px;' : ''}
321
321
  `;
322
322
 
323
- // Ne créer que le mainBlock pour l'instant
324
- // Les copies seront créées après le chargement des images
323
+ // Créer 3 copies pour le défilement infini
324
+ const repeatBlock1 = mainBlock.cloneNode(true);
325
+ const repeatBlock2 = mainBlock.cloneNode(true);
326
+
325
327
  scrollContainer.appendChild(mainBlock);
328
+ scrollContainer.appendChild(repeatBlock1);
329
+ scrollContainer.appendChild(repeatBlock2);
326
330
  mainContainer.appendChild(scrollContainer);
327
331
 
328
332
  element.innerHTML = '';
@@ -387,117 +391,67 @@
387
391
  const totalImages = images.length;
388
392
 
389
393
 
390
- // SOLUTION MOBILE : Amélioration du rendu des images sur mobile
391
- const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) ||
392
- (window.innerWidth <= 768 && /Chrome|CriOS/i.test(navigator.userAgent));
393
-
394
- // SOLUTION MOBILE : Charger toutes les images AVANT de créer les copies pour éviter le flou
395
- const loadImage = (img) => {
396
- return new Promise((resolve) => {
397
- // Vérifier que l'image est complètement chargée avec dimensions naturelles
398
- if (img.complete && img.naturalWidth > 0 && img.naturalHeight > 0) {
399
- // Image déjà chargée, vérifier le rendu avec un reflow
400
- void img.offsetHeight;
401
- imagesLoaded++;
402
- resolve();
403
- return;
394
+ // OPTIMISATION: Charger les images sans forcer les dimensions
395
+ images.forEach(img => {
396
+ if (img.dataset.src && !img.src) {
397
+ img.src = img.dataset.src;
398
+ img.loading = 'eager';
399
+ }
400
+
401
+ // OPTIMISATION: Préserver les styles CSS existants (object-fit, etc.)
402
+ const originalObjectFit = img.style.objectFit || getComputedStyle(img).objectFit;
403
+ const originalObjectPosition = img.style.objectPosition || getComputedStyle(img).objectPosition;
404
+ const originalWidth = img.style.width;
405
+ const originalHeight = img.style.height;
406
+
407
+ img.onload = () => {
408
+ // OPTIMISATION: Restaurer les styles CSS après chargement
409
+ if (originalObjectFit && originalObjectFit !== 'none') {
410
+ img.style.objectFit = originalObjectFit;
404
411
  }
405
-
406
- if (img.dataset.src && !img.src) {
407
- img.src = img.dataset.src;
412
+ if (originalObjectPosition && originalObjectPosition !== 'initial') {
413
+ img.style.objectPosition = originalObjectPosition;
408
414
  }
409
415
 
410
- // Utiliser eager sur mobile pour éviter le flou de lazy loading
411
- if (!img.loading && isMobile) {
412
- img.loading = 'eager';
416
+ // OPTIMISATION: Préserver les dimensions naturelles des images
417
+ if (!originalWidth || originalWidth === '') {
418
+ img.style.width = 'auto';
419
+ }
420
+ if (!originalHeight || originalHeight === '') {
421
+ img.style.height = 'auto';
413
422
  }
414
423
 
415
- img.onload = () => {
416
- // Vérifier que les dimensions naturelles sont disponibles
417
- if (img.naturalWidth > 0 && img.naturalHeight > 0) {
418
- // Forcer un reflow complet pour s'assurer que l'image est rendue
419
- void img.offsetHeight;
420
- void img.offsetWidth;
421
- // Double reflow pour mobile (surtout Retina)
422
- if (isMobile) {
423
- requestAnimationFrame(() => {
424
- void img.offsetHeight;
425
- imagesLoaded++;
426
- resolve();
427
- });
428
- } else {
429
- imagesLoaded++;
430
- resolve();
431
- }
432
- } else {
433
- imagesLoaded++;
434
- resolve();
435
- }
436
- };
437
- img.onerror = () => {
438
- imagesLoaded++;
439
- resolve(); // Résoudre même en cas d'erreur
440
- };
441
- });
442
- };
424
+ imagesLoaded++;
425
+ };
426
+ img.onerror = () => {
427
+ imagesLoaded++;
428
+ };
429
+ });
443
430
 
444
- // Attendre réellement que toutes les images soient chargées
445
- Promise.all(Array.from(images).map(loadImage)).then(() => {
446
- // Vérifier que toutes les images ont leurs dimensions naturelles
447
- let allImagesReady = true;
448
- images.forEach(img => {
449
- if (!img.complete || img.naturalWidth === 0 || img.naturalHeight === 0) {
450
- allImagesReady = false;
451
- }
452
- });
431
+ // SOLUTION SAFARI MOBILE SIMPLE : Attendre plus longtemps
432
+ const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
433
+
434
+ // Timeout plus long sur mobile pour laisser le temps aux images de se charger
435
+ const maxWaitTime = isMobile ? 5000 : 3000; // 5 secondes sur mobile
436
+ let waitTimeout = 0;
437
+
438
+ const waitForImages = () => {
439
+ waitTimeout += 100;
453
440
 
454
- if (allImagesReady || images.length === 0) {
455
- // Attendre plusieurs frames pour garantir le rendu complet, surtout sur mobile
456
- requestAnimationFrame(() => {
457
- requestAnimationFrame(() => {
458
- // Délai supplémentaire sur mobile pour garantir le rendu Retina
459
- const renderDelay = isMobile ? 100 : 0;
460
- setTimeout(() => {
461
- // Forcer un reflow complet du mainBlock avant clonage
462
- void mainBlock.offsetHeight;
463
-
464
- // Maintenant créer les copies avec les images complètement chargées et rendues
465
- const repeatBlock1 = mainBlock.cloneNode(true);
466
- const repeatBlock2 = mainBlock.cloneNode(true);
467
-
468
- // Forcer un reflow après clonage pour garantir le rendu
469
- scrollContainer.appendChild(repeatBlock1);
470
- void repeatBlock1.offsetHeight;
471
- scrollContainer.appendChild(repeatBlock2);
472
- void repeatBlock2.offsetHeight;
473
-
474
- // Démarrer l'animation
475
- startSafariAnimation();
476
- }, renderDelay);
477
- });
478
- });
479
- } else {
480
- // Fallback : attendre un peu plus si certaines images ne sont pas prêtes
441
+ if (imagesLoaded >= totalImages || imagesLoaded === 0 || waitTimeout >= maxWaitTime) {
442
+ // Attendre plus longtemps sur mobile pour le rendu visuel
443
+ const renderDelay = isMobile ? 1000 : 200;
481
444
  setTimeout(() => {
482
- const repeatBlock1 = mainBlock.cloneNode(true);
483
- const repeatBlock2 = mainBlock.cloneNode(true);
484
- scrollContainer.appendChild(repeatBlock1);
485
- scrollContainer.appendChild(repeatBlock2);
486
445
  startSafariAnimation();
487
- }, 500);
446
+ }, renderDelay);
447
+ } else {
448
+ setTimeout(waitForImages, 100);
488
449
  }
489
- }).catch(() => {
490
- // En cas d'erreur, créer les copies quand même
491
- const repeatBlock1 = mainBlock.cloneNode(true);
492
- const repeatBlock2 = mainBlock.cloneNode(true);
493
- scrollContainer.appendChild(repeatBlock1);
494
- scrollContainer.appendChild(repeatBlock2);
495
- startSafariAnimation();
496
- });
450
+ };
451
+
452
+ waitForImages();
497
453
 
498
454
  const startSafariAnimation = () => {
499
- // Vérifier que speed est bien défini et valide
500
- const validSpeed = parseFloat(speed) || 100;
501
455
 
502
456
  // Recalculer la taille après chargement des images
503
457
  const newContentSize = isVertical ? mainBlock.offsetHeight : mainBlock.offsetWidth;
@@ -518,7 +472,7 @@
518
472
 
519
473
  // Solution Safari simplifiée
520
474
  const totalSize = finalContentSize * 3 + gapSize * 2;
521
- const step = (validSpeed * (isVertical ? 1.5 : 0.8)) / 60;
475
+ const step = (parseFloat(speed) * (isVertical ? 1.5 : 0.8)) / 60;
522
476
  let isPaused = false;
523
477
 
524
478
  // Ajuster la taille du conteneur
@@ -536,11 +490,6 @@
536
490
  currentPosition = 0;
537
491
  }
538
492
 
539
- // Désactiver will-change sur mobile après initialisation pour éviter le flou
540
- if (isMobile) {
541
- scrollContainer.style.willChange = 'auto';
542
- }
543
-
544
493
  // Forcer la position initiale pour éviter l'invisibilité
545
494
  const initialTransform = isVertical
546
495
  ? `translate3d(0, ${currentPosition}px, 0)`
@@ -579,11 +528,10 @@
579
528
  requestAnimationFrame(animate);
580
529
  };
581
530
 
582
- // Démarrer l'animation immédiatement (les copies sont déjà créées)
583
- // Utiliser requestAnimationFrame pour garantir le rendu
584
- requestAnimationFrame(() => {
531
+ // Démarrer l'animation avec un petit délai pour Safari
532
+ setTimeout(() => {
585
533
  animate();
586
- });
534
+ }, 50);
587
535
 
588
536
  // Pause au survol pour Safari
589
537
  if (element.getAttribute('bb-marquee-pause') === 'true') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bebranded/bb-contents",
3
- "version": "1.0.104",
3
+ "version": "1.0.106",
4
4
  "description": "Contenus additionnels français pour Webflow",
5
5
  "main": "bb-contents.js",
6
6
  "scripts": {