eva-css-fluid 2.0.0 → 2.0.6

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 CHANGED
@@ -64,6 +64,38 @@ yarn add eva-css-fluid
64
64
 
65
65
  **Migrating from another framework?** See the [Migration Guide](./MIGRATION.md) for detailed instructions.
66
66
 
67
+ ## 🚦 Which Configuration Method Should I Use?
68
+
69
+ EVA CSS can be configured in two ways. **Choose based on your project needs:**
70
+
71
+ ### For Quick Start / Learning
72
+ šŸ‘‰ **Use SCSS Variables** - Everything in one file, works immediately
73
+
74
+ ### For Production Projects
75
+ Choose based on your needs:
76
+
77
+ | You want... | Use... |
78
+ |-------------|--------|
79
+ | Simplicity, no build scripts | **SCSS Variables** (`@use ... with ()`) |
80
+ | Centralized config, multiple SCSS files | **JSON Config** (requires custom build script) |
81
+ | Watch mode without complexity | **SCSS Variables** |
82
+ | Config validation, better DX | **JSON Config** (requires custom build script) |
83
+
84
+ šŸ’” **You can start with SCSS variables and migrate to JSON later - the generated CSS is identical!**
85
+
86
+ ### Option Comparison
87
+
88
+ | Feature | SCSS Variables | JSON Config |
89
+ |---------|----------------|-------------|
90
+ | **Setup complexity** | ⭐ Simple | ⭐⭐⭐ Requires script |
91
+ | **Works with `npx sass`** | āœ… Yes, immediately | āš ļø No, needs custom script |
92
+ | **Config location** | Inside SCSS file | Separate `eva.config.cjs` |
93
+ | **Multiple SCSS files** | āš ļø Config duplicated | āœ… Shared config |
94
+ | **Validation** | āŒ No | āœ… `npx eva-css validate` |
95
+ | **Generated CSS** | āœ… Identical output | āœ… Identical output |
96
+
97
+ **See detailed workflows below** for implementation examples.
98
+
67
99
  ## šŸš€ Quick Start
68
100
 
69
101
  ### New Project (Recommended)
@@ -120,9 +152,39 @@ npx sass --load-path=node_modules styles/main.scss:styles/main.css
120
152
 
121
153
  ### Using SCSS with Custom Configuration
122
154
 
123
- **This is the main feature of EVA CSS!** You can configure EVA CSS in two ways:
155
+ **This is the main feature of EVA CSS!** Extract sizes from your design and configure EVA to generate only what you need.
156
+
157
+ #### Option 1: SCSS Variables (Recommended for Beginners)
158
+
159
+ **Direct configuration in your SCSS file** - Works immediately with `npx sass`:
160
+
161
+ ```scss
162
+ // Example: Sizes extracted from Figma design
163
+ @use 'eva-css-fluid' with (
164
+ $sizes: 4, 8, 16, 32, 64, 128, // šŸ‘ˆ Change these to YOUR design sizes!
165
+ $font-sizes: 14, 16, 20, 24, 32, // šŸ‘ˆ Change these to YOUR font sizes!
166
+ $build-class: true,
167
+ $px-rem-suffix: false
168
+ );
169
+ ```
124
170
 
125
- #### Option 1: JSON Configuration (Recommended)
171
+ **Compile immediately:**
172
+
173
+ ```bash
174
+ npx sass --load-path=node_modules styles/main.scss:styles/main.css
175
+ ```
176
+
177
+ āœ… **Advantages:**
178
+ - Works immediately with standard Sass compilation
179
+ - No additional build scripts needed
180
+ - Perfect for watch mode: `npx sass --watch ...`
181
+ - Great for learning and simple projects
182
+
183
+ āš ļø **Note:** If you import EVA in multiple SCSS files, you'll need to duplicate the configuration.
184
+
185
+ #### Option 2: JSON Configuration (Advanced - Requires Build Script)
186
+
187
+ **Centralized configuration file** - Better for complex projects with multiple SCSS files:
126
188
 
127
189
  Create `eva.config.cjs` in your project root:
128
190
 
@@ -136,42 +198,72 @@ module.exports = {
136
198
  };
137
199
  ```
138
200
 
139
- Or add to your `package.json`:
140
-
141
- ```json
142
- {
143
- "eva": {
144
- "sizes": [4, 8, 16, 32, 64, 128],
145
- "fontSizes": [14, 16, 20, 24, 32],
146
- "buildClass": true
147
- }
148
- }
149
- ```
150
-
151
- Then simply import EVA CSS:
201
+ Then in your SCSS:
152
202
 
153
203
  ```scss
154
204
  @use 'eva-css-fluid';
155
205
  ```
156
206
 
157
- And build with the integrated script:
207
+ āš ļø **IMPORTANT:** JSON configuration requires a **custom build script** to work. SCSS cannot execute JavaScript directly.
158
208
 
209
+ **You have two choices:**
210
+
211
+ **A) Use the EVA package's build script** (for building EVA itself):
159
212
  ```bash
213
+ # This is only for building the EVA CSS package itself, NOT for your project
214
+ cd node_modules/eva-css-fluid
160
215
  npm run build
161
- # Configuration is automatically loaded from eva.config.cjs or package.json
162
216
  ```
163
217
 
164
- #### Option 2: SCSS Variables
218
+ **B) Create your own build script** (recommended for user projects):
165
219
 
166
- ```scss
167
- // Example: Sizes extracted from Figma design
168
- @use 'eva-css-fluid' with (
169
- $sizes: 4, 8, 16, 32, 64, 128, // šŸ‘ˆ Change these to YOUR design sizes!
170
- $font-sizes: 14, 16, 20, 24, 32, // šŸ‘ˆ Change these to YOUR font sizes!
171
- $build-class: true,
172
- $px-rem-suffix: false
173
- );
174
- ```
220
+ 1. Copy the build script template:
221
+ ```bash
222
+ # Create scripts directory if needed
223
+ mkdir -p scripts
224
+
225
+ # Copy the ready-to-use script from the monorepo examples
226
+ cp node_modules/eva-css-fluid/../../examples/user-scripts/build-with-config.js scripts/build-eva.js
227
+
228
+ # Or download directly from GitHub
229
+ curl -o scripts/build-eva.js https://raw.githubusercontent.com/nkdeus/eva-framework/main/examples/user-scripts/build-with-config.js
230
+ ```
231
+
232
+ 2. Add npm script to your `package.json`:
233
+ ```json
234
+ {
235
+ "scripts": {
236
+ "build:css": "node scripts/build-eva.js styles/main.scss dist/main.css",
237
+ "watch:css": "nodemon --watch eva.config.cjs --watch styles/ --exec 'npm run build:css'"
238
+ }
239
+ }
240
+ ```
241
+
242
+ 3. Build your CSS:
243
+ ```bash
244
+ npm run build:css
245
+ ```
246
+
247
+ **What the script does:**
248
+ - Reads your `eva.config.cjs` configuration
249
+ - Converts JSON config → SCSS variables
250
+ - Compiles SCSS with the injected config
251
+ - Handles HEX → OKLCH color conversion automatically
252
+
253
+ šŸ“š **See [examples/user-scripts/README.md](../../examples/user-scripts/README.md) for detailed documentation**
254
+
255
+ āœ… **Advantages:**
256
+ - Single config file shared across multiple SCSS files
257
+ - Config validation with `npx eva-css validate`
258
+ - Cleaner SCSS files
259
+ - Better for large projects
260
+
261
+ āš ļø **Disadvantages:**
262
+ - Requires custom build script setup
263
+ - More complex workflow
264
+ - Not compatible with standard `npx sass` command
265
+
266
+ šŸ’” **New to EVA CSS?** Start with **Option 1 (SCSS Variables)** and migrate to JSON config later if needed!
175
267
 
176
268
  **Real example from a Figma project:**
177
269
 
@@ -189,6 +281,60 @@ npm run build
189
281
  // var(--4), var(--8), var(--16), var(--32), var(--64), var(--120), var(--141)
190
282
  ```
191
283
 
284
+ ## ā“ FAQ - Configuration
285
+
286
+ ### Q: Why doesn't `@use 'eva-css-fluid'` automatically load `eva.config.cjs`?
287
+
288
+ **A:** SCSS cannot execute JavaScript during compilation. The `eva.config.cjs` file must be read **before** SCSS compilation and transformed into SCSS variables.
289
+
290
+ **Solutions:**
291
+ - **Simple:** Use `@use ... with ()` directly in your SCSS (no script needed)
292
+ - **Advanced:** Create a build script that reads the config and injects it into SCSS (see Option 2 above)
293
+
294
+ ### Q: What's the difference between "JSON config" and "SCSS variables"?
295
+
296
+ **A:** The generated CSS is **100% identical**. It's only a matter of workflow organization:
297
+
298
+ | Method | Configuration Location | Compilation Command |
299
+ |--------|----------------------|---------------------|
300
+ | SCSS Variables | Inside SCSS file with `@use ... with ()` | `npx sass styles.scss` |
301
+ | JSON Config | Separate `eva.config.cjs` file | Custom script required |
302
+
303
+ **Choose based on your workflow:**
304
+ - **Simple projects:** SCSS variables (quick and easy)
305
+ - **Complex projects with multiple SCSS files:** JSON config (shared configuration)
306
+
307
+ ### Q: Can I use the `scripts/build-with-config.cjs` from the eva-css package?
308
+
309
+ **A:** That script is designed to **build EVA CSS itself** (the framework), not your project.
310
+
311
+ For your project, you need to:
312
+ 1. Create your own build script (see template in `examples/user-scripts/`)
313
+ 2. Or use SCSS variables with `@use ... with ()` instead
314
+
315
+ ### Q: Which option should I use for my project?
316
+
317
+ **A:** Follow this decision tree:
318
+
319
+ ```
320
+ Do you have multiple SCSS files that need the same EVA config?
321
+ ā”œā”€ NO → Use SCSS Variables (simpler)
322
+ └─ YES → Do you want config validation and centralized settings?
323
+ ā”œā”€ YES → Use JSON Config (requires build script setup)
324
+ └─ NO → Use SCSS Variables (simpler, just duplicate config)
325
+ ```
326
+
327
+ ### Q: Can I migrate from SCSS variables to JSON config later?
328
+
329
+ **A:** Yes! Since both methods generate identical CSS, you can switch at any time:
330
+
331
+ 1. Create `eva.config.cjs` with your settings
332
+ 2. Set up a build script (see examples/)
333
+ 3. Update your SCSS from `@use ... with ()` to `@use 'eva-css-fluid'`
334
+ 4. Update your build command
335
+
336
+ No CSS changes needed!
337
+
192
338
  ## šŸŽØ Configuration Options
193
339
 
194
340
  ### JSON Configuration (eva.config.cjs or package.json)
@@ -246,6 +392,30 @@ module.exports = {
246
392
  };
247
393
  ```
248
394
 
395
+ **Real-world example** (Tailwind colors to EVA theme):
396
+
397
+ ```javascript
398
+ // Extract colors from your design system
399
+ module.exports = {
400
+ theme: {
401
+ name: 'myproject',
402
+ colors: {
403
+ brand: '#3b82f6', // Tailwind blue-500
404
+ accent: '#22c55e', // Tailwind green-500
405
+ extra: '#a855f7' // Tailwind purple-500
406
+ },
407
+ lightMode: { lightness: 98, darkness: 10 },
408
+ darkMode: { lightness: 8, darkness: 95 },
409
+ autoSwitch: true // Auto dark mode with prefers-color-scheme
410
+ }
411
+ };
412
+ ```
413
+
414
+ **These HEX colors are automatically converted to:**
415
+ - `#3b82f6` → `oklch(57.4% 0.213 263.8)` (perceptually uniform blue)
416
+ - `#22c55e` → `oklch(72.6% 0.200 147.6)` (perceptually uniform green)
417
+ - `#a855f7` → `oklch(60.8% 0.248 302.7)` (perceptually uniform purple)
418
+
249
419
  **Available colors:** `brand`, `accent`, `extra`, `dark`, `light`
250
420
 
251
421
  **Color formats:**
@@ -481,6 +651,251 @@ var(--brand-b_) // More brighter
481
651
  }
482
652
  ```
483
653
 
654
+ ## ā— Troubleshooting
655
+
656
+ ### Common Issues and Solutions
657
+
658
+ #### "The target selector was not found" with @extend
659
+
660
+ **Error:**
661
+ ```
662
+ Error: The target selector was not found.
663
+ Use "@extend .w-64 !optional" to avoid this error.
664
+ ```
665
+
666
+ **Cause:** You're using `@use` instead of `@forward` when trying to extend EVA classes.
667
+
668
+ **Solution:** Use `@forward` to expose EVA classes in your module:
669
+
670
+ ```scss
671
+ // āŒ Wrong - @use doesn't expose classes for @extend
672
+ @use 'eva-css-fluid';
673
+
674
+ .my-class {
675
+ @extend .w-64; // Error!
676
+ }
677
+
678
+ // āœ… Correct - @forward exposes classes
679
+ @forward 'eva-css-fluid';
680
+
681
+ .my-class {
682
+ @extend .w-64; // Works!
683
+ }
684
+ ```
685
+
686
+ #### Theme colors not appearing in compiled CSS
687
+
688
+ **Problem:** You defined colors in `eva.config.cjs` but they don't show up in the output CSS.
689
+
690
+ **Solutions:**
691
+
692
+ 1. **Using JSON config?** Make sure you're using the build script:
693
+ ```bash
694
+ # Won't work - SCSS can't read .cjs files
695
+ npx sass styles/main.scss dist/main.css
696
+
697
+ # Use this instead
698
+ node scripts/build-eva.js styles/main.scss dist/main.css
699
+ ```
700
+
701
+ 2. **Import colors module** if using SCSS variables:
702
+ ```scss
703
+ @use 'eva-css-fluid/src/colors' with (
704
+ $theme-name: 'myapp',
705
+ $theme-colors: (
706
+ brand: (lightness: 62.8, chroma: 0.258, hue: 29.23),
707
+ // ... more colors
708
+ )
709
+ );
710
+ ```
711
+
712
+ 3. **Apply theme class in HTML:**
713
+ ```html
714
+ <!-- Without this class, theme colors won't be active -->
715
+ <body class="current-theme theme-myapp">
716
+ <h1 class="_c-brand">Now this works!</h1>
717
+ </body>
718
+ ```
719
+
720
+ #### HEX colors not converting to OKLCH
721
+
722
+ **Problem:** You put HEX colors in `eva.config.cjs` but get an error or they don't work.
723
+
724
+ **Cause:** The build script needs `eva-colors` to convert HEX → OKLCH automatically.
725
+
726
+ **Solution:**
727
+
728
+ 1. Install `eva-colors` as a dependency:
729
+ ```bash
730
+ npm install eva-colors
731
+ ```
732
+
733
+ 2. Or convert colors manually:
734
+ ```bash
735
+ npx eva-color convert "#ff5733"
736
+ # Output: oklch(62.8% 0.258 29.23)
737
+ ```
738
+
739
+ 3. Then use OKLCH format in config:
740
+ ```javascript
741
+ // eva.config.cjs
742
+ module.exports = {
743
+ theme: {
744
+ colors: {
745
+ brand: { lightness: 62.8, chroma: 0.258, hue: 29.23 }
746
+ }
747
+ }
748
+ };
749
+ ```
750
+
751
+ #### Configuration not loading / "Invalid configuration" error
752
+
753
+ **Problem:** Your `eva.config.cjs` isn't being read or validation fails.
754
+
755
+ **Checklist:**
756
+
757
+ 1. **File location:** Must be in project root (same level as `package.json`)
758
+ 2. **File name:** Must be exactly `eva.config.cjs` or `eva.config.js`
759
+ 3. **Syntax:** Must use `module.exports`, not ESM `export`
760
+ 4. **Validate config:**
761
+ ```bash
762
+ npx eva-css validate
763
+ ```
764
+
765
+ **Common mistakes:**
766
+
767
+ ```javascript
768
+ // āŒ Wrong - ESM syntax
769
+ export default {
770
+ sizes: [16, 24]
771
+ };
772
+
773
+ // āœ… Correct - CommonJS
774
+ module.exports = {
775
+ sizes: [16, 24]
776
+ };
777
+ ```
778
+
779
+ #### Dark mode toggle not working
780
+
781
+ **Problem:** Clicking toggle button doesn't switch themes.
782
+
783
+ **Required setup:**
784
+
785
+ 1. **HTML structure:**
786
+ ```html
787
+ <body class="current-theme theme-myapp">
788
+ <!-- Both classes required ^^ -->
789
+ <button onclick="document.body.classList.toggle('toggle-theme')">
790
+ Toggle Dark Mode
791
+ </button>
792
+ </body>
793
+ ```
794
+
795
+ 2. **Theme configuration:**
796
+ ```javascript
797
+ // eva.config.cjs
798
+ module.exports = {
799
+ theme: {
800
+ name: 'myapp', // Must match class: .theme-myapp
801
+ lightMode: { lightness: 96.4, darkness: 6.4 },
802
+ darkMode: { lightness: 5, darkness: 95 },
803
+ autoSwitch: false // Set true for auto prefers-color-scheme
804
+ }
805
+ };
806
+ ```
807
+
808
+ 3. **Toggle class:** The `.toggle-theme` class triggers dark mode when present.
809
+
810
+ #### CSS file size is huge (100KB+)
811
+
812
+ **Problem:** Generated CSS file is very large.
813
+
814
+ **Solutions:**
815
+
816
+ 1. **Enable custom class mode** to generate only needed classes:
817
+ ```scss
818
+ @use 'eva-css-fluid' with (
819
+ $sizes: (16, 24, 32, 64),
820
+ $custom-class: true,
821
+ $class-config: (
822
+ w: (64,), // Only .w-64
823
+ p: (16, 24), // Only .p-16 and .p-24
824
+ fs: (16, 24) // Only .fs-16 and .fs-24
825
+ )
826
+ );
827
+ ```
828
+ **Result:** Reduces output by ~85%
829
+
830
+ 2. **Use CSS purging** to remove unused classes:
831
+ ```bash
832
+ npm install --save-dev eva-css-purge
833
+ npx eva-purge --css dist/eva.css --content "src/**/*.html"
834
+ ```
835
+ **Result:** Typically 60-90% size reduction
836
+
837
+ 3. **Use variables mode** instead of utility classes:
838
+ ```scss
839
+ @use 'eva-css-fluid' with (
840
+ $build-class: false // No utility classes, only variables
841
+ );
842
+ ```
843
+ **Result:** Much smaller CSS (only variables, no classes)
844
+
845
+ #### Sass compilation error: "Cannot find module"
846
+
847
+ **Error:**
848
+ ```
849
+ Error: Can't find stylesheet to import.
850
+ ā•·
851
+ 1 │ @use 'eva-css-fluid';
852
+ │ ^^^^^^^^^^^^^^^^^^^^^
853
+ ```
854
+
855
+ **Solutions:**
856
+
857
+ 1. **Add load-path** if using older Sass:
858
+ ```bash
859
+ npx sass --load-path=node_modules styles/main.scss dist/main.css
860
+ ```
861
+
862
+ 2. **Check package is installed:**
863
+ ```bash
864
+ npm ls eva-css-fluid
865
+ # Should show: eva-css-fluid@x.x.x
866
+ ```
867
+
868
+ 3. **Try explicit path:**
869
+ ```scss
870
+ @use '../node_modules/eva-css-fluid/src';
871
+ ```
872
+
873
+ #### Watch mode not detecting config changes
874
+
875
+ **Problem:** Changing `eva.config.cjs` doesn't trigger rebuild.
876
+
877
+ **Solution:** Use `nodemon` to watch config file:
878
+
879
+ ```json
880
+ {
881
+ "scripts": {
882
+ "watch:css": "nodemon --watch eva.config.cjs --watch styles/ --exec 'node scripts/build-eva.js styles/main.scss dist/main.css'"
883
+ }
884
+ }
885
+ ```
886
+
887
+ Install nodemon:
888
+ ```bash
889
+ npm install --save-dev nodemon
890
+ ```
891
+
892
+ #### Need help?
893
+
894
+ - šŸ“– [Full Documentation](https://eva-css.xyz/)
895
+ - šŸ’¬ [GitHub Issues](https://github.com/nkdeus/eva/issues)
896
+ - šŸ“¦ [NPM Package](https://www.npmjs.com/package/eva-css-fluid)
897
+ - šŸŽÆ [Working Examples](../../examples/)
898
+
484
899
  ## šŸ“š Documentation
485
900
 
486
901
  - [Full Documentation](https://eva-css.xyz/)
package/cli.cjs CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  /**
4
4
  * EVA CSS CLI
5
- * Commands for configuration validation and management
5
+ * Commands for configuration validation and project setup
6
6
  */
7
7
 
8
8
  const { validateConfigCommand, generateScssCommand } = require('./src/config-loader.cjs');
9
+ const { initCommand, setupCommand } = require('./src/cli-commands.cjs');
9
10
 
10
11
  const args = process.argv.slice(2);
11
12
  const command = args[0];
@@ -18,21 +19,36 @@ Usage:
18
19
  eva-css <command> [options]
19
20
 
20
21
  Commands:
22
+ init Initialize EVA CSS in existing project (creates eva.config.cjs)
23
+ setup Complete project setup with workflow choice (SCSS vs JSON)
21
24
  validate Validate eva.config.js or package.json configuration
22
25
  generate Generate SCSS variables from config file
23
26
  help Show this help message
24
27
 
25
28
  Examples:
26
- eva-css validate
27
- eva-css generate src/_config-generated.scss
29
+ eva-css init # Initialize eva.config.cjs interactively
30
+ eva-css setup # Complete setup with file generation
31
+ eva-css validate # Validate configuration
32
+ eva-css generate output.scss
28
33
 
29
- Configuration:
30
- Create eva.config.js in your project root or add "eva" key to package.json
31
- See: https://eva-css.xyz/configuration
34
+ Getting Started:
35
+ For new projects: eva-css setup
36
+ For existing projects: eva-css init
37
+
38
+ Documentation:
39
+ https://github.com/nkdeus/eva/blob/main/packages/eva-css/README.md
32
40
  `);
33
41
  }
34
42
 
35
43
  switch (command) {
44
+ case 'init':
45
+ initCommand();
46
+ break;
47
+
48
+ case 'setup':
49
+ setupCommand();
50
+ break;
51
+
36
52
  case 'validate':
37
53
  validateConfigCommand();
38
54
  break;
package/package.json CHANGED
@@ -1,87 +1,87 @@
1
1
  {
2
- "name": "eva-css-fluid",
3
- "version": "2.0.0",
4
- "description": "Fluid design framework with OKLCH colors - Transform static designs into responsive fluid systems",
5
- "type": "module",
6
- "main": "src/index.scss",
7
- "sass": "src/index.scss",
8
- "style": "dist/eva.css",
9
- "bin": {
10
- "eva-css": "./cli.cjs"
11
- },
12
- "exports": {
13
- ".": {
14
- "sass": "./index.scss",
15
- "style": "./dist/eva.css",
16
- "default": "./dist/eva.css"
17
- },
18
- "./src": {
19
- "sass": "./src/index.scss",
20
- "default": "./src/index.scss"
21
- },
22
- "./variables": {
23
- "sass": "./src/variables.scss",
24
- "default": "./src/variables.scss"
25
- },
26
- "./core": {
27
- "sass": "./src/core.scss",
28
- "default": "./src/core.scss"
29
- },
30
- "./colors": {
31
- "sass": "./src/colors-only.scss",
32
- "default": "./src/colors-only.scss"
33
- },
34
- "./src/*": "./src/*.scss",
35
- "./package.json": "./package.json"
36
- },
37
- "files": [
38
- "src/",
39
- "dist/",
40
- "index.scss",
41
- "cli.cjs",
42
- "scripts/",
43
- "eva.config.template.js",
44
- "README.md",
45
- "MIGRATION.md"
46
- ],
47
- "keywords": [
48
- "css",
49
- "scss",
50
- "sass",
51
- "framework",
52
- "fluid-design",
53
- "oklch",
54
- "utility-css",
55
- "design-system",
56
- "responsive",
57
- "eva"
58
- ],
59
- "scripts": {
60
- "build": "node scripts/build-with-config.cjs",
61
- "build:min": "node scripts/build-with-config.cjs --min",
62
- "build:purge": "node scripts/build-with-config.cjs --purge",
63
- "build:sass": "sass src/index.scss dist/eva.css --style=expanded",
64
- "build:sass:min": "sass src/index.scss dist/eva.min.css --style=compressed",
65
- "watch": "sass --watch src/index.scss dist/eva.css",
66
- "dev": "npm run watch",
67
- "validate:config": "node cli.cjs validate",
68
- "generate:config": "node cli.cjs generate"
69
- },
70
- "dependencies": {
71
- "eva-colors": "^2.0.0"
72
- },
73
- "devDependencies": {
74
- "sass": "^1.94.1"
75
- },
76
- "repository": {
77
- "type": "git",
78
- "url": "https://github.com/nkdeus/eva.git",
79
- "directory": "packages/eva-css"
80
- },
81
- "author": {
82
- "name": "Michaƫl Tati",
83
- "url": "https://ulysse-2029.com/"
84
- },
85
- "homepage": "https://eva-css.xyz/",
86
- "license": "MIT"
2
+ "name": "eva-css-fluid",
3
+ "version": "2.0.6",
4
+ "description": "Fluid design framework with OKLCH colors - Transform static designs into responsive fluid systems",
5
+ "type": "module",
6
+ "main": "src/index.scss",
7
+ "sass": "src/index.scss",
8
+ "style": "dist/eva.css",
9
+ "bin": {
10
+ "eva-css": "./cli.cjs"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "sass": "./index.scss",
15
+ "style": "./dist/eva.css",
16
+ "default": "./dist/eva.css"
17
+ },
18
+ "./src": {
19
+ "sass": "./src/index.scss",
20
+ "default": "./src/index.scss"
21
+ },
22
+ "./variables": {
23
+ "sass": "./src/variables.scss",
24
+ "default": "./src/variables.scss"
25
+ },
26
+ "./core": {
27
+ "sass": "./src/core.scss",
28
+ "default": "./src/core.scss"
29
+ },
30
+ "./colors": {
31
+ "sass": "./src/colors-only.scss",
32
+ "default": "./src/colors-only.scss"
33
+ },
34
+ "./src/*": "./src/*.scss",
35
+ "./package.json": "./package.json"
36
+ },
37
+ "files": [
38
+ "src/",
39
+ "dist/",
40
+ "index.scss",
41
+ "cli.cjs",
42
+ "scripts/",
43
+ "eva.config.template.js",
44
+ "README.md",
45
+ "MIGRATION.md"
46
+ ],
47
+ "keywords": [
48
+ "css",
49
+ "scss",
50
+ "sass",
51
+ "framework",
52
+ "fluid-design",
53
+ "oklch",
54
+ "utility-css",
55
+ "design-system",
56
+ "responsive",
57
+ "eva"
58
+ ],
59
+ "scripts": {
60
+ "build": "node scripts/build-with-config.cjs",
61
+ "build:min": "node scripts/build-with-config.cjs --min",
62
+ "build:purge": "node scripts/build-with-config.cjs --purge",
63
+ "build:sass": "sass src/index.scss dist/eva.css --style=expanded",
64
+ "build:sass:min": "sass src/index.scss dist/eva.min.css --style=compressed",
65
+ "watch": "sass --watch src/index.scss dist/eva.css",
66
+ "dev": "npm run watch",
67
+ "validate:config": "node cli.cjs validate",
68
+ "generate:config": "node cli.cjs generate"
69
+ },
70
+ "dependencies": {
71
+ "eva-colors": "^2.0.6"
72
+ },
73
+ "devDependencies": {
74
+ "sass": "^1.94.1"
75
+ },
76
+ "repository": {
77
+ "type": "git",
78
+ "url": "https://github.com/nkdeus/eva.git",
79
+ "directory": "packages/eva-css"
80
+ },
81
+ "author": {
82
+ "name": "Michaƫl Tati",
83
+ "url": "https://ulysse-2029.com/"
84
+ },
85
+ "homepage": "https://eva-css.xyz/",
86
+ "license": "MIT"
87
87
  }
@@ -0,0 +1,539 @@
1
+ /**
2
+ * EVA CSS CLI Interactive Commands
3
+ *
4
+ * Commands: init, setup
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const readline = require('readline');
10
+
11
+ // CLI colors
12
+ const colors = {
13
+ reset: '\x1b[0m',
14
+ bright: '\x1b[1m',
15
+ dim: '\x1b[2m',
16
+ green: '\x1b[32m',
17
+ blue: '\x1b[34m',
18
+ cyan: '\x1b[36m',
19
+ yellow: '\x1b[33m',
20
+ red: '\x1b[31m'
21
+ };
22
+
23
+ function log(msg) {
24
+ console.log(msg);
25
+ }
26
+
27
+ function success(msg) {
28
+ log(`${colors.green}āœ…${colors.reset} ${msg}`);
29
+ }
30
+
31
+ function info(msg) {
32
+ log(`${colors.blue}ℹ${colors.reset} ${msg}`);
33
+ }
34
+
35
+ function error(msg) {
36
+ log(`${colors.red}āŒ${colors.reset} ${msg}`);
37
+ }
38
+
39
+ function title(msg) {
40
+ log(`\n${colors.bright}${colors.cyan}${msg}${colors.reset}\n`);
41
+ }
42
+
43
+ // Readline interface for prompts
44
+ function prompt(question) {
45
+ const rl = readline.createInterface({
46
+ input: process.stdin,
47
+ output: process.stdout
48
+ });
49
+
50
+ return new Promise(resolve => {
51
+ rl.question(`${colors.cyan}?${colors.reset} ${question} `, answer => {
52
+ rl.close();
53
+ resolve(answer.trim());
54
+ });
55
+ });
56
+ }
57
+
58
+ async function select(question, options) {
59
+ log(`${colors.cyan}?${colors.reset} ${question}`);
60
+ options.forEach((opt, i) => {
61
+ const description = opt.description ? ` ${colors.dim}- ${opt.description}${colors.reset}` : '';
62
+ log(` ${colors.dim}${i + 1}.${colors.reset} ${opt.label}${description}`);
63
+ });
64
+
65
+ const answer = await prompt(` Select (1-${options.length}):`);
66
+ const index = parseInt(answer) - 1;
67
+
68
+ if (index >= 0 && index < options.length) {
69
+ return options[index].value;
70
+ }
71
+
72
+ error('Invalid selection, using default');
73
+ return options[0].value;
74
+ }
75
+
76
+ async function confirm(question, defaultValue = true) {
77
+ const defaultText = defaultValue ? 'Y/n' : 'y/N';
78
+ const answer = await prompt(`${question} (${defaultText})`);
79
+
80
+ if (!answer) return defaultValue;
81
+ return answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes';
82
+ }
83
+
84
+ /**
85
+ * Generate eva.config.cjs template
86
+ */
87
+ function generateEvaConfig(options) {
88
+ const { sizes, fontSizes, buildClass, debug, workflow } = options;
89
+
90
+ return `/**
91
+ * EVA CSS Configuration
92
+ *
93
+ * This configuration file defines your design tokens.
94
+ * Customize sizes, font sizes, and build options.
95
+ *
96
+ * Documentation: https://github.com/nkdeus/eva/blob/main/packages/eva-css/docs/JSON-CONFIG.md
97
+ */
98
+
99
+ module.exports = {
100
+ // Design sizes - extracted from your design system
101
+ // These become CSS variables: var(--4), var(--8), var(--16), etc.
102
+ sizes: [${sizes.join(', ')}],
103
+
104
+ // Font sizes for typography
105
+ // These become CSS variables: var(--14), var(--16), var(--20), etc.
106
+ fontSizes: [${fontSizes.join(', ')}],
107
+
108
+ // Generate utility classes (.w-64, .p-16, .fs-24, etc.)
109
+ buildClass: ${buildClass},
110
+
111
+ // Show configuration during build (useful for debugging)
112
+ debug: ${debug},
113
+
114
+ // Theme configuration
115
+ theme: {
116
+ name: 'eva',
117
+ colors: {
118
+ // Using EVA default colors
119
+ // You can customize: brand, accent, extra
120
+ },
121
+
122
+ lightMode: {
123
+ lightness: 96.4, // Light background
124
+ darkness: 6.4 // Dark text
125
+ },
126
+
127
+ darkMode: {
128
+ lightness: 5, // Dark background
129
+ darkness: 95 // Light text
130
+ },
131
+
132
+ // Auto-switch based on system preference
133
+ autoSwitch: false
134
+ }${workflow === 'json' ? `,
135
+
136
+ // Optional: CSS purging for production
137
+ // Uncomment to reduce file size by 60-90%
138
+ /*
139
+ purge: {
140
+ enabled: true,
141
+ content: ['*.html', 'src/**/*.{js,jsx,tsx,vue}'],
142
+ css: 'dist/main.css',
143
+ output: 'dist/main-purged.css',
144
+ safelist: ['theme-', 'current-', 'toggle-']
145
+ }
146
+ */` : ''}
147
+ };
148
+ `;
149
+ }
150
+
151
+ /**
152
+ * Generate build script for JSON config workflow
153
+ */
154
+ function generateBuildScript() {
155
+ return `#!/usr/bin/env node
156
+ /**
157
+ * EVA CSS Build Script
158
+ *
159
+ * This script loads eva.config.cjs and injects it into SCSS compilation.
160
+ *
161
+ * USAGE:
162
+ * node scripts/build.js <input.scss> <output.css>
163
+ */
164
+
165
+ const fs = require('fs');
166
+ const path = require('path');
167
+ const { execSync } = require('child_process');
168
+
169
+ /**
170
+ * Load EVA configuration from eva.config.cjs
171
+ */
172
+ function loadConfig() {
173
+ const configPath = path.join(process.cwd(), 'eva.config.cjs');
174
+
175
+ if (!fs.existsSync(configPath)) {
176
+ console.log('āš ļø No eva.config.cjs found');
177
+ return null;
178
+ }
179
+
180
+ delete require.cache[require.resolve(configPath)];
181
+ return require(configPath);
182
+ }
183
+
184
+ /**
185
+ * Convert configuration to SCSS variables
186
+ */
187
+ function generateScssWithParams(config) {
188
+ const params = [];
189
+
190
+ if (config.sizes) {
191
+ params.push(\`$sizes: (\${config.sizes.join(', ')})\`);
192
+ }
193
+
194
+ if (config.fontSizes) {
195
+ params.push(\`$font-sizes: (\${config.fontSizes.join(', ')})\`);
196
+ }
197
+
198
+ if (typeof config.buildClass === 'boolean') {
199
+ params.push(\`$build-class: \${config.buildClass}\`);
200
+ }
201
+
202
+ if (typeof config.debug === 'boolean') {
203
+ params.push(\`$debug: \${config.debug}\`);
204
+ }
205
+
206
+ return params.join(',\\n ');
207
+ }
208
+
209
+ /**
210
+ * Build CSS from SCSS with configuration injection
211
+ */
212
+ function buildCss(inputScss, outputCss, config) {
213
+ if (!fs.existsSync(inputScss)) {
214
+ console.error(\`āŒ Input file not found: \${inputScss}\`);
215
+ process.exit(1);
216
+ }
217
+
218
+ const outputDir = path.dirname(outputCss);
219
+ if (!fs.existsSync(outputDir)) {
220
+ fs.mkdirSync(outputDir, { recursive: true });
221
+ }
222
+
223
+ const inputDir = path.dirname(inputScss);
224
+ const inputBase = path.basename(inputScss, '.scss');
225
+ const tempPath = path.join(inputDir, \`.\${inputBase}-temp.scss\`);
226
+
227
+ try {
228
+ const content = fs.readFileSync(inputScss, 'utf8');
229
+ let output = content;
230
+
231
+ if (config) {
232
+ const params = generateScssWithParams(config);
233
+
234
+ if (params) {
235
+ output = content.replace(
236
+ /@use\\s+['"]eva-css\\/index['"];?/g,
237
+ \`@use 'eva-css/index' with (\\n \${params}\\n);\`
238
+ );
239
+
240
+ console.log('āœ… Config injected into SCSS');
241
+ }
242
+ }
243
+
244
+ fs.writeFileSync(tempPath, output);
245
+
246
+ console.log('šŸ”Ø Compiling SCSS...');
247
+ execSync(
248
+ \`npx sass --load-path=node_modules \${tempPath}:\${outputCss}\`,
249
+ { stdio: 'inherit' }
250
+ );
251
+
252
+ if (fs.existsSync(outputCss)) {
253
+ const stats = fs.statSync(outputCss);
254
+ const sizeKB = (stats.size / 1024).toFixed(2);
255
+ console.log(\`āœ… CSS compiled: \${outputCss} (\${sizeKB} KB)\`);
256
+ }
257
+ } catch (error) {
258
+ console.error('āŒ Build failed:', error.message);
259
+ process.exit(1);
260
+ } finally {
261
+ if (fs.existsSync(tempPath)) {
262
+ fs.unlinkSync(tempPath);
263
+ }
264
+ }
265
+ }
266
+
267
+ /**
268
+ * Main execution
269
+ */
270
+ function main() {
271
+ const [,, input, output] = process.argv;
272
+
273
+ if (!input || !output) {
274
+ console.log('Usage: node scripts/build.js <input.scss> <output.css>');
275
+ process.exit(1);
276
+ }
277
+
278
+ console.log('šŸš€ EVA CSS Build\\n');
279
+ console.log(\`šŸ“„ Input: \${input}\`);
280
+ console.log(\`šŸ“¤ Output: \${output}\\n\`);
281
+
282
+ const config = loadConfig();
283
+ buildCss(input, output, config);
284
+
285
+ console.log('\\n✨ Build complete!\\n');
286
+ }
287
+
288
+ if (require.main === module) {
289
+ main();
290
+ }
291
+
292
+ module.exports = { loadConfig, generateScssWithParams, buildCss };
293
+ `;
294
+ }
295
+
296
+ /**
297
+ * eva-css init command
298
+ * Initialize EVA CSS in existing project
299
+ */
300
+ async function initCommand() {
301
+ try {
302
+ title('šŸŽØ EVA CSS Initialization');
303
+
304
+ // Check if eva.config.cjs already exists
305
+ const configPath = path.join(process.cwd(), 'eva.config.cjs');
306
+ if (fs.existsSync(configPath)) {
307
+ error('eva.config.cjs already exists!');
308
+ const overwrite = await confirm('Overwrite?', false);
309
+ if (!overwrite) {
310
+ log('\nAborted.');
311
+ process.exit(0);
312
+ }
313
+ }
314
+
315
+ // Get configuration from user
316
+ log('');
317
+ info('Configure your design system:\n');
318
+
319
+ const sizesInput = await prompt('Design sizes (comma-separated) [4, 8, 16, 32, 64, 128]:');
320
+ const sizes = sizesInput ? sizesInput.split(',').map(s => parseInt(s.trim())) : [4, 8, 16, 32, 64, 128];
321
+
322
+ const fontSizesInput = await prompt('Font sizes (comma-separated) [14, 16, 20, 24, 32, 48]:');
323
+ const fontSizes = fontSizesInput ? fontSizesInput.split(',').map(s => parseInt(s.trim())) : [14, 16, 20, 24, 32, 48];
324
+
325
+ const buildClass = await confirm('Generate utility classes?', true);
326
+ const debug = await confirm('Enable debug mode?', false);
327
+
328
+ // Generate config file
329
+ const configContent = generateEvaConfig({
330
+ sizes,
331
+ fontSizes,
332
+ buildClass,
333
+ debug,
334
+ workflow: 'json'
335
+ });
336
+
337
+ fs.writeFileSync(configPath, configContent);
338
+ success('Created eva.config.cjs');
339
+
340
+ // Success message
341
+ title('āœ… EVA CSS Initialized!');
342
+
343
+ log(`${colors.bright}Next steps:${colors.reset}\n`);
344
+ log(` ${colors.dim}1.${colors.reset} Run ${colors.cyan}npx eva-css validate${colors.reset} to verify configuration`);
345
+ log(` ${colors.dim}2.${colors.reset} Import EVA CSS in your SCSS: ${colors.dim}@use 'eva-css/index';${colors.reset}`);
346
+ log(` ${colors.dim}3.${colors.reset} Use ${colors.cyan}eva-css setup${colors.reset} for full project setup with build scripts\n`);
347
+
348
+ log(`${colors.dim}Documentation: https://github.com/nkdeus/eva/blob/main/packages/eva-css/README.md${colors.reset}\n`);
349
+
350
+ } catch (err) {
351
+ error(`Failed to initialize: ${err.message}`);
352
+ process.exit(1);
353
+ }
354
+ }
355
+
356
+ /**
357
+ * eva-css setup command
358
+ * Complete project setup with workflow choice
359
+ */
360
+ async function setupCommand() {
361
+ try {
362
+ title('šŸš€ EVA CSS Project Setup');
363
+
364
+ // Choose workflow
365
+ log('');
366
+ const workflow = await select('Choose your workflow:', [
367
+ {
368
+ label: 'SCSS Variables',
369
+ value: 'scss',
370
+ description: 'Simple, works with npx sass directly'
371
+ },
372
+ {
373
+ label: 'JSON Config',
374
+ value: 'json',
375
+ description: 'Centralized config, requires build script'
376
+ }
377
+ ]);
378
+
379
+ log('');
380
+ info('Configure your design system:\n');
381
+
382
+ const sizesInput = await prompt('Design sizes (comma-separated) [4, 8, 16, 32, 64, 128]:');
383
+ const sizes = sizesInput ? sizesInput.split(',').map(s => parseInt(s.trim())) : [4, 8, 16, 32, 64, 128];
384
+
385
+ const fontSizesInput = await prompt('Font sizes (comma-separated) [14, 16, 20, 24, 32, 48]:');
386
+ const fontSizes = fontSizesInput ? fontSizesInput.split(',').map(s => parseInt(s.trim())) : [14, 16, 20, 24, 32, 48];
387
+
388
+ const buildClass = await confirm('Generate utility classes?', true);
389
+ const debug = await confirm('Enable debug mode?', false);
390
+
391
+ log('\nšŸ“ Setting up project files...\n');
392
+
393
+ // Create directories
394
+ if (!fs.existsSync('styles')) {
395
+ fs.mkdirSync('styles', { recursive: true });
396
+ success('Created styles/');
397
+ }
398
+
399
+ if (!fs.existsSync('dist')) {
400
+ fs.mkdirSync('dist', { recursive: true });
401
+ success('Created dist/');
402
+ }
403
+
404
+ if (workflow === 'json') {
405
+ // JSON Config workflow
406
+
407
+ // 1. Create eva.config.cjs
408
+ const configContent = generateEvaConfig({ sizes, fontSizes, buildClass, debug, workflow });
409
+ fs.writeFileSync('eva.config.cjs', configContent);
410
+ success('Created eva.config.cjs');
411
+
412
+ // 2. Create build script
413
+ if (!fs.existsSync('scripts')) {
414
+ fs.mkdirSync('scripts', { recursive: true });
415
+ }
416
+ fs.writeFileSync('scripts/build.js', generateBuildScript());
417
+ success('Created scripts/build.js');
418
+
419
+ // 3. Create clean SCSS (no config inline)
420
+ const scssContent = `// EVA CSS
421
+ // Configuration is loaded from eva.config.cjs
422
+
423
+ @use 'eva-css/index';
424
+
425
+ // Your custom styles here
426
+
427
+ body {
428
+ margin: 0;
429
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
430
+ transition: background 0.3s, color 0.3s;
431
+ }
432
+ `;
433
+ fs.writeFileSync('styles/main.scss', scssContent);
434
+ success('Created styles/main.scss');
435
+
436
+ // 4. Update or create package.json scripts
437
+ const packageJsonPath = 'package.json';
438
+ let packageJson = {};
439
+
440
+ if (fs.existsSync(packageJsonPath)) {
441
+ packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
442
+ } else {
443
+ packageJson = {
444
+ name: path.basename(process.cwd()),
445
+ version: '1.0.0',
446
+ private: true
447
+ };
448
+ }
449
+
450
+ packageJson.scripts = packageJson.scripts || {};
451
+ packageJson.scripts.build = 'node scripts/build.js styles/main.scss dist/main.css';
452
+ packageJson.scripts.watch = 'nodemon --watch styles --watch eva.config.cjs --ext scss,cjs --exec "npm run build"';
453
+ packageJson.scripts.validate = 'eva-css validate';
454
+
455
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
456
+ success('Updated package.json scripts');
457
+
458
+ // Success message
459
+ title('āœ… JSON Config Workflow Setup Complete!');
460
+
461
+ log(`${colors.bright}Next steps:${colors.reset}\n`);
462
+ log(` ${colors.dim}1.${colors.reset} Install dependencies: ${colors.cyan}npm install --save-dev sass nodemon${colors.reset}`);
463
+ log(` ${colors.dim}2.${colors.reset} Validate config: ${colors.cyan}npm run validate${colors.reset}`);
464
+ log(` ${colors.dim}3.${colors.reset} Build CSS: ${colors.cyan}npm run build${colors.reset}`);
465
+ log(` ${colors.dim}4.${colors.reset} Watch mode: ${colors.cyan}npm run watch${colors.reset}\n`);
466
+
467
+ } else {
468
+ // SCSS Variables workflow
469
+
470
+ // Create SCSS with inline config
471
+ const scssContent = `// EVA CSS - SCSS Variables Configuration
472
+
473
+ @use 'eva-css/index' with (
474
+ // Design sizes from your design system
475
+ $sizes: (${sizes.join(', ')}),
476
+
477
+ // Font sizes for typography
478
+ $font-sizes: (${fontSizes.join(', ')}),
479
+
480
+ // Generate utility classes
481
+ $build-class: ${buildClass},
482
+
483
+ // Show debug info during build
484
+ $debug: ${debug}
485
+ );
486
+
487
+ // Your custom styles here
488
+
489
+ body {
490
+ margin: 0;
491
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
492
+ transition: background 0.3s, color 0.3s;
493
+ }
494
+ `;
495
+ fs.writeFileSync('styles/main.scss', scssContent);
496
+ success('Created styles/main.scss');
497
+
498
+ // Update or create package.json scripts
499
+ const packageJsonPath = 'package.json';
500
+ let packageJson = {};
501
+
502
+ if (fs.existsSync(packageJsonPath)) {
503
+ packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
504
+ } else {
505
+ packageJson = {
506
+ name: path.basename(process.cwd()),
507
+ version: '1.0.0',
508
+ private: true
509
+ };
510
+ }
511
+
512
+ packageJson.scripts = packageJson.scripts || {};
513
+ packageJson.scripts.build = 'sass --load-path=node_modules styles/main.scss:dist/main.css';
514
+ packageJson.scripts.watch = 'sass --watch --load-path=node_modules styles/main.scss:dist/main.css';
515
+
516
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
517
+ success('Updated package.json scripts');
518
+
519
+ // Success message
520
+ title('āœ… SCSS Variables Workflow Setup Complete!');
521
+
522
+ log(`${colors.bright}Next steps:${colors.reset}\n`);
523
+ log(` ${colors.dim}1.${colors.reset} Install Sass: ${colors.cyan}npm install --save-dev sass${colors.reset}`);
524
+ log(` ${colors.dim}2.${colors.reset} Build CSS: ${colors.cyan}npm run build${colors.reset}`);
525
+ log(` ${colors.dim}3.${colors.reset} Watch mode: ${colors.cyan}npm run watch${colors.reset}\n`);
526
+ }
527
+
528
+ log(`${colors.dim}Documentation: https://github.com/nkdeus/eva/blob/main/packages/eva-css/README.md${colors.reset}\n`);
529
+
530
+ } catch (err) {
531
+ error(`Setup failed: ${err.message}`);
532
+ process.exit(1);
533
+ }
534
+ }
535
+
536
+ module.exports = {
537
+ initCommand,
538
+ setupCommand
539
+ };