canvasframework 0.5.46 → 0.5.47

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.
@@ -1,192 +1,185 @@
1
1
  import Component from '../core/Component.js';
2
- /**
3
- * Chip (étiquette cliquable)
4
- * @class
5
- * @extends Component
6
- * @property {string} text - Texte
7
- * @property {string|null} icon - Icône
8
- * @property {boolean} closable - Peut être fermé
9
- * @property {string} platform - Plateforme
10
- * @property {string} bgColor - Couleur de fond
11
- * @property {string} textColor - Couleur du texte
12
- * @property {Function} onClose - Callback à la fermeture
13
- * @property {number} borderRadius - Rayon des coins
14
- * @property {Object|null} closeButtonRect - Rectangle du bouton fermer
15
- */
2
+
16
3
  class Chip extends Component {
17
- /**
18
- * Crée une instance de Chip
19
- * @param {CanvasFramework} framework - Framework parent
20
- * @param {Object} [options={}] - Options de configuration
21
- * @param {string} [options.text=''] - Texte
22
- * @param {string} [options.icon] - Icône
23
- * @param {boolean} [options.closable=true] - Peut être fermé
24
- * @param {string} [options.bgColor] - Couleur de fond (auto selon platform)
25
- * @param {string} [options.textColor='#000000'] - Couleur du texte
26
- * @param {Function} [options.onClose] - Callback à la fermeture
27
- * @param {number} [options.height=32] - Hauteur
28
- */
29
4
  constructor(framework, options = {}) {
30
5
  super(framework, options);
6
+
31
7
  this.text = options.text || '';
32
8
  this.icon = options.icon || null;
33
9
  this.closable = options.closable !== false;
34
- this.platform = framework.platform;
35
- this.bgColor = options.bgColor || (framework.platform === 'material' ? '#E0E0E0' : '#F0F0F0');
36
- this.textColor = options.textColor || '#000000';
10
+ this.platform = framework.platform; // 'material' ou 'cupertino'
37
11
  this.onClose = options.onClose;
38
-
39
- // Calculer la largeur en fonction du contenu
12
+
13
+ // Couleurs par défaut selon platform
14
+ if (this.platform === 'material') {
15
+ this.bgColor = options.bgColor || '#E0E0E0';
16
+ this.textColor = options.textColor || '#1F1F1F';
17
+ this.rippleColor = options.rippleColor || 'rgba(0,0,0,0.12)';
18
+ } else { // Cupertino
19
+ this.bgColor = options.bgColor || 'rgba(242,242,247,0.95)';
20
+ this.textColor = options.textColor || '#000';
21
+ }
22
+
23
+ // Dimensions
40
24
  const ctx = framework.ctx;
41
25
  ctx.font = '14px -apple-system, sans-serif';
42
26
  const textWidth = ctx.measureText(this.text).width;
43
- const iconWidth = this.icon ? 24 : 0;
27
+ const iconWidth = this.icon ? 20 : 0;
44
28
  const closeWidth = this.closable ? 24 : 0;
45
- this.width = iconWidth + textWidth + closeWidth + 24; // padding
29
+ this.width = iconWidth + textWidth + closeWidth + 24;
46
30
  this.height = options.height || 32;
47
31
  this.borderRadius = this.height / 2;
48
-
32
+
33
+ // Ripple pour Material
34
+ this.ripples = [];
35
+ this.pressed = false;
36
+
49
37
  this.closeButtonRect = null;
50
38
  this.onPress = this.handlePress.bind(this);
51
39
  }
52
40
 
53
- /**
54
- * Dessine le chip
55
- * @param {CanvasRenderingContext2D} ctx - Contexte de dessin
56
- */
41
+ addRipple(x, y) {
42
+ const ripple = {
43
+ x, y,
44
+ radius: 0,
45
+ maxRadius: Math.max(this.width, this.height) * 1.5,
46
+ opacity: 0.3
47
+ };
48
+ this.ripples.push(ripple);
49
+
50
+ const animate = () => {
51
+ let active = false;
52
+ for (let r of this.ripples) {
53
+ if (r.radius < r.maxRadius) {
54
+ r.radius += r.maxRadius / 15;
55
+ r.opacity -= 0.03;
56
+ active = true;
57
+ }
58
+ }
59
+ this.ripples = this.ripples.filter(r => r.opacity > 0);
60
+ if (active) requestAnimationFrame(animate);
61
+ };
62
+ animate();
63
+ }
64
+
57
65
  draw(ctx) {
58
66
  ctx.save();
59
-
67
+
60
68
  // Background
61
- ctx.fillStyle = this.pressed ? this.darkenColor(this.bgColor) : this.bgColor;
69
+ ctx.fillStyle = this.pressed && this.platform === 'cupertino'
70
+ ? this.darkenColor(this.bgColor, 0.1)
71
+ : this.bgColor;
72
+
62
73
  ctx.beginPath();
63
74
  this.roundRect(ctx, this.x, this.y, this.width, this.height, this.borderRadius);
64
75
  ctx.fill();
65
-
66
- let currentX = this.x + 12;
67
-
68
- // Icône
76
+
77
+ let offsetX = this.x + 12;
78
+
79
+ // Icon
69
80
  if (this.icon) {
70
81
  ctx.font = '16px sans-serif';
82
+ ctx.fillStyle = this.textColor;
71
83
  ctx.textAlign = 'left';
72
84
  ctx.textBaseline = 'middle';
73
- ctx.fillStyle = this.textColor;
74
- ctx.fillText(this.icon, currentX, this.y + this.height / 2);
75
- currentX += 20;
85
+ ctx.fillText(this.icon, offsetX, this.y + this.height / 2);
86
+ offsetX += 20;
76
87
  }
77
-
78
- // Texte
79
- ctx.font = '14px -apple-system, sans-serif';
88
+
89
+ // Text
90
+ ctx.font = this.platform === 'material'
91
+ ? '500 14px Roboto, sans-serif'
92
+ : '400 14px -apple-system';
80
93
  ctx.fillStyle = this.textColor;
81
- ctx.textAlign = 'left';
82
- ctx.textBaseline = 'middle';
83
- ctx.fillText(this.text, currentX, this.y + this.height / 2);
84
-
85
- // Bouton de fermeture
94
+ ctx.fillText(this.text, offsetX, this.y + this.height / 2);
95
+
96
+ // Ripple (Material)
97
+ if (this.platform === 'material') {
98
+ ctx.save();
99
+ ctx.beginPath();
100
+ this.roundRect(ctx, this.x, this.y, this.width, this.height, this.borderRadius);
101
+ ctx.clip();
102
+
103
+ this.ripples.forEach(r => {
104
+ ctx.globalAlpha = r.opacity;
105
+ ctx.fillStyle = this.rippleColor;
106
+ ctx.beginPath();
107
+ ctx.arc(this.x + r.x, this.y + r.y, r.radius, 0, Math.PI * 2);
108
+ ctx.fill();
109
+ });
110
+
111
+ ctx.restore();
112
+ ctx.globalAlpha = 1;
113
+ }
114
+
115
+ // Close button
86
116
  if (this.closable) {
87
- const closeX = this.x + this.width - 20;
88
- const closeY = this.y + this.height / 2;
89
-
90
- this.closeButtonRect = {
91
- x: closeX - 8,
92
- y: closeY - 8,
93
- width: 16,
94
- height: 16
95
- };
96
-
97
- // Cercle du bouton (optionnel)
98
- ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
117
+ const cx = this.x + this.width - 20;
118
+ const cy = this.y + this.height / 2;
119
+ this.closeButtonRect = { x: cx - 8, y: cy - 8, width: 16, height: 16 };
120
+
121
+ ctx.fillStyle = 'rgba(0,0,0,0.1)';
99
122
  ctx.beginPath();
100
- ctx.arc(closeX, closeY, 8, 0, Math.PI * 2);
123
+ ctx.arc(cx, cy, 8, 0, Math.PI * 2);
101
124
  ctx.fill();
102
-
103
- // Croix (X)
125
+
104
126
  ctx.strokeStyle = this.textColor;
105
127
  ctx.lineWidth = 1.5;
106
128
  ctx.lineCap = 'round';
107
129
  ctx.beginPath();
108
- ctx.moveTo(closeX - 4, closeY - 4);
109
- ctx.lineTo(closeX + 4, closeY + 4);
110
- ctx.stroke();
111
-
112
- ctx.beginPath();
113
- ctx.moveTo(closeX + 4, closeY - 4);
114
- ctx.lineTo(closeX - 4, closeY + 4);
130
+ ctx.moveTo(cx - 4, cy - 4);
131
+ ctx.lineTo(cx + 4, cy + 4);
132
+ ctx.moveTo(cx + 4, cy - 4);
133
+ ctx.lineTo(cx - 4, cy + 4);
115
134
  ctx.stroke();
116
135
  }
117
-
136
+
118
137
  ctx.restore();
119
138
  }
120
139
 
121
- /**
122
- * Gère la pression (clic)
123
- * @param {number} x - Coordonnée X
124
- * @param {number} y - Coordonnée Y
125
- * @private
126
- */
127
140
  handlePress(x, y) {
128
- const adjustedY = y - this.framework.scrollOffset;
129
-
130
- // Vérifier si on clique sur le bouton de fermeture
141
+ // Vérifie bouton close
131
142
  if (this.closable && this.closeButtonRect) {
132
- if (x >= this.closeButtonRect.x &&
133
- x <= this.closeButtonRect.x + this.closeButtonRect.width &&
134
- adjustedY >= this.closeButtonRect.y &&
135
- adjustedY <= this.closeButtonRect.y + this.closeButtonRect.height) {
136
- if (this.onClose) this.onClose();
143
+ if (x >= this.closeButtonRect.x && x <= this.closeButtonRect.x + this.closeButtonRect.width &&
144
+ y >= this.closeButtonRect.y && y <= this.closeButtonRect.y + this.closeButtonRect.height) {
145
+ this.onClose?.();
137
146
  return;
138
147
  }
139
148
  }
140
-
141
- // Sinon, déclencher onClick normal
142
- if (this.onClick) this.onClick();
149
+
150
+ // Ripple Material
151
+ if (this.platform === 'material') {
152
+ this.addRipple(x - this.x, y - this.y);
153
+ } else {
154
+ // Feedback press Cupertino
155
+ this.pressed = true;
156
+ setTimeout(() => { this.pressed = false; this.markDirty(); }, 100);
157
+ }
158
+
159
+ this.onClick?.();
143
160
  }
144
161
 
145
- /**
146
- * Dessine un rectangle avec coins arrondis
147
- * @param {CanvasRenderingContext2D} ctx - Contexte de dessin
148
- * @param {number} x - Position X
149
- * @param {number} y - Position Y
150
- * @param {number} width - Largeur
151
- * @param {number} height - Hauteur
152
- * @param {number} radius - Rayon des coins
153
- * @private
154
- */
155
- roundRect(ctx, x, y, width, height, radius) {
156
- ctx.beginPath();
157
- ctx.moveTo(x + radius, y);
158
- ctx.lineTo(x + width - radius, y);
159
- ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
160
- ctx.lineTo(x + width, y + height - radius);
161
- ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
162
- ctx.lineTo(x + radius, y + height);
163
- ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
164
- ctx.lineTo(x, y + radius);
165
- ctx.quadraticCurveTo(x, y, x + radius, y);
162
+ roundRect(ctx, x, y, w, h, r) {
163
+ ctx.moveTo(x + r, y);
164
+ ctx.lineTo(x + w - r, y);
165
+ ctx.quadraticCurveTo(x + w, y, x + w, y + r);
166
+ ctx.lineTo(x + w, y + h - r);
167
+ ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
168
+ ctx.lineTo(x + r, y + h);
169
+ ctx.quadraticCurveTo(x, y + h, x, y + h - r);
170
+ ctx.lineTo(x, y + r);
171
+ ctx.quadraticCurveTo(x, y, x + r, y);
166
172
  ctx.closePath();
167
173
  }
168
174
 
169
- /**
170
- * Assombrit une couleur
171
- * @param {string} color - Couleur
172
- * @returns {string} Couleur assombrie
173
- * @private
174
- */
175
- darkenColor(color) {
176
- // Utiliser la même méthode que Button
175
+ darkenColor(color, factor = 0.2) {
177
176
  if (color.startsWith('#')) {
178
- const rgb = this.hexToRgb(color);
179
- return `rgb(${Math.max(0, rgb.r - 20)}, ${Math.max(0, rgb.g - 20)}, ${Math.max(0, rgb.b - 20)})`;
177
+ const { r, g, b } = this.hexToRgb(color);
178
+ return `rgb(${Math.floor(r * (1 - factor))}, ${Math.floor(g * (1 - factor))}, ${Math.floor(b * (1 - factor))})`;
180
179
  }
181
180
  return color;
182
181
  }
183
182
 
184
- /**
185
- * Convertit une couleur hex en RGB
186
- * @param {string} hex - Couleur hexadécimale
187
- * @returns {{r: number, g: number, b: number}} Objet RGB
188
- * @private
189
- */
190
183
  hexToRgb(hex) {
191
184
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
192
185
  return result ? {
@@ -195,18 +188,6 @@ class Chip extends Component {
195
188
  b: parseInt(result[3], 16)
196
189
  } : { r: 0, g: 0, b: 0 };
197
190
  }
198
-
199
- /**
200
- * Vérifie si un point est dans les limites
201
- * @param {number} x - Coordonnée X
202
- * @param {number} y - Coordonnée Y
203
- * @returns {boolean} True si le point est dans le chip
204
- */
205
- isPointInside(x, y) {
206
- const adjustedY = y - this.framework.scrollOffset;
207
- return x >= this.x && x <= this.x + this.width &&
208
- adjustedY >= this.y && adjustedY <= this.y + this.height;
209
- }
210
191
  }
211
192
 
212
- export default Chip;
193
+ export default Chip;
@@ -1,151 +1,206 @@
1
1
  import Component from '../core/Component.js';
2
2
 
3
3
  /**
4
- * Bouton radio pour les sélections uniques
4
+ * RadioButton Material You & Cupertino
5
5
  * @class
6
6
  * @extends Component
7
- * @property {string} group - Groupe de boutons radio
8
- * @property {boolean} checked - État sélectionné
9
- * @property {string} label - Texte du label
10
- * @property {string} platform - Plateforme
11
- * @property {number} circleSize - Taille du cercle
12
- * @property {number} circleRadius - Rayon du cercle
13
- * @property {Function} onChange - Callback au changement
14
7
  */
15
8
  class RadioButton extends Component {
16
- /**
17
- * Crée une instance de RadioButton
18
- * @param {CanvasFramework} framework - Framework parent
19
- * @param {Object} [options={}] - Options de configuration
20
- * @param {string} [options.group='default'] - Groupe de boutons
21
- * @param {boolean} [options.checked=false] - État initial
22
- * @param {string} [options.label=''] - Texte du label
23
- * @param {Function} [options.onChange] - Callback au changement
24
- */
25
9
  constructor(framework, options = {}) {
26
10
  super(framework, options);
11
+
27
12
  this.group = options.group || 'default';
28
13
  this.checked = options.checked || false;
29
14
  this.label = options.label || '';
30
- this.labelColor = options.labelColor || '#000000'; // Nouvelle propriété
15
+ this.labelColor = options.labelColor || (framework.platform === 'material' ? '#1F1F1F' : '#000000');
31
16
  this.platform = framework.platform;
32
- this.circleSize = 24; // Taille du cercle
33
- this.circleRadius = 10; // Rayon du cercle
17
+
18
+ // Cercle
19
+ this.circleSize = 24; // Taille du bouton
20
+ this.circleRadius = 12; // Rayon du cercle extérieur
21
+ this.innerRadius = this.circleRadius * 0.5; // Cercle intérieur proportionnel
22
+
23
+ // Animation feedback
24
+ this.tapAlpha = 0; // Pour iOS
25
+ this.ripple = null; // Pour Material
26
+ this.rippleSpeed = 0.15;
27
+
34
28
  this.onChange = options.onChange;
35
-
36
- // Calculer la largeur totale incluant le label
37
- this.totalWidth = this.label ? this.circleSize + 8 + this.getTextWidth(this.label) : this.circleSize;
38
- this.width = this.totalWidth; // Mettre à jour la largeur totale
39
- this.height = this.circleSize; // Garder la même hauteur
40
-
41
- // Définir onClick
29
+
30
+ // Calcul largeur totale avec label
31
+ this.width = this.label ? this.circleSize + 8 + this.getTextWidth(this.label) : this.circleSize;
32
+ this.height = this.circleSize;
33
+
42
34
  this.onClick = this.handleClick.bind(this);
35
+ this.selectionProgress = this.checked ? 1 : 0; // 0 = non sélectionné, 1 = sélectionné
36
+ this.animSpeed = 0.2; // vitesse animation
43
37
  }
44
-
45
- /**
46
- * Calcule la largeur du texte
47
- * @param {string} text - Texte à mesurer
48
- * @returns {number} Largeur du texte
49
- * @private
50
- */
38
+
51
39
  getTextWidth(text) {
52
- // Utiliser le contexte temporaire pour mesurer le texte
53
40
  const ctx = this.framework.ctx;
54
41
  ctx.save();
55
- ctx.font = '16px -apple-system, sans-serif';
42
+ ctx.font = this.platform === 'material' ? '16px Roboto' : '16px -apple-system';
56
43
  const width = ctx.measureText(text).width;
57
44
  ctx.restore();
58
45
  return width;
59
46
  }
60
47
 
61
- /**
62
- * Gère le clic sur le bouton radio
63
- * @private
64
- */
65
- handleClick() {
66
- // Décocher les autres du même groupe
48
+ handleClick(x, y) {
49
+ // Décocher les autres du groupe
67
50
  for (let comp of this.framework.components) {
68
51
  if (comp instanceof RadioButton && comp.group === this.group && comp !== this) {
69
52
  comp.checked = false;
70
53
  }
71
54
  }
72
55
  this.checked = true;
56
+
57
+ // Feedback
58
+ if (this.platform === 'material') {
59
+ this.ripple = { x: x - this.x, y: y - this.y, radius: 0, opacity: 0.3 };
60
+ this.animateRipple();
61
+ } else {
62
+ this.tapAlpha = 0.3;
63
+ this.animateTap();
64
+ }
65
+
73
66
  if (this.onChange) this.onChange(this.checked);
74
67
  }
75
68
 
76
- /**
77
- * Dessine le bouton radio
78
- * @param {CanvasRenderingContext2D} ctx - Contexte de dessin
79
- */
69
+ animateRipple() {
70
+ if (!this.ripple) return;
71
+ const step = () => {
72
+ if (!this.ripple) return;
73
+ this.ripple.radius += this.circleSize * this.rippleSpeed;
74
+ this.ripple.opacity -= 0.02;
75
+
76
+ if (this.ripple.opacity <= 0) this.ripple = null;
77
+ else requestAnimationFrame(step);
78
+ this.markDirty();
79
+ };
80
+ step();
81
+ }
82
+
83
+ animateTap() {
84
+ const step = () => {
85
+ this.tapAlpha -= 0.03;
86
+ if (this.tapAlpha <= 0) this.tapAlpha = 0;
87
+ else requestAnimationFrame(step);
88
+ this.markDirty();
89
+ };
90
+ step();
91
+ }
92
+
93
+ update() {
94
+ const target = this.checked ? 1 : 0;
95
+ this.selectionProgress += (target - this.selectionProgress) * this.animSpeed;
96
+ this.selectionProgress = Math.max(0, Math.min(1, this.selectionProgress));
97
+
98
+
99
+ }
100
+
80
101
  draw(ctx) {
81
102
  ctx.save();
82
-
103
+
83
104
  const centerX = this.x + this.circleSize / 2;
84
105
  const centerY = this.y + this.circleSize / 2;
85
-
106
+
86
107
  if (this.platform === 'material') {
87
- // Outer circle
88
- ctx.strokeStyle = this.checked ? '#6200EE' : '#666666';
108
+ // Cercle extérieur
109
+ ctx.strokeStyle = this.checked ? '#6750A4' : '#666666';
89
110
  ctx.lineWidth = 2;
90
111
  ctx.beginPath();
91
112
  ctx.arc(centerX, centerY, this.circleRadius, 0, Math.PI * 2);
92
113
  ctx.stroke();
93
-
94
- // Inner circle
114
+
115
+ // Cercle intérieur
95
116
  if (this.checked) {
96
- ctx.fillStyle = '#6200EE';
117
+ ctx.fillStyle = '#6750A4';
97
118
  ctx.beginPath();
98
- ctx.arc(centerX, centerY, 5, 0, Math.PI * 2);
119
+ ctx.arc(centerX, centerY, this.innerRadius, 0, Math.PI * 2);
99
120
  ctx.fill();
100
121
  }
101
- } else {
102
- // Cupertino (iOS style)
122
+
123
+ // Ripple
124
+ if (this.ripple) {
125
+ ctx.globalAlpha = this.ripple.opacity;
126
+ ctx.fillStyle = '#6750A4';
127
+ ctx.beginPath();
128
+ ctx.arc(this.x + this.ripple.x, this.y + this.ripple.y, this.ripple.radius, 0, Math.PI * 2);
129
+ ctx.fill();
130
+ ctx.globalAlpha = 1;
131
+ }
132
+ } else {
133
+ // Cupertino
103
134
  if (this.checked) {
104
- // Cercle bleu rempli
105
135
  ctx.fillStyle = '#007AFF';
106
136
  ctx.beginPath();
107
137
  ctx.arc(centerX, centerY, this.circleRadius, 0, Math.PI * 2);
108
138
  ctx.fill();
109
-
110
- // Point blanc au centre
139
+
140
+ // Point central blanc
111
141
  ctx.fillStyle = '#FFFFFF';
112
142
  ctx.beginPath();
113
- ctx.arc(centerX, centerY, 4, 0, Math.PI * 2);
143
+ ctx.arc(centerX, centerY, this.innerRadius, 0, Math.PI * 2);
114
144
  ctx.fill();
115
145
  } else {
116
- // Cercle gris clair
117
146
  ctx.strokeStyle = '#D1D1D6';
118
147
  ctx.lineWidth = 1.5;
119
148
  ctx.beginPath();
120
149
  ctx.arc(centerX, centerY, this.circleRadius, 0, Math.PI * 2);
121
150
  ctx.stroke();
122
151
  }
152
+
153
+ // Tap overlay
154
+ if (this.tapAlpha > 0) {
155
+ ctx.fillStyle = `rgba(0,0,0,${this.tapAlpha})`;
156
+ ctx.beginPath();
157
+ ctx.arc(centerX, centerY, this.circleRadius, 0, Math.PI * 2);
158
+ ctx.fill();
159
+ }
123
160
  }
124
-
161
+
162
+ this.update();
163
+
164
+ // Cercle intérieur avec animation Material
165
+ if (this.platform === 'material') {
166
+ if (this.selectionProgress > 0) {
167
+ ctx.fillStyle = '#6200EE';
168
+ ctx.beginPath();
169
+ ctx.arc(centerX, centerY, 5 * this.selectionProgress, 0, Math.PI*2);
170
+ ctx.fill();
171
+ }
172
+ }
173
+
174
+ // Cercle bleu pour Cupertino
175
+ if (this.platform === 'cupertino' && this.selectionProgress > 0) {
176
+ ctx.fillStyle = '#007AFF';
177
+ ctx.beginPath();
178
+ ctx.arc(centerX, centerY, this.circleRadius * this.selectionProgress, 0, Math.PI*2);
179
+ ctx.fill();
180
+
181
+ // Point blanc au centre
182
+ ctx.fillStyle = '#FFFFFF';
183
+ ctx.beginPath();
184
+ ctx.arc(centerX, centerY, 4 * this.selectionProgress, 0, Math.PI*2);
185
+ ctx.fill();
186
+ }
187
+
125
188
  // Label
126
189
  if (this.label) {
127
- ctx.fillStyle = this.labelColor; // Au lieu de '#000000'
128
- ctx.font = '16px -apple-system, sans-serif';
190
+ ctx.fillStyle = this.labelColor;
191
+ ctx.font = this.platform === 'material' ? '16px Roboto' : '16px -apple-system';
129
192
  ctx.textAlign = 'left';
130
193
  ctx.textBaseline = 'middle';
131
194
  ctx.fillText(this.label, this.x + this.circleSize + 8, centerY);
132
195
  }
133
-
196
+
134
197
  ctx.restore();
135
198
  }
136
-
137
- /**
138
- * Vérifie si un point est dans les limites
139
- * @param {number} x - Coordonnée X
140
- * @param {number} y - Coordonnée Y
141
- * @returns {boolean} True si le point est dans le bouton
142
- */
199
+
143
200
  isPointInside(x, y) {
144
- return x >= this.x &&
145
- x <= this.x + this.width &&
146
- y >= this.y &&
147
- y <= this.y + this.height;
201
+ return x >= this.x && x <= this.x + this.width &&
202
+ y >= this.y && y <= this.y + this.height;
148
203
  }
149
204
  }
150
205
 
151
- export default RadioButton;
206
+ export default RadioButton;