@melcanz85/chaincss 1.8.0 → 1.9.2
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 +298 -311
- package/atomic-optimizer.js +275 -0
- package/cache-manager.js +68 -0
- package/chaincss.js +182 -17
- package/index.js +24 -0
- package/index.react.js +4 -0
- package/package.json +27 -3
- package/prefixer.js +2 -2
- package/react-hooks.js +175 -0
- package/tokens.js +256 -0
- package/transpiler.js +24 -35
- package/types.d.ts +148 -0
- package/.github/workflows/publish.yml +0 -22
- package/publish.sh +0 -7
package/README.md
CHANGED
|
@@ -1,446 +1,433 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ChainCSS
|
|
2
2
|
|
|
3
|
+

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