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.
@@ -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
- this.logicWorker = new Worker('./LogicWorker.js', { type: 'module' });
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
- return comp instanceof AppBar ||
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 (other instanceof Input || other instanceof PasswordInput || other instanceof InputTags || other instanceof InputDatalist && other !== child && other.focused) {
880
- other.focused = false;
881
- other.cursorVisible = false;
882
- if (other.onBlur) other.onBlur();
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 (other instanceof Input || other instanceof PasswordInput || other instanceof InputTags || other instanceof InputDatalist && other !== comp && other.focused) {
926
- other.focused = false;
927
- other.cursorVisible = false;
928
- if (other.onBlur) other.onBlur();
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
- return comp instanceof AppBar ||
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.16';
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canvasframework",
3
- "version": "0.3.17",
3
+ "version": "0.3.18",
4
4
  "description": "Canvas-based cross-platform UI framework (Material & Cupertino)",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -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
+ }