@melcanz85/chaincss 1.7.3 → 1.9.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/README.md +323 -348
- package/atomic-optimizer.js +275 -0
- package/cache-manager.js +68 -0
- package/chaincss.js +183 -16
- package/index.js +24 -0
- package/index.react.js +4 -0
- package/package.json +25 -2
- package/prefixer.js +2 -2
- package/react-hooks.js +175 -0
- package/tokens.js +256 -0
- package/transpiler.js +155 -204
- package/types.d.ts +148 -0
- package/.github/workflows/publish.yml +0 -22
- package/publish.sh +0 -7
package/README.md
CHANGED
|
@@ -1,473 +1,448 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ChainCSS
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@melcanz85/chaincss)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
**Write CSS with JavaScript. The only CSS-in-JS library that lets you CHOOSE your runtime cost.**
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
ChainCSS is a revolutionary CSS-in-JS solution that gives you **two powerful modes** in one package:
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
**Build-time compilation** → Pure CSS, zero JavaScript in browser
|
|
11
|
+
|
|
12
|
+
**Runtime hooks** → Dynamic, prop-based styles when you need them
|
|
13
|
+
|
|
14
|
+
"The performance of vanilla CSS with the power of JavaScript — now with **CHOICE.**"
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
// Same beautiful API, two powerful modes
|
|
18
|
+
const button = $()
|
|
19
|
+
.color('white')
|
|
20
|
+
.backgroundColor('#667eea')
|
|
21
|
+
.padding('1rem')
|
|
22
|
+
.borderRadius('4px')
|
|
23
|
+
.block('.btn');
|
|
24
|
+
````
|
|
25
|
+
## Installation
|
|
11
26
|
|
|
12
27
|
```bash
|
|
28
|
+
|
|
13
29
|
npm install @melcanz85/chaincss
|
|
14
30
|
```
|
|
15
31
|
|
|
16
|
-
|
|
32
|
+
## Two Powerful Modes - One API
|
|
17
33
|
|
|
18
|
-
|
|
34
|
+
### Mode 1: Build-time (Zero Runtime)
|
|
19
35
|
|
|
20
|
-
|
|
36
|
+
**Perfect for:** Static styles, layouts, design systems — anything that doesn't change.
|
|
21
37
|
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
38
|
+
```javascript
|
|
39
|
+
// chaincss/button.jcss
|
|
40
|
+
const button = $()
|
|
41
|
+
.backgroundColor('#667eea')
|
|
42
|
+
.color('white')
|
|
43
|
+
.padding('0.5rem 1rem')
|
|
44
|
+
.borderRadius('4px')
|
|
45
|
+
.block('.btn');
|
|
27
46
|
|
|
28
|
-
|
|
29
|
-
|
|
47
|
+
module.exports = { button };
|
|
48
|
+
````
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
// chaincss/processor.js
|
|
52
|
+
const chaincss = require('@melcanz85/chaincss');
|
|
53
|
+
|
|
54
|
+
chaincss.processor('./chaincss/main.jcss', './dist/style.css');
|
|
55
|
+
// Outputs pure CSS: .btn { background: #667eea; color: white; ... }
|
|
56
|
+
// Zero JavaScript sent to browser
|
|
57
|
+
// Max performance, smallest bundle
|
|
58
|
+
````
|
|
59
|
+
### Mode 2: Runtime (React Hooks)
|
|
60
|
+
|
|
61
|
+
**Perfect for:** Dynamic styles that respond to props, state, or themes.
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
// components/DynamicButton.jsx
|
|
65
|
+
import { useChainStyles } from '@melcanz85/chaincss';
|
|
66
|
+
|
|
67
|
+
function DynamicButton({ variant = 'primary', children }) {
|
|
68
|
+
const styles = useChainStyles({
|
|
69
|
+
button: () => $()
|
|
70
|
+
.backgroundColor(variant === 'primary' ? '#667eea' : '#48bb78')
|
|
71
|
+
.color('white')
|
|
72
|
+
.padding('0.5rem 1rem')
|
|
73
|
+
.borderRadius('4px')
|
|
74
|
+
.hover()
|
|
75
|
+
.transform('translateY(-2px)')
|
|
76
|
+
.boxShadow('0 4px 6px rgba(0,0,0,0.1)')
|
|
77
|
+
.block()
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return <button className={styles.button}>{children}</button>;
|
|
30
81
|
}
|
|
82
|
+
// Styles injected at runtime
|
|
83
|
+
// Automatic cleanup on unmount
|
|
84
|
+
// Fully dynamic based on props
|
|
85
|
+
```
|
|
31
86
|
|
|
87
|
+
## Use BOTH in the Same Project!
|
|
32
88
|
|
|
33
|
-
|
|
89
|
+
```jsx
|
|
90
|
+
// Best of both worlds:
|
|
91
|
+
// - Layout styles → Build-time (zero cost)
|
|
92
|
+
// - Interactive styles → Runtime (dynamic)
|
|
34
93
|
|
|
35
|
-
|
|
94
|
+
// chaincss/layout.jcss (build-time)
|
|
95
|
+
const grid = $().display('grid').gap('1rem').block('.grid');
|
|
36
96
|
|
|
37
|
-
|
|
97
|
+
// components/Card.jsx (runtime)
|
|
98
|
+
function Card({ isHighlighted }) {
|
|
99
|
+
const styles = useChainStyles({
|
|
100
|
+
card: () => $()
|
|
101
|
+
.backgroundColor(isHighlighted ? '#fffacd' : 'white')
|
|
102
|
+
.padding('1rem')
|
|
103
|
+
.block()
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
```
|
|
38
107
|
|
|
39
|
-
|
|
40
|
-
- Flexbox & Grid
|
|
41
|
-
- Transforms & Animations
|
|
42
|
-
- Filters & Effects
|
|
43
|
-
- Text effects
|
|
44
|
-
- Box properties
|
|
108
|
+
## Features at a Glance
|
|
45
109
|
|
|
46
|
-
|
|
110
|
+
Feature Status Description
|
|
47
111
|
|
|
48
|
-
|
|
112
|
+
Zero Runtime ✅ Pure CSS output, no JS in browser
|
|
49
113
|
|
|
50
|
-
|
|
114
|
+
React Hooks ✅ Dynamic runtime styles when needed
|
|
51
115
|
|
|
52
|
-
|
|
53
|
-
npm install autoprefixer postcss browserslist caniuse-db
|
|
54
|
-
```
|
|
55
|
-
Project Structure
|
|
116
|
+
Atomic CSS ✅ 90% smaller CSS files
|
|
56
117
|
|
|
57
|
-
|
|
118
|
+
TypeScript ✅ First-class type support
|
|
58
119
|
|
|
59
|
-
|
|
60
|
-
├── chaincss/ # ChainCSS source files
|
|
61
|
-
│ ├── main.jcss # Main entry file
|
|
62
|
-
│ ├── chain.jcss # Chaining definitions
|
|
63
|
-
│ └── processor.js # Processing script
|
|
64
|
-
├── public/ # Output files
|
|
65
|
-
│ ├── index.html
|
|
66
|
-
│ └── style.css # Generated CSS
|
|
67
|
-
├── node_modules/
|
|
68
|
-
├── package.json
|
|
69
|
-
└── package-lock.json
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
The Initialization processor Setup
|
|
73
|
-
|
|
74
|
-
In chaincss/processor.js:
|
|
75
|
-
|
|
76
|
-
const chain = require("@melcanz85/chaincss");
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
// Process main file and output CSS
|
|
80
|
-
chain.processor('./chaincss/main.jcss', './public/style.css');
|
|
81
|
-
} catch (err) {
|
|
82
|
-
console.error('Error processing chainCSS file:', err.stack);
|
|
83
|
-
process.exit(1);
|
|
84
|
-
}
|
|
120
|
+
Design Tokens ✅ Centralized design system
|
|
85
121
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
//--Chaining File (chaincss/chain.jcss):
|
|
89
|
-
|
|
90
|
-
### This is where the chaining happens all codes must be in javascript syntax.
|
|
91
|
-
The chain methods are the same as the css properties but in camelCase mode
|
|
92
|
-
and the exception of the background property which is shorten to 'bg' only for
|
|
93
|
-
example background-color is bgColor() in chaincss. The value of the block()
|
|
94
|
-
method is the css selector which is always at the end of the chain or block.
|
|
95
|
-
|
|
96
|
-
// Variables for consistent styling
|
|
97
|
-
const bodyBg = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
|
|
98
|
-
const headerBg = 'rgba(255, 255, 255, 0.95)';
|
|
99
|
-
const bodyFontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
|
100
|
-
Ubuntu, sans-serif";
|
|
101
|
-
const headerBoxShadow = '0 2px 20px rgba(0,0,0,0.1)';
|
|
102
|
-
const logoFontSize = '1.8rem';
|
|
103
|
-
|
|
104
|
-
const reset = chain
|
|
105
|
-
.margin('0')
|
|
106
|
-
.padding('0')
|
|
107
|
-
.boxSizing('border-box')
|
|
108
|
-
.block('*');
|
|
109
|
-
|
|
110
|
-
const body = chain
|
|
111
|
-
.fontFamily(bodyFontFamily)
|
|
112
|
-
.lineHeight('1.6')
|
|
113
|
-
.color('#1e293b')
|
|
114
|
-
.bg(bodyBg)
|
|
115
|
-
.block('body');
|
|
116
|
-
|
|
117
|
-
/* Header/Navigation */
|
|
118
|
-
const navbar = chain
|
|
119
|
-
.bg(headerBg)
|
|
120
|
-
.backdropFilter('blur(10px)')
|
|
121
|
-
.padding('1rem 5%')
|
|
122
|
-
.position('fixed')
|
|
123
|
-
.width('100%')
|
|
124
|
-
.top('0')
|
|
125
|
-
.zIndex('1000')
|
|
126
|
-
.boxShadow(headerBoxShadow)
|
|
127
|
-
.block('.navbar');
|
|
128
|
-
|
|
129
|
-
const nav_container = chain
|
|
130
|
-
.maxWidth('1200px')
|
|
131
|
-
.margin('0 auto')
|
|
132
|
-
.display('flex')
|
|
133
|
-
.justifyContent('space-between')
|
|
134
|
-
.alignItems('center')
|
|
135
|
-
.block('.nav-container');
|
|
136
|
-
|
|
137
|
-
const logo = chain
|
|
138
|
-
.fontSize(logoFontSize)
|
|
139
|
-
.fontWeight('700')
|
|
140
|
-
.bg('linear-gradient(135deg, #667eea, #764ba2)')
|
|
141
|
-
.backgroundClip('text')
|
|
142
|
-
.textFillColor('transparent')
|
|
143
|
-
.letterSpacing('-0.5px')
|
|
144
|
-
.block('.logo');
|
|
122
|
+
Auto-prefixing ✅ Built-in + full Autoprefixer
|
|
145
123
|
|
|
146
|
-
|
|
147
|
-
reset,
|
|
148
|
-
navbar,
|
|
149
|
-
nav_container,
|
|
150
|
-
logo
|
|
151
|
-
};
|
|
124
|
+
Source Maps ✅ Debug your .jcss files
|
|
152
125
|
|
|
126
|
+
Watch Mode ✅ Instant recompilation
|
|
153
127
|
|
|
154
|
-
|
|
128
|
+
VM Security ✅ Safe code execution
|
|
155
129
|
|
|
156
|
-
<@
|
|
157
|
-
// Import chaining definitions
|
|
158
|
-
const style = get('./chain.jcss');
|
|
159
130
|
|
|
160
|
-
|
|
161
|
-
style.logo.fontSize = '2rem';
|
|
162
|
-
|
|
163
|
-
// Compile to CSS
|
|
164
|
-
compile(style);
|
|
165
|
-
@>
|
|
131
|
+
## The ChainCSS API
|
|
166
132
|
|
|
167
|
-
|
|
168
|
-
<@
|
|
169
|
-
run(
|
|
170
|
-
chain.opacity('0').transform('translateY(20px)').block('from'),
|
|
171
|
-
chain.opacity('1').transform('translateY(0)').block('to'),
|
|
172
|
-
);
|
|
173
|
-
@>
|
|
174
|
-
}
|
|
133
|
+
### The Chain Builder
|
|
175
134
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
chain.flexDirection('column').alignItems('center').block('.cta-buttons'),
|
|
183
|
-
chain.gridTemplateColumns('1fr').block('.example-container'),
|
|
184
|
-
chain.display('none').block('.nav-links')
|
|
185
|
-
);
|
|
186
|
-
@>
|
|
187
|
-
}
|
|
135
|
+
```javascript
|
|
136
|
+
// jQuery-like fluent API
|
|
137
|
+
const style = $()
|
|
138
|
+
.propertyName('value') // camelCase → kebab-case
|
|
139
|
+
.anotherProperty('value')
|
|
140
|
+
.block('.selector'); // End the chain with selector(s)
|
|
188
141
|
|
|
142
|
+
// Pseudo-classes & nested styles
|
|
143
|
+
const button = $()
|
|
144
|
+
.color('white')
|
|
145
|
+
.backgroundColor('#667eea')
|
|
146
|
+
.hover()
|
|
147
|
+
.backgroundColor('#5a67d8')
|
|
148
|
+
.transform('scale(1.05)')
|
|
149
|
+
.focus()
|
|
150
|
+
.boxShadow('0 0 0 3px rgba(102,126,234,0.5)')
|
|
151
|
+
.block('.btn');
|
|
152
|
+
````
|
|
153
|
+
### File Structure
|
|
189
154
|
|
|
190
|
-
|
|
155
|
+
```text
|
|
156
|
+
your-project/
|
|
157
|
+
├── chaincss/
|
|
158
|
+
│ ├── main.jcss # Entry point - imports & compiles
|
|
159
|
+
│ ├── processor.cjs # Build script
|
|
160
|
+
│ └── *.jcss # Your style definitions
|
|
161
|
+
├── src/
|
|
162
|
+
│ └── style/
|
|
163
|
+
│ └── global.css # Generated CSS
|
|
164
|
+
└── package.json
|
|
165
|
+
```
|
|
166
|
+
### Basic Example
|
|
191
167
|
|
|
192
|
-
|
|
168
|
+
**chaincss/button.jcss**
|
|
193
169
|
|
|
194
|
-
|
|
170
|
+
```javascript
|
|
171
|
+
const button = $()
|
|
172
|
+
.backgroundColor('#667eea')
|
|
173
|
+
.color('white')
|
|
174
|
+
.padding('0.75rem 1.5rem')
|
|
175
|
+
.borderRadius('0.375rem')
|
|
176
|
+
.fontWeight('600')
|
|
177
|
+
.block('.btn');
|
|
195
178
|
|
|
196
|
-
|
|
197
|
-
```bash
|
|
198
|
-
npm create vite@latest my-app -- --template react
|
|
199
|
-
cd my-app
|
|
179
|
+
module.exports = { button };
|
|
200
180
|
```
|
|
181
|
+
**chaincss/main.jcss**
|
|
201
182
|
|
|
202
|
-
|
|
183
|
+
```javascript
|
|
184
|
+
<@
|
|
185
|
+
const { button } = get('./button.jcss');
|
|
186
|
+
compile({ button });
|
|
187
|
+
@>
|
|
188
|
+
````
|
|
203
189
|
|
|
204
|
-
|
|
205
|
-
├── src/
|
|
206
|
-
│ ├── components/
|
|
207
|
-
│ │ ├── Navbar/
|
|
208
|
-
│ │ │ ├── Navbar.jsx
|
|
209
|
-
│ │ │ └── navbar.jcss # Chain definitions with fluent API
|
|
210
|
-
│ │ ├── Button/
|
|
211
|
-
│ │ │ ├── Button.jsx
|
|
212
|
-
│ │ │ └── button.jcss # Chain definitions with fluent API
|
|
213
|
-
│ │ └── ...
|
|
214
|
-
│ ├── style/
|
|
215
|
-
│ │ └── global.css # Generated CSS
|
|
216
|
-
│ ├── App.jsx
|
|
217
|
-
│ └── main.jsx
|
|
218
|
-
├── chaincss/
|
|
219
|
-
│ ├── main.jcss # Entry point - imports and compiles
|
|
220
|
-
│ └── processor.js # Processing script
|
|
221
|
-
└── package.json
|
|
190
|
+
**chaincss/processor.js**
|
|
222
191
|
|
|
223
|
-
|
|
192
|
+
```javascript
|
|
224
193
|
|
|
225
|
-
|
|
226
|
-
2. **`main.jcss` imports all component styles** using `get()` function
|
|
227
|
-
3. **Styles are merged and compiled** into a single `global.css` file
|
|
228
|
-
4. **React components import the generated CSS** and use the class names
|
|
194
|
+
const chaincss = require('@melcanz85/chaincss');
|
|
229
195
|
|
|
230
|
-
|
|
196
|
+
chaincss.processor('./chaincss/main.jcss', './src/style');
|
|
197
|
+
// Generates ./src/style/global.css
|
|
198
|
+
```
|
|
199
|
+
## Advanced Features
|
|
200
|
+
|
|
201
|
+
### Design Tokens
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
|
|
205
|
+
// tokens.js
|
|
206
|
+
const { createTokens } = require('@melcanz85/chaincss');
|
|
207
|
+
|
|
208
|
+
module.exports = createTokens({
|
|
209
|
+
colors: {
|
|
210
|
+
primary: '#667eea',
|
|
211
|
+
secondary: '#764ba2'
|
|
212
|
+
},
|
|
213
|
+
spacing: {
|
|
214
|
+
sm: '0.5rem',
|
|
215
|
+
md: '1rem',
|
|
216
|
+
lg: '1.5rem'
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// In your styles
|
|
221
|
+
const button = $()
|
|
222
|
+
.color('$colors.primary') // ← Token syntax!
|
|
223
|
+
.padding('$spacing.md')
|
|
224
|
+
.block('.btn');
|
|
225
|
+
```
|
|
231
226
|
|
|
232
|
-
|
|
227
|
+
## Atomic CSS Optimization
|
|
233
228
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
.
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
229
|
+
```javascript
|
|
230
|
+
// chaincss.config.js
|
|
231
|
+
module.exports = {
|
|
232
|
+
atomic: {
|
|
233
|
+
enabled: true, // Enable 90% CSS size reduction
|
|
234
|
+
threshold: 3, // Styles used 3+ times become atomic
|
|
235
|
+
naming: 'hash' // Smallest class names
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
```
|
|
239
|
+
**Before (standard CSS):** 4,823 chars
|
|
240
|
+
**After (atomic CSS):** 499 chars → **90% smaller!**
|
|
244
241
|
|
|
245
|
-
|
|
242
|
+
### Built-in Security
|
|
246
243
|
|
|
247
|
-
**
|
|
244
|
+
ChainCSS uses **secure VM sandboxing** to safely execute your .jcss files. No eval, no global leaks, no security risks.
|
|
248
245
|
|
|
249
|
-
const hero = chain
|
|
250
|
-
.padding('120px 5% 80px')
|
|
251
|
-
.bg('linear-gradient(135deg, #667eea 0%, #764ba2 100%)')
|
|
252
|
-
.color('white')
|
|
253
|
-
.textAlign('center')
|
|
254
|
-
.block('.hero');
|
|
255
246
|
|
|
256
|
-
|
|
247
|
+
## Quick Start Guides
|
|
257
248
|
|
|
258
|
-
|
|
249
|
+
### With Node.js (Vanilla)
|
|
259
250
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
chain.margin('0').padding('0').boxSizing('border-box').block('*'),
|
|
264
|
-
chain
|
|
265
|
-
.fontFamily("-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif")
|
|
266
|
-
.lineHeight('1.6')
|
|
267
|
-
.color('#1e293b')
|
|
268
|
-
.bg('linear-gradient(135deg, #667eea 0%, #764ba2 100%)')
|
|
269
|
-
.block('body')
|
|
270
|
-
);
|
|
271
|
-
@>
|
|
251
|
+
```bash
|
|
252
|
+
# 1. Install
|
|
253
|
+
npm install @melcanz85/chaincss
|
|
272
254
|
|
|
273
|
-
.
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
padding: 0.5rem 1rem;
|
|
277
|
-
border-radius: 4px;
|
|
278
|
-
border: none;
|
|
279
|
-
cursor: pointer;
|
|
280
|
-
}
|
|
255
|
+
# 2. Create processor.cjs
|
|
256
|
+
echo "const chaincss = require('@melcanz85/chaincss');
|
|
257
|
+
chaincss.processor('./chaincss/main.jcss', './dist');" > processor.js
|
|
281
258
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const
|
|
285
|
-
|
|
259
|
+
# 3. Create your first .jcss file
|
|
260
|
+
mkdir chaincss
|
|
261
|
+
echo "const hello = $().color('red').block('.hello');
|
|
262
|
+
compile({ hello });" > chaincss/main.jcss
|
|
286
263
|
|
|
287
|
-
|
|
288
|
-
|
|
264
|
+
# 4. Build
|
|
265
|
+
node processor.js
|
|
266
|
+
# ✅ ./dist/global.css generated!
|
|
267
|
+
```
|
|
268
|
+
### With React + Vite
|
|
289
269
|
|
|
290
|
-
|
|
291
|
-
|
|
270
|
+
```bash
|
|
271
|
+
# 1. Create React app
|
|
272
|
+
npm create vite@latest my-app -- --template react
|
|
273
|
+
cd my-app
|
|
292
274
|
|
|
293
|
-
|
|
294
|
-
|
|
275
|
+
# 2. Install ChainCSS
|
|
276
|
+
npm install @melcanz85/chaincss
|
|
295
277
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
278
|
+
# 3. Create component with styles
|
|
279
|
+
mkdir -p src/components/Button
|
|
280
|
+
```
|
|
281
|
+
**src/components/Button/Button.jsx**
|
|
282
|
+
|
|
283
|
+
```jsx
|
|
284
|
+
|
|
285
|
+
import { useChainStyles } from '@melcanz85/chaincss';
|
|
286
|
+
|
|
287
|
+
export function Button({ variant = 'primary', children }) {
|
|
288
|
+
const styles = useChainStyles({
|
|
289
|
+
button: () => $()
|
|
290
|
+
.backgroundColor(variant === 'primary' ? '#667eea' : '#48bb78')
|
|
291
|
+
.color('white')
|
|
292
|
+
.padding('0.5rem 1rem')
|
|
293
|
+
.borderRadius('0.375rem')
|
|
294
|
+
.hover()
|
|
295
|
+
.transform('translateY(-2px)')
|
|
296
|
+
.boxShadow('0 4px 6px rgba(0,0,0,0.1)')
|
|
297
|
+
.block()
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
return <button className={styles.button}>{children}</button>;
|
|
304
301
|
}
|
|
302
|
+
```
|
|
305
303
|
|
|
306
|
-
/* Responsive */
|
|
307
|
-
@media (max-width: 768px) {
|
|
308
|
-
<@
|
|
309
|
-
run(
|
|
310
|
-
chain.fontSize('2.5rem').block('.hero h1'),
|
|
311
|
-
chain.flexDirection('column').gap('1rem').block('.stats'),
|
|
312
|
-
chain.flexDirection('column').alignItems('center').block('.cta-buttons'),
|
|
313
|
-
chain.gridTemplateColumns('1fr').block('.example-container'),
|
|
314
|
-
chain.display('none').block('.nav-links')
|
|
315
|
-
);
|
|
316
|
-
@>
|
|
317
|
-
}
|
|
318
304
|
|
|
319
|
-
|
|
305
|
+
## Performance Comparison
|
|
320
306
|
|
|
321
|
-
|
|
307
|
+
Approach Runtime Cost Bundle Size Dynamic Styles Learning Curve
|
|
322
308
|
|
|
323
|
-
|
|
309
|
+
**ChainCSS (Build)** **Zero** **Just CSS** Build-time Low
|
|
324
310
|
|
|
325
|
-
|
|
311
|
+
**ChainCSS (Runtime)** Minimal Small runtime ✅ Full Low
|
|
326
312
|
|
|
327
|
-
|
|
313
|
+
Styled Components 5-10KB runtime CSS + runtime ✅ Full Medium
|
|
328
314
|
|
|
329
|
-
|
|
315
|
+
Emotion 8-12KB runtime CSS + runtime ✅ Full Medium
|
|
330
316
|
|
|
331
|
-
|
|
317
|
+
Tailwind Zero Just CSS ⚠️ Limited High
|
|
332
318
|
|
|
333
|
-
|
|
319
|
+
CSS Modules Zero Just CSS ❌ None Low
|
|
334
320
|
|
|
335
|
-
|
|
321
|
+
**ChainCSS is the ONLY library that gives you BOTH worlds!**
|
|
336
322
|
|
|
337
|
-
* Keep styles close to components: Button/button.jcss
|
|
338
323
|
|
|
339
|
-
|
|
324
|
+
## Configuration
|
|
340
325
|
|
|
341
|
-
|
|
326
|
+
Create chaincss.config.js in your project root:
|
|
342
327
|
|
|
343
|
-
|
|
328
|
+
```javascript
|
|
344
329
|
|
|
345
|
-
|
|
330
|
+
module.exports = {
|
|
331
|
+
// Atomic CSS optimization
|
|
332
|
+
atomic: {
|
|
333
|
+
enabled: true,
|
|
334
|
+
threshold: 3, // Min usage for atomic conversion
|
|
335
|
+
naming: 'hash' // 'hash' | 'readable' | 'short'
|
|
336
|
+
},
|
|
337
|
+
|
|
338
|
+
// Prefixer options
|
|
339
|
+
prefixer: {
|
|
340
|
+
mode: 'auto', // 'auto' or 'full'
|
|
341
|
+
browsers: ['> 0.5%', 'last 2 versions']
|
|
342
|
+
},
|
|
343
|
+
|
|
344
|
+
// Source maps
|
|
345
|
+
sourceMaps: true
|
|
346
|
+
};
|
|
347
|
+
```
|
|
346
348
|
|
|
347
|
-
3. Dynamic Styles
|
|
348
349
|
|
|
349
|
-
|
|
350
|
-
const theme = {
|
|
351
|
-
primary: '#667eea',
|
|
352
|
-
secondary: '#764ba2'
|
|
353
|
-
};
|
|
350
|
+
## API Reference
|
|
354
351
|
|
|
355
|
-
|
|
356
|
-
.backgroundColor(theme.primary)
|
|
357
|
-
.block('.btn');
|
|
358
|
-
|
|
359
|
-
const buttonHover = chain
|
|
360
|
-
.backgroundColor(theme.secondary)
|
|
361
|
-
.block('.btn:hover');
|
|
352
|
+
### Core Functions
|
|
362
353
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
You can directly put css syntax code on your main.jcss file.
|
|
354
|
+
Function Description
|
|
366
355
|
|
|
367
|
-
|
|
356
|
+
`$()` Create a new chain builder
|
|
368
357
|
|
|
369
|
-
|
|
358
|
+
`.block(selector)` End chain and assign selector(s)
|
|
370
359
|
|
|
371
|
-
|
|
360
|
+
`compile(styles)` Compile style objects to CSS
|
|
372
361
|
|
|
373
|
-
|
|
374
|
-
main file it will overwrite the styles in the chain file.
|
|
362
|
+
`run(...styles)` Process inline styles
|
|
375
363
|
|
|
376
|
-
|
|
364
|
+
`get(filename)` Import .jcss files
|
|
377
365
|
|
|
378
|
-
|
|
379
|
-
easily enable proper syntax highlighting in your editor:
|
|
366
|
+
`processor(input, output)` Build-time processor
|
|
380
367
|
|
|
381
|
-
VS Code
|
|
382
368
|
|
|
383
|
-
|
|
369
|
+
### React Hooks
|
|
384
370
|
|
|
385
|
-
|
|
386
|
-
"files.associations": {
|
|
387
|
-
"*.jcss": "javascript"
|
|
388
|
-
}
|
|
389
|
-
}
|
|
371
|
+
Hook Description
|
|
390
372
|
|
|
391
|
-
|
|
373
|
+
`useChainStyles(styles, options)` Basic styles hook
|
|
392
374
|
|
|
393
|
-
|
|
375
|
+
`useDynamicChainStyles(factory, deps)` Styles that depend on props/state
|
|
394
376
|
|
|
395
|
-
|
|
377
|
+
`useThemeChainStyles(styles, theme)` Theme-aware styles
|
|
396
378
|
|
|
397
|
-
|
|
379
|
+
`ChainCSSGlobal` Global styles component
|
|
398
380
|
|
|
399
|
-
|
|
381
|
+
`cx(...classes)` Conditional class merging
|
|
400
382
|
|
|
401
|
-
Add to your .vimrc or init.vim:
|
|
402
383
|
|
|
403
|
-
|
|
384
|
+
## Editor Support
|
|
404
385
|
|
|
405
|
-
|
|
386
|
+
### VS Code
|
|
406
387
|
|
|
407
|
-
|
|
388
|
+
```json
|
|
389
|
+
{
|
|
390
|
+
"files.associations": {
|
|
391
|
+
"*.jcss": "javascript"
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
```
|
|
408
395
|
|
|
409
|
-
|
|
396
|
+
### WebStorm
|
|
410
397
|
|
|
411
|
-
|
|
412
|
-
"extensions": ["jcss"],
|
|
413
|
-
"syntax": "Packages/JavaScript/JavaScript.sublime-syntax"
|
|
414
|
-
}
|
|
398
|
+
* Settings → Editor → File Types
|
|
415
399
|
|
|
416
|
-
|
|
400
|
+
* Add `*.jcss` as JavaScript
|
|
417
401
|
|
|
418
|
-
|
|
419
|
-
|
|
402
|
+
### Vim
|
|
403
|
+
|
|
404
|
+
```vim
|
|
405
|
+
au BufRead,BufNewFile `*.jcss` setfiletype javascript
|
|
406
|
+
```
|
|
420
407
|
|
|
421
|
-
"*":
|
|
422
|
-
core:
|
|
423
|
-
customFileTypes:
|
|
424
|
-
"source.js": [
|
|
425
|
-
"jcss"
|
|
426
|
-
]
|
|
427
408
|
|
|
409
|
+
## Roadmap
|
|
428
410
|
|
|
429
|
-
|
|
411
|
+
* Zero-runtime compilation
|
|
430
412
|
|
|
431
|
-
|
|
413
|
+
* React hooks
|
|
432
414
|
|
|
415
|
+
* Atomic CSS optimization
|
|
433
416
|
|
|
434
|
-
|
|
417
|
+
* Design tokens
|
|
435
418
|
|
|
436
|
-
|
|
419
|
+
* TypeScript support
|
|
437
420
|
|
|
438
|
-
|
|
421
|
+
* Vue/Svelte integrations (coming soon)
|
|
439
422
|
|
|
440
|
-
|
|
423
|
+
* Plugin system (coming soon)
|
|
441
424
|
|
|
442
|
-
✅ Keyframe animations @keyframes support
|
|
443
|
-
|
|
444
|
-
✅ Source maps Debug generated CSS
|
|
445
425
|
|
|
446
|
-
|
|
426
|
+
## Contributing
|
|
447
427
|
|
|
428
|
+
Contributions are welcome! Whether it's:
|
|
448
429
|
|
|
449
|
-
|
|
430
|
+
* Bug fixes
|
|
450
431
|
|
|
451
|
-
|
|
432
|
+
* Documentation improvements
|
|
452
433
|
|
|
453
|
-
|
|
434
|
+
* New features
|
|
454
435
|
|
|
455
|
-
|
|
436
|
+
* Test cases
|
|
456
437
|
|
|
438
|
+
Please see CONTRIBUTING.md for guidelines.
|
|
457
439
|
|
|
458
|
-
## 🔄 chaincss vs Other Approaches
|
|
459
440
|
|
|
460
|
-
|
|
461
|
-
|----------------|-------------------|---------------------|---------------|-------------|
|
|
462
|
-
| **When CSS is generated** | ⚙️ **Build time** | 🕒 Runtime (browser) | ⚙️ Build time | 📁 Already written |
|
|
463
|
-
| **Browser work**| None - just serves CSS | Executes JS to generate CSS | None - just serves CSS | None |
|
|
464
|
-
| **Dynamic values**| ✅ Via JS at build time | ✅ Via props at runtime | ⚠️ Limited | ❌ Manual |
|
|
465
|
-
| **Bundle size** | Just the CSS | CSS + JS runtime | Just the CSS | Just the CSS |
|
|
441
|
+
## License
|
|
466
442
|
|
|
467
|
-
|
|
443
|
+
MIT © [Rommel Caneos]('https://github.com/melcanz08')
|
|
468
444
|
|
|
469
|
-
Contributions are welcome! Feel free to open issues or submit pull requests.
|
|
470
445
|
|
|
471
|
-
|
|
446
|
+
## Star Us on GitHub!
|
|
472
447
|
|
|
473
|
-
|
|
448
|
+
If ChainCSS helps you, please [give it a star!]('https://github.com/melcanz08/chaincss') It helps others discover it.
|