@tenphi/tasty 0.0.0-snapshot.cfcf770 → 0.0.0-snapshot.d2dcdeb

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.
Files changed (101) hide show
  1. package/README.md +25 -19
  2. package/dist/compute-styles.js +6 -28
  3. package/dist/compute-styles.js.map +1 -1
  4. package/dist/config.d.ts +41 -1
  5. package/dist/config.js +92 -7
  6. package/dist/config.js.map +1 -1
  7. package/dist/core/index.d.ts +2 -2
  8. package/dist/core/index.js +1 -1
  9. package/dist/debug.js +4 -4
  10. package/dist/debug.js.map +1 -1
  11. package/dist/hooks/useCounterStyle.d.ts +3 -17
  12. package/dist/hooks/useCounterStyle.js +55 -35
  13. package/dist/hooks/useCounterStyle.js.map +1 -1
  14. package/dist/hooks/useFontFace.d.ts +3 -1
  15. package/dist/hooks/useFontFace.js +21 -24
  16. package/dist/hooks/useFontFace.js.map +1 -1
  17. package/dist/hooks/useGlobalStyles.d.ts +18 -2
  18. package/dist/hooks/useGlobalStyles.js +51 -40
  19. package/dist/hooks/useGlobalStyles.js.map +1 -1
  20. package/dist/hooks/useKeyframes.d.ts +4 -2
  21. package/dist/hooks/useKeyframes.js +42 -50
  22. package/dist/hooks/useKeyframes.js.map +1 -1
  23. package/dist/hooks/useProperty.d.ts +4 -2
  24. package/dist/hooks/useProperty.js +29 -41
  25. package/dist/hooks/useProperty.js.map +1 -1
  26. package/dist/hooks/useRawCSS.d.ts +13 -44
  27. package/dist/hooks/useRawCSS.js +90 -21
  28. package/dist/hooks/useRawCSS.js.map +1 -1
  29. package/dist/hooks/useStyles.d.ts +4 -4
  30. package/dist/hooks/useStyles.js +7 -5
  31. package/dist/hooks/useStyles.js.map +1 -1
  32. package/dist/index.d.ts +2 -2
  33. package/dist/index.js +1 -1
  34. package/dist/injector/index.js +1 -1
  35. package/dist/injector/index.js.map +1 -1
  36. package/dist/injector/injector.d.ts +9 -7
  37. package/dist/injector/injector.js +126 -38
  38. package/dist/injector/injector.js.map +1 -1
  39. package/dist/injector/sheet-manager.js +4 -2
  40. package/dist/injector/sheet-manager.js.map +1 -1
  41. package/dist/injector/types.d.ts +11 -2
  42. package/dist/pipeline/parseStateKey.js +4 -4
  43. package/dist/pipeline/parseStateKey.js.map +1 -1
  44. package/dist/plugins/types.d.ts +12 -1
  45. package/dist/rsc-cache.js +79 -0
  46. package/dist/rsc-cache.js.map +1 -0
  47. package/dist/ssr/astro-client.d.ts +1 -0
  48. package/dist/ssr/astro-client.js +19 -0
  49. package/dist/ssr/astro-client.js.map +1 -0
  50. package/dist/ssr/astro-middleware.d.ts +15 -0
  51. package/dist/ssr/astro-middleware.js +19 -0
  52. package/dist/ssr/astro-middleware.js.map +1 -0
  53. package/dist/ssr/astro.d.ts +89 -10
  54. package/dist/ssr/astro.js +112 -27
  55. package/dist/ssr/astro.js.map +1 -1
  56. package/dist/ssr/async-storage.js +14 -4
  57. package/dist/ssr/async-storage.js.map +1 -1
  58. package/dist/ssr/collect-auto-properties.js +28 -9
  59. package/dist/ssr/collect-auto-properties.js.map +1 -1
  60. package/dist/ssr/collector.d.ts +5 -13
  61. package/dist/ssr/collector.js +27 -15
  62. package/dist/ssr/collector.js.map +1 -1
  63. package/dist/ssr/context.js +16 -0
  64. package/dist/ssr/context.js.map +1 -0
  65. package/dist/ssr/hydrate.d.ts +20 -13
  66. package/dist/ssr/hydrate.js +24 -28
  67. package/dist/ssr/hydrate.js.map +1 -1
  68. package/dist/ssr/index.d.ts +3 -3
  69. package/dist/ssr/index.js +4 -4
  70. package/dist/ssr/index.js.map +1 -1
  71. package/dist/ssr/next.d.ts +7 -4
  72. package/dist/ssr/next.js +7 -6
  73. package/dist/ssr/next.js.map +1 -1
  74. package/dist/ssr/ssr-collector-ref.js +19 -2
  75. package/dist/ssr/ssr-collector-ref.js.map +1 -1
  76. package/dist/tasty.d.ts +1 -1
  77. package/dist/tasty.js +9 -4
  78. package/dist/tasty.js.map +1 -1
  79. package/dist/utils/deps-equal.js +15 -0
  80. package/dist/utils/deps-equal.js.map +1 -0
  81. package/dist/utils/hash.js +14 -0
  82. package/dist/utils/hash.js.map +1 -0
  83. package/dist/utils/typography.d.ts +21 -10
  84. package/dist/utils/typography.js +1 -1
  85. package/dist/utils/typography.js.map +1 -1
  86. package/dist/zero/babel.d.ts +7 -108
  87. package/dist/zero/babel.js +36 -12
  88. package/dist/zero/babel.js.map +1 -1
  89. package/docs/README.md +2 -2
  90. package/docs/adoption.md +5 -3
  91. package/docs/comparison.md +24 -25
  92. package/docs/configuration.md +69 -1
  93. package/docs/design-system.md +22 -10
  94. package/docs/dsl.md +3 -3
  95. package/docs/getting-started.md +10 -10
  96. package/docs/injector.md +9 -7
  97. package/docs/methodology.md +2 -2
  98. package/docs/{runtime.md → react-api.md} +17 -32
  99. package/docs/ssr.md +125 -39
  100. package/docs/tasty-static.md +14 -2
  101. package/package.json +9 -3
@@ -84,25 +84,37 @@ configure({
84
84
 
85
85
  ### Typography presets
86
86
 
87
- Use `generateTypographyTokens()` to create typography tokens from your own presets, then pass them to `configure({ tokens })`:
87
+ Pass typography presets directly to `configure()` they are converted to tokens automatically:
88
88
 
89
89
  ```tsx
90
- import { configure, generateTypographyTokens } from '@tenphi/tasty';
90
+ import { configure } from '@tenphi/tasty';
91
91
 
92
- const typographyTokens = generateTypographyTokens({
93
- h1: { fontSize: '2rem', lineHeight: '1.2', letterSpacing: '-0.02em', fontWeight: 700 },
94
- t2: { fontSize: '0.875rem', lineHeight: '1.5', letterSpacing: 'normal', fontWeight: 400 },
92
+ configure({
93
+ presets: {
94
+ h1: { fontSize: '2rem', lineHeight: '1.2', letterSpacing: '-0.02em', fontWeight: 700 },
95
+ t2: { fontSize: '0.875rem', lineHeight: '1.5', letterSpacing: 'normal', fontWeight: 400 },
96
+ },
95
97
  });
98
+ ```
99
+
100
+ Preset values support state maps for responsive or theme-aware typography:
96
101
 
102
+ ```tsx
97
103
  configure({
98
- tokens: {
99
- ...typographyTokens,
104
+ presets: {
105
+ t2: {
106
+ fontSize: '0.875rem',
107
+ lineHeight: '1.5',
108
+ fontWeight: { '': 400, '@dark': 300 },
109
+ },
100
110
  },
101
111
  });
102
112
  ```
103
113
 
104
114
  Then use `preset: 'h1'` or `preset: 't2'` in any component's styles.
105
115
 
116
+ > You can also call `generateTypographyTokens()` manually and spread the result into `tokens` for more control — `presets` is just a shorthand.
117
+
106
118
  ### Registering brand fonts
107
119
 
108
120
  Register your design system's custom fonts via `configure({ fontFace })` so every component can reference them:
@@ -334,7 +346,7 @@ Usage:
334
346
 
335
347
  Sub-elements share the root component's state context by default. A `disabled` modifier on `<Card>` affects `Title`, `Content`, and `Footer` styles automatically — no prop drilling. For the full mental model, see [Methodology — Component architecture](methodology.md#component-architecture-root--sub-elements).
336
348
 
337
- For sub-element syntax details (selector affix `$`, `@own()`, `elements` config), see [Runtime API — Sub-element Styling](runtime.md#sub-element-styling).
349
+ For sub-element syntax details (selector affix `$`, `@own()`, `elements` config), see [React API — Sub-element Styling](react-api.md#sub-element-styling).
338
350
 
339
351
  ---
340
352
 
@@ -404,7 +416,7 @@ ds/
404
416
  index.ts # Recipe definitions (imported by config.ts)
405
417
  tokens/
406
418
  colors.ts # Color token definitions
407
- typography.ts # Typography presets via generateTypographyTokens()
419
+ typography.ts # Typography presets for configure({ presets })
408
420
  spacing.ts # Spacing token definitions
409
421
  index.ts # Public API: re-exports components + configure
410
422
  ```
@@ -418,7 +430,7 @@ The key principle: `config.ts` imports tokens and recipes, calls `configure()`,
418
430
  - **[Methodology](methodology.md)** — The recommended patterns for structuring Tasty components
419
431
  - **[Getting Started](getting-started.md)** — Installation, first component, tooling setup
420
432
  - **[Style DSL](dsl.md)** — State maps, tokens, units, extending semantics, keyframes, @property
421
- - **[Runtime API](runtime.md)** — `tasty()` factory, component props, variants, sub-elements, hooks
433
+ - **[React API](react-api.md)** — `tasty()` factory, component props, variants, sub-elements, style functions
422
434
  - **[Configuration](configuration.md)** — Full `configure()` API: tokens, recipes, custom units, style handlers
423
435
  - **[Adoption Guide](adoption.md)** — Who should adopt Tasty, incremental phases, what changes for product engineers
424
436
  - **[Style Properties](styles.md)** — Complete reference for all enhanced style properties
package/docs/dsl.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  This is the Tasty style language reference — the value syntax, state mappings, tokens, units, extending semantics, and special declarations that apply to both runtime `tasty()` and build-time `tastyStatic()`.
4
4
 
5
- For the runtime React API (`tasty()`, hooks, component props), see [Runtime API](runtime.md). For all enhanced style properties, see [Style Properties](styles.md). For global configuration, see [Configuration](configuration.md).
5
+ For the runtime React API (`tasty()`, hooks, component props), see [React API](react-api.md). For all enhanced style properties, see [Style Properties](styles.md). For global configuration, see [Configuration](configuration.md).
6
6
 
7
7
  ---
8
8
 
@@ -107,7 +107,7 @@ mods={{ hovered: true, theme: 'danger' }}
107
107
  // → data-hovered="" data-theme="danger"
108
108
  ```
109
109
 
110
- Modifiers can also be exposed as top-level component props via `modProps` — see [Runtime — Mod Props](runtime.md#mod-props).
110
+ Modifiers can also be exposed as top-level component props via `modProps` — see [Runtime — Mod Props](react-api.md#mod-props).
111
111
 
112
112
  ---
113
113
 
@@ -681,7 +681,7 @@ For a complete reference of all enhanced style properties — syntax, values, mo
681
681
 
682
682
  ## Learn more
683
683
 
684
- - **[Runtime API](runtime.md)** — `tasty()` factory, component props, variants, sub-elements, hooks
684
+ - **[React API](react-api.md)** — `tasty()` factory, component props, variants, sub-elements, style functions
685
685
  - **[Methodology](methodology.md)** — Recommended patterns: root + sub-elements, styleProps, tokens, wrapping
686
686
  - **[Configuration](configuration.md)** — Tokens, recipes, custom units, style handlers, TypeScript extensions
687
687
  - **[Style Properties](styles.md)** — Complete reference for all enhanced style properties
@@ -1,6 +1,6 @@
1
1
  # Getting Started
2
2
 
3
- This guide walks you from zero to a working Tasty component, then through the optional shared configuration and tooling layers. It is the right starting point when you already want to try Tasty in code. If you are still deciding whether Tasty fits your team, start with [Comparison](comparison.md) and [Adoption Guide](adoption.md) first. For a feature overview, see the [README](../README.md). For the full style language reference, see the [Style DSL](dsl.md). For the React API, see the [Runtime API](runtime.md). For the rest of the docs by role or task, see the [Docs Hub](README.md).
3
+ This guide walks you from zero to a working Tasty component, then through the optional shared configuration and tooling layers. It is the right starting point when you already want to try Tasty in code. If you are still deciding whether Tasty fits your team, start with [Comparison](comparison.md) and [Adoption Guide](adoption.md) first. For a feature overview, see the [README](../README.md). For the full style language reference, see the [Style DSL](dsl.md). For the React API, see the [React API](react-api.md). For the rest of the docs by role or task, see the [Docs Hub](README.md).
4
4
 
5
5
  ---
6
6
 
@@ -179,19 +179,19 @@ export default [
179
179
 
180
180
  ## Choosing a rendering mode
181
181
 
182
- Tasty has two styling approaches. Pick the one that fits your use case, then decide whether your runtime setup also needs server rendering support:
182
+ `tasty()` is the default for all React apps. All `tasty()` components and style functions are hook-free and work as React Server Components without `'use client'`. In server-only contexts, they produce zero client JavaScript with the full feature set.
183
183
 
184
184
  | Approach | Entry point | Best for | Trade-off |
185
185
  |------|-------------|----------|-----------|
186
- | **Runtime** | `tasty()` from `@tenphi/tasty` | Interactive apps with reusable stateful components, design systems | CSS generated at runtime; full feature set (styleProps, sub-elements, variants) |
187
- | **Zero-runtime** | `tastyStatic()` from `@tenphi/tasty/static` | Static sites, landing pages, SSG | Zero JS overhead; requires Babel plugin; no dynamic props |
186
+ | **Runtime (default)** | `tasty()` from `@tenphi/tasty` | All React apps server-rendered by default, zero client JS until you need interactivity | Full feature set (styleProps, sub-elements, variants); CSS computed during rendering |
187
+ | **Runtime + SSR integration** | Add `@tenphi/tasty/ssr/*` | Apps with client-side hydration (Next.js client components, Astro islands) | Adds CSS batching, deduplication, FOUC prevention, and client cache hydration |
188
+ | **Zero-runtime** | `tastyStatic()` from `@tenphi/tasty/static` | Non-React frameworks or build-time extraction without React | Requires Babel plugin; no `styleProps` or runtime-only APIs |
188
189
 
189
- Both share the same DSL, tokens, units, and state mappings.
190
+ Both `tasty()` and `tastyStatic()` share the same DSL, tokens, units, and state mappings.
190
191
 
191
- - Runtime is the default and requires no extra setup beyond `@tenphi/tasty`.
192
- - If your framework can execute runtime code during server rendering, add SSR support on top of runtime with `@tenphi/tasty/ssr/next`, `@tenphi/tasty/ssr/astro`, or the core SSR API. This still uses `tasty()`; it just collects CSS on the server and hydrates the cache on the client.
193
- - Zero-runtime requires the Babel plugin and additional peer dependencies. See [Zero Runtime (tastyStatic)](tasty-static.md).
194
- - SSR works with existing `tasty()` components — wrap your app with a registry, middleware, or collector. See [Server-Side Rendering](ssr.md).
192
+ - **Runtime** is the default and requires no extra setup beyond `@tenphi/tasty`. In server-only contexts (Next.js RSC, Astro without `client:*` directives, SSG), `tasty()` produces static HTML + CSS with zero client JavaScript — the same end result as `tastyStatic()` but with the full feature set. For example, `tasty()` + `tastyIntegration()` in Astro without islands gives you the complete API with zero JS shipped.
193
+ - **SSR integration** is only needed when your app also has client-side rendering. Add `@tenphi/tasty/ssr/next`, `@tenphi/tasty/ssr/astro`, or the core SSR API to get CSS deduplication and cache hydration. See [Server-Side Rendering](ssr.md).
194
+ - **Zero-runtime** requires the Babel plugin and additional peer dependencies. Use it when you need build-time extraction without a React runtime. See [Zero Runtime (tastyStatic)](tasty-static.md).
195
195
 
196
196
  ---
197
197
 
@@ -200,7 +200,7 @@ Both share the same DSL, tokens, units, and state mappings.
200
200
  - **[Docs Hub](README.md)** — Pick the next guide by role, styling approach, or task
201
201
  - **[Methodology](methodology.md)** — The recommended patterns for structuring Tasty components: sub-elements, styleProps, tokens, extension
202
202
  - **[Style DSL](dsl.md)** — State maps, tokens, units, extending semantics, keyframes, @property
203
- - **[Runtime API](runtime.md)** — `tasty()` factory, component props, variants, sub-elements, hooks
203
+ - **[React API](react-api.md)** — `tasty()` factory, component props, variants, sub-elements, style functions
204
204
  - **[Building a Design System](design-system.md)** — Practical guide to building a DS layer with Tasty: tokens, recipes, primitives, compound components
205
205
  - **[Adoption Guide](adoption.md)** — Roll out Tasty inside an existing design system or platform team
206
206
  - **[Comparison](comparison.md)** — Evaluate Tasty against other styling systems
package/docs/injector.md CHANGED
@@ -115,11 +115,13 @@ dispose();
115
115
 
116
116
  ### `useRawCSS(css, options?)` or `useRawCSS(factory, deps, options?)`
117
117
 
118
- React hook for injecting raw CSS. Uses `useInsertionEffect` for proper timing and cleanup.
118
+ Inject raw CSS without parsing. Hook-free works in client components, SSR, and React Server Components.
119
119
 
120
120
  Supports two overloads:
121
- - **Static CSS**: `useRawCSS(cssString, options?)`
122
- - **Factory function**: `useRawCSS(() => cssString, deps, options?)` - re-evaluates when deps change (like `useMemo`)
121
+ - **Static CSS**: `useRawCSS(cssString, options?)` — content-based deduplication
122
+ - **Factory function**: `useRawCSS(() => cssString, deps, options?)` factory called on every invocation, dedup handled internally
123
+
124
+ Use the `id` option for update tracking — when the CSS changes for the same id, the previous injection is replaced:
123
125
 
124
126
  ```tsx
125
127
  import { useRawCSS } from '@tenphi/tasty';
@@ -132,7 +134,7 @@ function GlobalReset() {
132
134
  return null;
133
135
  }
134
136
 
135
- // Dynamic CSS with factory function (like useMemo)
137
+ // Dynamic CSS with factory function and update tracking
136
138
  function ThemeStyles({ theme }: { theme: 'dark' | 'light' }) {
137
139
  useRawCSS(() => `
138
140
  body {
@@ -140,7 +142,7 @@ function ThemeStyles({ theme }: { theme: 'dark' | 'light' }) {
140
142
  background: ${theme === 'dark' ? '#000' : '#fff'};
141
143
  color: ${theme === 'dark' ? '#fff' : '#000'};
142
144
  }
143
- `, [theme]);
145
+ `, [theme], { id: 'theme-body' });
144
146
 
145
147
  return null;
146
148
  }
@@ -525,7 +527,7 @@ const StyledButton = tasty({
525
527
  // 4. dispose() is called when component unmounts
526
528
  ```
527
529
 
528
- For most development, you'll use the [Runtime API](./runtime.md) rather than the injector directly. The injector provides the high-performance foundation that makes Tasty's declarative styling possible.
530
+ For most development, you'll use the [React API](./react-api.md) rather than the injector directly. The injector provides the high-performance foundation that makes Tasty's declarative styling possible.
529
531
 
530
532
  ---
531
533
 
@@ -539,4 +541,4 @@ Direct injector usage is recommended for:
539
541
  - **Performance-critical scenarios** where you need direct control
540
542
  - **Testing utilities** that need to inject or extract CSS
541
543
 
542
- For regular component styling, prefer the [`tasty()` API](./runtime.md) which provides a more developer-friendly interface.
544
+ For regular component styling, prefer the [`tasty()` API](./react-api.md) which provides a more developer-friendly interface.
@@ -214,7 +214,7 @@ The array form is simpler but types all values as `ModValue`:
214
214
  modProps: ['isLoading', 'isSelected'] as const,
215
215
  ```
216
216
 
217
- For the full API reference, see [Runtime — Mod Props](runtime.md#mod-props).
217
+ For the full API reference, see [Runtime — Mod Props](react-api.md#mod-props).
218
218
 
219
219
  ---
220
220
 
@@ -610,7 +610,7 @@ The `elements` prop gives you typed sub-components with automatic `data-element`
610
610
  - **[Getting Started](getting-started.md)** — Installation, first component, tooling setup
611
611
  - **[Building a Design System](design-system.md)** — Practical guide to building a DS layer with Tasty
612
612
  - **[Style DSL](dsl.md)** — State maps, tokens, units, extending semantics, keyframes, @property
613
- - **[Runtime API](runtime.md)** — `tasty()` factory, component props, variants, sub-elements, hooks
613
+ - **[React API](react-api.md)** — `tasty()` factory, component props, variants, sub-elements, style functions
614
614
  - **[Configuration](configuration.md)** — Full `configure()` API: tokens, recipes, custom units, style handlers
615
615
  - **[Style Properties](styles.md)** — Complete reference for all enhanced style properties
616
616
  - **[Adoption Guide](adoption.md)** — Who should adopt Tasty, incremental phases, what changes for product engineers
@@ -1,6 +1,8 @@
1
- # Runtime API
1
+ # React API
2
2
 
3
- The React-specific `tasty()` component factory, component props, and hooks. `tasty()` components are hook-free and compatible with React Server Components no `'use client'` directive needed. For the shared style language (state maps, tokens, units, extending semantics), see [Style DSL](dsl.md). For global configuration, see [Configuration](configuration.md). For the broader docs map, see the [Docs Hub](README.md).
3
+ The React-specific `tasty()` component factory, component props, and style functions. All Tasty style functions — `tasty()` components, `useStyles()`, `useGlobalStyles()`, `useRawCSS()`, `useKeyframes()`, `useProperty()`, `useFontFace()`, and `useCounterStyle()` — are hook-free and compatible with React Server Components. No `'use client'` directive needed. For the shared style language (state maps, tokens, units, extending semantics), see [Style DSL](dsl.md). For global configuration, see [Configuration](configuration.md). For the broader docs map, see the [Docs Hub](README.md).
4
+
5
+ > **Note:** This file was previously named `runtime.md`. All functionality documented here works in both server and client contexts — "runtime" referred to style computation during React rendering, not to client-side JavaScript.
4
6
 
5
7
  ---
6
8
 
@@ -351,11 +353,15 @@ On the client, CSS is injected synchronously into the DOM (idempotent via the in
351
353
 
352
354
  ---
353
355
 
354
- ## Hooks
356
+ ## Style Functions
357
+
358
+ All style functions below are plain functions (not React hooks) and can be used in any environment: client components, SSR with a `ServerStyleCollector`, and React Server Components. They retain their `use` prefix for backward compatibility, but do not use any React hooks internally.
359
+
360
+ In server-only contexts (Next.js RSC without `'use client'`, Astro without `client:*` directives, SSG), components that use only Tasty style functions produce zero client JavaScript. Tasty never forces the `'use client'` boundary — that decision belongs to your component when it needs React interactivity (state, effects, event handlers).
355
361
 
356
362
  ### useStyles
357
363
 
358
- Generate a className from a style object. Thin wrapper around `computeStyles()` that adds React context-based SSR collector discovery for backward compatibility:
364
+ Generate a className from a style object. Thin wrapper around `computeStyles()`:
359
365
 
360
366
  ```tsx
361
367
  import { useStyles } from '@tenphi/tasty';
@@ -373,7 +379,7 @@ function MyComponent() {
373
379
 
374
380
  ### useGlobalStyles
375
381
 
376
- Inject global styles for a CSS selector:
382
+ Inject global styles for a CSS selector. Accepts an optional third argument with an `id` for update tracking — when the styles change, the previous injection is disposed and the new one is injected:
377
383
 
378
384
  ```tsx
379
385
  import { useGlobalStyles } from '@tenphi/tasty';
@@ -391,7 +397,7 @@ function ThemeStyles() {
391
397
 
392
398
  ### useRawCSS
393
399
 
394
- Inject raw CSS strings:
400
+ Inject raw CSS strings. Accepts an optional `id` in the options for update tracking — when the CSS changes for the same id, the previous injection is replaced:
395
401
 
396
402
  ```tsx
397
403
  import { useRawCSS } from '@tenphi/tasty';
@@ -425,7 +431,7 @@ function Spinner() {
425
431
  }
426
432
  ```
427
433
 
428
- `useKeyframes()` also supports a factory function with dependencies:
434
+ `useKeyframes()` also supports a factory function. The deps array is accepted for backward compatibility but the factory is called on every invocation — deduplication is handled internally by content hash:
429
435
 
430
436
  ```tsx
431
437
  function Pulse({ scale }: { scale: number }) {
@@ -521,43 +527,22 @@ function EmojiList() {
521
527
  }
522
528
  ```
523
529
 
524
- Factory form with dependencies:
525
-
526
- ```tsx
527
- function DynamicList({ marker }: { marker: string }) {
528
- const styleName = useCounterStyle(
529
- () => ({
530
- system: 'cyclic',
531
- symbols: `"${marker}"`,
532
- suffix: '" "',
533
- }),
534
- [marker],
535
- );
536
-
537
- return <ol style={{ listStyleType: styleName }}>...</ol>;
538
- }
539
- ```
540
-
541
- Signatures:
530
+ Signature:
542
531
 
543
532
  ```ts
544
533
  function useCounterStyle(
545
534
  descriptors: CounterStyleDescriptors,
546
535
  options?: { name?: string; root?: Document | ShadowRoot },
547
536
  ): string;
548
-
549
- function useCounterStyle(
550
- factory: () => CounterStyleDescriptors,
551
- deps: readonly unknown[],
552
- options?: { name?: string; root?: Document | ShadowRoot },
553
- ): string;
554
537
  ```
555
538
 
556
539
  ### Troubleshooting
557
540
 
558
541
  - Styles are not updating: make sure `configure()` runs before first render, and verify the generated class name or global rule with [Debug Utilities](debug.md).
559
- - SSR output looks wrong: check the [SSR guide](ssr.md) for collector setup. `computeStyles()` discovers the SSR collector via `AsyncLocalStorage` or the global getter registered by `TastyRegistry`.
542
+ - SSR output looks wrong: check the [SSR guide](ssr.md) for collector setup. All style functions discover the SSR collector via `AsyncLocalStorage` or the global getter registered by `TastyRegistry`.
560
543
  - Animation/custom property issues: prefer `useKeyframes()` and `useProperty()` over raw CSS when you want Tasty to manage injection and SSR collection for you.
544
+ - For dynamic styles that change over the component lifecycle, use the `id` option in `useGlobalStyles()` and `useRawCSS()` to enable update tracking.
545
+ - RSC inline mode: CSS accumulated by standalone style functions (`useGlobalStyles`, `useRawCSS`, etc.) is flushed into inline `<style>` tags by the next `tasty()` component in the render tree. If your page uses only standalone style functions without any `tasty()` component, the CSS will not be emitted. Ensure at least one `tasty()` component is present in each RSC render tree.
561
546
 
562
547
  ---
563
548
 
package/docs/ssr.md CHANGED
@@ -18,7 +18,7 @@ The Astro integration (`@tenphi/tasty/ssr/astro`) has no additional dependencies
18
18
 
19
19
  ## How It Works
20
20
 
21
- `tasty()` components are hook-free and use `computeStyles()` internally — a synchronous, framework-agnostic function. On the server, `computeStyles()` detects a `ServerStyleCollector` (via `AsyncLocalStorage` or an explicit option) and collects CSS into it instead of trying to access the DOM. On the client, CSS is injected synchronously into the DOM during render; the injector's content-based cache makes this idempotent. The collector accumulates all styles, serializes them as `<style>` tags and a cache state script in the HTML. On the client, `hydrateTastyCache()` pre-populates the injector cache so that `computeStyles()` skips the rendering pipeline entirely during hydration.
21
+ `tasty()` components are hook-free and use `computeStyles()` internally — a synchronous, framework-agnostic function. On the server, `computeStyles()` discovers a `ServerStyleCollector` via a registered getter (module-level for Next.js, `globalThis` for Astro/generic frameworks using `AsyncLocalStorage`) and collects CSS into it instead of trying to access the DOM. On the client, CSS is injected synchronously into the DOM during render; the injector's content-based cache makes this idempotent. The collector accumulates all styles, serializes them as `<style>` tags and a cache state script in the HTML. On the client, `hydrateTastyCache()` pre-populates the injector cache so that `computeStyles()` skips the rendering pipeline entirely during hydration.
22
22
 
23
23
  ```
24
24
  Server Client
@@ -83,14 +83,20 @@ That's it. All `tasty()` components inside the tree automatically get SSR suppor
83
83
  ### How it works
84
84
 
85
85
  - `TastyRegistry` is a `'use client'` component, but Next.js still server-renders it on initial page load. The `'use client'` boundary is required solely to access `useServerInsertedHTML` — **not** because `tasty()` components need the client.
86
- - During SSR, `TastyRegistry` creates a `ServerStyleCollector` and registers it via a module-level global getter. All style computationwhether from `tasty()` components, `computeStyles()`, `useStyles()`, or other hooks like `useGlobalStyles()` — discovers the collector through this single global getter. No React context is involved.
86
+ - During SSR, `TastyRegistry` creates a `ServerStyleCollector` and registers it via a module-level getter (not `globalThis` — this avoids leaking between Next.js's separate RSC and SSR module graphs). It also wraps children in a React context provider so that hooks inside the SSR tree can discover the collector. All style functions — `tasty()` components, `computeStyles()`, `useStyles()`, `useGlobalStyles()`, `useRawCSS()`, `useKeyframes()`, `useProperty()`, `useFontFace()`, and `useCounterStyle()`discover the collector through the module-level getter or context provider.
87
87
  - `TastyRegistry` uses `useServerInsertedHTML` to flush collected CSS into the HTML stream as `<style data-tasty-ssr>` tags. This is fully streaming-compatible — styles are injected alongside each Suspense boundary as it resolves.
88
- - A companion `<script>` tag transfers the `cacheKey → className` mapping to the client.
89
- - When the module loads on the client, `hydrateTastyCache()` runs automatically and pre-populates the injector cache. During hydration, `computeStyles()` hits the cache and skips the entire pipeline.
88
+ - A companion inline `<script>` tag merges the `cacheKey → className` mapping into `window.__TASTY_SSR_CACHE__` for each flush. This streaming-friendly approach accumulates cache entries incrementally as Suspense boundaries resolve.
89
+ - When the `@tenphi/tasty/ssr/next` module loads on the client, `hydrateTastyCache()` runs automatically from `window.__TASTY_SSR_CACHE__` and pre-populates the injector cache. During hydration, `computeStyles()` hits the cache and skips the entire pipeline.
90
90
 
91
- ### Using tasty() in Server Components
91
+ ### Using Tasty in Server Components
92
92
 
93
- `tasty()` components are hook-free and do not require `'use client'`. They can be used directly in React Server Components. Dynamic `styleProps` like `<Grid flow="column">` work normally in server components. During SSR, `computeStyles()` discovers the collector via the same global getter registered by `TastyRegistry` — no React context or client boundary needed for this path.
93
+ All Tasty style functions are hook-free and do not require `'use client'`. They can be used directly in React Server Components:
94
+
95
+ - `tasty()` components — dynamic `styleProps` like `<Grid flow="column">` work normally
96
+ - `useStyles()`, `useGlobalStyles()`, `useRawCSS()` — inject styles by class or selector
97
+ - `useKeyframes()`, `useProperty()`, `useFontFace()`, `useCounterStyle()` — inject ancillary CSS rules
98
+
99
+ During SSR, all functions discover the collector via the same global getter registered by `TastyRegistry` — no React context or client boundary needed. In RSC mode without a collector (e.g., Astro zero-setup), CSS is accumulated in a per-request cache and flushed into an inline `<style>` tag by the next `tasty()` component in the tree. Ensure at least one `tasty()` component is present in every RSC render tree — standalone style functions alone cannot emit their CSS without a `tasty()` component to trigger the flush.
94
100
 
95
101
  ### Options
96
102
 
@@ -116,18 +122,17 @@ The nonce is automatically applied to all `<style>` and `<script>` tags injected
116
122
 
117
123
  ## Astro
118
124
 
119
- ### 1. Add the middleware
125
+ Tasty offers three levels of Astro integration. Choose the one that matches your needs:
120
126
 
121
- Create or update your Astro middleware:
127
+ | Setup | Config needed | Deduplication | Hooks work | Client JS |
128
+ |---|---|---|---|---|
129
+ | Zero setup | None | Per render tree | Yes (within each tree) | None |
130
+ | `tastyIntegration({ islands: false })` | One line | Cross-tree | Yes | None |
131
+ | `tastyIntegration()` | One line | Cross-tree | Yes | Auto-hydration |
122
132
 
123
- ```ts
124
- // src/middleware.ts
125
- import { tastyMiddleware } from '@tenphi/tasty/ssr/astro';
126
-
127
- export const onRequest = tastyMiddleware();
128
- ```
133
+ ### Zero setup (static pages)
129
134
 
130
- ### 2. Use tasty() components as normal
135
+ `tasty()` components work in Astro with **no configuration**. Each component emits its own inline `<style>` tag during server rendering via the RSC inline path. Just import and use:
131
136
 
132
137
  ```tsx
133
138
  // src/components/Card.tsx
@@ -153,51 +158,118 @@ import Card from '../components/Card.tsx';
153
158
 
154
159
  <html>
155
160
  <body>
156
- <Card>Static card styles collected by middleware</Card>
157
- <Card client:load>Island card — styles hydrated on client</Card>
161
+ <Card>Styled with zero setup</Card>
158
162
  </body>
159
163
  </html>
160
164
  ```
161
165
 
162
- ### How it works
166
+ **Trade-offs**: Styles are deduplicated within each React render tree, but Astro renders separate component trees independently, so shared CSS (tokens, `@property` rules) may appear more than once. All style functions (`useGlobalStyles`, `useRawCSS`, `useKeyframes`, `useProperty`, `useFontFace`, `useCounterStyle`) work in zero-setup mode — their CSS is accumulated in the RSC cache and flushed by the next `tasty()` component in the tree.
163
167
 
164
- Astro's `@astrojs/react` renderer calls `renderToString()` for each React component without wrapping the tree in a provider. The middleware uses `AsyncLocalStorage` to make the collector available to all `computeStyles()` calls within the request.
168
+ Best for quick prototyping, small static sites, or trying Tasty out in Astro.
165
169
 
166
- - **Static components** (no `client:*`): Styles are collected during `renderToString` and injected into `</head>`. No JavaScript is shipped for these components.
167
- - **Islands** (`client:load`, `client:visible`, etc.): Styles are collected during SSR the same way. On the client, importing `@tenphi/tasty/ssr/astro` auto-hydrates the cache from `<script data-tasty-cache>`. The island's `computeStyles()` calls hit the cache during hydration.
170
+ ### Astro Integration (recommended)
168
171
 
169
- ### Client-side hydration for islands
172
+ For production use, add `tastyIntegration()` to your Astro config. This registers middleware automatically and, by default, injects client-side hydration for islands.
170
173
 
171
- The `@tenphi/tasty/ssr/astro` module auto-hydrates when imported on the client. To ensure the cache is warm before any island renders, import it in a shared entry point or in each island component:
174
+ #### With islands (default)
172
175
 
173
- ```tsx
174
- // src/components/MyIsland.tsx
175
- import '@tenphi/tasty/ssr/astro'; // auto-hydrates cache on import
176
- import { tasty } from '@tenphi/tasty';
176
+ ```ts
177
+ // astro.config.mjs
178
+ import { defineConfig } from 'astro/config';
179
+ import react from '@astrojs/react';
180
+ import { tastyIntegration } from '@tenphi/tasty/ssr/astro';
177
181
 
178
- const MyIsland = tasty({
179
- styles: { padding: '2x', fill: '#blue' },
182
+ export default defineConfig({
183
+ integrations: [react(), tastyIntegration()],
180
184
  });
185
+ ```
186
+
187
+ This gives you:
188
+
189
+ - A `ServerStyleCollector` per request via `AsyncLocalStorage`, deduplicating CSS across all React trees on the page
190
+ - A single consolidated `<style data-tasty-ssr>` injected into `</head>`
191
+ - A `<script data-tasty-cache>` tag with the `cacheKey -> className` map for client hydration
192
+ - Auto-injected client hydration script (via `injectScript('before-hydration')`) so islands skip the style pipeline during hydration -- no need to import anything manually in each island component
181
193
 
182
- export default MyIsland;
194
+ All style functions (`useGlobalStyles`, `useRawCSS`, `useKeyframes`, `useProperty`, `useFontFace`, `useCounterStyle`) work on the server.
195
+
196
+ ```astro
197
+ ---
198
+ // src/pages/index.astro
199
+ import Card from '../components/Card.tsx';
200
+ import Interactive from '../components/Interactive.tsx';
201
+ ---
202
+
203
+ <html>
204
+ <body>
205
+ <Card>Static -- styles in <style data-tasty-ssr></Card>
206
+ <Interactive client:load>Island -- cache hydrated automatically</Interactive>
207
+ </body>
208
+ </html>
183
209
  ```
184
210
 
185
- ### Options
211
+ #### Static only (no client JS)
212
+
213
+ If your site has no `client:*` islands, skip the hydration script and cache transfer:
214
+
215
+ ```ts
216
+ // astro.config.mjs
217
+ import { defineConfig } from 'astro/config';
218
+ import react from '@astrojs/react';
219
+ import { tastyIntegration } from '@tenphi/tasty/ssr/astro';
220
+
221
+ export default defineConfig({
222
+ integrations: [react(), tastyIntegration({ islands: false })],
223
+ });
224
+ ```
225
+
226
+ This gives the same middleware deduplication and hook support, but ships zero client-side JavaScript. No `<script data-tasty-cache>` is emitted.
227
+
228
+ ### Manual middleware (advanced)
229
+
230
+ If you need to compose Tasty's middleware with other middleware (e.g., via `sequence()`), use `tastyMiddleware()` directly:
231
+
232
+ ```ts
233
+ // src/middleware.ts
234
+ import { sequence } from 'astro:middleware';
235
+ import { tastyMiddleware } from '@tenphi/tasty/ssr/astro';
236
+
237
+ export const onRequest = sequence(
238
+ tastyMiddleware(),
239
+ myOtherMiddleware,
240
+ );
241
+ ```
242
+
243
+ For island hydration with manual middleware, import the client module in a shared entry point or in each island:
244
+
245
+ ```tsx
246
+ import '@tenphi/tasty/ssr/astro-client';
247
+ ```
248
+
249
+ #### Options
186
250
 
187
251
  ```ts
188
- // Skip cache state transfer
252
+ // Skip cache state transfer (static-only, no islands)
189
253
  export const onRequest = tastyMiddleware({ transferCache: false });
190
254
  ```
191
255
 
256
+ ### How it works
257
+
258
+ Astro's `@astrojs/react` renderer calls `renderToString()` for each React component without wrapping the tree in a provider. The middleware creates a `ServerStyleCollector` and binds it via `AsyncLocalStorage`. All `computeStyles()` calls within the request discover this collector automatically.
259
+
260
+ - **Static components** (no `client:*`): Styles are collected during `renderToString` and injected into `</head>` as a single `<style>` tag. No JavaScript is shipped.
261
+ - **Islands** (`client:load`, `client:visible`, etc.): Styles are collected during SSR the same way. On the client, the hydration script (auto-injected by `tastyIntegration()` or manually via `@tenphi/tasty/ssr/astro-client`) reads the cache state from `<script data-tasty-cache>` and pre-populates the injector. The island's `computeStyles()` calls hit the cache during hydration.
262
+ - The middleware reads the full response body, then injects the collected CSS into `</head>` before sending the final HTML.
263
+
192
264
  ### CSP nonce
193
265
 
194
- Same as Next.js -- call `configure({ nonce: '...' })` before any rendering happens. The middleware reads the nonce and applies it to injected tags.
266
+ Call `configure({ nonce: '...' })` before any rendering happens. The middleware reads the nonce and applies it to injected `<style>` and `<script>` tags.
195
267
 
196
268
  ---
197
269
 
198
270
  ## Generic Framework Integration
199
271
 
200
- Any React-based framework can integrate using `runWithCollector`, which binds a `ServerStyleCollector` to the current async context via `AsyncLocalStorage`. All `computeStyles()` and hook calls within the render automatically discover the collector.
272
+ Any React-based framework can integrate using `runWithCollector`, which binds a `ServerStyleCollector` to the current async context via `AsyncLocalStorage`. All style function calls within the render automatically discover the collector.
201
273
 
202
274
  ```tsx
203
275
  import {
@@ -279,7 +351,8 @@ const stream = await runWithCollector(collector, () =>
279
351
  |---|---|
280
352
  | `@tenphi/tasty/ssr` | Core SSR API: `ServerStyleCollector`, `runWithCollector`, `hydrateTastyCache` |
281
353
  | `@tenphi/tasty/ssr/next` | Next.js App Router: `TastyRegistry` component |
282
- | `@tenphi/tasty/ssr/astro` | Astro: `tastyMiddleware`, auto-hydration on import |
354
+ | `@tenphi/tasty/ssr/astro` | Astro: `tastyIntegration`, `tastyMiddleware` |
355
+ | `@tenphi/tasty/ssr/astro-client` | Astro: client-side cache hydration (auto-injected by integration, or import manually) |
283
356
 
284
357
  ### `ServerStyleCollector`
285
358
 
@@ -290,9 +363,14 @@ Server-safe style collector. One instance per request.
290
363
  | `allocateClassName(cacheKey)` | Allocate a sequential class name (`t0`, `t1`, ...) for a cache key. Returns `{ className, isNewAllocation }`. |
291
364
  | `collectChunk(cacheKey, className, rules)` | Record CSS rules for a chunk. Deduplicated by `cacheKey`. |
292
365
  | `collectKeyframes(name, css)` | Record a `@keyframes` rule. Deduplicated by name. |
366
+ | `allocateKeyframeName(providedName?)` | Allocate a keyframe name. Returns `providedName` if given, otherwise generates one (`k0`, `k1`, ...). |
293
367
  | `collectProperty(name, css)` | Record a `@property` rule. Deduplicated by name. |
294
368
  | `collectFontFace(key, css)` | Record a `@font-face` rule. Deduplicated by content hash. |
295
369
  | `collectCounterStyle(name, css)` | Record a `@counter-style` rule. Deduplicated by name. |
370
+ | `allocateCounterStyleName(providedName?)` | Allocate a counter-style name. Returns `providedName` if given, otherwise generates one (`cs0`, `cs1`, ...). |
371
+ | `collectGlobalStyles(key, css)` | Record global styles (from `useGlobalStyles`). Deduplicated by key. |
372
+ | `collectRawCSS(key, css)` | Record raw CSS text (from `useRawCSS`). Deduplicated by key. |
373
+ | `collectInternals()` | Collect internal `@property` rules, `:root` token defaults, `@font-face`, and `@counter-style` rules from the global config. Called automatically on first chunk collection; idempotent. |
296
374
  | `getCSS()` | Get all collected CSS as a single string. For non-streaming SSR. |
297
375
  | `flushCSS()` | Get only CSS collected since the last flush. For streaming SSR. |
298
376
  | `getCacheState()` | Serialize `{ entries: Record<cacheKey, className>, classCounter }` for client hydration. |
@@ -306,9 +384,17 @@ Next.js App Router component. Props:
306
384
  | `children` | `ReactNode` | required | Application tree |
307
385
  | `transferCache` | `boolean` | `true` | Embed cache state script for zero-cost hydration |
308
386
 
387
+ ### `tastyIntegration(options?)`
388
+
389
+ Astro integration factory. Registers middleware and optionally injects client hydration.
390
+
391
+ | Option | Type | Default | Description |
392
+ |---|---|---|---|
393
+ | `islands` | `boolean` | `true` | When `true`, injects client hydration script and enables `transferCache`. When `false`, no client JS is shipped. |
394
+
309
395
  ### `tastyMiddleware(options?)`
310
396
 
311
- Astro middleware factory. Options:
397
+ Astro middleware factory. Use for manual middleware composition.
312
398
 
313
399
  | Option | Type | Default | Description |
314
400
  |---|---|---|---|
@@ -320,7 +406,7 @@ Pre-populate the client injector cache. When called without arguments, reads fro
320
406
 
321
407
  ### `runWithCollector(collector, fn)`
322
408
 
323
- Run a function with a `ServerStyleCollector` bound to the current async context via `AsyncLocalStorage`. All `computeStyles()` and `useStyles()` calls within `fn` (and async continuations) will find this collector.
409
+ Run a function with a `ServerStyleCollector` bound to the current async context via `AsyncLocalStorage`. All style function calls within `fn` (and async continuations) — including `computeStyles()`, `useStyles()`, `useGlobalStyles()`, `useRawCSS()`, `useKeyframes()`, `useProperty()`, `useFontFace()`, and `useCounterStyle()` will find this collector.
324
410
 
325
411
  ---
326
412
 
@@ -328,11 +414,11 @@ Run a function with a `ServerStyleCollector` bound to the current async context
328
414
 
329
415
  ### Styles flash on page load (FOUC)
330
416
 
331
- The `TastyRegistry` or `tastyMiddleware` is missing. Ensure your layout wraps the app with `TastyRegistry` (Next.js) or the middleware is registered (Astro).
417
+ The `TastyRegistry` or `tastyIntegration` is missing. Ensure your layout wraps the app with `TastyRegistry` (Next.js) or that `tastyIntegration()` is in your Astro config (or `tastyMiddleware()` is registered manually).
332
418
 
333
419
  ### Hydration mismatch warnings
334
420
 
335
- Class names are deterministic for the same render order. If you see mismatches, ensure `hydrateTastyCache()` runs before React hydration. For Next.js, this is automatic. For Astro, import `@tenphi/tasty/ssr/astro` in your island components. For custom setups, call `hydrateTastyCache()` before `hydrateRoot()`.
421
+ Class names are deterministic for the same render order. If you see mismatches, ensure `hydrateTastyCache()` runs before React hydration. For Next.js, this is automatic. For Astro with `tastyIntegration()`, this is also automatic. For manual Astro middleware setups, import `@tenphi/tasty/ssr/astro-client` in your island components. For custom setups, call `hydrateTastyCache()` before `hydrateRoot()`.
336
422
 
337
423
  ### Styles duplicated after hydration
338
424
 
@@ -161,11 +161,23 @@ module.exports = {
161
161
  | `configFile` | `string` | — | Absolute path to a TS/JS module that default-exports a `TastyZeroConfig` object. JSON-serializable alternative to `config` — required for Turbopack. |
162
162
  | `config` | `TastyZeroConfig \| () => TastyZeroConfig` | `{}` | Inline config object or factory function. Takes precedence over `configFile`. |
163
163
  | `configDeps` | `string[]` | `[]` | Absolute file paths that affect config (for cache invalidation) |
164
- | `config.states` | `Record<string, string>` | `{}` | Predefined state aliases |
164
+ | `injectImport` | `boolean` | `true` | Replace `@tenphi/tasty/static` imports with an import of the generated CSS file. Set to `false` to manage CSS imports manually. |
165
+ | `config.states` | `Record<string, string>` | `{}` | Predefined state aliases (e.g. `{ '@mobile': '@media(w < 768px)' }`) |
165
166
  | `config.devMode` | `boolean` | `false` | Add source comments to CSS |
167
+ | `config.tokens` | `ConfigTokens` | — | Design tokens injected as CSS custom properties on `:root`. Values are parsed through the Tasty DSL. Supports state maps for responsive/themed tokens. |
168
+ | `config.replaceTokens` | `Record<string, string \| number>` | — | Parse-time token substitution. Keys use `$name` for custom properties and `#name` for color tokens. |
166
169
  | `config.recipes` | `Record<string, RecipeStyles>` | `{}` | Predefined style recipes |
170
+ | `config.keyframes` | `Record<string, KeyframesSteps>` | — | Global `@keyframes` definitions available to all `tastyStatic` calls |
167
171
  | `config.fontFace` | `Record<string, FontFaceInput>` | — | Global `@font-face` definitions |
168
172
  | `config.counterStyle` | `Record<string, CounterStyleDescriptors>` | — | Global `@counter-style` definitions |
173
+ | `config.units` | `Record<string, string \| UnitHandler>` | — | Custom units for the style parser (merged with built-ins). E.g. `{ em: 'em', vw: 'vw' }` |
174
+ | `config.funcs` | `Record<string, Function>` | — | Custom functions for the style parser (merged with existing) |
175
+ | `config.plugins` | `TastyPlugin[]` | — | Plugins that extend tasty with custom functions, units, states, and handlers |
176
+ | `config.handlers` | `Record<string, StyleHandlerDefinition>` | — | Custom style handlers that transform style properties into CSS declarations |
177
+ | `config.presets` | `Record<string, TypographyPreset>` | — | Typography presets — shorthand for `generateTypographyTokens()`. Generated tokens merge under explicit `tokens`. |
178
+ | `config.globalStyles` | `Record<string, Styles>` | — | Global Tasty styles keyed by CSS selector. Supports the full style syntax. |
179
+ | `config.autoPropertyTypes` | `boolean` | `true` | Automatically infer and register CSS `@property` declarations from values |
180
+ | `config.parserCacheSize` | `number` | `1000` | Parser LRU cache size. Larger values improve performance for builds with many unique style values |
169
181
 
170
182
  ---
171
183
 
@@ -516,5 +528,5 @@ const card = tastyStatic({
516
528
 
517
529
  - [Docs Hub](README.md) — Choose the right guide by task or rendering mode
518
530
  - [Style DSL](dsl.md) — State maps, tokens, units, extending semantics (shared by runtime and static)
519
- - [Runtime API](runtime.md) — Runtime styling: `tasty()` factory, component props, variants, sub-elements, hooks
531
+ - [React API](react-api.md) — Runtime styling: `tasty()` factory, component props, variants, sub-elements, style functions
520
532
  - [Configuration](configuration.md) — Global configuration: tokens, recipes, custom units, and style handlers