canvasframework 0.3.24 → 0.3.25

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.
@@ -178,8 +178,22 @@ class CanvasFramework {
178
178
  this.lightTheme = lightTheme;
179
179
  this.darkTheme = darkTheme;
180
180
  this.theme = lightTheme; // thème par défaut
181
-
181
+ // État actuel + préférence
182
+ this.themeMode = options.themeMode || 'system'; // 'light', 'dark', 'system'
183
+ this.userThemeOverride = null; // null = suit system, sinon 'light' ou 'dark'
184
+
185
+ // Applique le thème initial
186
+ this.setupSystemThemeListener();
187
+
188
+ // Récupère override utilisateur
189
+ const savedOverride = localStorage.getItem('themeOverride');
190
+ if (savedOverride && ['light', 'dark'].includes(savedOverride)) {
191
+ this.userThemeOverride = savedOverride;
192
+ this.themeMode = savedOverride;
193
+ }
194
+
182
195
  this.components = [];
196
+ this.applyThemeFromSystem();
183
197
  this.state = {};
184
198
  // NOUVELLE OPTION: choisir entre Canvas 2D et WebGL
185
199
  this.useWebGL = options.useWebGL !== false; // true par défaut
@@ -265,6 +279,70 @@ class CanvasFramework {
265
279
  }
266
280
  }
267
281
 
282
+ /**
283
+ * Détecte le thème système et applique si mode = 'system'
284
+ */
285
+ applyThemeFromSystem() {
286
+ if (this.themeMode === 'system') {
287
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
288
+ const newTheme = prefersDark ? this.darkTheme : this.lightTheme;
289
+ this.setTheme(newTheme);
290
+ } else {
291
+ // Mode forcé
292
+ this.setTheme(
293
+ this.themeMode === 'dark' ? this.darkTheme : this.lightTheme
294
+ );
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Écoute les changements système (ex: utilisateur bascule dark mode)
300
+ */
301
+ setupSystemThemeListener() {
302
+ const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
303
+
304
+ // Ancienne méthode (compatibilité large)
305
+ if (mediaQuery.addEventListener) {
306
+ mediaQuery.addEventListener('change', (e) => {
307
+ if (this.themeMode === 'system') {
308
+ this.applyThemeFromSystem();
309
+ }
310
+ });
311
+ } else {
312
+ // Anciens navigateurs (rare en 2026)
313
+ mediaQuery.addListener((e) => {
314
+ if (this.themeMode === 'system') {
315
+ this.applyThemeFromSystem();
316
+ }
317
+ });
318
+ }
319
+ }
320
+
321
+ /**
322
+ * Change le mode thème
323
+ * @param {'light'|'dark'|'system'} mode - Mode à appliquer
324
+ * @param {boolean} [save=true] - Sauvegarder le choix utilisateur ?
325
+ */
326
+ setThemeMode(mode, save = true) {
327
+ if (!['light', 'dark', 'system'].includes(mode)) {
328
+ console.warn('Mode invalide, valeurs acceptées: light, dark, system');
329
+ return;
330
+ }
331
+
332
+ this.themeMode = mode;
333
+
334
+ if (save && mode !== 'system') {
335
+ this.userThemeOverride = mode;
336
+ // Sauvegarde (ex: localStorage ou ton SecureStorage)
337
+ localStorage.setItem('themeOverride', mode);
338
+ } else if (mode === 'system') {
339
+ this.userThemeOverride = null;
340
+ localStorage.removeItem('themeOverride');
341
+ }
342
+
343
+ this.applyThemeFromSystem();
344
+ }
345
+
268
346
  /**
269
347
  * Active ou désactive les DevTools
270
348
  * @param {boolean} enabled - true pour activer, false pour désactiver
@@ -431,13 +509,16 @@ class CanvasFramework {
431
509
  setTheme(theme) {
432
510
  this.theme = theme;
433
511
 
434
- // Intercepter le context pour remplacer les couleurs globalement
435
512
  if (!this.useWebGL) {
436
513
  this.wrapContext(this.ctx, theme);
437
514
  }
438
515
 
439
- // marque tous les composants dirty pour redraw
440
- for (let comp of this.components) comp.markDirty();
516
+ // Protège la boucle
517
+ if (this.components && Array.isArray(this.components)) {
518
+ this.components.forEach(comp => comp.markDirty());
519
+ } else {
520
+ console.warn('[setTheme] components pas encore initialisé');
521
+ }
441
522
  }
442
523
 
443
524
  // Switch Theme
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canvasframework",
3
- "version": "0.3.24",
3
+ "version": "0.3.25",
4
4
  "description": "Canvas-based cross-platform UI framework (Material & Cupertino)",
5
5
  "type": "module",
6
6
  "main": "./index.js",