canvasframework 0.3.17 → 0.3.18
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/core/CanvasFramework.js +63 -41
- package/index.js +10 -1
- package/package.json +1 -1
- package/utils/NotificationManager.js +60 -0
package/core/CanvasFramework.js
CHANGED
|
@@ -67,6 +67,7 @@ import GeoLocationService from '../utils/GeoLocationService.js';
|
|
|
67
67
|
import WebSocketClient from '../utils/WebSocketClient.js';
|
|
68
68
|
import AnimationEngine from '../utils/AnimationEngine.js';
|
|
69
69
|
import CryptoManager from '../utils/CryptoManager.js';
|
|
70
|
+
import NotificationManager from '../utils/NotificationManager.js';
|
|
70
71
|
|
|
71
72
|
// Features
|
|
72
73
|
import PullToRefresh from '../features/PullToRefresh.js';
|
|
@@ -113,6 +114,20 @@ export const darkTheme = {
|
|
|
113
114
|
border: '#333333'
|
|
114
115
|
};
|
|
115
116
|
|
|
117
|
+
const FIXED_COMPONENT_TYPES = new Set([
|
|
118
|
+
AppBar,
|
|
119
|
+
BottomNavigationBar,
|
|
120
|
+
Drawer,
|
|
121
|
+
Dialog,
|
|
122
|
+
Modal,
|
|
123
|
+
FAB,
|
|
124
|
+
Toast,
|
|
125
|
+
BottomSheet,
|
|
126
|
+
ContextMenu,
|
|
127
|
+
OpenStreetMap,
|
|
128
|
+
SelectDialog
|
|
129
|
+
]);
|
|
130
|
+
|
|
116
131
|
/**
|
|
117
132
|
* Framework principal pour créer des interfaces utilisateur basées sur Canvas
|
|
118
133
|
* @class
|
|
@@ -173,12 +188,13 @@ class CanvasFramework {
|
|
|
173
188
|
this.showFps = options.showFps || false; // false par défaut
|
|
174
189
|
this.debbug = options.debug || false; // false par défaut (et correction de la faute de frappe)
|
|
175
190
|
// Worker pour multithreading
|
|
176
|
-
this.worker = new Worker('./CanvasWorker.js', { type: 'module' });
|
|
191
|
+
this.worker = new Worker(new URL('./CanvasWorker.js', import.meta.url), { type: 'module' });
|
|
177
192
|
this.worker.onmessage = this.handleWorkerMessage.bind(this);
|
|
178
193
|
this.worker.postMessage({ type: 'INIT', payload: { components: [] } });
|
|
179
194
|
|
|
180
195
|
// Worker logique pour calculs séparés
|
|
181
|
-
|
|
196
|
+
|
|
197
|
+
this.logicWorker = new Worker(new URL('./LogicWorker.js', import.meta.url), { type: 'module' });
|
|
182
198
|
this.logicWorker.onmessage = this.handleLogicWorkerMessage.bind(this);
|
|
183
199
|
this.logicWorkerState = {};
|
|
184
200
|
|
|
@@ -819,19 +835,8 @@ class CanvasFramework {
|
|
|
819
835
|
}
|
|
820
836
|
|
|
821
837
|
checkComponentsAtPosition(x, y, eventType) {
|
|
822
|
-
const isFixedComponent = (comp) =>
|
|
823
|
-
|
|
824
|
-
comp instanceof BottomNavigationBar ||
|
|
825
|
-
comp instanceof Drawer ||
|
|
826
|
-
comp instanceof Dialog ||
|
|
827
|
-
comp instanceof Modal ||
|
|
828
|
-
comp instanceof FAB ||
|
|
829
|
-
comp instanceof Toast ||
|
|
830
|
-
comp instanceof BottomSheet ||
|
|
831
|
-
comp instanceof ContextMenu ||
|
|
832
|
-
comp instanceof OpenStreetMap ||
|
|
833
|
-
comp instanceof SelectDialog;
|
|
834
|
-
};
|
|
838
|
+
const isFixedComponent = (comp) =>
|
|
839
|
+
FIXED_COMPONENT_TYPES.has(comp.constructor);
|
|
835
840
|
|
|
836
841
|
for (let i = this.components.length - 1; i >= 0; i--) {
|
|
837
842
|
const comp = this.components[i];
|
|
@@ -859,7 +864,7 @@ class CanvasFramework {
|
|
|
859
864
|
switch (eventType) {
|
|
860
865
|
case 'start':
|
|
861
866
|
child.pressed = true;
|
|
862
|
-
if (child.onPress) child.onPress(relativeX, relativeY);
|
|
867
|
+
if (child.onPress) child.onPress?.(relativeX, relativeY);
|
|
863
868
|
break;
|
|
864
869
|
|
|
865
870
|
case 'move':
|
|
@@ -867,7 +872,7 @@ class CanvasFramework {
|
|
|
867
872
|
child.hovered = true;
|
|
868
873
|
if (child.onHover) child.onHover();
|
|
869
874
|
}
|
|
870
|
-
if (child.onMove) child.onMove(relativeX, relativeY);
|
|
875
|
+
if (child.onMove) child.onMove?.(relativeX, relativeY);
|
|
871
876
|
break;
|
|
872
877
|
|
|
873
878
|
case 'end':
|
|
@@ -876,11 +881,18 @@ class CanvasFramework {
|
|
|
876
881
|
|
|
877
882
|
if (child instanceof Input || child instanceof PasswordInput || child instanceof InputTags || child instanceof InputDatalist) {
|
|
878
883
|
for (let other of this.components) {
|
|
879
|
-
if (
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
+
if (
|
|
885
|
+
(other instanceof Input ||
|
|
886
|
+
other instanceof PasswordInput ||
|
|
887
|
+
other instanceof InputTags ||
|
|
888
|
+
other instanceof InputDatalist) &&
|
|
889
|
+
other !== child &&
|
|
890
|
+
other.focused
|
|
891
|
+
) {
|
|
892
|
+
other.focused = false;
|
|
893
|
+
other.cursorVisible = false;
|
|
894
|
+
other.onBlur?.();
|
|
895
|
+
}
|
|
884
896
|
}
|
|
885
897
|
|
|
886
898
|
child.focused = true;
|
|
@@ -889,7 +901,7 @@ class CanvasFramework {
|
|
|
889
901
|
} else if (child.onClick) {
|
|
890
902
|
child.onClick();
|
|
891
903
|
} else if (child.onPress) {
|
|
892
|
-
child.onPress(relativeX, relativeY);
|
|
904
|
+
child.onPress?.(relativeX, relativeY);
|
|
893
905
|
}
|
|
894
906
|
}
|
|
895
907
|
break;
|
|
@@ -922,11 +934,18 @@ class CanvasFramework {
|
|
|
922
934
|
|
|
923
935
|
if (comp instanceof Input || comp instanceof PasswordInput || comp instanceof InputTags || comp instanceof InputDatalist) {
|
|
924
936
|
for (let other of this.components) {
|
|
925
|
-
if (
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
937
|
+
if (
|
|
938
|
+
(other instanceof Input ||
|
|
939
|
+
other instanceof PasswordInput ||
|
|
940
|
+
other instanceof InputTags ||
|
|
941
|
+
other instanceof InputDatalist) &&
|
|
942
|
+
other !== comp &&
|
|
943
|
+
other.focused
|
|
944
|
+
) {
|
|
945
|
+
other.focused = false;
|
|
946
|
+
other.cursorVisible = false;
|
|
947
|
+
other.onBlur?.();
|
|
948
|
+
}
|
|
930
949
|
}
|
|
931
950
|
|
|
932
951
|
comp.focused = true;
|
|
@@ -948,8 +967,18 @@ class CanvasFramework {
|
|
|
948
967
|
}
|
|
949
968
|
}
|
|
950
969
|
}
|
|
951
|
-
|
|
970
|
+
|
|
952
971
|
getMaxScroll() {
|
|
972
|
+
let maxY = 0;
|
|
973
|
+
for (const comp of this.components) {
|
|
974
|
+
if (this.isFixedComponent(comp) || !comp.visible) continue;
|
|
975
|
+
const bottom = comp.y + comp.height;
|
|
976
|
+
if (bottom > maxY) maxY = bottom;
|
|
977
|
+
}
|
|
978
|
+
return Math.max(0, maxY - this.height + 50);
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
/*getMaxScroll() {
|
|
953
982
|
let maxY = 0;
|
|
954
983
|
for (let comp of this.components) {
|
|
955
984
|
if (!this.isFixedComponent(comp)) {
|
|
@@ -957,7 +986,7 @@ class CanvasFramework {
|
|
|
957
986
|
}
|
|
958
987
|
}
|
|
959
988
|
return Math.max(0, maxY - this.height + 50);
|
|
960
|
-
}
|
|
989
|
+
}*/
|
|
961
990
|
|
|
962
991
|
handleResize() {
|
|
963
992
|
// Pour WebGL, NE PAS redimensionner automatiquement
|
|
@@ -1251,17 +1280,7 @@ class CanvasFramework {
|
|
|
1251
1280
|
}
|
|
1252
1281
|
|
|
1253
1282
|
isFixedComponent(comp) {
|
|
1254
|
-
|
|
1255
|
-
comp instanceof BottomNavigationBar ||
|
|
1256
|
-
comp instanceof Drawer ||
|
|
1257
|
-
comp instanceof Dialog ||
|
|
1258
|
-
comp instanceof Modal ||
|
|
1259
|
-
comp instanceof FAB ||
|
|
1260
|
-
comp instanceof Toast ||
|
|
1261
|
-
comp instanceof BottomSheet ||
|
|
1262
|
-
comp instanceof ContextMenu ||
|
|
1263
|
-
comp instanceof OpenStreetMap ||
|
|
1264
|
-
comp instanceof SelectDialog;
|
|
1283
|
+
return FIXED_COMPONENT_TYPES.has(comp.constructor);
|
|
1265
1284
|
}
|
|
1266
1285
|
|
|
1267
1286
|
showToast(message, duration = 3000) {
|
|
@@ -1277,3 +1296,6 @@ class CanvasFramework {
|
|
|
1277
1296
|
}
|
|
1278
1297
|
|
|
1279
1298
|
export default CanvasFramework;
|
|
1299
|
+
|
|
1300
|
+
|
|
1301
|
+
|
package/index.js
CHANGED
|
@@ -75,6 +75,7 @@ export { default as GeoLocationService } from './utils/GeoLocationService.js';
|
|
|
75
75
|
export { default as WebSocketClient } from './utils/WebSocketClient.js';
|
|
76
76
|
export { default as AnimationEngine } from './utils/AnimationEngine.js';
|
|
77
77
|
export { default as CryptoManager } from './utils/CryptoManager.js';
|
|
78
|
+
export { default as NotificationManager } from './utils/NotificationManager.js';
|
|
78
79
|
|
|
79
80
|
// Features
|
|
80
81
|
export { default as PullToRefresh } from './features/PullToRefresh.js';
|
|
@@ -98,7 +99,15 @@ export { default as FeatureFlags } from './manager/FeatureFlags.js';
|
|
|
98
99
|
|
|
99
100
|
// Version du framework
|
|
100
101
|
|
|
101
|
-
export const VERSION = '0.3.
|
|
102
|
+
export const VERSION = '0.3.18';
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
102
111
|
|
|
103
112
|
|
|
104
113
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
|
|
2
|
+
// NotificationManager.js
|
|
3
|
+
export default class NotificationManager {
|
|
4
|
+
constructor(defaults = {}) {
|
|
5
|
+
this.defaults = {
|
|
6
|
+
icon: defaults.icon || null,
|
|
7
|
+
silent: defaults.silent || false,
|
|
8
|
+
requireInteraction: defaults.requireInteraction || false,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// Vérifier si l'API est disponible
|
|
12
|
+
this.isSupported = "Notification" in window;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Demander la permission si nécessaire
|
|
16
|
+
async requestPermission() {
|
|
17
|
+
if (!this.isSupported) return false;
|
|
18
|
+
if (Notification.permission === "granted") return true;
|
|
19
|
+
if (Notification.permission !== "denied") {
|
|
20
|
+
const permission = await Notification.requestPermission();
|
|
21
|
+
return permission === "granted";
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Créer une notification
|
|
27
|
+
async notify(title, options = {}) {
|
|
28
|
+
if (!this.isSupported) {
|
|
29
|
+
console.warn("Notifications API non supportée");
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const hasPermission = await this.requestPermission();
|
|
34
|
+
if (!hasPermission) return null;
|
|
35
|
+
|
|
36
|
+
const notifOptions = {
|
|
37
|
+
...this.defaults,
|
|
38
|
+
...options,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const notification = new Notification(title, notifOptions);
|
|
42
|
+
|
|
43
|
+
// Callbacks
|
|
44
|
+
if (options.onClick) {
|
|
45
|
+
notification.onclick = options.onClick;
|
|
46
|
+
}
|
|
47
|
+
if (options.onClose) {
|
|
48
|
+
notification.onclose = options.onClose;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Auto-close après duration (si défini)
|
|
52
|
+
if (options.duration && options.duration > 0) {
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
notification.close();
|
|
55
|
+
}, options.duration);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return notification;
|
|
59
|
+
}
|
|
60
|
+
}
|