eva-css-fluid 2.0.8 → 2.3.0

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/src/_eva.scss CHANGED
@@ -11,9 +11,22 @@ $Φ: 1.61803398875;
11
11
  $min: 0.5rem;
12
12
  $ez: 142.4;
13
13
  $unit: 1rem;
14
- $unit-fluid: 1vw;
14
+ $unit-fluid: 1vw !default;
15
15
 
16
- $screen: 1440;
16
+ $screen: 1440 !default;
17
+
18
+ // Émettre l'unité fluide comme custom property et la multiplier en calc(),
19
+ // au lieu de la figer au build. Permet de basculer un sous-arbre vw -> cqi
20
+ // à l'exécution (var --eva-fluid-unit) sans rebuild ni second fichier.
21
+ // $fluid-runtime: false -> sortie littérale (anciennes valeurs, zéro coût runtime).
22
+ $fluid-runtime: true !default;
23
+
24
+ // Plancher de lisibilité (a11y) — plus petite taille de texte tolérée, en px.
25
+ // Floore la borne min des clamp() de font-size : la borne min EST la taille
26
+ // petit écran (mobile), donc le plancher = taille mobile, pas le corps desktop.
27
+ // 13-14 reste lisible sur mobile ; 16 écraserait le rétrécissement fluide.
28
+ // 0 = désactivé (sortie inchangée, rétrocompatible).
29
+ $min-font-size: 0 !default;
17
30
 
18
31
  $eva: 0;
19
32
 
@@ -195,6 +208,42 @@ $font-properties: (
195
208
  @return round2($percent * $unit-fluid);
196
209
  }
197
210
 
211
+ // Construit le terme fluide central d'un clamp().
212
+ // $vw-val : longueur fluide (ex. 0.14vw) issue de getVW (éventuellement divisée).
213
+ // $op : "+" ou "-" (offset rem ajouté/retranché).
214
+ // $rem-val: offset statique en rem.
215
+ //
216
+ // Mode runtime ($fluid-runtime: true) :
217
+ // 0.14vw + 0.75rem -> calc(0.14 * var(--eva-fluid-unit, 1vw) + 0.75rem)
218
+ // Le coefficient (0.14) est la valeur numérique de $vw-val ; l'unité devient
219
+ // commutable à l'exécution. Valeur calculée identique au mode littéral tant
220
+ // que --eva-fluid-unit n'est pas redéfinie (fallback = $unit-fluid).
221
+ //
222
+ // Mode littéral ($fluid-runtime: false) :
223
+ // renvoie l'expression historique "0.14vw + 0.75rem".
224
+ @function fluidExpr($vw-val, $op, $rem-val) {
225
+ @if $fluid-runtime {
226
+ $coef: math.div($vw-val, $unit-fluid); // unité retirée -> coefficient pur
227
+ @if $op == "-" {
228
+ @return calc(#{$coef} * var(--eva-fluid-unit, #{$unit-fluid}) - #{$rem-val});
229
+ } @else {
230
+ @return calc(#{$coef} * var(--eva-fluid-unit, #{$unit-fluid}) + #{$rem-val});
231
+ }
232
+ } @else {
233
+ @return #{$vw-val} #{$op} #{$rem-val};
234
+ }
235
+ }
236
+
237
+ // Plancher de lisibilité : remonte une borne min (rem) à au moins
238
+ // $min-font-size (converti px -> rem pour suivre le zoom utilisateur).
239
+ // $min-font-size: 0 -> renvoie la valeur telle quelle (no-op).
240
+ @function floorRem($rem-val) {
241
+ @if $min-font-size > 0 {
242
+ @return math.max($rem-val, toRem($min-font-size));
243
+ }
244
+ @return $rem-val;
245
+ }
246
+
198
247
  @function getFinalMinDiv($size, $ratio) {
199
248
  @return round2(math.div($size, $ratio));
200
249
  }
@@ -228,6 +277,19 @@ $font-properties: (
228
277
  @return meta.type-of($var) == "map";
229
278
  }
230
279
 
280
+ // UNITÉ FLUIDE COMMUTABLE À L'EXÉCUTION
281
+ // =============================================================================
282
+ // Typer la propriété (au lieu d'une chaîne re-parsée à chaque substitution) :
283
+ // stockage d'une valeur <length> typée, zéro re-parse. inherits: true pour que
284
+ // l'override sur un conteneur se propage à tout son sous-arbre.
285
+ @if $fluid-runtime {
286
+ @property --eva-fluid-unit {
287
+ syntax: "<length>";
288
+ inherits: true;
289
+ initial-value: #{$unit-fluid};
290
+ }
291
+ }
292
+
231
293
  // GÉNÉRATION DES VARIABLES CSS PERSONNALISÉES
232
294
  // =============================================================================
233
295
  // Génère toujours les variables CSS (mode dev et prod)
@@ -247,10 +309,10 @@ $font-properties: (
247
309
  $rem-min: getMinRem($calc-percent);
248
310
  $rem-max: getMaxRem($calc-percent);
249
311
 
250
- $vw-light: #{round2(math.div(getVW($calc-percent), 4))} "+" #{round2(math.div($size-rem, 1.33))};
251
- $vw-medium: #{round2(math.div(getVW($calc-percent), 2))} "+" #{round2(math.div($size-rem, 2))};
252
- $vw-strong: #{round2(math.div(getVW($calc-percent), 1.33))} "+" #{round2(math.div($size-rem, 4))};
253
- $vw-extrem: #{getVW($calc-percent_)} "-" #{$rem-min};
312
+ $vw-light: fluidExpr(round2(math.div(getVW($calc-percent), 4)), "+", round2(math.div($size-rem, 1.33)));
313
+ $vw-medium: fluidExpr(round2(math.div(getVW($calc-percent), 2)), "+", round2(math.div($size-rem, 2)));
314
+ $vw-strong: fluidExpr(round2(math.div(getVW($calc-percent), 1.33)), "+", round2(math.div($size-rem, 4)));
315
+ $vw-extrem: fluidExpr(getVW($calc-percent_), "-", $rem-min);
254
316
 
255
317
  $final-min__: $min;
256
318
  $final-min_: getFinalMinDiv($rem-min, $Φ);
@@ -315,9 +377,9 @@ $font-properties: (
315
377
 
316
378
  $rem-min: getMinRem($calc-percent);
317
379
 
318
- $vw-light: #{round2(math.div(getVW($calc-percent), 4))} "+" #{round2(math.div($size-rem, 1.33))};
319
- $vw-medium: #{round2(math.div(getVW($calc-percent), 2))} "+" #{round2(math.div($size-rem, 2))};
320
- $vw-strong: #{round2(math.div(getVW($calc-percent), 1.33))} "+" #{round2(math.div($size-rem, 4))};
380
+ $vw-light: fluidExpr(round2(math.div(getVW($calc-percent), 4)), "+", round2(math.div($size-rem, 1.33)));
381
+ $vw-medium: fluidExpr(round2(math.div(getVW($calc-percent), 2)), "+", round2(math.div($size-rem, 2)));
382
+ $vw-strong: fluidExpr(round2(math.div(getVW($calc-percent), 1.33)), "+", round2(math.div($size-rem, 4)));
321
383
 
322
384
  $rem-max: getMaxRem($calc-percent);
323
385
 
@@ -326,17 +388,17 @@ $font-properties: (
326
388
 
327
389
  $css-fs-vars: (
328
390
  "__": (
329
- min: $final-min__,
391
+ min: floorRem($final-min__),
330
392
  fluid: $vw-strong,
331
393
  max: $rem-max
332
394
  ),
333
395
  "_": (
334
- min: $rem-min,
396
+ min: floorRem($rem-min),
335
397
  fluid: $vw-medium,
336
398
  max: $rem-max
337
399
  ),
338
400
  "": (
339
- min: $final-min,
401
+ min: floorRem($final-min),
340
402
  fluid: $vw-light,
341
403
  max: $rem-max
342
404
  ),
@@ -416,3 +478,24 @@ $fs: "fs";
416
478
  }
417
479
  }
418
480
  }
481
+
482
+ // UTILITAIRES CONTENEUR (opt-in) — unité fluide à l'exécution
483
+ // =============================================================================
484
+ // Disponibles uniquement en mode runtime + génération de classes.
485
+ // .eva-root : conteneur pleine largeur. cqi ≡ vw pour le livrable, et tout
486
+ // conteneur imbriqué peut alors override localement.
487
+ // (caveat: container-type sur un élément racine interagit avec
488
+ // position:sticky / overflow — à poser délibérément.)
489
+ // .eva-cqi : bascule les tokens EVA de ce sous-arbre sur la largeur de
490
+ // l'élément (cards dashboard, cellule de lab, demi-colonne…).
491
+ // container-type + override de --eva-fluid-unit, indissociables.
492
+ @if $fluid-runtime and $build-class {
493
+ .eva-root {
494
+ container: eva-root / inline-size;
495
+ }
496
+
497
+ .eva-cqi {
498
+ container-type: inline-size;
499
+ --eva-fluid-unit: 1cqi;
500
+ }
501
+ }
@@ -16,6 +16,10 @@ const defaults = {
16
16
  customClass: false,
17
17
  classConfig: {},
18
18
  debug: false,
19
+ fluidUnit: '1vw', // unité fluide: '1vw' (livrable) ou '1cqi' (conteneur)
20
+ referenceWidth: 1440, // largeur où les tokens atteignent leur valeur max
21
+ fluidRuntime: true, // émettre var(--eva-fluid-unit) commutable à l'exécution
22
+ minFontSize: 0, // plancher a11y (px) sur les min de font-size; 0 = désactivé
19
23
  theme: {
20
24
  name: 'eva',
21
25
  colors: {
@@ -110,13 +114,44 @@ function validateConfig(config, source = 'config file') {
110
114
  }
111
115
 
112
116
  // Validate boolean flags
113
- const booleanFlags = ['buildClass', 'pxRemSuffix', 'nameBySize', 'customClass', 'debug'];
117
+ const booleanFlags = ['buildClass', 'pxRemSuffix', 'nameBySize', 'customClass', 'debug', 'fluidRuntime'];
114
118
  booleanFlags.forEach(flag => {
115
119
  if (config[flag] !== undefined && typeof config[flag] !== 'boolean') {
116
120
  errors.push(`${flag}: Must be a boolean (true or false)`);
117
121
  }
118
122
  });
119
123
 
124
+ // Validate fluidUnit (relative length: viewport or container unit)
125
+ if (config.fluidUnit !== undefined) {
126
+ if (typeof config.fluidUnit !== 'string') {
127
+ errors.push('fluidUnit: Must be a string CSS length (e.g. "1vw" or "1cqi")');
128
+ } else if (!/^\d*\.?\d+(vw|vi|vmin|vmax|cqi|cqw|cqmin|cqmax|svw|lvw|dvw)$/.test(config.fluidUnit.trim())) {
129
+ errors.push(
130
+ `fluidUnit: "${config.fluidUnit}" is not a recognized fluid unit. ` +
131
+ 'Use a viewport unit (vw, vi, svw, lvw, dvw) or a container unit (cqi, cqw, cqmin, cqmax)'
132
+ );
133
+ }
134
+ }
135
+
136
+ // Validate referenceWidth
137
+ if (config.referenceWidth !== undefined) {
138
+ if (typeof config.referenceWidth !== 'number' || config.referenceWidth <= 0) {
139
+ errors.push('referenceWidth: Must be a positive number (px value, e.g. 1440)');
140
+ }
141
+ }
142
+
143
+ // Validate minFontSize (a11y readability floor, px; 0 = off)
144
+ if (config.minFontSize !== undefined) {
145
+ if (typeof config.minFontSize !== 'number' || config.minFontSize < 0) {
146
+ errors.push('minFontSize: Must be a number >= 0 (px value, e.g. 14; 0 disables the floor)');
147
+ } else if (config.minFontSize > 16) {
148
+ warnings.push(
149
+ `minFontSize: ${config.minFontSize}px is high for a mobile floor — the min bound is the ` +
150
+ `small-screen size, not the desktop body size (recommended: 13-14)`
151
+ );
152
+ }
153
+ }
154
+
120
155
  // Validate classConfig
121
156
  if (config.classConfig !== undefined) {
122
157
  if (typeof config.classConfig !== 'object' || Array.isArray(config.classConfig)) {
@@ -375,6 +410,12 @@ function toScssVariables(config) {
375
410
  lines.push(`$custom-class: ${config.customClass};`);
376
411
  lines.push(`$debug: ${config.debug};`);
377
412
 
413
+ // Fluid engine (runtime-switchable unit)
414
+ lines.push(`$unit-fluid: ${config.fluidUnit || defaults.fluidUnit};`);
415
+ lines.push(`$reference-width: ${config.referenceWidth || defaults.referenceWidth};`);
416
+ lines.push(`$fluid-runtime: ${config.fluidRuntime !== undefined ? config.fluidRuntime : defaults.fluidRuntime};`);
417
+ lines.push(`$min-font-size: ${config.minFontSize !== undefined ? config.minFontSize : defaults.minFontSize};`);
418
+
378
419
  // Class config (convert to SCSS map)
379
420
  if (config.customClass && Object.keys(config.classConfig).length > 0) {
380
421
  lines.push('$class-config: (');
package/src/core.scss CHANGED
@@ -12,6 +12,10 @@ $font-sizes: 12, 14, 16, 18, 20, 24, 32, 48 !default;
12
12
  $px-rem-suffix: false !default;
13
13
  $name-by-size: true !default;
14
14
  $class-config: () !default;
15
+ $unit-fluid: 1vw !default; // unité fluide (vw|cqi) + fallback runtime
16
+ $reference-width: 1440 !default; // largeur où les tokens atteignent leur max
17
+ $fluid-runtime: true !default; // émettre var(--eva-fluid-unit) en calc()
18
+ $min-font-size: 0 !default; // plancher a11y (px) sur les min de font-size; 0 = off
15
19
 
16
20
  // Core variable generation system
17
21
  @use '_eva' with (
@@ -21,7 +25,11 @@ $class-config: () !default;
21
25
  $px-rem-suffix: $px-rem-suffix,
22
26
  $name-by-size: $name-by-size,
23
27
  $custom-class: false,
24
- $class-config: $class-config
28
+ $class-config: $class-config,
29
+ $unit-fluid: $unit-fluid,
30
+ $screen: $reference-width,
31
+ $fluid-runtime: $fluid-runtime,
32
+ $min-font-size: $min-font-size
25
33
  );
26
34
 
27
35
  // Color system
package/src/index.scss CHANGED
@@ -15,6 +15,10 @@ $name-by-size: true !default;
15
15
  $custom-class: false !default;
16
16
  $class-config: () !default;
17
17
  $debug: false !default;
18
+ $unit-fluid: 1vw !default; // unité fluide (vw|cqi) + fallback runtime
19
+ $reference-width: 1440 !default; // largeur où les tokens atteignent leur max
20
+ $fluid-runtime: true !default; // émettre var(--eva-fluid-unit) en calc()
21
+ $min-font-size: 0 !default; // plancher a11y (px) sur les min de font-size; 0 = off
18
22
 
19
23
  // ===========================================
20
24
  // CORE FRAMEWORK MODULES
@@ -31,7 +35,11 @@ $debug: false !default;
31
35
  $name-by-size: $name-by-size,
32
36
  $custom-class: $custom-class,
33
37
  $class-config: $class-config,
34
- $debug: $debug
38
+ $debug: $debug,
39
+ $unit-fluid: $unit-fluid,
40
+ $screen: $reference-width,
41
+ $fluid-runtime: $fluid-runtime,
42
+ $min-font-size: $min-font-size
35
43
  );
36
44
 
37
45
  // OKLCH color system with opacity/brightness modifiers
@@ -11,6 +11,10 @@ $font-sizes: 12, 14, 16, 18, 20, 24, 32, 48 !default;
11
11
  $px-rem-suffix: false !default;
12
12
  $name-by-size: true !default;
13
13
  $class-config: () !default;
14
+ $unit-fluid: 1vw !default; // unité fluide (vw|cqi) + fallback runtime
15
+ $reference-width: 1440 !default; // largeur où les tokens atteignent leur max
16
+ $fluid-runtime: true !default; // émettre var(--eva-fluid-unit) en calc()
17
+ $min-font-size: 0 !default; // plancher a11y (px) sur les min de font-size; 0 = off
14
18
 
15
19
  // Import only the core variable generation system
16
20
  @use '_eva' with (
@@ -20,7 +24,11 @@ $class-config: () !default;
20
24
  $px-rem-suffix: $px-rem-suffix,
21
25
  $name-by-size: $name-by-size,
22
26
  $custom-class: false,
23
- $class-config: $class-config
27
+ $class-config: $class-config,
28
+ $unit-fluid: $unit-fluid,
29
+ $screen: $reference-width,
30
+ $fluid-runtime: $fluid-runtime,
31
+ $min-font-size: $min-font-size
24
32
  );
25
33
 
26
34
  // Import colors system