canvasframework 0.3.22 → 0.3.23
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.
- package/components/SliverAppBar.js +139 -0
- package/core/CanvasFramework.js +98 -0
- package/core/UIBuilder.js +2 -0
- package/index.js +3 -1
- package/package.json +1 -1
- package/utils/DevTools.js +1247 -0
- package/utils/DevToolsConsole.js +201 -0
- package/utils/InspectionOverlay.js +308 -0
|
@@ -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;
|
package/core/CanvasFramework.js
CHANGED
|
@@ -52,6 +52,7 @@ 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';
|
|
55
56
|
|
|
56
57
|
// Utils
|
|
57
58
|
import SafeArea from '../utils/SafeArea.js';
|
|
@@ -71,6 +72,12 @@ import AnimationEngine from '../utils/AnimationEngine.js';
|
|
|
71
72
|
import CryptoManager from '../utils/CryptoManager.js';
|
|
72
73
|
import NotificationManager from '../utils/NotificationManager.js';
|
|
73
74
|
|
|
75
|
+
// DevTools
|
|
76
|
+
import DevTools from '../utils/DevTools.js';
|
|
77
|
+
import InspectionOverlay from '../utils/InspectionOverlay.js';
|
|
78
|
+
import DevToolsConsole from '../utils/DevToolsConsole.js';
|
|
79
|
+
|
|
80
|
+
|
|
74
81
|
// Features
|
|
75
82
|
import PullToRefresh from '../features/PullToRefresh.js';
|
|
76
83
|
import Skeleton from '../features/Skeleton.js';
|
|
@@ -126,6 +133,7 @@ const FIXED_COMPONENT_TYPES = new Set([
|
|
|
126
133
|
FAB,
|
|
127
134
|
Toast,
|
|
128
135
|
Banner,
|
|
136
|
+
SliverAppBar,
|
|
129
137
|
BottomSheet,
|
|
130
138
|
ContextMenu,
|
|
131
139
|
OpenStreetMap,
|
|
@@ -243,6 +251,96 @@ class CanvasFramework {
|
|
|
243
251
|
this.setupEventListeners();
|
|
244
252
|
this.setupHistoryListener();
|
|
245
253
|
this.startRenderLoop();
|
|
254
|
+
|
|
255
|
+
this.devTools = new DevTools(this);
|
|
256
|
+
this.inspectionOverlay = new InspectionOverlay(this);
|
|
257
|
+
|
|
258
|
+
// MODIFICATION: Vérifier explicitement l'option enableDevTools
|
|
259
|
+
const shouldEnableDevTools = options.enableDevTools === true;
|
|
260
|
+
|
|
261
|
+
if (shouldEnableDevTools) {
|
|
262
|
+
this.enableDevTools();
|
|
263
|
+
console.log('DevTools enabled. Press Ctrl+Shift+D to toggle.');
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Active ou désactive les DevTools
|
|
269
|
+
* @param {boolean} enabled - true pour activer, false pour désactiver
|
|
270
|
+
*/
|
|
271
|
+
enableDevTools(enabled = true) {
|
|
272
|
+
if (enabled) {
|
|
273
|
+
// Créer le DevTools s'il n'existe pas
|
|
274
|
+
if (!this.devTools) {
|
|
275
|
+
this.devTools = new DevTools(this);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Attacher seulement si pas déjà fait
|
|
279
|
+
if (!this.devTools._isAttached) {
|
|
280
|
+
this.devTools.attachToFramework();
|
|
281
|
+
this.devTools._isAttached = true;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Afficher le bouton
|
|
285
|
+
if (this.devTools.toggleBtn) {
|
|
286
|
+
this.devTools.toggleBtn.style.display = 'block';
|
|
287
|
+
}
|
|
288
|
+
} else {
|
|
289
|
+
// Désactiver complètement
|
|
290
|
+
if (this.devTools) {
|
|
291
|
+
// Détacher du framework
|
|
292
|
+
if (this.devTools.detachFromFramework) {
|
|
293
|
+
this.devTools.detachFromFramework();
|
|
294
|
+
} else if (this.devTools.cleanup) {
|
|
295
|
+
this.devTools.cleanup();
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Supprimer de la page DOM
|
|
299
|
+
if (this.devTools.container && this.devTools.container.parentNode) {
|
|
300
|
+
this.devTools.container.parentNode.removeChild(this.devTools.container);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (this.devTools.toggleBtn && this.devTools.toggleBtn.parentNode) {
|
|
304
|
+
this.devTools.toggleBtn.parentNode.removeChild(this.devTools.toggleBtn);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
this.devTools._isAttached = false;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Bascule l'overlay d'inspection
|
|
314
|
+
*/
|
|
315
|
+
toggleInspection() {
|
|
316
|
+
this.inspectionOverlay.toggle();
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Exécute une commande DevTools
|
|
321
|
+
*/
|
|
322
|
+
devToolsCommand(command, ...args) {
|
|
323
|
+
switch (command) {
|
|
324
|
+
case 'inspect':
|
|
325
|
+
this.inspectionOverlay.enable();
|
|
326
|
+
break;
|
|
327
|
+
case 'performance':
|
|
328
|
+
this.devTools.switchTab('performance');
|
|
329
|
+
this.devTools.toggle();
|
|
330
|
+
break;
|
|
331
|
+
case 'components':
|
|
332
|
+
this.devTools.switchTab('components');
|
|
333
|
+
this.devTools.toggle();
|
|
334
|
+
break;
|
|
335
|
+
case 'highlight':
|
|
336
|
+
if (args[0]) {
|
|
337
|
+
this.devTools.highlightComponent(args[0]);
|
|
338
|
+
}
|
|
339
|
+
break;
|
|
340
|
+
case 'reflow':
|
|
341
|
+
this.components.forEach(comp => comp.markDirty());
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
246
344
|
}
|
|
247
345
|
|
|
248
346
|
wrapContext(ctx, theme) {
|
package/core/UIBuilder.js
CHANGED
|
@@ -53,6 +53,7 @@ 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';
|
|
56
57
|
|
|
57
58
|
// Features
|
|
58
59
|
import PullToRefresh from '../features/PullToRefresh.js';
|
|
@@ -92,6 +93,7 @@ const Components = {
|
|
|
92
93
|
Modal,
|
|
93
94
|
Drawer,
|
|
94
95
|
AppBar,
|
|
96
|
+
SliverAppBar,
|
|
95
97
|
Chip,
|
|
96
98
|
Stepper,
|
|
97
99
|
Accordion,
|
package/index.js
CHANGED
|
@@ -60,6 +60,7 @@ 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';
|
|
63
64
|
|
|
64
65
|
// Utils
|
|
65
66
|
export { default as SafeArea } from './utils/SafeArea.js';
|
|
@@ -78,6 +79,7 @@ export { default as WebSocketClient } from './utils/WebSocketClient.js';
|
|
|
78
79
|
export { default as AnimationEngine } from './utils/AnimationEngine.js';
|
|
79
80
|
export { default as CryptoManager } from './utils/CryptoManager.js';
|
|
80
81
|
export { default as NotificationManager } from './utils/NotificationManager.js';
|
|
82
|
+
export { default as DevTools } from './utils/DevTools.js';
|
|
81
83
|
|
|
82
84
|
// Features
|
|
83
85
|
export { default as PullToRefresh } from './features/PullToRefresh.js';
|
|
@@ -101,7 +103,7 @@ export { default as FeatureFlags } from './manager/FeatureFlags.js';
|
|
|
101
103
|
|
|
102
104
|
// Version du framework
|
|
103
105
|
|
|
104
|
-
export const VERSION = '0.3.
|
|
106
|
+
export const VERSION = '0.3.23';
|
|
105
107
|
|
|
106
108
|
|
|
107
109
|
|