@tenphi/tasty 0.0.0-snapshot.056b911

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 (332) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +635 -0
  3. package/dist/_virtual/_rolldown/runtime.js +7 -0
  4. package/dist/chunks/cacheKey.d.ts +1 -0
  5. package/dist/chunks/cacheKey.js +77 -0
  6. package/dist/chunks/cacheKey.js.map +1 -0
  7. package/dist/chunks/definitions.d.ts +37 -0
  8. package/dist/chunks/definitions.js +258 -0
  9. package/dist/chunks/definitions.js.map +1 -0
  10. package/dist/chunks/index.d.ts +1 -0
  11. package/dist/chunks/renderChunk.d.ts +1 -0
  12. package/dist/chunks/renderChunk.js +59 -0
  13. package/dist/chunks/renderChunk.js.map +1 -0
  14. package/dist/compute-styles.d.ts +31 -0
  15. package/dist/compute-styles.js +335 -0
  16. package/dist/compute-styles.js.map +1 -0
  17. package/dist/config.d.ts +409 -0
  18. package/dist/config.js +584 -0
  19. package/dist/config.js.map +1 -0
  20. package/dist/core/index.d.ts +34 -0
  21. package/dist/core/index.js +27 -0
  22. package/dist/counter-style/index.js +51 -0
  23. package/dist/counter-style/index.js.map +1 -0
  24. package/dist/debug.d.ts +89 -0
  25. package/dist/debug.js +453 -0
  26. package/dist/debug.js.map +1 -0
  27. package/dist/font-face/index.js +63 -0
  28. package/dist/font-face/index.js.map +1 -0
  29. package/dist/hooks/index.d.ts +7 -0
  30. package/dist/hooks/useCounterStyle.d.ts +36 -0
  31. package/dist/hooks/useCounterStyle.js +64 -0
  32. package/dist/hooks/useCounterStyle.js.map +1 -0
  33. package/dist/hooks/useFontFace.d.ts +45 -0
  34. package/dist/hooks/useFontFace.js +66 -0
  35. package/dist/hooks/useFontFace.js.map +1 -0
  36. package/dist/hooks/useGlobalStyles.d.ts +46 -0
  37. package/dist/hooks/useGlobalStyles.js +88 -0
  38. package/dist/hooks/useGlobalStyles.js.map +1 -0
  39. package/dist/hooks/useKeyframes.d.ts +58 -0
  40. package/dist/hooks/useKeyframes.js +54 -0
  41. package/dist/hooks/useKeyframes.js.map +1 -0
  42. package/dist/hooks/useProperty.d.ts +81 -0
  43. package/dist/hooks/useProperty.js +96 -0
  44. package/dist/hooks/useProperty.js.map +1 -0
  45. package/dist/hooks/useRawCSS.d.ts +22 -0
  46. package/dist/hooks/useRawCSS.js +103 -0
  47. package/dist/hooks/useRawCSS.js.map +1 -0
  48. package/dist/hooks/useStyles.d.ts +40 -0
  49. package/dist/hooks/useStyles.js +31 -0
  50. package/dist/hooks/useStyles.js.map +1 -0
  51. package/dist/index.d.ts +51 -0
  52. package/dist/index.js +36 -0
  53. package/dist/injector/index.d.ts +182 -0
  54. package/dist/injector/index.js +185 -0
  55. package/dist/injector/index.js.map +1 -0
  56. package/dist/injector/injector.d.ts +193 -0
  57. package/dist/injector/injector.js +564 -0
  58. package/dist/injector/injector.js.map +1 -0
  59. package/dist/injector/sheet-manager.d.ts +132 -0
  60. package/dist/injector/sheet-manager.js +698 -0
  61. package/dist/injector/sheet-manager.js.map +1 -0
  62. package/dist/injector/types.d.ts +228 -0
  63. package/dist/keyframes/index.js +206 -0
  64. package/dist/keyframes/index.js.map +1 -0
  65. package/dist/parser/classify.js +319 -0
  66. package/dist/parser/classify.js.map +1 -0
  67. package/dist/parser/const.js +60 -0
  68. package/dist/parser/const.js.map +1 -0
  69. package/dist/parser/lru.js +109 -0
  70. package/dist/parser/lru.js.map +1 -0
  71. package/dist/parser/parser.d.ts +25 -0
  72. package/dist/parser/parser.js +115 -0
  73. package/dist/parser/parser.js.map +1 -0
  74. package/dist/parser/tokenizer.js +69 -0
  75. package/dist/parser/tokenizer.js.map +1 -0
  76. package/dist/parser/types.d.ts +51 -0
  77. package/dist/parser/types.js +46 -0
  78. package/dist/parser/types.js.map +1 -0
  79. package/dist/pipeline/conditions.d.ts +134 -0
  80. package/dist/pipeline/conditions.js +406 -0
  81. package/dist/pipeline/conditions.js.map +1 -0
  82. package/dist/pipeline/exclusive.js +230 -0
  83. package/dist/pipeline/exclusive.js.map +1 -0
  84. package/dist/pipeline/index.d.ts +55 -0
  85. package/dist/pipeline/index.js +708 -0
  86. package/dist/pipeline/index.js.map +1 -0
  87. package/dist/pipeline/materialize.js +1103 -0
  88. package/dist/pipeline/materialize.js.map +1 -0
  89. package/dist/pipeline/parseStateKey.d.ts +15 -0
  90. package/dist/pipeline/parseStateKey.js +446 -0
  91. package/dist/pipeline/parseStateKey.js.map +1 -0
  92. package/dist/pipeline/simplify.js +515 -0
  93. package/dist/pipeline/simplify.js.map +1 -0
  94. package/dist/pipeline/warnings.js +18 -0
  95. package/dist/pipeline/warnings.js.map +1 -0
  96. package/dist/plugins/index.d.ts +2 -0
  97. package/dist/plugins/okhsl-plugin.d.ts +35 -0
  98. package/dist/plugins/okhsl-plugin.js +97 -0
  99. package/dist/plugins/okhsl-plugin.js.map +1 -0
  100. package/dist/plugins/types.d.ts +87 -0
  101. package/dist/properties/index.js +222 -0
  102. package/dist/properties/index.js.map +1 -0
  103. package/dist/properties/property-type-resolver.d.ts +24 -0
  104. package/dist/properties/property-type-resolver.js +90 -0
  105. package/dist/properties/property-type-resolver.js.map +1 -0
  106. package/dist/rsc-cache.js +81 -0
  107. package/dist/rsc-cache.js.map +1 -0
  108. package/dist/ssr/astro-client.d.ts +1 -0
  109. package/dist/ssr/astro-client.js +24 -0
  110. package/dist/ssr/astro-client.js.map +1 -0
  111. package/dist/ssr/astro-middleware.d.ts +15 -0
  112. package/dist/ssr/astro-middleware.js +19 -0
  113. package/dist/ssr/astro-middleware.js.map +1 -0
  114. package/dist/ssr/astro.d.ts +106 -0
  115. package/dist/ssr/astro.js +149 -0
  116. package/dist/ssr/astro.js.map +1 -0
  117. package/dist/ssr/async-storage.d.ts +17 -0
  118. package/dist/ssr/async-storage.js +44 -0
  119. package/dist/ssr/async-storage.js.map +1 -0
  120. package/dist/ssr/collect-auto-properties.js +58 -0
  121. package/dist/ssr/collect-auto-properties.js.map +1 -0
  122. package/dist/ssr/collector.d.ts +102 -0
  123. package/dist/ssr/collector.js +227 -0
  124. package/dist/ssr/collector.js.map +1 -0
  125. package/dist/ssr/context.js +16 -0
  126. package/dist/ssr/context.js.map +1 -0
  127. package/dist/ssr/format-global-rules.js +22 -0
  128. package/dist/ssr/format-global-rules.js.map +1 -0
  129. package/dist/ssr/format-keyframes.js +69 -0
  130. package/dist/ssr/format-keyframes.js.map +1 -0
  131. package/dist/ssr/format-property.js +49 -0
  132. package/dist/ssr/format-property.js.map +1 -0
  133. package/dist/ssr/format-rules.js +73 -0
  134. package/dist/ssr/format-rules.js.map +1 -0
  135. package/dist/ssr/hydrate.d.ts +22 -0
  136. package/dist/ssr/hydrate.js +49 -0
  137. package/dist/ssr/hydrate.js.map +1 -0
  138. package/dist/ssr/index.d.ts +4 -0
  139. package/dist/ssr/index.js +10 -0
  140. package/dist/ssr/index.js.map +1 -0
  141. package/dist/ssr/next.d.ts +45 -0
  142. package/dist/ssr/next.js +75 -0
  143. package/dist/ssr/next.js.map +1 -0
  144. package/dist/ssr/ssr-collector-ref.js +29 -0
  145. package/dist/ssr/ssr-collector-ref.js.map +1 -0
  146. package/dist/states/index.d.ts +49 -0
  147. package/dist/states/index.js +170 -0
  148. package/dist/states/index.js.map +1 -0
  149. package/dist/static/index.d.ts +5 -0
  150. package/dist/static/index.js +4 -0
  151. package/dist/static/inject.d.ts +5 -0
  152. package/dist/static/inject.js +17 -0
  153. package/dist/static/inject.js.map +1 -0
  154. package/dist/static/tastyStatic.d.ts +46 -0
  155. package/dist/static/tastyStatic.js +30 -0
  156. package/dist/static/tastyStatic.js.map +1 -0
  157. package/dist/static/types.d.ts +49 -0
  158. package/dist/static/types.js +24 -0
  159. package/dist/static/types.js.map +1 -0
  160. package/dist/styles/border.d.ts +25 -0
  161. package/dist/styles/border.js +120 -0
  162. package/dist/styles/border.js.map +1 -0
  163. package/dist/styles/color.d.ts +14 -0
  164. package/dist/styles/color.js +26 -0
  165. package/dist/styles/color.js.map +1 -0
  166. package/dist/styles/const.js +17 -0
  167. package/dist/styles/const.js.map +1 -0
  168. package/dist/styles/createStyle.js +79 -0
  169. package/dist/styles/createStyle.js.map +1 -0
  170. package/dist/styles/dimension.js +109 -0
  171. package/dist/styles/dimension.js.map +1 -0
  172. package/dist/styles/directional.js +133 -0
  173. package/dist/styles/directional.js.map +1 -0
  174. package/dist/styles/display.d.ts +30 -0
  175. package/dist/styles/display.js +73 -0
  176. package/dist/styles/display.js.map +1 -0
  177. package/dist/styles/fade.d.ts +15 -0
  178. package/dist/styles/fade.js +62 -0
  179. package/dist/styles/fade.js.map +1 -0
  180. package/dist/styles/fill.d.ts +42 -0
  181. package/dist/styles/fill.js +51 -0
  182. package/dist/styles/fill.js.map +1 -0
  183. package/dist/styles/flow.d.ts +16 -0
  184. package/dist/styles/flow.js +12 -0
  185. package/dist/styles/flow.js.map +1 -0
  186. package/dist/styles/gap.d.ts +31 -0
  187. package/dist/styles/gap.js +38 -0
  188. package/dist/styles/gap.js.map +1 -0
  189. package/dist/styles/height.d.ts +17 -0
  190. package/dist/styles/height.js +19 -0
  191. package/dist/styles/height.js.map +1 -0
  192. package/dist/styles/index.d.ts +1 -0
  193. package/dist/styles/index.js +8 -0
  194. package/dist/styles/index.js.map +1 -0
  195. package/dist/styles/inset.d.ts +24 -0
  196. package/dist/styles/inset.js +34 -0
  197. package/dist/styles/inset.js.map +1 -0
  198. package/dist/styles/list.d.ts +16 -0
  199. package/dist/styles/list.js +100 -0
  200. package/dist/styles/list.js.map +1 -0
  201. package/dist/styles/margin.d.ts +24 -0
  202. package/dist/styles/margin.js +32 -0
  203. package/dist/styles/margin.js.map +1 -0
  204. package/dist/styles/outline.d.ts +29 -0
  205. package/dist/styles/outline.js +55 -0
  206. package/dist/styles/outline.js.map +1 -0
  207. package/dist/styles/padding.d.ts +24 -0
  208. package/dist/styles/padding.js +32 -0
  209. package/dist/styles/padding.js.map +1 -0
  210. package/dist/styles/placement.d.ts +37 -0
  211. package/dist/styles/placement.js +74 -0
  212. package/dist/styles/placement.js.map +1 -0
  213. package/dist/styles/predefined.d.ts +71 -0
  214. package/dist/styles/predefined.js +237 -0
  215. package/dist/styles/predefined.js.map +1 -0
  216. package/dist/styles/preset.d.ts +52 -0
  217. package/dist/styles/preset.js +127 -0
  218. package/dist/styles/preset.js.map +1 -0
  219. package/dist/styles/radius.d.ts +12 -0
  220. package/dist/styles/radius.js +83 -0
  221. package/dist/styles/radius.js.map +1 -0
  222. package/dist/styles/scrollMargin.d.ts +24 -0
  223. package/dist/styles/scrollMargin.js +32 -0
  224. package/dist/styles/scrollMargin.js.map +1 -0
  225. package/dist/styles/scrollbar.d.ts +25 -0
  226. package/dist/styles/scrollbar.js +51 -0
  227. package/dist/styles/scrollbar.js.map +1 -0
  228. package/dist/styles/shadow.d.ts +14 -0
  229. package/dist/styles/shadow.js +25 -0
  230. package/dist/styles/shadow.js.map +1 -0
  231. package/dist/styles/shared.js +17 -0
  232. package/dist/styles/shared.js.map +1 -0
  233. package/dist/styles/transition.d.ts +14 -0
  234. package/dist/styles/transition.js +159 -0
  235. package/dist/styles/transition.js.map +1 -0
  236. package/dist/styles/types.d.ts +564 -0
  237. package/dist/styles/width.d.ts +17 -0
  238. package/dist/styles/width.js +19 -0
  239. package/dist/styles/width.js.map +1 -0
  240. package/dist/tasty.d.ts +134 -0
  241. package/dist/tasty.js +243 -0
  242. package/dist/tasty.js.map +1 -0
  243. package/dist/types.d.ts +184 -0
  244. package/dist/utils/cache-wrapper.js +21 -0
  245. package/dist/utils/cache-wrapper.js.map +1 -0
  246. package/dist/utils/case-converter.js +8 -0
  247. package/dist/utils/case-converter.js.map +1 -0
  248. package/dist/utils/color-math.d.ts +46 -0
  249. package/dist/utils/color-math.js +749 -0
  250. package/dist/utils/color-math.js.map +1 -0
  251. package/dist/utils/color-space.d.ts +5 -0
  252. package/dist/utils/color-space.js +228 -0
  253. package/dist/utils/color-space.js.map +1 -0
  254. package/dist/utils/colors.d.ts +5 -0
  255. package/dist/utils/colors.js +10 -0
  256. package/dist/utils/colors.js.map +1 -0
  257. package/dist/utils/css-types.d.ts +7 -0
  258. package/dist/utils/deps-equal.js +15 -0
  259. package/dist/utils/deps-equal.js.map +1 -0
  260. package/dist/utils/dotize.d.ts +26 -0
  261. package/dist/utils/dotize.js +122 -0
  262. package/dist/utils/dotize.js.map +1 -0
  263. package/dist/utils/filter-base-props.d.ts +15 -0
  264. package/dist/utils/filter-base-props.js +45 -0
  265. package/dist/utils/filter-base-props.js.map +1 -0
  266. package/dist/utils/get-display-name.d.ts +7 -0
  267. package/dist/utils/get-display-name.js +10 -0
  268. package/dist/utils/get-display-name.js.map +1 -0
  269. package/dist/utils/has-keys.js +13 -0
  270. package/dist/utils/has-keys.js.map +1 -0
  271. package/dist/utils/hash.js +14 -0
  272. package/dist/utils/hash.js.map +1 -0
  273. package/dist/utils/is-dev-env.js +19 -0
  274. package/dist/utils/is-dev-env.js.map +1 -0
  275. package/dist/utils/is-valid-element-type.js +15 -0
  276. package/dist/utils/is-valid-element-type.js.map +1 -0
  277. package/dist/utils/merge-styles.d.ts +7 -0
  278. package/dist/utils/merge-styles.js +145 -0
  279. package/dist/utils/merge-styles.js.map +1 -0
  280. package/dist/utils/mod-attrs.d.ts +6 -0
  281. package/dist/utils/mod-attrs.js +20 -0
  282. package/dist/utils/mod-attrs.js.map +1 -0
  283. package/dist/utils/process-tokens.d.ts +17 -0
  284. package/dist/utils/process-tokens.js +83 -0
  285. package/dist/utils/process-tokens.js.map +1 -0
  286. package/dist/utils/resolve-recipes.d.ts +17 -0
  287. package/dist/utils/resolve-recipes.js +146 -0
  288. package/dist/utils/resolve-recipes.js.map +1 -0
  289. package/dist/utils/selector-transform.js +32 -0
  290. package/dist/utils/selector-transform.js.map +1 -0
  291. package/dist/utils/string.js +8 -0
  292. package/dist/utils/string.js.map +1 -0
  293. package/dist/utils/styles.d.ts +99 -0
  294. package/dist/utils/styles.js +220 -0
  295. package/dist/utils/styles.js.map +1 -0
  296. package/dist/utils/typography.d.ts +58 -0
  297. package/dist/utils/typography.js +51 -0
  298. package/dist/utils/typography.js.map +1 -0
  299. package/dist/utils/warnings.d.ts +16 -0
  300. package/dist/utils/warnings.js +16 -0
  301. package/dist/utils/warnings.js.map +1 -0
  302. package/dist/zero/babel.d.ts +195 -0
  303. package/dist/zero/babel.js +456 -0
  304. package/dist/zero/babel.js.map +1 -0
  305. package/dist/zero/css-writer.d.ts +45 -0
  306. package/dist/zero/css-writer.js +73 -0
  307. package/dist/zero/css-writer.js.map +1 -0
  308. package/dist/zero/extractor.d.ts +24 -0
  309. package/dist/zero/extractor.js +266 -0
  310. package/dist/zero/extractor.js.map +1 -0
  311. package/dist/zero/index.d.ts +3 -0
  312. package/dist/zero/index.js +3 -0
  313. package/dist/zero/next.d.ts +86 -0
  314. package/dist/zero/next.js +143 -0
  315. package/dist/zero/next.js.map +1 -0
  316. package/docs/PIPELINE.md +519 -0
  317. package/docs/README.md +31 -0
  318. package/docs/adoption.md +298 -0
  319. package/docs/comparison.md +419 -0
  320. package/docs/configuration.md +389 -0
  321. package/docs/debug.md +318 -0
  322. package/docs/design-system.md +436 -0
  323. package/docs/dsl.md +688 -0
  324. package/docs/getting-started.md +217 -0
  325. package/docs/injector.md +544 -0
  326. package/docs/methodology.md +616 -0
  327. package/docs/react-api.md +557 -0
  328. package/docs/ssr.md +440 -0
  329. package/docs/styles.md +596 -0
  330. package/docs/tasty-static.md +532 -0
  331. package/package.json +221 -0
  332. package/tasty.config.ts +14 -0
@@ -0,0 +1,389 @@
1
+ # Configuration
2
+
3
+ Configure the Tasty style system before your app renders using the `configure()` function. Configuration must be done **before any styles are generated** (before first render). For a higher-level docs map, see the [Docs Hub](README.md).
4
+
5
+ ```jsx
6
+ import { configure } from '@tenphi/tasty';
7
+
8
+ configure({
9
+ // CSP nonce for style elements
10
+ nonce: 'abc123',
11
+
12
+ // Global state aliases
13
+ states: {
14
+ '@mobile': '@media(w < 768px)',
15
+ '@tablet': '@media(768px <= w < 1024px)',
16
+ '@dark': '@root(schema=dark)',
17
+ },
18
+
19
+ // Parser configuration
20
+ parserCacheSize: 2000, // LRU cache size (default: 1000)
21
+
22
+ // Custom units (merged with built-in units)
23
+ units: {
24
+ vh: 'vh',
25
+ vw: 'vw',
26
+ custom: (n) => `${n * 10}px`, // Function-based unit
27
+ },
28
+
29
+ // Custom functions for the parser
30
+ funcs: {
31
+ double: (groups) => {
32
+ const value = parseFloat(groups[0]?.output || '0');
33
+ return `${value * 2}px`;
34
+ },
35
+ },
36
+ });
37
+ ```
38
+
39
+ These docs use `data-schema="dark"` in examples. If your app already standardizes on a different attribute such as `data-theme`, keep the same pattern and swap the attribute name consistently everywhere you define root-state aliases.
40
+
41
+ ---
42
+
43
+ ## Options
44
+
45
+ | Option | Type | Default | Description |
46
+ |--------|------|---------|-------------|
47
+ | `nonce` | `string` | - | CSP nonce for style elements |
48
+ | `states` | `Record<string, string>` | - | Global state aliases for advanced state mapping |
49
+ | `parserCacheSize` | `number` | `1000` | Parser LRU cache size |
50
+ | `units` | `Record<string, string \| Function>` | Built-in | Custom units (merged with built-in). See [built-in units](dsl.md#built-in-units) |
51
+ | `funcs` | `Record<string, Function>` | - | Custom parser functions (merged with existing) |
52
+ | `handlers` | `Record<string, StyleHandlerDefinition>` | Built-in | Custom style handlers (replace built-in) |
53
+ | `tokens` | `Record<string, value \| stateMap>` | - | Design tokens injected as `:root` CSS custom properties |
54
+ | `replaceTokens` | `Record<string, string \| number>` | - | Parse-time token substitution (inline replacement) |
55
+ | `keyframes` | `Record<string, KeyframesSteps>` | - | Global keyframes for animations |
56
+ | `properties` | `Record<string, PropertyDefinition>` | - | Global CSS @property definitions |
57
+ | `fontFace` | `Record<string, FontFaceInput>` | - | Global @font-face definitions |
58
+ | `counterStyle` | `Record<string, CounterStyleDescriptors>` | - | Global @counter-style definitions |
59
+ | `autoPropertyTypes` | `boolean` | `true` | Auto-infer and register `@property` types from values |
60
+ | `recipes` | `Record<string, RecipeStyles>` | - | Predefined style recipes (named style bundles) |
61
+ | `presets` | `Record<string, TypographyPreset>` | - | Typography presets — shorthand for `generateTypographyTokens()` |
62
+ | `bodyStyles` | `Styles` | - | Tasty styles applied to the `body` tag |
63
+ | `colorSpace` | `'rgb' \| 'hsl' \| 'oklch'` | `'oklch'` | Color space for decomposed color token companion variables |
64
+
65
+ ---
66
+
67
+ ## Color Space
68
+
69
+ Controls the CSS color space used for decomposed color token companion variables. When you define `#name` color tokens, tasty generates both `--name-color` (full color) and `--name-color-{suffix}` (decomposed components for alpha composition).
70
+
71
+ ```jsx
72
+ configure({
73
+ colorSpace: 'oklch', // default
74
+ });
75
+ ```
76
+
77
+ | Color Space | Suffix | Components Format | Alpha Syntax |
78
+ |---|---|---|---|
79
+ | `rgb` | `-rgb` | `255 128 0` | `rgb(var(--name-color-rgb) / .5)` |
80
+ | `hsl` | `-hsl` | `300 100% 25%` | `hsl(var(--name-color-hsl) / .5)` |
81
+ | `oklch` | `-oklch` | `0.42 0.16 328` | `oklch(var(--name-color-oklch) / .5)` |
82
+
83
+ The `oklch` color space is the default because it provides perceptually uniform color manipulation — alpha fading and color mixing produce more natural-looking results.
84
+
85
+ ---
86
+
87
+ ## Design Tokens
88
+
89
+ Design tokens define CSS custom properties on `:root`. They are injected automatically when the first style is rendered. Values are parsed through the Tasty DSL, so you can use units, color syntax, and other DSL features.
90
+
91
+ Tokens support state maps for responsive or theme-aware values:
92
+
93
+ ```jsx
94
+ configure({
95
+ tokens: {
96
+ '$gap': '4px',
97
+ '$radius': '6px',
98
+ '#primary': {
99
+ '': '#purple',
100
+ '@dark': '#light-purple',
101
+ },
102
+ '$font-size': {
103
+ '': '14px',
104
+ '@mobile': '12px',
105
+ },
106
+ },
107
+ });
108
+ ```
109
+
110
+ - `$name` keys become `--name` CSS custom properties
111
+ - `#name` keys become `--name-color` and `--name-color-{colorSpace}` properties (suffix depends on `colorSpace`, default `oklch`)
112
+
113
+ Tokens are automatically emitted in all rendering modes: runtime (client), SSR, and zero-runtime (Babel plugin).
114
+
115
+ ---
116
+
117
+ ## Replace Tokens (Parse-Time Substitution)
118
+
119
+ Replace tokens are **substituted inline at parse time** — they are baked into the generated CSS, not resolved via CSS custom properties at runtime. This makes them ideal for value aliases and shorthand references.
120
+
121
+ Use `$name` for value tokens and `#name` for color token aliases:
122
+
123
+ ```jsx
124
+ configure({
125
+ replaceTokens: {
126
+ $spacing: '2x',
127
+ '$card-padding': '4x',
128
+ '#accent': '#purple',
129
+ '#surface-hover': '#gray.05',
130
+ },
131
+ });
132
+ ```
133
+
134
+ When a component uses `padding: '$card-padding'`, the parser replaces it with `'4x'` before generating CSS. When a component uses `fill: '#accent'`, it is replaced with `'#purple'`, which in turn resolves to `var(--purple-color)`.
135
+
136
+ See [Replace Tokens](dsl.md#replace-tokens) in the Style DSL reference.
137
+
138
+ ---
139
+
140
+ ## Font Face
141
+
142
+ Register custom fonts globally so every component can reference them by family name. Values are descriptor objects or arrays (for multiple weights/styles). Rules are injected eagerly when styles are first generated.
143
+
144
+ ```ts
145
+ configure({
146
+ fontFace: {
147
+ 'Brand Sans': [
148
+ {
149
+ src: 'url("/fonts/brand-regular.woff2") format("woff2")',
150
+ fontWeight: 400,
151
+ fontDisplay: 'swap',
152
+ },
153
+ {
154
+ src: 'url("/fonts/brand-bold.woff2") format("woff2")',
155
+ fontWeight: 700,
156
+ fontDisplay: 'swap',
157
+ },
158
+ ],
159
+ Icons: {
160
+ src: 'url("/fonts/icons.woff2") format("woff2")',
161
+ fontDisplay: 'block',
162
+ },
163
+ },
164
+ });
165
+ ```
166
+
167
+ Now any component can use `fontFamily: '"Brand Sans", sans-serif'` and the browser will already have the `@font-face` rules in the stylesheet.
168
+
169
+ See [Font Face (`@fontFace`)](dsl.md#font-face-fontface) for inline usage inside component styles and the full list of supported descriptors.
170
+
171
+ ---
172
+
173
+ ## Counter Style
174
+
175
+ Define custom list-marker algorithms globally. Rules are injected eagerly when styles are first generated.
176
+
177
+ ```ts
178
+ configure({
179
+ counterStyle: {
180
+ thumbs: {
181
+ system: 'cyclic',
182
+ symbols: '"👍"',
183
+ suffix: '" "',
184
+ },
185
+ 'lower-roman-parens': {
186
+ system: 'extends lower-roman',
187
+ suffix: '") "',
188
+ },
189
+ },
190
+ });
191
+ ```
192
+
193
+ Components can then reference `listStyleType: 'thumbs'` directly.
194
+
195
+ See [Counter Style (`@counterStyle`)](dsl.md#counter-style-counterstyle) for inline usage inside component styles and the full list of supported descriptors.
196
+
197
+ ---
198
+
199
+ ## Recipes
200
+
201
+ Recipes are predefined, named style bundles. Define them globally via `configure()`:
202
+
203
+ ```jsx
204
+ configure({
205
+ recipes: {
206
+ card: {
207
+ padding: '4x',
208
+ fill: '#surface',
209
+ radius: '1r',
210
+ border: true,
211
+ },
212
+ elevated: {
213
+ shadow: '2x 2x 4x #shadow',
214
+ },
215
+ },
216
+ });
217
+ ```
218
+
219
+ Recipe values are flat tasty styles (no sub-element keys). They may contain base styles, tokens, local states, `@keyframes`, and `@properties`. Recipes cannot reference other recipes.
220
+
221
+ For how to apply, compose, and override recipes in components, see [Recipes](dsl.md#recipes) in the Style DSL reference.
222
+
223
+ ---
224
+
225
+ ## Typography Presets
226
+
227
+ Typography presets are a shorthand for `generateTypographyTokens()`. Instead of calling the function manually and spreading the result into `tokens`, pass the presets directly:
228
+
229
+ ```jsx
230
+ configure({
231
+ presets: {
232
+ h1: { fontSize: '32px', lineHeight: '1.2', fontWeight: '700' },
233
+ t2: { fontSize: '16px', lineHeight: '1.5', fontWeight: '400' },
234
+ tag: {
235
+ fontSize: '10px',
236
+ lineHeight: '1.4',
237
+ letterSpacing: '0.04em',
238
+ fontWeight: '600',
239
+ },
240
+ },
241
+ });
242
+ ```
243
+
244
+ Each preset generates `$name-font-size`, `$name-line-height`, `$name-letter-spacing`, `$name-font-weight`, and optional `$name-bold-font-weight`, `$name-icon-size`, `$name-text-transform`, `$name-font-family`, `$name-font-style` tokens.
245
+
246
+ Preset values support state maps for responsive or theme-aware typography:
247
+
248
+ ```jsx
249
+ configure({
250
+ presets: {
251
+ t2: {
252
+ fontSize: '16px',
253
+ lineHeight: '1.5',
254
+ fontWeight: { '': '400', '@dark': '300' },
255
+ },
256
+ },
257
+ });
258
+ ```
259
+
260
+ The generated tokens are merged **under** explicit `tokens` — if both `presets` and `tokens` define `$t2-font-weight`, the `tokens` value wins. Plugins can also provide `presets`; plugin presets are merged first, then config presets, then explicit tokens on top.
261
+
262
+ ---
263
+
264
+ ## Body Styles
265
+
266
+ Apply Tasty styles to the `body` element via configuration, without needing `useGlobalStyles('body', ...)` at runtime:
267
+
268
+ ```jsx
269
+ configure({
270
+ bodyStyles: {
271
+ fill: '#surface',
272
+ color: '#text',
273
+ preset: 't2',
274
+ margin: 0,
275
+ fontFamily: 'system-ui, sans-serif',
276
+ },
277
+ });
278
+ ```
279
+
280
+ Body styles support the full Tasty style syntax including style properties, tokens, state maps, `@keyframes`, `@fontFace`, and sub-element selectors. They are injected alongside `:root` tokens when the first style is rendered.
281
+
282
+ Body styles are automatically emitted in all rendering modes: runtime (client), SSR, and zero-runtime (Babel plugin). Plugins can also provide `bodyStyles`; they are merged with config body styles (config wins on conflict).
283
+
284
+ ---
285
+
286
+ ## Auto Property Types
287
+
288
+ CSS cannot transition or animate custom properties unless their type is declared via [`@property`](https://developer.mozilla.org/en-US/docs/Web/CSS/@property). Tasty handles this automatically — when a custom property is assigned a concrete value (e.g. `'$scale': 1`, `'$gap': '10px'`, `'#accent': 'purple'`), the type is inferred and a `@property` rule is registered.
289
+
290
+ This works across all declaration contexts: component styles, `@keyframes`, global config, and the zero-runtime Babel plugin. It also resolves `var()` chains — if `$a` references `var(--b)`, the type propagates once `--b` is resolved.
291
+
292
+ Supported types:
293
+
294
+ | Detection | Inferred syntax |
295
+ |-----------|-----------------|
296
+ | `1`, `0.5`, `-3` (bare numbers) | `<number>` |
297
+ | `10px`, `2rem`, `100vw` (length units) | `<length>` |
298
+ | `50%` | `<percentage>` |
299
+ | `45deg`, `0.5turn` (angle units) | `<angle>` |
300
+ | `300ms`, `1s` (time units) | `<time>` |
301
+ | `#name` tokens (by naming convention) | `<color>` |
302
+
303
+ Auto-inferred properties use `inherits: true` (the CSS default). Use explicit `@properties` when you need different settings:
304
+
305
+ ```jsx
306
+ // In component styles
307
+ styles: {
308
+ '@properties': {
309
+ '$scale': { syntax: '<number>', inherits: false, initialValue: 1 },
310
+ },
311
+ }
312
+
313
+ // Or globally
314
+ configure({
315
+ properties: {
316
+ '$scale': { syntax: '<number>', inherits: false, initialValue: 1 },
317
+ },
318
+ });
319
+ ```
320
+
321
+ To disable auto-inference entirely (only explicit `@properties` will be used):
322
+
323
+ ```jsx
324
+ configure({ autoPropertyTypes: false });
325
+ ```
326
+
327
+ ---
328
+
329
+ ## Custom Style Handlers
330
+
331
+ Override or extend the built-in style property handlers. A handler definition can take three forms:
332
+
333
+ | Form | Syntax | Description |
334
+ |------|--------|-------------|
335
+ | Function only | `handler` | Triggered by its key name; receives only that property |
336
+ | Single dep | `['styleName', handler]` | Triggered by the specified style property |
337
+ | Multi dep | `[['dep1', 'dep2', ...], handler]` | Triggered by any of the listed properties; receives all of them |
338
+
339
+ The multi-dep form is useful when output depends on several style properties together (e.g., `gap` needs to know `display` and `flow` to decide the CSS strategy).
340
+
341
+ ```jsx
342
+ import { configure, styleHandlers } from '@tenphi/tasty';
343
+
344
+ configure({
345
+ handlers: {
346
+ // Function only — overrides built-in fill handler
347
+ fill: ({ fill }) => {
348
+ if (fill?.startsWith('gradient:')) {
349
+ return { background: fill.slice(9) };
350
+ }
351
+ return styleHandlers.fill({ fill });
352
+ },
353
+
354
+ // Function only — new single-prop handler
355
+ elevation: ({ elevation }) => {
356
+ const level = parseInt(elevation) || 1;
357
+ return {
358
+ 'box-shadow': `0 ${level * 2}px ${level * 4}px rgba(0,0,0,0.1)`,
359
+ 'z-index': String(level * 100),
360
+ };
361
+ },
362
+
363
+ // Multi dep — handler reads multiple style properties
364
+ gap: [['display', 'flow', 'gap'], ({ display, flow, gap }) => {
365
+ if (!gap) return;
366
+ const isGrid = display?.includes('grid');
367
+ return { gap: isGrid ? gap : `/* custom logic for ${flow} */` };
368
+ }],
369
+ },
370
+ });
371
+ ```
372
+
373
+ ---
374
+
375
+ ## Extending Style Types (TypeScript)
376
+
377
+ Use module augmentation to extend the `StylesInterface`:
378
+
379
+ ```tsx
380
+ // tasty.d.ts
381
+ declare module '@tenphi/tasty' {
382
+ interface StylesInterface {
383
+ elevation?: string;
384
+ gradient?: string;
385
+ }
386
+ }
387
+ ```
388
+
389
+ See [Style DSL](dsl.md) for state maps, tokens, units, and extending semantics, and [React API](react-api.md) for `tasty()`, style functions, and component props.
package/docs/debug.md ADDED
@@ -0,0 +1,318 @@
1
+ # Tasty Debug Utilities
2
+
3
+ Runtime CSS inspection and diagnostics for the Tasty styling system. Inspect injected styles, measure cache performance, analyze style chunks, and troubleshoot CSS issues — all from the browser console.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ `tastyDebug` is a diagnostic object that exposes Tasty's runtime CSS state. It is designed for development use but can be manually installed in production for debugging.
10
+
11
+ In development mode (`isDevEnv()` returns `true`), `tastyDebug` is automatically installed on `window.tastyDebug`. In production, install it manually when needed.
12
+
13
+ All methods **log to the console by default**. Pass `{ raw: true }` to suppress logging and only return data.
14
+
15
+ ---
16
+
17
+ ## Quick Start
18
+
19
+ ```typescript
20
+ // Auto-installed in dev mode. Otherwise:
21
+ import { tastyDebug } from '@tenphi/tasty';
22
+ tastyDebug.install();
23
+
24
+ // Print a quick-start guide
25
+ tastyDebug.help();
26
+
27
+ // Get a comprehensive overview (logged automatically)
28
+ tastyDebug.summary();
29
+
30
+ // See all active CSS
31
+ tastyDebug.css('active');
32
+
33
+ // Inspect a specific element
34
+ tastyDebug.inspect('.my-button');
35
+
36
+ // Silent mode — return data only, no console output
37
+ const data = tastyDebug.summary({ raw: true });
38
+ ```
39
+
40
+ ---
41
+
42
+ ## Options
43
+
44
+ All methods accept a shared options object:
45
+
46
+ ```typescript
47
+ interface DebugOptions {
48
+ root?: Document | ShadowRoot; // Target root (default: document)
49
+ raw?: boolean; // Suppress console logging (default: false)
50
+ }
51
+ ```
52
+
53
+ When `raw` is `false` (the default), results are logged to the console **and** returned. When `raw` is `true`, results are returned silently.
54
+
55
+ ---
56
+
57
+ ## API Reference
58
+
59
+ ### `css(target, opts?): string`
60
+
61
+ Retrieves CSS text for a given target. Logs the result with rule count and size.
62
+
63
+ **Targets:**
64
+
65
+ | Target | Description |
66
+ |---|---|
67
+ | `'all'` | All tasty CSS (component + global + raw) |
68
+ | `'active'` | CSS for classes currently in the DOM |
69
+ | `'unused'` | CSS with refCount = 0 (cached but not used) |
70
+ | `'global'` | Only global CSS (from `injectGlobal`) |
71
+ | `'page'` | All CSS on the page (including non-tasty) |
72
+ | `'t42'` | CSS for a specific tasty class |
73
+ | `['t0', 't5']` | CSS for multiple tasty classes |
74
+ | `'.my-button'` | CSS affecting a DOM element (by selector) |
75
+ | `element` | CSS affecting a DOM element (by reference) |
76
+
77
+ **Extra options:**
78
+
79
+ ```typescript
80
+ interface CssOptions extends DebugOptions {
81
+ prettify?: boolean; // Format output (default: true)
82
+ source?: boolean; // Read original CSS instead of live CSSOM (default: false, dev-mode only)
83
+ }
84
+ ```
85
+
86
+ ```typescript
87
+ // Active CSS with stats
88
+ tastyDebug.css('active');
89
+
90
+ // Specific class, silent
91
+ const css = tastyDebug.css('t42', { raw: true });
92
+
93
+ // Compare original vs browser-parsed CSS (dev mode only)
94
+ tastyDebug.css('t42'); // live CSSOM
95
+ tastyDebug.css('t42', { source: true }); // original output
96
+
97
+ // Shadow DOM
98
+ tastyDebug.css('all', { root: shadowRoot });
99
+ ```
100
+
101
+ The `source` option reads from `RuleInfo.cssText`, which is only populated when `devMode` is active (development environment or `localStorage.TASTY_DEBUG = 'true'`). In production without debug mode, it falls back to the live CSSOM with a warning.
102
+
103
+ ---
104
+
105
+ ### `inspect(target, opts?): InspectResult`
106
+
107
+ Inspects a DOM element and returns detailed information about its tasty styles, including chunk assignments.
108
+
109
+ ```typescript
110
+ interface InspectResult {
111
+ element?: Element | null;
112
+ classes: string[]; // Tasty classes on the element
113
+ chunks: ChunkInfo[]; // Chunk assignment per class
114
+ css: string; // Prettified CSS
115
+ size: number; // CSS size in characters
116
+ rules: number; // Number of CSS rule blocks
117
+ }
118
+
119
+ interface ChunkInfo {
120
+ className: string;
121
+ chunkName: string | null; // e.g., 'appearance', 'font', 'dimension'
122
+ }
123
+ ```
124
+
125
+ ```typescript
126
+ tastyDebug.inspect('.my-card');
127
+ // Logs: inspect div — 3 classes, 5 rules, 1.2KB
128
+ // Chunks: t3→appearance, t7→font, t12→dimension
129
+
130
+ // Silent
131
+ const result = tastyDebug.inspect('.my-card', { raw: true });
132
+ console.log(result.classes); // ['t3', 't7', 't12']
133
+ console.log(result.rules); // 5
134
+ ```
135
+
136
+ ---
137
+
138
+ ### `summary(opts?): Summary`
139
+
140
+ One-shot overview of the entire Tasty CSS state. Logs a compact report.
141
+
142
+ ```typescript
143
+ interface Summary {
144
+ activeClasses: string[];
145
+ unusedClasses: string[];
146
+ totalStyledClasses: string[];
147
+
148
+ activeCSSSize: number;
149
+ unusedCSSSize: number;
150
+ globalCSSSize: number;
151
+ rawCSSSize: number;
152
+ keyframesCSSSize: number;
153
+ propertyCSSSize: number;
154
+ totalCSSSize: number;
155
+
156
+ activeRuleCount: number;
157
+ unusedRuleCount: number;
158
+ globalRuleCount: number;
159
+ rawRuleCount: number;
160
+ keyframesRuleCount: number;
161
+ propertyRuleCount: number;
162
+ totalRuleCount: number;
163
+
164
+ metrics: CacheMetrics | null;
165
+ definedProperties: string[];
166
+ definedKeyframes: { name: string; refCount: number }[];
167
+ chunkBreakdown: ChunkBreakdown;
168
+ }
169
+ ```
170
+
171
+ ```typescript
172
+ // Logged automatically
173
+ tastyDebug.summary();
174
+ // Output:
175
+ // Active: 42 classes, 186 rules, 12.4KB
176
+ // Unused: 3 classes, 8 rules, 0.5KB
177
+ // Global: 12 rules, 1.1KB
178
+ // Total: 45 classes, 206 rules, 14.0KB
179
+ // Cache: 94.2% hit rate (312 lookups)
180
+
181
+ // Silent
182
+ const s = tastyDebug.summary({ raw: true });
183
+ console.log(s.totalRuleCount); // 206
184
+ ```
185
+
186
+ ---
187
+
188
+ ### `chunks(opts?): ChunkBreakdown`
189
+
190
+ Breakdown of styles by chunk type.
191
+
192
+ ```typescript
193
+ interface ChunkBreakdown {
194
+ byChunk: Record<string, {
195
+ classes: string[];
196
+ cssSize: number;
197
+ ruleCount: number;
198
+ }>;
199
+ totalChunkTypes: number;
200
+ totalClasses: number;
201
+ }
202
+ ```
203
+
204
+ ```typescript
205
+ tastyDebug.chunks();
206
+ // Output:
207
+ // appearance: 24 cls, 48 rules, 3.2KB
208
+ // font: 18 cls, 18 rules, 1.1KB
209
+ // dimension: 31 cls, 45 rules, 2.4KB
210
+ ```
211
+
212
+ Chunk types: `combined`, `appearance`, `font`, `dimension`, `display`, `layout`, `position`, `misc`, `subcomponents`.
213
+
214
+ ---
215
+
216
+ ### `cache(opts?): CacheStatus`
217
+
218
+ Cache state and performance metrics.
219
+
220
+ ```typescript
221
+ interface CacheStatus {
222
+ classes: {
223
+ active: string[];
224
+ unused: string[];
225
+ all: string[];
226
+ };
227
+ metrics: CacheMetrics | null;
228
+ }
229
+ ```
230
+
231
+ ```typescript
232
+ tastyDebug.cache();
233
+ // Output:
234
+ // Active: 42, Unused: 3
235
+ // Hits: 294, Misses: 18, Rate: 94.2%
236
+ ```
237
+
238
+ ---
239
+
240
+ ### `cleanup(opts?): void`
241
+
242
+ Forces immediate cleanup of all unused styles (those with `refCount = 0`).
243
+
244
+ ```typescript
245
+ tastyDebug.cleanup();
246
+ tastyDebug.cleanup({ root: shadowRoot });
247
+ ```
248
+
249
+ ---
250
+
251
+ ### `help(): void`
252
+
253
+ Prints a quick-start guide to the console.
254
+
255
+ ```typescript
256
+ tastyDebug.help();
257
+ ```
258
+
259
+ ---
260
+
261
+ ### `install(): void`
262
+
263
+ Attaches `tastyDebug` to `window.tastyDebug`. Called automatically in development mode.
264
+
265
+ ```typescript
266
+ import { tastyDebug } from '@tenphi/tasty';
267
+ tastyDebug.install();
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Shadow DOM Support
273
+
274
+ All methods accept a `root` option to target a Shadow DOM:
275
+
276
+ ```typescript
277
+ const shadowRoot = host.shadowRoot;
278
+ tastyDebug.css('all', { root: shadowRoot });
279
+ tastyDebug.inspect('.shadow-component', { root: shadowRoot });
280
+ tastyDebug.summary({ root: shadowRoot });
281
+ ```
282
+
283
+ ---
284
+
285
+ ## Common Workflows
286
+
287
+ ### Debugging a component's styles
288
+
289
+ ```typescript
290
+ // 1. Inspect the element
291
+ tastyDebug.inspect('.my-button');
292
+
293
+ // 2. See CSS for a specific class
294
+ tastyDebug.css('t3');
295
+
296
+ // 3. Compare original vs browser-parsed (dev mode)
297
+ tastyDebug.css('t3', { source: true });
298
+ ```
299
+
300
+ ### Checking cache efficiency
301
+
302
+ ```typescript
303
+ const { metrics } = tastyDebug.cache({ raw: true });
304
+ if (metrics) {
305
+ const total = metrics.hits + metrics.misses;
306
+ const rate = total > 0 ? ((metrics.hits / total) * 100).toFixed(1) : 0;
307
+ console.log(`Cache hit rate: ${rate}%`);
308
+ }
309
+ ```
310
+
311
+ ### Monitoring CSS growth
312
+
313
+ ```typescript
314
+ const s = tastyDebug.summary({ raw: true });
315
+ console.log(`Total: ${s.totalRuleCount} rules, ${(s.totalCSSSize / 1024).toFixed(1)}KB`);
316
+ console.log(`Active: ${s.activeRuleCount} rules`);
317
+ console.log(`Unused: ${s.unusedRuleCount} rules`);
318
+ ```