@tenphi/tasty 0.0.0-snapshot.bbd10c7 → 0.0.0-snapshot.bbfcd75

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 (370) hide show
  1. package/README.md +196 -140
  2. package/dist/babel-Zs1Q03qt.d.ts +83 -0
  3. package/dist/chunks/async-storage-CG5HnUT5.js +20 -0
  4. package/dist/chunks/async-storage-CG5HnUT5.js.map +1 -0
  5. package/dist/chunks/build-config-CUQVwdWF.js +42 -0
  6. package/dist/chunks/build-config-CUQVwdWF.js.map +1 -0
  7. package/dist/chunks/collector-B0LTHw6Z.js +208 -0
  8. package/dist/chunks/collector-B0LTHw6Z.js.map +1 -0
  9. package/dist/chunks/config-engine-C3pF9EK9.js +267 -0
  10. package/dist/chunks/config-engine-C3pF9EK9.js.map +1 -0
  11. package/dist/chunks/css-definitions-D_it4XZH.js +875 -0
  12. package/dist/chunks/css-definitions-D_it4XZH.js.map +1 -0
  13. package/dist/chunks/css-resources-BN8apgxt.js +142 -0
  14. package/dist/chunks/css-resources-BN8apgxt.js.map +1 -0
  15. package/dist/{debug.js → chunks/debug-C9LeNVoJ.js} +187 -139
  16. package/dist/chunks/debug-C9LeNVoJ.js.map +1 -0
  17. package/dist/chunks/dsl-C5yuAn41.js +1373 -0
  18. package/dist/chunks/dsl-C5yuAn41.js.map +1 -0
  19. package/dist/chunks/hydration-TRcz5vnk.js +41 -0
  20. package/dist/chunks/hydration-TRcz5vnk.js.map +1 -0
  21. package/dist/chunks/react-runtime-O-OUrKLH.js +557 -0
  22. package/dist/chunks/react-runtime-O-OUrKLH.js.map +1 -0
  23. package/dist/chunks/runtime-engine-DvnE2g-E.js +2437 -0
  24. package/dist/chunks/runtime-engine-DvnE2g-E.js.map +1 -0
  25. package/dist/chunks/runtime-state-BTDqSYBk.js +127 -0
  26. package/dist/chunks/runtime-state-BTDqSYBk.js.map +1 -0
  27. package/dist/{utils/merge-styles.js → chunks/shared-utils-DWA4LjIa.js} +55 -55
  28. package/dist/chunks/shared-utils-DWA4LjIa.js.map +1 -0
  29. package/dist/chunks/style-engine-C1ECBZxR.js +5131 -0
  30. package/dist/chunks/style-engine-C1ECBZxR.js.map +1 -0
  31. package/dist/{zero/extractor.js → chunks/zero-engine-B6EnYcXY.js} +89 -82
  32. package/dist/chunks/zero-engine-B6EnYcXY.js.map +1 -0
  33. package/dist/collector-hl5KNH7k.d.ts +165 -0
  34. package/dist/config-DWL1ZYue.d.ts +1358 -0
  35. package/dist/core/index.d.ts +5 -34
  36. package/dist/core/index.js +9 -27
  37. package/dist/index-D9N9GV24.d.ts +1947 -0
  38. package/dist/index.d.ts +5 -51
  39. package/dist/index.js +11 -36
  40. package/dist/{utils/merge-styles.d.ts → merge-styles-C_oMoJVd.d.ts} +3 -3
  41. package/dist/ssr/astro-client.js +6 -0
  42. package/dist/ssr/astro-client.js.map +1 -0
  43. package/dist/ssr/astro-middleware-extract-static.d.ts +11 -0
  44. package/dist/ssr/astro-middleware-extract-static.js +9 -0
  45. package/dist/ssr/astro-middleware-extract-static.js.map +1 -0
  46. package/dist/ssr/astro-middleware-extract.d.ts +11 -0
  47. package/dist/ssr/astro-middleware-extract.js +9 -0
  48. package/dist/ssr/astro-middleware-extract.js.map +1 -0
  49. package/dist/ssr/astro-middleware-static.d.ts +18 -0
  50. package/dist/ssr/astro-middleware-static.js +7 -0
  51. package/dist/ssr/astro-middleware-static.js.map +1 -0
  52. package/dist/ssr/astro-middleware.d.ts +19 -0
  53. package/dist/ssr/astro-middleware.js +7 -0
  54. package/dist/ssr/astro-middleware.js.map +1 -0
  55. package/dist/ssr/astro.d.ts +117 -11
  56. package/dist/ssr/astro.js +204 -48
  57. package/dist/ssr/astro.js.map +1 -1
  58. package/dist/ssr/index.d.ts +37 -4
  59. package/dist/ssr/index.js +6 -6
  60. package/dist/ssr/index.js.map +1 -1
  61. package/dist/ssr/next-config.d.ts +66 -0
  62. package/dist/ssr/next-config.js +124 -0
  63. package/dist/ssr/next-config.js.map +1 -0
  64. package/dist/ssr/next.d.ts +14 -5
  65. package/dist/ssr/next.js +31 -46
  66. package/dist/ssr/next.js.map +1 -1
  67. package/dist/static/index.d.ts +91 -5
  68. package/dist/static/index.js +31 -3
  69. package/dist/static/index.js.map +1 -0
  70. package/dist/static/inject.js.map +1 -1
  71. package/dist/types-jKZNpias.d.ts +1616 -0
  72. package/dist/zero/babel.d.ts +2 -182
  73. package/dist/zero/babel.js +82 -113
  74. package/dist/zero/babel.js.map +1 -1
  75. package/dist/zero/index.d.ts +81 -3
  76. package/dist/zero/index.js +2 -3
  77. package/dist/zero/next.d.ts +1 -1
  78. package/dist/zero/next.js +0 -31
  79. package/dist/zero/next.js.map +1 -1
  80. package/docs/README.md +20 -12
  81. package/docs/adoption.md +59 -32
  82. package/docs/ai-agents.md +229 -0
  83. package/docs/comparison.md +76 -48
  84. package/docs/configuration.md +566 -69
  85. package/docs/debug.md +37 -23
  86. package/docs/design-system.md +63 -32
  87. package/docs/dsl.md +527 -179
  88. package/docs/getting-started.md +62 -41
  89. package/docs/injector.md +157 -51
  90. package/docs/methodology.md +69 -37
  91. package/docs/migration-v3.md +285 -0
  92. package/docs/pipeline.md +744 -0
  93. package/docs/plugins.md +353 -0
  94. package/docs/{runtime.md → react-api.md} +176 -67
  95. package/docs/runtime-benchmarks.md +377 -0
  96. package/docs/ssr.md +350 -94
  97. package/docs/styles.md +108 -27
  98. package/docs/tasty-static.md +149 -87
  99. package/package.json +121 -23
  100. package/tasty.config.ts +6 -0
  101. package/dist/_virtual/_rolldown/runtime.js +0 -7
  102. package/dist/chunks/cacheKey.js +0 -77
  103. package/dist/chunks/cacheKey.js.map +0 -1
  104. package/dist/chunks/definitions.d.ts +0 -37
  105. package/dist/chunks/definitions.js +0 -258
  106. package/dist/chunks/definitions.js.map +0 -1
  107. package/dist/chunks/index.d.ts +0 -1
  108. package/dist/chunks/renderChunk.d.ts +0 -1
  109. package/dist/chunks/renderChunk.js +0 -59
  110. package/dist/chunks/renderChunk.js.map +0 -1
  111. package/dist/compute-styles.d.ts +0 -31
  112. package/dist/compute-styles.js +0 -356
  113. package/dist/compute-styles.js.map +0 -1
  114. package/dist/config.d.ts +0 -372
  115. package/dist/config.js +0 -507
  116. package/dist/config.js.map +0 -1
  117. package/dist/counter-style/index.js +0 -51
  118. package/dist/counter-style/index.js.map +0 -1
  119. package/dist/debug.d.ts +0 -89
  120. package/dist/debug.js.map +0 -1
  121. package/dist/font-face/index.js +0 -63
  122. package/dist/font-face/index.js.map +0 -1
  123. package/dist/hooks/index.d.ts +0 -7
  124. package/dist/hooks/useCounterStyle.d.ts +0 -50
  125. package/dist/hooks/useCounterStyle.js +0 -45
  126. package/dist/hooks/useCounterStyle.js.map +0 -1
  127. package/dist/hooks/useFontFace.d.ts +0 -43
  128. package/dist/hooks/useFontFace.js +0 -69
  129. package/dist/hooks/useFontFace.js.map +0 -1
  130. package/dist/hooks/useGlobalStyles.d.ts +0 -30
  131. package/dist/hooks/useGlobalStyles.js +0 -77
  132. package/dist/hooks/useGlobalStyles.js.map +0 -1
  133. package/dist/hooks/useKeyframes.d.ts +0 -56
  134. package/dist/hooks/useKeyframes.js +0 -63
  135. package/dist/hooks/useKeyframes.js.map +0 -1
  136. package/dist/hooks/useProperty.d.ts +0 -79
  137. package/dist/hooks/useProperty.js +0 -108
  138. package/dist/hooks/useProperty.js.map +0 -1
  139. package/dist/hooks/useRawCSS.d.ts +0 -53
  140. package/dist/hooks/useRawCSS.js +0 -34
  141. package/dist/hooks/useRawCSS.js.map +0 -1
  142. package/dist/hooks/useStyles.d.ts +0 -40
  143. package/dist/hooks/useStyles.js +0 -29
  144. package/dist/hooks/useStyles.js.map +0 -1
  145. package/dist/injector/index.d.ts +0 -166
  146. package/dist/injector/index.js +0 -166
  147. package/dist/injector/index.js.map +0 -1
  148. package/dist/injector/injector.d.ts +0 -166
  149. package/dist/injector/injector.js +0 -464
  150. package/dist/injector/injector.js.map +0 -1
  151. package/dist/injector/sheet-manager.d.ts +0 -136
  152. package/dist/injector/sheet-manager.js +0 -733
  153. package/dist/injector/sheet-manager.js.map +0 -1
  154. package/dist/injector/types.d.ts +0 -204
  155. package/dist/keyframes/index.js +0 -206
  156. package/dist/keyframes/index.js.map +0 -1
  157. package/dist/parser/classify.js +0 -319
  158. package/dist/parser/classify.js.map +0 -1
  159. package/dist/parser/const.js +0 -60
  160. package/dist/parser/const.js.map +0 -1
  161. package/dist/parser/lru.js +0 -109
  162. package/dist/parser/lru.js.map +0 -1
  163. package/dist/parser/parser.d.ts +0 -25
  164. package/dist/parser/parser.js +0 -115
  165. package/dist/parser/parser.js.map +0 -1
  166. package/dist/parser/tokenizer.js +0 -69
  167. package/dist/parser/tokenizer.js.map +0 -1
  168. package/dist/parser/types.d.ts +0 -51
  169. package/dist/parser/types.js +0 -46
  170. package/dist/parser/types.js.map +0 -1
  171. package/dist/pipeline/conditions.d.ts +0 -134
  172. package/dist/pipeline/conditions.js +0 -406
  173. package/dist/pipeline/conditions.js.map +0 -1
  174. package/dist/pipeline/exclusive.js +0 -230
  175. package/dist/pipeline/exclusive.js.map +0 -1
  176. package/dist/pipeline/index.d.ts +0 -55
  177. package/dist/pipeline/index.js +0 -708
  178. package/dist/pipeline/index.js.map +0 -1
  179. package/dist/pipeline/materialize.js +0 -1103
  180. package/dist/pipeline/materialize.js.map +0 -1
  181. package/dist/pipeline/parseStateKey.d.ts +0 -15
  182. package/dist/pipeline/parseStateKey.js +0 -446
  183. package/dist/pipeline/parseStateKey.js.map +0 -1
  184. package/dist/pipeline/simplify.js +0 -515
  185. package/dist/pipeline/simplify.js.map +0 -1
  186. package/dist/pipeline/warnings.js +0 -18
  187. package/dist/pipeline/warnings.js.map +0 -1
  188. package/dist/plugins/index.d.ts +0 -2
  189. package/dist/plugins/okhsl-plugin.d.ts +0 -35
  190. package/dist/plugins/okhsl-plugin.js +0 -97
  191. package/dist/plugins/okhsl-plugin.js.map +0 -1
  192. package/dist/plugins/types.d.ts +0 -76
  193. package/dist/properties/index.js +0 -222
  194. package/dist/properties/index.js.map +0 -1
  195. package/dist/properties/property-type-resolver.d.ts +0 -24
  196. package/dist/properties/property-type-resolver.js +0 -90
  197. package/dist/properties/property-type-resolver.js.map +0 -1
  198. package/dist/ssr/async-storage.d.ts +0 -17
  199. package/dist/ssr/async-storage.js +0 -34
  200. package/dist/ssr/async-storage.js.map +0 -1
  201. package/dist/ssr/collect-auto-properties.js +0 -39
  202. package/dist/ssr/collect-auto-properties.js.map +0 -1
  203. package/dist/ssr/collector.d.ts +0 -102
  204. package/dist/ssr/collector.js +0 -219
  205. package/dist/ssr/collector.js.map +0 -1
  206. package/dist/ssr/format-global-rules.js +0 -22
  207. package/dist/ssr/format-global-rules.js.map +0 -1
  208. package/dist/ssr/format-keyframes.js +0 -69
  209. package/dist/ssr/format-keyframes.js.map +0 -1
  210. package/dist/ssr/format-property.js +0 -49
  211. package/dist/ssr/format-property.js.map +0 -1
  212. package/dist/ssr/format-rules.js +0 -73
  213. package/dist/ssr/format-rules.js.map +0 -1
  214. package/dist/ssr/hydrate.d.ts +0 -22
  215. package/dist/ssr/hydrate.js +0 -49
  216. package/dist/ssr/hydrate.js.map +0 -1
  217. package/dist/ssr/ssr-collector-ref.js +0 -12
  218. package/dist/ssr/ssr-collector-ref.js.map +0 -1
  219. package/dist/states/index.d.ts +0 -49
  220. package/dist/states/index.js +0 -170
  221. package/dist/states/index.js.map +0 -1
  222. package/dist/static/tastyStatic.d.ts +0 -46
  223. package/dist/static/tastyStatic.js +0 -30
  224. package/dist/static/tastyStatic.js.map +0 -1
  225. package/dist/static/types.d.ts +0 -49
  226. package/dist/static/types.js +0 -24
  227. package/dist/static/types.js.map +0 -1
  228. package/dist/styles/border.d.ts +0 -25
  229. package/dist/styles/border.js +0 -120
  230. package/dist/styles/border.js.map +0 -1
  231. package/dist/styles/color.d.ts +0 -14
  232. package/dist/styles/color.js +0 -26
  233. package/dist/styles/color.js.map +0 -1
  234. package/dist/styles/const.js +0 -17
  235. package/dist/styles/const.js.map +0 -1
  236. package/dist/styles/createStyle.js +0 -79
  237. package/dist/styles/createStyle.js.map +0 -1
  238. package/dist/styles/dimension.js +0 -109
  239. package/dist/styles/dimension.js.map +0 -1
  240. package/dist/styles/directional.js +0 -133
  241. package/dist/styles/directional.js.map +0 -1
  242. package/dist/styles/display.d.ts +0 -30
  243. package/dist/styles/display.js +0 -73
  244. package/dist/styles/display.js.map +0 -1
  245. package/dist/styles/fade.d.ts +0 -15
  246. package/dist/styles/fade.js +0 -62
  247. package/dist/styles/fade.js.map +0 -1
  248. package/dist/styles/fill.d.ts +0 -42
  249. package/dist/styles/fill.js +0 -51
  250. package/dist/styles/fill.js.map +0 -1
  251. package/dist/styles/flow.d.ts +0 -16
  252. package/dist/styles/flow.js +0 -12
  253. package/dist/styles/flow.js.map +0 -1
  254. package/dist/styles/gap.d.ts +0 -31
  255. package/dist/styles/gap.js +0 -38
  256. package/dist/styles/gap.js.map +0 -1
  257. package/dist/styles/height.d.ts +0 -17
  258. package/dist/styles/height.js +0 -19
  259. package/dist/styles/height.js.map +0 -1
  260. package/dist/styles/index.d.ts +0 -1
  261. package/dist/styles/index.js +0 -8
  262. package/dist/styles/index.js.map +0 -1
  263. package/dist/styles/inset.d.ts +0 -24
  264. package/dist/styles/inset.js +0 -34
  265. package/dist/styles/inset.js.map +0 -1
  266. package/dist/styles/list.d.ts +0 -16
  267. package/dist/styles/list.js +0 -100
  268. package/dist/styles/list.js.map +0 -1
  269. package/dist/styles/margin.d.ts +0 -24
  270. package/dist/styles/margin.js +0 -32
  271. package/dist/styles/margin.js.map +0 -1
  272. package/dist/styles/outline.d.ts +0 -29
  273. package/dist/styles/outline.js +0 -55
  274. package/dist/styles/outline.js.map +0 -1
  275. package/dist/styles/padding.d.ts +0 -24
  276. package/dist/styles/padding.js +0 -32
  277. package/dist/styles/padding.js.map +0 -1
  278. package/dist/styles/placement.d.ts +0 -37
  279. package/dist/styles/placement.js +0 -74
  280. package/dist/styles/placement.js.map +0 -1
  281. package/dist/styles/predefined.d.ts +0 -71
  282. package/dist/styles/predefined.js +0 -237
  283. package/dist/styles/predefined.js.map +0 -1
  284. package/dist/styles/preset.d.ts +0 -52
  285. package/dist/styles/preset.js +0 -127
  286. package/dist/styles/preset.js.map +0 -1
  287. package/dist/styles/radius.d.ts +0 -12
  288. package/dist/styles/radius.js +0 -83
  289. package/dist/styles/radius.js.map +0 -1
  290. package/dist/styles/scrollMargin.d.ts +0 -24
  291. package/dist/styles/scrollMargin.js +0 -32
  292. package/dist/styles/scrollMargin.js.map +0 -1
  293. package/dist/styles/scrollbar.d.ts +0 -25
  294. package/dist/styles/scrollbar.js +0 -51
  295. package/dist/styles/scrollbar.js.map +0 -1
  296. package/dist/styles/shadow.d.ts +0 -14
  297. package/dist/styles/shadow.js +0 -25
  298. package/dist/styles/shadow.js.map +0 -1
  299. package/dist/styles/shared.js +0 -17
  300. package/dist/styles/shared.js.map +0 -1
  301. package/dist/styles/transition.d.ts +0 -14
  302. package/dist/styles/transition.js +0 -159
  303. package/dist/styles/transition.js.map +0 -1
  304. package/dist/styles/types.d.ts +0 -564
  305. package/dist/styles/width.d.ts +0 -17
  306. package/dist/styles/width.js +0 -19
  307. package/dist/styles/width.js.map +0 -1
  308. package/dist/tasty.d.ts +0 -134
  309. package/dist/tasty.js +0 -240
  310. package/dist/tasty.js.map +0 -1
  311. package/dist/types.d.ts +0 -184
  312. package/dist/utils/cache-wrapper.js +0 -21
  313. package/dist/utils/cache-wrapper.js.map +0 -1
  314. package/dist/utils/case-converter.js +0 -8
  315. package/dist/utils/case-converter.js.map +0 -1
  316. package/dist/utils/color-math.d.ts +0 -46
  317. package/dist/utils/color-math.js +0 -749
  318. package/dist/utils/color-math.js.map +0 -1
  319. package/dist/utils/color-space.d.ts +0 -5
  320. package/dist/utils/color-space.js +0 -228
  321. package/dist/utils/color-space.js.map +0 -1
  322. package/dist/utils/colors.d.ts +0 -5
  323. package/dist/utils/colors.js +0 -10
  324. package/dist/utils/colors.js.map +0 -1
  325. package/dist/utils/css-types.d.ts +0 -7
  326. package/dist/utils/dotize.d.ts +0 -26
  327. package/dist/utils/dotize.js +0 -122
  328. package/dist/utils/dotize.js.map +0 -1
  329. package/dist/utils/filter-base-props.d.ts +0 -15
  330. package/dist/utils/filter-base-props.js +0 -45
  331. package/dist/utils/filter-base-props.js.map +0 -1
  332. package/dist/utils/get-display-name.d.ts +0 -7
  333. package/dist/utils/get-display-name.js +0 -10
  334. package/dist/utils/get-display-name.js.map +0 -1
  335. package/dist/utils/has-keys.js +0 -13
  336. package/dist/utils/has-keys.js.map +0 -1
  337. package/dist/utils/is-dev-env.js +0 -19
  338. package/dist/utils/is-dev-env.js.map +0 -1
  339. package/dist/utils/is-valid-element-type.js +0 -15
  340. package/dist/utils/is-valid-element-type.js.map +0 -1
  341. package/dist/utils/merge-styles.js.map +0 -1
  342. package/dist/utils/mod-attrs.d.ts +0 -6
  343. package/dist/utils/mod-attrs.js +0 -20
  344. package/dist/utils/mod-attrs.js.map +0 -1
  345. package/dist/utils/process-tokens.d.ts +0 -17
  346. package/dist/utils/process-tokens.js +0 -83
  347. package/dist/utils/process-tokens.js.map +0 -1
  348. package/dist/utils/resolve-recipes.d.ts +0 -17
  349. package/dist/utils/resolve-recipes.js +0 -146
  350. package/dist/utils/resolve-recipes.js.map +0 -1
  351. package/dist/utils/selector-transform.js +0 -32
  352. package/dist/utils/selector-transform.js.map +0 -1
  353. package/dist/utils/string.js +0 -8
  354. package/dist/utils/string.js.map +0 -1
  355. package/dist/utils/styles.d.ts +0 -99
  356. package/dist/utils/styles.js +0 -220
  357. package/dist/utils/styles.js.map +0 -1
  358. package/dist/utils/typography.d.ts +0 -47
  359. package/dist/utils/typography.js +0 -51
  360. package/dist/utils/typography.js.map +0 -1
  361. package/dist/utils/warnings.d.ts +0 -16
  362. package/dist/utils/warnings.js +0 -16
  363. package/dist/utils/warnings.js.map +0 -1
  364. package/dist/zero/css-writer.d.ts +0 -45
  365. package/dist/zero/css-writer.js +0 -73
  366. package/dist/zero/css-writer.js.map +0 -1
  367. package/dist/zero/extractor.d.ts +0 -24
  368. package/dist/zero/extractor.js.map +0 -1
  369. package/docs/PIPELINE.md +0 -519
  370. /package/dist/{chunks/cacheKey.d.ts → ssr/astro-client.d.ts} +0 -0
@@ -1,6 +1,8 @@
1
1
  # Methodology
2
2
 
3
- Tasty has opinions about how components should be structured. The patterns described here are not mandatory — Tasty works without them — but following them gets the most out of the engine: deterministic state resolution, cleaner component APIs, simpler overrides, and fewer surprises as the system grows.
3
+ State maps keep a property’s branches from fighting. This guide applies the same goal to component architecture: keep state ownership explicit, expose intentional public APIs, and make extension predictable as a component system grows.
4
+
5
+ The patterns are recommended rather than required. Tasty works without them, but they help design-system teams carry its state-resolution guarantees across roots, sub-elements, typed props, tokens, and styled wrappers.
4
6
 
5
7
  ---
6
8
 
@@ -75,7 +77,7 @@ const Nav = tasty({
75
77
  '': '#text',
76
78
  '@own(:hover)': '#primary',
77
79
  '@own(:focus-visible)': '#primary',
78
- 'selected': '#primary',
80
+ selected: '#primary',
79
81
  },
80
82
  },
81
83
  },
@@ -117,16 +119,16 @@ Style props accept state maps, so responsive values work through the same API:
117
119
 
118
120
  Tasty exports predefined style prop lists that group properties by role. Use them instead of hand-picking arrays:
119
121
 
120
- | Preset | Properties | Typical use |
121
- |--------|-----------|-------------|
122
- | `FLOW_STYLES` | flow, gap, columnGap, rowGap, align, justify, placeItems, placeContent, alignItems, alignContent, justifyItems, justifyContent, gridColumns, gridRows, gridTemplate, gridAreas | Layout containers (`Space`, `Grid`) |
123
- | `POSITION_STYLES` | gridArea, gridColumn, gridRow, order, placeSelf, alignSelf, justifySelf, zIndex, margin, inset, position | Positioned elements (`Button`, `Badge`) |
124
- | `DIMENSION_STYLES` | width, height, flexBasis, flexGrow, flexShrink, flex | Sized elements |
125
- | `COLOR_STYLES` | color, fill, fade, image | Color-customizable elements |
126
- | `BLOCK_STYLES` | padding, paddingInline, paddingBlock, overflow, scrollbar, textAlign, border, radius, shadow, outline | Block-level containers |
127
- | `CONTAINER_STYLES` | All of the above combined (+ BASE_STYLES) | Fully flexible containers |
128
- | `OUTER_STYLES` | POSITION_STYLES + DIMENSION_STYLES + block outer (border, radius, shadow, outline) | Components whose outer shell is customizable |
129
- | `INNER_STYLES` | BASE_STYLES + COLOR_STYLES + block inner (padding, overflow, scrollbar) + FLOW_STYLES | Components whose inner layout is customizable |
122
+ | Preset | Properties | Typical use |
123
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------- |
124
+ | `FLOW_STYLES` | flow, gap, columnGap, rowGap, align, justify, placeItems, placeContent, alignItems, alignContent, justifyItems, justifyContent, gridColumns, gridRows, gridTemplate, gridAreas | Layout containers (`Space`, `Grid`) |
125
+ | `POSITION_STYLES` | gridArea, gridColumn, gridRow, order, placeSelf, alignSelf, justifySelf, zIndex, physical/logical margin, inset, scroll margin/padding, position | Positioned elements (`Button`, `Badge`) |
126
+ | `DIMENSION_STYLES` | width, height, blockSize, inlineSize, flexBasis, flexGrow, flexShrink, flex | Sized elements |
127
+ | `COLOR_STYLES` | color, fill, fade, image | Color-customizable elements |
128
+ | `BLOCK_STYLES` | padding, blockPadding, inlinePadding, overflow, scrollbar, textAlign, border, blockBorder, inlineBorder, radius, shadow, outline | Block-level containers |
129
+ | `CONTAINER_STYLES` | All of the above combined (+ BASE_STYLES) | Fully flexible containers |
130
+ | `OUTER_STYLES` | POSITION_STYLES + DIMENSION_STYLES + block outer (border, radius, shadow, outline) | Components whose outer shell is customizable |
131
+ | `INNER_STYLES` | BASE_STYLES + COLOR_STYLES + block inner (padding, overflow, scrollbar) + FLOW_STYLES | Components whose inner layout is customizable |
130
132
 
131
133
  ```tsx
132
134
  import { tasty, FLOW_STYLES, POSITION_STYLES } from '@tenphi/tasty';
@@ -159,7 +161,7 @@ Match the preset to the component's role:
159
161
 
160
162
  ### The governance trade-off
161
163
 
162
- Exposing every CSS property as a prop defeats the purpose of a design system. The more props a component exposes, the more ways product engineers can deviate from the intended design. A good rule of thumb: expose props that product engineers *need* to adjust for layout and composition, and keep visual identity (colors, borders, typography) controlled through the component definition, variants, or styled wrappers.
164
+ Exposing every CSS property as a prop defeats the purpose of a design system. The more props a component exposes, the more ways product engineers can deviate from the intended design. A good rule of thumb: expose props that product engineers _need_ to adjust for layout and composition, and keep visual identity (colors, borders, typography) controlled through the component definition, variants, or styled wrappers.
163
165
 
164
166
  ---
165
167
 
@@ -180,17 +182,19 @@ const Card = tasty({
180
182
  });
181
183
 
182
184
  // Clean prop API — no mods object needed
183
- <Card isLoading isSelected>Content</Card>
185
+ <Card isLoading isSelected>
186
+ Content
187
+ </Card>;
184
188
  ```
185
189
 
186
190
  ### When to use which
187
191
 
188
- | Pattern | Use when |
189
- |---|---|
190
- | `modProps` | The component has a fixed set of known boolean/string states that drive styles. Provides TypeScript autocomplete and a cleaner JSX API. |
191
- | `mods` prop | The component needs arbitrary or dynamic modifiers that aren't known at definition time. |
192
- | Both | Combine `modProps` for the known states and `mods` for ad-hoc overrides. Mod props take precedence. |
193
- | `styleProps` | Exposing CSS properties (layout, sizing) for customization — different from modifiers. |
192
+ | Pattern | Use when |
193
+ | ------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
194
+ | `modProps` | The component has a fixed set of known boolean/string states that drive styles. Provides TypeScript autocomplete and a cleaner JSX API. |
195
+ | `mods` prop | The component needs arbitrary or dynamic modifiers that aren't known at definition time. |
196
+ | Both | Combine `modProps` for the known states and `mods` for ad-hoc overrides. Mod props take precedence. |
197
+ | `styleProps` | Exposing CSS properties (layout, sizing) for customization — different from modifiers. |
194
198
 
195
199
  ### Typed modProps vs array form
196
200
 
@@ -214,7 +218,7 @@ The array form is simpler but types all values as `ModValue`:
214
218
  modProps: ['isLoading', 'isSelected'] as const,
215
219
  ```
216
220
 
217
- For the full API reference, see [Runtime — Mod Props](runtime.md#mod-props).
221
+ For the full API reference, see [React API — Mod Props](react-api.md#mod-props).
218
222
 
219
223
  ---
220
224
 
@@ -239,20 +243,20 @@ const ProgressBar = tasty({
239
243
  });
240
244
 
241
245
  // Usage: the progress value comes from a prop, not from styles
242
- <ProgressBar tokens={{ '$progress': `${percent}%` }} />
246
+ <ProgressBar tokens={{ $progress: `${percent}%` }} />;
243
247
  ```
244
248
 
245
249
  The `tokens` prop sets `style="--progress: 75%"` on the DOM element. The `$progress` reference in styles maps to `var(--progress)`, so the bar width updates without regenerating any CSS.
246
250
 
247
251
  ### When to use tokens vs other mechanisms
248
252
 
249
- | Need | Use |
250
- |------|-----|
251
- | Value changes per instance at render time (progress, user color, avatar size) | `tokens` prop (on component) |
252
- | Value is constant across all instances (card padding, border radius) | `configure({ tokens })` for `:root` CSS custom properties |
253
- | Value should be inlined at parse time (alias for another token) | `configure({ replaceTokens })` |
254
- | Value changes based on component state (hover, disabled, breakpoint) | State map in `styles` |
255
- | Value changes based on a variant (primary, danger, outline) | `variants` option |
253
+ | Need | Use |
254
+ | ----------------------------------------------------------------------------- | --------------------------------------------------------- |
255
+ | Value changes per instance at render time (progress, user color, avatar size) | `tokens` prop (on component) |
256
+ | Value is constant across all instances (card padding, border radius) | `configure({ tokens })` for `:root` CSS custom properties |
257
+ | Value should be inlined at parse time (alias for another token) | `configure({ replaceTokens })` |
258
+ | Value changes based on component state (hover, disabled, breakpoint) | State map in `styles` |
259
+ | Value changes based on a variant (primary, danger, outline) | `variants` option |
256
260
 
257
261
  Design tokens (via `configure({ tokens })`) are injected as CSS custom properties on `:root`. Replace tokens (via `configure({ replaceTokens })`) are resolved at parse time and baked into the generated CSS. The `tokens` prop on components is resolved at render time via inline CSS custom properties. Use design tokens for design-system constants, replace tokens for value aliases, and the `tokens` prop for truly dynamic per-instance values.
258
262
 
@@ -271,11 +275,11 @@ const ProgressBar = tasty({
271
275
  });
272
276
 
273
277
  // Clean prop API — no tokens object needed
274
- <ProgressBar progress="75%" accentColor="#purple" />
278
+ <ProgressBar progress="75%" accentColor="#purple" />;
275
279
 
276
280
  // Conversion:
277
281
  // 'progress' → $progress → --progress
278
- // 'accentColor' → #accent → --accent-color + --accent-color-oklch
282
+ // 'accentColor' → #accent → --accent-color
279
283
  ```
280
284
 
281
285
  #### Object form
@@ -291,7 +295,7 @@ const Card = tasty({
291
295
  styles: { padding: '$card-size', fill: '#card-accent' },
292
296
  });
293
297
 
294
- <Card size="4x" color="#purple" />
298
+ <Card size="4x" color="#purple" />;
295
299
  ```
296
300
 
297
301
  #### Merge order
@@ -326,7 +330,7 @@ const LargeCard = tasty(Card, {
326
330
  styles: { padding: '6x', Title: { color: '#danger' } },
327
331
  });
328
332
 
329
- <LargeCard />
333
+ <LargeCard />;
330
334
  ```
331
335
 
332
336
  Why? Styled wrappers are:
@@ -399,6 +403,34 @@ tasty(Button, {
399
403
 
400
404
  For full details on merge semantics, `@inherit`, `null`, and `false` tombstones, see [Style DSL — Extending vs. Replacing State Maps](dsl.md#extending-vs-replacing-state-maps).
401
405
 
406
+ ### Styling non-Tasty components or string tags
407
+
408
+ `tasty(Component, { ... })` always forwards every prop to `Component`, which means `Component` must be Tasty-aware (i.e. it knows how to consume `styles`, `mods`, `qa`, etc.). To apply styles to a third-party component (Next.js `Link`, `react-router`'s `Link`, Radix primitives, MUI, etc.) or to a plain DOM tag, use the options-only form with `as`:
409
+
410
+ ```tsx
411
+ import NextLink from 'next/link';
412
+
413
+ const Link = tasty({
414
+ as: NextLink,
415
+ styles: {
416
+ color: { '': '#accent-text', ':hover': '#text' },
417
+ textDecoration: 'underline',
418
+ },
419
+ styleProps: ['padding'],
420
+ });
421
+
422
+ const Span = tasty({
423
+ as: 'span',
424
+ styles: { preset: 'strong' },
425
+ });
426
+
427
+ <Link href="/blog" padding="1x">
428
+ Blog
429
+ </Link>;
430
+ ```
431
+
432
+ The wrapped component only needs to forward `className` (and ideally `style` and `ref`) to its underlying DOM node. Tasty-specific props (`qa`, `qaVal`, `mods`, `tokens`, `isDisabled`, `isHidden`, `isChecked`, and any `styleProps`/`modProps`/`tokenProps` you declared) are consumed by the wrapper and converted to `data-*` attributes or CSS custom properties — they never leak to the DOM.
433
+
402
434
  ### When to use styleProps vs wrapping
403
435
 
404
436
  If the component exposes the properties you need as `styleProps`, use them directly — that is what they are for:
@@ -567,7 +599,7 @@ Modifiers are compiled into exclusive selectors once. Changing `styles` at runti
567
599
 
568
600
  ```tsx
569
601
  // Bad: bypassing Tasty for custom styling
570
- <Button style={{ backgroundColor: 'red', padding: '12px 24px' }} />
602
+ <Button style={{ backgroundColor: 'red', padding: '12px 24px' }} />;
571
603
 
572
604
  // Good: create a styled wrapper
573
605
  const DangerButton = tasty(Button, {
@@ -584,7 +616,7 @@ The `style` prop bypasses tokens, units, and state maps. It should only be used
584
616
  <Card>
585
617
  <div data-element="Title">Card Title</div>
586
618
  <div data-element="Content">Card content</div>
587
- </Card>
619
+ </Card>;
588
620
 
589
621
  // Better: declare elements for typed sub-components
590
622
  const Card = tasty({
@@ -598,7 +630,7 @@ const Card = tasty({
598
630
  <Card>
599
631
  <Card.Title>Card Title</Card.Title>
600
632
  <Card.Content>Card content</Card.Content>
601
- </Card>
633
+ </Card>;
602
634
  ```
603
635
 
604
636
  The `elements` prop gives you typed sub-components with automatic `data-element` attributes, `mods` support, and better discoverability.
@@ -610,7 +642,7 @@ The `elements` prop gives you typed sub-components with automatic `data-element`
610
642
  - **[Getting Started](getting-started.md)** — Installation, first component, tooling setup
611
643
  - **[Building a Design System](design-system.md)** — Practical guide to building a DS layer with Tasty
612
644
  - **[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
645
+ - **[React API](react-api.md)** — `tasty()` factory, component props, variants, sub-elements, style functions
614
646
  - **[Configuration](configuration.md)** — Full `configure()` API: tokens, recipes, custom units, style handlers
615
647
  - **[Style Properties](styles.md)** — Complete reference for all enhanced style properties
616
648
  - **[Adoption Guide](adoption.md)** — Who should adopt Tasty, incremental phases, what changes for product engineers
@@ -0,0 +1,285 @@
1
+ # Migration Guide: v2 → v3
2
+
3
+ Everything that changes when you upgrade from `@tenphi/tasty` 2.x to 3.0, in the order you will hit it.
4
+
5
+ Most of the work is mechanical renames — see the [search-and-replace cheat sheet](#search-and-replace-cheat-sheet) at the end. The parts that need real attention are the [directional shorthand](#2-directional-shorthand) rule and the [behavior changes](#8-behavior-changes-that-are-not-renames).
6
+
7
+ - [At a glance](#at-a-glance)
8
+ - [1. Styles-object keys](#1-styles-object-keys)
9
+ - [2. Directional shorthand](#2-directional-shorthand)
10
+ - [3. Config keys](#3-config-keys)
11
+ - [4. Renamed exports](#4-renamed-exports)
12
+ - [5. Removed exports](#5-removed-exports)
13
+ - [6. Removed props](#6-removed-props)
14
+ - [7. Moved subpath](#7-moved-subpath)
15
+ - [8. Behavior changes that are not renames](#8-behavior-changes-that-are-not-renames)
16
+ - [9. New in v3](#9-new-in-v3)
17
+ - [Search-and-replace cheat sheet](#search-and-replace-cheat-sheet)
18
+ - [Not changed](#not-changed)
19
+
20
+ ---
21
+
22
+ ## At a glance
23
+
24
+ | v2.11 | v3.0 | Find it with |
25
+ | ------------------------------- | --------------------------------- | ------------------------------ |
26
+ | `'@properties': { … }` | `'@property': { … }` | `rg "'@properties'"` |
27
+ | `'@fontFace': { … }` | `'@font-face': { … }` | `rg "'@fontFace'"` |
28
+ | `'@counterStyle': { … }` | `'@counter-style': { … }` | `rg "'@counterStyle'"` |
29
+ | `padding: '2x 4x top right'` | `padding: '2x top, 4x right'` | dev-mode console warning |
30
+ | `fade: '3x 1x top bottom'` | `fade: '3x top, 1x bottom'` | dev-mode console warning |
31
+ | `configure({ funcs })` | `configure({ functions })` | `rg "funcs"` |
32
+ | `configure({ fontFace })` | `configure({ fontFaces })` | `rg "fontFace:"` |
33
+ | `configure({ counterStyle })` | `configure({ counterStyles })` | `rg "counterStyle:"` |
34
+ | `getCssText()` | `getCSSText()` | `rg "getCssText"` |
35
+ | `getCssTextForNode()` | `getCSSTextForNode()` | `rg "getCssTextForNode"` |
36
+ | `getCssTextForClasses()` | `getCSSTextForClasses()` | `rg "getCssTextForClasses"` |
37
+ | `getGlobalFontFace()` | `getGlobalFontFaces()` | `rg "getGlobalFontFace\b"` |
38
+ | `getGlobalCounterStyle()` | `getGlobalCounterStyles()` | `rg "getGlobalCounterStyle\b"` |
39
+ | `getGlobalFunction()` | `getGlobalFunctions()` | `rg "getGlobalFunction\b"` |
40
+ | `okhslFunc` / `okhstFunc` | `okhslFunction` / `okhstFunction` | `rg "okhs[lt]Func\b"` |
41
+ | `CssOptions` | `CSSOptions` | `rg "CssOptions"` |
42
+ | `ParserOptions.funcs` | `ParserOptions.functions` | `rg "funcs:"` |
43
+ | `StyleParser#setFuncs()` | `StyleParser#setFunctions()` | `rg "setFuncs"` |
44
+ | `ChunkInfo` (from `tastyDebug`) | `DebugChunkInfo` | `rg "ChunkInfo"` |
45
+ | `@tenphi/tasty/next` | `@tenphi/tasty/zero/next` | `rg "tasty/next"` |
46
+ | `getIsTestEnvironment()` | `isTestEnvironment()` | `rg "getIsTestEnvironment"` |
47
+ | `hydrateTastyCache()` | `hydrateTastyClasses()` | `rg "hydrateTastyCache"` |
48
+
49
+ ---
50
+
51
+ ## 1. Styles-object keys
52
+
53
+ At-rule keys now match the real CSS at-rule names Tasty already emits, so they are kebab-case rather than camelCase. The generated CSS is unchanged.
54
+
55
+ ```diff
56
+ const Card = tasty({
57
+ styles: {
58
+ - '@properties': { '$elevation': { syntax: '<number>' } },
59
+ - '@fontFace': { Inter: { src: 'url(/inter.woff2)' } },
60
+ - '@counterStyle': { dashes: { system: 'cyclic', symbols: '"—"' } },
61
+ + '@property': { '$elevation': { syntax: '<number>' } },
62
+ + '@font-face': { Inter: { src: 'url(/inter.woff2)' } },
63
+ + '@counter-style': { dashes: { system: 'cyclic', symbols: '"—"' } },
64
+ },
65
+ });
66
+ ```
67
+
68
+ `@keyframes` and `@starting` are unchanged — they were already spec-faithful.
69
+
70
+ ---
71
+
72
+ ## 2. Directional shorthand
73
+
74
+ **This is the one change that can alter rendered CSS without a rename.** A style group that names direction modifiers now takes a **single** value, applied to every direction it names.
75
+
76
+ The old form looked positional but never was: the parser buckets values and modifiers into separate arrays per comma group, so `'2x 4x top right'`, `'2x top 4x right'`, and `'top 2x right 4x'` were all the same input, and the pairing was decided by the order the _modifiers_ happened to appear in. `'1x 2x right top'` and `'1x 2x top right'` produced different CSS, and `'1x 2x top top'` silently assigned `top` twice.
77
+
78
+ Per-side values now come from comma-separated groups:
79
+
80
+ ```diff
81
+ - padding: '2x 4x top right'
82
+ + padding: '2x top, 4x right'
83
+
84
+ - margin: 'right 1x top 2x'
85
+ + margin: '1x right, 2x top'
86
+
87
+ - inset: 'left 2x right 1x'
88
+ + inset: '2x left, 1x right'
89
+
90
+ - fade: '3x 1x top bottom'
91
+ + fade: '3x top, 1x bottom'
92
+ ```
93
+
94
+ Affects `padding`, `margin`, `inset`, `scrollMargin`, and `fade`. Extra values are ignored with a **development-mode warning** naming the offending value, so run your app in dev and watch the console — that is the reliable way to find every occurrence. Production is silent and never throws.
95
+
96
+ **Unchanged:** single-value directional groups (`padding: '2x top'`, `'1x left right'`), every value-only CSS shorthand form (`padding: '1x 2x'`, `'1x 2x 3x 4x'`, and `fade: '3x 1x'` — a group that names no direction is unambiguous and keeps plain shorthand order), CSS-wide keywords, and the `longhand` modifier.
97
+
98
+ `inset`'s `dock` modifier keeps its two-value form with sharper semantics: the first value applies to the named edge, the second to the perpendicular sides it spans, so `inset: '2x 4x bottom dock'` still gives `auto 32px 16px 32px`. A third value with `dock`, or a second value without it, now warns.
99
+
100
+ ---
101
+
102
+ ## 3. Config keys
103
+
104
+ ```diff
105
+ configure({
106
+ - funcs: { double: (groups) => `calc(2 * ${groups[0].output})` },
107
+ - fontFace: { Inter: { src: 'url(/inter.woff2)' } },
108
+ - counterStyle: { dashes: { system: 'cyclic', symbols: '"—"' } },
109
+ + functions: { double: (groups) => `calc(2 * ${groups[0].output})` },
110
+ + fontFaces: { Inter: { src: 'url(/inter.woff2)' } },
111
+ + counterStyles: { dashes: { system: 'cyclic', symbols: '"—"' } },
112
+ });
113
+ ```
114
+
115
+ `functions` is a single map holding both flavors, discriminated by value type:
116
+
117
+ - **bare key + function value** → a parse-time function, called as `name(...)`
118
+ - **`$$name` key + object value** → a declarative CSS `@function`, called as `$$name(...)`
119
+
120
+ A key whose prefix doesn't match its value type is ignored with a development warning.
121
+
122
+ > If you are coming from a pre-release build of v3, note the intermediate `function` config key never shipped. Upgraders from 2.x only ever wrote `funcs`.
123
+
124
+ ---
125
+
126
+ ## 4. Renamed exports
127
+
128
+ **Raw-CSS family** — aligned on the `CSS` initialism already used by `useRawCSS` / `injectRawCSS` / `getRawCSSText`:
129
+
130
+ - `getCssText()` → `getCSSText()`
131
+ - `getCssTextForNode()` → `getCSSTextForNode()`
132
+ - `StyleInjector#getCssTextForClasses()` → `getCSSTextForClasses()`
133
+ - `CssOptions` → `CSSOptions`
134
+
135
+ **Config getters** — pluralized to match their already-plural config keys:
136
+
137
+ - `getGlobalFontFace()` → `getGlobalFontFaces()`
138
+ - `getGlobalCounterStyle()` → `getGlobalCounterStyles()`
139
+ - `getGlobalFunction()` → `getGlobalFunctions()`
140
+
141
+ **Color functions** — aligned with the `useFunction` / `FunctionDefinition` family:
142
+
143
+ - `okhslFunc` → `okhslFunction`
144
+ - `okhstFunc` → `okhstFunction`
145
+ - `createColorFunc(name, channelLabel, convert)` → `createColorFunc(name, convert, label?)` — the label is now an optional trailing argument used only to format development warnings
146
+
147
+ **Parser** (`@tenphi/tasty/core`):
148
+
149
+ - `ParserOptions.funcs` → `ParserOptions.functions`
150
+ - `StyleParser#setFuncs()` → `StyleParser#setFunctions()`
151
+
152
+ **Debug types:** the debug-local `ChunkInfo` is now `DebugChunkInfo`, so it no longer collides with the parser's `ChunkInfo`.
153
+
154
+ ---
155
+
156
+ ## 5. Removed exports
157
+
158
+ | Removed | Use instead |
159
+ | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
160
+ | `getIsTestEnvironment()` | `isTestEnvironment()` |
161
+ | `hydrateTastyCache()` | `hydrateTastyClasses()` |
162
+ | `customFunc()` | `configure({ functions })` |
163
+ | `getGlobalFuncs()` | `getGlobalFunctions()` for `@function` definitions; the parse-function registry is internal |
164
+ | `resetGlobalFuncs()` | `resetConfig()` |
165
+ | `setGlobalPredefinedTokens()` | `configure({ replaceTokens })` |
166
+ | `resetGlobalPredefinedTokens()` | `resetConfig()` |
167
+ | `setMiddlewareTransferCache()` / `getMiddlewareTransferCache()` | internal; no replacement needed |
168
+ | `clearWriterCache()` | internal test utility |
169
+ | `DEFAULT_PLUGINS` | nothing — it was never consumed, and passing it to `configure({ plugins })` was a no-op. The default `okhsl`/`okhst` functions are registered automatically. |
170
+ | `registerDefaultFunctions()` | internal bootstrap helper |
171
+ | `warn()` / `deprecationWarning()` | internal helpers with no callers |
172
+ | `Bucket` enum | parser-internal |
173
+ | `Props` type | inline `Record<string, any>` |
174
+ | `UseStylesOptions` | `useStyles()` takes `Styles \| undefined` directly |
175
+ | `GlobalStyledProps` | its only member was the already-dead `breakpoints` prop |
176
+ | duplicate `PropertyOptions` | the single `PropertyOptions` from `injector/types` |
177
+
178
+ `getGlobalFuncs()` deserves a note: it returned the **live mutable internal registry**, and writing to it bypassed the parser's cache invalidation, so the write silently never took effect. If you were mutating it, move to `configure({ functions })`.
179
+
180
+ ---
181
+
182
+ ## 6. Removed props
183
+
184
+ `css`, `block`, `inline`, and `breakpoints` are gone from `BaseProps` / `TastySpecificKeys`. All four were typed but never consumed — passing them did nothing in v2 either.
185
+
186
+ ---
187
+
188
+ ## 7. Moved subpath
189
+
190
+ ```diff
191
+ - import { withTasty } from '@tenphi/tasty/next';
192
+ + import { withTasty } from '@tenphi/tasty/zero/next';
193
+ ```
194
+
195
+ The build-time extraction Next.js wrapper already lived under the `zero` namespace internally; the top-level `/next` path collided confusingly with `@tenphi/tasty/ssr/next`, which is a different integration.
196
+
197
+ ---
198
+
199
+ ## 8. Behavior changes that are not renames
200
+
201
+ **Repeated `configure()` calls now merge.** `recipes`, `keyframes`, `properties`, `fontFaces`, `counterStyles`, and CSS `@function` definitions used to replace wholesale, so a design-system `configure()` followed by an application `configure()` silently dropped the design system's values. All of them now merge, with the later call winning on a key conflict — matching `tokens` and `globalStyles`, which already merged. If you were relying on a second call to _clear_ a collection, use `resetConfig()`.
202
+
203
+ `configure({ polyfills })` is now correctly rejected after the first render, like every sibling option, and shallow-merges so an unrelated later call cannot switch a polyfill off.
204
+
205
+ **The `theme` prop is now implemented.** It maps to a `data-theme` attribute on the rendered element; previously it fell through and was spread onto the DOM raw. Augment `TastyThemeNames` for autocomplete.
206
+
207
+ **`tasty(Component, options)` no longer leaks factory-only options.** `variants`, `elements`, `styleProps`, `modProps`, and `tokenProps` are stripped instead of being passed to the wrapped component as runtime props, matching the element factory.
208
+
209
+ **Replacing a built-in style handler now warns.** Built-in handlers are shared across style names, so `configure({ handlers: { fill } })` also takes over `image` and the whole `background-*` family, and `configure({ handlers: { display } })` takes down `flow`, `gap`, `hide`, `overflow`, `whiteSpace`, and `textOverflow`. This was always true; what's new is that a development-mode warning now names exactly what was displaced. If you see it, either declare the whole group and delegate the rest to `styleHandlers.*`, or pick a narrower name. See [Plugins](plugins.md#custom-style-handlers).
210
+
211
+ **Multi-dependency custom handlers are fixed.** A handler whose dependencies mixed known and unknown style names was invoked once per chunk with only _part_ of its dependencies, and could emit stale CSS. Unknown names now join their handler's chunk, so it is invoked once with all of them. No built-in style moved, so no existing class name changes.
212
+
213
+ **`isChecked` added to the root prop types.** It already worked at runtime; it was just missing from `BaseProps` / `AllBaseProps`.
214
+
215
+ **The `okhsl`/`okhst` "expected 3 values" warning is now development-only** and follows the `[Tasty]` prefix convention: `[Tasty] okhsl(): expected 3 values (H S L), got: …`. It previously fired in production.
216
+
217
+ ---
218
+
219
+ ## 9. New in v3
220
+
221
+ Nothing here is required to upgrade.
222
+
223
+ - **CSS `@function` support** — reusable, parameterized functions via the `'@function'` styles key, the `useFunction` style function, or `configure({ functions })`. Works across client rendering, SSR/RSC, and build-time extraction. `configure({ polyfills: { functions: true } })` inlines every call into plain CSS for browsers that don't ship the at-rule yet. See [Style DSL](dsl.md#functions-function).
224
+ - **Custom color plugins with no core special-casing** — `okhsl`/`okhst` are now ordinary one-line plugins, and a third-party color space can achieve identical integration. New `createColorFunc` and `resolveFunctionColor` helpers.
225
+ - **`configure({ propHandlers })`** — props middleware for every component: props in, props out. The extension point for props that aren't style values.
226
+ - **`configure({ baseStyleProps })`** — expose style properties as props on every component without listing them in each `styleProps`.
227
+ - **`defineHandler(deps, fn)`** — infers a multi-dependency handler's parameter types from its dependency list.
228
+ - **Plugins can supply `properties`, `keyframes`, `fontFaces`, and `counterStyles`** in addition to what they already could.
229
+ - See [Plugins & Extension Points](plugins.md) for all of the above.
230
+
231
+ ---
232
+
233
+ ## Search-and-replace cheat sheet
234
+
235
+ Run these in order — the `Css` → `CSS` renames must happen before any broader pattern, and the quoted at-rule keys must stay quote-anchored so they can't hit `configure({ properties })`.
236
+
237
+ ```bash
238
+ # 1. Raw-CSS family (before anything that touches "Css")
239
+ rg -l 'getCssTextForClasses' | xargs sed -i '' 's/getCssTextForClasses/getCSSTextForClasses/g'
240
+ rg -l 'getCssTextForNode' | xargs sed -i '' 's/getCssTextForNode/getCSSTextForNode/g'
241
+ rg -l 'getCssText' | xargs sed -i '' 's/getCssText/getCSSText/g'
242
+ rg -l 'CssOptions' | xargs sed -i '' 's/CssOptions/CSSOptions/g'
243
+
244
+ # 2. Styles-object at-rule keys (quote-anchored)
245
+ rg -l "'@properties'" | xargs sed -i '' "s/'@properties'/'@property'/g"
246
+ rg -l "'@fontFace'" | xargs sed -i '' "s/'@fontFace'/'@font-face'/g"
247
+ rg -l "'@counterStyle'" | xargs sed -i '' "s/'@counterStyle'/'@counter-style'/g"
248
+
249
+ # 3. Config getters (word-anchored so the plural forms are not double-pluralized)
250
+ rg -l 'getGlobalFontFace\b' | xargs sed -i '' 's/getGlobalFontFace\b/getGlobalFontFaces/g'
251
+ rg -l 'getGlobalCounterStyle\b' | xargs sed -i '' 's/getGlobalCounterStyle\b/getGlobalCounterStyles/g'
252
+ rg -l 'getGlobalFunction\b' | xargs sed -i '' 's/getGlobalFunction\b/getGlobalFunctions/g'
253
+
254
+ # 4. Color functions and parser methods
255
+ rg -l 'okhslFunc\b' | xargs sed -i '' 's/okhslFunc\b/okhslFunction/g'
256
+ rg -l 'okhstFunc\b' | xargs sed -i '' 's/okhstFunc\b/okhstFunction/g'
257
+ rg -l 'setFuncs' | xargs sed -i '' 's/setFuncs/setFunctions/g'
258
+
259
+ # 5. Removed exports with direct replacements
260
+ rg -l 'getIsTestEnvironment' | xargs sed -i '' 's/getIsTestEnvironment/isTestEnvironment/g'
261
+ rg -l 'hydrateTastyCache' | xargs sed -i '' 's/hydrateTastyCache/hydrateTastyClasses/g'
262
+
263
+ # 6. Moved subpath
264
+ rg -l "@tenphi/tasty/next" | xargs sed -i '' "s|@tenphi/tasty/next|@tenphi/tasty/zero/next|g"
265
+
266
+ # 7. Verify nothing is left (should print nothing)
267
+ rg "getCssText|CssOptions|'@properties'|'@fontFace'|'@counterStyle'|okhs[lt]Func\b|setFuncs|getIsTestEnvironment|hydrateTastyCache|@tenphi/tasty/next|getGlobalFontFace\b|getGlobalCounterStyle\b|getGlobalFunction\b"
268
+ ```
269
+
270
+ `configure({ funcs })` → `functions`, `fontFace` → `fontFaces`, and `counterStyle` → `counterStyles` are deliberately **not** scripted: those words appear in many other contexts, so change them by hand and let TypeScript find the call sites.
271
+
272
+ The directional shorthand cannot be scripted at all — the whole point is that the old form's meaning was not recoverable from its text. Run your app in development and follow the console warnings.
273
+
274
+ ---
275
+
276
+ ## Not changed
277
+
278
+ Worth stating explicitly, because it's easy to assume otherwise:
279
+
280
+ - **At-rule styles-object keys are CSS-spec-faithful, not JS-conventional.** `@keyframes`, `@property`, `@font-face`, `@counter-style`, `@function`, `@starting` — kebab-case, matching what Tasty emits.
281
+ - **The `func()` injector method stays abbreviated.** `function` is a reserved word.
282
+ - `injector.fontFace()` and `injector.counterStyle()` keep their singular names — only the _config keys_ and _getters_ were pluralized.
283
+ - `useFontFace` and `useCounterStyle` are unchanged.
284
+ - `configure({ properties })` and `autoPropertyTypes` are unchanged; only the styles-object `@property` key was renamed.
285
+ - **The deprecated style aliases are retained deliberately.** `backgroundColor`, `background`, `backgroundImage`, `flex`, `grid`, and `flexDirection` still carry `@deprecated` tags and still work. They are the guardrail that discourages their use in projects that have not enabled `@tenphi/eslint-plugin-tasty` yet — read the tags as guidance, not as a removal notice.