canvasframework 0.3.6

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.
Files changed (85) hide show
  1. package/README.md +554 -0
  2. package/components/Accordion.js +252 -0
  3. package/components/AndroidDatePickerDialog.js +398 -0
  4. package/components/AppBar.js +225 -0
  5. package/components/Avatar.js +202 -0
  6. package/components/BottomNavigationBar.js +205 -0
  7. package/components/BottomSheet.js +374 -0
  8. package/components/Button.js +225 -0
  9. package/components/Card.js +193 -0
  10. package/components/Checkbox.js +180 -0
  11. package/components/Chip.js +212 -0
  12. package/components/CircularProgress.js +143 -0
  13. package/components/ContextMenu.js +116 -0
  14. package/components/DatePicker.js +257 -0
  15. package/components/Dialog.js +367 -0
  16. package/components/Divider.js +125 -0
  17. package/components/Drawer.js +261 -0
  18. package/components/FAB.js +270 -0
  19. package/components/FileUpload.js +315 -0
  20. package/components/IOSDatePickerWheel.js +268 -0
  21. package/components/ImageCarousel.js +193 -0
  22. package/components/ImageComponent.js +223 -0
  23. package/components/Input.js +309 -0
  24. package/components/List.js +94 -0
  25. package/components/ListItem.js +223 -0
  26. package/components/Modal.js +364 -0
  27. package/components/MultiSelectDialog.js +206 -0
  28. package/components/NumberInput.js +271 -0
  29. package/components/ProgressBar.js +88 -0
  30. package/components/RadioButton.js +142 -0
  31. package/components/SearchInput.js +315 -0
  32. package/components/SegmentedControl.js +202 -0
  33. package/components/Select.js +199 -0
  34. package/components/SelectDialog.js +255 -0
  35. package/components/Slider.js +113 -0
  36. package/components/Snackbar.js +243 -0
  37. package/components/Stepper.js +281 -0
  38. package/components/SwipeableListItem.js +179 -0
  39. package/components/Switch.js +147 -0
  40. package/components/Table.js +492 -0
  41. package/components/Tabs.js +125 -0
  42. package/components/Text.js +141 -0
  43. package/components/TextField.js +331 -0
  44. package/components/Toast.js +236 -0
  45. package/components/TreeView.js +420 -0
  46. package/components/Video.js +397 -0
  47. package/components/View.js +140 -0
  48. package/components/VirtualList.js +120 -0
  49. package/core/CanvasFramework.js +1271 -0
  50. package/core/CanvasWork.js +32 -0
  51. package/core/Component.js +153 -0
  52. package/core/LogicWorker.js +25 -0
  53. package/core/WebGLCanvasAdapter.js +1369 -0
  54. package/features/Column.js +43 -0
  55. package/features/Grid.js +47 -0
  56. package/features/LayoutComponent.js +43 -0
  57. package/features/OpenStreetMap.js +310 -0
  58. package/features/Positioned.js +33 -0
  59. package/features/PullToRefresh.js +328 -0
  60. package/features/Row.js +40 -0
  61. package/features/SignaturePad.js +257 -0
  62. package/features/Skeleton.js +84 -0
  63. package/features/Stack.js +21 -0
  64. package/index.js +101 -0
  65. package/manager/AccessibilityManager.js +107 -0
  66. package/manager/ErrorHandler.js +59 -0
  67. package/manager/FeatureFlags.js +60 -0
  68. package/manager/MemoryManager.js +107 -0
  69. package/manager/PerformanceMonitor.js +84 -0
  70. package/manager/SecurityManager.js +54 -0
  71. package/package.json +28 -0
  72. package/utils/AnimationEngine.js +428 -0
  73. package/utils/DataStore.js +403 -0
  74. package/utils/EventBus.js +407 -0
  75. package/utils/FetchClient.js +74 -0
  76. package/utils/FormValidator.js +355 -0
  77. package/utils/GeoLocationService.js +62 -0
  78. package/utils/I18n.js +207 -0
  79. package/utils/IndexedDBManager.js +273 -0
  80. package/utils/OfflineSyncManager.js +342 -0
  81. package/utils/QueryBuilder.js +478 -0
  82. package/utils/SafeArea.js +64 -0
  83. package/utils/SecureStorage.js +289 -0
  84. package/utils/StateManager.js +207 -0
  85. package/utils/WebSocketClient.js +66 -0
@@ -0,0 +1,403 @@
1
+ /**
2
+ * Cache local avec TTL (Time To Live) et gestion avancée
3
+ * @class
4
+ * @property {Map} store - Stockage interne
5
+ * @property {number} defaultTTL - TTL par défaut en ms
6
+ * @property {number} maxSize - Taille max du cache
7
+ * @property {Object} stats - Statistiques du cache
8
+ */
9
+ class DataStore {
10
+ /**
11
+ * Crée une instance de DataStore
12
+ * @param {Object} [options={}] - Options
13
+ * @param {number} [options.defaultTTL=3600000] - TTL par défaut (1h)
14
+ * @param {number} [options.maxSize=100] - Taille max du cache
15
+ * @param {boolean} [options.enableStats=true] - Activer les stats
16
+ */
17
+ constructor(options = {}) {
18
+ this.store = new Map();
19
+ this.defaultTTL = options.defaultTTL || 3600000; // 1 heure par défaut
20
+ this.maxSize = options.maxSize || 100;
21
+ this.enableStats = options.enableStats !== false;
22
+
23
+ // Statistiques
24
+ this.stats = {
25
+ hits: 0,
26
+ misses: 0,
27
+ sets: 0,
28
+ deletes: 0,
29
+ evictions: 0
30
+ };
31
+
32
+ // Nettoyage périodique
33
+ this.startCleanupInterval();
34
+ }
35
+
36
+ /**
37
+ * Stocke une valeur avec TTL
38
+ * @param {string} key - Clé
39
+ * @param {*} value - Valeur
40
+ * @param {number} [ttl] - TTL en ms (optionnel)
41
+ * @returns {DataStore} Instance pour chaînage
42
+ */
43
+ set(key, value, ttl) {
44
+ const expiresAt = Date.now() + (ttl || this.defaultTTL);
45
+
46
+ // Si le cache est plein, supprimer l'élément le plus ancien
47
+ if (this.store.size >= this.maxSize && !this.store.has(key)) {
48
+ this.evictOldest();
49
+ }
50
+
51
+ this.store.set(key, {
52
+ value,
53
+ expiresAt,
54
+ createdAt: Date.now(),
55
+ accessCount: 0
56
+ });
57
+
58
+ if (this.enableStats) this.stats.sets++;
59
+
60
+ return this;
61
+ }
62
+
63
+ /**
64
+ * Récupère une valeur
65
+ * @param {string} key - Clé
66
+ * @param {*} [defaultValue=null] - Valeur par défaut
67
+ * @returns {*} Valeur ou null
68
+ */
69
+ get(key, defaultValue = null) {
70
+ const item = this.store.get(key);
71
+
72
+ if (!item) {
73
+ if (this.enableStats) this.stats.misses++;
74
+ return defaultValue;
75
+ }
76
+
77
+ // Vérifier l'expiration
78
+ if (Date.now() > item.expiresAt) {
79
+ this.delete(key);
80
+ if (this.enableStats) this.stats.misses++;
81
+ return defaultValue;
82
+ }
83
+
84
+ // Mettre à jour les stats d'accès
85
+ item.accessCount++;
86
+
87
+ if (this.enableStats) this.stats.hits++;
88
+
89
+ return item.value;
90
+ }
91
+
92
+ /**
93
+ * Vérifie si une clé existe et n'est pas expirée
94
+ * @param {string} key - Clé
95
+ * @returns {boolean} True si existe et valide
96
+ */
97
+ has(key) {
98
+ const item = this.store.get(key);
99
+
100
+ if (!item) return false;
101
+
102
+ if (Date.now() > item.expiresAt) {
103
+ this.delete(key);
104
+ return false;
105
+ }
106
+
107
+ return true;
108
+ }
109
+
110
+ /**
111
+ * Supprime une entrée
112
+ * @param {string} key - Clé
113
+ * @returns {boolean} True si supprimé
114
+ */
115
+ delete(key) {
116
+ const deleted = this.store.delete(key);
117
+ if (deleted && this.enableStats) this.stats.deletes++;
118
+ return deleted;
119
+ }
120
+
121
+ /**
122
+ * Vide tout le cache
123
+ */
124
+ clear() {
125
+ this.store.clear();
126
+ if (this.enableStats) {
127
+ this.stats = {
128
+ hits: 0,
129
+ misses: 0,
130
+ sets: 0,
131
+ deletes: 0,
132
+ evictions: 0
133
+ };
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Récupère ou calcule une valeur (memoization)
139
+ * @param {string} key - Clé
140
+ * @param {Function} factory - Fonction qui retourne la valeur
141
+ * @param {number} [ttl] - TTL optionnel
142
+ * @returns {Promise<*>} Valeur
143
+ */
144
+ async getOrSet(key, factory, ttl) {
145
+ if (this.has(key)) {
146
+ return this.get(key);
147
+ }
148
+
149
+ const value = await factory();
150
+ this.set(key, value, ttl);
151
+ return value;
152
+ }
153
+
154
+ /**
155
+ * Récupère plusieurs valeurs
156
+ * @param {Array<string>} keys - Clés
157
+ * @returns {Object} Objet clé-valeur
158
+ */
159
+ getMany(keys) {
160
+ const result = {};
161
+
162
+ for (let key of keys) {
163
+ const value = this.get(key);
164
+ if (value !== null) {
165
+ result[key] = value;
166
+ }
167
+ }
168
+
169
+ return result;
170
+ }
171
+
172
+ /**
173
+ * Stocke plusieurs valeurs
174
+ * @param {Object} items - Objet clé-valeur
175
+ * @param {number} [ttl] - TTL optionnel
176
+ * @returns {DataStore} Instance pour chaînage
177
+ */
178
+ setMany(items, ttl) {
179
+ for (let key in items) {
180
+ this.set(key, items[key], ttl);
181
+ }
182
+ return this;
183
+ }
184
+
185
+ /**
186
+ * Supprime plusieurs entrées
187
+ * @param {Array<string>} keys - Clés
188
+ * @returns {number} Nombre de suppressions
189
+ */
190
+ deleteMany(keys) {
191
+ let count = 0;
192
+ for (let key of keys) {
193
+ if (this.delete(key)) count++;
194
+ }
195
+ return count;
196
+ }
197
+
198
+ /**
199
+ * Met à jour le TTL d'une entrée
200
+ * @param {string} key - Clé
201
+ * @param {number} ttl - Nouveau TTL en ms
202
+ * @returns {boolean} True si mis à jour
203
+ */
204
+ touch(key, ttl) {
205
+ const item = this.store.get(key);
206
+
207
+ if (!item) return false;
208
+
209
+ item.expiresAt = Date.now() + (ttl || this.defaultTTL);
210
+ return true;
211
+ }
212
+
213
+ /**
214
+ * Obtient le TTL restant
215
+ * @param {string} key - Clé
216
+ * @returns {number} TTL en ms, ou -1 si n'existe pas
217
+ */
218
+ ttl(key) {
219
+ const item = this.store.get(key);
220
+
221
+ if (!item) return -1;
222
+
223
+ const remaining = item.expiresAt - Date.now();
224
+ return remaining > 0 ? remaining : -1;
225
+ }
226
+
227
+ /**
228
+ * Évince l'élément le plus ancien (LRU)
229
+ * @private
230
+ */
231
+ evictOldest() {
232
+ let oldestKey = null;
233
+ let oldestTime = Infinity;
234
+
235
+ for (let [key, item] of this.store.entries()) {
236
+ // Utiliser l'accès le moins récent comme critère
237
+ const priority = item.createdAt - (item.accessCount * 1000);
238
+
239
+ if (priority < oldestTime) {
240
+ oldestTime = priority;
241
+ oldestKey = key;
242
+ }
243
+ }
244
+
245
+ if (oldestKey) {
246
+ this.store.delete(oldestKey);
247
+ if (this.enableStats) this.stats.evictions++;
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Nettoie les entrées expirées
253
+ * @returns {number} Nombre d'entrées nettoyées
254
+ */
255
+ cleanup() {
256
+ const now = Date.now();
257
+ let cleaned = 0;
258
+
259
+ for (let [key, item] of this.store.entries()) {
260
+ if (now > item.expiresAt) {
261
+ this.store.delete(key);
262
+ cleaned++;
263
+ }
264
+ }
265
+
266
+ return cleaned;
267
+ }
268
+
269
+ /**
270
+ * Démarre le nettoyage automatique
271
+ * @param {number} [interval=60000] - Intervalle en ms (1 minute)
272
+ * @private
273
+ */
274
+ startCleanupInterval(interval = 60000) {
275
+ if (this.cleanupTimer) {
276
+ clearInterval(this.cleanupTimer);
277
+ }
278
+
279
+ this.cleanupTimer = setInterval(() => {
280
+ this.cleanup();
281
+ }, interval);
282
+ }
283
+
284
+ /**
285
+ * Arrête le nettoyage automatique
286
+ */
287
+ stopCleanupInterval() {
288
+ if (this.cleanupTimer) {
289
+ clearInterval(this.cleanupTimer);
290
+ this.cleanupTimer = null;
291
+ }
292
+ }
293
+
294
+ /**
295
+ * Obtient toutes les clés
296
+ * @param {boolean} [includeExpired=false] - Inclure les expirées
297
+ * @returns {Array<string>} Liste des clés
298
+ */
299
+ keys(includeExpired = false) {
300
+ const keys = [];
301
+ const now = Date.now();
302
+
303
+ for (let [key, item] of this.store.entries()) {
304
+ if (includeExpired || now <= item.expiresAt) {
305
+ keys.push(key);
306
+ }
307
+ }
308
+
309
+ return keys;
310
+ }
311
+
312
+ /**
313
+ * Obtient la taille du cache
314
+ * @returns {number} Nombre d'entrées
315
+ */
316
+ size() {
317
+ return this.store.size;
318
+ }
319
+
320
+ /**
321
+ * Obtient les statistiques
322
+ * @returns {Object} Statistiques
323
+ */
324
+ getStats() {
325
+ const hitRate = this.stats.hits + this.stats.misses > 0
326
+ ? (this.stats.hits / (this.stats.hits + this.stats.misses) * 100).toFixed(2)
327
+ : 0;
328
+
329
+ return {
330
+ ...this.stats,
331
+ size: this.store.size,
332
+ hitRate: `${hitRate}%`,
333
+ maxSize: this.maxSize
334
+ };
335
+ }
336
+
337
+ /**
338
+ * Réinitialise les statistiques
339
+ */
340
+ resetStats() {
341
+ this.stats = {
342
+ hits: 0,
343
+ misses: 0,
344
+ sets: 0,
345
+ deletes: 0,
346
+ evictions: 0
347
+ };
348
+ }
349
+
350
+ /**
351
+ * Exporte le cache en JSON
352
+ * @returns {string} JSON
353
+ */
354
+ export() {
355
+ const data = {};
356
+
357
+ for (let [key, item] of this.store.entries()) {
358
+ data[key] = {
359
+ value: item.value,
360
+ expiresAt: item.expiresAt,
361
+ createdAt: item.createdAt
362
+ };
363
+ }
364
+
365
+ return JSON.stringify(data);
366
+ }
367
+
368
+ /**
369
+ * Importe un cache depuis JSON
370
+ * @param {string} json - JSON
371
+ */
372
+ import(json) {
373
+ const data = JSON.parse(json);
374
+ const now = Date.now();
375
+
376
+ for (let key in data) {
377
+ const item = data[key];
378
+
379
+ // Ne pas importer les entrées expirées
380
+ if (item.expiresAt > now) {
381
+ this.store.set(key, {
382
+ value: item.value,
383
+ expiresAt: item.expiresAt,
384
+ createdAt: item.createdAt,
385
+ accessCount: 0
386
+ });
387
+ }
388
+ }
389
+ }
390
+
391
+ /**
392
+ * Détruit le store
393
+ */
394
+ destroy() {
395
+ this.stopCleanupInterval();
396
+ this.clear();
397
+ }
398
+ }
399
+
400
+ // Instance globale par défaut
401
+ DataStore.global = new DataStore();
402
+
403
+ export default DataStore;