canvasframework 0.5.18 → 0.5.20

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 (113) hide show
  1. package/README.md +30 -0
  2. package/components/Accordion.js +265 -0
  3. package/components/AndroidDatePickerDialog.js +406 -0
  4. package/components/AppBar.js +398 -0
  5. package/components/AudioPlayer.js +611 -0
  6. package/components/Avatar.js +202 -0
  7. package/components/Banner.js +342 -0
  8. package/components/BottomNavigationBar.js +433 -0
  9. package/components/BottomSheet.js +234 -0
  10. package/components/Button.js +358 -0
  11. package/components/Camera.js +644 -0
  12. package/components/Card.js +193 -0
  13. package/components/Chart.js +700 -0
  14. package/components/Checkbox.js +166 -0
  15. package/components/Chip.js +212 -0
  16. package/components/CircularProgress.js +327 -0
  17. package/components/ContextMenu.js +116 -0
  18. package/components/DatePicker.js +298 -0
  19. package/components/Dialog.js +337 -0
  20. package/components/Divider.js +125 -0
  21. package/components/Drawer.js +276 -0
  22. package/components/FAB.js +270 -0
  23. package/components/FileUpload.js +315 -0
  24. package/components/FloatedCamera.js +644 -0
  25. package/components/IOSDatePickerWheel.js +430 -0
  26. package/components/ImageCarousel.js +219 -0
  27. package/components/ImageComponent.js +223 -0
  28. package/components/Input.js +831 -0
  29. package/components/InputDatalist.js +723 -0
  30. package/components/InputTags.js +624 -0
  31. package/components/List.js +95 -0
  32. package/components/ListItem.js +269 -0
  33. package/components/Modal.js +364 -0
  34. package/components/MorphingFAB.js +428 -0
  35. package/components/MultiSelectDialog.js +206 -0
  36. package/components/NumberInput.js +271 -0
  37. package/components/PasswordInput.js +462 -0
  38. package/components/ProgressBar.js +88 -0
  39. package/components/QRCodeReader.js +539 -0
  40. package/components/RadioButton.js +151 -0
  41. package/components/SearchInput.js +315 -0
  42. package/components/SegmentedControl.js +357 -0
  43. package/components/Select.js +199 -0
  44. package/components/SelectDialog.js +255 -0
  45. package/components/Slider.js +113 -0
  46. package/components/SliverAppBar.js +139 -0
  47. package/components/Snackbar.js +243 -0
  48. package/components/SpeedDialFAB.js +397 -0
  49. package/components/Stepper.js +281 -0
  50. package/components/SwipeableListItem.js +327 -0
  51. package/components/Switch.js +147 -0
  52. package/components/Table.js +492 -0
  53. package/components/Tabs.js +423 -0
  54. package/components/Text.js +141 -0
  55. package/components/TextField.js +151 -0
  56. package/components/TimePicker.js +934 -0
  57. package/components/Toast.js +236 -0
  58. package/components/TreeView.js +420 -0
  59. package/components/Video.js +397 -0
  60. package/components/View.js +140 -0
  61. package/components/VirtualList.js +120 -0
  62. package/core/CanvasFramework.js +3045 -0
  63. package/core/Component.js +243 -0
  64. package/core/ThemeManager.js +358 -0
  65. package/core/UIBuilder.js +267 -0
  66. package/core/WebGLCanvasAdapter.js +782 -0
  67. package/features/Column.js +43 -0
  68. package/features/Grid.js +47 -0
  69. package/features/LayoutComponent.js +43 -0
  70. package/features/OpenStreetMap.js +310 -0
  71. package/features/Positioned.js +33 -0
  72. package/features/PullToRefresh.js +328 -0
  73. package/features/Row.js +40 -0
  74. package/features/SignaturePad.js +257 -0
  75. package/features/Skeleton.js +193 -0
  76. package/features/Stack.js +21 -0
  77. package/index.js +119 -0
  78. package/manager/AccessibilityManager.js +107 -0
  79. package/manager/ErrorHandler.js +59 -0
  80. package/manager/FeatureFlags.js +60 -0
  81. package/manager/MemoryManager.js +107 -0
  82. package/manager/PerformanceMonitor.js +84 -0
  83. package/manager/SecurityManager.js +54 -0
  84. package/package.json +22 -16
  85. package/utils/AnimationEngine.js +734 -0
  86. package/utils/CryptoManager.js +303 -0
  87. package/utils/DataStore.js +403 -0
  88. package/utils/DevTools.js +1618 -0
  89. package/utils/DevToolsConsole.js +201 -0
  90. package/utils/EventBus.js +407 -0
  91. package/utils/FetchClient.js +74 -0
  92. package/utils/FirebaseAuth.js +653 -0
  93. package/utils/FirebaseCore.js +246 -0
  94. package/utils/FirebaseFirestore.js +581 -0
  95. package/utils/FirebaseFunctions.js +97 -0
  96. package/utils/FirebaseRealtimeDB.js +498 -0
  97. package/utils/FirebaseStorage.js +612 -0
  98. package/utils/FormValidator.js +355 -0
  99. package/utils/GeoLocationService.js +62 -0
  100. package/utils/I18n.js +207 -0
  101. package/utils/IndexedDBManager.js +273 -0
  102. package/utils/InspectionOverlay.js +308 -0
  103. package/utils/NotificationManager.js +60 -0
  104. package/utils/OfflineSyncManager.js +342 -0
  105. package/utils/PayPalPayment.js +678 -0
  106. package/utils/QueryBuilder.js +478 -0
  107. package/utils/SafeArea.js +64 -0
  108. package/utils/SecureStorage.js +289 -0
  109. package/utils/StateManager.js +207 -0
  110. package/utils/StripePayment.js +552 -0
  111. package/utils/WebSocketClient.js +66 -0
  112. package/dist/canvasframework.js +0 -2
  113. package/dist/canvasframework.js.LICENSE.txt +0 -1
@@ -0,0 +1,116 @@
1
+ import Component from '../core/Component.js';
2
+ /**
3
+ * Menu contextuel
4
+ * @class
5
+ * @extends Component
6
+ * @property {string[]} options - Options du menu
7
+ * @property {Function} onSelect - Callback à la sélection
8
+ * @property {number} itemHeight - Hauteur d'un item
9
+ * @property {boolean} isOpen - État ouvert
10
+ * @property {number} hoveredIndex - Index survolé
11
+ */
12
+ class ContextMenu extends Component {
13
+ /**
14
+ * Crée une instance de ContextMenu
15
+ * @param {CanvasFramework} framework - Framework parent
16
+ * @param {Object} [options={}] - Options de configuration
17
+ * @param {string[]} [options.options=[]] - Options du menu
18
+ * @param {Function} [options.onSelect] - Callback à la sélection
19
+ */
20
+ constructor(framework, options = {}) {
21
+ super(framework, options);
22
+ this.options = options.options || [];
23
+ this.onSelect = options.onSelect;
24
+ this.itemHeight = 48;
25
+ this.height = this.options.length * this.itemHeight;
26
+ this.hoveredIndex = -1;
27
+ this.isOpen = true;
28
+
29
+ // Définir onClick pour le menu
30
+ this.onClick = this.handleClick.bind(this);
31
+ }
32
+
33
+ /**
34
+ * Dessine le menu contextuel
35
+ * @param {CanvasRenderingContext2D} ctx - Contexte de dessin
36
+ */
37
+ draw(ctx) {
38
+ if (!this.isOpen) return;
39
+
40
+ ctx.save();
41
+
42
+ // Background
43
+ ctx.fillStyle = '#FFFFFF';
44
+ ctx.shadowColor = 'rgba(0, 0, 0, 0.2)';
45
+ ctx.shadowBlur = 10;
46
+ ctx.fillRect(this.x, this.y, this.width, this.height);
47
+
48
+ ctx.shadowColor = 'transparent';
49
+
50
+ // Options
51
+ for (let i = 0; i < this.options.length; i++) {
52
+ const itemY = this.y + i * this.itemHeight;
53
+
54
+ if (this.hoveredIndex === i) {
55
+ ctx.fillStyle = '#F5F5F5';
56
+ ctx.fillRect(this.x, itemY, this.width, this.itemHeight);
57
+ }
58
+
59
+ ctx.fillStyle = '#000000';
60
+ ctx.font = '16px -apple-system, sans-serif';
61
+ ctx.textAlign = 'left';
62
+ ctx.textBaseline = 'middle';
63
+ ctx.fillText(this.options[i], this.x + 16, itemY + this.itemHeight / 2);
64
+
65
+ // Divider
66
+ if (i < this.options.length - 1) {
67
+ ctx.strokeStyle = '#E0E0E0';
68
+ ctx.lineWidth = 1;
69
+ ctx.beginPath();
70
+ ctx.moveTo(this.x, itemY + this.itemHeight);
71
+ ctx.lineTo(this.x + this.width, itemY + this.itemHeight);
72
+ ctx.stroke();
73
+ }
74
+ }
75
+
76
+ ctx.restore();
77
+ }
78
+
79
+ /**
80
+ * Vérifie si un point est dans les limites
81
+ * @param {number} x - Coordonnée X
82
+ * @param {number} y - Coordonnée Y
83
+ * @returns {boolean} True si le point est dans le menu
84
+ */
85
+ isPointInside(x, y) {
86
+ const adjustedY = y - this.framework.scrollOffset;
87
+ const inBounds = super.isPointInside(x, adjustedY);
88
+ if (inBounds) {
89
+ this.hoveredIndex = Math.floor((adjustedY - this.y) / this.itemHeight);
90
+ } else {
91
+ this.hoveredIndex = -1;
92
+ }
93
+ return inBounds;
94
+ }
95
+
96
+ /**
97
+ * Gère le clic sur le menu
98
+ * @private
99
+ */
100
+ handleClick() {
101
+ if (this.hoveredIndex >= 0 && this.onSelect) {
102
+ this.onSelect(this.hoveredIndex);
103
+ this.close();
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Ferme le menu contextuel
109
+ */
110
+ close() {
111
+ this.isOpen = false;
112
+ this.framework.remove(this);
113
+ }
114
+ }
115
+
116
+ export default ContextMenu;
@@ -0,0 +1,298 @@
1
+ import Component from '../core/Component.js';
2
+ import AndroidDatePickerDialog from '../components/AndroidDatePickerDialog.js';
3
+ import Modal from '../components/Modal.js';
4
+ import IOSDatePickerWheel from '../components/IOSDatePickerWheel.js';
5
+ import Button from '../components/Button.js';
6
+
7
+ /**
8
+ * Sélecteur de date (wrapper)
9
+ * @class
10
+ * @extends Component
11
+ * @property {Date} selectedDate - Date sélectionnée
12
+ * @property {Date|null} minDate - Date minimum
13
+ * @property {Date|null} maxDate - Date maximum
14
+ * @property {Function} onChange - Callback au changement
15
+ * @property {string} platform - Plateforme
16
+ * @property {string} label - Label
17
+ * @property {Modal|null} pickerModal - Modal iOS
18
+ */
19
+ class DatePicker extends Component {
20
+ /**
21
+ * Crée une instance de DatePicker
22
+ * @param {CanvasFramework} framework - Framework parent
23
+ * @param {Object} [options={}] - Options de configuration
24
+ * @param {Date} [options.selectedDate=new Date()] - Date initiale
25
+ * @param {Date} [options.minDate] - Date minimum
26
+ * @param {Date} [options.maxDate] - Date maximum
27
+ * @param {Function} [options.onChange] - Callback au changement
28
+ * @param {string} [options.label='Sélectionner une date'] - Label
29
+ */
30
+ constructor(framework, options = {}) {
31
+ super(framework, options);
32
+ this.selectedDate = options.selectedDate || new Date();
33
+ this.minDate = options.minDate || null;
34
+ this.maxDate = options.maxDate || null;
35
+ this.onChange = options.onChange;
36
+ this.platform = framework.platform;
37
+ this.label = options.label || 'Sélectionner une date';
38
+
39
+ // Options de personnalisation
40
+ this.headerBgColor = options.headerBgColor || '#6200EE'; // Android dialog header
41
+ this.inputBgColor = options.inputBgColor || null;
42
+ this.inputTextColor = options.inputTextColor || null;
43
+ this.inputBorderColor = options.inputBorderColor || null;
44
+ this.labelColor = options.labelColor || null;
45
+ this.inputHeight = options.inputHeight || 50;
46
+ this.inputRadius = options.inputRadius || (this.platform === 'cupertino' ? 10 : 0);
47
+ this.fontSize = options.fontSize || null;
48
+ this.selectedColor = options.selectedColor || '#6200EE'; // Android selected items
49
+ this.buttonColor = options.buttonColor || '#6200EE'; // Android buttons
50
+
51
+ // Dimensions
52
+ if (this.platform === 'cupertino') {
53
+ this.width = options.width || framework.width - 40;
54
+ this.pickerModal = null;
55
+ } else {
56
+ this.width = options.width || Math.min(320, framework.width - 40);
57
+ }
58
+
59
+ this.height = this.inputHeight;
60
+ this.onClick = this.openPicker.bind(this);
61
+ }
62
+
63
+ /**
64
+ * Ouvre le sélecteur de date
65
+ * @private
66
+ */
67
+ openPicker() {
68
+ if (this.platform === 'cupertino') {
69
+ this.openIOSPicker();
70
+ } else {
71
+ this.openAndroidDialog();
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Ouvre le sélecteur iOS
77
+ * @private
78
+ */
79
+
80
+
81
+ openIOSPicker() {
82
+ const modal = new Modal(this.framework, {
83
+ title: '',
84
+ width: this.framework.width,
85
+ height: 320,
86
+ showCloseButton: false,
87
+ closeOnOverlayClick: true,
88
+ bgColor: '#F9F9F9'
89
+ });
90
+
91
+ const picker = new IOSDatePickerWheel(this.framework, {
92
+ x: 0,
93
+ y: 20,
94
+ width: this.framework.width - 40,
95
+ selectedDate: this.selectedDate,
96
+ onChange: (date) => {
97
+ this.selectedDate = date;
98
+ if (this.onChange) this.onChange(date);
99
+ }
100
+ // Ajoutez ici d'autres options si IOSDatePickerWheel en supporte
101
+ });
102
+ modal.add(picker);
103
+
104
+ const btnOK = new Button(this.framework, {
105
+ x: (this.framework.width - 200) / 2,
106
+ y: 230,
107
+ width: 200,
108
+ height: 44,
109
+ text: 'Valider',
110
+ // Personnalisation du bouton si nécessaire
111
+ bgColor: this.buttonColor,
112
+ textColor: '#FFFFFF',
113
+ onClick: () => modal.hide()
114
+ });
115
+ modal.add(btnOK);
116
+
117
+ this.framework.add(modal);
118
+ modal.show();
119
+ this.pickerModal = modal;
120
+ }
121
+
122
+ /**
123
+ * Ouvre le dialog Android
124
+ * @private
125
+ */
126
+ openAndroidDialog() {
127
+ const dialog = new AndroidDatePickerDialog(this.framework, {
128
+ selectedDate: this.selectedDate,
129
+ onChange: (date) => {
130
+ this.selectedDate = date;
131
+ if (this.onChange) this.onChange(date);
132
+ },
133
+ // Transmettre toutes les options de couleur
134
+ headerBgColor: this.headerBgColor,
135
+ selectedColor: this.selectedColor,
136
+ buttonColor: this.buttonColor
137
+ });
138
+
139
+ this.framework.add(dialog);
140
+ dialog.show();
141
+ }
142
+
143
+ /**
144
+ * Dessine le sélecteur de date
145
+ * @param {CanvasRenderingContext2D} ctx - Contexte de dessin
146
+ */
147
+ draw(ctx) {
148
+ if (this.platform === 'cupertino') {
149
+ // Styles Cupertino
150
+ const bgColor = this.inputBgColor || '#FFFFFF';
151
+ const textColor = this.inputTextColor || '#000000';
152
+ const labelColor = this.labelColor || '#8E8E93';
153
+ const borderColor = this.inputBorderColor || '#C7C7CC';
154
+ const fontSize = this.fontSize || 16;
155
+
156
+ ctx.save();
157
+
158
+ // Background
159
+ ctx.fillStyle = bgColor;
160
+ this.roundRect(ctx, this.x, this.y, this.width, this.height, this.inputRadius);
161
+ ctx.fill();
162
+
163
+ // Border
164
+ ctx.strokeStyle = borderColor;
165
+ ctx.lineWidth = 1;
166
+ ctx.stroke();
167
+
168
+ // Label
169
+ ctx.fillStyle = labelColor;
170
+ ctx.font = '14px -apple-system, sans-serif';
171
+ ctx.textAlign = 'left';
172
+ ctx.textBaseline = 'middle';
173
+ ctx.fillText(this.label, this.x + 15, this.y + this.height / 2 - 10);
174
+
175
+ // Selected date
176
+ ctx.fillStyle = textColor;
177
+ ctx.font = `${fontSize}px -apple-system, sans-serif`;
178
+ ctx.fillText(this.formatDate(this.selectedDate), this.x + 15, this.y + this.height / 2 + 10);
179
+
180
+ // Chevron
181
+ ctx.strokeStyle = borderColor;
182
+ ctx.lineWidth = 2;
183
+ ctx.lineCap = 'round';
184
+ ctx.beginPath();
185
+ ctx.moveTo(this.x + this.width - 25, this.y + this.height / 2 - 5);
186
+ ctx.lineTo(this.x + this.width - 20, this.y + this.height / 2);
187
+ ctx.lineTo(this.x + this.width - 15, this.y + this.height / 2 - 5);
188
+ ctx.stroke();
189
+
190
+ ctx.restore();
191
+ } else {
192
+ // Styles Material
193
+ const bgColor = this.inputBgColor || (this.pressed ? '#F5F5F5' : '#FFFFFF');
194
+ const textColor = this.inputTextColor || '#000000';
195
+ const labelColor = this.labelColor || '#666666';
196
+ const borderColor = this.inputBorderColor || '#E0E0E0';
197
+ const fontSize = this.fontSize || 16;
198
+ const iconColor = labelColor;
199
+
200
+ ctx.save();
201
+
202
+ // Background
203
+ ctx.fillStyle = bgColor;
204
+ if (this.inputRadius > 0) {
205
+ this.roundRect(ctx, this.x, this.y, this.width, this.height, this.inputRadius);
206
+ ctx.fill();
207
+ } else {
208
+ ctx.fillRect(this.x, this.y, this.width, this.height);
209
+ }
210
+
211
+ // Border
212
+ ctx.strokeStyle = borderColor;
213
+ ctx.lineWidth = 1;
214
+ if (this.inputRadius > 0) {
215
+ this.roundRect(ctx, this.x, this.y, this.width, this.height, this.inputRadius);
216
+ ctx.stroke();
217
+ } else {
218
+ ctx.strokeRect(this.x, this.y, this.width, this.height);
219
+ }
220
+
221
+ // Calendar icon
222
+ ctx.strokeStyle = iconColor;
223
+ ctx.lineWidth = 2;
224
+ ctx.strokeRect(this.x + 15, this.y + 15, 20, 20);
225
+ ctx.beginPath();
226
+ ctx.moveTo(this.x + 18, this.y + 12);
227
+ ctx.lineTo(this.x + 18, this.y + 18);
228
+ ctx.moveTo(this.x + 32, this.y + 12);
229
+ ctx.lineTo(this.x + 32, this.y + 18);
230
+ ctx.stroke();
231
+
232
+ // Label
233
+ ctx.fillStyle = labelColor;
234
+ ctx.font = '12px Roboto, sans-serif';
235
+ ctx.textAlign = 'left';
236
+ ctx.textBaseline = 'top';
237
+ ctx.fillText(this.label, this.x + 45, this.y + 8);
238
+
239
+ // Date
240
+ ctx.fillStyle = textColor;
241
+ ctx.font = `${fontSize}px Roboto, sans-serif`;
242
+ ctx.textBaseline = 'bottom';
243
+ ctx.fillText(this.formatDate(this.selectedDate), this.x + 45, this.y + this.height - 8);
244
+
245
+ ctx.restore();
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Formate une date
251
+ * @param {Date} date - Date à formater
252
+ * @returns {string} Date formatée
253
+ * @private
254
+ */
255
+ formatDate(date) {
256
+ const day = date.getDate().toString().padStart(2, '0');
257
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
258
+ const year = date.getFullYear();
259
+ return `${day}/${month}/${year}`;
260
+ }
261
+
262
+ /**
263
+ * Dessine un rectangle avec coins arrondis
264
+ * @param {CanvasRenderingContext2D} ctx - Contexte de dessin
265
+ * @param {number} x - Position X
266
+ * @param {number} y - Position Y
267
+ * @param {number} width - Largeur
268
+ * @param {number} height - Hauteur
269
+ * @param {number} radius - Rayon des coins
270
+ * @private
271
+ */
272
+ roundRect(ctx, x, y, width, height, radius) {
273
+ ctx.beginPath();
274
+ ctx.moveTo(x + radius, y);
275
+ ctx.lineTo(x + width - radius, y);
276
+ ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
277
+ ctx.lineTo(x + width, y + height - radius);
278
+ ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
279
+ ctx.lineTo(x + radius, y + height);
280
+ ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
281
+ ctx.lineTo(x, y + radius);
282
+ ctx.quadraticCurveTo(x, y, x + radius, y);
283
+ ctx.closePath();
284
+ }
285
+
286
+ /**
287
+ * Vérifie si un point est dans les limites
288
+ * @param {number} x - Coordonnée X
289
+ * @param {number} y - Coordonnée Y
290
+ * @returns {boolean} True si le point est dans le sélecteur
291
+ */
292
+ isPointInside(x, y) {
293
+ return x >= this.x && x <= this.x + this.width &&
294
+ y >= this.y && y <= this.y + this.height;
295
+ }
296
+ }
297
+
298
+ export default DatePicker;