chaincss 2.3.0 → 2.3.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 +456 -352
- package/chaincssTutorial.md +1168 -0
- package/dist/browser.js +94 -1
- package/dist/compiler/index.js +93 -0
- package/dist/compiler/intent-engine.d.ts +5 -0
- package/dist/compiler/suggestions.d.ts +2 -0
- package/dist/core/types.d.ts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +121 -1
- package/dist/runtime/index.js +94 -1
- package/package.json +1 -1
- package/src/compiler/intent-engine.ts +28 -0
- package/src/compiler/suggestions.ts +32 -0
- package/src/core/types.ts +1 -0
- package/src/index.ts +1 -0
package/README.md
CHANGED
|
@@ -1,36 +1,51 @@
|
|
|
1
1
|
<h1 align="center">ChainCSS</h1>
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
<strong>The
|
|
5
|
-
Zero runtime by default.
|
|
4
|
+
<strong>The CSS-in-JS platform with compiler intelligence.</strong><br>
|
|
5
|
+
Zero runtime by default. Semantic styling. WCAG-aware. Intent-driven.
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
8
|
<p align="center">
|
|
9
9
|
<a href="https://www.npmjs.com/package/chaincss">
|
|
10
10
|
<img src="https://img.shields.io/npm/v/chaincss" alt="npm">
|
|
11
11
|
</a>
|
|
12
|
+
|
|
12
13
|
<a href="https://github.com/melcanz08/chaincss/blob/main/LICENSE">
|
|
13
14
|
<img src="https://img.shields.io/github/license/melcanz08/chaincss" alt="license">
|
|
14
15
|
</a>
|
|
15
|
-
|
|
16
|
-
<img src="https://img.shields.io/badge/docs-chaincss.dev-blue" alt="docs">
|
|
17
|
-
</a>
|
|
16
|
+
|
|
18
17
|
<a href="https://github.com/melcanz08/chaincss/actions">
|
|
19
|
-
<img src="https://img.shields.io/badge/tests-
|
|
18
|
+
<img src="https://img.shields.io/badge/tests-708%20passed-brightgreen" alt="tests">
|
|
19
|
+
</a>
|
|
20
|
+
|
|
21
|
+
<a href="https://github.com/melcanz08/chaincss">
|
|
22
|
+
<img src="https://img.shields.io/badge/modules-17-blue" alt="modules">
|
|
20
23
|
</a>
|
|
21
24
|
</p>
|
|
22
25
|
|
|
23
26
|
|
|
27
|
+
|
|
24
28
|
# What is ChainCSS?
|
|
25
29
|
|
|
26
30
|
ChainCSS lets you write styles as **native JavaScript method chains** — no CSS syntax, no template literals, no object literals.
|
|
27
31
|
|
|
28
32
|
It automatically detects which styles are static (compiled to zero-runtime CSS) and which are dynamic (stay in JS), then splits them automatically.
|
|
29
33
|
|
|
34
|
+
ChainCSS is also a **CSS intelligence platform** — not just a styling library.
|
|
35
|
+
|
|
36
|
+
It writes, checks, and optimizes your styles at build time with zero runtime cost.
|
|
37
|
+
|
|
30
38
|
```ts
|
|
31
39
|
import { chain } from "chaincss";
|
|
32
40
|
|
|
41
|
+
// A single intent expands to a full,
|
|
42
|
+
// accessible, responsive card:
|
|
33
43
|
const card = chain()
|
|
44
|
+
.intent("card")
|
|
45
|
+
.$el("card");
|
|
46
|
+
|
|
47
|
+
// Or write explicit styles:
|
|
48
|
+
const hero = chain()
|
|
34
49
|
.display("flex")
|
|
35
50
|
.flexDirection("column")
|
|
36
51
|
.gap(16)
|
|
@@ -41,505 +56,589 @@ const card = chain()
|
|
|
41
56
|
.boxShadow("0 4px 12px rgba(0,0,0,0.15)")
|
|
42
57
|
.transform("translateY(-2px)")
|
|
43
58
|
.end()
|
|
44
|
-
.$el("
|
|
59
|
+
.$el("hero");
|
|
45
60
|
```
|
|
46
61
|
|
|
47
|
-
**No CSS syntax. No template literals.
|
|
62
|
+
**No CSS syntax. No template literals. Compiler-enforced quality.**
|
|
48
63
|
|
|
49
64
|
|
|
50
|
-
#
|
|
65
|
+
# Constraint-Based Styling
|
|
51
66
|
|
|
52
|
-
|
|
53
|
-
npm install chaincss
|
|
54
|
-
```
|
|
67
|
+
Declare relationships, not values. The constraint solver compiles them to native CSS at build time.
|
|
55
68
|
|
|
56
|
-
|
|
69
|
+
**No runtime JS. No manual `calc()`. The compiler picks the best CSS feature.**
|
|
57
70
|
|
|
58
|
-
|
|
59
|
-
|---|---|
|
|
60
|
-
| **Vite** | Add `chaincss()` plugin to `vite.config.ts` |
|
|
61
|
-
| **Node.js** | `import { chain } from "chaincss"` |
|
|
62
|
-
| **Browser CDN** | `import { chain } from "https://cdn.jsdelivr.net/npm/chaincss/dist/browser.js"` |
|
|
63
|
-
| **Browser + import map** | Map `"chaincss"` to `./node_modules/chaincss/dist/browser.js` |
|
|
71
|
+
---
|
|
64
72
|
|
|
73
|
+
## 1. Aspect Ratios from Math
|
|
65
74
|
|
|
66
|
-
|
|
75
|
+
Describe the relationship between width and height:
|
|
67
76
|
|
|
68
77
|
```ts
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
export default defineConfig({
|
|
74
|
-
plugins: [chaincss({ atomic: true })],
|
|
75
|
-
});
|
|
78
|
+
chain()
|
|
79
|
+
.constrain("height", "= width * 0.5") // 2:1 ratio
|
|
80
|
+
.constrain("width", "< parent") // Don't overflow container
|
|
81
|
+
.$el("video");
|
|
76
82
|
```
|
|
77
83
|
|
|
84
|
+
### Compiles to
|
|
78
85
|
|
|
79
|
-
|
|
86
|
+
```css
|
|
87
|
+
.video {
|
|
88
|
+
aspect-ratio: 1 / 2;
|
|
89
|
+
max-width: 100%;
|
|
90
|
+
}
|
|
91
|
+
```
|
|
80
92
|
|
|
81
|
-
|
|
93
|
+
The solver detects `width * 0.5` and emits `aspect-ratio` instead of:
|
|
82
94
|
|
|
83
|
-
|
|
95
|
+
```css
|
|
96
|
+
height: calc(width * 0.5);
|
|
97
|
+
```
|
|
84
98
|
|
|
85
|
-
|
|
86
|
-
import { chain } from "chaincss";
|
|
99
|
+
`aspect-ratio` has better performance and avoids layout shifts.
|
|
87
100
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
.$el("my-component");
|
|
101
|
+
### Tailwind Equivalent
|
|
102
|
+
|
|
103
|
+
```txt
|
|
104
|
+
aspect-[2/1] max-w-full
|
|
93
105
|
```
|
|
94
106
|
|
|
95
|
-
|
|
107
|
+
### ChainCSS Difference
|
|
96
108
|
|
|
97
|
-
|
|
98
|
-
import { smartChain } from "chaincss";
|
|
109
|
+
You write the math. The compiler writes the CSS.
|
|
99
110
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
.color(props.textColor)
|
|
104
|
-
.fontSize(theme.sizes.lg)
|
|
105
|
-
.$el("hybrid-card");
|
|
106
|
-
```
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 2. Container-Aware Responsive Layouts
|
|
107
114
|
|
|
108
|
-
|
|
115
|
+
Use conditional constraints to generate `@container` queries automatically.
|
|
109
116
|
|
|
110
117
|
```ts
|
|
111
|
-
|
|
118
|
+
chain()
|
|
119
|
+
.constrain("columns", ">= 3 when > 768px")
|
|
120
|
+
.constrain("gap", "= 24px")
|
|
121
|
+
.$el("grid");
|
|
122
|
+
```
|
|
112
123
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
124
|
+
### Compiles to
|
|
125
|
+
|
|
126
|
+
```css
|
|
127
|
+
.grid {
|
|
128
|
+
gap: 24px;
|
|
129
|
+
}
|
|
118
130
|
|
|
119
|
-
|
|
131
|
+
@container (min-width: 768px) {
|
|
132
|
+
.grid {
|
|
133
|
+
columns: 3;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
120
136
|
```
|
|
121
137
|
|
|
138
|
+
> Requires `container-type: inline-size` on the parent.
|
|
139
|
+
> ChainCSS adds it automatically when container constraints are detected.
|
|
140
|
+
|
|
141
|
+
---
|
|
122
142
|
|
|
123
|
-
|
|
143
|
+
## 3. Fluid Values with `clamp()`
|
|
124
144
|
|
|
125
|
-
|
|
145
|
+
Stop calculating `clamp()` manually.
|
|
126
146
|
|
|
127
147
|
```ts
|
|
128
148
|
chain()
|
|
129
|
-
.
|
|
130
|
-
.
|
|
131
|
-
|
|
132
|
-
.br(8)
|
|
133
|
-
.fs(16)
|
|
134
|
-
.fw(700)
|
|
135
|
-
.c("#333")
|
|
136
|
-
.w(200)
|
|
137
|
-
.h(100)
|
|
138
|
-
.d("flex")
|
|
139
|
-
.z(10)
|
|
140
|
-
.op(0.5)
|
|
141
|
-
.ov("hidden")
|
|
142
|
-
.pos("relative");
|
|
149
|
+
.constrain("fontSize", "= clamp(14px, 5vw, 24px)")
|
|
150
|
+
.constrain("padding", "= clamp(16px, 4vw, 32px)")
|
|
151
|
+
.$el("hero");
|
|
143
152
|
```
|
|
144
153
|
|
|
154
|
+
### Compiles to
|
|
145
155
|
|
|
146
|
-
|
|
156
|
+
```css
|
|
157
|
+
.hero {
|
|
158
|
+
font-size: clamp(14px, 5vw, 24px);
|
|
159
|
+
padding: clamp(16px, 4vw, 32px);
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Works with:
|
|
164
|
+
|
|
165
|
+
- `clamp()`
|
|
166
|
+
- `min()`
|
|
167
|
+
- `max()`
|
|
168
|
+
- `calc()`
|
|
147
169
|
|
|
148
|
-
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 4. Scroll-Driven Sticky Positioning
|
|
173
|
+
|
|
174
|
+
"Stick this element until another element reaches the viewport."
|
|
149
175
|
|
|
150
176
|
```ts
|
|
151
|
-
chain()
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
chain().flexCenter();
|
|
155
|
-
chain().gridCenter();
|
|
156
|
-
chain().stack(16);
|
|
157
|
-
chain().cols(3);
|
|
158
|
-
chain().rows(2);
|
|
159
|
-
chain().bento(4);
|
|
160
|
-
chain().gridTable("200px");
|
|
177
|
+
chain()
|
|
178
|
+
.constrain("sidebar", "sticky until footer")
|
|
179
|
+
.$el("sidebar");
|
|
161
180
|
```
|
|
162
181
|
|
|
163
|
-
###
|
|
182
|
+
### Compiles to
|
|
164
183
|
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
184
|
+
```css
|
|
185
|
+
.sidebar {
|
|
186
|
+
position: sticky;
|
|
187
|
+
top: 0;
|
|
188
|
+
|
|
189
|
+
animation: sticky-sidebar 1s linear both;
|
|
190
|
+
animation-timeline: scroll();
|
|
191
|
+
animation-range: contain 0% contain 100%;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
@keyframes sticky-sidebar {
|
|
195
|
+
to {
|
|
196
|
+
position: relative;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
177
199
|
```
|
|
178
200
|
|
|
179
|
-
|
|
201
|
+
Zero JavaScript. Uses native `animation-timeline: scroll()` available in modern Chromium browsers.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## 5. Parent-Relative Constraints
|
|
206
|
+
|
|
207
|
+
Keep elements inside their parents without writing media queries.
|
|
180
208
|
|
|
181
209
|
```ts
|
|
182
|
-
chain()
|
|
183
|
-
|
|
210
|
+
chain()
|
|
211
|
+
.constrain("width", "< parent")
|
|
212
|
+
.constrain("width", "> 320px")
|
|
213
|
+
.$el("modal");
|
|
184
214
|
```
|
|
185
215
|
|
|
186
|
-
###
|
|
216
|
+
### Compiles to
|
|
187
217
|
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
218
|
+
```css
|
|
219
|
+
.modal {
|
|
220
|
+
max-width: 100%;
|
|
221
|
+
min-width: 320px;
|
|
222
|
+
}
|
|
193
223
|
```
|
|
194
224
|
|
|
195
|
-
|
|
225
|
+
---
|
|
196
226
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
227
|
+
# How It Works
|
|
228
|
+
|
|
229
|
+
The compiler parses constraint expressions and resolves them into the most optimal native CSS feature.
|
|
230
|
+
|
|
231
|
+
| You Write | Compiler Resolves To | Strategy |
|
|
232
|
+
|---|---|---|
|
|
233
|
+
| `width < parent` | `max-width: 100%` | Direct mapping |
|
|
234
|
+
| `height = width * 0.5` | `aspect-ratio: 1 / 2` | Aspect-ratio optimization |
|
|
235
|
+
| `fontSize = clamp(14, 5vw, 24)` | `font-size: clamp(...)` | Native clamp |
|
|
236
|
+
| `columns >= 3 when > 768px` | `@container (min-width: 768px)` | Container query |
|
|
237
|
+
| `sidebar sticky until footer` | `animation-timeline: scroll()` | Scroll timeline |
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Supported Operators
|
|
242
|
+
|
|
243
|
+
```txt
|
|
244
|
+
< > <= >= = !=
|
|
203
245
|
```
|
|
204
246
|
|
|
205
|
-
|
|
247
|
+
## Supported References
|
|
206
248
|
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
chain().aspect("16/9");
|
|
213
|
-
chain().aspect("square");
|
|
214
|
-
chain().fluidText({ min: 16, max: 24 });
|
|
215
|
-
chain().lineClamp(3);
|
|
249
|
+
```txt
|
|
250
|
+
parent
|
|
251
|
+
viewport
|
|
252
|
+
self
|
|
253
|
+
sibling.width
|
|
216
254
|
```
|
|
217
255
|
|
|
218
|
-
|
|
256
|
+
## Supported Functions
|
|
219
257
|
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
chain().textGradient(["#667eea", "#764ba2"]);
|
|
226
|
-
chain().meshGradient(["#f0f", "#0ff", "#ff0", "#0f0"]);
|
|
227
|
-
chain().noise(0.05);
|
|
228
|
-
chain().shimmer();
|
|
258
|
+
```txt
|
|
259
|
+
clamp()
|
|
260
|
+
min()
|
|
261
|
+
max()
|
|
262
|
+
calc()
|
|
229
263
|
```
|
|
230
264
|
|
|
231
|
-
|
|
265
|
+
---
|
|
232
266
|
|
|
233
|
-
|
|
234
|
-
chain().clickScale(0.95);
|
|
235
|
-
chain().pressable();
|
|
236
|
-
chain().focusRing("#3b82f6");
|
|
237
|
-
chain().skeleton(true);
|
|
267
|
+
# Debugging Constraints
|
|
238
268
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
269
|
+
See how constraints were resolved during compilation.
|
|
270
|
+
|
|
271
|
+
## CLI
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
chaincss build --explain
|
|
242
275
|
```
|
|
243
276
|
|
|
244
|
-
###
|
|
277
|
+
### Output
|
|
245
278
|
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
chain().outlineDebug();
|
|
250
|
-
chain().parallax(2);
|
|
251
|
-
chain().frostedNav(15);
|
|
279
|
+
```txt
|
|
280
|
+
card: height = width * 0.5 → aspect-ratio: 1/2
|
|
281
|
+
card: width < parent → max-width: 100%
|
|
252
282
|
```
|
|
253
283
|
|
|
254
|
-
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Programmatic Debugging
|
|
255
287
|
|
|
256
288
|
```ts
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
289
|
+
import { resolveConstraint } from "chaincss/compiler";
|
|
290
|
+
|
|
291
|
+
const result = resolveConstraint({
|
|
292
|
+
property: "height",
|
|
293
|
+
operator: "=",
|
|
294
|
+
expression: "width * 0.5",
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
console.log(result.explanation);
|
|
298
|
+
// "height = width * 0.5 → aspect-ratio: 1/2"
|
|
262
299
|
```
|
|
263
300
|
|
|
264
|
-
## Nested Selectors
|
|
265
301
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
302
|
+
# What Makes ChainCSS Different
|
|
303
|
+
|
|
304
|
+
| Capability | ChainCSS | Tailwind | StyleX | Vanilla Extract |
|
|
305
|
+
|---|---|---|---|---|
|
|
306
|
+
| Zero runtime | ✅ | ✅ | ✅ | ✅ |
|
|
307
|
+
| Intent-based API | ✅ | ❌ | ❌ | ❌ |
|
|
308
|
+
| Semantic tokens | ✅ | ❌ | ❌ | ❌ |
|
|
309
|
+
| WCAG accessibility checking | ✅ | ❌ | ❌ | ❌ |
|
|
310
|
+
| Responsive inference | ✅ | ❌ | ❌ | ❌ |
|
|
311
|
+
| Pattern learning | ✅ | ❌ | ❌ | ❌ |
|
|
312
|
+
| CSS `if()` transpiler | ✅ | ❌ | ❌ | ❌ |
|
|
313
|
+
| Constraint-based styling | ✅ | ❌ | ❌ | ❌ |
|
|
314
|
+
| Layout intelligence | ✅ | ❌ | ❌ | ❌ |
|
|
315
|
+
| Scroll-driven animations | ✅ | ❌ | ❌ | ❌ |
|
|
316
|
+
| Self-healing CSS | ✅ | ❌ | ❌ | ❌ |
|
|
317
|
+
| Source-aware optimization | ✅ | ❌ | ❌ | ❌ |
|
|
318
|
+
| Design system extraction | ✅ | ❌ | ❌ | ❌ |
|
|
319
|
+
| 3 modes (build/runtime/hybrid) | ✅ | ❌ | ❌ | ❌ |
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
# Installation
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
npm install chaincss
|
|
273
327
|
```
|
|
274
328
|
|
|
275
|
-
|
|
329
|
+
|
|
330
|
+
# Quick Start
|
|
331
|
+
|
|
332
|
+
| Environment | Setup |
|
|
333
|
+
|---|---|
|
|
334
|
+
| Vite | Add `chaincss()` plugin to `vite.config.ts` |
|
|
335
|
+
| Node.js | `import { chain } from "chaincss"` |
|
|
336
|
+
| Browser CDN | `import { chain } from "https://cdn.jsdelivr.net/npm/chaincss/dist/browser.js"` |
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
# Intent API (v2.3)
|
|
340
|
+
|
|
341
|
+
The highest-level API.
|
|
342
|
+
|
|
343
|
+
Write what you want — the compiler figures out how.
|
|
276
344
|
|
|
277
345
|
```ts
|
|
278
|
-
|
|
279
|
-
chain().
|
|
346
|
+
// Layout intents
|
|
347
|
+
chain().intent("center-content").$el("centered");
|
|
348
|
+
chain().intent("stack").$el("stack");
|
|
349
|
+
chain().intent("sidebar-layout").$el("dashboard");
|
|
350
|
+
|
|
351
|
+
// Component intents
|
|
352
|
+
chain().intent("card").$el("card");
|
|
353
|
+
chain().intent("button-primary").$el("cta");
|
|
354
|
+
chain().intent("modal").$el("dialog");
|
|
355
|
+
|
|
356
|
+
// Semantic intents
|
|
357
|
+
chain().intent("hero-section").$el("hero");
|
|
358
|
+
chain().intent("sticky-header").$el("nav");
|
|
359
|
+
|
|
360
|
+
// Interaction intents
|
|
361
|
+
chain().intent("hover-lift").$el("interactive");
|
|
362
|
+
chain().intent("focus-ring").$el("accessible");
|
|
280
363
|
```
|
|
281
364
|
|
|
282
|
-
|
|
365
|
+
Each intent triggers:
|
|
366
|
+
- semantic tokens
|
|
367
|
+
- responsive overrides
|
|
368
|
+
- accessibility checks
|
|
369
|
+
- theme adaptation
|
|
370
|
+
|
|
371
|
+
—all at build time.
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
# Semantic Tokens
|
|
283
376
|
|
|
284
377
|
```ts
|
|
285
378
|
chain()
|
|
286
|
-
.
|
|
287
|
-
.
|
|
288
|
-
.
|
|
289
|
-
.
|
|
290
|
-
|
|
379
|
+
.surface("interactive")
|
|
380
|
+
.text("primary")
|
|
381
|
+
.elevation("floating")
|
|
382
|
+
.spacing("comfortable")
|
|
383
|
+
.state("hover")
|
|
384
|
+
.state("focus")
|
|
385
|
+
.$el("composed");
|
|
291
386
|
```
|
|
292
387
|
|
|
293
|
-
|
|
388
|
+
| Category | Available Intents |
|
|
389
|
+
|---|---|
|
|
390
|
+
| surface | interactive, container, overlay, sheet |
|
|
391
|
+
| text | primary, secondary, muted, link |
|
|
392
|
+
| elevation | flat, raised, floating, modal |
|
|
393
|
+
| spacing | none, tight, compact, spacious |
|
|
394
|
+
| state | hover, active, focus, disabled |
|
|
395
|
+
|
|
396
|
+
|
|
294
397
|
|
|
295
|
-
|
|
398
|
+
# Compiler Intelligence
|
|
399
|
+
|
|
400
|
+
ChainCSS analyzes your styles at build time and reports issues before they ship.
|
|
296
401
|
|
|
297
402
|
```ts
|
|
298
403
|
chain()
|
|
299
|
-
.
|
|
300
|
-
.
|
|
301
|
-
.
|
|
302
|
-
.
|
|
303
|
-
.
|
|
304
|
-
.$el("
|
|
404
|
+
.width("1200px")
|
|
405
|
+
.color("#999")
|
|
406
|
+
.fontSize("10px")
|
|
407
|
+
.outline("none")
|
|
408
|
+
.animation("fadeIn 1s")
|
|
409
|
+
.$el("risky-button");
|
|
305
410
|
```
|
|
306
411
|
|
|
307
|
-
|
|
412
|
+
The compiler can:
|
|
413
|
+
- detect WCAG contrast failures
|
|
414
|
+
- fix invalid font sizes
|
|
415
|
+
- add focus-visible fallbacks
|
|
416
|
+
- wrap animations in reduced-motion queries
|
|
417
|
+
- prevent mobile overflow
|
|
308
418
|
|
|
309
|
-
```ts
|
|
310
|
-
chain()
|
|
311
|
-
.width(helpers.calc("100% - 20px"))
|
|
312
|
-
.fontSize(helpers.clamp(16, 4, 24))
|
|
313
|
-
.margin(helpers.add(10, 20))
|
|
314
|
-
.$el("calculated");
|
|
315
419
|
|
|
316
|
-
// helpers.add(), .sub(), .mul(), .div(), .sum(), .difference()
|
|
317
|
-
// helpers.mpx(), .rem(), .em(), .percent(), .vw(), .vh()
|
|
318
|
-
// helpers.min(), .max(), .clamp(), .round(), .rgba(), .hsla()
|
|
319
|
-
// helpers.fluidType(min, max, minWidth, maxWidth)
|
|
320
|
-
```
|
|
321
420
|
|
|
322
|
-
|
|
421
|
+
# Constraint-Based Styling
|
|
323
422
|
|
|
324
423
|
```ts
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
secondary: "#10b981",
|
|
331
|
-
},
|
|
332
|
-
spacing: {
|
|
333
|
-
sm: "8px",
|
|
334
|
-
md: "16px",
|
|
335
|
-
lg: "24px",
|
|
336
|
-
},
|
|
337
|
-
});
|
|
424
|
+
chain()
|
|
425
|
+
.constrain("width", "< parent")
|
|
426
|
+
.constrain("height", "= width * 0.5")
|
|
427
|
+
.constrain("columns", ">= 3 when > 768px")
|
|
428
|
+
.$el("responsive-card");
|
|
338
429
|
```
|
|
339
430
|
|
|
340
|
-
### Theme Contracts
|
|
341
431
|
|
|
342
|
-
```ts
|
|
343
|
-
import { createThemeContract, createTheme, validateTheme } from "chaincss";
|
|
344
432
|
|
|
345
|
-
|
|
346
|
-
colors: { primary: "", background: "" },
|
|
347
|
-
spacing: { sm: "", md: "" },
|
|
348
|
-
});
|
|
433
|
+
# Scroll Timeline Engine
|
|
349
434
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
435
|
+
```ts
|
|
436
|
+
import {
|
|
437
|
+
createScrollAnimation,
|
|
438
|
+
compileScrollAnimation
|
|
439
|
+
} from "chaincss";
|
|
354
440
|
|
|
355
|
-
const
|
|
356
|
-
|
|
441
|
+
const fadeIn = createScrollAnimation(
|
|
442
|
+
"fadeIn",
|
|
443
|
+
".reveal"
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
const parallax = createScrollAnimation(
|
|
447
|
+
"parallax",
|
|
448
|
+
".bg"
|
|
449
|
+
);
|
|
357
450
|
```
|
|
358
451
|
|
|
359
|
-
|
|
452
|
+
Native scroll-driven animations with zero JavaScript runtime.
|
|
360
453
|
|
|
361
|
-
```ts
|
|
362
|
-
import { recipe } from "chaincss";
|
|
363
454
|
|
|
364
|
-
const button = recipe({
|
|
365
|
-
base: { selectors: ["btn"], display: "inline-flex", borderRadius: "8px", fontWeight: 600 },
|
|
366
|
-
variants: {
|
|
367
|
-
size: {
|
|
368
|
-
sm: { padding: "8px 16px", fontSize: "14px" },
|
|
369
|
-
lg: { padding: "16px 32px", fontSize: "18px" },
|
|
370
|
-
},
|
|
371
|
-
color: {
|
|
372
|
-
primary: { background: "#3b82f6", color: "white" },
|
|
373
|
-
danger: { background: "#ef4444", color: "white" },
|
|
374
|
-
},
|
|
375
|
-
},
|
|
376
|
-
defaultVariants: { size: "md", color: "primary" },
|
|
377
|
-
compoundVariants: [
|
|
378
|
-
{ variants: { size: "lg", color: "primary" }, style: { fontWeight: 800 } },
|
|
379
|
-
],
|
|
380
|
-
});
|
|
381
455
|
|
|
382
|
-
|
|
383
|
-
```
|
|
456
|
+
# Core API
|
|
384
457
|
|
|
385
|
-
|
|
458
|
+
## The Chain
|
|
386
459
|
|
|
387
460
|
```ts
|
|
388
|
-
chain
|
|
389
|
-
chain().zoomIn().$el("el"); chain().bounce().$el("el"); chain().bounce().$el("el");
|
|
390
|
-
chain().pulse().$el("el"); chain().spin().$el("el"); chain().spin().$el("el");
|
|
391
|
-
chain().shake().$el("el"); chain().wiggle().$el("el"); chain().wiggle().$el("el");
|
|
392
|
-
chain().float().$el("el"); chain().flash().$el("el"); chain().flash().$el("el");
|
|
393
|
-
chain().textReveal().$el("el");
|
|
461
|
+
import { chain } from "chaincss";
|
|
394
462
|
|
|
395
|
-
|
|
396
|
-
|
|
463
|
+
const styles = chain()
|
|
464
|
+
.display("flex")
|
|
465
|
+
.padding(20)
|
|
466
|
+
.color("red")
|
|
467
|
+
.$el("my-component");
|
|
397
468
|
```
|
|
398
469
|
|
|
399
|
-
|
|
470
|
+
## Smart Chain
|
|
400
471
|
|
|
401
472
|
```ts
|
|
402
|
-
import {
|
|
473
|
+
import { smartChain } from "chaincss";
|
|
403
474
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
475
|
+
const styles = smartChain()
|
|
476
|
+
.display("flex")
|
|
477
|
+
.padding(20)
|
|
478
|
+
.color(props.textColor)
|
|
479
|
+
.fontSize(theme.sizes.lg)
|
|
480
|
+
.$el("hybrid-card");
|
|
407
481
|
```
|
|
408
482
|
|
|
409
|
-
### Style Timeline
|
|
410
483
|
|
|
411
|
-
```ts
|
|
412
|
-
import { enableTimeline, getStyleHistory, getStyleDiff } from "chaincss";
|
|
413
484
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
485
|
+
# Shorthands
|
|
486
|
+
|
|
487
|
+
```ts
|
|
488
|
+
chain()
|
|
489
|
+
.bg("#fff")
|
|
490
|
+
.m(16)
|
|
491
|
+
.p(20)
|
|
492
|
+
.br(8)
|
|
493
|
+
.fs(16)
|
|
494
|
+
.fw(700)
|
|
495
|
+
.c("#333");
|
|
419
496
|
```
|
|
420
497
|
|
|
421
498
|
|
|
422
|
-
#
|
|
499
|
+
# Macros
|
|
423
500
|
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
501
|
+
```ts
|
|
502
|
+
chain().flex();
|
|
503
|
+
chain().grid();
|
|
504
|
+
chain().center();
|
|
505
|
+
chain().stack(16);
|
|
506
|
+
chain().glass();
|
|
507
|
+
chain().glow("#6366f1");
|
|
508
|
+
chain().focusRing("#3b82f6");
|
|
431
509
|
```
|
|
432
510
|
|
|
433
511
|
|
|
434
|
-
|
|
512
|
+
|
|
513
|
+
# Conditional Styles
|
|
435
514
|
|
|
436
515
|
```ts
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
516
|
+
chain()
|
|
517
|
+
.padding(12)
|
|
518
|
+
.when(isActive, c =>
|
|
519
|
+
c.background("#10b981")
|
|
520
|
+
.color("white")
|
|
521
|
+
)
|
|
522
|
+
.$el("stateful-btn");
|
|
523
|
+
```
|
|
440
524
|
|
|
441
|
-
output: {
|
|
442
|
-
cssFile: "global.css",
|
|
443
|
-
minify: true,
|
|
444
|
-
},
|
|
445
525
|
|
|
446
|
-
atomic: {
|
|
447
|
-
enabled: true,
|
|
448
|
-
mode: "hybrid",
|
|
449
|
-
threshold: 2,
|
|
450
|
-
naming: "hash",
|
|
451
|
-
},
|
|
452
526
|
|
|
453
|
-
|
|
454
|
-
sm: "(min-width: 640px)",
|
|
455
|
-
md: "(min-width: 768px)",
|
|
456
|
-
},
|
|
527
|
+
# Responsive Design
|
|
457
528
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
529
|
+
```ts
|
|
530
|
+
chain()
|
|
531
|
+
.display("flex")
|
|
532
|
+
.flexDirection("column")
|
|
533
|
+
.responsive("md", c =>
|
|
534
|
+
c.flexDirection("row")
|
|
535
|
+
)
|
|
536
|
+
.$el("responsive");
|
|
463
537
|
```
|
|
464
538
|
|
|
465
539
|
|
|
466
|
-
# Framework Integration
|
|
467
540
|
|
|
468
|
-
|
|
541
|
+
# Math Engine
|
|
469
542
|
|
|
470
|
-
```
|
|
471
|
-
import {
|
|
543
|
+
```ts
|
|
544
|
+
import {
|
|
545
|
+
math,
|
|
546
|
+
add,
|
|
547
|
+
fluidType,
|
|
548
|
+
convert
|
|
549
|
+
} from "chaincss";
|
|
550
|
+
|
|
551
|
+
add("10px", "2rem");
|
|
552
|
+
|
|
553
|
+
fluidType({
|
|
554
|
+
minSize: 14,
|
|
555
|
+
maxSize: 20
|
|
556
|
+
});
|
|
472
557
|
|
|
473
|
-
|
|
474
|
-
const styles = chain()
|
|
475
|
-
.bg("white")
|
|
476
|
-
.p(24)
|
|
477
|
-
.rounded(12)
|
|
478
|
-
.$el("card");
|
|
479
|
-
|
|
480
|
-
return (
|
|
481
|
-
<div className={styles.selectors[0]}>
|
|
482
|
-
Content
|
|
483
|
-
</div>
|
|
484
|
-
);
|
|
485
|
-
}
|
|
558
|
+
convert("32px", "rem");
|
|
486
559
|
```
|
|
487
560
|
|
|
488
|
-
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
# Design Tokens
|
|
489
564
|
|
|
490
565
|
```ts
|
|
491
|
-
import {
|
|
566
|
+
import {
|
|
567
|
+
createTokens,
|
|
568
|
+
createThemeContract,
|
|
569
|
+
createTheme
|
|
570
|
+
} from "chaincss";
|
|
492
571
|
|
|
493
|
-
const
|
|
494
|
-
|
|
572
|
+
const tokens = createTokens({
|
|
573
|
+
colors: {
|
|
574
|
+
primary: "#6366f1",
|
|
575
|
+
secondary: "#10b981"
|
|
576
|
+
}
|
|
577
|
+
});
|
|
495
578
|
```
|
|
496
579
|
|
|
497
|
-
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
# Recipe System
|
|
498
583
|
|
|
499
584
|
```ts
|
|
500
|
-
import {
|
|
585
|
+
import { recipe } from "chaincss";
|
|
501
586
|
|
|
502
|
-
const
|
|
503
|
-
|
|
587
|
+
const button = recipe({
|
|
588
|
+
base: {
|
|
589
|
+
selectors: ["btn"],
|
|
590
|
+
display: "inline-flex",
|
|
591
|
+
borderRadius: "8px"
|
|
592
|
+
}
|
|
593
|
+
});
|
|
504
594
|
```
|
|
505
595
|
|
|
506
|
-
### Vanilla JS
|
|
507
596
|
|
|
508
|
-
```html
|
|
509
|
-
<script type="module">
|
|
510
|
-
import { chain, injectChainStyles } from "https://cdn.jsdelivr.net/npm/chaincss/dist/browser.js";
|
|
511
|
-
const h1 = chain()
|
|
512
|
-
.fs(48)
|
|
513
|
-
.fw(800)
|
|
514
|
-
.textGradient(["#6366f1","#06b6d4"])
|
|
515
|
-
.$el("h1");
|
|
516
597
|
|
|
517
|
-
|
|
598
|
+
# Animations
|
|
599
|
+
|
|
600
|
+
```ts
|
|
601
|
+
chain()
|
|
602
|
+
.fadeIn()
|
|
603
|
+
.slideInUp()
|
|
604
|
+
.zoomIn()
|
|
605
|
+
.bounce()
|
|
606
|
+
.pulse()
|
|
607
|
+
.$el("animated");
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
# Self-Healing CSS
|
|
613
|
+
|
|
614
|
+
```ts
|
|
615
|
+
import { correct, heal } from "chaincss";
|
|
616
|
+
|
|
617
|
+
correct("display", "flexbox");
|
|
618
|
+
correct("position", "abs");
|
|
518
619
|
|
|
519
|
-
|
|
520
|
-
|
|
620
|
+
heal(
|
|
621
|
+
{
|
|
622
|
+
display: "flexbox",
|
|
623
|
+
position: "abs"
|
|
624
|
+
},
|
|
625
|
+
"smart"
|
|
626
|
+
);
|
|
521
627
|
```
|
|
522
628
|
|
|
523
629
|
|
|
524
|
-
## Complete Feature List
|
|
525
630
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
| Plugins | 2 | Vite, Webpack |
|
|
538
|
-
| Bundles | 5 | Main, Runtime, Browser, Compiler, CLI |
|
|
539
|
-
| React Hooks | 6 | useSmartStyles, createSmartComponent, useChainStyles, useDynamicChainStyles, useThemeChainStyles, withSmartStyles |
|
|
540
|
-
| Design Systems | 3 | Tokens, Theme Contracts, Recipes |
|
|
541
|
-
| Dev Tools | 3 | Suggestions Engine, Timeline, Component Generator |
|
|
542
|
-
| Tests | 258 | 18 test files, 0 failures |
|
|
631
|
+
# CLI
|
|
632
|
+
|
|
633
|
+
```bash
|
|
634
|
+
chaincss init
|
|
635
|
+
chaincss build
|
|
636
|
+
chaincss watch
|
|
637
|
+
chaincss cache clear
|
|
638
|
+
chaincss optimize --report
|
|
639
|
+
chaincss doctor
|
|
640
|
+
```
|
|
641
|
+
|
|
543
642
|
|
|
544
643
|
|
|
545
644
|
# Performance
|
|
@@ -547,8 +646,9 @@ const styles = chain().flex().center().$el("centered");
|
|
|
547
646
|
- Zero runtime for static styles
|
|
548
647
|
- Atomic CSS extraction
|
|
549
648
|
- Smart static/dynamic splitting
|
|
550
|
-
-
|
|
551
|
-
-
|
|
649
|
+
- Cross-file dead code elimination
|
|
650
|
+
- Multi-pass optimization pipeline
|
|
651
|
+
|
|
552
652
|
|
|
553
653
|
|
|
554
654
|
# Contributing
|
|
@@ -564,11 +664,15 @@ npm test
|
|
|
564
664
|
```
|
|
565
665
|
|
|
566
666
|
|
|
667
|
+
|
|
567
668
|
# License
|
|
568
669
|
|
|
569
670
|
MIT © Rommel Caneos
|
|
570
671
|
|
|
571
672
|
<p align="center">
|
|
572
|
-
<strong>ChainCSS</strong> —
|
|
573
|
-
|
|
673
|
+
<strong>ChainCSS v2.3</strong> — The CSS intelligence platform.<br>
|
|
674
|
+
|
|
675
|
+
<a href="https://github.com/melcanz08/chaincss">
|
|
676
|
+
github.com/melcanz08/chaincss
|
|
677
|
+
</a>
|
|
574
678
|
</p>
|