@tenphi/tasty 3.9.11 → 3.11.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 +399 -380
- package/dist/babel-types-BKDTT4--.d.ts +18 -0
- package/dist/chunks/async-storage-f9j9JRtq.js +37 -0
- package/dist/chunks/async-storage-f9j9JRtq.js.map +1 -0
- package/dist/chunks/build-config-5d8WlQbq.js +60 -0
- package/dist/chunks/build-config-5d8WlQbq.js.map +1 -0
- package/dist/chunks/{collector-D2ARGT2L.js → collector-CjCak4iE.js} +8 -6
- package/dist/chunks/collector-CjCak4iE.js.map +1 -0
- package/dist/chunks/{config-engine-DEmmPPdp.js → config-engine-uOFYZidB.js} +4 -4
- package/dist/chunks/{config-engine-DEmmPPdp.js.map → config-engine-uOFYZidB.js.map} +1 -1
- package/dist/chunks/config-file-DlZXJMj8.js +25 -0
- package/dist/chunks/config-file-DlZXJMj8.js.map +1 -0
- package/dist/chunks/{css-definitions-DotDkIXt.js → css-definitions-ubrHP97m.js} +130 -96
- package/dist/chunks/css-definitions-ubrHP97m.js.map +1 -0
- package/dist/chunks/{debug-D8pg9RGI.js → debug-CJ31U_WE.js} +6 -6
- package/dist/chunks/{debug-D8pg9RGI.js.map → debug-CJ31U_WE.js.map} +1 -1
- package/dist/chunks/{dsl-DRhFWQzo.js → dsl-DYSJc1-T.js} +11 -6
- package/dist/chunks/dsl-DYSJc1-T.js.map +1 -0
- package/dist/chunks/{react-runtime-BpxlOTbO.js → react-runtime-CyyCI02N.js} +190 -63
- package/dist/chunks/react-runtime-CyyCI02N.js.map +1 -0
- package/dist/chunks/{runtime-engine-CKFXUH-A.js → runtime-engine-BQmOu5-W.js} +69 -53
- package/dist/chunks/runtime-engine-BQmOu5-W.js.map +1 -0
- package/dist/chunks/{runtime-state-BxaLhVdP.js → runtime-state-DEsyUMU-.js} +28 -3
- package/dist/chunks/runtime-state-DEsyUMU-.js.map +1 -0
- package/dist/chunks/{style-engine-BBbBuSkT.js → style-engine-BX2LshDZ.js} +309 -103
- package/dist/chunks/style-engine-BX2LshDZ.js.map +1 -0
- package/dist/chunks/{zero-engine-gJrKBRiw.js → zero-engine-Dw0P4yGM.js} +62 -27
- package/dist/chunks/zero-engine-Dw0P4yGM.js.map +1 -0
- package/dist/{collector-w4mBj5gd.d.ts → collector-CTU-nl0g.d.ts} +2 -2
- package/dist/{config-CZWCzBr6.d.ts → config-CcxqSZI2.d.ts} +35 -16
- package/dist/core/index.d.ts +4 -4
- package/dist/core/index.js +7 -7
- package/dist/hydrate-CRyjjAyl.d.ts +22 -0
- package/dist/{index-G9JuwM9p.d.ts → index-xtey-KDu.d.ts} +43 -13
- package/dist/index.d.ts +4 -4
- package/dist/index.js +8 -8
- package/dist/{merge-styles-VXwJ0Frr.d.ts → merge-styles-DSkVc6CD.d.ts} +2 -2
- package/dist/ssr/astro.js +4 -4
- package/dist/ssr/client.d.ts +2 -0
- package/dist/ssr/client.js +2 -0
- package/dist/ssr/index.d.ts +3 -22
- package/dist/ssr/index.js +4 -4
- package/dist/ssr/index.js.map +1 -1
- package/dist/ssr/next-config.d.ts +1 -1
- package/dist/ssr/next-config.js +13 -18
- package/dist/ssr/next-config.js.map +1 -1
- package/dist/ssr/next.d.ts +1 -1
- package/dist/ssr/next.js +3 -3
- package/dist/static/index.d.ts +2 -2
- package/dist/{types-JEY8PVYP.d.ts → types-DJEM_BOJ.d.ts} +6 -6
- package/dist/zero/babel.d.ts +67 -2
- package/dist/zero/babel.js +47 -44
- package/dist/zero/babel.js.map +1 -1
- package/dist/zero/index.d.ts +58 -3
- package/dist/zero/index.js +24 -2
- package/dist/zero/index.js.map +1 -0
- package/dist/zero/next.d.ts +2 -1
- package/dist/zero/next.js +3 -7
- package/dist/zero/next.js.map +1 -1
- package/docs/README.md +4 -1
- package/docs/adoption.md +25 -17
- package/docs/ai-agents.md +37 -34
- package/docs/comparison.md +9 -8
- package/docs/configuration.md +174 -59
- package/docs/debug.md +3 -2
- package/docs/design-system.md +117 -15
- package/docs/dsl.md +122 -81
- package/docs/getting-started.md +81 -24
- package/docs/injector.md +39 -40
- package/docs/methodology.md +45 -20
- package/docs/migration-v3.md +2 -2
- package/docs/pipeline.md +20 -17
- package/docs/plugins.md +20 -40
- package/docs/react-api.md +28 -8
- package/docs/runtime-benchmarks.md +4 -4
- package/docs/ssr.md +83 -63
- package/docs/styles.md +27 -17
- package/docs/tasty-static.md +142 -55
- package/package.json +24 -10
- package/dist/babel-rZcEwPLM.d.ts +0 -82
- package/dist/chunks/async-storage-CG5HnUT5.js +0 -20
- package/dist/chunks/async-storage-CG5HnUT5.js.map +0 -1
- package/dist/chunks/build-config-CL4eRu2z.js +0 -42
- package/dist/chunks/build-config-CL4eRu2z.js.map +0 -1
- package/dist/chunks/collector-D2ARGT2L.js.map +0 -1
- package/dist/chunks/css-definitions-DotDkIXt.js.map +0 -1
- package/dist/chunks/dsl-DRhFWQzo.js.map +0 -1
- package/dist/chunks/react-runtime-BpxlOTbO.js.map +0 -1
- package/dist/chunks/runtime-engine-CKFXUH-A.js.map +0 -1
- package/dist/chunks/runtime-state-BxaLhVdP.js.map +0 -1
- package/dist/chunks/style-engine-BBbBuSkT.js.map +0 -1
- package/dist/chunks/zero-engine-gJrKBRiw.js.map +0 -1
package/docs/styles.md
CHANGED
|
@@ -10,6 +10,8 @@ The properties documented below have **custom handlers** with enhanced syntax. T
|
|
|
10
10
|
|
|
11
11
|
Other CSS properties (e.g. `opacity`, `transform`, `cursor`, `position`, `zIndex`) are passed through with standard Tasty value parsing but no special handler logic.
|
|
12
12
|
|
|
13
|
+
[`@tenphi/eslint-plugin-tasty`](getting-started.md#eslint-plugin) reports raw CSS properties that have a handler here (`prefer-shorthand-property`) and modifiers a property does not accept (`valid-directional-modifier`, `valid-radius-shape`).
|
|
14
|
+
|
|
13
15
|
---
|
|
14
16
|
|
|
15
17
|
## Recommended Props
|
|
@@ -64,7 +66,7 @@ Standard CSS display values. Handled together with `hide`, `textOverflow`, `over
|
|
|
64
66
|
| `display` | Any CSS display value | Overridden by `hide` or multi-line `textOverflow` |
|
|
65
67
|
| `hide` | `true` / `false` | Shortcut for `display: none`. Highest priority |
|
|
66
68
|
| `overflow` | Any CSS overflow value | Overridden when `textOverflow` sets `hidden` |
|
|
67
|
-
| `whiteSpace` | Any CSS white-space value |
|
|
69
|
+
| `whiteSpace` | Any CSS white-space value | Explicit value wins over the `nowrap` / `initial` that `textOverflow` sets |
|
|
68
70
|
|
|
69
71
|
### `textOverflow`
|
|
70
72
|
|
|
@@ -78,7 +80,7 @@ Text truncation with optional multi-line clamping.
|
|
|
78
80
|
| `"ellipsis / 3"` | Multi-line clamp (3 lines) with ellipsis, sets `overflow: hidden` and `white-space: initial` |
|
|
79
81
|
| `"clip"` | Single-line truncation without ellipsis, sets `overflow: hidden` and `white-space: nowrap` |
|
|
80
82
|
| `"clip / 2"` | Multi-line clip (2 lines), sets `overflow: hidden` and `white-space: initial` |
|
|
81
|
-
| `
|
|
83
|
+
| `"initial"` | Reset text-overflow to initial |
|
|
82
84
|
|
|
83
85
|
Explicit `whiteSpace` overrides the default white-space set by `textOverflow`.
|
|
84
86
|
|
|
@@ -144,6 +146,8 @@ A group that names *no* direction keeps plain CSS shorthand order, which is unam
|
|
|
144
146
|
|
|
145
147
|
Later comma-separated groups override earlier groups for conflicting directions.
|
|
146
148
|
|
|
149
|
+
A group with directions but no value (`padding: 'top'`) uses `1x`, the same as `padding: true`, so it follows `configure({ units })`.
|
|
150
|
+
|
|
147
151
|
Individual physical props `paddingTop`, `paddingRight`, `paddingBottom`, and `paddingLeft` are supported, but `padding` with modifiers is recommended. Use `blockPadding` or `inlinePadding` for an enhanced logical-axis shorthand; native declarations such as `paddingInlineStart` remain ordinary CSS properties. See [Logical properties](#logical-properties).
|
|
148
152
|
|
|
149
153
|
### `margin`
|
|
@@ -198,7 +202,7 @@ Element width with min/max control. One, two, or three values set `min-width`, `
|
|
|
198
202
|
|
|
199
203
|
| Value | Effect |
|
|
200
204
|
|-------|--------|
|
|
201
|
-
| `"stretch"` | Fill available space
|
|
205
|
+
| `"stretch"` | Fill the available space, margins included. Emitted with `-webkit-fill-available` and `-moz-available` fallbacks for engines without the standard keyword |
|
|
202
206
|
| `true` | Reset to `auto` / `initial` / `initial` |
|
|
203
207
|
| Number | Converted to `px` |
|
|
204
208
|
|
|
@@ -206,7 +210,7 @@ Separate `minWidth` and `maxWidth` props are supported and override values from
|
|
|
206
210
|
|
|
207
211
|
### `height`
|
|
208
212
|
|
|
209
|
-
Element height. Same syntax, modifiers, and positional patterns as `width`.
|
|
213
|
+
Element height. Same syntax, modifiers, keywords, and positional patterns as `width`, including `stretch`.
|
|
210
214
|
|
|
211
215
|
Separate `minHeight` and `maxHeight` props are supported and override values from the `height` syntax.
|
|
212
216
|
|
|
@@ -305,9 +309,8 @@ Background color with design token support. Preferred over `backgroundColor` and
|
|
|
305
309
|
| `"#surface #primary.10"` | Background `#surface` with `#primary.10` overlay (two colors enable smooth transitions between both) |
|
|
306
310
|
| `"rgb(255 128 0)"` | CSS color value |
|
|
307
311
|
| `"color-mix(in oklab, #primary 50%, #surface)"` | CSS color function — see [CSS Color Functions](dsl.md#css-color-functions) |
|
|
308
|
-
| `true` | Default fill color |
|
|
309
312
|
|
|
310
|
-
When two colors are provided, the first sets the background color and the second is applied as an overlay gradient layer. This enables independent CSS transitions on each color.
|
|
313
|
+
When two colors are provided, the first sets the background color and the second is applied as an overlay gradient layer. This enables independent CSS transitions on each color. With `image` or `backgroundImage` on the same element, the image is layered over the overlay color in one `background-image`.
|
|
311
314
|
|
|
312
315
|
**Related deprecated props:** `backgroundColor` (use `fill`), `background` (overrides all background props when set — avoid).
|
|
313
316
|
|
|
@@ -368,7 +371,7 @@ Border shorthand with directional and multi-group support. Use **comma-separated
|
|
|
368
371
|
|
|
369
372
|
**Syntax:** `[width] [style] [color] [directions...]` — comma-separated for multiple groups
|
|
370
373
|
|
|
371
|
-
**Defaults:** width = `1bw`, style = `solid`, color = `#border`
|
|
374
|
+
**Defaults:** width = `1bw`, style = `solid`, color = `#border`, which is the text color (`currentColor`) until your tokens define `#border`
|
|
372
375
|
|
|
373
376
|
**Styles:** `none`, `hidden`, `dotted`, `dashed`, `solid`, `double`, `groove`, `ridge`, `inset`, `outset`
|
|
374
377
|
|
|
@@ -388,6 +391,8 @@ Border shorthand with directional and multi-group support. Use **comma-separated
|
|
|
388
391
|
|
|
389
392
|
Later comma-separated groups override earlier groups for conflicting directions.
|
|
390
393
|
|
|
394
|
+
A directional group without a width (`'dotted left'`) uses `1bw`, the same as `border: true`, so it follows `configure({ units })`.
|
|
395
|
+
|
|
391
396
|
### `radius`
|
|
392
397
|
|
|
393
398
|
Border radius with shape presets and directional modifiers.
|
|
@@ -427,13 +432,15 @@ Use these when an edge modifier would round one corner too many. Edge and corner
|
|
|
427
432
|
| `"4px top-left"` | Top-left corner `4px`, every other corner `0` |
|
|
428
433
|
| `"top bottom-right"` | Both top corners and bottom-right `1r`, bottom-left `0` |
|
|
429
434
|
|
|
435
|
+
A value-less corner group (`'top-right'`, `'top bottom-right'`) uses `1r`, the same as `radius: true`, so it follows `configure({ units })`.
|
|
436
|
+
|
|
430
437
|
### `outline`
|
|
431
438
|
|
|
432
439
|
Outline with inline offset support.
|
|
433
440
|
|
|
434
441
|
**Syntax:** `[width] [style] [color] / [offset]`
|
|
435
442
|
|
|
436
|
-
**Defaults:** width = `1ow`, style = `solid`, color = `#outline`
|
|
443
|
+
**Defaults:** width = `1ow`, style = `solid`, color = `#outline`, which is the text color (`currentColor`) until your tokens define `#outline`
|
|
437
444
|
|
|
438
445
|
**Styles:** Same as `border` (`none`, `dotted`, `dashed`, `solid`, etc.)
|
|
439
446
|
|
|
@@ -468,7 +475,7 @@ Multiple shadows: `shadow="1x 1x 2x #dark.20, inset 0 0 4x #dark.10"`
|
|
|
468
475
|
|
|
469
476
|
### `preset`
|
|
470
477
|
|
|
471
|
-
Typography preset that sets font-size, line-height, letter-spacing, font-weight, font-style,
|
|
478
|
+
Typography preset that sets font-size, line-height, letter-spacing, font-weight, font-style, text-transform, and font-family (unless `font` or `fontFamily` is set) from named design tokens. It also sets the `--bold-font-weight` and `--icon-size` variables that `strong` and `icon` read.
|
|
472
479
|
|
|
473
480
|
**Syntax:** `name`, `name / modifier...`, or `modifier...` (shorthand)
|
|
474
481
|
|
|
@@ -480,10 +487,11 @@ Use `/` to separate the preset name from one or more space-separated modifiers.
|
|
|
480
487
|
|
|
481
488
|
| Modifier | Effect |
|
|
482
489
|
|----------|--------|
|
|
483
|
-
| `strong` (or `bold`) | Sets `font-weight` to bold (from `$bold-font-weight` token) |
|
|
490
|
+
| `strong` (or `bold`) | Sets `font-weight` to bold (from `$bold-font-weight` token, `700` until your tokens define it) |
|
|
484
491
|
| `italic` | Sets `font-style: italic` |
|
|
485
492
|
| `icon` | Sets font-size and line-height to icon size |
|
|
486
493
|
| `tight` | Sets line-height equal to font-size |
|
|
494
|
+
| `normal` | Sets `line-height: normal` |
|
|
487
495
|
|
|
488
496
|
```jsx
|
|
489
497
|
preset="h1" // heading 1
|
|
@@ -503,9 +511,9 @@ Font family with design-system fallback. Preferred over `fontFamily`.
|
|
|
503
511
|
|
|
504
512
|
| Value | Effect |
|
|
505
513
|
|-------|--------|
|
|
506
|
-
| `"monospace"` | Monospace
|
|
507
|
-
| `true` | Default
|
|
508
|
-
| `"CustomFont"` | Custom font
|
|
514
|
+
| `"monospace"` | Monospace stack from `$font-mono`, falling back to the built-in `$font-mono-fallback` |
|
|
515
|
+
| `true` | Default sans stack from `$font-sans`, falling back to `$font-sans-fallback` |
|
|
516
|
+
| `"CustomFont"` | Custom font followed by the `$font-sans` stack |
|
|
509
517
|
|
|
510
518
|
`fontFamily` is supported as a direct pass-through without fallback logic.
|
|
511
519
|
|
|
@@ -581,12 +589,14 @@ When easing is provided without a duration, the default timing variable is used
|
|
|
581
589
|
| `width` | `width`, `min-width`, `max-width` |
|
|
582
590
|
| `height` | `height`, `min-height`, `max-height` |
|
|
583
591
|
| `gap` | `gap`, `margin` |
|
|
584
|
-
| `zIndex` | `z-index` |
|
|
592
|
+
| `zIndex` | `z-index` (same as writing `z-index`) |
|
|
585
593
|
| `inset` | `inset`, `top`, `right`, `bottom`, `left` |
|
|
586
594
|
|
|
595
|
+
Any other name passes through as a CSS property.
|
|
596
|
+
|
|
587
597
|
When two entries cover the same property, an entry that names that one property wins over a group such as `theme`, in either order: `opacity 120ms ease-in-out, theme` keeps the opacity timing. Otherwise the later entry wins, as in CSS.
|
|
588
598
|
|
|
589
|
-
Default timing: `$transition` (or `${name}-transition` with `$transition` fallback per semantic name). Prefer omitting the duration or using a duration token instead of repeating raw time values across components. Explicit zero can disable motion.
|
|
599
|
+
Default timing: `$transition` (or `${name}-transition` with `$transition` fallback per semantic name). `$transition` is `80ms` until your tokens define it. Prefer omitting the duration or using a duration token instead of repeating raw time values across components. Explicit zero can disable motion.
|
|
590
600
|
|
|
591
601
|
```jsx
|
|
592
602
|
transition="theme"
|
|
@@ -674,11 +684,11 @@ plain CSS shorthand order, like `padding`. See the [`padding` rule](#padding).
|
|
|
674
684
|
|
|
675
685
|
| Value | Effect |
|
|
676
686
|
|-------|--------|
|
|
677
|
-
| `"top"` | Fade top edge, default width
|
|
687
|
+
| `"top"` | Fade top edge, default width `2x`, all other edges unfaded |
|
|
678
688
|
| `"2x left right"` | Fade left and right edges with `2x` width, top/bottom unfaded |
|
|
679
689
|
| `"3x 1x"` | All edges faded — top/bottom `3x`, left/right `1x` (CSS shorthand order) |
|
|
680
690
|
| `"3x top, 1x bottom"` | Fade top with `3x` width, bottom with `1x` width |
|
|
681
|
-
| `"2x #
|
|
691
|
+
| `"2x #clear #dark"` | All edges faded with `2x` width, from `#clear` to `#dark` |
|
|
682
692
|
| `"top #a #b, bottom #c #d"` | Top fades from `#a` to `#b`, bottom fades from `#c` to `#d` |
|
|
683
693
|
|
|
684
694
|
Colors are optional: first = transparent mask start, second = opaque mask end.
|
package/docs/tasty-static.md
CHANGED
|
@@ -8,30 +8,33 @@ Choose `tastyStatic` specifically when styles must be generated during the build
|
|
|
8
8
|
|
|
9
9
|
## When to Use
|
|
10
10
|
|
|
11
|
-
- **
|
|
12
|
-
- **No
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
11
|
+
- **CSS that must exist before anything renders** — static sites, landing pages, and HTML served from a CDN get one stylesheet generated at build time
|
|
12
|
+
- **No React at runtime** — `tastyStatic` returns class names, so plain DOM code or any templating that sets `class` can use them; the [Programmatic API](#programmatic-api) covers frameworks Babel does not process
|
|
13
|
+
- **Class-name objects instead of components** — extend them with `tastyStatic(base, styles)` and pass them wherever a `className` goes
|
|
14
|
+
- **Self-contained packages** — [inject mode](#inject-mode) embeds the CSS in the JavaScript, so consumers have no stylesheet to wire up
|
|
15
|
+
|
|
16
|
+
If the styles depend on props, keep `tasty()`: rendered only on the server, it also ships no styling runtime (see [Server-Side Rendering](ssr.md)).
|
|
15
17
|
|
|
16
18
|
## Requirements
|
|
17
19
|
|
|
18
20
|
Build-time extraction is part of the main `@tenphi/tasty` package but requires additional peer dependencies depending on your setup:
|
|
19
21
|
|
|
20
|
-
| Dependency | Version | Required for
|
|
21
|
-
| ---------------------------- | ------- |
|
|
22
|
-
| `@babel/core` | >= 7.24 | Babel plugin (`@tenphi/tasty/babel-plugin`)
|
|
23
|
-
| `@babel/helper-plugin-utils` | >= 7.24 | Babel plugin
|
|
24
|
-
| `@babel/types` | >= 7.24 | Babel plugin
|
|
25
|
-
| `jiti` | >= 2.6 | Next.js wrapper (
|
|
22
|
+
| Dependency | Version | Required for |
|
|
23
|
+
| ---------------------------- | ------- | ------------------------------------------------------------------------------ |
|
|
24
|
+
| `@babel/core` | >= 7.24 | Babel plugin (`@tenphi/tasty/babel-plugin`) |
|
|
25
|
+
| `@babel/helper-plugin-utils` | >= 7.24 | Babel plugin |
|
|
26
|
+
| `@babel/types` | >= 7.24 | Babel plugin |
|
|
27
|
+
| `jiti` | >= 2.6 | Babel plugin and Next.js wrapper (imported on load, even without `configFile`) |
|
|
28
|
+
| `babel-loader` | any | Next.js wrapper (`@tenphi/tasty/zero/next`) |
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
The Babel packages and `jiti` are optional peer dependencies of `@tenphi/tasty`; `babel-loader` is resolved from your project. Install what your setup requires:
|
|
28
31
|
|
|
29
32
|
```bash
|
|
30
|
-
#
|
|
31
|
-
pnpm add -D @babel/core @babel/helper-plugin-utils @babel/types
|
|
32
|
-
|
|
33
|
-
# For Next.js with TypeScript config file
|
|
33
|
+
# Any Babel-based setup (Vite, custom Babel config, etc.)
|
|
34
34
|
pnpm add -D @babel/core @babel/helper-plugin-utils @babel/types jiti
|
|
35
|
+
|
|
36
|
+
# Next.js
|
|
37
|
+
pnpm add -D @babel/core @babel/helper-plugin-utils @babel/types jiti babel-loader
|
|
35
38
|
```
|
|
36
39
|
|
|
37
40
|
---
|
|
@@ -52,13 +55,15 @@ const button = tastyStatic({
|
|
|
52
55
|
radius: '1r',
|
|
53
56
|
});
|
|
54
57
|
|
|
55
|
-
// Use in JSX
|
|
56
|
-
<button className={button}>Click me</button
|
|
58
|
+
// Use in JSX
|
|
59
|
+
<button className={button.className}>Click me</button>;
|
|
57
60
|
|
|
58
|
-
//
|
|
59
|
-
|
|
61
|
+
// toString() returns the class name, for template strings and plain JS
|
|
62
|
+
element.className = `${button} is-active`;
|
|
60
63
|
```
|
|
61
64
|
|
|
65
|
+
In TSX, pass `button.className`: React types `className` as `string`, so passing the `StaticStyle` object fails type-checking even though it works at runtime.
|
|
66
|
+
|
|
62
67
|
---
|
|
63
68
|
|
|
64
69
|
## API Reference
|
|
@@ -105,6 +110,8 @@ tastyStatic('body', {
|
|
|
105
110
|
});
|
|
106
111
|
```
|
|
107
112
|
|
|
113
|
+
The selector can be a list (`'.uni-checkbox, uni-checkbox'`): every item gets the states and sub-elements. Local `@keyframes` and `@starting` states work as in `tastyStatic(styles)`.
|
|
114
|
+
|
|
108
115
|
---
|
|
109
116
|
|
|
110
117
|
## StaticStyle Object
|
|
@@ -242,7 +249,7 @@ const card = tastyStatic({
|
|
|
242
249
|
color: '#text',
|
|
243
250
|
});
|
|
244
251
|
|
|
245
|
-
<div className={card}>Styled card</div>;
|
|
252
|
+
<div className={card.className}>Styled card</div>;
|
|
246
253
|
```
|
|
247
254
|
|
|
248
255
|
---
|
|
@@ -281,10 +288,10 @@ Starting with Next.js 16, Turbopack is the default bundler. `withTastyZero` supp
|
|
|
281
288
|
|
|
282
289
|
The `configFile` option is key for Turbopack — it passes a file path (JSON-serializable) instead of a function, and the Babel plugin loads the config internally via jiti.
|
|
283
290
|
|
|
284
|
-
**Requirements**: `babel-loader` must be installed in your project:
|
|
291
|
+
**Requirements**: `babel-loader` must be installed in your project (see [Requirements](#requirements)):
|
|
285
292
|
|
|
286
293
|
```bash
|
|
287
|
-
pnpm add babel-loader
|
|
294
|
+
pnpm add -D babel-loader
|
|
288
295
|
```
|
|
289
296
|
|
|
290
297
|
### CSS Injection
|
|
@@ -299,34 +306,95 @@ public/tasty.css
|
|
|
299
306
|
|
|
300
307
|
---
|
|
301
308
|
|
|
309
|
+
## Programmatic API
|
|
310
|
+
|
|
311
|
+
`@tenphi/tasty/zero` turns styles into CSS in Node without Babel or React — for build scripts, or CSS shipped to other frameworks:
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
import {
|
|
315
|
+
configure,
|
|
316
|
+
extractStylesForSelector,
|
|
317
|
+
extractStylesWithChunks,
|
|
318
|
+
} from '@tenphi/tasty/zero';
|
|
319
|
+
|
|
320
|
+
configure({
|
|
321
|
+
units: { u: 'var(--unit)' },
|
|
322
|
+
states: { '@dark': '@root(schema=dark)' },
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
extractStylesForSelector('.card', { padding: '2u', fill: '#surface' }).css;
|
|
326
|
+
// → '.card { padding: calc(2 * var(--unit)); background-color: … }'
|
|
327
|
+
|
|
328
|
+
extractStylesWithChunks({ display: 'flex', gap: '1u' });
|
|
329
|
+
// → [{ className: 'ts…', css: '.ts….ts… { … }' }]
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
`configure()` takes the same options as the Babel plugin's `config` (see [Plugin Options](#plugin-options)) and replaces the previous configuration on each call; `resetConfig()` returns to the defaults. Options that shape the extracted rules apply — `states`, `units`, parse `functions`, `handlers`, `replaceTokens`, `recipes`, `plugins`, `namePrefix`. Definitions that become at-rules or global CSS of their own are not emitted with the rules: `tokens`, `globalStyles`, `fontFaces`, `counterStyles`, `properties` and `$$` `@function` definitions. Render tokens and global styles with `extractStylesForSelector(':root', tokens)` and `extractStylesForSelector(selector, styles)`.
|
|
333
|
+
|
|
334
|
+
`extractConfigProperties()` returns the `@property` rules the Babel plugin writes at the top of its output: Tasty's default set (`#border`, `#outline`, `$gap`, `$radius`, `$transition`, …) overlaid with the configured `properties`. Emit them once per stylesheet. Style handlers read several of these tokens with no fallback of their own (`border: true` reads `#border`, `transition` reads `$transition`), so without them those declarations resolve to nothing.
|
|
335
|
+
|
|
336
|
+
The configuration is process-wide and shared with the Babel plugin and the runtime `configure()` from `@tenphi/tasty`. The extractors re-apply their own configuration when the Babel plugin replaced it, but not after a runtime `configure()` — don't mix the runtime and build-time configuration in one process.
|
|
337
|
+
|
|
338
|
+
`extractStylesForSelector()` output starts with the `@keyframes` its rules animate — local `@keyframes` and configured `keyframes` — under hashed names the `animation` declarations are rewritten to. `extractStylesWithChunks()` returns class rules only.
|
|
339
|
+
|
|
340
|
+
To write the results to a file the way the Babel plugin does, use `createCSSWriter()`. It deduplicates blocks by key and prepends the generated-file header:
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
import {
|
|
344
|
+
createCSSWriter,
|
|
345
|
+
extractConfigProperties,
|
|
346
|
+
extractStylesWithChunks,
|
|
347
|
+
} from '@tenphi/tasty/zero';
|
|
348
|
+
|
|
349
|
+
const writer = createCSSWriter('dist/tasty.css', { devMode: true });
|
|
350
|
+
|
|
351
|
+
for (const prop of extractConfigProperties()) {
|
|
352
|
+
writer.add(`@property:${prop.name}`, prop.css);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
for (const chunk of extractStylesWithChunks({ display: 'flex', gap: '1u' })) {
|
|
356
|
+
writer.add(chunk.className, chunk.css, 'src/card.ts'); // source is a devMode comment
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
writer.write(); // also: has(key), getCSS(), clear(), getOutputPath()
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
302
364
|
## Vite Integration
|
|
303
365
|
|
|
366
|
+
`@vitejs/plugin-react` 6 no longer runs Babel; add it with `@rolldown/plugin-babel` (`pnpm add -D @rolldown/plugin-babel`):
|
|
367
|
+
|
|
304
368
|
```typescript
|
|
305
369
|
// vite.config.ts
|
|
306
370
|
import { defineConfig } from 'vite';
|
|
307
371
|
import react from '@vitejs/plugin-react';
|
|
372
|
+
import babel from '@rolldown/plugin-babel';
|
|
308
373
|
|
|
309
374
|
export default defineConfig({
|
|
310
375
|
plugins: [
|
|
311
|
-
react(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
},
|
|
376
|
+
react(),
|
|
377
|
+
babel({
|
|
378
|
+
plugins: [
|
|
379
|
+
[
|
|
380
|
+
'@tenphi/tasty/babel-plugin',
|
|
381
|
+
{
|
|
382
|
+
output: 'src/tasty.css',
|
|
383
|
+
config: {
|
|
384
|
+
states: { '@mobile': '@media(w < 768px)' },
|
|
321
385
|
},
|
|
322
|
-
|
|
386
|
+
},
|
|
323
387
|
],
|
|
324
|
-
|
|
388
|
+
],
|
|
325
389
|
}),
|
|
326
390
|
],
|
|
327
391
|
});
|
|
328
392
|
```
|
|
329
393
|
|
|
394
|
+
With `@vitejs/plugin-react` 5 or older, pass the same `plugins` array to `react({ babel: { plugins } })` instead.
|
|
395
|
+
|
|
396
|
+
Keep `output` outside `public/`: the plugin replaces each `@tenphi/tasty/static` import with an import of the generated file, and Vite does not let JavaScript import files from `public/`. Vite then bundles the CSS like any other stylesheet.
|
|
397
|
+
|
|
330
398
|
---
|
|
331
399
|
|
|
332
400
|
## Build Transformation
|
|
@@ -344,44 +412,61 @@ const button = tastyStatic({
|
|
|
344
412
|
|
|
345
413
|
tastyStatic('.heading', { preset: 'h1' });
|
|
346
414
|
|
|
347
|
-
export const Button = () => <button className={button}>Click</button>;
|
|
415
|
+
export const Button = () => <button className={button.className}>Click</button>;
|
|
348
416
|
```
|
|
349
417
|
|
|
350
418
|
### After (Production Build)
|
|
351
419
|
|
|
352
420
|
```tsx
|
|
421
|
+
import './tasty.css';
|
|
422
|
+
|
|
353
423
|
const button = {
|
|
354
|
-
className: '
|
|
424
|
+
className: 'ts3f783b ts070801',
|
|
355
425
|
styles: { padding: '2x 4x', fill: '#purple', color: '#white' },
|
|
356
426
|
toString() {
|
|
357
427
|
return this.className;
|
|
358
428
|
},
|
|
359
429
|
};
|
|
360
430
|
|
|
361
|
-
export const Button = () => <button className={button}>Click</button>;
|
|
431
|
+
export const Button = () => <button className={button.className}>Click</button>;
|
|
362
432
|
```
|
|
363
433
|
|
|
434
|
+
The `@tenphi/tasty/static` import becomes an import of the generated file (relative to the source file), and the selector-mode call is removed.
|
|
435
|
+
|
|
364
436
|
### Generated CSS (tasty.css)
|
|
365
437
|
|
|
366
438
|
```css
|
|
367
439
|
/* Generated by @tenphi/tasty/zero - DO NOT EDIT */
|
|
368
440
|
|
|
369
|
-
|
|
370
|
-
|
|
441
|
+
@property --current-color {
|
|
442
|
+
syntax: '<color>';
|
|
443
|
+
inherits: true;
|
|
444
|
+
initial-value: currentcolor;
|
|
371
445
|
}
|
|
372
446
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
447
|
+
/* …the rest of Tasty's default @property rules (--gap, --radius, --white-color, …) */
|
|
448
|
+
|
|
449
|
+
.ts3f783b.ts3f783b {
|
|
450
|
+
color: var(--white-color);
|
|
451
|
+
--current-color: var(--white-color);
|
|
376
452
|
}
|
|
377
453
|
|
|
378
|
-
.
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
454
|
+
.ts3f783b.ts3f783b {
|
|
455
|
+
background-color: var(--purple-color);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.ts070801.ts070801 {
|
|
459
|
+
padding: 16px 32px;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.heading {
|
|
463
|
+
font-size: var(--h1-font-size, var(--default-font-size));
|
|
464
|
+
/* …line-height, letter-spacing, font-weight, and the rest of the h1 preset */
|
|
382
465
|
}
|
|
383
466
|
```
|
|
384
467
|
|
|
468
|
+
Styles are split into chunks (here appearance and spacing), each with its own class. Color tokens compile to custom properties: `#purple` becomes `var(--purple-color)`. Define it in `config.tokens` and the plugin writes it to `:root` at the top of the same file. Units are literal (`2x` is `16px`). Selector-mode rules use the selector as written, without the doubled specificity of class rules.
|
|
469
|
+
|
|
385
470
|
---
|
|
386
471
|
|
|
387
472
|
## Inject Mode
|
|
@@ -454,18 +539,18 @@ import { injectCSS as _$i } from '@tenphi/tasty/static/inject';
|
|
|
454
539
|
|
|
455
540
|
const button =
|
|
456
541
|
(_$i(
|
|
457
|
-
'
|
|
458
|
-
'.
|
|
542
|
+
'tsa903d6 ts070801',
|
|
543
|
+
'.tsa903d6.tsa903d6 { background-color: var(--purple-color); }\n.ts070801.ts070801 { padding: 16px 32px; }',
|
|
459
544
|
),
|
|
460
545
|
{
|
|
461
|
-
className: '
|
|
546
|
+
className: 'tsa903d6 ts070801',
|
|
462
547
|
styles: { padding: '2x 4x', fill: '#purple' },
|
|
463
548
|
toString() {
|
|
464
549
|
return this.className;
|
|
465
550
|
},
|
|
466
551
|
});
|
|
467
552
|
|
|
468
|
-
_$i('.heading', '.heading{font-size:
|
|
553
|
+
_$i('.heading', '.heading { font-size: var(--h1-font-size, …); … }');
|
|
469
554
|
```
|
|
470
555
|
|
|
471
556
|
### Dev Mode / HMR
|
|
@@ -525,7 +610,7 @@ const card = tastyStatic({
|
|
|
525
610
|
|
|
526
611
|
## Extending Style Types (TypeScript)
|
|
527
612
|
|
|
528
|
-
If you add custom style properties, use module augmentation so `tastyStatic` recognizes them too. See [
|
|
613
|
+
If you add custom style properties, use module augmentation so `tastyStatic` recognizes them too. See [TypeScript](configuration.md#typescript) in the configuration docs.
|
|
529
614
|
|
|
530
615
|
---
|
|
531
616
|
|
|
@@ -547,10 +632,12 @@ const card = tastyStatic({
|
|
|
547
632
|
});
|
|
548
633
|
|
|
549
634
|
<div
|
|
550
|
-
className={card}
|
|
551
|
-
style={
|
|
552
|
-
|
|
553
|
-
|
|
635
|
+
className={card.className}
|
|
636
|
+
style={
|
|
637
|
+
{
|
|
638
|
+
'--card-bg': isActive ? 'var(--purple-color)' : 'var(--white-color)',
|
|
639
|
+
} as React.CSSProperties
|
|
640
|
+
}
|
|
554
641
|
/>;
|
|
555
642
|
```
|
|
556
643
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tenphi/tasty",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.0",
|
|
4
4
|
"description": "A design-system-integrated styling system and DSL for concise, state-aware UI styling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -62,6 +62,11 @@
|
|
|
62
62
|
"import": "./dist/ssr/astro.js",
|
|
63
63
|
"default": "./dist/ssr/astro.js"
|
|
64
64
|
},
|
|
65
|
+
"./ssr/client": {
|
|
66
|
+
"types": "./dist/ssr/client.d.ts",
|
|
67
|
+
"import": "./dist/ssr/client.js",
|
|
68
|
+
"default": "./dist/ssr/client.js"
|
|
69
|
+
},
|
|
65
70
|
"./ssr/astro-client": {
|
|
66
71
|
"types": "./dist/ssr/astro-client.d.ts",
|
|
67
72
|
"import": "./dist/ssr/astro-client.js",
|
|
@@ -169,7 +174,7 @@
|
|
|
169
174
|
"@eslint/js": "^10.0.1",
|
|
170
175
|
"@size-limit/esbuild": "^14.0.0",
|
|
171
176
|
"@size-limit/file": "^14.0.0",
|
|
172
|
-
"@tenphi/eslint-plugin-tasty": "^1.1
|
|
177
|
+
"@tenphi/eslint-plugin-tasty": "^1.5.1",
|
|
173
178
|
"@testing-library/jest-dom": "^7.0.1",
|
|
174
179
|
"@testing-library/react": "^16.3.3",
|
|
175
180
|
"@types/babel__core": "^7.20.5",
|
|
@@ -200,13 +205,13 @@
|
|
|
200
205
|
"name": "main (import *)",
|
|
201
206
|
"path": "dist/index.js",
|
|
202
207
|
"import": "*",
|
|
203
|
-
"limit": "
|
|
208
|
+
"limit": "59.65 kB"
|
|
204
209
|
},
|
|
205
210
|
{
|
|
206
211
|
"name": "main (tasty)",
|
|
207
212
|
"path": "dist/index.js",
|
|
208
213
|
"import": "{ tasty }",
|
|
209
|
-
"limit": "
|
|
214
|
+
"limit": "52.67 kB"
|
|
210
215
|
},
|
|
211
216
|
{
|
|
212
217
|
"name": "main (StyleParser)",
|
|
@@ -224,13 +229,13 @@
|
|
|
224
229
|
"name": "main (useRawCSS)",
|
|
225
230
|
"path": "dist/index.js",
|
|
226
231
|
"import": "{ useRawCSS }",
|
|
227
|
-
"limit": "
|
|
232
|
+
"limit": "32.48 kB"
|
|
228
233
|
},
|
|
229
234
|
{
|
|
230
235
|
"name": "core (import *)",
|
|
231
236
|
"path": "dist/core/index.js",
|
|
232
237
|
"import": "*",
|
|
233
|
-
"limit": "
|
|
238
|
+
"limit": "55.23 kB"
|
|
234
239
|
},
|
|
235
240
|
{
|
|
236
241
|
"name": "static",
|
|
@@ -247,7 +252,7 @@
|
|
|
247
252
|
"path",
|
|
248
253
|
"crypto"
|
|
249
254
|
],
|
|
250
|
-
"limit": "
|
|
255
|
+
"limit": "39.13 kB"
|
|
251
256
|
},
|
|
252
257
|
{
|
|
253
258
|
"name": "babel-plugin",
|
|
@@ -256,9 +261,11 @@
|
|
|
256
261
|
"ignore": [
|
|
257
262
|
"fs",
|
|
258
263
|
"path",
|
|
259
|
-
"crypto"
|
|
264
|
+
"crypto",
|
|
265
|
+
"node:module",
|
|
266
|
+
"node:path"
|
|
260
267
|
],
|
|
261
|
-
"limit": "
|
|
268
|
+
"limit": "43.55 kB"
|
|
262
269
|
},
|
|
263
270
|
{
|
|
264
271
|
"name": "astro client",
|
|
@@ -266,6 +273,12 @@
|
|
|
266
273
|
"import": "*",
|
|
267
274
|
"limit": "0.5 kB"
|
|
268
275
|
},
|
|
276
|
+
{
|
|
277
|
+
"name": "ssr client",
|
|
278
|
+
"path": "dist/ssr/client.js",
|
|
279
|
+
"import": "{ hydrateTastyClasses }",
|
|
280
|
+
"limit": "0.5 kB"
|
|
281
|
+
},
|
|
269
282
|
{
|
|
270
283
|
"name": "Next.js config",
|
|
271
284
|
"path": "dist/ssr/next-config.js",
|
|
@@ -276,7 +289,7 @@
|
|
|
276
289
|
"node:module",
|
|
277
290
|
"node:path"
|
|
278
291
|
],
|
|
279
|
-
"limit": "
|
|
292
|
+
"limit": "40.18 kB"
|
|
280
293
|
}
|
|
281
294
|
],
|
|
282
295
|
"scripts": {
|
|
@@ -298,6 +311,7 @@
|
|
|
298
311
|
"bench:overhead": "vitest bench --config vitest.production-browser-bench.config.ts src/tasty-overhead.bench.tsx",
|
|
299
312
|
"bench:injection": "vitest bench --config vitest.production-browser-bench.config.ts src/tasty-injection.bench.ts",
|
|
300
313
|
"bench:interaction": "vitest bench --config vitest.production-browser-bench.config.ts src/tasty-interaction.bench.tsx",
|
|
314
|
+
"bench:tree": "vitest bench --config vitest.production-browser-bench.config.ts src/tasty-tree.bench.tsx",
|
|
301
315
|
"bench:cold-start": "node scripts/cold-start/index.mjs",
|
|
302
316
|
"changeset": "changeset",
|
|
303
317
|
"version": "changeset version",
|