canvasframework 0.5.25 → 0.5.27

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 (2) hide show
  1. package/components/Card.js +202 -25
  2. package/package.json +1 -1
@@ -1,13 +1,14 @@
1
1
  import Component from '../core/Component.js';
2
+
2
3
  /**
3
4
  * Container avec système de layout et effet d'élévation
4
5
  * @class
5
6
  * @extends Component
6
7
  * @property {Component[]} children - Enfants
7
8
  * @property {number} padding - Padding interne
8
- * @property {number} gap - Espacement entre enfants
9
+ * @property {number} gap - Espacement constant entre enfants SEULEMENT
9
10
  * @property {string} direction - Direction ('column' ou 'row')
10
- * @property {string} align - Alignement ('start', 'center', 'end')
11
+ * @property {string} align - Alignement ('start', 'center', 'end', 'stretch')
11
12
  * @property {string} bgColor - Couleur de fond
12
13
  * @property {number} borderRadius - Rayon des coins
13
14
  * @property {number} elevation - Niveau d'élévation (ombres)
@@ -18,7 +19,7 @@ class Card extends Component {
18
19
  * @param {CanvasFramework} framework - Framework parent
19
20
  * @param {Object} [options={}] - Options de configuration
20
21
  * @param {number} [options.padding=0] - Padding interne
21
- * @param {number} [options.gap=0] - Espacement entre enfants
22
+ * @param {number} [options.gap=0] - Espacement constant entre enfants SEULEMENT
22
23
  * @param {string} [options.direction='column'] - Direction
23
24
  * @param {string} [options.align='start'] - Alignement
24
25
  * @param {string} [options.bgColor='transparent'] - Couleur de fond
@@ -29,12 +30,12 @@ class Card extends Component {
29
30
  super(framework, options);
30
31
  this.children = [];
31
32
  this.padding = options.padding || 0;
32
- this.gap = options.gap || 0;
33
+ this.gap = options.gap || 0; // Espacement UNIQUEMENT entre enfants
33
34
  this.direction = options.direction || 'column';
34
35
  this.align = options.align || 'start';
35
36
  this.bgColor = options.bgColor || 'transparent';
36
37
  this.borderRadius = options.borderRadius || 0;
37
- this.elevation = options.elevation || 0; // Nouvelle propriété
38
+ this.elevation = options.elevation || 0;
38
39
  }
39
40
 
40
41
  /**
@@ -49,32 +50,94 @@ class Card extends Component {
49
50
  }
50
51
 
51
52
  /**
52
- * Organise les enfants selon le layout
53
+ * Supprime un enfant
54
+ * @param {Component} child - Composant enfant à supprimer
55
+ * @returns {boolean} True si l'enfant a été supprimé
56
+ */
57
+ remove(child) {
58
+ const index = this.children.indexOf(child);
59
+ if (index > -1) {
60
+ this.children.splice(index, 1);
61
+ this.layout();
62
+ return true;
63
+ }
64
+ return false;
65
+ }
66
+
67
+ /**
68
+ * Supprime tous les enfants
69
+ */
70
+ clear() {
71
+ this.children = [];
72
+ this.layout();
73
+ }
74
+
75
+ /**
76
+ * Organise les enfants selon le layout avec espacement constant
53
77
  * @private
54
78
  */
55
79
  layout() {
56
- let currentX = this.x + this.padding;
57
- let currentY = this.y + this.padding;
58
-
59
- for (let child of this.children) {
60
- if (this.direction === 'column') {
61
- child.x = currentX;
80
+ if (this.children.length === 0) return;
81
+
82
+ if (this.direction === 'column') {
83
+ let currentY = this.y + this.padding;
84
+
85
+ for (let i = 0; i < this.children.length; i++) {
86
+ const child = this.children[i];
87
+
88
+ // Positionner l'enfant sans tenir compte de ses marges internes
62
89
  child.y = currentY;
90
+
91
+ // Gérer l'alignement horizontal
63
92
  if (this.align === 'center') {
64
93
  child.x = this.x + (this.width - child.width) / 2;
65
94
  } else if (this.align === 'end') {
66
95
  child.x = this.x + this.width - child.width - this.padding;
96
+ } else if (this.align === 'stretch') {
97
+ child.x = this.x + this.padding;
98
+ child.width = this.width - (this.padding * 2);
99
+ } else {
100
+ // Alignement 'start' par défaut
101
+ child.x = this.x + this.padding;
67
102
  }
68
- currentY += child.height + this.gap;
69
- } else {
103
+
104
+ // Mettre à jour la position Y pour l'enfant suivant
105
+ // UNIQUEMENT avec le gap spécifié, rien d'autre
106
+ currentY += child.height;
107
+
108
+ // Ajouter le gap seulement si ce n'est pas le dernier enfant
109
+ if (i < this.children.length - 1) {
110
+ currentY += this.gap;
111
+ }
112
+ }
113
+ } else {
114
+ // Direction 'row'
115
+ let currentX = this.x + this.padding;
116
+
117
+ for (let i = 0; i < this.children.length; i++) {
118
+ const child = this.children[i];
119
+
70
120
  child.x = currentX;
71
- child.y = currentY;
121
+
122
+ // Gérer l'alignement vertical
72
123
  if (this.align === 'center') {
73
124
  child.y = this.y + (this.height - child.height) / 2;
74
125
  } else if (this.align === 'end') {
75
126
  child.y = this.y + this.height - child.height - this.padding;
127
+ } else if (this.align === 'stretch') {
128
+ child.y = this.y + this.padding;
129
+ child.height = this.height - (this.padding * 2);
130
+ } else {
131
+ child.y = this.y + this.padding;
132
+ }
133
+
134
+ // Mettre à jour la position X pour l'enfant suivant
135
+ currentX += child.width;
136
+
137
+ // Ajouter le gap seulement si ce n'est pas le dernier enfant
138
+ if (i < this.children.length - 1) {
139
+ currentX += this.gap;
76
140
  }
77
- currentX += child.width + this.gap;
78
141
  }
79
142
  }
80
143
  }
@@ -87,12 +150,12 @@ class Card extends Component {
87
150
  */
88
151
  getShadowConfig(elevation) {
89
152
  const shadows = [
90
- { blur: 0, offsetY: 0, color: 'transparent', spread: 0 }, // 0 - pas d'ombre
91
- { blur: 2, offsetY: 1, color: 'rgba(0,0,0,0.12)', spread: 0 }, // 1 - léger
92
- { blur: 3, offsetY: 1, color: 'rgba(0,0,0,0.14)', spread: 0 }, // 2 - léger
93
- { blur: 4, offsetY: 2, color: 'rgba(0,0,0,0.16)', spread: 0 }, // 3 - moyen
94
- { blur: 6, offsetY: 3, color: 'rgba(0,0,0,0.18)', spread: 0 }, // 4 - moyen
95
- { blur: 8, offsetY: 4, color: 'rgba(0,0,0,0.20)', spread: 0 }, // 5 - fort
153
+ { blur: 0, offsetY: 0, color: 'transparent', spread: 0 },
154
+ { blur: 2, offsetY: 1, color: 'rgba(0,0,0,0.12)', spread: 0 },
155
+ { blur: 3, offsetY: 1, color: 'rgba(0,0,0,0.14)', spread: 0 },
156
+ { blur: 4, offsetY: 2, color: 'rgba(0,0,0,0.16)', spread: 0 },
157
+ { blur: 6, offsetY: 3, color: 'rgba(0,0,0,0.18)', spread: 0 },
158
+ { blur: 8, offsetY: 4, color: 'rgba(0,0,0,0.20)', spread: 0 },
96
159
  ];
97
160
 
98
161
  return shadows[Math.min(elevation, shadows.length - 1)];
@@ -108,16 +171,13 @@ class Card extends Component {
108
171
 
109
172
  const shadow = this.getShadowConfig(this.elevation);
110
173
 
111
- // Sauvegarder l'état du contexte
112
174
  ctx.save();
113
175
 
114
- // Configurer l'ombre
115
176
  ctx.shadowColor = shadow.color;
116
177
  ctx.shadowBlur = shadow.blur;
117
178
  ctx.shadowOffsetX = 0;
118
179
  ctx.shadowOffsetY = shadow.offsetY;
119
180
 
120
- // Dessiner un rectangle pour l'ombre
121
181
  if (this.borderRadius > 0) {
122
182
  ctx.beginPath();
123
183
  this.roundRect(ctx, this.x, this.y + shadow.offsetY, this.width, this.height, this.borderRadius);
@@ -174,6 +234,12 @@ class Card extends Component {
174
234
  * @private
175
235
  */
176
236
  roundRect(ctx, x, y, width, height, radius) {
237
+ if (radius === 0) {
238
+ ctx.rect(x, y, width, height);
239
+ return;
240
+ }
241
+
242
+ ctx.beginPath();
177
243
  ctx.moveTo(x + radius, y);
178
244
  ctx.lineTo(x + width - radius, y);
179
245
  ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
@@ -183,6 +249,7 @@ class Card extends Component {
183
249
  ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
184
250
  ctx.lineTo(x, y + radius);
185
251
  ctx.quadraticCurveTo(x, y, x + radius, y);
252
+ ctx.closePath();
186
253
  }
187
254
 
188
255
  /**
@@ -219,6 +286,116 @@ class Card extends Component {
219
286
  lower() {
220
287
  this.setElevation(this.elevation - 1);
221
288
  }
289
+
290
+ /**
291
+ * Met à jour la position de la carte (surcharge pour recalculer le layout)
292
+ * @param {number} x - Nouvelle position X
293
+ * @param {number} y - Nouvelle position Y
294
+ */
295
+ setPosition(x, y) {
296
+ const deltaX = x - this.x;
297
+ const deltaY = y - this.y;
298
+
299
+ super.setPosition(x, y);
300
+
301
+ // Déplacer tous les enfants avec la carte
302
+ for (let child of this.children) {
303
+ child.x += deltaX;
304
+ child.y += deltaY;
305
+ }
306
+ }
307
+
308
+ /**
309
+ * Met à jour les dimensions (surcharge pour recalculer le layout)
310
+ * @param {number} width - Nouvelle largeur
311
+ * @param {number} height - Nouvelle hauteur
312
+ */
313
+ setSize(width, height) {
314
+ super.setSize(width, height);
315
+ this.layout();
316
+ }
317
+
318
+ /**
319
+ * Définit l'espacement entre enfants
320
+ * @param {number} gap - Nouvel espacement
321
+ */
322
+ setGap(gap) {
323
+ this.gap = Math.max(0, gap);
324
+ this.layout();
325
+ }
326
+
327
+ /**
328
+ * Définit le padding
329
+ * @param {number} padding - Nouveau padding
330
+ */
331
+ setPadding(padding) {
332
+ this.padding = Math.max(0, padding);
333
+ this.layout();
334
+ }
335
+
336
+ /**
337
+ * Définit la direction du layout
338
+ * @param {string} direction - 'column' ou 'row'
339
+ */
340
+ setDirection(direction) {
341
+ if (direction === 'column' || direction === 'row') {
342
+ this.direction = direction;
343
+ this.layout();
344
+ }
345
+ }
346
+
347
+ /**
348
+ * Définit l'alignement
349
+ * @param {string} align - 'start', 'center', 'end' ou 'stretch'
350
+ */
351
+ setAlign(align) {
352
+ if (['start', 'center', 'end', 'stretch'].includes(align)) {
353
+ this.align = align;
354
+ this.layout();
355
+ }
356
+ }
357
+
358
+ /**
359
+ * Calcule la hauteur totale nécessaire pour contenir tous les enfants
360
+ * @returns {number} Hauteur totale nécessaire
361
+ */
362
+ getTotalHeight() {
363
+ if (this.children.length === 0) return 0;
364
+
365
+ const totalChildrenHeight = this.children.reduce((sum, child) => sum + child.height, 0);
366
+ const totalGapHeight = this.gap * Math.max(0, this.children.length - 1);
367
+ return totalChildrenHeight + totalGapHeight + (this.padding * 2);
368
+ }
369
+
370
+ /**
371
+ * Calcule la largeur totale nécessaire pour contenir tous les enfants
372
+ * @returns {number} Largeur totale nécessaire
373
+ */
374
+ getTotalWidth() {
375
+ if (this.children.length === 0) return 0;
376
+
377
+ const totalChildrenWidth = this.children.reduce((sum, child) => sum + child.width, 0);
378
+ const totalGapWidth = this.gap * Math.max(0, this.children.length - 1);
379
+ return totalChildrenWidth + totalGapWidth + (this.padding * 2);
380
+ }
381
+
382
+ /**
383
+ * Ajuste automatiquement la hauteur de la carte pour contenir tous les enfants
384
+ */
385
+ fitHeight() {
386
+ if (this.direction === 'column') {
387
+ this.height = this.getTotalHeight();
388
+ }
389
+ }
390
+
391
+ /**
392
+ * Ajuste automatiquement la largeur de la carte pour contenir tous les enfants
393
+ */
394
+ fitWidth() {
395
+ if (this.direction === 'row') {
396
+ this.width = this.getTotalWidth();
397
+ }
398
+ }
222
399
  }
223
400
 
224
401
  export default Card;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canvasframework",
3
- "version": "0.5.25",
3
+ "version": "0.5.27",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/beyons/CanvasFramework.git"