canvasframework 0.5.13 → 0.5.15

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.
@@ -354,15 +354,18 @@ class QRCodeReader extends Component {
354
354
 
355
355
  // Fond semi-transparent autour
356
356
  ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
357
-
357
+
358
358
  // Haut
359
- ctx.fillRect(this.x, this.y, this.width, centerY - halfSize);
359
+ ctx.fillRect(this.x, this.y, this.width, centerY - this.y - halfSize);
360
+
360
361
  // Bas
361
- ctx.fillRect(this.x, centerY + halfSize, this.width, this.height - (centerY + halfSize));
362
+ ctx.fillRect(this.x, centerY + halfSize, this.width, this.y + this.height - (centerY + halfSize));
363
+
362
364
  // Gauche
363
- ctx.fillRect(this.x, centerY - halfSize, centerX - halfSize, frameSize);
365
+ ctx.fillRect(this.x, centerY - halfSize, centerX - this.x - halfSize, frameSize);
366
+
364
367
  // Droite
365
- ctx.fillRect(centerX + halfSize, centerY - halfSize, centerX - halfSize, frameSize);
368
+ ctx.fillRect(centerX + halfSize, centerY - halfSize, this.x + this.width - (centerX + halfSize), frameSize);
366
369
 
367
370
  // Cadre de scan
368
371
  ctx.strokeStyle = this.scannerFrameColor;
@@ -371,7 +374,7 @@ class QRCodeReader extends Component {
371
374
 
372
375
  // Coins décoratifs
373
376
  const cornerSize = 20;
374
-
377
+
375
378
  // Coin haut gauche
376
379
  ctx.beginPath();
377
380
  ctx.moveTo(centerX - halfSize, centerY - halfSize + cornerSize);
@@ -1781,189 +1781,120 @@ class CanvasFramework {
1781
1781
  * @private
1782
1782
  */
1783
1783
  async navigateTo(path, options = {}) {
1784
-
1785
- const {
1786
- replace = false,
1787
- animate = true,
1788
- direction = 'forward',
1789
- transition = null,
1790
- state = {}
1791
- } = options;
1792
-
1793
- const match = this.matchRoute(path);
1794
- if (!match) {
1795
- console.warn(`Route not found: ${path}`);
1796
- return;
1797
- }
1798
-
1799
- const {
1800
- route,
1801
- params,
1802
- query,
1803
- pathname
1804
- } = match;
1805
-
1806
- // ===== LIFECYCLE: AVANT DE QUITTER L'ANCIENNE ROUTE =====
1807
-
1808
- // Hook beforeLeave de la route actuelle (peut bloquer la navigation)
1809
- const currentRouteData = this.routes.get(this.currentRoute);
1810
- if (currentRouteData?.beforeLeave) {
1811
- const canLeave = await currentRouteData.beforeLeave(this.currentParams, this.currentQuery, this);
1812
- if (canLeave === false) {
1813
- console.log('Navigation cancelled by beforeLeave hook');
1814
- return;
1815
- }
1816
- }
1817
-
1818
- // ✅ NOUVEAU : Hook onLeave (alias plus intuitif de beforeLeave, mais ne bloque pas)
1819
- if (currentRouteData?.onLeave) {
1820
- await currentRouteData.onLeave(this.currentParams, this.currentQuery, this);
1821
- }
1822
-
1823
- // ===== LIFECYCLE: AVANT D'ENTRER DANS LA NOUVELLE ROUTE =====
1824
-
1825
- // Hook beforeEnter de la nouvelle route (peut bloquer la navigation)
1826
- if (route.beforeEnter) {
1827
- const canEnter = await route.beforeEnter(params, query, this);
1828
- if (canEnter === false) {
1829
- console.log('Navigation cancelled by beforeEnter hook');
1830
- return;
1831
- }
1832
- }
1833
-
1834
- // ✅ NOUVEAU : Hook onEnter (appelé juste avant de créer les composants)
1835
- if (route.onEnter) {
1836
- await route.onEnter(params, query, this);
1837
- }
1838
-
1839
- // ===== SAUVEGARDER L'ÉTAT ACTUEL =====
1840
-
1841
- // Sauvegarder l'ancienne route pour l'animation et les hooks
1842
- const oldComponents = [...this.components];
1843
- const oldRoute = this.currentRoute;
1844
- const oldParams = {
1845
- ...this.currentParams
1846
- };
1847
- const oldQuery = {
1848
- ...this.currentQuery
1849
- };
1850
-
1851
- // ===== METTRE À JOUR L'ÉTAT =====
1852
-
1853
- this.currentRoute = pathname;
1854
- this.currentParams = params;
1855
- this.currentQuery = query;
1856
-
1857
- // ===== GÉRER L'HISTORIQUE =====
1858
-
1859
- if (!replace) {
1860
- this.historyIndex++;
1861
- this.history = this.history.slice(0, this.historyIndex);
1862
- this.history.push({
1863
- path,
1864
- params,
1865
- query,
1866
- state
1867
- });
1868
-
1869
- // Mettre à jour l'historique du navigateur
1870
- window.history.pushState({
1871
- route: path,
1872
- params,
1873
- query,
1874
- state
1875
- },
1876
- '',
1877
- path
1878
- );
1879
- } else {
1880
- this.history[this.historyIndex] = {
1881
- path,
1882
- params,
1883
- query,
1884
- state
1885
- };
1886
- window.history.replaceState({
1887
- route: path,
1888
- params,
1889
- query,
1890
- state
1891
- },
1892
- '',
1893
- path
1894
- );
1895
- }
1896
-
1897
- // ===== CRÉER LES NOUVEAUX COMPOSANTS =====
1784
+ const {
1785
+ replace = false,
1786
+ animate = true,
1787
+ direction = 'forward',
1788
+ transition = null,
1789
+ state = {}
1790
+ } = options;
1791
+
1792
+ const match = this.matchRoute(path);
1793
+ if (!match) {
1794
+ console.warn(`Route not found: ${path}`);
1795
+ return;
1796
+ }
1898
1797
 
1899
- this.components = [];
1900
- if (typeof route.component === 'function') {
1901
- route.component(this, params, query);
1902
- }
1798
+ const { route, params, query, pathname } = match;
1903
1799
 
1904
- // ===== LANCER L'ANIMATION DE TRANSITION =====
1800
+ // ===== LIFECYCLE: AVANT DE QUITTER L'ANCIENNE ROUTE =====
1801
+ const currentRouteData = this.routes.get(this.currentRoute);
1802
+ if (currentRouteData?.beforeLeave) {
1803
+ const canLeave = await currentRouteData.beforeLeave(this.currentParams, this.currentQuery, this);
1804
+ if (canLeave === false) {
1805
+ console.log('Navigation cancelled by beforeLeave hook');
1806
+ return;
1807
+ }
1808
+ }
1905
1809
 
1906
- if (animate && !this.transitionState.isTransitioning) {
1907
- const transitionType = transition || route.transition || 'slide';
1908
- this.startTransition(oldComponents, this.components, transitionType, direction);
1909
- // Pas besoin d'appeler renderFull() ici, la boucle de rendu s'en chargera
1810
+ if (currentRouteData?.onLeave) {
1811
+ await currentRouteData.onLeave(this.currentParams, this.currentQuery, this);
1910
1812
  }
1911
1813
 
1912
- // ===== LIFECYCLE: APRÈS ÊTRE ENTRÉ DANS LA NOUVELLE ROUTE =====
1814
+ // ===== LIFECYCLE: AVANT D'ENTRER DANS LA NOUVELLE ROUTE =====
1815
+ if (route.beforeEnter) {
1816
+ const canEnter = await route.beforeEnter(params, query, this);
1817
+ if (canEnter === false) {
1818
+ console.log('Navigation cancelled by beforeEnter hook');
1819
+ return;
1820
+ }
1821
+ }
1913
1822
 
1914
- // Hook afterEnter (appelé immédiatement après la création des composants)
1915
- if (route.afterEnter) {
1916
- route.afterEnter(params, query, this);
1917
- }
1823
+ if (route.onEnter) {
1824
+ await route.onEnter(params, query, this);
1825
+ }
1918
1826
 
1919
- // NOUVEAU : Hook afterLeave de l'ancienne route (après transition complète)
1920
- if (currentRouteData?.afterLeave) {
1921
- // Si animation, attendre la fin de la transition
1922
- if (animate && this.transitionState.isTransitioning) {
1923
- setTimeout(() => {
1924
- currentRouteData.afterLeave(oldParams, oldQuery, this);
1925
- }, this.transitionState.duration || 300);
1926
- } else {
1927
- // Pas d'animation, appeler immédiatement
1928
- currentRouteData.afterLeave(oldParams, oldQuery, this);
1929
- }
1930
- }
1827
+ // ===== SAUVEGARDER L'ÉTAT ACTUEL =====
1828
+ const oldComponents = [...this.components];
1829
+ const oldRoute = this.currentRoute;
1830
+ const oldParams = { ...this.currentParams };
1831
+ const oldQuery = { ...this.currentQuery };
1931
1832
 
1932
- // ✅ OPTIONNEL : Marquer les composants comme "dirty" pour forcer le rendu
1933
- this._maxScrollDirty = true;
1934
-
1935
- // ✅ ARRÊTER LES CAMÉRAS DES ANCIENS COMPOSANTS
1833
+ // ✅ CRUCIAL : ARRÊTER LES ANCIENNES CAMÉRAS AVANT DE CRÉER LES NOUVELLES
1936
1834
  oldComponents.forEach(comp => {
1937
- // Vérifier si c'est un composant caméra
1938
1835
  if (comp.constructor.name === 'FloatedCamera' ||
1939
1836
  comp.constructor.name === 'Camera' ||
1837
+ comp.constructor.name === 'Video' ||
1940
1838
  comp.constructor.name === 'QRCodeReader') {
1941
- // Arrêter le stream vidéo
1942
1839
  if (comp.stopCamera && typeof comp.stopCamera === 'function') {
1943
1840
  comp.stopCamera();
1944
1841
  }
1842
+ // Destroy le composant pour être sûr
1843
+ if (comp.destroy && typeof comp.destroy === 'function') {
1844
+ comp.destroy();
1845
+ }
1945
1846
  }
1946
1847
  });
1947
-
1948
- // ✅ NOUVEAU : Vérifier si la nouvelle route contient des composants caméra
1949
- const hasCamera = this.components.some(comp =>
1950
- comp.constructor.name === 'FloatedCamera' ||
1951
- comp.constructor.name === 'Camera' ||
1952
- comp.constructor.name === 'QRCodeReader'
1953
- );
1954
-
1955
- // Si la nouvelle route N'A PAS de caméra, nettoyer toutes les vidéos après 3 secondes
1956
- if (!hasCamera) {
1957
- console.log('⏰ Nettoyage des vidéos programmé dans 3 secondes...');
1958
- setTimeout(() => {
1959
- const videos = document.querySelectorAll('video');
1960
- videos.forEach(v => v.remove());
1961
- }, 3000);
1848
+
1849
+ // ✅ Nettoyer toutes les vidéos orphelines AVANT de créer les nouveaux composants
1850
+ const allVideos = document.querySelectorAll('video');
1851
+ allVideos.forEach(v => v.remove());
1852
+
1853
+ // ===== METTRE À JOUR L'ÉTAT =====
1854
+ this.currentRoute = pathname;
1855
+ this.currentParams = params;
1856
+ this.currentQuery = query;
1857
+
1858
+ // ===== GÉRER L'HISTORIQUE =====
1859
+ if (!replace) {
1860
+ this.historyIndex++;
1861
+ this.history = this.history.slice(0, this.historyIndex);
1862
+ this.history.push({ path, params, query, state });
1863
+ window.history.pushState({ route: path, params, query, state }, '', path);
1962
1864
  } else {
1963
- console.log('📹 Route avec caméra détectée, pas de nettoyage automatique');
1865
+ this.history[this.historyIndex] = { path, params, query, state };
1866
+ window.history.replaceState({ route: path, params, query, state }, '', path);
1964
1867
  }
1965
-
1966
- }
1868
+
1869
+ // ===== CRÉER LES NOUVEAUX COMPOSANTS =====
1870
+ this.components = [];
1871
+ if (typeof route.component === 'function') {
1872
+ route.component(this, params, query);
1873
+ }
1874
+
1875
+ // ===== LANCER L'ANIMATION DE TRANSITION =====
1876
+ if (animate && !this.transitionState.isTransitioning) {
1877
+ const transitionType = transition || route.transition || 'slide';
1878
+ this.startTransition(oldComponents, this.components, transitionType, direction);
1879
+ }
1880
+
1881
+ // ===== LIFECYCLE: APRÈS ÊTRE ENTRÉ DANS LA NOUVELLE ROUTE =====
1882
+ if (route.afterEnter) {
1883
+ route.afterEnter(params, query, this);
1884
+ }
1885
+
1886
+ if (currentRouteData?.afterLeave) {
1887
+ if (animate && this.transitionState.isTransitioning) {
1888
+ setTimeout(() => {
1889
+ currentRouteData.afterLeave(oldParams, oldQuery, this);
1890
+ }, this.transitionState.duration || 300);
1891
+ } else {
1892
+ currentRouteData.afterLeave(oldParams, oldQuery, this);
1893
+ }
1894
+ }
1895
+
1896
+ this._maxScrollDirty = true;
1897
+ }
1967
1898
 
1968
1899
  /**
1969
1900
  * Démarre une animation de transition
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canvasframework",
3
- "version": "0.5.13",
3
+ "version": "0.5.15",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/beyons/CanvasFramework.git"