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.
- package/README.md +30 -0
- package/components/Accordion.js +265 -0
- package/components/AndroidDatePickerDialog.js +406 -0
- package/components/AppBar.js +398 -0
- package/components/AudioPlayer.js +611 -0
- package/components/Avatar.js +202 -0
- package/components/Banner.js +342 -0
- package/components/BottomNavigationBar.js +433 -0
- package/components/BottomSheet.js +234 -0
- package/components/Button.js +358 -0
- package/components/Camera.js +644 -0
- package/components/Card.js +193 -0
- package/components/Chart.js +700 -0
- package/components/Checkbox.js +166 -0
- package/components/Chip.js +212 -0
- package/components/CircularProgress.js +327 -0
- package/components/ContextMenu.js +116 -0
- package/components/DatePicker.js +298 -0
- package/components/Dialog.js +337 -0
- package/components/Divider.js +125 -0
- package/components/Drawer.js +276 -0
- package/components/FAB.js +270 -0
- package/components/FileUpload.js +315 -0
- package/components/FloatedCamera.js +644 -0
- package/components/IOSDatePickerWheel.js +430 -0
- package/components/ImageCarousel.js +219 -0
- package/components/ImageComponent.js +223 -0
- package/components/Input.js +831 -0
- package/components/InputDatalist.js +723 -0
- package/components/InputTags.js +624 -0
- package/components/List.js +95 -0
- package/components/ListItem.js +269 -0
- package/components/Modal.js +364 -0
- package/components/MorphingFAB.js +428 -0
- package/components/MultiSelectDialog.js +206 -0
- package/components/NumberInput.js +271 -0
- package/components/PasswordInput.js +462 -0
- package/components/ProgressBar.js +88 -0
- package/components/QRCodeReader.js +539 -0
- package/components/RadioButton.js +151 -0
- package/components/SearchInput.js +315 -0
- package/components/SegmentedControl.js +357 -0
- package/components/Select.js +199 -0
- package/components/SelectDialog.js +255 -0
- package/components/Slider.js +113 -0
- package/components/SliverAppBar.js +139 -0
- package/components/Snackbar.js +243 -0
- package/components/SpeedDialFAB.js +397 -0
- package/components/Stepper.js +281 -0
- package/components/SwipeableListItem.js +327 -0
- package/components/Switch.js +147 -0
- package/components/Table.js +492 -0
- package/components/Tabs.js +423 -0
- package/components/Text.js +141 -0
- package/components/TextField.js +151 -0
- package/components/TimePicker.js +934 -0
- package/components/Toast.js +236 -0
- package/components/TreeView.js +420 -0
- package/components/Video.js +397 -0
- package/components/View.js +140 -0
- package/components/VirtualList.js +120 -0
- package/core/CanvasFramework.js +3045 -0
- package/core/Component.js +243 -0
- package/core/ThemeManager.js +358 -0
- package/core/UIBuilder.js +267 -0
- package/core/WebGLCanvasAdapter.js +782 -0
- package/features/Column.js +43 -0
- package/features/Grid.js +47 -0
- package/features/LayoutComponent.js +43 -0
- package/features/OpenStreetMap.js +310 -0
- package/features/Positioned.js +33 -0
- package/features/PullToRefresh.js +328 -0
- package/features/Row.js +40 -0
- package/features/SignaturePad.js +257 -0
- package/features/Skeleton.js +193 -0
- package/features/Stack.js +21 -0
- package/index.js +119 -0
- package/manager/AccessibilityManager.js +107 -0
- package/manager/ErrorHandler.js +59 -0
- package/manager/FeatureFlags.js +60 -0
- package/manager/MemoryManager.js +107 -0
- package/manager/PerformanceMonitor.js +84 -0
- package/manager/SecurityManager.js +54 -0
- package/package.json +22 -16
- package/utils/AnimationEngine.js +734 -0
- package/utils/CryptoManager.js +303 -0
- package/utils/DataStore.js +403 -0
- package/utils/DevTools.js +1618 -0
- package/utils/DevToolsConsole.js +201 -0
- package/utils/EventBus.js +407 -0
- package/utils/FetchClient.js +74 -0
- package/utils/FirebaseAuth.js +653 -0
- package/utils/FirebaseCore.js +246 -0
- package/utils/FirebaseFirestore.js +581 -0
- package/utils/FirebaseFunctions.js +97 -0
- package/utils/FirebaseRealtimeDB.js +498 -0
- package/utils/FirebaseStorage.js +612 -0
- package/utils/FormValidator.js +355 -0
- package/utils/GeoLocationService.js +62 -0
- package/utils/I18n.js +207 -0
- package/utils/IndexedDBManager.js +273 -0
- package/utils/InspectionOverlay.js +308 -0
- package/utils/NotificationManager.js +60 -0
- package/utils/OfflineSyncManager.js +342 -0
- package/utils/PayPalPayment.js +678 -0
- package/utils/QueryBuilder.js +478 -0
- package/utils/SafeArea.js +64 -0
- package/utils/SecureStorage.js +289 -0
- package/utils/StateManager.js +207 -0
- package/utils/StripePayment.js +552 -0
- package/utils/WebSocketClient.js +66 -0
- package/dist/canvasframework.js +0 -2
- 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;
|