@tenphi/tasty 0.0.0-snapshot.1c5dff6 → 0.0.0-snapshot.1f1c00a

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 (331) hide show
  1. package/README.md +377 -238
  2. package/dist/babel-rZcEwPLM.d.ts +82 -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-CL4eRu2z.js +42 -0
  6. package/dist/chunks/build-config-CL4eRu2z.js.map +1 -0
  7. package/dist/chunks/collector-D2ARGT2L.js +208 -0
  8. package/dist/chunks/collector-D2ARGT2L.js.map +1 -0
  9. package/dist/chunks/config-engine-DEmmPPdp.js +272 -0
  10. package/dist/chunks/config-engine-DEmmPPdp.js.map +1 -0
  11. package/dist/chunks/css-definitions-DotDkIXt.js +876 -0
  12. package/dist/chunks/css-definitions-DotDkIXt.js.map +1 -0
  13. package/dist/chunks/css-resources-P7IBUUZs.js +142 -0
  14. package/dist/chunks/css-resources-P7IBUUZs.js.map +1 -0
  15. package/dist/chunks/debug-D8pg9RGI.js +502 -0
  16. package/dist/chunks/debug-D8pg9RGI.js.map +1 -0
  17. package/dist/chunks/dsl-DRhFWQzo.js +1378 -0
  18. package/dist/chunks/dsl-DRhFWQzo.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-BpxlOTbO.js +562 -0
  22. package/dist/chunks/react-runtime-BpxlOTbO.js.map +1 -0
  23. package/dist/chunks/runtime-engine-CKFXUH-A.js +2416 -0
  24. package/dist/chunks/runtime-engine-CKFXUH-A.js.map +1 -0
  25. package/dist/chunks/runtime-state-BxaLhVdP.js +127 -0
  26. package/dist/chunks/runtime-state-BxaLhVdP.js.map +1 -0
  27. package/dist/{utils/merge-styles.js → chunks/shared-utils-y-HjvPN4.js} +61 -58
  28. package/dist/chunks/shared-utils-y-HjvPN4.js.map +1 -0
  29. package/dist/chunks/style-engine-BBbBuSkT.js +5260 -0
  30. package/dist/chunks/style-engine-BBbBuSkT.js.map +1 -0
  31. package/dist/{zero/extractor.js → chunks/zero-engine-gJrKBRiw.js} +126 -66
  32. package/dist/chunks/zero-engine-gJrKBRiw.js.map +1 -0
  33. package/dist/collector-w4mBj5gd.d.ts +164 -0
  34. package/dist/config-CZWCzBr6.d.ts +1349 -0
  35. package/dist/core/index.d.ts +5 -33
  36. package/dist/core/index.js +9 -26
  37. package/dist/index-G9JuwM9p.d.ts +1920 -0
  38. package/dist/index.d.ts +5 -48
  39. package/dist/index.js +11 -33
  40. package/dist/{utils/merge-styles.d.ts → merge-styles-VXwJ0Frr.d.ts} +3 -4
  41. package/dist/ssr/astro-client.d.ts +1 -0
  42. package/dist/ssr/astro-client.js +6 -0
  43. package/dist/ssr/astro-client.js.map +1 -0
  44. package/dist/ssr/astro-middleware-extract-static.d.ts +10 -0
  45. package/dist/ssr/astro-middleware-extract-static.js +9 -0
  46. package/dist/ssr/astro-middleware-extract-static.js.map +1 -0
  47. package/dist/ssr/astro-middleware-extract.d.ts +10 -0
  48. package/dist/ssr/astro-middleware-extract.js +9 -0
  49. package/dist/ssr/astro-middleware-extract.js.map +1 -0
  50. package/dist/ssr/astro-middleware-static.d.ts +17 -0
  51. package/dist/ssr/astro-middleware-static.js +7 -0
  52. package/dist/ssr/astro-middleware-static.js.map +1 -0
  53. package/dist/ssr/astro-middleware.d.ts +18 -0
  54. package/dist/ssr/astro-middleware.js +7 -0
  55. package/dist/ssr/astro-middleware.js.map +1 -0
  56. package/dist/ssr/astro.d.ts +127 -0
  57. package/dist/ssr/astro.js +221 -0
  58. package/dist/ssr/astro.js.map +1 -0
  59. package/dist/ssr/index.d.ts +36 -0
  60. package/dist/ssr/index.js +10 -0
  61. package/dist/ssr/index.js.map +1 -0
  62. package/dist/ssr/next-config.d.ts +64 -0
  63. package/dist/ssr/next-config.js +128 -0
  64. package/dist/ssr/next-config.js.map +1 -0
  65. package/dist/ssr/next.d.ts +46 -0
  66. package/dist/ssr/next.js +60 -0
  67. package/dist/ssr/next.js.map +1 -0
  68. package/dist/static/index.d.ts +90 -5
  69. package/dist/static/index.js +31 -4
  70. package/dist/static/index.js.map +1 -0
  71. package/dist/static/inject.d.ts +4 -0
  72. package/dist/static/inject.js +17 -0
  73. package/dist/static/inject.js.map +1 -0
  74. package/dist/types-JEY8PVYP.d.ts +1567 -0
  75. package/dist/zero/babel.d.ts +2 -113
  76. package/dist/zero/babel.js +230 -106
  77. package/dist/zero/babel.js.map +1 -1
  78. package/dist/zero/index.d.ts +80 -3
  79. package/dist/zero/index.js +2 -4
  80. package/dist/zero/next.d.ts +57 -33
  81. package/dist/zero/next.js +93 -59
  82. package/dist/zero/next.js.map +1 -1
  83. package/docs/README.md +39 -0
  84. package/docs/adoption.md +323 -0
  85. package/docs/ai-agents.md +250 -0
  86. package/docs/comparison.md +448 -0
  87. package/docs/configuration.md +684 -56
  88. package/docs/debug.md +170 -343
  89. package/docs/design-system.md +455 -0
  90. package/docs/dsl.md +1065 -0
  91. package/docs/getting-started.md +240 -0
  92. package/docs/injector.md +159 -53
  93. package/docs/methodology.md +648 -0
  94. package/docs/migration-v3.md +285 -0
  95. package/docs/pipeline.md +765 -0
  96. package/docs/plugins.md +353 -0
  97. package/docs/react-api.md +683 -0
  98. package/docs/runtime-benchmarks.md +388 -0
  99. package/docs/ssr.md +610 -0
  100. package/docs/styles.md +211 -63
  101. package/docs/tasty-static.md +273 -67
  102. package/package.json +182 -58
  103. package/tasty.config.ts +6 -0
  104. package/dist/_virtual/_rolldown/runtime.js +0 -8
  105. package/dist/chunks/cacheKey.js +0 -70
  106. package/dist/chunks/cacheKey.js.map +0 -1
  107. package/dist/chunks/definitions.d.ts +0 -37
  108. package/dist/chunks/definitions.js +0 -260
  109. package/dist/chunks/definitions.js.map +0 -1
  110. package/dist/chunks/renderChunk.js +0 -61
  111. package/dist/chunks/renderChunk.js.map +0 -1
  112. package/dist/config.d.ts +0 -288
  113. package/dist/config.js +0 -403
  114. package/dist/config.js.map +0 -1
  115. package/dist/debug.d.ts +0 -204
  116. package/dist/debug.js +0 -733
  117. package/dist/debug.js.map +0 -1
  118. package/dist/hooks/useGlobalStyles.d.ts +0 -27
  119. package/dist/hooks/useGlobalStyles.js +0 -56
  120. package/dist/hooks/useGlobalStyles.js.map +0 -1
  121. package/dist/hooks/useKeyframes.d.ts +0 -56
  122. package/dist/hooks/useKeyframes.js +0 -54
  123. package/dist/hooks/useKeyframes.js.map +0 -1
  124. package/dist/hooks/useProperty.d.ts +0 -79
  125. package/dist/hooks/useProperty.js +0 -91
  126. package/dist/hooks/useProperty.js.map +0 -1
  127. package/dist/hooks/useRawCSS.d.ts +0 -53
  128. package/dist/hooks/useRawCSS.js +0 -28
  129. package/dist/hooks/useRawCSS.js.map +0 -1
  130. package/dist/hooks/useStyles.d.ts +0 -40
  131. package/dist/hooks/useStyles.js +0 -169
  132. package/dist/hooks/useStyles.js.map +0 -1
  133. package/dist/injector/index.d.ts +0 -157
  134. package/dist/injector/index.js +0 -154
  135. package/dist/injector/index.js.map +0 -1
  136. package/dist/injector/injector.d.ts +0 -139
  137. package/dist/injector/injector.js +0 -417
  138. package/dist/injector/injector.js.map +0 -1
  139. package/dist/injector/sheet-manager.d.ts +0 -135
  140. package/dist/injector/sheet-manager.js +0 -728
  141. package/dist/injector/sheet-manager.js.map +0 -1
  142. package/dist/injector/types.d.ts +0 -144
  143. package/dist/keyframes/index.js +0 -206
  144. package/dist/keyframes/index.js.map +0 -1
  145. package/dist/parser/classify.js +0 -319
  146. package/dist/parser/classify.js.map +0 -1
  147. package/dist/parser/const.js +0 -33
  148. package/dist/parser/const.js.map +0 -1
  149. package/dist/parser/lru.js +0 -109
  150. package/dist/parser/lru.js.map +0 -1
  151. package/dist/parser/parser.d.ts +0 -25
  152. package/dist/parser/parser.js +0 -116
  153. package/dist/parser/parser.js.map +0 -1
  154. package/dist/parser/tokenizer.js +0 -69
  155. package/dist/parser/tokenizer.js.map +0 -1
  156. package/dist/parser/types.d.ts +0 -51
  157. package/dist/parser/types.js +0 -46
  158. package/dist/parser/types.js.map +0 -1
  159. package/dist/pipeline/conditions.d.ts +0 -134
  160. package/dist/pipeline/conditions.js +0 -406
  161. package/dist/pipeline/conditions.js.map +0 -1
  162. package/dist/pipeline/exclusive.js +0 -231
  163. package/dist/pipeline/exclusive.js.map +0 -1
  164. package/dist/pipeline/index.d.ts +0 -53
  165. package/dist/pipeline/index.js +0 -660
  166. package/dist/pipeline/index.js.map +0 -1
  167. package/dist/pipeline/materialize.js +0 -856
  168. package/dist/pipeline/materialize.js.map +0 -1
  169. package/dist/pipeline/parseStateKey.d.ts +0 -15
  170. package/dist/pipeline/parseStateKey.js +0 -451
  171. package/dist/pipeline/parseStateKey.js.map +0 -1
  172. package/dist/pipeline/simplify.js +0 -516
  173. package/dist/pipeline/simplify.js.map +0 -1
  174. package/dist/pipeline/warnings.js +0 -18
  175. package/dist/pipeline/warnings.js.map +0 -1
  176. package/dist/plugins/okhsl-plugin.d.ts +0 -35
  177. package/dist/plugins/okhsl-plugin.js +0 -371
  178. package/dist/plugins/okhsl-plugin.js.map +0 -1
  179. package/dist/plugins/types.d.ts +0 -69
  180. package/dist/properties/index.js +0 -221
  181. package/dist/properties/index.js.map +0 -1
  182. package/dist/properties/property-type-resolver.d.ts +0 -24
  183. package/dist/properties/property-type-resolver.js +0 -83
  184. package/dist/properties/property-type-resolver.js.map +0 -1
  185. package/dist/states/index.d.ts +0 -49
  186. package/dist/states/index.js +0 -416
  187. package/dist/states/index.js.map +0 -1
  188. package/dist/static/tastyStatic.d.ts +0 -46
  189. package/dist/static/tastyStatic.js +0 -31
  190. package/dist/static/tastyStatic.js.map +0 -1
  191. package/dist/static/types.d.ts +0 -49
  192. package/dist/static/types.js +0 -24
  193. package/dist/static/types.js.map +0 -1
  194. package/dist/styles/align.d.ts +0 -15
  195. package/dist/styles/align.js +0 -14
  196. package/dist/styles/align.js.map +0 -1
  197. package/dist/styles/border.d.ts +0 -25
  198. package/dist/styles/border.js +0 -114
  199. package/dist/styles/border.js.map +0 -1
  200. package/dist/styles/color.d.ts +0 -14
  201. package/dist/styles/color.js +0 -23
  202. package/dist/styles/color.js.map +0 -1
  203. package/dist/styles/createStyle.js +0 -77
  204. package/dist/styles/createStyle.js.map +0 -1
  205. package/dist/styles/dimension.js +0 -97
  206. package/dist/styles/dimension.js.map +0 -1
  207. package/dist/styles/display.d.ts +0 -37
  208. package/dist/styles/display.js +0 -67
  209. package/dist/styles/display.js.map +0 -1
  210. package/dist/styles/fade.d.ts +0 -15
  211. package/dist/styles/fade.js +0 -58
  212. package/dist/styles/fade.js.map +0 -1
  213. package/dist/styles/fill.d.ts +0 -42
  214. package/dist/styles/fill.js +0 -52
  215. package/dist/styles/fill.js.map +0 -1
  216. package/dist/styles/flow.d.ts +0 -16
  217. package/dist/styles/flow.js +0 -12
  218. package/dist/styles/flow.js.map +0 -1
  219. package/dist/styles/gap.d.ts +0 -31
  220. package/dist/styles/gap.js +0 -37
  221. package/dist/styles/gap.js.map +0 -1
  222. package/dist/styles/height.d.ts +0 -17
  223. package/dist/styles/height.js +0 -20
  224. package/dist/styles/height.js.map +0 -1
  225. package/dist/styles/index.d.ts +0 -2
  226. package/dist/styles/index.js +0 -9
  227. package/dist/styles/index.js.map +0 -1
  228. package/dist/styles/inset.d.ts +0 -52
  229. package/dist/styles/inset.js +0 -150
  230. package/dist/styles/inset.js.map +0 -1
  231. package/dist/styles/justify.d.ts +0 -15
  232. package/dist/styles/justify.js +0 -14
  233. package/dist/styles/justify.js.map +0 -1
  234. package/dist/styles/list.d.ts +0 -16
  235. package/dist/styles/list.js +0 -98
  236. package/dist/styles/list.js.map +0 -1
  237. package/dist/styles/margin.d.ts +0 -24
  238. package/dist/styles/margin.js +0 -104
  239. package/dist/styles/margin.js.map +0 -1
  240. package/dist/styles/outline.d.ts +0 -29
  241. package/dist/styles/outline.js +0 -65
  242. package/dist/styles/outline.js.map +0 -1
  243. package/dist/styles/padding.d.ts +0 -24
  244. package/dist/styles/padding.js +0 -104
  245. package/dist/styles/padding.js.map +0 -1
  246. package/dist/styles/predefined.d.ts +0 -73
  247. package/dist/styles/predefined.js +0 -241
  248. package/dist/styles/predefined.js.map +0 -1
  249. package/dist/styles/preset.d.ts +0 -47
  250. package/dist/styles/preset.js +0 -126
  251. package/dist/styles/preset.js.map +0 -1
  252. package/dist/styles/radius.d.ts +0 -14
  253. package/dist/styles/radius.js +0 -51
  254. package/dist/styles/radius.js.map +0 -1
  255. package/dist/styles/scrollbar.d.ts +0 -23
  256. package/dist/styles/scrollbar.js +0 -34
  257. package/dist/styles/scrollbar.js.map +0 -1
  258. package/dist/styles/shadow.d.ts +0 -14
  259. package/dist/styles/shadow.js +0 -24
  260. package/dist/styles/shadow.js.map +0 -1
  261. package/dist/styles/styledScrollbar.d.ts +0 -47
  262. package/dist/styles/styledScrollbar.js +0 -38
  263. package/dist/styles/styledScrollbar.js.map +0 -1
  264. package/dist/styles/transition.d.ts +0 -14
  265. package/dist/styles/transition.js +0 -158
  266. package/dist/styles/transition.js.map +0 -1
  267. package/dist/styles/types.d.ts +0 -498
  268. package/dist/styles/width.d.ts +0 -17
  269. package/dist/styles/width.js +0 -20
  270. package/dist/styles/width.js.map +0 -1
  271. package/dist/tasty.d.ts +0 -982
  272. package/dist/tasty.js +0 -206
  273. package/dist/tasty.js.map +0 -1
  274. package/dist/tokens/typography.d.ts +0 -19
  275. package/dist/tokens/typography.js +0 -237
  276. package/dist/tokens/typography.js.map +0 -1
  277. package/dist/types.d.ts +0 -184
  278. package/dist/utils/cache-wrapper.js +0 -26
  279. package/dist/utils/cache-wrapper.js.map +0 -1
  280. package/dist/utils/case-converter.js +0 -8
  281. package/dist/utils/case-converter.js.map +0 -1
  282. package/dist/utils/colors.d.ts +0 -5
  283. package/dist/utils/colors.js +0 -9
  284. package/dist/utils/colors.js.map +0 -1
  285. package/dist/utils/css-types.d.ts +0 -7
  286. package/dist/utils/dotize.d.ts +0 -26
  287. package/dist/utils/dotize.js +0 -122
  288. package/dist/utils/dotize.js.map +0 -1
  289. package/dist/utils/filter-base-props.d.ts +0 -15
  290. package/dist/utils/filter-base-props.js +0 -45
  291. package/dist/utils/filter-base-props.js.map +0 -1
  292. package/dist/utils/get-display-name.d.ts +0 -7
  293. package/dist/utils/get-display-name.js +0 -10
  294. package/dist/utils/get-display-name.js.map +0 -1
  295. package/dist/utils/hsl-to-rgb.js +0 -38
  296. package/dist/utils/hsl-to-rgb.js.map +0 -1
  297. package/dist/utils/is-dev-env.js +0 -19
  298. package/dist/utils/is-dev-env.js.map +0 -1
  299. package/dist/utils/is-valid-element-type.js +0 -15
  300. package/dist/utils/is-valid-element-type.js.map +0 -1
  301. package/dist/utils/merge-styles.js.map +0 -1
  302. package/dist/utils/mod-attrs.d.ts +0 -8
  303. package/dist/utils/mod-attrs.js +0 -21
  304. package/dist/utils/mod-attrs.js.map +0 -1
  305. package/dist/utils/okhsl-to-rgb.js +0 -296
  306. package/dist/utils/okhsl-to-rgb.js.map +0 -1
  307. package/dist/utils/process-tokens.d.ts +0 -31
  308. package/dist/utils/process-tokens.js +0 -171
  309. package/dist/utils/process-tokens.js.map +0 -1
  310. package/dist/utils/resolve-recipes.d.ts +0 -17
  311. package/dist/utils/resolve-recipes.js +0 -147
  312. package/dist/utils/resolve-recipes.js.map +0 -1
  313. package/dist/utils/selector-transform.js +0 -32
  314. package/dist/utils/selector-transform.js.map +0 -1
  315. package/dist/utils/string.js +0 -8
  316. package/dist/utils/string.js.map +0 -1
  317. package/dist/utils/styles.d.ts +0 -177
  318. package/dist/utils/styles.js +0 -730
  319. package/dist/utils/styles.js.map +0 -1
  320. package/dist/utils/typography.d.ts +0 -36
  321. package/dist/utils/typography.js +0 -53
  322. package/dist/utils/typography.js.map +0 -1
  323. package/dist/utils/warnings.d.ts +0 -16
  324. package/dist/utils/warnings.js +0 -16
  325. package/dist/utils/warnings.js.map +0 -1
  326. package/dist/zero/css-writer.d.ts +0 -45
  327. package/dist/zero/css-writer.js +0 -74
  328. package/dist/zero/css-writer.js.map +0 -1
  329. package/dist/zero/extractor.d.ts +0 -24
  330. package/dist/zero/extractor.js.map +0 -1
  331. package/docs/usage.md +0 -695
@@ -1,416 +0,0 @@
1
- import { isDevEnv } from "../utils/is-dev-env.js";
2
- import { hasStylesGenerated } from "../config.js";
3
-
4
- //#region src/states/index.ts
5
- /**
6
- * Advanced State Mapping - Predefined States Management
7
- *
8
- * This module handles global and local predefined states for the Tasty styling system.
9
- * See ADVANCED_STATE_MAPPING.md for full specification.
10
- */
11
- const BUILTIN_STATES = new Set([
12
- "@starting",
13
- "@keyframes",
14
- "@properties",
15
- "@supports",
16
- "@inherit"
17
- ]);
18
- const RESERVED_PREFIXES = [
19
- "@media",
20
- "@root",
21
- "@parent",
22
- "@own",
23
- "@(",
24
- "@starting",
25
- "@keyframes",
26
- "@properties",
27
- "@supports",
28
- "@inherit"
29
- ];
30
- let globalPredefinedStates = {};
31
- const emittedWarnings = /* @__PURE__ */ new Set();
32
- const devMode = isDevEnv();
33
- /**
34
- * Emit a warning only once
35
- */
36
- function warnOnce(key, message) {
37
- if (devMode && !emittedWarnings.has(key)) {
38
- emittedWarnings.add(key);
39
- console.warn(message);
40
- }
41
- }
42
- /**
43
- * Configure global predefined states
44
- */
45
- function setGlobalPredefinedStates(states) {
46
- if (hasStylesGenerated()) {
47
- const newStateNames = Object.keys(states).join(", ");
48
- warnOnce(`dynamic-states:${newStateNames}`, `[Tasty] Cannot update predefined states after styles have been generated.\nThe new definition(s) for ${newStateNames} will be ignored.`);
49
- return;
50
- }
51
- for (const [name, value] of Object.entries(states)) {
52
- if (!/^@[A-Za-z][A-Za-z0-9-]*$/.test(name)) {
53
- warnOnce(`invalid-state-name:${name}`, `[Tasty] Invalid predefined state name '${name}'. Must start with '@' followed by a letter.`);
54
- continue;
55
- }
56
- if (BUILTIN_STATES.has(name)) {
57
- warnOnce(`reserved-state:${name}`, `[Tasty] Cannot define predefined state '${name}'. This name is reserved for built-in functionality.`);
58
- continue;
59
- }
60
- if (name === "@media" || name === "@root" || name === "@parent" || name === "@own" || name.startsWith("@(")) {
61
- warnOnce(`reserved-prefix:${name}`, `[Tasty] Cannot define predefined state '${name}'. This prefix is reserved for built-in functionality.`);
62
- continue;
63
- }
64
- const crossRefs = extractPredefinedStateRefs(value);
65
- if (crossRefs.length > 0) {
66
- warnOnce(`cross-ref:${name}`, `[Tasty] Predefined state '${name}' references another predefined state '${crossRefs[0]}'.\nPredefined states cannot reference each other. Use the full definition instead.`);
67
- continue;
68
- }
69
- if (globalPredefinedStates[name] && globalPredefinedStates[name] !== value) warnOnce(`duplicate-state:${name}`, `[Tasty] Duplicate predefined state '${name}' in configure(). The last definition will be used.`);
70
- globalPredefinedStates[name] = value;
71
- }
72
- }
73
- /**
74
- * Get global predefined states
75
- */
76
- function getGlobalPredefinedStates() {
77
- return globalPredefinedStates;
78
- }
79
- /**
80
- * Regex to match predefined state references in a string
81
- * Matches @name that is NOT followed by ( or : and is a complete word
82
- * Uses word boundary and negative lookahead
83
- */
84
- const PREDEFINED_STATE_PATTERN = /@([A-Za-z][A-Za-z0-9-]*)(?![A-Za-z0-9-:(])/g;
85
- /**
86
- * Extract predefined state references from a string
87
- */
88
- function extractPredefinedStateRefs(value) {
89
- const matches = value.matchAll(PREDEFINED_STATE_PATTERN);
90
- const refs = [];
91
- for (const match of matches) {
92
- const stateName = "@" + match[1];
93
- if (!BUILTIN_STATES.has(stateName) && !refs.includes(stateName)) refs.push(stateName);
94
- }
95
- return refs;
96
- }
97
- /**
98
- * Check if a state key is a predefined state reference
99
- */
100
- function isPredefinedStateRef(stateKey) {
101
- if (!stateKey.startsWith("@")) return false;
102
- if (BUILTIN_STATES.has(stateKey)) return false;
103
- for (const prefix of RESERVED_PREFIXES) if (stateKey === prefix || stateKey.startsWith(prefix)) {
104
- if (stateKey === "@media" || stateKey.startsWith("@media(") || stateKey.startsWith("@media:")) return false;
105
- if (stateKey === "@root" || stateKey.startsWith("@root(")) return false;
106
- if (stateKey === "@parent" || stateKey.startsWith("@parent(")) return false;
107
- if (stateKey === "@own" || stateKey.startsWith("@own(")) return false;
108
- if (stateKey.startsWith("@(")) return false;
109
- }
110
- return /^@[A-Za-z][A-Za-z0-9-]*$/.test(stateKey);
111
- }
112
- /**
113
- * Extract local predefined states from a styles object
114
- * Local predefined states are top-level keys starting with @ that have string values
115
- * and are valid predefined state names (not built-in like @media, @root, etc.)
116
- */
117
- function extractLocalPredefinedStates(styles) {
118
- const localStates = {};
119
- if (!styles || typeof styles !== "object") return localStates;
120
- for (const [key, value] of Object.entries(styles)) if (key.startsWith("@") && typeof value === "string") {
121
- if (!/^@[A-Za-z][A-Za-z0-9-]*$/.test(key)) continue;
122
- if (BUILTIN_STATES.has(key)) continue;
123
- if (key === "@media" || key === "@root" || key === "@parent" || key === "@own" || key.startsWith("@(")) continue;
124
- const crossRefs = extractPredefinedStateRefs(value);
125
- if (crossRefs.length > 0) {
126
- warnOnce(`local-cross-ref:${key}`, `[Tasty] Predefined state '${key}' references another predefined state '${crossRefs[0]}'.\nPredefined states cannot reference each other. Use the full definition instead.`);
127
- continue;
128
- }
129
- localStates[key] = value;
130
- }
131
- return localStates;
132
- }
133
- /**
134
- * Create a state parser context from styles
135
- */
136
- function createStateParserContext(styles, isSubElement) {
137
- return {
138
- localPredefinedStates: styles ? extractLocalPredefinedStates(styles) : {},
139
- globalPredefinedStates: getGlobalPredefinedStates(),
140
- isSubElement
141
- };
142
- }
143
- /**
144
- * Resolve a predefined state reference to its value
145
- * Returns the resolved value or null if not found
146
- */
147
- function resolvePredefinedState(stateKey, ctx) {
148
- if (ctx.localPredefinedStates[stateKey]) return ctx.localPredefinedStates[stateKey];
149
- if (ctx.globalPredefinedStates[stateKey]) return ctx.globalPredefinedStates[stateKey];
150
- warnOnce(`undefined-state:${stateKey}`, `[Tasty] Undefined predefined state '${stateKey}'.\nDefine it in configure({ states: { '${stateKey}': '...' } }) or in the component's styles.`);
151
- return null;
152
- }
153
- /**
154
- * Expand dimension shorthands in a condition string
155
- * w -> width, h -> height, is -> inline-size, bs -> block-size
156
- */
157
- function expandDimensionShorthands(condition) {
158
- let result = condition;
159
- result = result.replace(/\bw\b/g, "width");
160
- result = result.replace(/\bh\b/g, "height");
161
- result = result.replace(/\bis\b/g, "inline-size");
162
- result = result.replace(/\bbs\b/g, "block-size");
163
- return result;
164
- }
165
- /**
166
- * Convert tasty units in a string (e.g., 40x -> calc(var(--gap) * 40))
167
- */
168
- function expandTastyUnits(value) {
169
- return value.replace(/(\d+(?:\.\d+)?)\s*x\b/g, (_, num) => {
170
- return `calc(var(--gap) * ${num})`;
171
- });
172
- }
173
- /**
174
- * Parse an advanced state key and return its type and components
175
- */
176
- function parseAdvancedState(stateKey, ctx) {
177
- const raw = stateKey;
178
- if (stateKey === "@starting") return {
179
- type: "starting",
180
- condition: "",
181
- raw
182
- };
183
- if (stateKey.startsWith("@media:")) {
184
- const mediaType = stateKey.slice(7);
185
- if (![
186
- "all",
187
- "screen",
188
- "print",
189
- "speech"
190
- ].includes(mediaType)) warnOnce(`unknown-media-type:${mediaType}`, `[Tasty] Unknown media type '${mediaType}'. Valid types: all, screen, print, speech.`);
191
- return {
192
- type: "media",
193
- condition: "",
194
- mediaType,
195
- raw
196
- };
197
- }
198
- if (stateKey.startsWith("@media(")) {
199
- const endParen = findMatchingParen(stateKey, 6);
200
- if (endParen === -1) {
201
- warnOnce(`unclosed-media:${stateKey}`, `[Tasty] Unclosed media query '${stateKey}'. Missing closing parenthesis.`);
202
- return {
203
- type: "modifier",
204
- condition: stateKey,
205
- raw
206
- };
207
- }
208
- let condition = stateKey.slice(7, endParen);
209
- if (!condition.trim()) {
210
- warnOnce(`empty-media:${stateKey}`, `[Tasty] Empty media query condition '${stateKey}'.`);
211
- return {
212
- type: "modifier",
213
- condition: stateKey,
214
- raw
215
- };
216
- }
217
- condition = expandDimensionShorthands(condition);
218
- condition = expandTastyUnits(condition);
219
- return {
220
- type: "media",
221
- condition,
222
- raw
223
- };
224
- }
225
- if (stateKey.startsWith("@root(")) {
226
- const endParen = findMatchingParen(stateKey, 5);
227
- if (endParen === -1) {
228
- warnOnce(`unclosed-root:${stateKey}`, `[Tasty] Unclosed root state '${stateKey}'. Missing closing parenthesis.`);
229
- return {
230
- type: "modifier",
231
- condition: stateKey,
232
- raw
233
- };
234
- }
235
- const condition = stateKey.slice(6, endParen);
236
- if (!condition.trim()) {
237
- warnOnce(`empty-root:${stateKey}`, `[Tasty] Empty root state condition '${stateKey}'.`);
238
- return {
239
- type: "modifier",
240
- condition: stateKey,
241
- raw
242
- };
243
- }
244
- return {
245
- type: "root",
246
- condition,
247
- raw
248
- };
249
- }
250
- if (stateKey.startsWith("@parent(")) {
251
- const endParen = findMatchingParen(stateKey, 7);
252
- if (endParen === -1) {
253
- warnOnce(`unclosed-parent:${stateKey}`, `[Tasty] Unclosed parent state '${stateKey}'. Missing closing parenthesis.`);
254
- return {
255
- type: "modifier",
256
- condition: stateKey,
257
- raw
258
- };
259
- }
260
- const condition = stateKey.slice(8, endParen);
261
- if (!condition.trim()) {
262
- warnOnce(`empty-parent:${stateKey}`, `[Tasty] Empty parent state condition '${stateKey}'.`);
263
- return {
264
- type: "modifier",
265
- condition: stateKey,
266
- raw
267
- };
268
- }
269
- return {
270
- type: "parent",
271
- condition,
272
- raw
273
- };
274
- }
275
- if (stateKey.startsWith("@own(")) {
276
- const endParen = findMatchingParen(stateKey, 4);
277
- if (endParen === -1) {
278
- warnOnce(`unclosed-own:${stateKey}`, `[Tasty] Unclosed own state '${stateKey}'. Missing closing parenthesis.`);
279
- return {
280
- type: "modifier",
281
- condition: stateKey,
282
- raw
283
- };
284
- }
285
- const condition = stateKey.slice(5, endParen);
286
- if (!condition.trim()) {
287
- warnOnce(`empty-own:${stateKey}`, `[Tasty] Empty own state condition '${stateKey}'.`);
288
- return {
289
- type: "modifier",
290
- condition: stateKey,
291
- raw
292
- };
293
- }
294
- if (!ctx.isSubElement) {
295
- warnOnce(`own-outside-subelement:${stateKey}`, `[Tasty] @own(${condition}) used outside sub-element context.\n@own() is equivalent to '${condition}' at the root level. Did you mean to use it inside a sub-element?`);
296
- return {
297
- type: "modifier",
298
- condition,
299
- raw
300
- };
301
- }
302
- return {
303
- type: "own",
304
- condition,
305
- raw
306
- };
307
- }
308
- if (stateKey.startsWith("@(")) {
309
- const endParen = findMatchingParen(stateKey, 1);
310
- if (endParen === -1) {
311
- warnOnce(`unclosed-container:${stateKey}`, `[Tasty] Unclosed container query '${stateKey}'. Missing closing parenthesis.`);
312
- return {
313
- type: "modifier",
314
- condition: stateKey,
315
- raw
316
- };
317
- }
318
- const content = stateKey.slice(2, endParen);
319
- if (!content.trim()) {
320
- warnOnce(`empty-container:${stateKey}`, `[Tasty] Empty container query '${stateKey}'.`);
321
- return {
322
- type: "modifier",
323
- condition: stateKey,
324
- raw
325
- };
326
- }
327
- const commaIndex = findTopLevelComma(content);
328
- let containerName;
329
- let condition;
330
- if (commaIndex !== -1) {
331
- containerName = content.slice(0, commaIndex).trim();
332
- condition = content.slice(commaIndex + 1).trim();
333
- } else condition = content.trim();
334
- if (condition.startsWith("$")) {
335
- const styleCondition = parseStyleQuery(condition);
336
- if (!styleCondition) {
337
- warnOnce(`invalid-style-query:${stateKey}`, `[Tasty] Invalid style query '${condition}' in container query.`);
338
- return {
339
- type: "modifier",
340
- condition: stateKey,
341
- raw
342
- };
343
- }
344
- condition = styleCondition;
345
- } else if (/^[a-zA-Z][\w-]*\s*\(/.test(condition)) {} else {
346
- condition = expandDimensionShorthands(condition);
347
- condition = expandTastyUnits(condition);
348
- }
349
- return {
350
- type: "container",
351
- condition,
352
- containerName,
353
- raw
354
- };
355
- }
356
- if (isPredefinedStateRef(stateKey)) {
357
- const resolved = resolvePredefinedState(stateKey, ctx);
358
- if (resolved) return {
359
- ...parseAdvancedState(resolved, ctx),
360
- raw
361
- };
362
- return {
363
- type: "modifier",
364
- condition: stateKey,
365
- raw
366
- };
367
- }
368
- return {
369
- type: "modifier",
370
- condition: stateKey,
371
- raw
372
- };
373
- }
374
- /**
375
- * Parse a style query condition (e.g., $compact, $variant=compact, $variant="very compact")
376
- */
377
- function parseStyleQuery(condition) {
378
- const query = condition.slice(1);
379
- if (/[<>]/.test(query)) {
380
- warnOnce(`style-query-comparison:${condition}`, `[Tasty] Style queries only support equality. '${condition}' is invalid. Use '${condition.split(/[<>]/)[0]}=...' instead.`);
381
- return null;
382
- }
383
- const eqIndex = query.indexOf("=");
384
- if (eqIndex === -1) return `style(--${query})`;
385
- const propName = query.slice(0, eqIndex).trim();
386
- let value = query.slice(eqIndex + 1).trim();
387
- if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) {} else value = `"${value}"`;
388
- value = expandTastyUnits(value);
389
- return `style(--${propName}: ${value})`;
390
- }
391
- /**
392
- * Find the index of the first comma at parentheses depth 0.
393
- * Returns -1 if no top-level comma is found.
394
- * This prevents splitting on commas inside function calls like scroll-state(a, b).
395
- */
396
- function findTopLevelComma(s) {
397
- let depth = 0;
398
- for (let i = 0; i < s.length; i++) if (s[i] === "(") depth++;
399
- else if (s[i] === ")") depth--;
400
- else if (s[i] === "," && depth === 0) return i;
401
- return -1;
402
- }
403
- function findMatchingParen(str, startIndex) {
404
- let depth = 1;
405
- let i = startIndex + 1;
406
- while (i < str.length && depth > 0) {
407
- if (str[i] === "(") depth++;
408
- else if (str[i] === ")") depth--;
409
- i++;
410
- }
411
- return depth === 0 ? i - 1 : -1;
412
- }
413
-
414
- //#endregion
415
- export { createStateParserContext, expandDimensionShorthands, expandTastyUnits, extractLocalPredefinedStates, extractPredefinedStateRefs, findTopLevelComma, getGlobalPredefinedStates, parseAdvancedState, resolvePredefinedState, setGlobalPredefinedStates };
416
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/states/index.ts"],"sourcesContent":["/**\n * Advanced State Mapping - Predefined States Management\n *\n * This module handles global and local predefined states for the Tasty styling system.\n * See ADVANCED_STATE_MAPPING.md for full specification.\n */\n\nimport { hasStylesGenerated } from '../config';\nimport type { Styles } from '../styles/types';\nimport { isDevEnv } from '../utils/is-dev-env';\n\n/**\n * Parsed advanced state information\n */\nexport interface ParsedAdvancedState {\n type:\n | 'media'\n | 'container'\n | 'root'\n | 'parent'\n | 'own'\n | 'starting'\n | 'predefined'\n | 'modifier';\n condition: string; // e.g., 'width <= 920px' or 'hovered'\n containerName?: string; // for container queries\n raw: string; // original state key\n mediaType?: string; // for @media:screen, @media:print, etc.\n}\n\n/**\n * Context for state parsing operations\n */\nexport interface StateParserContext {\n localPredefinedStates: Record<string, string>;\n globalPredefinedStates: Record<string, string>;\n isSubElement?: boolean; // true when processing sub-element styles (for @own() validation)\n}\n\n/**\n * At-rule context for CSS generation\n */\nexport interface AtRuleContext {\n media?: string[]; // @media conditions to wrap rule in (merged with 'and')\n container?: { name?: string; condition: string }[]; // @container conditions (nested)\n startingStyle?: boolean;\n rootStates?: string[]; // :root state selectors (e.g., '[data-theme=\"dark\"]')\n negatedRootStates?: string[]; // Negated :root state selectors for non-overlapping rules (e.g., ':not([data-theme=\"dark\"])')\n}\n\n// Built-in state names that cannot be overridden\nconst BUILTIN_STATES = new Set([\n '@starting',\n '@keyframes',\n '@properties',\n '@supports',\n // @inherit is a value (not a key), but reserved here to prevent\n // users from accidentally defining a state named '@inherit'.\n '@inherit',\n]);\n\n// Reserved prefixes that are built-in\nconst RESERVED_PREFIXES = [\n '@media',\n '@root',\n '@parent',\n '@own',\n '@(',\n '@starting',\n '@keyframes',\n '@properties',\n '@supports',\n '@inherit',\n];\n\n// Global predefined states storage\nlet globalPredefinedStates: Record<string, string> = {};\n\n// Warnings tracking to avoid duplicates\nconst emittedWarnings = new Set<string>();\n\nconst devMode = isDevEnv();\n\n/**\n * Emit a warning only once\n */\nfunction warnOnce(key: string, message: string): void {\n if (devMode && !emittedWarnings.has(key)) {\n emittedWarnings.add(key);\n console.warn(message);\n }\n}\n\n/**\n * Configure global predefined states\n */\nexport function setGlobalPredefinedStates(\n states: Record<string, string>,\n): void {\n if (hasStylesGenerated()) {\n const newStateNames = Object.keys(states).join(', ');\n warnOnce(\n `dynamic-states:${newStateNames}`,\n `[Tasty] Cannot update predefined states after styles have been generated.\\n` +\n `The new definition(s) for ${newStateNames} will be ignored.`,\n );\n return;\n }\n\n // Validate state names\n for (const [name, value] of Object.entries(states)) {\n // Check for valid name format\n if (!/^@[A-Za-z][A-Za-z0-9-]*$/.test(name)) {\n warnOnce(\n `invalid-state-name:${name}`,\n `[Tasty] Invalid predefined state name '${name}'. Must start with '@' followed by a letter.`,\n );\n continue;\n }\n\n // Check for reserved names\n if (BUILTIN_STATES.has(name)) {\n warnOnce(\n `reserved-state:${name}`,\n `[Tasty] Cannot define predefined state '${name}'. This name is reserved for built-in functionality.`,\n );\n continue;\n }\n\n // Check for reserved prefixes (but only exact matches, not user-defined states like @mobile)\n // Reserved prefixes are: @media, @root, @parent, @own, @(\n // A user state like @mobile should NOT be blocked\n const isReservedPrefix =\n name === '@media' ||\n name === '@root' ||\n name === '@parent' ||\n name === '@own' ||\n name.startsWith('@(');\n\n if (isReservedPrefix) {\n warnOnce(\n `reserved-prefix:${name}`,\n `[Tasty] Cannot define predefined state '${name}'. This prefix is reserved for built-in functionality.`,\n );\n continue;\n }\n\n // Check for cross-references\n const crossRefs = extractPredefinedStateRefs(value);\n if (crossRefs.length > 0) {\n warnOnce(\n `cross-ref:${name}`,\n `[Tasty] Predefined state '${name}' references another predefined state '${crossRefs[0]}'.\\n` +\n `Predefined states cannot reference each other. Use the full definition instead.`,\n );\n continue;\n }\n\n // Check for duplicates\n if (\n globalPredefinedStates[name] &&\n globalPredefinedStates[name] !== value\n ) {\n warnOnce(\n `duplicate-state:${name}`,\n `[Tasty] Duplicate predefined state '${name}' in configure(). The last definition will be used.`,\n );\n }\n\n globalPredefinedStates[name] = value;\n }\n}\n\n/**\n * Get global predefined states\n */\nexport function getGlobalPredefinedStates(): Record<string, string> {\n return globalPredefinedStates;\n}\n\n/**\n * Clear global predefined states (for testing only)\n */\nexport function clearGlobalPredefinedStates(): void {\n globalPredefinedStates = {};\n emittedWarnings.clear();\n}\n\n/**\n * Regex to match predefined state references in a string\n * Matches @name that is NOT followed by ( or : and is a complete word\n * Uses word boundary and negative lookahead\n */\nconst PREDEFINED_STATE_PATTERN = /@([A-Za-z][A-Za-z0-9-]*)(?![A-Za-z0-9-:(])/g;\n\n/**\n * Extract predefined state references from a string\n */\nexport function extractPredefinedStateRefs(value: string): string[] {\n const matches = value.matchAll(PREDEFINED_STATE_PATTERN);\n const refs: string[] = [];\n\n for (const match of matches) {\n const stateName = '@' + match[1];\n // Skip built-in states (@starting) and duplicates\n // Note: @media, @root, @own are always followed by '(' so the regex\n // negative lookahead (?![A-Za-z0-9-:(]) already excludes them\n if (!BUILTIN_STATES.has(stateName) && !refs.includes(stateName)) {\n refs.push(stateName);\n }\n }\n\n return refs;\n}\n\n/**\n * Check if a state key is a predefined state reference\n */\nexport function isPredefinedStateRef(stateKey: string): boolean {\n if (!stateKey.startsWith('@')) return false;\n if (BUILTIN_STATES.has(stateKey)) return false;\n\n // Check if it's NOT a built-in prefix\n for (const prefix of RESERVED_PREFIXES) {\n if (stateKey === prefix || stateKey.startsWith(prefix)) {\n // Check if it's exactly @media, @root, @parent, @own, or starts with @( or @media(\n if (\n stateKey === '@media' ||\n stateKey.startsWith('@media(') ||\n stateKey.startsWith('@media:')\n ) {\n return false;\n }\n if (stateKey === '@root' || stateKey.startsWith('@root(')) return false;\n if (stateKey === '@parent' || stateKey.startsWith('@parent('))\n return false;\n if (stateKey === '@own' || stateKey.startsWith('@own(')) return false;\n if (stateKey.startsWith('@(')) return false;\n }\n }\n\n // Must match the predefined state pattern\n return /^@[A-Za-z][A-Za-z0-9-]*$/.test(stateKey);\n}\n\n/**\n * Extract local predefined states from a styles object\n * Local predefined states are top-level keys starting with @ that have string values\n * and are valid predefined state names (not built-in like @media, @root, etc.)\n */\nexport function extractLocalPredefinedStates(\n styles: Styles,\n): Record<string, string> {\n const localStates: Record<string, string> = {};\n\n if (!styles || typeof styles !== 'object') {\n return localStates;\n }\n\n for (const [key, value] of Object.entries(styles)) {\n // Check if it's a predefined state definition (starts with @, has string value)\n if (key.startsWith('@') && typeof value === 'string') {\n // Validate name format - must be @[letter][letters/numbers/dashes]*\n if (!/^@[A-Za-z][A-Za-z0-9-]*$/.test(key)) {\n continue; // Skip invalid names silently (might be something else)\n }\n\n // Skip built-in states\n if (BUILTIN_STATES.has(key)) {\n continue;\n }\n\n // Skip reserved prefixes\n if (\n key === '@media' ||\n key === '@root' ||\n key === '@parent' ||\n key === '@own' ||\n key.startsWith('@(')\n ) {\n continue;\n }\n\n // Check for cross-references (predefined states cannot reference each other)\n const crossRefs = extractPredefinedStateRefs(value);\n if (crossRefs.length > 0) {\n warnOnce(\n `local-cross-ref:${key}`,\n `[Tasty] Predefined state '${key}' references another predefined state '${crossRefs[0]}'.\\n` +\n `Predefined states cannot reference each other. Use the full definition instead.`,\n );\n continue;\n }\n\n localStates[key] = value;\n }\n }\n\n return localStates;\n}\n\n/**\n * Create a state parser context from styles\n */\nexport function createStateParserContext(\n styles?: Styles,\n isSubElement?: boolean,\n): StateParserContext {\n const localStates = styles ? extractLocalPredefinedStates(styles) : {};\n\n return {\n localPredefinedStates: localStates,\n globalPredefinedStates: getGlobalPredefinedStates(),\n isSubElement,\n };\n}\n\n/**\n * Resolve a predefined state reference to its value\n * Returns the resolved value or null if not found\n */\nexport function resolvePredefinedState(\n stateKey: string,\n ctx: StateParserContext,\n): string | null {\n // Check local first (higher priority)\n if (ctx.localPredefinedStates[stateKey]) {\n return ctx.localPredefinedStates[stateKey];\n }\n\n // Then check global\n if (ctx.globalPredefinedStates[stateKey]) {\n return ctx.globalPredefinedStates[stateKey];\n }\n\n // Not found - emit warning\n warnOnce(\n `undefined-state:${stateKey}`,\n `[Tasty] Undefined predefined state '${stateKey}'.\\n` +\n `Define it in configure({ states: { '${stateKey}': '...' } }) or in the component's styles.`,\n );\n\n return null;\n}\n\n/**\n * Normalize state key by trimming whitespace and removing trailing/leading operators\n */\nexport function normalizeStateKey(stateKey: string): {\n key: string;\n warnings: string[];\n} {\n const warnings: string[] = [];\n let key = stateKey;\n\n // Check for whitespace-only\n if (key.trim() === '') {\n if (key !== '') {\n warnings.push(\n `[Tasty] Whitespace-only state key normalized to default state ''.`,\n );\n }\n return { key: '', warnings };\n }\n\n // Trim whitespace\n key = key.trim();\n\n // Remove trailing operators\n const trailingOpMatch = key.match(/\\s*[&|^]\\s*$/);\n if (trailingOpMatch) {\n const originalKey = key;\n key = key.slice(0, -trailingOpMatch[0].length).trim();\n warnings.push(\n `[Tasty] State key '${originalKey}' has trailing operator. Normalized to '${key}'.`,\n );\n }\n\n // Remove leading operators (except !)\n const leadingOpMatch = key.match(/^\\s*[&|^]\\s*/);\n if (leadingOpMatch) {\n const originalKey = key;\n key = key.slice(leadingOpMatch[0].length).trim();\n warnings.push(\n `[Tasty] State key '${originalKey}' has leading operator. Normalized to '${key}'.`,\n );\n }\n\n return { key, warnings };\n}\n\n/**\n * Expand dimension shorthands in a condition string\n * w -> width, h -> height, is -> inline-size, bs -> block-size\n */\nexport function expandDimensionShorthands(condition: string): string {\n // Replace dimension shorthands (only when they appear as standalone words)\n let result = condition;\n\n // w -> width (but not part of other words)\n result = result.replace(/\\bw\\b/g, 'width');\n\n // h -> height\n result = result.replace(/\\bh\\b/g, 'height');\n\n // is -> inline-size\n result = result.replace(/\\bis\\b/g, 'inline-size');\n\n // bs -> block-size\n result = result.replace(/\\bbs\\b/g, 'block-size');\n\n return result;\n}\n\n/**\n * Convert tasty units in a string (e.g., 40x -> calc(var(--gap) * 40))\n */\nexport function expandTastyUnits(value: string): string {\n // Match number followed by 'x' unit (tasty gap unit)\n return value.replace(/(\\d+(?:\\.\\d+)?)\\s*x\\b/g, (_, num) => {\n return `calc(var(--gap) * ${num})`;\n });\n}\n\n/**\n * Parse an advanced state key and return its type and components\n */\nexport function parseAdvancedState(\n stateKey: string,\n ctx: StateParserContext,\n): ParsedAdvancedState {\n const raw = stateKey;\n\n // Check for @starting (exact match)\n if (stateKey === '@starting') {\n return {\n type: 'starting',\n condition: '',\n raw,\n };\n }\n\n // Check for @media:type (e.g., @media:print)\n if (stateKey.startsWith('@media:')) {\n const mediaType = stateKey.slice(7); // Remove '@media:'\n if (!['all', 'screen', 'print', 'speech'].includes(mediaType)) {\n warnOnce(\n `unknown-media-type:${mediaType}`,\n `[Tasty] Unknown media type '${mediaType}'. Valid types: all, screen, print, speech.`,\n );\n }\n return {\n type: 'media',\n condition: '',\n mediaType,\n raw,\n };\n }\n\n // Check for @media(...) - media query with condition\n if (stateKey.startsWith('@media(')) {\n const endParen = findMatchingParen(stateKey, 6);\n if (endParen === -1) {\n warnOnce(\n `unclosed-media:${stateKey}`,\n `[Tasty] Unclosed media query '${stateKey}'. Missing closing parenthesis.`,\n );\n return { type: 'modifier', condition: stateKey, raw };\n }\n\n let condition = stateKey.slice(7, endParen);\n\n // Check for empty condition\n if (!condition.trim()) {\n warnOnce(\n `empty-media:${stateKey}`,\n `[Tasty] Empty media query condition '${stateKey}'.`,\n );\n return { type: 'modifier', condition: stateKey, raw };\n }\n\n // Expand shorthands and units\n condition = expandDimensionShorthands(condition);\n condition = expandTastyUnits(condition);\n\n return {\n type: 'media',\n condition,\n raw,\n };\n }\n\n // Check for @root(...) - root state\n if (stateKey.startsWith('@root(')) {\n const endParen = findMatchingParen(stateKey, 5);\n if (endParen === -1) {\n warnOnce(\n `unclosed-root:${stateKey}`,\n `[Tasty] Unclosed root state '${stateKey}'. Missing closing parenthesis.`,\n );\n return { type: 'modifier', condition: stateKey, raw };\n }\n\n const condition = stateKey.slice(6, endParen);\n\n if (!condition.trim()) {\n warnOnce(\n `empty-root:${stateKey}`,\n `[Tasty] Empty root state condition '${stateKey}'.`,\n );\n return { type: 'modifier', condition: stateKey, raw };\n }\n\n return {\n type: 'root',\n condition,\n raw,\n };\n }\n\n // Check for @parent(...) - parent element state\n if (stateKey.startsWith('@parent(')) {\n const endParen = findMatchingParen(stateKey, 7);\n if (endParen === -1) {\n warnOnce(\n `unclosed-parent:${stateKey}`,\n `[Tasty] Unclosed parent state '${stateKey}'. Missing closing parenthesis.`,\n );\n return { type: 'modifier', condition: stateKey, raw };\n }\n\n const condition = stateKey.slice(8, endParen);\n\n if (!condition.trim()) {\n warnOnce(\n `empty-parent:${stateKey}`,\n `[Tasty] Empty parent state condition '${stateKey}'.`,\n );\n return { type: 'modifier', condition: stateKey, raw };\n }\n\n return {\n type: 'parent',\n condition,\n raw,\n };\n }\n\n // Check for @own(...) - sub-element own state\n if (stateKey.startsWith('@own(')) {\n const endParen = findMatchingParen(stateKey, 4);\n if (endParen === -1) {\n warnOnce(\n `unclosed-own:${stateKey}`,\n `[Tasty] Unclosed own state '${stateKey}'. Missing closing parenthesis.`,\n );\n return { type: 'modifier', condition: stateKey, raw };\n }\n\n const condition = stateKey.slice(5, endParen);\n\n if (!condition.trim()) {\n warnOnce(\n `empty-own:${stateKey}`,\n `[Tasty] Empty own state condition '${stateKey}'.`,\n );\n return { type: 'modifier', condition: stateKey, raw };\n }\n\n // Check if used outside sub-element context\n if (!ctx.isSubElement) {\n warnOnce(\n `own-outside-subelement:${stateKey}`,\n `[Tasty] @own(${condition}) used outside sub-element context.\\n` +\n `@own() is equivalent to '${condition}' at the root level. ` +\n `Did you mean to use it inside a sub-element?`,\n );\n // Treat as regular modifier\n return {\n type: 'modifier',\n condition,\n raw,\n };\n }\n\n return {\n type: 'own',\n condition,\n raw,\n };\n }\n\n // Check for @(...) - container query (unnamed or named)\n if (stateKey.startsWith('@(')) {\n const endParen = findMatchingParen(stateKey, 1);\n if (endParen === -1) {\n warnOnce(\n `unclosed-container:${stateKey}`,\n `[Tasty] Unclosed container query '${stateKey}'. Missing closing parenthesis.`,\n );\n return { type: 'modifier', condition: stateKey, raw };\n }\n\n const content = stateKey.slice(2, endParen);\n\n if (!content.trim()) {\n warnOnce(\n `empty-container:${stateKey}`,\n `[Tasty] Empty container query '${stateKey}'.`,\n );\n return { type: 'modifier', condition: stateKey, raw };\n }\n\n // Check if named container (first token is name, followed by comma)\n // Use parentheses-aware comma search so inner commas (e.g., scroll-state(a, b)) are skipped\n const commaIndex = findTopLevelComma(content);\n let containerName: string | undefined;\n let condition: string;\n\n if (commaIndex !== -1) {\n // Named container: @(layout, w < 600px)\n containerName = content.slice(0, commaIndex).trim();\n condition = content.slice(commaIndex + 1).trim();\n } else {\n // Unnamed container: @(w < 600px)\n condition = content.trim();\n }\n\n // Check for style query shorthand (starts with $)\n if (condition.startsWith('$')) {\n // Style query: @(layout, $compact) or @(layout, $variant=compact)\n const styleCondition = parseStyleQuery(condition);\n if (!styleCondition) {\n warnOnce(\n `invalid-style-query:${stateKey}`,\n `[Tasty] Invalid style query '${condition}' in container query.`,\n );\n return { type: 'modifier', condition: stateKey, raw };\n }\n condition = styleCondition;\n } else if (/^[a-zA-Z][\\w-]*\\s*\\(/.test(condition)) {\n // Function-like syntax: scroll-state(...), style(...), etc.\n // Pass through verbatim — no dimension expansion needed\n } else {\n // Dimension query - expand shorthands and units\n condition = expandDimensionShorthands(condition);\n condition = expandTastyUnits(condition);\n }\n\n return {\n type: 'container',\n condition,\n containerName,\n raw,\n };\n }\n\n // Check for predefined state reference\n if (isPredefinedStateRef(stateKey)) {\n const resolved = resolvePredefinedState(stateKey, ctx);\n if (resolved) {\n // Recursively parse the resolved value to extract the actual state type\n // (e.g., @mobile -> @media(w < 768px) should become a media state)\n const parsedResolved = parseAdvancedState(resolved, ctx);\n return {\n ...parsedResolved,\n raw, // Keep original raw for traceability\n };\n }\n // If not resolved, treat as modifier (will likely produce invalid CSS)\n return {\n type: 'modifier',\n condition: stateKey,\n raw,\n };\n }\n\n // Regular modifier (boolean mod, pseudo-class, class, attribute)\n return {\n type: 'modifier',\n condition: stateKey,\n raw,\n };\n}\n\n/**\n * Parse a style query condition (e.g., $compact, $variant=compact, $variant=\"very compact\")\n */\nfunction parseStyleQuery(condition: string): string | null {\n // Remove $ prefix\n const query = condition.slice(1);\n\n // Check for comparison operators (not supported)\n if (/[<>]/.test(query)) {\n warnOnce(\n `style-query-comparison:${condition}`,\n `[Tasty] Style queries only support equality. '${condition}' is invalid. Use '${condition.split(/[<>]/)[0]}=...' instead.`,\n );\n return null;\n }\n\n // Check for equality\n const eqIndex = query.indexOf('=');\n if (eqIndex === -1) {\n // Just existence check: style(--compact)\n return `style(--${query})`;\n }\n\n const propName = query.slice(0, eqIndex).trim();\n let value = query.slice(eqIndex + 1).trim();\n\n // Handle quoted values\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n // Keep quotes for CSS\n } else {\n // Add quotes if needed\n value = `\"${value}\"`;\n }\n\n // Expand tasty units in value\n value = expandTastyUnits(value);\n\n return `style(--${propName}: ${value})`;\n}\n\n/**\n * Find the index of the first comma at parentheses depth 0.\n * Returns -1 if no top-level comma is found.\n * This prevents splitting on commas inside function calls like scroll-state(a, b).\n */\nexport function findTopLevelComma(s: string): number {\n let depth = 0;\n\n for (let i = 0; i < s.length; i++) {\n if (s[i] === '(') depth++;\n else if (s[i] === ')') depth--;\n else if (s[i] === ',' && depth === 0) return i;\n }\n\n return -1;\n}\n\nfunction findMatchingParen(str: string, startIndex: number): number {\n let depth = 1;\n let i = startIndex + 1;\n\n while (i < str.length && depth > 0) {\n if (str[i] === '(') depth++;\n else if (str[i] === ')') depth--;\n i++;\n }\n\n return depth === 0 ? i - 1 : -1;\n}\n\n/**\n * Check if a state key is an advanced state (starts with @)\n */\nexport function isAdvancedState(stateKey: string): boolean {\n return stateKey.startsWith('@') || stateKey.startsWith('!@');\n}\n\n/**\n * Detect the type of advanced state from a raw state key\n */\nexport function detectAdvancedStateType(\n stateKey: string,\n): ParsedAdvancedState['type'] {\n // Handle negation prefix\n const key = stateKey.startsWith('!') ? stateKey.slice(1) : stateKey;\n\n if (key === '@starting') return 'starting';\n if (key.startsWith('@media')) return 'media';\n if (key.startsWith('@root(')) return 'root';\n if (key.startsWith('@parent(')) return 'parent';\n if (key.startsWith('@own(')) return 'own';\n if (key.startsWith('@(')) return 'container';\n if (isPredefinedStateRef(key)) return 'predefined';\n return 'modifier';\n}\n"],"mappings":"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"}
@@ -1,46 +0,0 @@
1
- import { Styles } from "../styles/types.js";
2
- import { StaticStyle } from "./types.js";
3
-
4
- //#region src/static/tastyStatic.d.ts
5
- /**
6
- * Generate styles and return a StaticStyle object.
7
- * The object has `className`, `styles`, and `toString()`.
8
- *
9
- * @example
10
- * ```typescript
11
- * const button = tastyStatic({
12
- * fill: '#blue',
13
- * padding: '2x',
14
- * });
15
- * // After build: { className: 'ts3f2a1b', styles: {...}, toString() }
16
- *
17
- * <div className={button} /> // Works via toString()
18
- * ```
19
- */
20
- declare function tastyStatic(styles: Styles): StaticStyle;
21
- /**
22
- * Extend an existing StaticStyle with additional styles.
23
- * Uses mergeStyles() internally for proper nested selector handling.
24
- *
25
- * @example
26
- * ```typescript
27
- * const button = tastyStatic({ fill: '#blue' });
28
- * const primary = tastyStatic(button, { fill: '#purple' });
29
- * // After build: { className: 'ts8c4d2e', styles: {...merged...}, toString() }
30
- * ```
31
- */
32
- declare function tastyStatic(base: StaticStyle, styles: Styles): StaticStyle;
33
- /**
34
- * Generate styles for a specific CSS selector.
35
- * The call is completely removed after build transformation.
36
- *
37
- * @example
38
- * ```typescript
39
- * tastyStatic('.heading', { preset: 'h1', color: '#primary' });
40
- * // After build: (removed)
41
- * ```
42
- */
43
- declare function tastyStatic(selector: string, styles: Styles): void;
44
- //#endregion
45
- export { tastyStatic };
46
- //# sourceMappingURL=tastyStatic.d.ts.map
@@ -1,31 +0,0 @@
1
- import { mergeStyles } from "../utils/merge-styles.js";
2
- import { createStaticStyle, isStaticStyle } from "./types.js";
3
-
4
- //#region src/static/tastyStatic.ts
5
- /**
6
- * Build-time only function for zero-runtime static site generation.
7
- *
8
- * This function is transformed by the Babel plugin:
9
- * - `tastyStatic(styles)` → StaticStyle object with className
10
- * - `tastyStatic(base, styles)` → StaticStyle object with merged styles
11
- * - `tastyStatic(selector, styles)` → removed entirely
12
- *
13
- * At runtime (during development/build), this function returns a placeholder.
14
- * In production, all calls are replaced/removed by the build plugin.
15
- */
16
- function tastyStatic(stylesOrBaseOrSelector, styles) {
17
- if (typeof stylesOrBaseOrSelector === "string") {
18
- console.warn(`[tasty] tastyStatic('${stylesOrBaseOrSelector}', styles) was called at runtime. This indicates the Babel plugin is not configured. Add @tenphi/tasty/babel-plugin to your Babel config.`);
19
- return;
20
- }
21
- if (isStaticStyle(stylesOrBaseOrSelector)) {
22
- console.warn("[tasty] tastyStatic(base, styles) was called at runtime. This indicates the Babel plugin is not configured. Add @tenphi/tasty/babel-plugin to your Babel config.");
23
- return createStaticStyle("__TASTY_STATIC_NOT_TRANSFORMED__", mergeStyles(stylesOrBaseOrSelector.styles, styles || {}));
24
- }
25
- console.warn("[tasty] tastyStatic(styles) was called at runtime. This indicates the Babel plugin is not configured. Add @tenphi/tasty/babel-plugin to your Babel config.");
26
- return createStaticStyle("__TASTY_STATIC_NOT_TRANSFORMED__", stylesOrBaseOrSelector);
27
- }
28
-
29
- //#endregion
30
- export { tastyStatic };
31
- //# sourceMappingURL=tastyStatic.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tastyStatic.js","names":[],"sources":["../../src/static/tastyStatic.ts"],"sourcesContent":["import type { Styles } from '../styles/types';\nimport { mergeStyles } from '../utils/merge-styles';\n\nimport type { StaticStyle } from './types';\nimport { createStaticStyle, isStaticStyle } from './types';\n\n/**\n * Generate styles and return a StaticStyle object.\n * The object has `className`, `styles`, and `toString()`.\n *\n * @example\n * ```typescript\n * const button = tastyStatic({\n * fill: '#blue',\n * padding: '2x',\n * });\n * // After build: { className: 'ts3f2a1b', styles: {...}, toString() }\n *\n * <div className={button} /> // Works via toString()\n * ```\n */\nexport function tastyStatic(styles: Styles): StaticStyle;\n\n/**\n * Extend an existing StaticStyle with additional styles.\n * Uses mergeStyles() internally for proper nested selector handling.\n *\n * @example\n * ```typescript\n * const button = tastyStatic({ fill: '#blue' });\n * const primary = tastyStatic(button, { fill: '#purple' });\n * // After build: { className: 'ts8c4d2e', styles: {...merged...}, toString() }\n * ```\n */\nexport function tastyStatic(base: StaticStyle, styles: Styles): StaticStyle;\n\n/**\n * Generate styles for a specific CSS selector.\n * The call is completely removed after build transformation.\n *\n * @example\n * ```typescript\n * tastyStatic('.heading', { preset: 'h1', color: '#primary' });\n * // After build: (removed)\n * ```\n */\nexport function tastyStatic(selector: string, styles: Styles): void;\n\n/**\n * Build-time only function for zero-runtime static site generation.\n *\n * This function is transformed by the Babel plugin:\n * - `tastyStatic(styles)` → StaticStyle object with className\n * - `tastyStatic(base, styles)` → StaticStyle object with merged styles\n * - `tastyStatic(selector, styles)` → removed entirely\n *\n * At runtime (during development/build), this function returns a placeholder.\n * In production, all calls are replaced/removed by the build plugin.\n */\nexport function tastyStatic(\n stylesOrBaseOrSelector: Styles | StaticStyle | string,\n styles?: Styles,\n): StaticStyle | void {\n // This code only executes if the Babel plugin hasn't processed the file yet.\n // In a properly configured build, this function is never called at runtime.\n\n if (typeof stylesOrBaseOrSelector === 'string') {\n // Selector mode: tastyStatic(selector, styles)\n // The plugin will remove this call entirely\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n `[tasty] tastyStatic('${stylesOrBaseOrSelector}', styles) was called at runtime. ` +\n 'This indicates the Babel plugin is not configured. ' +\n 'Add @tenphi/tasty/babel-plugin to your Babel config.',\n );\n }\n return; // void\n }\n\n if (isStaticStyle(stylesOrBaseOrSelector)) {\n // Extension mode: tastyStatic(base, styles)\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n '[tasty] tastyStatic(base, styles) was called at runtime. ' +\n 'This indicates the Babel plugin is not configured. ' +\n 'Add @tenphi/tasty/babel-plugin to your Babel config.',\n );\n }\n // Merge styles for dev mode preview (won't have real classNames)\n const mergedStyles = mergeStyles(\n stylesOrBaseOrSelector.styles,\n styles || {},\n );\n return createStaticStyle('__TASTY_STATIC_NOT_TRANSFORMED__', mergedStyles);\n }\n\n // Styles mode: tastyStatic(styles)\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n '[tasty] tastyStatic(styles) was called at runtime. ' +\n 'This indicates the Babel plugin is not configured. ' +\n 'Add @tenphi/tasty/babel-plugin to your Babel config.',\n );\n }\n\n // Return placeholder - styles won't be applied without the plugin\n return createStaticStyle(\n '__TASTY_STATIC_NOT_TRANSFORMED__',\n stylesOrBaseOrSelector,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AA2DA,SAAgB,YACd,wBACA,QACoB;AAIpB,KAAI,OAAO,2BAA2B,UAAU;AAI5C,UAAQ,KACN,wBAAwB,uBAAuB,2IAGhD;AAEH;;AAGF,KAAI,cAAc,uBAAuB,EAAE;AAGvC,UAAQ,KACN,mKAGD;AAOH,SAAO,kBAAkB,oCAJJ,YACnB,uBAAuB,QACvB,UAAU,EAAE,CACb,CACyE;;AAK1E,SAAQ,KACN,6JAGD;AAIH,QAAO,kBACL,oCACA,uBACD"}
@@ -1,49 +0,0 @@
1
- import { Styles } from "../styles/types.js";
2
-
3
- //#region src/static/types.d.ts
4
- /**
5
- * Static style definition returned by tastyStatic().
6
- *
7
- * Supports both explicit className access and implicit string coercion via toString().
8
- *
9
- * @example
10
- * ```typescript
11
- * const button = tastyStatic({ fill: '#blue' });
12
- *
13
- * // Both work in JSX:
14
- * <div className={button} /> // Uses toString()
15
- * <div className={button.className} /> // Explicit
16
- *
17
- * // Extension:
18
- * const primary = tastyStatic(button, { fill: '#purple' });
19
- * ```
20
- */
21
- interface StaticStyle {
22
- /**
23
- * Generated className(s) for use in JSX.
24
- * May contain multiple space-separated class names due to chunking.
25
- */
26
- className: string;
27
- /**
28
- * The original (or merged) styles object.
29
- * Available for extension via tastyStatic(base, overrides).
30
- */
31
- styles: Styles;
32
- /**
33
- * Returns className for implicit string coercion.
34
- * Enables `<div className={button} />` syntax.
35
- */
36
- toString(): string;
37
- }
38
- /**
39
- * Create a StaticStyle object.
40
- * Used internally by the Babel plugin to generate output.
41
- */
42
- declare function createStaticStyle(className: string, styles: Styles): StaticStyle;
43
- /**
44
- * Type guard to check if a value is a StaticStyle object.
45
- */
46
- declare function isStaticStyle(value: unknown): value is StaticStyle;
47
- //#endregion
48
- export { StaticStyle, createStaticStyle, isStaticStyle };
49
- //# sourceMappingURL=types.d.ts.map
@@ -1,24 +0,0 @@
1
- //#region src/static/types.ts
2
- /**
3
- * Create a StaticStyle object.
4
- * Used internally by the Babel plugin to generate output.
5
- */
6
- function createStaticStyle(className, styles) {
7
- return {
8
- className,
9
- styles,
10
- toString() {
11
- return this.className;
12
- }
13
- };
14
- }
15
- /**
16
- * Type guard to check if a value is a StaticStyle object.
17
- */
18
- function isStaticStyle(value) {
19
- return typeof value === "object" && value !== null && "className" in value && "styles" in value && "toString" in value && typeof value.className === "string" && typeof value.styles === "object";
20
- }
21
-
22
- //#endregion
23
- export { createStaticStyle, isStaticStyle };
24
- //# sourceMappingURL=types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../src/static/types.ts"],"sourcesContent":["import type { Styles } from '../styles/types';\n\n/**\n * Static style definition returned by tastyStatic().\n *\n * Supports both explicit className access and implicit string coercion via toString().\n *\n * @example\n * ```typescript\n * const button = tastyStatic({ fill: '#blue' });\n *\n * // Both work in JSX:\n * <div className={button} /> // Uses toString()\n * <div className={button.className} /> // Explicit\n *\n * // Extension:\n * const primary = tastyStatic(button, { fill: '#purple' });\n * ```\n */\nexport interface StaticStyle {\n /**\n * Generated className(s) for use in JSX.\n * May contain multiple space-separated class names due to chunking.\n */\n className: string;\n\n /**\n * The original (or merged) styles object.\n * Available for extension via tastyStatic(base, overrides).\n */\n styles: Styles;\n\n /**\n * Returns className for implicit string coercion.\n * Enables `<div className={button} />` syntax.\n */\n toString(): string;\n}\n\n/**\n * Create a StaticStyle object.\n * Used internally by the Babel plugin to generate output.\n */\nexport function createStaticStyle(\n className: string,\n styles: Styles,\n): StaticStyle {\n return {\n className,\n styles,\n toString() {\n return this.className;\n },\n };\n}\n\n/**\n * Type guard to check if a value is a StaticStyle object.\n */\nexport function isStaticStyle(value: unknown): value is StaticStyle {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'className' in value &&\n 'styles' in value &&\n 'toString' in value &&\n typeof (value as StaticStyle).className === 'string' &&\n typeof (value as StaticStyle).styles === 'object'\n );\n}\n"],"mappings":";;;;;AA2CA,SAAgB,kBACd,WACA,QACa;AACb,QAAO;EACL;EACA;EACA,WAAW;AACT,UAAO,KAAK;;EAEf;;;;;AAMH,SAAgB,cAAc,OAAsC;AAClE,QACE,OAAO,UAAU,YACjB,UAAU,QACV,eAAe,SACf,YAAY,SACZ,cAAc,SACd,OAAQ,MAAsB,cAAc,YAC5C,OAAQ,MAAsB,WAAW"}