canvasframework 0.3.22 → 0.3.24

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.
@@ -0,0 +1,139 @@
1
+ import AppBar from './AppBar.js';
2
+ /**
3
+ * SliverAppBar - CanvasFramework
4
+ * Collapse / Stretch / Parallax
5
+ * Compatible Material & Cupertino
6
+ * ⚠️ Ne modifie PAS AppBar
7
+ */
8
+ class SliverAppBar extends AppBar {
9
+ constructor(framework, options = {}) {
10
+ super(framework, {
11
+ ...options,
12
+ y: 0
13
+ });
14
+ // Heights
15
+ this.expandedHeight = options.expandedHeight || 240;
16
+ this.collapsedHeight = options.collapsedHeight ?? 56;
17
+ // Effects
18
+ this.stretch = options.stretch ?? true;
19
+ this.parallax = options.parallax ?? true;
20
+ this.parallaxFactor = options.parallaxFactor ?? 0.4;
21
+ // Background
22
+ this.backgroundImage = options.backgroundImage || null;
23
+ this.backgroundColor = options.backgroundColor || this.bgColor || '#FFFFFF';
24
+ this.backgroundOpacity = this._extractOpacity(this.backgroundColor);
25
+ // Overlay (au-dessus de l'image)
26
+ this.overlayColor = options.overlayColor || '#000000';
27
+ this.overlayOpacity = options.overlayOpacity ?? 0;
28
+ // Foreground (titre + icônes)
29
+ this.foregroundColor = options.foregroundColor || options.textColor || this.textColor || '#FFFFFF';
30
+ // SliverAppBar participe au scroll
31
+ this.fixed = false;
32
+ }
33
+
34
+ /**
35
+ * Extrait l'opacité d'une couleur rgba() ou retourne 1
36
+ */
37
+ _extractOpacity(color) {
38
+ if (typeof color === 'string' && color.startsWith('rgba')) {
39
+ const match = color.match(/rgba?\([^,]+,[^,]+,[^,]+,\s*([\d.]+)\)/);
40
+ return match ? parseFloat(match[1]) : 1;
41
+ }
42
+ return 1;
43
+ }
44
+
45
+ /**
46
+ * Mise à jour dynamique selon le scroll
47
+ */
48
+ updateWithScroll(scrollOffset) {
49
+ const scrollY = -scrollOffset;
50
+ const collapseRange = this.expandedHeight - this.collapsedHeight;
51
+ const collapse = Math.min(scrollY, collapseRange);
52
+ let newHeight = this.expandedHeight - collapse;
53
+ // Stretch (overscroll)
54
+ if (scrollY < 0 && this.stretch) {
55
+ newHeight = this.expandedHeight - scrollY;
56
+ }
57
+ this.height = Math.max(newHeight, this.collapsedHeight);
58
+ }
59
+
60
+ draw(ctx) {
61
+ const scrollOffset = this.framework.scrollOffset || 0;
62
+ this.updateWithScroll(scrollOffset);
63
+ ctx.save();
64
+ // ===== Collapse progress (0 → 1)
65
+ const collapseProgress = Math.min(
66
+ 1,
67
+ Math.max(
68
+ 0,
69
+ (this.expandedHeight - this.height) /
70
+ (this.expandedHeight - this.collapsedHeight)
71
+ )
72
+ );
73
+ // ===== BACKGROUND IMAGE (en premier) =====
74
+ if (this.backgroundImage && this.backgroundImage.complete) {
75
+ let bgOffset = 0;
76
+ if (this.parallax) {
77
+ bgOffset = Math.max(0, -scrollOffset * this.parallaxFactor);
78
+ }
79
+ ctx.drawImage(
80
+ this.backgroundImage,
81
+ this.x,
82
+ this.y - bgOffset,
83
+ this.width,
84
+ this.height + bgOffset
85
+ );
86
+ }
87
+
88
+ // ===== BACKGROUND COLOR (overlay coloré au-dessus de l'image) =====
89
+ ctx.globalAlpha = this.backgroundOpacity;
90
+ ctx.fillStyle = this.backgroundColor;
91
+ ctx.fillRect(this.x, this.y, this.width, this.height);
92
+ ctx.globalAlpha = 1;
93
+
94
+ // ===== OVERLAY SUPPLÉMENTAIRE (si besoin) =====
95
+ if (this.overlayOpacity > 0) {
96
+ ctx.globalAlpha = this.overlayOpacity;
97
+ ctx.fillStyle = this.overlayColor;
98
+ ctx.fillRect(this.x, this.y, this.width, this.height);
99
+ ctx.globalAlpha = 1;
100
+ }
101
+ // ===== TITLE (fade with collapse) =====
102
+ ctx.globalAlpha = 1 - collapseProgress;
103
+ ctx.fillStyle = this.foregroundColor;
104
+ ctx.font = `bold 20px -apple-system, Roboto, sans-serif`;
105
+ ctx.textAlign = 'left';
106
+ ctx.textBaseline = 'bottom';
107
+ ctx.fillText(
108
+ this.title,
109
+ this.x + 16,
110
+ this.y + this.height - 16
111
+ );
112
+ ctx.globalAlpha = 1;
113
+
114
+ // ===== PREVENT APPBAR BACKGROUND OVERWRITE =====
115
+ const originalBg = this.bgColor;
116
+ const originalTextColor = this.textColor;
117
+ const originalIconColor = this.iconColor;
118
+ const originalPlatform = this.platform;
119
+
120
+ // Force transparent pour éviter que super.draw() dessine un fond
121
+ this.bgColor = 'rgba(0,0,0,0)';
122
+ // Force la couleur du texte et des icônes
123
+ this.textColor = this.foregroundColor;
124
+ this.iconColor = this.foregroundColor;
125
+ // Force Material pour uniformiser le comportement des couleurs
126
+ this.platform = 'material';
127
+
128
+ // Icons, ripple, elevation, etc.
129
+ super.draw(ctx);
130
+
131
+ // Restore
132
+ this.bgColor = originalBg;
133
+ this.textColor = originalTextColor;
134
+ this.iconColor = originalIconColor;
135
+ this.platform = originalPlatform;
136
+ ctx.restore();
137
+ }
138
+ }
139
+ export default SliverAppBar;
@@ -52,6 +52,8 @@ import InputTags from '../components/InputTags.js';
52
52
  import InputDatalist from '../components/InputDatalist.js';
53
53
  import Banner from '../components/Banner.js';
54
54
  import Chart from '../components/Chart.js';
55
+ import SliverAppBar from '../components/SliverAppBar.js';
56
+ import AudioPlayer from '../components/AudioPlayer.js';
55
57
 
56
58
  // Utils
57
59
  import SafeArea from '../utils/SafeArea.js';
@@ -71,6 +73,12 @@ import AnimationEngine from '../utils/AnimationEngine.js';
71
73
  import CryptoManager from '../utils/CryptoManager.js';
72
74
  import NotificationManager from '../utils/NotificationManager.js';
73
75
 
76
+ // DevTools
77
+ import DevTools from '../utils/DevTools.js';
78
+ import InspectionOverlay from '../utils/InspectionOverlay.js';
79
+ import DevToolsConsole from '../utils/DevToolsConsole.js';
80
+
81
+
74
82
  // Features
75
83
  import PullToRefresh from '../features/PullToRefresh.js';
76
84
  import Skeleton from '../features/Skeleton.js';
@@ -126,6 +134,7 @@ const FIXED_COMPONENT_TYPES = new Set([
126
134
  FAB,
127
135
  Toast,
128
136
  Banner,
137
+ SliverAppBar,
129
138
  BottomSheet,
130
139
  ContextMenu,
131
140
  OpenStreetMap,
@@ -243,6 +252,96 @@ class CanvasFramework {
243
252
  this.setupEventListeners();
244
253
  this.setupHistoryListener();
245
254
  this.startRenderLoop();
255
+
256
+ this.devTools = new DevTools(this);
257
+ this.inspectionOverlay = new InspectionOverlay(this);
258
+
259
+ // MODIFICATION: Vérifier explicitement l'option enableDevTools
260
+ const shouldEnableDevTools = options.enableDevTools === true;
261
+
262
+ if (shouldEnableDevTools) {
263
+ this.enableDevTools();
264
+ console.log('DevTools enabled. Press Ctrl+Shift+D to toggle.');
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Active ou désactive les DevTools
270
+ * @param {boolean} enabled - true pour activer, false pour désactiver
271
+ */
272
+ enableDevTools(enabled = true) {
273
+ if (enabled) {
274
+ // Créer le DevTools s'il n'existe pas
275
+ if (!this.devTools) {
276
+ this.devTools = new DevTools(this);
277
+ }
278
+
279
+ // Attacher seulement si pas déjà fait
280
+ if (!this.devTools._isAttached) {
281
+ this.devTools.attachToFramework();
282
+ this.devTools._isAttached = true;
283
+ }
284
+
285
+ // Afficher le bouton
286
+ if (this.devTools.toggleBtn) {
287
+ this.devTools.toggleBtn.style.display = 'block';
288
+ }
289
+ } else {
290
+ // Désactiver complètement
291
+ if (this.devTools) {
292
+ // Détacher du framework
293
+ if (this.devTools.detachFromFramework) {
294
+ this.devTools.detachFromFramework();
295
+ } else if (this.devTools.cleanup) {
296
+ this.devTools.cleanup();
297
+ }
298
+
299
+ // Supprimer de la page DOM
300
+ if (this.devTools.container && this.devTools.container.parentNode) {
301
+ this.devTools.container.parentNode.removeChild(this.devTools.container);
302
+ }
303
+
304
+ if (this.devTools.toggleBtn && this.devTools.toggleBtn.parentNode) {
305
+ this.devTools.toggleBtn.parentNode.removeChild(this.devTools.toggleBtn);
306
+ }
307
+
308
+ this.devTools._isAttached = false;
309
+ }
310
+ }
311
+ }
312
+
313
+ /**
314
+ * Bascule l'overlay d'inspection
315
+ */
316
+ toggleInspection() {
317
+ this.inspectionOverlay.toggle();
318
+ }
319
+
320
+ /**
321
+ * Exécute une commande DevTools
322
+ */
323
+ devToolsCommand(command, ...args) {
324
+ switch (command) {
325
+ case 'inspect':
326
+ this.inspectionOverlay.enable();
327
+ break;
328
+ case 'performance':
329
+ this.devTools.switchTab('performance');
330
+ this.devTools.toggle();
331
+ break;
332
+ case 'components':
333
+ this.devTools.switchTab('components');
334
+ this.devTools.toggle();
335
+ break;
336
+ case 'highlight':
337
+ if (args[0]) {
338
+ this.devTools.highlightComponent(args[0]);
339
+ }
340
+ break;
341
+ case 'reflow':
342
+ this.components.forEach(comp => comp.markDirty());
343
+ break;
344
+ }
246
345
  }
247
346
 
248
347
  wrapContext(ctx, theme) {
package/core/UIBuilder.js CHANGED
@@ -53,6 +53,8 @@ import InputTags from '../components/InputTags.js';
53
53
  import InputDatalist from '../components/InputDatalist.js';
54
54
  import Banner from '../components/Banner.js';
55
55
  import Chart from '../components/Chart.js';
56
+ import SliverAppBar from '../components/SliverAppBar.js';
57
+ import AudioPlayer from '../components/AudioPlayer.js';
56
58
 
57
59
  // Features
58
60
  import PullToRefresh from '../features/PullToRefresh.js';
@@ -92,6 +94,7 @@ const Components = {
92
94
  Modal,
93
95
  Drawer,
94
96
  AppBar,
97
+ SliverAppBar,
95
98
  Chip,
96
99
  Stepper,
97
100
  Accordion,
@@ -116,6 +119,7 @@ const Components = {
116
119
  Divider,
117
120
  FileUpload,
118
121
  Table,
122
+ AudioPlayer,
119
123
  TreeView,
120
124
  SearchInput,
121
125
  ImageCarousel,
package/index.js CHANGED
@@ -60,6 +60,8 @@ export { default as InputTags } from './components/InputTags.js';
60
60
  export { default as InputDatalist } from './components/InputDatalist.js';
61
61
  export { default as Banner } from './components/Banner.js';
62
62
  export { default as Chart } from './components/Chart.js';
63
+ export { default as SliverAppBar } from './components/SliverAppBar.js';
64
+ export { default as AudioPlayer } from './components/AudioPlayer.js';
63
65
 
64
66
  // Utils
65
67
  export { default as SafeArea } from './utils/SafeArea.js';
@@ -78,6 +80,7 @@ export { default as WebSocketClient } from './utils/WebSocketClient.js';
78
80
  export { default as AnimationEngine } from './utils/AnimationEngine.js';
79
81
  export { default as CryptoManager } from './utils/CryptoManager.js';
80
82
  export { default as NotificationManager } from './utils/NotificationManager.js';
83
+ export { default as DevTools } from './utils/DevTools.js';
81
84
 
82
85
  // Features
83
86
  export { default as PullToRefresh } from './features/PullToRefresh.js';
@@ -101,7 +104,7 @@ export { default as FeatureFlags } from './manager/FeatureFlags.js';
101
104
 
102
105
  // Version du framework
103
106
 
104
- export const VERSION = '0.3.21';
107
+ export const VERSION = '0.3.24';
105
108
 
106
109
 
107
110
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canvasframework",
3
- "version": "0.3.22",
3
+ "version": "0.3.24",
4
4
  "description": "Canvas-based cross-platform UI framework (Material & Cupertino)",
5
5
  "type": "module",
6
6
  "main": "./index.js",