@tenphi/tasty 0.6.0 → 0.7.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 +76 -15
- package/dist/config.d.ts +8 -0
- package/dist/config.js.map +1 -1
- package/dist/hooks/useStyles.js +5 -5
- package/dist/hooks/useStyles.js.map +1 -1
- package/dist/injector/injector.js +38 -25
- package/dist/injector/injector.js.map +1 -1
- package/dist/injector/sheet-manager.d.ts +12 -4
- package/dist/injector/sheet-manager.js +23 -9
- package/dist/injector/sheet-manager.js.map +1 -1
- package/dist/injector/types.d.ts +9 -0
- package/dist/properties/index.js +77 -17
- package/dist/properties/index.js.map +1 -1
- package/dist/properties/property-type-resolver.d.ts +24 -0
- package/dist/properties/property-type-resolver.js +83 -0
- package/dist/properties/property-type-resolver.js.map +1 -0
- package/dist/styles/fill.js +6 -5
- package/dist/styles/fill.js.map +1 -1
- package/dist/utils/styles.js +161 -0
- package/dist/utils/styles.js.map +1 -1
- package/dist/zero/babel.d.ts +5 -0
- package/dist/zero/babel.js +13 -7
- package/dist/zero/babel.js.map +1 -1
- package/dist/zero/extractor.js +66 -1
- package/dist/zero/extractor.js.map +1 -1
- package/docs/configuration.md +211 -0
- package/docs/debug.md +505 -0
- package/docs/injector.md +528 -0
- package/docs/styles.md +567 -0
- package/docs/tasty-static.md +376 -0
- package/docs/usage.md +643 -0
- package/package.json +5 -4
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# Zero Runtime Mode (tastyStatic)
|
|
2
|
+
|
|
3
|
+
`tastyStatic` is a build-time utility for generating CSS with zero runtime overhead. It's designed for static sites, no-JS websites, and performance-critical applications where you want to eliminate all runtime styling code.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## When to Use
|
|
8
|
+
|
|
9
|
+
- **Static site generation (SSG)** — Pre-render all styles at build time
|
|
10
|
+
- **No-JavaScript websites** — CSS works without any JS runtime
|
|
11
|
+
- **Performance-critical pages** — Zero runtime overhead for styling
|
|
12
|
+
- **Landing pages** — Minimal bundle size with pre-generated CSS
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
The zero-runtime mode is part of the main `@tenphi/tasty` package. No additional packages required.
|
|
17
|
+
|
|
18
|
+
### Basic Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { tastyStatic } from '@tenphi/tasty/static';
|
|
22
|
+
|
|
23
|
+
// Define styles - returns StaticStyle object
|
|
24
|
+
const button = tastyStatic({
|
|
25
|
+
display: 'inline-flex',
|
|
26
|
+
padding: '2x 4x',
|
|
27
|
+
fill: '#purple',
|
|
28
|
+
color: '#white',
|
|
29
|
+
radius: '1r',
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Use in JSX - works via toString() coercion
|
|
33
|
+
<button className={button}>Click me</button>
|
|
34
|
+
|
|
35
|
+
// Or access className explicitly
|
|
36
|
+
<button className={button.className}>Click me</button>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## API Reference
|
|
42
|
+
|
|
43
|
+
### tastyStatic(styles)
|
|
44
|
+
|
|
45
|
+
Creates a `StaticStyle` object from a styles definition.
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
const card = tastyStatic({
|
|
49
|
+
padding: '4x',
|
|
50
|
+
fill: '#white',
|
|
51
|
+
border: true,
|
|
52
|
+
radius: true,
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### tastyStatic(base, styles)
|
|
57
|
+
|
|
58
|
+
Extends an existing `StaticStyle` with additional styles. Uses `mergeStyles` internally for proper nested selector handling.
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
const button = tastyStatic({
|
|
62
|
+
padding: '2x 4x',
|
|
63
|
+
fill: '#blue',
|
|
64
|
+
Icon: { color: '#white' },
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const primaryButton = tastyStatic(button, {
|
|
68
|
+
fill: '#purple',
|
|
69
|
+
Icon: { opacity: 0.8 },
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### tastyStatic(selector, styles)
|
|
74
|
+
|
|
75
|
+
Generates global styles for a CSS selector. The call is removed from the bundle after transformation.
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
tastyStatic('body', {
|
|
79
|
+
fill: '#surface',
|
|
80
|
+
color: '#text',
|
|
81
|
+
preset: 't3',
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## StaticStyle Object
|
|
88
|
+
|
|
89
|
+
| Property | Type | Description |
|
|
90
|
+
|----------|------|-------------|
|
|
91
|
+
| `className` | `string` | Space-separated class names for use in JSX |
|
|
92
|
+
| `styles` | `Styles` | The original (or merged) styles object |
|
|
93
|
+
| `toString()` | `() => string` | Returns `className` for string coercion |
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Babel Plugin Configuration
|
|
98
|
+
|
|
99
|
+
### Basic Configuration
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
// babel.config.js
|
|
103
|
+
module.exports = {
|
|
104
|
+
plugins: [
|
|
105
|
+
['@tenphi/tasty/babel-plugin', {
|
|
106
|
+
output: 'public/tasty.css',
|
|
107
|
+
}]
|
|
108
|
+
]
|
|
109
|
+
};
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### With Configuration
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
module.exports = {
|
|
116
|
+
plugins: [
|
|
117
|
+
['@tenphi/tasty/babel-plugin', {
|
|
118
|
+
output: 'public/tasty.css',
|
|
119
|
+
config: {
|
|
120
|
+
states: {
|
|
121
|
+
'@mobile': '@media(w < 768px)',
|
|
122
|
+
'@tablet': '@media(w < 1024px)',
|
|
123
|
+
'@dark': '@root(theme=dark)',
|
|
124
|
+
},
|
|
125
|
+
devMode: true,
|
|
126
|
+
},
|
|
127
|
+
}]
|
|
128
|
+
]
|
|
129
|
+
};
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Plugin Options
|
|
133
|
+
|
|
134
|
+
| Option | Type | Default | Description |
|
|
135
|
+
|--------|------|---------|-------------|
|
|
136
|
+
| `output` | `string` | `'tasty.css'` | Path for generated CSS file |
|
|
137
|
+
| `config.states` | `Record<string, string>` | `{}` | Predefined state aliases |
|
|
138
|
+
| `config.devMode` | `boolean` | `false` | Add source comments to CSS |
|
|
139
|
+
| `config.recipes` | `Record<string, RecipeStyles>` | `{}` | Predefined style recipes |
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Recipes
|
|
144
|
+
|
|
145
|
+
Recipes work with `tastyStatic` the same way as with runtime `tasty`:
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
// babel.config.js
|
|
149
|
+
module.exports = {
|
|
150
|
+
plugins: [
|
|
151
|
+
['@tenphi/tasty/babel-plugin', {
|
|
152
|
+
output: 'public/tasty.css',
|
|
153
|
+
config: {
|
|
154
|
+
recipes: {
|
|
155
|
+
card: { padding: '4x', fill: '#surface', radius: '1r', border: true },
|
|
156
|
+
elevated: { shadow: '2x 2x 4x #shadow' },
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
}]
|
|
160
|
+
]
|
|
161
|
+
};
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
import { tastyStatic } from '@tenphi/tasty/static';
|
|
166
|
+
|
|
167
|
+
const card = tastyStatic({
|
|
168
|
+
recipe: 'card elevated',
|
|
169
|
+
color: '#text',
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
<div className={card}>Styled card</div>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Next.js Integration
|
|
178
|
+
|
|
179
|
+
```javascript
|
|
180
|
+
// next.config.js
|
|
181
|
+
const { withTastyZero } = require('@tenphi/tasty/next');
|
|
182
|
+
|
|
183
|
+
module.exports = withTastyZero({
|
|
184
|
+
output: 'public/tasty.css',
|
|
185
|
+
config: {
|
|
186
|
+
states: {
|
|
187
|
+
'@mobile': '@media(w < 768px)',
|
|
188
|
+
},
|
|
189
|
+
devMode: process.env.NODE_ENV === 'development',
|
|
190
|
+
},
|
|
191
|
+
})({
|
|
192
|
+
reactStrictMode: true,
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Including the CSS
|
|
197
|
+
|
|
198
|
+
```tsx
|
|
199
|
+
// app/layout.tsx (App Router)
|
|
200
|
+
import '@/public/tasty.css';
|
|
201
|
+
|
|
202
|
+
// or pages/_app.tsx (Pages Router)
|
|
203
|
+
import '../public/tasty.css';
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Vite Integration
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
// vite.config.ts
|
|
212
|
+
import { defineConfig } from 'vite';
|
|
213
|
+
import react from '@vitejs/plugin-react';
|
|
214
|
+
|
|
215
|
+
export default defineConfig({
|
|
216
|
+
plugins: [
|
|
217
|
+
react({
|
|
218
|
+
babel: {
|
|
219
|
+
plugins: [
|
|
220
|
+
['@tenphi/tasty/babel-plugin', {
|
|
221
|
+
output: 'public/tasty.css',
|
|
222
|
+
config: {
|
|
223
|
+
states: { '@mobile': '@media(w < 768px)' },
|
|
224
|
+
},
|
|
225
|
+
}],
|
|
226
|
+
],
|
|
227
|
+
},
|
|
228
|
+
}),
|
|
229
|
+
],
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Build Transformation
|
|
236
|
+
|
|
237
|
+
### Before (Source Code)
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
import { tastyStatic } from '@tenphi/tasty/static';
|
|
241
|
+
|
|
242
|
+
const button = tastyStatic({
|
|
243
|
+
padding: '2x 4x',
|
|
244
|
+
fill: '#purple',
|
|
245
|
+
color: '#white',
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
tastyStatic('.heading', { preset: 'h1' });
|
|
249
|
+
|
|
250
|
+
export const Button = () => <button className={button}>Click</button>;
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### After (Production Build)
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
const button = {
|
|
257
|
+
className: 'ts3f2a1b ts8c4d2e',
|
|
258
|
+
styles: { padding: '2x 4x', fill: '#purple', color: '#white' },
|
|
259
|
+
toString() { return this.className; }
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
export const Button = () => <button className={button}>Click</button>;
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Generated CSS (tasty.css)
|
|
266
|
+
|
|
267
|
+
```css
|
|
268
|
+
/* Generated by @tenphi/tasty/zero - DO NOT EDIT */
|
|
269
|
+
|
|
270
|
+
.ts3f2a1b.ts3f2a1b {
|
|
271
|
+
padding: 16px 32px;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.ts8c4d2e.ts8c4d2e {
|
|
275
|
+
background: #9370db;
|
|
276
|
+
color: #fff;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.heading.heading {
|
|
280
|
+
font-size: 2.5rem;
|
|
281
|
+
font-weight: 700;
|
|
282
|
+
line-height: 1.2;
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Style Extension
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
// Base button
|
|
292
|
+
const button = tastyStatic({
|
|
293
|
+
display: 'inline-flex',
|
|
294
|
+
padding: '2x 4x',
|
|
295
|
+
radius: '1r',
|
|
296
|
+
fill: '#gray.20',
|
|
297
|
+
color: '#text',
|
|
298
|
+
transition: 'fill 0.15s',
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// Variants
|
|
302
|
+
const primaryButton = tastyStatic(button, {
|
|
303
|
+
fill: '#purple',
|
|
304
|
+
color: '#white',
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
const dangerButton = tastyStatic(button, {
|
|
308
|
+
fill: '#danger',
|
|
309
|
+
color: '#white',
|
|
310
|
+
});
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## State-based Styling
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
const card = tastyStatic({
|
|
319
|
+
padding: {
|
|
320
|
+
'': '4x',
|
|
321
|
+
'@mobile': '2x',
|
|
322
|
+
},
|
|
323
|
+
display: {
|
|
324
|
+
'': 'flex',
|
|
325
|
+
'@mobile': 'block',
|
|
326
|
+
},
|
|
327
|
+
});
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## Extending Style Types (TypeScript)
|
|
333
|
+
|
|
334
|
+
If you add custom style properties, use module augmentation so `tastyStatic` recognizes them too. See [Extending Style Types](configuration.md#extending-style-types-typescript) in the configuration docs.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Limitations
|
|
339
|
+
|
|
340
|
+
1. **Static values only** — All style values must be known at build time
|
|
341
|
+
2. **No runtime props** — Cannot use `styleProps` or dynamic `styles` prop
|
|
342
|
+
3. **No mods at runtime** — Modifiers must be defined statically
|
|
343
|
+
4. **Build-time transformation required** — Babel plugin must process files
|
|
344
|
+
|
|
345
|
+
### Workarounds
|
|
346
|
+
|
|
347
|
+
For dynamic styling needs, combine with regular CSS or CSS variables:
|
|
348
|
+
|
|
349
|
+
```tsx
|
|
350
|
+
const card = tastyStatic({
|
|
351
|
+
padding: '4x',
|
|
352
|
+
fill: 'var(--card-bg, #white)',
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
<div
|
|
356
|
+
className={card}
|
|
357
|
+
style={{ '--card-bg': isActive ? '#purple' : '#white' }}
|
|
358
|
+
/>
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Best Practices
|
|
364
|
+
|
|
365
|
+
1. **Define base styles** for common patterns, then extend for variants
|
|
366
|
+
2. **Use selector mode** for global/body styles
|
|
367
|
+
3. **Enable devMode** in development for easier debugging
|
|
368
|
+
4. **Configure states** for consistent responsive breakpoints
|
|
369
|
+
5. **Import generated CSS** early in your app entry point
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Related
|
|
374
|
+
|
|
375
|
+
- [Usage Guide](usage.md) — Runtime styling: component creation, state mappings, sub-elements, variants, and hooks
|
|
376
|
+
- [Configuration](configuration.md) — Global configuration: tokens, recipes, custom units, and style handlers
|