esm-styles 0.1.11 → 0.1.13

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.
@@ -0,0 +1,600 @@
1
+ # ESM Styles Usage Guide
2
+
3
+ This guide explains how to use ESM Styles to create and manage your CSS styles using JavaScript/TypeScript.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Basic Concepts](#basic-concepts)
8
+ - [CLI Usage](#cli-usage)
9
+ - [Configuration](#configuration)
10
+ - [JS to CSS Translation Rules](#js-to-css-translation-rules)
11
+ - [Layers](#layers)
12
+ - [Media Queries](#media-queries)
13
+ - [CSS Variables](#css-variables)
14
+ - [Supporting Modules](#supporting-modules)
15
+
16
+ ## Basic Concepts
17
+
18
+ ESM Styles allows you to write CSS using JavaScript objects with an intuitive nested syntax. The main benefits are:
19
+
20
+ - Composition with JavaScript functions
21
+ - JS tooling and editor support
22
+ - Dynamic generation of styles
23
+ - Modular organization of styles
24
+
25
+ You write styles as objects with nested selectors, and the library converts them to valid CSS:
26
+
27
+ ```js
28
+ // component.styles.mjs
29
+ export default {
30
+ button: {
31
+ backgroundColor: '#4285f4',
32
+ color: 'white',
33
+ padding: '10px 20px',
34
+
35
+ ':hover': {
36
+ backgroundColor: '#3367d6',
37
+ },
38
+ },
39
+ }
40
+ ```
41
+
42
+ ## CLI Usage
43
+
44
+ Once you've installed ESM Styles, you can use the CLI to build your styles:
45
+
46
+ ```bash
47
+ # Using default esm-styles.config.js in the current directory
48
+ npx esm-styles build
49
+
50
+ # Using a custom config file
51
+ npx esm-styles build path/to/config.js
52
+ ```
53
+
54
+ The CLI will:
55
+
56
+ 1. Read your configuration file
57
+ 2. Process each layer file
58
+ 3. Convert styles to CSS
59
+ 4. Generate theme/device variable files
60
+ 5. Create supporting modules
61
+ 6. Output all files to the specified output directory
62
+
63
+ ## Configuration
64
+
65
+ The configuration file is where you define your style structure, paths, media queries, and themes.
66
+
67
+ ```js
68
+ // esm-styles.config.js
69
+ export default {
70
+ // Base paths
71
+ basePath: './src/styles',
72
+ sourcePath: 'source',
73
+ outputPath: 'css',
74
+ sourceFilesSuffix: '.styles.mjs',
75
+
76
+ // Input layers - order matters
77
+ layers: ['defaults', 'components', 'layout'],
78
+
79
+ // Output
80
+ mainCssFile: 'styles.css',
81
+
82
+ // CSS Variables configuration
83
+ globalVariables: 'global',
84
+ globalRootSelector: ':root',
85
+
86
+ // Media types and their variable sets
87
+ media: {
88
+ theme: ['light', 'dark'],
89
+ device: ['mobile', 'tablet', 'desktop'],
90
+ },
91
+
92
+ // Selectors/media queries for each media type
93
+ mediaSelectors: {
94
+ theme: {
95
+ light: [
96
+ {
97
+ selector: '.light',
98
+ },
99
+ {
100
+ selector: '.auto',
101
+ mediaQuery: 'screen and (prefers-color-scheme: light)',
102
+ prefix: 'auto',
103
+ },
104
+ ],
105
+ dark: [
106
+ {
107
+ selector: '.dark',
108
+ },
109
+ {
110
+ selector: '.auto',
111
+ mediaQuery: 'screen and (prefers-color-scheme: dark)',
112
+ prefix: 'auto',
113
+ },
114
+ ],
115
+ },
116
+ device: {
117
+ mobile: [
118
+ {
119
+ mediaQuery: 'screen and (max-width: 767px)',
120
+ },
121
+ ],
122
+ // Additional device selectors...
123
+ },
124
+ },
125
+
126
+ // Media query shorthands
127
+ mediaQueries: {
128
+ mobile: '(max-width: 767px)',
129
+ tablet: '(min-width: 768px) and (max-width: 1024px)',
130
+ desktop: '(min-width: 1025px)',
131
+ },
132
+ }
133
+ ```
134
+
135
+ ### Configuration Properties
136
+
137
+ | Property | Description |
138
+ | -------------------- | ------------------------------------------------------------------------- |
139
+ | `basePath` | Base directory for all styles, relative to where the build command is run |
140
+ | `sourcePath` | Directory inside `basePath` containing source style files |
141
+ | `outputPath` | Directory inside `basePath` where output CSS files will be written |
142
+ | `sourceFilesSuffix` | Suffix for source style files (default: `.styles.mjs`) |
143
+ | `layers` | Array of layer names, defining the order of CSS specificity |
144
+ | `mainCssFile` | Name of the output CSS file that imports all layer and variable files |
145
+ | `globalVariables` | Name of the file containing global CSS variables |
146
+ | `globalRootSelector` | Root selector for CSS variables (default: `:root`) |
147
+ | `media` | Object defining media types and their variable sets |
148
+ | `mediaSelectors` | Configuration for applying media types with selectors/queries |
149
+ | `mediaQueries` | Object defining shorthand names for media queries |
150
+
151
+ ## JS to CSS Translation Rules
152
+
153
+ ESM Styles converts JavaScript objects to CSS following these rules:
154
+
155
+ ### T1: Properties vs Selectors
156
+
157
+ Object keys that contain another object become CSS selectors, while keys with primitive values become CSS properties:
158
+
159
+ ```js
160
+ {
161
+ p: {
162
+ fontSize: '16px', // CSS property
163
+ color: 'black', // CSS property
164
+
165
+ a: { // Nested selector
166
+ color: 'blue'
167
+ }
168
+ }
169
+ }
170
+ ```
171
+
172
+ Property names are automatically converted from camelCase to kebab-case.
173
+
174
+ ### T2: HTML Tag Selectors
175
+
176
+ HTML tag names are recognized and become tag selectors:
177
+
178
+ ```js
179
+ {
180
+ div: {
181
+ margin: '10px',
182
+
183
+ p: {
184
+ lineHeight: 1.5,
185
+ }
186
+ }
187
+ }
188
+ ```
189
+
190
+ Becomes:
191
+
192
+ ```css
193
+ div {
194
+ margin: 10px;
195
+ }
196
+
197
+ div p {
198
+ line-height: 1.5;
199
+ }
200
+ ```
201
+
202
+ ### T3: Class Selectors
203
+
204
+ Keys with non-primitive values that aren't recognized as HTML tags become class selectors:
205
+
206
+ ```js
207
+ {
208
+ card: {
209
+ backgroundColor: 'white',
210
+ borderRadius: '4px'
211
+ }
212
+ }
213
+ ```
214
+
215
+ Becomes:
216
+
217
+ ```css
218
+ .card {
219
+ background-color: white;
220
+ border-radius: 4px;
221
+ }
222
+ ```
223
+
224
+ ### T4: Special Selectors
225
+
226
+ You can use pseudo-classes, IDs, and attribute selectors directly:
227
+
228
+ ```js
229
+ {
230
+ a: {
231
+ color: 'blue',
232
+
233
+ ':hover': {
234
+ color: 'red'
235
+ },
236
+
237
+ '#main': {
238
+ fontWeight: 'bold'
239
+ },
240
+
241
+ '[target="_blank"]': {
242
+ textDecoration: 'underline'
243
+ }
244
+ }
245
+ }
246
+ ```
247
+
248
+ ### T5: Underscore for Class Names
249
+
250
+ Use a single underscore prefix to force a class selector when the name matches an HTML tag:
251
+
252
+ ```js
253
+ {
254
+ div: {
255
+ _button: { // Creates div.button
256
+ padding: '10px'
257
+ },
258
+
259
+ button: { // Creates div button
260
+ margin: '5px'
261
+ }
262
+ }
263
+ }
264
+ ```
265
+
266
+ ### T6: Double Underscore for Any Level Descendants
267
+
268
+ Use double underscore to create a descendant selector that can match at any nesting level:
269
+
270
+ ```js
271
+ {
272
+ card: {
273
+ position: 'relative',
274
+
275
+ __close: { // Creates .card .close
276
+ position: 'absolute',
277
+ top: '10px',
278
+ right: '10px'
279
+ }
280
+ }
281
+ }
282
+ ```
283
+
284
+ ### T7: Complex Selectors
285
+
286
+ You can use complex selectors directly as keys:
287
+
288
+ ```js
289
+ {
290
+ ul: {
291
+ '> li:not(:last-child)': {
292
+ borderBottom: '1px solid #eee'
293
+ }
294
+ }
295
+ }
296
+ ```
297
+
298
+ ### T8: Comma-Separated Selectors
299
+
300
+ Use commas to target multiple selectors:
301
+
302
+ ```js
303
+ {
304
+ 'button, .btn': {
305
+ padding: '10px 20px'
306
+ }
307
+ }
308
+ ```
309
+
310
+ ### T9: Content Property
311
+
312
+ For the `content` property, use JavaScript unicode notation for special characters:
313
+
314
+ ```js
315
+ {
316
+ '::before': {
317
+ content: '\u2022', // Bullet character
318
+ }
319
+ }
320
+ ```
321
+
322
+ ## Layers
323
+
324
+ CSS layers help manage specificity and provide better organization of styles. ESM Styles supports @layer directives:
325
+
326
+ ```js
327
+ {
328
+ p: {
329
+ color: 'black',
330
+
331
+ '@layer typography': {
332
+ fontFamily: 'sans-serif',
333
+ lineHeight: 1.5
334
+ }
335
+ }
336
+ }
337
+ ```
338
+
339
+ Your configuration can define multiple layer files that will be automatically wrapped in their respective layer directives:
340
+
341
+ ```js
342
+ // defaults.styles.mjs
343
+ export default {
344
+ // Base styles
345
+ }
346
+
347
+ // components.styles.mjs
348
+ export default {
349
+ // Component styles
350
+ }
351
+
352
+ // layout.styles.mjs
353
+ export default {
354
+ // Layout styles
355
+ }
356
+ ```
357
+
358
+ The build process generates:
359
+
360
+ ```css
361
+ @layer defaults, components, layout;
362
+
363
+ @layer defaults {
364
+ /* defaults.css content */
365
+ }
366
+
367
+ @layer components {
368
+ /* components.css content */
369
+ }
370
+
371
+ @layer layout {
372
+ /* layout.css content */
373
+ }
374
+ ```
375
+
376
+ ## Media Queries
377
+
378
+ ### Standard Media Queries
379
+
380
+ You can use standard media queries directly in your styles:
381
+
382
+ ```js
383
+ {
384
+ container: {
385
+ maxWidth: '1200px',
386
+
387
+ '@media (max-width: 768px)': {
388
+ maxWidth: '100%',
389
+ padding: '0 20px'
390
+ }
391
+ }
392
+ }
393
+ ```
394
+
395
+ ### Nested Media Queries
396
+
397
+ Media queries can be nested for more specific targeting:
398
+
399
+ ```js
400
+ {
401
+ card: {
402
+ '@media (max-width: 768px)': {
403
+ padding: '10px',
404
+
405
+ '@media (orientation: portrait)': {
406
+ marginBottom: '20px'
407
+ }
408
+ }
409
+ }
410
+ }
411
+ ```
412
+
413
+ ### Media Query Shorthands
414
+
415
+ Use named media query shorthands for better readability:
416
+
417
+ ```js
418
+ {
419
+ section: {
420
+ display: 'grid',
421
+ gridTemplateColumns: 'repeat(3, 1fr)',
422
+
423
+ '@mobile': {
424
+ display: 'block'
425
+ },
426
+
427
+ '@tablet': {
428
+ gridTemplateColumns: 'repeat(2, 1fr)'
429
+ }
430
+ }
431
+ }
432
+ ```
433
+
434
+ ### Theme and Device Selectors
435
+
436
+ Use named selectors defined in `mediaSelectors` configuration:
437
+
438
+ ```js
439
+ {
440
+ button: {
441
+ backgroundColor: 'white',
442
+ color: 'black',
443
+
444
+ '@dark': {
445
+ backgroundColor: '#222',
446
+ color: 'white'
447
+ }
448
+ }
449
+ }
450
+ ```
451
+
452
+ This will generate appropriate selectors based on your config, including automatic handling of prefers-color-scheme media queries.
453
+
454
+ ## CSS Variables
455
+
456
+ ESM Styles provides a powerful system for managing CSS variables across themes and devices.
457
+
458
+ ### Global Variables
459
+
460
+ Define global variables that remain consistent across all themes:
461
+
462
+ ```js
463
+ // global.styles.mjs
464
+ export default {
465
+ spacing: {
466
+ xs: '4px',
467
+ sm: '8px',
468
+ md: '16px',
469
+ lg: '24px',
470
+ xl: '32px',
471
+ },
472
+ radius: {
473
+ sm: '4px',
474
+ md: '8px',
475
+ lg: '16px',
476
+ },
477
+ }
478
+ ```
479
+
480
+ ### Theme Variables
481
+
482
+ Define theme-specific variables that change depending on the active theme:
483
+
484
+ ```js
485
+ // light.styles.mjs
486
+ export default {
487
+ colors: {
488
+ background: '#ffffff',
489
+ surface: '#f5f5f5',
490
+ text: '#111111',
491
+ primary: '#4285f4'
492
+ }
493
+ }
494
+
495
+ // dark.styles.mjs
496
+ export default {
497
+ colors: {
498
+ background: '#121212',
499
+ surface: '#222222',
500
+ text: '#ffffff',
501
+ primary: '#5c9eff'
502
+ }
503
+ }
504
+ ```
505
+
506
+ ### Variable Inheritance
507
+
508
+ Variables defined in one theme automatically inherit from previous themes if not explicitly defined:
509
+
510
+ ```js
511
+ // In your config: theme: ['light', 'twilight', 'dark']
512
+
513
+ // light.styles.mjs
514
+ export default {
515
+ colors: {
516
+ primary: '#4285f4',
517
+ secondary: '#34a853',
518
+ accent: '#ea4335'
519
+ }
520
+ }
521
+
522
+ // twilight.styles.mjs
523
+ export default {
524
+ colors: {
525
+ primary: '#5c9eff',
526
+ // secondary will be inherited
527
+ accent: '#ff7e75'
528
+ }
529
+ }
530
+
531
+ // dark.styles.mjs
532
+ export default {
533
+ colors: {
534
+ primary: '#8ab4ff',
535
+ secondary: '#66c385'
536
+ // accent will be inherited from twilight
537
+ }
538
+ }
539
+ ```
540
+
541
+ ## Supporting Modules
542
+
543
+ ESM Styles generates supporting modules for each media type to provide convenient access to CSS variables:
544
+
545
+ ### Theme Module
546
+
547
+ The build process automatically generates modules like `$theme.mjs`:
548
+
549
+ ```js
550
+ // $theme.mjs (generated)
551
+ export default {
552
+ colors: {
553
+ background: {
554
+ var: '--colors-background',
555
+ light: '#ffffff',
556
+ dark: '#121212',
557
+ },
558
+ surface: {
559
+ var: '--colors-surface',
560
+ light: '#f5f5f5',
561
+ dark: '#222222',
562
+ },
563
+ // More variables...
564
+ },
565
+ }
566
+ ```
567
+
568
+ ### Using Supporting Modules
569
+
570
+ Import and use supporting modules in your style files:
571
+
572
+ ```js
573
+ // components.styles.mjs
574
+ import $theme from './$theme.mjs'
575
+
576
+ export default {
577
+ button: {
578
+ backgroundColor: $theme.colors.primary,
579
+ color: $theme.colors.background,
580
+ padding: '10px 20px',
581
+ borderRadius: '4px',
582
+ },
583
+ }
584
+ ```
585
+
586
+ This gets compiled to:
587
+
588
+ ```css
589
+ button {
590
+ background-color: var(--colors-primary);
591
+ color: var(--colors-background);
592
+ padding: 10px 20px;
593
+ border-radius: 4px;
594
+ }
595
+ ```
596
+
597
+ The supporting modules provide:
598
+
599
+ - Autocomplete for available variables in most code editors
600
+ - The ability to see the actual values for each theme
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "esm-styles",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "A library for working with ESM styles",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "type": "module",
8
8
  "files": [
9
- "dist"
9
+ "dist",
10
+ "README.md",
11
+ "doc"
10
12
  ],
11
13
  "scripts": {
12
14
  "build": "tsc",
@@ -48,5 +50,10 @@
48
50
  },
49
51
  "dependencies": {
50
52
  "js-beautify": "^1.15.4"
51
- }
53
+ },
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "https://github.com/romochka/esm-styles.git"
57
+ },
58
+ "homepage": "https://github.com/romochka/esm-styles#readme"
52
59
  }