chaincss 2.1.9 → 2.1.11
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 +132 -382
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +31 -0
- package/package.json +1 -1
- package/src/runtime/index.ts +32 -1
package/README.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
+
# ChainCSS
|
|
2
|
+
|
|
1
3
|
<p align="center">
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
<strong>The first CSS-in-JS library with true auto-detection mixed mode.</strong><br>
|
|
5
|
-
Zero runtime by default. Dynamic when you need it. No compromises.
|
|
6
|
-
</p>
|
|
4
|
+
<strong>The first CSS-in-JS library with true auto-detection mixed mode.</strong><br>
|
|
5
|
+
Zero runtime by default. Dynamic when you need it. No compromises.
|
|
7
6
|
</p>
|
|
8
7
|
|
|
9
8
|
<p align="center">
|
|
@@ -16,48 +15,48 @@
|
|
|
16
15
|
|
|
17
16
|
## What is ChainCSS?
|
|
18
17
|
|
|
19
|
-
ChainCSS lets you write styles as **native JavaScript method chains** instead of CSS strings or object literals.
|
|
18
|
+
ChainCSS lets you write styles as **native JavaScript method chains** instead of CSS strings or object literals.
|
|
19
|
+
|
|
20
|
+
It automatically detects which styles are static (compiled to CSS) and which are dynamic (kept in JS), then splits them for optimal performance.
|
|
20
21
|
|
|
22
|
+
```ts
|
|
21
23
|
import { chain } from "chaincss";
|
|
22
24
|
|
|
23
25
|
const card = chain()
|
|
24
|
-
.display("flex")
|
|
25
|
-
.flexDirection("column")
|
|
26
|
-
.gap(16)
|
|
27
|
-
.padding(24)
|
|
28
|
-
.background("white")
|
|
29
|
-
.borderRadius(12)
|
|
30
|
-
.hover()
|
|
31
|
-
.boxShadow("0 4px 12px rgba(0,0,0,0.15)")
|
|
32
|
-
.transform("translateY(-2px)")
|
|
33
|
-
.end()
|
|
34
|
-
.$el("card");
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
.display("flex")
|
|
27
|
+
.flexDirection("column")
|
|
28
|
+
.gap(16)
|
|
29
|
+
.padding(24)
|
|
30
|
+
.background("white")
|
|
31
|
+
.borderRadius(12)
|
|
32
|
+
.hover()
|
|
33
|
+
.boxShadow("0 4px 12px rgba(0,0,0,0.15)")
|
|
34
|
+
.transform("translateY(-2px)")
|
|
35
|
+
.end()
|
|
36
|
+
.$el("card");
|
|
37
|
+
```
|
|
37
38
|
|
|
38
39
|
**No CSS syntax. No template literals. No object literals. Just JavaScript.**
|
|
39
40
|
|
|
40
41
|
---
|
|
41
42
|
|
|
42
|
-
##
|
|
43
|
-
|
|
44
|
-
ChainCSS automatically detects which styles are static and which are dynamic.
|
|
43
|
+
## Auto-Detection Mixed Mode
|
|
45
44
|
|
|
45
|
+
```ts
|
|
46
46
|
import { smartChain } from "chaincss";
|
|
47
47
|
|
|
48
48
|
const styles = smartChain()
|
|
49
|
-
.display("flex")
|
|
50
|
-
.padding(20)
|
|
51
|
-
.color(props.textColor)
|
|
52
|
-
.fontSize(theme.sizes.lg)
|
|
53
|
-
.$el("dynamic-card");
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
.display("flex")
|
|
50
|
+
.padding(20)
|
|
51
|
+
.color(props.textColor)
|
|
52
|
+
.fontSize(theme.sizes.lg)
|
|
53
|
+
.$el("dynamic-card");
|
|
54
|
+
```
|
|
56
55
|
|
|
57
56
|
| Library | Approach | Dynamic Support | Runtime Cost |
|
|
58
|
-
|
|
57
|
+
|--------|---------|----------------|-------------|
|
|
59
58
|
| Tailwind | Utility classes | No | Zero |
|
|
60
|
-
| Styled Components | Runtime CSS-in-JS | Yes |
|
|
59
|
+
| Styled Components | Runtime CSS-in-JS | Yes | High |
|
|
61
60
|
| Panda CSS | Build-time + recipes | Limited | Near-zero |
|
|
62
61
|
| Vanilla Extract | Build-time only | No | Zero |
|
|
63
62
|
| **ChainCSS** | **Auto-detection + split** | **Yes** | **Minimal** |
|
|
@@ -66,424 +65,175 @@ text
|
|
|
66
65
|
|
|
67
66
|
## Installation
|
|
68
67
|
|
|
68
|
+
```bash
|
|
69
69
|
npm install chaincss
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
```
|
|
72
71
|
|
|
73
|
-
###
|
|
72
|
+
### Vite Setup
|
|
74
73
|
|
|
75
|
-
|
|
74
|
+
```ts
|
|
76
75
|
import { defineConfig } from "vite";
|
|
77
76
|
import chaincss from "chaincss/plugin/vite";
|
|
78
77
|
|
|
79
78
|
export default defineConfig({
|
|
80
|
-
plugins: [chaincss()],
|
|
79
|
+
plugins: [chaincss()],
|
|
81
80
|
});
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
```
|
|
84
82
|
|
|
85
83
|
---
|
|
86
84
|
|
|
87
85
|
## Core API
|
|
88
86
|
|
|
89
|
-
###
|
|
87
|
+
### Basic Chain
|
|
90
88
|
|
|
89
|
+
```ts
|
|
91
90
|
import { chain } from "chaincss";
|
|
92
91
|
|
|
93
92
|
const styles = chain()
|
|
94
|
-
.display("flex")
|
|
95
|
-
.padding(20)
|
|
96
|
-
.color("red")
|
|
97
|
-
.$el("my-component");
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
### Shorthands (80+)
|
|
102
|
-
|
|
103
|
-
chain()
|
|
104
|
-
.bg("#fff") // backgroundColor
|
|
105
|
-
.m(16) // margin
|
|
106
|
-
.p(20) // padding
|
|
107
|
-
.br(8) // borderRadius
|
|
108
|
-
.fs(16) // fontSize
|
|
109
|
-
.fw(700) // fontWeight
|
|
110
|
-
.c("#333") // color
|
|
111
|
-
.w(200) // width
|
|
112
|
-
.h(100) // height
|
|
113
|
-
.d("flex") // display
|
|
114
|
-
text
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
### Macros (57 built-in)
|
|
118
|
-
|
|
119
|
-
**Layout:**
|
|
120
|
-
|
|
121
|
-
chain().flex() // display: flex
|
|
122
|
-
chain().grid() // display: grid
|
|
123
|
-
chain().center() // flex + align-items + justify-content center
|
|
124
|
-
chain().flexCenter() // flex centering
|
|
125
|
-
chain().gridCenter() // grid centering
|
|
126
|
-
chain().stack(16) // flex column with gap
|
|
127
|
-
chain().cols(3) // grid-template-columns: repeat(3, 1fr)
|
|
128
|
-
chain().bento(4) // bento grid layout
|
|
129
|
-
text
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
**Spacing:**
|
|
133
|
-
|
|
134
|
-
chain().mx(10) // margin-left + margin-right
|
|
135
|
-
chain().my(20) // margin-top + margin-bottom
|
|
136
|
-
chain().px(16) // padding-left + padding-right
|
|
137
|
-
chain().py(24) // padding-top + padding-bottom
|
|
138
|
-
chain().size(50) // width + height
|
|
139
|
-
chain().gap(16) // gap
|
|
140
|
-
text
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
**Positioning:**
|
|
144
|
-
|
|
145
|
-
chain().absolute({ top: 0, left: 0 })
|
|
146
|
-
chain().fixed({ top: 0, right: 0 })
|
|
147
|
-
chain().sticky({ top: 0 })
|
|
148
|
-
chain().relative()
|
|
149
|
-
text
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
**Visibility:**
|
|
153
|
-
|
|
154
|
-
chain().hide() // visibility: hidden + opacity: 0
|
|
155
|
-
chain().show() // visibility: visible + opacity: 1
|
|
156
|
-
chain().unselectable() // user-select: none
|
|
157
|
-
chain().scrollable("y") // overflow-y: auto
|
|
158
|
-
text
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
**Shapes:**
|
|
162
|
-
|
|
163
|
-
chain().circle(50) // width + height + border-radius: 50%
|
|
164
|
-
chain().square(40) // width + height
|
|
165
|
-
chain().pill() // border-radius: 9999px
|
|
166
|
-
chain().truncate() // text-overflow: ellipsis
|
|
167
|
-
chain().aspect("16/9") // aspect-ratio
|
|
168
|
-
text
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
**Aesthetic Effects:**
|
|
172
|
-
|
|
173
|
-
chain().glass() // backdrop-filter blur + semi-transparent bg
|
|
174
|
-
chain().glow("#ff0000") // box-shadow glow
|
|
175
|
-
chain().textGradient(["#667eea", "#764ba2"]) // gradient text
|
|
176
|
-
chain().meshGradient(["#f0f", "#0ff", "#ff0", "#0f0"]) // mesh gradient
|
|
177
|
-
chain().noise(0.05) // noise texture overlay
|
|
178
|
-
chain().shimmer() // loading shimmer effect
|
|
179
|
-
text
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
**State & Interactions:**
|
|
183
|
-
|
|
184
|
-
chain()
|
|
185
|
-
.hover()
|
|
186
|
-
.background("#2563eb")
|
|
187
|
-
.transform("scale(1.05)")
|
|
188
|
-
.end()
|
|
189
|
-
|
|
190
|
-
chain().clickScale(0.95) // scale on click
|
|
191
|
-
chain().pressable() // cursor pointer + hover effects
|
|
192
|
-
chain().focusRing("#3b82f6") // focus-visible ring
|
|
193
|
-
chain().skeleton(true) // loading skeleton animation
|
|
194
|
-
chain().dark(c => c.bg("#1a202c").c("white")) // dark mode
|
|
195
|
-
chain().light(c => c.bg("white").c("#1a202c")) // light mode
|
|
196
|
-
chain().children(c => c.gap(8)) // direct children styles
|
|
197
|
-
text
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
**Utility:**
|
|
201
|
-
|
|
202
|
-
chain().fullScreen() // fixed fullscreen overlay
|
|
203
|
-
chain().containerMacro(1200) // centered container
|
|
204
|
-
chain().outlineDebug() // debug outlines
|
|
205
|
-
chain().parallax(2) // parallax scrolling
|
|
206
|
-
chain().lineClamp(3) // text line clamp
|
|
207
|
-
chain().frostedNav(15) // frosted glass navigation
|
|
208
|
-
text
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
### Conditional Styles
|
|
212
|
-
|
|
213
|
-
chain()
|
|
214
|
-
.padding(12)
|
|
215
|
-
.when(isActive, c => c
|
|
216
|
-
.background("#10b981")
|
|
217
|
-
.color("white")
|
|
218
|
-
)
|
|
219
|
-
.when(isDisabled, c => c
|
|
220
|
-
.opacity(0.5)
|
|
221
|
-
.cursor("not-allowed")
|
|
222
|
-
)
|
|
223
|
-
.$el("stateful-btn");
|
|
224
|
-
text
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
### Nested Selectors
|
|
228
|
-
|
|
229
|
-
chain()
|
|
230
|
-
.display("flex")
|
|
231
|
-
.nest("& > *", c => c.flex(1))
|
|
232
|
-
.nest("&:first-child", c => c.fontWeight(700))
|
|
233
|
-
.nest(".child", c => c.color("red"))
|
|
234
|
-
.$el("flex-container");
|
|
235
|
-
text
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
### Mixins with use()
|
|
239
|
-
|
|
240
|
-
const sharedStyles = { display: "flex", alignItems: "center", gap: 8 };
|
|
241
|
-
chain().use(sharedStyles).padding(20).$el("reused");
|
|
242
|
-
text
|
|
93
|
+
.display("flex")
|
|
94
|
+
.padding(20)
|
|
95
|
+
.color("red")
|
|
96
|
+
.$el("my-component");
|
|
97
|
+
```
|
|
243
98
|
|
|
99
|
+
---
|
|
244
100
|
|
|
245
|
-
|
|
101
|
+
## Shorthands
|
|
246
102
|
|
|
103
|
+
```ts
|
|
247
104
|
chain()
|
|
248
|
-
.
|
|
249
|
-
.
|
|
250
|
-
.
|
|
251
|
-
.
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
105
|
+
.bg("#fff")
|
|
106
|
+
.m(16)
|
|
107
|
+
.p(20)
|
|
108
|
+
.br(8)
|
|
109
|
+
.fs(16)
|
|
110
|
+
.fw(700)
|
|
111
|
+
.c("#333")
|
|
112
|
+
.w(200)
|
|
113
|
+
.h(100)
|
|
114
|
+
.d("flex");
|
|
115
|
+
```
|
|
255
116
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
### Transform Methods
|
|
117
|
+
---
|
|
259
118
|
|
|
260
|
-
|
|
261
|
-
text
|
|
119
|
+
## Macros
|
|
262
120
|
|
|
121
|
+
### Layout
|
|
263
122
|
|
|
264
|
-
|
|
123
|
+
```ts
|
|
124
|
+
chain().flex();
|
|
125
|
+
chain().grid();
|
|
126
|
+
chain().center();
|
|
127
|
+
chain().flexCenter();
|
|
128
|
+
chain().gridCenter();
|
|
129
|
+
chain().stack(16);
|
|
130
|
+
chain().cols(3);
|
|
131
|
+
```
|
|
265
132
|
|
|
266
|
-
|
|
267
|
-
.width(chain().calc("100% - 20px"))
|
|
268
|
-
.fontSize(chain().clamp(16, 4, 24))
|
|
269
|
-
.margin(chain().add(10, 20))
|
|
270
|
-
.$el("calculated");
|
|
271
|
-
text
|
|
133
|
+
### Spacing
|
|
272
134
|
|
|
135
|
+
```ts
|
|
136
|
+
chain().mx(10);
|
|
137
|
+
chain().my(20);
|
|
138
|
+
chain().px(16);
|
|
139
|
+
chain().py(24);
|
|
140
|
+
chain().size(50);
|
|
141
|
+
chain().gap(16);
|
|
142
|
+
```
|
|
273
143
|
|
|
274
144
|
---
|
|
275
145
|
|
|
276
|
-
##
|
|
277
|
-
|
|
278
|
-
import { recipe } from "chaincss";
|
|
279
|
-
|
|
280
|
-
const button = recipe({
|
|
281
|
-
base: {
|
|
282
|
-
selectors: ["btn"],
|
|
283
|
-
display: "inline-flex",
|
|
284
|
-
borderRadius: "8px",
|
|
285
|
-
fontWeight: 600,
|
|
286
|
-
},
|
|
287
|
-
variants: {
|
|
288
|
-
size: {
|
|
289
|
-
sm: { padding: "8px 16px", fontSize: "14px" },
|
|
290
|
-
md: { padding: "12px 24px", fontSize: "16px" },
|
|
291
|
-
lg: { padding: "16px 32px", fontSize: "18px" },
|
|
292
|
-
},
|
|
293
|
-
color: {
|
|
294
|
-
primary: { background: "#3b82f6", color: "white" },
|
|
295
|
-
danger: { background: "#ef4444", color: "white" },
|
|
296
|
-
},
|
|
297
|
-
},
|
|
298
|
-
defaultVariants: { size: "md", color: "primary" },
|
|
299
|
-
compoundVariants: [
|
|
300
|
-
{
|
|
301
|
-
variants: { size: "lg", color: "primary" },
|
|
302
|
-
style: { fontWeight: 800 },
|
|
303
|
-
},
|
|
304
|
-
],
|
|
305
|
-
});
|
|
146
|
+
## States & Interactions
|
|
306
147
|
|
|
307
|
-
|
|
308
|
-
text
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
---
|
|
312
|
-
|
|
313
|
-
## Animations (42 built-in presets)
|
|
314
|
-
|
|
315
|
-
chain()
|
|
316
|
-
.fadeIn()
|
|
317
|
-
.slideInUp()
|
|
318
|
-
.zoomIn()
|
|
319
|
-
.bounce()
|
|
320
|
-
.pulse()
|
|
321
|
-
.spin()
|
|
322
|
-
.shake()
|
|
323
|
-
.wiggle()
|
|
324
|
-
.float()
|
|
325
|
-
.flash()
|
|
326
|
-
.textReveal()
|
|
327
|
-
.$el("animated");
|
|
328
|
-
|
|
329
|
-
// Custom animation
|
|
148
|
+
```ts
|
|
330
149
|
chain()
|
|
331
|
-
.
|
|
332
|
-
"
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
text
|
|
337
|
-
|
|
150
|
+
.hover()
|
|
151
|
+
.background("#2563eb")
|
|
152
|
+
.transform("scale(1.05)")
|
|
153
|
+
.end();
|
|
154
|
+
```
|
|
338
155
|
|
|
339
156
|
---
|
|
340
157
|
|
|
341
|
-
##
|
|
342
|
-
|
|
343
|
-
import { createTokens } from "chaincss";
|
|
344
|
-
|
|
345
|
-
const tokens = createTokens({
|
|
346
|
-
colors: { primary: "#3b82f6", secondary: "#10b981", danger: "#ef4444" },
|
|
347
|
-
spacing: { sm: "8px", md: "16px", lg: "24px" },
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
chain(true)
|
|
351
|
-
.color("colors.primary").padding("colors.primary").padding("spacing.md")
|
|
352
|
-
.$el("themed");
|
|
353
|
-
text
|
|
158
|
+
## Conditional Styles
|
|
354
159
|
|
|
160
|
+
```ts
|
|
161
|
+
chain()
|
|
162
|
+
.padding(12)
|
|
163
|
+
.when(isActive, c => c.background("#10b981").color("white"))
|
|
164
|
+
.when(isDisabled, c => c.opacity(0.5).cursor("not-allowed"))
|
|
165
|
+
.$el("stateful-btn");
|
|
166
|
+
```
|
|
355
167
|
|
|
356
168
|
---
|
|
357
169
|
|
|
358
|
-
##
|
|
359
|
-
|
|
360
|
-
import { createThemeContract, createTheme, validateTheme } from "chaincss";
|
|
361
|
-
|
|
362
|
-
const contract = createThemeContract({
|
|
363
|
-
colors: { primary: "", background: "", text: "" },
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
const lightTheme = createTheme(contract, {
|
|
367
|
-
colors: { primary: "#3b82f6", background: "#ffffff", text: "#1a202c" },
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
const darkTheme = createTheme(contract, {
|
|
371
|
-
colors: { primary: "#60a5fa", background: "#1a202c", text: "#f7fafc" },
|
|
372
|
-
});
|
|
373
|
-
text
|
|
170
|
+
## Nested Selectors
|
|
374
171
|
|
|
172
|
+
```ts
|
|
173
|
+
chain()
|
|
174
|
+
.display("flex")
|
|
175
|
+
.nest("& > *", c => c.flex(1))
|
|
176
|
+
.nest(".child", c => c.color("red"))
|
|
177
|
+
.$el("flex-container");
|
|
178
|
+
```
|
|
375
179
|
|
|
376
180
|
---
|
|
377
181
|
|
|
378
|
-
##
|
|
379
|
-
|
|
380
|
-
### React
|
|
381
|
-
|
|
382
|
-
import { chain } from "chaincss";
|
|
383
|
-
|
|
384
|
-
function Card() {
|
|
385
|
-
const styles = chain().bg("white").p(24).rounded(12).$el("card");
|
|
386
|
-
return <div className={styles.selectors[0]}>Content</div>;
|
|
387
|
-
}
|
|
388
|
-
text
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
### Vue
|
|
392
|
-
|
|
393
|
-
import { chain } from "chaincss";
|
|
394
|
-
const styles = chain().display("grid").cols(3).gap(16).$el("vue-grid");
|
|
395
|
-
// <div :class="styles.selectors[0]">
|
|
396
|
-
text
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
### Svelte
|
|
400
|
-
|
|
401
|
-
import { chain } from "chaincss";
|
|
402
|
-
const styles = chain().flex().center().$el("centered");
|
|
403
|
-
// <div class={styles.selectors[0]}>Content</div>
|
|
404
|
-
text
|
|
182
|
+
## Responsive
|
|
405
183
|
|
|
184
|
+
```ts
|
|
185
|
+
chain()
|
|
186
|
+
.display("flex")
|
|
187
|
+
.flexDirection("column")
|
|
188
|
+
.responsive("md", c => c.flexDirection("row"))
|
|
189
|
+
.$el("responsive");
|
|
190
|
+
```
|
|
406
191
|
|
|
407
192
|
---
|
|
408
193
|
|
|
409
|
-
##
|
|
410
|
-
|
|
411
|
-
import { smartChain, buildChain, runtimeChain } from "chaincss";
|
|
412
|
-
|
|
413
|
-
// Auto-detect
|
|
414
|
-
const styles = smartChain()
|
|
415
|
-
.display("flex") // static -> build
|
|
416
|
-
.color(dynamicVariable) // dynamic -> runtime
|
|
417
|
-
.$el("hybrid");
|
|
418
|
-
|
|
419
|
-
// Force build-time only
|
|
420
|
-
const static = buildChain().display("flex").$el("static");
|
|
421
|
-
|
|
422
|
-
// Force runtime only
|
|
423
|
-
const dynamic = runtimeChain().color(props.color).$el("runtime");
|
|
424
|
-
text
|
|
194
|
+
## Animations
|
|
425
195
|
|
|
196
|
+
```ts
|
|
197
|
+
chain()
|
|
198
|
+
.fadeIn()
|
|
199
|
+
.slideInUp()
|
|
200
|
+
.zoomIn()
|
|
201
|
+
.$el("animated");
|
|
202
|
+
```
|
|
426
203
|
|
|
427
204
|
---
|
|
428
205
|
|
|
429
206
|
## CLI
|
|
430
207
|
|
|
431
|
-
|
|
432
|
-
chaincss
|
|
433
|
-
chaincss
|
|
434
|
-
chaincss
|
|
435
|
-
chaincss cache
|
|
436
|
-
chaincss
|
|
437
|
-
|
|
438
|
-
|
|
208
|
+
```bash
|
|
209
|
+
chaincss init
|
|
210
|
+
chaincss build
|
|
211
|
+
chaincss watch
|
|
212
|
+
chaincss cache clear
|
|
213
|
+
chaincss cache stats
|
|
214
|
+
```
|
|
439
215
|
|
|
440
216
|
---
|
|
441
217
|
|
|
442
218
|
## Configuration
|
|
443
219
|
|
|
444
|
-
|
|
220
|
+
```ts
|
|
445
221
|
export default {
|
|
446
|
-
inputs: ["src
|
|
447
|
-
output: { cssFile: "global.css", minify: true },
|
|
448
|
-
atomic: { enabled: true, mode: "hybrid", threshold: 2, naming: "hash" },
|
|
449
|
-
breakpoints: { sm: "(min-width: 640px)", md: "(min-width: 768px)", lg: "(min-width: 1024px)" },
|
|
450
|
-
tokens: { enabled: true, prefix: "$" },
|
|
222
|
+
inputs: ["src/**/*.chain.{js,ts}", "src/**/*.tsx"],
|
|
223
|
+
output: { cssFile: "global.css", minify: true },
|
|
451
224
|
};
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
---
|
|
456
|
-
|
|
457
|
-
## Complete Feature List
|
|
458
|
-
|
|
459
|
-
| Category | Count |
|
|
460
|
-
|----------|-------|
|
|
461
|
-
| Macros | 57 |
|
|
462
|
-
| Shorthand Properties | 80 |
|
|
463
|
-
| Animation Presets | 42 |
|
|
464
|
-
| Breakpoints | 20 |
|
|
465
|
-
| Chain API Methods | 30+ |
|
|
466
|
-
| Math Helpers | 15 |
|
|
467
|
-
| CSS Properties | 300+ |
|
|
468
|
-
| CLI Commands | 5 |
|
|
469
|
-
| Framework Integrations | 4 (React, Vue, Svelte, Solid) |
|
|
470
|
-
| Plugins | 2 (Vite, Webpack) |
|
|
471
|
-
| React Hooks | 6 |
|
|
472
|
-
| Recipe System | Variants, defaultVariants, compoundVariants |
|
|
473
|
-
| Theme System | Theme, createThemeContract, validateTheme |
|
|
474
|
-
|
|
475
|
-
**Total: 550+ features | 210 tests | Zero-runtime by default**
|
|
225
|
+
```
|
|
476
226
|
|
|
477
227
|
---
|
|
478
228
|
|
|
479
229
|
## Contributing
|
|
480
230
|
|
|
231
|
+
```bash
|
|
481
232
|
git clone https://github.com/melcanz08/chaincss.git
|
|
482
233
|
cd chaincss
|
|
483
234
|
npm install
|
|
484
235
|
npm test
|
|
485
|
-
|
|
486
|
-
|
|
236
|
+
```
|
|
487
237
|
|
|
488
238
|
---
|
|
489
239
|
|
|
@@ -492,6 +242,6 @@ text
|
|
|
492
242
|
MIT © Rommel Caneos
|
|
493
243
|
|
|
494
244
|
<p align="center">
|
|
495
|
-
<strong>ChainCSS</strong> — Write styles like JavaScript. Ship zero runtime
|
|
496
|
-
<a href="https://chaincss.dev">chaincss.dev</a>
|
|
245
|
+
<strong>ChainCSS</strong> — Write styles like JavaScript. Ship zero runtime.
|
|
497
246
|
</p>
|
|
247
|
+
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -22,3 +22,4 @@ export declare const chainStyles: (...args: any[]) => any;
|
|
|
22
22
|
export { setupHMR, registerForHMR } from './hmr.js';
|
|
23
23
|
export { generateStyleId, hashString, kebabCase, isBrowser, isDevelopment, isProduction, debounce, memoize, cn as cnUtils, devWarn, devLog, logError, createDebugger } from './utils.js';
|
|
24
24
|
export type { RuntimeStyleDefinition, UseChainStylesOptions, RuntimeCompiledResult, StyleInjector, UseAtomicClassesReturn, HMRPayload, ChainCSSDebugger } from './types.js';
|
|
25
|
+
export declare function injectChainStyles(styles: Record<string, any>): HTMLStyleElement;
|
package/dist/runtime/index.js
CHANGED
|
@@ -3907,6 +3907,36 @@ var useComputedStylesSvelte = (...args) => getSvelteExports().useComputedStyles?
|
|
|
3907
3907
|
var provideStyleContextSvelte = (...args) => getSvelteExports().provideStyleContext?.(...args);
|
|
3908
3908
|
var injectStyleContextSvelte = (...args) => getSvelteExports().injectStyleContext?.(...args);
|
|
3909
3909
|
var chainStyles2 = (...args) => getSvelteExports().chainStyles?.(...args);
|
|
3910
|
+
function injectChainStyles(styles3) {
|
|
3911
|
+
let css = "";
|
|
3912
|
+
for (const [key, obj] of Object.entries(styles3)) {
|
|
3913
|
+
if (!obj || !obj.selectors) continue;
|
|
3914
|
+
const sel = "." + obj.selectors[0];
|
|
3915
|
+
css += sel + "{";
|
|
3916
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
3917
|
+
if (["selectors", "hover", "atRules", "nestedRules", "_name", "_classes"].includes(k)) continue;
|
|
3918
|
+
css += k.replace(/([A-Z])/g, "-$1").toLowerCase() + ":" + v + ";";
|
|
3919
|
+
}
|
|
3920
|
+
css += "}";
|
|
3921
|
+
if (obj.hover) {
|
|
3922
|
+
css += sel + ":hover{";
|
|
3923
|
+
for (const [k, v] of Object.entries(obj.hover)) css += k.replace(/([A-Z])/g, "-$1").toLowerCase() + ":" + v + ";";
|
|
3924
|
+
css += "}";
|
|
3925
|
+
}
|
|
3926
|
+
if (obj.nestedRules) {
|
|
3927
|
+
for (const rule of obj.nestedRules) {
|
|
3928
|
+
css += rule.selector.replace("&", sel) + "{";
|
|
3929
|
+
for (const [k, v] of Object.entries(rule.styles || {})) css += k.replace(/([A-Z])/g, "-$1").toLowerCase() + ":" + v + ";";
|
|
3930
|
+
css += "}";
|
|
3931
|
+
}
|
|
3932
|
+
}
|
|
3933
|
+
}
|
|
3934
|
+
const el = document.createElement("style");
|
|
3935
|
+
el.setAttribute("data-chaincss", "runtime");
|
|
3936
|
+
el.textContent = css;
|
|
3937
|
+
document.head.appendChild(el);
|
|
3938
|
+
return el;
|
|
3939
|
+
}
|
|
3910
3940
|
export {
|
|
3911
3941
|
$,
|
|
3912
3942
|
$t,
|
|
@@ -3932,6 +3962,7 @@ export {
|
|
|
3932
3962
|
enableChainCSSDebug,
|
|
3933
3963
|
generateStyleId,
|
|
3934
3964
|
hashString,
|
|
3965
|
+
injectChainStyles,
|
|
3935
3966
|
injectStyleContext,
|
|
3936
3967
|
injectStyleContextSvelte,
|
|
3937
3968
|
isBrowser,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chaincss",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.11",
|
|
4
4
|
"description": "ChainCSS v3.0 - The first CSS-in-JS library with true auto-detection mixed mode. Zero runtime by default, dynamic when you need it.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
package/src/runtime/index.ts
CHANGED
|
@@ -88,4 +88,35 @@ export type {
|
|
|
88
88
|
UseAtomicClassesReturn,
|
|
89
89
|
HMRPayload,
|
|
90
90
|
ChainCSSDebugger
|
|
91
|
-
} from './types.js';
|
|
91
|
+
} from './types.js';
|
|
92
|
+
// Auto-inject styles into DOM
|
|
93
|
+
export function injectChainStyles(styles: Record<string, any>) {
|
|
94
|
+
let css = '';
|
|
95
|
+
for (const [key, obj] of Object.entries(styles)) {
|
|
96
|
+
if (!obj || !obj.selectors) continue;
|
|
97
|
+
const sel = '.' + obj.selectors[0];
|
|
98
|
+
css += sel + '{';
|
|
99
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
100
|
+
if (['selectors','hover','atRules','nestedRules','_name','_classes'].includes(k)) continue;
|
|
101
|
+
css += k.replace(/([A-Z])/g,'-$1').toLowerCase() + ':' + v + ';';
|
|
102
|
+
}
|
|
103
|
+
css += '}';
|
|
104
|
+
if (obj.hover) {
|
|
105
|
+
css += sel + ':hover{';
|
|
106
|
+
for (const [k, v] of Object.entries(obj.hover)) css += k.replace(/([A-Z])/g,'-$1').toLowerCase() + ':' + v + ';';
|
|
107
|
+
css += '}';
|
|
108
|
+
}
|
|
109
|
+
if (obj.nestedRules) {
|
|
110
|
+
for (const rule of obj.nestedRules) {
|
|
111
|
+
css += rule.selector.replace('&', sel) + '{';
|
|
112
|
+
for (const [k, v] of Object.entries(rule.styles || {})) css += k.replace(/([A-Z])/g,'-$1').toLowerCase() + ':' + v + ';';
|
|
113
|
+
css += '}';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const el = document.createElement('style');
|
|
118
|
+
el.setAttribute('data-chaincss', 'runtime');
|
|
119
|
+
el.textContent = css;
|
|
120
|
+
document.head.appendChild(el);
|
|
121
|
+
return el;
|
|
122
|
+
}
|