@tenphi/tasty 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (359) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +236 -0
  3. package/dist/_virtual/_rolldown/runtime.mjs +7 -0
  4. package/dist/chunks/cacheKey.d.ts +1 -0
  5. package/dist/chunks/cacheKey.js +70 -0
  6. package/dist/chunks/cacheKey.js.map +1 -0
  7. package/dist/chunks/cacheKey.mjs +70 -0
  8. package/dist/chunks/cacheKey.mjs.map +1 -0
  9. package/dist/chunks/definitions.d.ts +37 -0
  10. package/dist/chunks/definitions.js +260 -0
  11. package/dist/chunks/definitions.js.map +1 -0
  12. package/dist/chunks/definitions.mjs +260 -0
  13. package/dist/chunks/definitions.mjs.map +1 -0
  14. package/dist/chunks/index.d.ts +3 -0
  15. package/dist/chunks/renderChunk.d.ts +2 -0
  16. package/dist/chunks/renderChunk.js +61 -0
  17. package/dist/chunks/renderChunk.js.map +1 -0
  18. package/dist/chunks/renderChunk.mjs +61 -0
  19. package/dist/chunks/renderChunk.mjs.map +1 -0
  20. package/dist/config.d.ts +279 -0
  21. package/dist/config.js +400 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/config.mjs +231 -0
  24. package/dist/config.mjs.map +1 -0
  25. package/dist/css-writer.d.mts +45 -0
  26. package/dist/css-writer.mjs +74 -0
  27. package/dist/css-writer.mjs.map +1 -0
  28. package/dist/debug.d.ts +204 -0
  29. package/dist/debug.js +733 -0
  30. package/dist/debug.js.map +1 -0
  31. package/dist/extractor.d.mts +24 -0
  32. package/dist/extractor.mjs +150 -0
  33. package/dist/extractor.mjs.map +1 -0
  34. package/dist/hooks/index.d.ts +5 -0
  35. package/dist/hooks/useGlobalStyles.d.ts +27 -0
  36. package/dist/hooks/useGlobalStyles.js +56 -0
  37. package/dist/hooks/useGlobalStyles.js.map +1 -0
  38. package/dist/hooks/useKeyframes.d.ts +56 -0
  39. package/dist/hooks/useKeyframes.js +54 -0
  40. package/dist/hooks/useKeyframes.js.map +1 -0
  41. package/dist/hooks/useProperty.d.ts +79 -0
  42. package/dist/hooks/useProperty.js +91 -0
  43. package/dist/hooks/useProperty.js.map +1 -0
  44. package/dist/hooks/useRawCSS.d.ts +53 -0
  45. package/dist/hooks/useRawCSS.js +28 -0
  46. package/dist/hooks/useRawCSS.js.map +1 -0
  47. package/dist/hooks/useStyles.d.ts +40 -0
  48. package/dist/hooks/useStyles.js +169 -0
  49. package/dist/hooks/useStyles.js.map +1 -0
  50. package/dist/index.d.ts +38 -0
  51. package/dist/index.js +30 -0
  52. package/dist/injector/index.d.ts +157 -0
  53. package/dist/injector/index.js +154 -0
  54. package/dist/injector/index.js.map +1 -0
  55. package/dist/injector/injector.d.ts +139 -0
  56. package/dist/injector/injector.js +404 -0
  57. package/dist/injector/injector.js.map +1 -0
  58. package/dist/injector/injector.mjs +404 -0
  59. package/dist/injector/injector.mjs.map +1 -0
  60. package/dist/injector/sheet-manager.d.ts +127 -0
  61. package/dist/injector/sheet-manager.js +714 -0
  62. package/dist/injector/sheet-manager.js.map +1 -0
  63. package/dist/injector/sheet-manager.mjs +714 -0
  64. package/dist/injector/sheet-manager.mjs.map +1 -0
  65. package/dist/injector/types.d.mts +18 -0
  66. package/dist/injector/types.d.ts +135 -0
  67. package/dist/keyframes/index.js +206 -0
  68. package/dist/keyframes/index.js.map +1 -0
  69. package/dist/keyframes/index.mjs +156 -0
  70. package/dist/keyframes/index.mjs.map +1 -0
  71. package/dist/parser/classify.js +319 -0
  72. package/dist/parser/classify.js.map +1 -0
  73. package/dist/parser/classify.mjs +319 -0
  74. package/dist/parser/classify.mjs.map +1 -0
  75. package/dist/parser/const.js +33 -0
  76. package/dist/parser/const.js.map +1 -0
  77. package/dist/parser/const.mjs +33 -0
  78. package/dist/parser/const.mjs.map +1 -0
  79. package/dist/parser/lru.js +109 -0
  80. package/dist/parser/lru.js.map +1 -0
  81. package/dist/parser/lru.mjs +109 -0
  82. package/dist/parser/lru.mjs.map +1 -0
  83. package/dist/parser/parser.d.ts +25 -0
  84. package/dist/parser/parser.js +116 -0
  85. package/dist/parser/parser.js.map +1 -0
  86. package/dist/parser/parser.mjs +116 -0
  87. package/dist/parser/parser.mjs.map +1 -0
  88. package/dist/parser/tokenizer.js +69 -0
  89. package/dist/parser/tokenizer.js.map +1 -0
  90. package/dist/parser/tokenizer.mjs +69 -0
  91. package/dist/parser/tokenizer.mjs.map +1 -0
  92. package/dist/parser/types.d.mts +37 -0
  93. package/dist/parser/types.d.ts +46 -0
  94. package/dist/parser/types.js +46 -0
  95. package/dist/parser/types.js.map +1 -0
  96. package/dist/parser/types.mjs +46 -0
  97. package/dist/parser/types.mjs.map +1 -0
  98. package/dist/pipeline/conditions.js +377 -0
  99. package/dist/pipeline/conditions.js.map +1 -0
  100. package/dist/pipeline/conditions.mjs +377 -0
  101. package/dist/pipeline/conditions.mjs.map +1 -0
  102. package/dist/pipeline/exclusive.d.ts +1 -0
  103. package/dist/pipeline/exclusive.js +231 -0
  104. package/dist/pipeline/exclusive.js.map +1 -0
  105. package/dist/pipeline/exclusive.mjs +231 -0
  106. package/dist/pipeline/exclusive.mjs.map +1 -0
  107. package/dist/pipeline/index.d.ts +53 -0
  108. package/dist/pipeline/index.js +641 -0
  109. package/dist/pipeline/index.js.map +1 -0
  110. package/dist/pipeline/index.mjs +635 -0
  111. package/dist/pipeline/index.mjs.map +1 -0
  112. package/dist/pipeline/materialize.js +821 -0
  113. package/dist/pipeline/materialize.js.map +1 -0
  114. package/dist/pipeline/materialize.mjs +821 -0
  115. package/dist/pipeline/materialize.mjs.map +1 -0
  116. package/dist/pipeline/parseStateKey.d.ts +1 -0
  117. package/dist/pipeline/parseStateKey.js +418 -0
  118. package/dist/pipeline/parseStateKey.js.map +1 -0
  119. package/dist/pipeline/parseStateKey.mjs +418 -0
  120. package/dist/pipeline/parseStateKey.mjs.map +1 -0
  121. package/dist/pipeline/simplify.js +557 -0
  122. package/dist/pipeline/simplify.js.map +1 -0
  123. package/dist/pipeline/simplify.mjs +557 -0
  124. package/dist/pipeline/simplify.mjs.map +1 -0
  125. package/dist/plugins/index.d.ts +2 -0
  126. package/dist/plugins/okhsl-plugin.d.ts +35 -0
  127. package/dist/plugins/okhsl-plugin.js +371 -0
  128. package/dist/plugins/okhsl-plugin.js.map +1 -0
  129. package/dist/plugins/okhsl-plugin.mjs +345 -0
  130. package/dist/plugins/okhsl-plugin.mjs.map +1 -0
  131. package/dist/plugins/types.d.mts +49 -0
  132. package/dist/plugins/types.d.ts +69 -0
  133. package/dist/properties/index.js +158 -0
  134. package/dist/properties/index.js.map +1 -0
  135. package/dist/properties/index.mjs +141 -0
  136. package/dist/properties/index.mjs.map +1 -0
  137. package/dist/states/index.d.ts +45 -0
  138. package/dist/states/index.js +389 -0
  139. package/dist/states/index.js.map +1 -0
  140. package/dist/states/index.mjs +161 -0
  141. package/dist/states/index.mjs.map +1 -0
  142. package/dist/static/index.d.ts +5 -0
  143. package/dist/static/index.js +5 -0
  144. package/dist/static/tastyStatic.d.ts +46 -0
  145. package/dist/static/tastyStatic.js +31 -0
  146. package/dist/static/tastyStatic.js.map +1 -0
  147. package/dist/static/types.d.ts +49 -0
  148. package/dist/static/types.js +24 -0
  149. package/dist/static/types.js.map +1 -0
  150. package/dist/styles/align.d.ts +15 -0
  151. package/dist/styles/align.js +14 -0
  152. package/dist/styles/align.js.map +1 -0
  153. package/dist/styles/align.mjs +14 -0
  154. package/dist/styles/align.mjs.map +1 -0
  155. package/dist/styles/border.d.ts +25 -0
  156. package/dist/styles/border.js +114 -0
  157. package/dist/styles/border.js.map +1 -0
  158. package/dist/styles/border.mjs +114 -0
  159. package/dist/styles/border.mjs.map +1 -0
  160. package/dist/styles/color.d.ts +14 -0
  161. package/dist/styles/color.js +23 -0
  162. package/dist/styles/color.js.map +1 -0
  163. package/dist/styles/color.mjs +23 -0
  164. package/dist/styles/color.mjs.map +1 -0
  165. package/dist/styles/createStyle.js +77 -0
  166. package/dist/styles/createStyle.js.map +1 -0
  167. package/dist/styles/createStyle.mjs +77 -0
  168. package/dist/styles/createStyle.mjs.map +1 -0
  169. package/dist/styles/dimension.js +97 -0
  170. package/dist/styles/dimension.js.map +1 -0
  171. package/dist/styles/dimension.mjs +97 -0
  172. package/dist/styles/dimension.mjs.map +1 -0
  173. package/dist/styles/display.d.ts +37 -0
  174. package/dist/styles/display.js +67 -0
  175. package/dist/styles/display.js.map +1 -0
  176. package/dist/styles/display.mjs +67 -0
  177. package/dist/styles/display.mjs.map +1 -0
  178. package/dist/styles/fade.d.ts +15 -0
  179. package/dist/styles/fade.js +58 -0
  180. package/dist/styles/fade.js.map +1 -0
  181. package/dist/styles/fade.mjs +58 -0
  182. package/dist/styles/fade.mjs.map +1 -0
  183. package/dist/styles/fill.d.ts +44 -0
  184. package/dist/styles/fill.js +51 -0
  185. package/dist/styles/fill.js.map +1 -0
  186. package/dist/styles/fill.mjs +51 -0
  187. package/dist/styles/fill.mjs.map +1 -0
  188. package/dist/styles/flow.d.ts +16 -0
  189. package/dist/styles/flow.js +12 -0
  190. package/dist/styles/flow.js.map +1 -0
  191. package/dist/styles/flow.mjs +12 -0
  192. package/dist/styles/flow.mjs.map +1 -0
  193. package/dist/styles/gap.d.ts +31 -0
  194. package/dist/styles/gap.js +37 -0
  195. package/dist/styles/gap.js.map +1 -0
  196. package/dist/styles/gap.mjs +37 -0
  197. package/dist/styles/gap.mjs.map +1 -0
  198. package/dist/styles/height.d.ts +17 -0
  199. package/dist/styles/height.js +20 -0
  200. package/dist/styles/height.js.map +1 -0
  201. package/dist/styles/height.mjs +20 -0
  202. package/dist/styles/height.mjs.map +1 -0
  203. package/dist/styles/index.d.ts +2 -0
  204. package/dist/styles/index.js +9 -0
  205. package/dist/styles/index.js.map +1 -0
  206. package/dist/styles/index.mjs +9 -0
  207. package/dist/styles/index.mjs.map +1 -0
  208. package/dist/styles/inset.d.ts +50 -0
  209. package/dist/styles/inset.js +142 -0
  210. package/dist/styles/inset.js.map +1 -0
  211. package/dist/styles/inset.mjs +142 -0
  212. package/dist/styles/inset.mjs.map +1 -0
  213. package/dist/styles/justify.d.ts +15 -0
  214. package/dist/styles/justify.js +14 -0
  215. package/dist/styles/justify.js.map +1 -0
  216. package/dist/styles/justify.mjs +14 -0
  217. package/dist/styles/justify.mjs.map +1 -0
  218. package/dist/styles/list.d.ts +16 -0
  219. package/dist/styles/list.js +98 -0
  220. package/dist/styles/list.js.map +1 -0
  221. package/dist/styles/margin.d.ts +28 -0
  222. package/dist/styles/margin.js +96 -0
  223. package/dist/styles/margin.js.map +1 -0
  224. package/dist/styles/margin.mjs +96 -0
  225. package/dist/styles/margin.mjs.map +1 -0
  226. package/dist/styles/outline.d.ts +29 -0
  227. package/dist/styles/outline.js +65 -0
  228. package/dist/styles/outline.js.map +1 -0
  229. package/dist/styles/outline.mjs +65 -0
  230. package/dist/styles/outline.mjs.map +1 -0
  231. package/dist/styles/padding.d.ts +28 -0
  232. package/dist/styles/padding.js +96 -0
  233. package/dist/styles/padding.js.map +1 -0
  234. package/dist/styles/padding.mjs +96 -0
  235. package/dist/styles/padding.mjs.map +1 -0
  236. package/dist/styles/predefined.d.ts +74 -0
  237. package/dist/styles/predefined.js +241 -0
  238. package/dist/styles/predefined.js.map +1 -0
  239. package/dist/styles/predefined.mjs +232 -0
  240. package/dist/styles/predefined.mjs.map +1 -0
  241. package/dist/styles/preset.d.ts +47 -0
  242. package/dist/styles/preset.js +126 -0
  243. package/dist/styles/preset.js.map +1 -0
  244. package/dist/styles/preset.mjs +126 -0
  245. package/dist/styles/preset.mjs.map +1 -0
  246. package/dist/styles/radius.d.ts +14 -0
  247. package/dist/styles/radius.js +51 -0
  248. package/dist/styles/radius.js.map +1 -0
  249. package/dist/styles/radius.mjs +51 -0
  250. package/dist/styles/radius.mjs.map +1 -0
  251. package/dist/styles/scrollbar.d.ts +21 -0
  252. package/dist/styles/scrollbar.js +105 -0
  253. package/dist/styles/scrollbar.js.map +1 -0
  254. package/dist/styles/scrollbar.mjs +105 -0
  255. package/dist/styles/scrollbar.mjs.map +1 -0
  256. package/dist/styles/shadow.d.ts +14 -0
  257. package/dist/styles/shadow.js +24 -0
  258. package/dist/styles/shadow.js.map +1 -0
  259. package/dist/styles/shadow.mjs +24 -0
  260. package/dist/styles/shadow.mjs.map +1 -0
  261. package/dist/styles/styledScrollbar.d.ts +47 -0
  262. package/dist/styles/styledScrollbar.js +38 -0
  263. package/dist/styles/styledScrollbar.js.map +1 -0
  264. package/dist/styles/styledScrollbar.mjs +38 -0
  265. package/dist/styles/styledScrollbar.mjs.map +1 -0
  266. package/dist/styles/transition.d.ts +14 -0
  267. package/dist/styles/transition.js +138 -0
  268. package/dist/styles/transition.js.map +1 -0
  269. package/dist/styles/transition.mjs +138 -0
  270. package/dist/styles/transition.mjs.map +1 -0
  271. package/dist/styles/types.d.mts +492 -0
  272. package/dist/styles/types.d.ts +496 -0
  273. package/dist/styles/width.d.ts +17 -0
  274. package/dist/styles/width.js +20 -0
  275. package/dist/styles/width.js.map +1 -0
  276. package/dist/styles/width.mjs +20 -0
  277. package/dist/styles/width.mjs.map +1 -0
  278. package/dist/tasty.d.ts +983 -0
  279. package/dist/tasty.js +191 -0
  280. package/dist/tasty.js.map +1 -0
  281. package/dist/tokens/typography.d.ts +19 -0
  282. package/dist/tokens/typography.js +237 -0
  283. package/dist/tokens/typography.js.map +1 -0
  284. package/dist/types.d.ts +182 -0
  285. package/dist/utils/cache-wrapper.js +26 -0
  286. package/dist/utils/cache-wrapper.js.map +1 -0
  287. package/dist/utils/cache-wrapper.mjs +26 -0
  288. package/dist/utils/cache-wrapper.mjs.map +1 -0
  289. package/dist/utils/case-converter.js +8 -0
  290. package/dist/utils/case-converter.js.map +1 -0
  291. package/dist/utils/case-converter.mjs +8 -0
  292. package/dist/utils/case-converter.mjs.map +1 -0
  293. package/dist/utils/colors.d.ts +5 -0
  294. package/dist/utils/colors.js +9 -0
  295. package/dist/utils/colors.js.map +1 -0
  296. package/dist/utils/dotize.d.ts +26 -0
  297. package/dist/utils/dotize.js +122 -0
  298. package/dist/utils/dotize.js.map +1 -0
  299. package/dist/utils/filter-base-props.d.ts +15 -0
  300. package/dist/utils/filter-base-props.js +45 -0
  301. package/dist/utils/filter-base-props.js.map +1 -0
  302. package/dist/utils/get-display-name.d.ts +7 -0
  303. package/dist/utils/get-display-name.js +10 -0
  304. package/dist/utils/get-display-name.js.map +1 -0
  305. package/dist/utils/hsl-to-rgb.js +38 -0
  306. package/dist/utils/hsl-to-rgb.js.map +1 -0
  307. package/dist/utils/hsl-to-rgb.mjs +38 -0
  308. package/dist/utils/hsl-to-rgb.mjs.map +1 -0
  309. package/dist/utils/is-dev-env.js +19 -0
  310. package/dist/utils/is-dev-env.js.map +1 -0
  311. package/dist/utils/is-dev-env.mjs +19 -0
  312. package/dist/utils/is-dev-env.mjs.map +1 -0
  313. package/dist/utils/merge-styles.d.ts +7 -0
  314. package/dist/utils/merge-styles.js +146 -0
  315. package/dist/utils/merge-styles.js.map +1 -0
  316. package/dist/utils/merge-styles.mjs +146 -0
  317. package/dist/utils/merge-styles.mjs.map +1 -0
  318. package/dist/utils/mod-attrs.d.ts +8 -0
  319. package/dist/utils/mod-attrs.js +21 -0
  320. package/dist/utils/mod-attrs.js.map +1 -0
  321. package/dist/utils/okhsl-to-rgb.js +296 -0
  322. package/dist/utils/okhsl-to-rgb.js.map +1 -0
  323. package/dist/utils/okhsl-to-rgb.mjs +296 -0
  324. package/dist/utils/okhsl-to-rgb.mjs.map +1 -0
  325. package/dist/utils/process-tokens.d.ts +31 -0
  326. package/dist/utils/process-tokens.js +171 -0
  327. package/dist/utils/process-tokens.js.map +1 -0
  328. package/dist/utils/process-tokens.mjs +28 -0
  329. package/dist/utils/process-tokens.mjs.map +1 -0
  330. package/dist/utils/resolve-recipes.d.ts +17 -0
  331. package/dist/utils/resolve-recipes.js +143 -0
  332. package/dist/utils/resolve-recipes.js.map +1 -0
  333. package/dist/utils/resolve-recipes.mjs +143 -0
  334. package/dist/utils/resolve-recipes.mjs.map +1 -0
  335. package/dist/utils/string.js +8 -0
  336. package/dist/utils/string.js.map +1 -0
  337. package/dist/utils/string.mjs +8 -0
  338. package/dist/utils/string.mjs.map +1 -0
  339. package/dist/utils/styles.d.mts +18 -0
  340. package/dist/utils/styles.d.ts +183 -0
  341. package/dist/utils/styles.js +585 -0
  342. package/dist/utils/styles.js.map +1 -0
  343. package/dist/utils/styles.mjs +346 -0
  344. package/dist/utils/styles.mjs.map +1 -0
  345. package/dist/utils/typography.d.ts +36 -0
  346. package/dist/utils/typography.js +53 -0
  347. package/dist/utils/typography.js.map +1 -0
  348. package/dist/utils/warnings.d.ts +16 -0
  349. package/dist/utils/warnings.js +16 -0
  350. package/dist/utils/warnings.js.map +1 -0
  351. package/dist/zero/babel.d.mts +108 -0
  352. package/dist/zero/babel.mjs +282 -0
  353. package/dist/zero/babel.mjs.map +1 -0
  354. package/dist/zero/index.d.mts +3 -0
  355. package/dist/zero/index.mjs +4 -0
  356. package/dist/zero/next.d.mts +60 -0
  357. package/dist/zero/next.mjs +78 -0
  358. package/dist/zero/next.mjs.map +1 -0
  359. package/package.json +127 -0
@@ -0,0 +1,346 @@
1
+ import { StyleParser } from "../parser/parser.mjs";
2
+ import { okhslFunc } from "../plugins/okhsl-plugin.mjs";
3
+ import { cacheWrapper } from "./cache-wrapper.mjs";
4
+ import { okhslToRgb } from "./okhsl-to-rgb.mjs";
5
+ import { hslToRgb } from "./hsl-to-rgb.mjs";
6
+
7
+ //#region src/utils/styles.ts
8
+ /**
9
+ * Normalize a color token value.
10
+ * - Boolean `true` is converted to `'transparent'`
11
+ * - Boolean `false` returns `null` (signals the token should be skipped)
12
+ * - Other values are returned as-is
13
+ *
14
+ * @param value - The raw token value
15
+ * @returns Normalized value or null if the token should be skipped
16
+ */
17
+ function normalizeColorTokenValue(value) {
18
+ if (value === true) return "transparent";
19
+ if (value === false) return null;
20
+ return value;
21
+ }
22
+ const devMode = process.env.NODE_ENV !== "production";
23
+ const COLOR_VAR_PATTERN = /var\(--([a-z0-9-]+)-color/;
24
+ const COLOR_VAR_RGB_PATTERN = /var\(--([a-z0-9-]+)-color-rgb/;
25
+ const RGB_ALPHA_PATTERN = /\/\s*([0-9.]+)\)/;
26
+ const SIMPLE_COLOR_PATTERNS = [
27
+ /^#[0-9a-fA-F]{3,8}$/,
28
+ /^rgb\(/,
29
+ /^hsl\(/,
30
+ /^lch\(/,
31
+ /^oklch\(/,
32
+ /^okhsl\(/,
33
+ /^var\(--[a-z0-9-]+-color/,
34
+ /^currentColor$/,
35
+ /^transparent$/
36
+ ];
37
+ let colorWarningCount = 0;
38
+ const MAX_COLOR_WARNINGS = 10;
39
+ const CUSTOM_UNITS = {
40
+ r: "6px",
41
+ cr: "10px",
42
+ bw: "1px",
43
+ ow: "3px",
44
+ x: "8px",
45
+ fs: "var(--font-size)",
46
+ lh: "var(--line-height)",
47
+ sf: function sf(num) {
48
+ return `minmax(0, ${num}fr)`;
49
+ }
50
+ };
51
+ const DIRECTIONS = [
52
+ "top",
53
+ "right",
54
+ "bottom",
55
+ "left"
56
+ ];
57
+ let __tastyParser = null;
58
+ function getOrCreateParser() {
59
+ if (!__tastyParser) {
60
+ __tastyParser = new StyleParser({ units: CUSTOM_UNITS });
61
+ __tastyParser.setFuncs(__tastyFuncs);
62
+ }
63
+ return __tastyParser;
64
+ }
65
+ const __tastyFuncs = { okhsl: okhslFunc };
66
+ /**
67
+ * Get the global StyleParser instance.
68
+ * Used by configure() to apply parser configuration.
69
+ */
70
+ function getGlobalParser() {
71
+ return getOrCreateParser();
72
+ }
73
+ /**
74
+ * Get the current custom functions registry.
75
+ * Used by configure() to merge with new functions.
76
+ */
77
+ function getGlobalFuncs() {
78
+ return __tastyFuncs;
79
+ }
80
+ /**
81
+ * Storage for predefined tokens that are replaced during style parsing.
82
+ * Keys are token names (with $ or # prefix), values are pre-processed CSS values.
83
+ */
84
+ let __globalPredefinedTokens = null;
85
+ /**
86
+ * Set global predefined tokens.
87
+ * Called from configure() after processing token values.
88
+ * Merges with existing tokens (new tokens override existing ones with same key).
89
+ * Keys are normalized to lowercase (parser lowercases input before classification).
90
+ * @internal
91
+ */
92
+ function setGlobalPredefinedTokens(tokens) {
93
+ const normalizedTokens = {};
94
+ for (const [key, value] of Object.entries(tokens)) {
95
+ const lowerKey = key.toLowerCase();
96
+ const lowerValue = value.toLowerCase();
97
+ if (lowerKey.startsWith("#") && lowerValue === "#current") {
98
+ console.warn(`Tasty: Using #current to define color token "${key}" is not supported. The #current token represents currentcolor which cannot be used as a base for other tokens.`);
99
+ continue;
100
+ }
101
+ normalizedTokens[lowerKey] = value;
102
+ }
103
+ __globalPredefinedTokens = __globalPredefinedTokens ? {
104
+ ...__globalPredefinedTokens,
105
+ ...normalizedTokens
106
+ } : normalizedTokens;
107
+ getOrCreateParser().clearCache();
108
+ }
109
+ /**
110
+ * Get the current global predefined tokens.
111
+ * Returns null if no tokens are configured.
112
+ */
113
+ function getGlobalPredefinedTokens() {
114
+ return __globalPredefinedTokens;
115
+ }
116
+ /**
117
+ *
118
+ * @param {String} value
119
+ * @param {Number} mode
120
+ * @returns {Object<String,String|Array>}
121
+ */
122
+ function parseStyle(value) {
123
+ let str;
124
+ if (typeof value === "string") str = value;
125
+ else if (typeof value === "number") str = String(value);
126
+ else str = "";
127
+ return getOrCreateParser().process(str);
128
+ }
129
+ /**
130
+ * Parse color. Find it value, name and opacity.
131
+ * Optimized to avoid heavy parseStyle calls for simple color patterns.
132
+ */
133
+ function parseColor(val, ignoreError = false) {
134
+ if (typeof val !== "string") val = String(val ?? "");
135
+ val = val.trim();
136
+ if (!val) return {};
137
+ const isSimpleColor = SIMPLE_COLOR_PATTERNS.some((pattern) => pattern.test(val));
138
+ let firstColor;
139
+ if (isSimpleColor) firstColor = val;
140
+ else {
141
+ const extractedColor = parseStyle(val).groups.find((g) => g.colors.length)?.colors[0];
142
+ if (!extractedColor) {
143
+ if (!ignoreError && devMode && colorWarningCount < MAX_COLOR_WARNINGS) {
144
+ console.warn("CubeUIKit: unable to parse color:", val);
145
+ colorWarningCount++;
146
+ if (colorWarningCount === MAX_COLOR_WARNINGS) console.warn("CubeUIKit: color parsing warnings will be suppressed from now on");
147
+ }
148
+ return {};
149
+ }
150
+ firstColor = extractedColor;
151
+ }
152
+ let nameMatch = firstColor.match(COLOR_VAR_PATTERN);
153
+ if (!nameMatch) nameMatch = firstColor.match(COLOR_VAR_RGB_PATTERN);
154
+ let opacity;
155
+ if (firstColor.startsWith("rgb") || firstColor.startsWith("hsl") || firstColor.startsWith("lch") || firstColor.startsWith("oklch") || firstColor.startsWith("okhsl")) {
156
+ const alphaMatch = firstColor.match(RGB_ALPHA_PATTERN);
157
+ if (alphaMatch) {
158
+ const v = parseFloat(alphaMatch[1]);
159
+ if (!isNaN(v)) opacity = v * 100;
160
+ }
161
+ }
162
+ return {
163
+ color: firstColor,
164
+ name: nameMatch ? nameMatch[1] : void 0,
165
+ opacity
166
+ };
167
+ }
168
+ function strToRgb(color, _ignoreAlpha = false) {
169
+ if (!color) return void 0;
170
+ if (color.startsWith("rgb")) return color;
171
+ if (color.startsWith("#")) return hexToRgb(color);
172
+ if (color.startsWith("okhsl(")) return okhslToRgb(color);
173
+ if (color.startsWith("hsl")) return hslToRgb(color);
174
+ return null;
175
+ }
176
+ /**
177
+ * Extract RGB values from an rgb()/rgba() string.
178
+ * Supports all modern CSS syntax variations:
179
+ * - Comma-separated: rgb(255, 128, 0)
180
+ * - Space-separated: rgb(255 128 0)
181
+ * - Fractional: rgb(128.5, 64.3, 32.1)
182
+ * - Percentages: rgb(50%, 25%, 75%)
183
+ * - Slash alpha notation: rgb(255 128 0 / 0.5)
184
+ *
185
+ * Returns array of RGB values (0-255 range), converting percentages as needed.
186
+ */
187
+ function getRgbValuesFromRgbaString(str) {
188
+ const match = str.match(/rgba?\(([^)]+)\)/i);
189
+ if (!match) return [];
190
+ const [colorPart] = match[1].trim().split("/");
191
+ return colorPart.trim().split(/[,\s]+/).filter(Boolean).slice(0, 3).map((part) => {
192
+ part = part.trim();
193
+ if (part.endsWith("%")) return parseFloat(part) / 100 * 255;
194
+ return parseFloat(part);
195
+ });
196
+ }
197
+ function hexToRgb(hex) {
198
+ const rgba = hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, (m, r, g, b) => "#" + r + r + g + g + b + b).substring(1).match(/.{2}/g).map((x, i) => parseInt(x, 16) * (i === 3 ? 1 / 255 : 1));
199
+ if (rgba.some((v) => Number.isNaN(v))) return null;
200
+ if (rgba.length >= 3) return `rgb(${rgba.slice(0, 3).join(" ")}${rgba.length > 3 ? ` / ${rgba[3]}` : ""})`;
201
+ return null;
202
+ }
203
+ function filterMods(mods, allowedMods) {
204
+ return mods.filter((mod) => allowedMods.includes(mod));
205
+ }
206
+ const STATES_REGEXP = /([&|!^])|([()])|(@media:[a-z]+)|(@media\([^)]+\))|(@root\([^)]+\))|(@own\([^)]+\))|(@\([^)]+\))|(@starting)|(@[A-Za-z][A-Za-z0-9-]*)|([a-z][a-z0-9-]+=(?:"[^"]*"|'[^']*'|[^\s&|!^()]+))|([a-z][a-z0-9-]+)|(:[a-z][a-z0-9-]+\([^)]+\)|:[a-z][a-z0-9-]+)|(\.[a-z][a-z0-9-]+)|(\[[^\]]+])/gi;
207
+ const STATE_OPERATOR_LIST = [
208
+ "!",
209
+ "&",
210
+ "|",
211
+ "^"
212
+ ];
213
+ /**
214
+ * Convert state notation tokens to a compute model (string, or nested [op, lhs, rhs]).
215
+ */
216
+ function convertTokensToComputeUnits(tokens) {
217
+ if (tokens.length === 1) return tokens[0];
218
+ const hasLength = (x) => typeof x === "string" || Array.isArray(x);
219
+ STATE_OPERATOR_LIST.forEach((operator) => {
220
+ let i;
221
+ while ((i = tokens.indexOf(operator)) !== -1) {
222
+ const token = tokens[i];
223
+ if (token === "!") {
224
+ const next = tokens[i + 1];
225
+ if (next !== void 0 && hasLength(next) && next.length !== 1) tokens.splice(i, 2, ["!", next]);
226
+ else tokens.splice(i, 1);
227
+ } else {
228
+ const prev = tokens[i - 1];
229
+ const next = tokens[i + 1];
230
+ if (prev !== void 0 && next !== void 0 && hasLength(prev) && hasLength(next) && prev.length !== 1 && next.length !== 1) tokens.splice(i - 1, 3, [
231
+ token,
232
+ prev,
233
+ next
234
+ ]);
235
+ else tokens.splice(i, 1);
236
+ }
237
+ }
238
+ });
239
+ return tokens.length === 1 ? tokens[0] : tokens;
240
+ }
241
+ /**
242
+ * Replace commas with | only outside of parentheses.
243
+ * This preserves commas in advanced states like @(card, w < 600px)
244
+ */
245
+ function replaceCommasOutsideParens(str) {
246
+ let result = "";
247
+ let depth = 0;
248
+ for (const char of str) if (char === "(") {
249
+ depth++;
250
+ result += char;
251
+ } else if (char === ")") {
252
+ depth--;
253
+ result += char;
254
+ } else if (char === "," && depth === 0) result += "|";
255
+ else result += char;
256
+ return result;
257
+ }
258
+ /**
259
+ * Parse state notation and return tokens, modifiers and compute model.
260
+ */
261
+ function parseStateNotationInner(notation, value) {
262
+ const tokens = replaceCommasOutsideParens(notation).match(STATES_REGEXP);
263
+ if (!tokens || !tokens.length) return {
264
+ model: void 0,
265
+ mods: [],
266
+ notMods: [],
267
+ tokens: [],
268
+ value
269
+ };
270
+ else if (tokens.length === 1) return {
271
+ model: tokens[0],
272
+ mods: tokens.slice(0),
273
+ notMods: [],
274
+ tokens,
275
+ value
276
+ };
277
+ const mods = [];
278
+ const operations = [[]];
279
+ let list = operations[0];
280
+ let position = 0;
281
+ let operation;
282
+ tokens.forEach((token) => {
283
+ switch (token) {
284
+ case "(":
285
+ operation = [];
286
+ position++;
287
+ list = operations[position] = operation;
288
+ break;
289
+ case ")":
290
+ position--;
291
+ operations[position].push(convertTokensToComputeUnits(list));
292
+ list = operations[position];
293
+ break;
294
+ default:
295
+ if (token.length > 1) {
296
+ if (!mods.includes(token)) mods.push(token);
297
+ }
298
+ list.push(token);
299
+ }
300
+ });
301
+ while (position) {
302
+ position--;
303
+ operations[position].push(convertTokensToComputeUnits(list));
304
+ list = operations[position];
305
+ }
306
+ return {
307
+ tokens,
308
+ mods,
309
+ notMods: [],
310
+ model: convertTokensToComputeUnits(operations[0]),
311
+ value
312
+ };
313
+ }
314
+ const parseStateNotation = cacheWrapper(parseStateNotationInner);
315
+ const _innerCache = /* @__PURE__ */ new WeakMap();
316
+ function stringifyStyles(styles) {
317
+ if (styles == null || typeof styles !== "object") return "";
318
+ const keys = Object.keys(styles).sort();
319
+ const parts = [];
320
+ for (const k of keys) {
321
+ const v = styles[k];
322
+ if (v === void 0 || typeof v === "function" || typeof v === "symbol") continue;
323
+ const c0 = k.charCodeAt(0);
324
+ const needsInnerSort = (c0 >= 65 && c0 <= 90 || c0 === 38) && v && typeof v === "object" && !Array.isArray(v);
325
+ let sv;
326
+ if (needsInnerSort) {
327
+ sv = _innerCache.get(v);
328
+ if (sv === void 0) {
329
+ const innerKeys = Object.keys(v).sort();
330
+ const innerParts = [];
331
+ for (const ik of innerKeys) {
332
+ const ivs = JSON.stringify(v[ik]);
333
+ if (ivs !== void 0) innerParts.push(JSON.stringify(ik) + ":" + ivs);
334
+ }
335
+ sv = "{" + innerParts.join(",") + "}";
336
+ _innerCache.set(v, sv);
337
+ }
338
+ } else sv = JSON.stringify(v);
339
+ parts.push(JSON.stringify(k) + ":" + sv);
340
+ }
341
+ return "{" + parts.join(",") + "}";
342
+ }
343
+
344
+ //#endregion
345
+ export { CUSTOM_UNITS, DIRECTIONS, filterMods, getGlobalFuncs, getGlobalParser, getGlobalPredefinedTokens, getRgbValuesFromRgbaString, normalizeColorTokenValue, parseColor, parseStyle, setGlobalPredefinedTokens, strToRgb, stringifyStyles };
346
+ //# sourceMappingURL=styles.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.mjs","names":[],"sources":["../../src/utils/styles.ts"],"sourcesContent":["import { StyleParser } from '../parser/parser';\nimport { okhslFunc } from '../plugins/okhsl-plugin';\nimport { createStateParserContext, parseAdvancedState } from '../states';\nimport type { Styles } from '../styles/types';\n\nimport { cacheWrapper } from './cache-wrapper';\nimport { camelToKebab } from './case-converter';\nimport { hslToRgb } from './hsl-to-rgb';\nimport { okhslToRgb } from './okhsl-to-rgb';\n\nimport type { ProcessedStyle, StyleDetails } from '../parser/types';\nimport type {\n AtRuleContext,\n ParsedAdvancedState,\n StateParserContext,\n} from '../states';\n\nexport type StyleValue<T = string> = T | boolean | number | null | undefined;\n\n/**\n * Normalize a color token value.\n * - Boolean `true` is converted to `'transparent'`\n * - Boolean `false` returns `null` (signals the token should be skipped)\n * - Other values are returned as-is\n *\n * @param value - The raw token value\n * @returns Normalized value or null if the token should be skipped\n */\nexport function normalizeColorTokenValue<T>(\n value: T | boolean,\n): T | 'transparent' | null {\n if (value === true) {\n return 'transparent';\n }\n if (value === false) {\n return null;\n }\n return value as T;\n}\n\nexport type StyleValueStateMap<T = string> = Record<string, StyleValue<T> | '@inherit'>;\n\n/**\n * Combined type for style values that can be either a direct value or a state map.\n * Use this for component props that accept style values.\n */\nexport type StylePropValue<T = string> = StyleValue<T> | StyleValueStateMap<T>;\n\nexport type ComputeModel = string | number;\n\nexport type CSSMap = { $?: string | string[] } & Record<string, string | string[]>;\n\nexport type StyleHandlerResult = CSSMap | CSSMap[] | void;\n\nexport type RawStyleHandler = (value: StyleValueStateMap) => StyleHandlerResult;\n\nexport type StyleHandler = RawStyleHandler & {\n __lookupStyles: string[];\n};\n\n/**\n * Handler definition forms for configure() and plugins.\n * - Function only: lookup styles inferred from key name\n * - Single property tuple: ['styleName', handler]\n * - Multi-property tuple: [['style1', 'style2'], handler]\n */\nexport type StyleHandlerDefinition =\n | RawStyleHandler\n | [string, RawStyleHandler]\n | [string[], RawStyleHandler];\n\nexport interface StyleStateData {\n model?: ComputeModel;\n tokens?: string[];\n value: StyleValue | StyleValueStateMap | StyleStateData;\n /** The list of mods to apply */\n mods: string[];\n /** The list of **not** mods to apply (e.g. `:not(:hover)`) */\n notMods: string[];\n /** Advanced states (media queries, container queries, etc.) */\n advancedStates?: ParsedAdvancedState[];\n /** At-rule context for CSS generation */\n atRuleContext?: AtRuleContext;\n /** Own mods for sub-element states (from @own()) - applied to sub-element selector */\n ownMods?: string[];\n /** Negated own mods for sub-element states */\n negatedOwnMods?: string[];\n}\n\nexport interface ParsedColor {\n color?: string;\n name?: string;\n opacity?: number;\n}\n\nexport type StyleStateDataList = StyleStateData[];\n\nexport type StyleStateDataListMap = Record<string, StyleStateDataList>;\n\nexport type StyleMap = Record<string, StyleValue | StyleValueStateMap>;\n\nexport type StyleStateMap = Record<string, StyleStateData>;\n\nconst devMode = process.env.NODE_ENV !== 'production';\n\n// Precompiled regex patterns for parseColor optimization\n// Match var(--name-color...) and extract the name, regardless of fallbacks\nconst COLOR_VAR_PATTERN = /var\\(--([a-z0-9-]+)-color/;\nconst COLOR_VAR_RGB_PATTERN = /var\\(--([a-z0-9-]+)-color-rgb/;\nconst RGB_ALPHA_PATTERN = /\\/\\s*([0-9.]+)\\)/;\nconst SIMPLE_COLOR_PATTERNS = [\n /^#[0-9a-fA-F]{3,8}$/, // Hex colors: #fff, #ffffff, #ffff, #ffffffff\n /^rgb\\(/, // RGB/RGBA functions\n /^hsl\\(/, // HSL/HSLA functions\n /^lch\\(/, // LCH color functions\n /^oklch\\(/, // OKLCH color functions\n /^okhsl\\(/, // OKHSL color functions\n /^var\\(--[a-z0-9-]+-color/, // CSS custom properties for colors\n /^currentColor$/, // CSS currentColor keyword\n /^transparent$/, // CSS transparent keyword\n];\n\n// Rate limiting for dev warnings to avoid spam\nlet colorWarningCount = 0;\nconst MAX_COLOR_WARNINGS = 10;\n\nexport const CUSTOM_UNITS = {\n r: '6px',\n cr: '10px',\n bw: '1px',\n ow: '3px',\n x: '8px',\n fs: 'var(--font-size)',\n lh: 'var(--line-height)',\n sf: function sf(num) {\n return `minmax(0, ${num}fr)`;\n },\n};\n\nexport const DIRECTIONS = ['top', 'right', 'bottom', 'left'];\n\nconst MOD_NAME_CACHE = new Map();\n\nexport function getModSelector(modName: string): string {\n if (!MOD_NAME_CACHE.has(modName)) {\n let selector: string;\n\n // Check if it's a shorthand value mod: key=value, key^=value, key$=value, key*=value\n // Supports: key=value, key=\"value\", key='value', and with ^=, $=, *= operators\n const valueModMatch = modName.match(\n /^([a-z][a-z0-9-]*)(\\^=|\\$=|\\*=|=)(.+)$/i,\n );\n if (valueModMatch) {\n const key = valueModMatch[1];\n const operator = valueModMatch[2];\n let value = valueModMatch[3];\n\n // Remove quotes if present\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n // Convert to full attribute selector with the appropriate operator\n selector = `[data-${camelToKebab(key)}${operator}\"${value}\"]`;\n } else if (modName.match(/^[a-z]/)) {\n // Boolean mod: convert camelCase to kebab-case\n selector = `[data-${camelToKebab(modName)}]`;\n } else {\n // Check if it contains :has() with capitalized element names\n if (modName.includes(':has(')) {\n selector = modName.replace(/:has\\(([^)]+)\\)/g, (match, content) => {\n // Validate that combinators have spaces around them\n // Check for capitalized words adjacent to combinators without spaces\n const invalidPattern = /[A-Z][a-z]*[>+~]|[>+~][A-Z][a-z]*/;\n if (invalidPattern.test(content)) {\n console.error(\n `[Tasty] Invalid :has() selector syntax: \"${modName}\"\\n` +\n `Combinators (>, +, ~) must have spaces around them when used with element names.\\n` +\n `Example: Use \":has(Body > Row)\" instead of \":has(Body>Row)\"\\n` +\n `This is a design choice: the parser uses simple whitespace splitting for performance.`,\n );\n }\n\n // Transform capitalized words to [data-element=\"...\"] selectors\n const tokens = content.split(/\\s+/);\n const transformed = tokens.map((token: string) =>\n /^[A-Z]/.test(token) ? `[data-element=\"${token}\"]` : token,\n );\n return `:has(${transformed.join(' ')})`;\n });\n } else {\n // Pass through (e.g., :hover, .class, [attr])\n selector = modName;\n }\n }\n\n MOD_NAME_CACHE.set(modName, selector);\n }\n\n return MOD_NAME_CACHE.get(modName);\n}\n\n// Lazy-initialized to break the circular dependency:\n// parser.ts → classify.ts → utils/styles.ts → parser.ts\nlet __tastyParser: StyleParser | null = null;\n\nfunction getOrCreateParser(): StyleParser {\n if (!__tastyParser) {\n __tastyParser = new StyleParser({ units: CUSTOM_UNITS });\n __tastyParser.setFuncs(__tastyFuncs);\n }\n return __tastyParser;\n}\n\n// Registry for user-provided custom functions that the parser can call.\n// It is updated through the `customFunc` helper exported below.\n// okhsl is registered as a built-in function so it works regardless of\n// tree-shaking or module initialization order.\nconst __tastyFuncs: Record<string, (groups: StyleDetails[]) => string> = {\n okhsl: okhslFunc,\n};\n\nexport function customFunc(\n name: string,\n fn: (groups: StyleDetails[]) => string,\n) {\n __tastyFuncs[name] = fn;\n getOrCreateParser().setFuncs(__tastyFuncs);\n}\n\n/**\n * Get the global StyleParser instance.\n * Used by configure() to apply parser configuration.\n */\nexport function getGlobalParser(): StyleParser {\n return getOrCreateParser();\n}\n\n/**\n * Get the current custom functions registry.\n * Used by configure() to merge with new functions.\n */\nexport function getGlobalFuncs(): Record<\n string,\n (groups: StyleDetails[]) => string\n> {\n return __tastyFuncs;\n}\n\n// ============================================================================\n// Global Predefined Tokens\n// ============================================================================\n\n/**\n * Storage for predefined tokens that are replaced during style parsing.\n * Keys are token names (with $ or # prefix), values are pre-processed CSS values.\n */\nlet __globalPredefinedTokens: Record<string, string> | null = null;\n\n/**\n * Set global predefined tokens.\n * Called from configure() after processing token values.\n * Merges with existing tokens (new tokens override existing ones with same key).\n * Keys are normalized to lowercase (parser lowercases input before classification).\n * @internal\n */\nexport function setGlobalPredefinedTokens(\n tokens: Record<string, string>,\n): void {\n // Normalize keys to lowercase for case-insensitive matching\n const normalizedTokens: Record<string, string> = {};\n for (const [key, value] of Object.entries(tokens)) {\n const lowerKey = key.toLowerCase();\n const lowerValue = value.toLowerCase();\n\n // Warn if trying to use bare #current to define other color tokens\n // #current represents currentcolor which cannot be used as a base for recursive token resolution\n // Note: #current.5 (with opacity) is allowed since it resolves to a concrete color-mix value\n if (lowerKey.startsWith('#') && lowerValue === '#current') {\n console.warn(\n `Tasty: Using #current to define color token \"${key}\" is not supported. ` +\n `The #current token represents currentcolor which cannot be used as a base for other tokens.`,\n );\n continue; // Skip this token\n }\n\n normalizedTokens[lowerKey] = value;\n }\n // Merge with existing tokens (consistent with how states, units, funcs are handled)\n __globalPredefinedTokens = __globalPredefinedTokens\n ? { ...__globalPredefinedTokens, ...normalizedTokens }\n : normalizedTokens;\n // Clear parser cache since token values affect parsing\n getOrCreateParser().clearCache();\n}\n\n/**\n * Get the current global predefined tokens.\n * Returns null if no tokens are configured.\n */\nexport function getGlobalPredefinedTokens(): Record<string, string> | null {\n return __globalPredefinedTokens;\n}\n\n/**\n * Reset global predefined tokens.\n * Used for testing.\n * @internal\n */\nexport function resetGlobalPredefinedTokens(): void {\n __globalPredefinedTokens = null;\n // Clear parser cache since token availability affects parsing\n getOrCreateParser().clearCache();\n}\n\n/**\n *\n * @param {String} value\n * @param {Number} mode\n * @returns {Object<String,String|Array>}\n */\nexport function parseStyle(value: StyleValue): ProcessedStyle {\n let str: string;\n\n if (typeof value === 'string') {\n str = value;\n } else if (typeof value === 'number') {\n str = String(value);\n } else {\n // boolean, null, undefined, objects etc. → empty string\n str = '';\n }\n\n return getOrCreateParser().process(str);\n}\n\n/**\n * Parse color. Find it value, name and opacity.\n * Optimized to avoid heavy parseStyle calls for simple color patterns.\n */\nexport function parseColor(val: string, ignoreError = false): ParsedColor {\n // Early return for non-strings or empty values\n if (typeof val !== 'string') {\n val = String(val ?? '');\n }\n\n val = val.trim();\n if (!val) return {};\n\n // Fast path: Check if it's a simple color pattern that doesn't need full parsing\n const isSimpleColor = SIMPLE_COLOR_PATTERNS.some((pattern) =>\n pattern.test(val),\n );\n\n let firstColor: string;\n if (isSimpleColor) {\n // For simple colors, use the value directly without parsing\n firstColor = val;\n } else {\n const processed = parseStyle(val);\n const extractedColor = processed.groups.find((g) => g.colors.length)\n ?.colors[0];\n\n if (!extractedColor) {\n // Rate-limited warning to avoid spam\n if (!ignoreError && devMode && colorWarningCount < MAX_COLOR_WARNINGS) {\n console.warn('CubeUIKit: unable to parse color:', val);\n colorWarningCount++;\n if (colorWarningCount === MAX_COLOR_WARNINGS) {\n console.warn(\n 'CubeUIKit: color parsing warnings will be suppressed from now on',\n );\n }\n }\n return {};\n }\n\n firstColor = extractedColor;\n }\n\n // Extract color name (if present) from variable pattern using precompiled regex\n let nameMatch = firstColor.match(COLOR_VAR_PATTERN);\n if (!nameMatch) {\n nameMatch = firstColor.match(COLOR_VAR_RGB_PATTERN);\n }\n\n let opacity: number | undefined;\n if (\n firstColor.startsWith('rgb') ||\n firstColor.startsWith('hsl') ||\n firstColor.startsWith('lch') ||\n firstColor.startsWith('oklch') ||\n firstColor.startsWith('okhsl')\n ) {\n const alphaMatch = firstColor.match(RGB_ALPHA_PATTERN);\n if (alphaMatch) {\n const v = parseFloat(alphaMatch[1]);\n if (!isNaN(v)) opacity = v * 100;\n }\n }\n\n return {\n color: firstColor,\n name: nameMatch ? nameMatch[1] : undefined,\n opacity,\n };\n}\n\nexport function strToRgb(color, _ignoreAlpha = false) {\n if (!color) return undefined;\n\n if (color.startsWith('rgb')) return color;\n\n if (color.startsWith('#')) return hexToRgb(color);\n\n if (color.startsWith('okhsl(')) return okhslToRgb(color);\n\n if (color.startsWith('hsl')) return hslToRgb(color);\n\n return null;\n}\n\n/**\n * Extract RGB values from an rgb()/rgba() string.\n * Supports all modern CSS syntax variations:\n * - Comma-separated: rgb(255, 128, 0)\n * - Space-separated: rgb(255 128 0)\n * - Fractional: rgb(128.5, 64.3, 32.1)\n * - Percentages: rgb(50%, 25%, 75%)\n * - Slash alpha notation: rgb(255 128 0 / 0.5)\n *\n * Returns array of RGB values (0-255 range), converting percentages as needed.\n */\nexport function getRgbValuesFromRgbaString(str: string): number[] {\n // Extract content inside rgb()/rgba()\n const match = str.match(/rgba?\\(([^)]+)\\)/i);\n if (!match) return [];\n\n const inner = match[1].trim();\n // Split by slash first (for alpha), then handle color components\n const [colorPart] = inner.split('/');\n // Split by comma or whitespace\n const parts = colorPart\n .trim()\n .split(/[,\\s]+/)\n .filter(Boolean);\n\n return parts.slice(0, 3).map((part) => {\n part = part.trim();\n if (part.endsWith('%')) {\n // Convert percentage to 0-255 range\n return (parseFloat(part) / 100) * 255;\n }\n return parseFloat(part);\n });\n}\n\nexport function hexToRgb(hex) {\n const rgba = hex\n .replace(\n /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i,\n (m, r, g, b) => '#' + r + r + g + g + b + b,\n )\n .substring(1)\n .match(/.{2}/g)\n .map((x, i) => parseInt(x, 16) * (i === 3 ? 1 / 255 : 1));\n\n if (rgba.some((v) => Number.isNaN(v))) {\n return null;\n }\n\n if (rgba.length >= 3) {\n return `rgb(${rgba.slice(0, 3).join(' ')}${rgba.length > 3 ? ` / ${rgba[3]}` : ''})`;\n }\n\n return null;\n}\n\nexport function filterMods(mods, allowedMods) {\n return mods.filter((mod) => allowedMods.includes(mod));\n}\n\nexport function extendStyles(defaultStyles, newStyles) {\n let styles = {};\n\n if (!defaultStyles) {\n if (!newStyles) {\n return styles;\n }\n } else {\n styles = Object.assign({}, defaultStyles);\n }\n\n if (newStyles) {\n Object.keys(newStyles).forEach((key) => {\n if (newStyles[key] != null) {\n styles[key] = newStyles[key];\n }\n });\n }\n\n return styles;\n}\n\n/**\n * Split properties into style and non-style properties.\n * @param props - Component prop map.\n * @param [styleList] - List of all style properties.\n * @param [defaultStyles] - Default style map of the component.\n * @param [propMap] - Props to style alias map.\n * @param [ignoreList] - A list of properties to ignore.\n */\nexport function extractStyles(\n props: Record<string, unknown>,\n styleList: readonly string[] = [],\n defaultStyles?: Styles,\n propMap?: Record<string, string>,\n ignoreList: readonly string[] = [],\n): Styles {\n const styles: Styles = {\n ...defaultStyles,\n ...(ignoreList.includes('styles')\n ? undefined\n : props.styles && typeof props.styles === 'object'\n ? (props.styles as Styles)\n : undefined),\n };\n\n Object.keys(props).forEach((prop) => {\n const propName = propMap ? propMap[prop] || prop : prop;\n const value = props[prop];\n\n if (ignoreList && ignoreList.includes(prop)) {\n // do nothing\n } else if (styleList.includes(propName)) {\n styles[propName] = value as Styles[keyof Styles];\n }\n }, {});\n\n return styles;\n}\n\n// Enhanced regex that includes advanced state patterns\n// Matches: operators, parentheses, @media(...), @(...), @root(...), @own(...), @starting, @predefined,\n// value mods, boolean mods, pseudo-classes, classes, attribute selectors\nconst STATES_REGEXP =\n /([&|!^])|([()])|(@media:[a-z]+)|(@media\\([^)]+\\))|(@root\\([^)]+\\))|(@own\\([^)]+\\))|(@\\([^)]+\\))|(@starting)|(@[A-Za-z][A-Za-z0-9-]*)|([a-z][a-z0-9-]+=(?:\"[^\"]*\"|'[^']*'|[^\\s&|!^()]+))|([a-z][a-z0-9-]+)|(:[a-z][a-z0-9-]+\\([^)]+\\)|:[a-z][a-z0-9-]+)|(\\.[a-z][a-z0-9-]+)|(\\[[^\\]]+])/gi;\n\n/**\n * Check if a token is an advanced state (starts with @)\n */\nexport function isAdvancedStateToken(token: string): boolean {\n return token.startsWith('@') || token.startsWith('!@');\n}\nexport const STATE_OPERATORS = {\n NOT: '!',\n AND: '&',\n OR: '|',\n XOR: '^',\n};\n\nexport const STATE_OPERATOR_LIST = ['!', '&', '|', '^'];\n\n/**\n * Convert state notation tokens to a compute model (string, or nested [op, lhs, rhs]).\n */\nfunction convertTokensToComputeUnits(tokens: unknown[]): unknown {\n if (tokens.length === 1) {\n return tokens[0];\n }\n\n const hasLength = (x: unknown): x is string | unknown[] =>\n typeof x === 'string' || Array.isArray(x);\n\n STATE_OPERATOR_LIST.forEach((operator) => {\n let i;\n\n while ((i = tokens.indexOf(operator)) !== -1) {\n const token = tokens[i];\n\n if (token === '!') {\n const next = tokens[i + 1];\n if (next !== undefined && hasLength(next) && next.length !== 1) {\n tokens.splice(i, 2, ['!', next]);\n } else {\n tokens.splice(i, 1);\n }\n } else {\n const prev = tokens[i - 1];\n const next = tokens[i + 1];\n if (\n prev !== undefined &&\n next !== undefined &&\n hasLength(prev) &&\n hasLength(next) &&\n prev.length !== 1 &&\n next.length !== 1\n ) {\n tokens.splice(i - 1, 3, [token, prev, next]);\n } else {\n tokens.splice(i, 1);\n }\n }\n }\n });\n\n return tokens.length === 1 ? tokens[0] : tokens;\n}\n\n/**\n * Replace commas with | only outside of parentheses.\n * This preserves commas in advanced states like @(card, w < 600px)\n */\nfunction replaceCommasOutsideParens(str: string): string {\n let result = '';\n let depth = 0;\n\n for (const char of str) {\n\n if (char === '(') {\n depth++;\n result += char;\n } else if (char === ')') {\n depth--;\n result += char;\n } else if (char === ',' && depth === 0) {\n // Only replace commas at the top level (outside parentheses)\n result += '|';\n } else {\n result += char;\n }\n }\n\n return result;\n}\n\n/**\n * Parse state notation and return tokens, modifiers and compute model.\n */\nfunction parseStateNotationInner(\n notation: string,\n value: StyleValue | StyleValueStateMap | StyleStateData,\n): StyleStateData {\n const tokens = replaceCommasOutsideParens(notation).match(STATES_REGEXP);\n\n if (!tokens || !tokens.length) {\n return {\n model: undefined,\n mods: [],\n notMods: [],\n tokens: [],\n value,\n };\n } else if (tokens.length === 1) {\n return {\n model: tokens[0],\n mods: tokens.slice(0),\n notMods: [],\n tokens,\n value,\n };\n }\n\n const mods: string[] = [];\n\n const operations: unknown[][] = [[]];\n let list = operations[0];\n let position = 0;\n let operation: unknown[];\n\n tokens.forEach((token) => {\n switch (token) {\n case '(':\n operation = [];\n position++;\n list = operations[position] = operation;\n break;\n case ')':\n position--;\n operations[position].push(\n convertTokensToComputeUnits(list as unknown[]),\n );\n list = operations[position];\n break;\n default:\n if (token.length > 1) {\n if (!mods.includes(token)) {\n mods.push(token);\n }\n }\n list.push(token);\n }\n });\n\n while (position) {\n position--;\n operations[position].push(\n convertTokensToComputeUnits(list as unknown[]),\n );\n list = operations[position];\n }\n\n return {\n tokens,\n mods,\n notMods: [],\n model: convertTokensToComputeUnits(\n operations[0] as unknown[],\n ) as ComputeModel | undefined,\n value,\n };\n}\n\nexport const parseStateNotation = cacheWrapper(parseStateNotationInner);\n\n/**\n * Build an AtRuleContext from parsed advanced states\n */\nexport function buildAtRuleContext(\n advancedStates: ParsedAdvancedState[],\n negatedStates: Set<string>,\n): AtRuleContext | undefined {\n if (advancedStates.length === 0) return undefined;\n\n const ctx: AtRuleContext = {};\n\n for (const state of advancedStates) {\n const isNegated = negatedStates.has(state.raw);\n\n switch (state.type) {\n case 'media': {\n if (!ctx.media) ctx.media = [];\n let mediaCondition = '';\n\n if (state.mediaType) {\n // @media:print, @media:screen, etc.\n mediaCondition = state.mediaType;\n } else if (state.condition) {\n // @media(width < 920px)\n mediaCondition = `(${state.condition})`;\n }\n\n if (mediaCondition) {\n if (isNegated) {\n ctx.media.push(`not ${mediaCondition}`);\n } else {\n ctx.media.push(mediaCondition);\n }\n }\n break;\n }\n\n case 'container': {\n if (!ctx.container) ctx.container = [];\n let condition = state.condition;\n if (isNegated) {\n condition = `not (${condition})`;\n }\n ctx.container.push({\n name: state.containerName,\n condition,\n });\n break;\n }\n\n case 'root': {\n if (!ctx.rootStates) ctx.rootStates = [];\n // Parse the condition to generate the proper selector\n const rootSelector = buildRootSelector(state.condition, isNegated);\n ctx.rootStates.push(rootSelector);\n break;\n }\n\n case 'starting': {\n if (!isNegated) {\n ctx.startingStyle = true;\n }\n break;\n }\n\n // 'own' and 'predefined' are handled differently (selector-based, not at-rule)\n // 'modifier' is a regular state\n }\n }\n\n // Return undefined if no at-rules were added\n if (\n !ctx.media?.length &&\n !ctx.container?.length &&\n !ctx.rootStates?.length &&\n !ctx.startingStyle\n ) {\n return undefined;\n }\n\n return ctx;\n}\n\n/**\n * Build a root state selector from a condition\n */\nfunction buildRootSelector(condition: string, isNegated: boolean): string {\n // Handle different condition formats:\n // - theme=dark -> [data-theme=\"dark\"]\n // - .className -> .className\n // - [attr] -> [attr]\n // - booleanMod -> [data-boolean-mod]\n\n let selector: string;\n\n if (condition.startsWith('.')) {\n // Class selector\n selector = condition;\n } else if (condition.startsWith('[')) {\n // Attribute selector\n selector = condition;\n } else if (condition.includes('=')) {\n // Value mod: theme=dark -> [data-theme=\"dark\"]\n const [key, value] = condition.split('=');\n selector = `[data-${camelToKebab(key.trim())}=\"${value.trim()}\"]`;\n } else {\n // Boolean mod: camelCase -> [data-camel-case]\n selector = `[data-${camelToKebab(condition)}]`;\n }\n\n if (isNegated) {\n return `:not(${selector})`;\n }\n return selector;\n}\n\n/**\n * Parse state notation and return tokens, modifiers and compute model.\n * Enhanced to detect and extract advanced states.\n */\nexport function styleStateMapToStyleStateDataList(\n styleStateMap: StyleStateMap | StyleValue | StyleValueStateMap,\n parserContext?: StateParserContext,\n): { states: StyleStateDataList; mods: string[]; hasAdvancedStates: boolean } {\n if (typeof styleStateMap !== 'object' || !styleStateMap) {\n return {\n states: [\n {\n model: undefined,\n mods: [],\n notMods: [],\n value: styleStateMap,\n },\n ],\n mods: [],\n hasAdvancedStates: false,\n };\n }\n\n const stateDataList: StyleStateDataList = [];\n let hasAdvancedStates = false;\n\n Object.keys(styleStateMap).forEach((stateNotation) => {\n const state = parseStateNotation(\n stateNotation,\n styleStateMap[stateNotation],\n );\n\n // Check if this state contains any advanced states\n const advancedStates: ParsedAdvancedState[] = [];\n const negatedAdvancedStates = new Set<string>();\n const regularMods: string[] = [];\n const ownMods: string[] = [];\n const negatedOwnMods: string[] = [];\n\n // Scan tokens for advanced states\n if (state.tokens) {\n let isNegated = false;\n for (const token of state.tokens) {\n if (token === '!') {\n isNegated = true;\n continue;\n }\n\n if (isAdvancedStateToken(token)) {\n hasAdvancedStates = true;\n const ctx = parserContext || createStateParserContext(undefined);\n const parsed = parseAdvancedState(token, ctx);\n advancedStates.push(parsed);\n\n // Handle @own states specially - extract condition as ownMod\n if (parsed.type === 'own' && parsed.condition) {\n if (isNegated) {\n negatedOwnMods.push(parsed.condition);\n } else {\n ownMods.push(parsed.condition);\n }\n } else if (isNegated) {\n negatedAdvancedStates.add(token);\n }\n isNegated = false;\n } else if (\n token.length > 1 &&\n !['&', '|', '^', '(', ')'].includes(token)\n ) {\n regularMods.push(token);\n isNegated = false;\n } else {\n isNegated = false;\n }\n }\n }\n\n // If there are advanced states, build the atRuleContext\n if (advancedStates.length > 0) {\n state.advancedStates = advancedStates;\n state.atRuleContext = buildAtRuleContext(\n advancedStates,\n negatedAdvancedStates,\n );\n // Filter mods to only include regular mods (not advanced states)\n state.mods = regularMods;\n }\n\n // Store own mods for sub-element selector generation\n if (ownMods.length > 0) {\n state.ownMods = ownMods;\n }\n if (negatedOwnMods.length > 0) {\n state.negatedOwnMods = negatedOwnMods;\n }\n\n stateDataList.push(state);\n });\n\n stateDataList.reverse();\n\n let initialState;\n\n const allMods: string[] = stateDataList.reduce((all: string[], state) => {\n if (!state.mods.length && !state.advancedStates?.length) {\n initialState = state;\n } else {\n state.mods.forEach((mod) => {\n if (!all.includes(mod)) {\n all.push(mod);\n }\n });\n }\n\n return all;\n }, []);\n\n if (!initialState) {\n stateDataList.push({\n mods: [],\n notMods: allMods,\n value: true,\n });\n }\n\n return { states: stateDataList, mods: allMods, hasAdvancedStates };\n}\n\nexport const COMPUTE_FUNC_MAP = {\n '!': (a) => !a, // NOT - boolean negation\n '^': (a, b) => (a && !b) || (!a && b), // XOR - true when exactly one is true\n '|': (a, b) => a || b, // OR - logical OR\n '&': (a, b) => a && b, // AND - logical AND\n};\n\n/**\n * Compute a result based on a model and incoming map.\n */\nexport function computeState(\n computeModel: ComputeModel,\n valueMap: (number | boolean)[] | Record<string, boolean> | ((...args: unknown[]) => unknown),\n) {\n if (!computeModel) return true;\n\n if (!Array.isArray(computeModel)) {\n if (typeof valueMap === 'function') {\n return !!valueMap(computeModel);\n } else {\n return !!valueMap[computeModel];\n }\n }\n\n const func = COMPUTE_FUNC_MAP[computeModel[0]];\n\n if (!func) {\n console.warn(\n 'CubeUIKit: unexpected compute method in the model',\n computeModel,\n );\n // return false;\n }\n\n let a = computeModel[1];\n\n if (typeof a === 'object') {\n a = !!computeState(a, valueMap);\n } else if (typeof valueMap === 'function') {\n a = !!valueMap(a);\n } else {\n a = !!valueMap[a];\n }\n\n if (computeModel.length === 2) {\n return func(a);\n }\n\n let b = computeModel[2];\n\n if (typeof b === 'object') {\n b = !!computeState(b, valueMap);\n } else if (typeof valueMap === 'function') {\n b = !!valueMap(b);\n } else {\n b = !!valueMap[b];\n }\n\n return !!func(a, b);\n}\n\nconst _innerCache = new WeakMap();\n\nexport function stringifyStyles(styles: unknown): string {\n if (styles == null || typeof styles !== 'object') return '';\n const keys = Object.keys(styles).sort();\n const parts: string[] = [];\n for (const k of keys) {\n const v = styles[k];\n if (v === undefined || typeof v === 'function' || typeof v === 'symbol')\n continue;\n\n const c0 = k.charCodeAt(0);\n const needsInnerSort =\n ((c0 >= 65 && c0 <= 90) || c0 === 38) &&\n v &&\n typeof v === 'object' &&\n !Array.isArray(v);\n\n let sv: string;\n if (needsInnerSort) {\n sv = _innerCache.get(v);\n if (sv === undefined) {\n const innerKeys = Object.keys(v).sort();\n const innerParts: string[] = [];\n for (const ik of innerKeys) {\n const ivs = JSON.stringify(v[ik]);\n if (ivs !== undefined)\n innerParts.push(JSON.stringify(ik) + ':' + ivs);\n }\n sv = '{' + innerParts.join(',') + '}';\n _innerCache.set(v, sv);\n }\n } else {\n sv = JSON.stringify(v);\n }\n parts.push(JSON.stringify(k) + ':' + sv);\n }\n return '{' + parts.join(',') + '}';\n}\n"],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { Styles } from "../styles/types.js";
2
+ import { TypographyPreset } from "../tokens/typography.js";
3
+
4
+ //#region src/utils/typography.d.ts
5
+ /**
6
+ * Generate typography tokens with $ prefix for CSS custom properties.
7
+ *
8
+ * Each preset generates the following CSS custom properties:
9
+ * - `${name}-font-size`
10
+ * - `${name}-line-height`
11
+ * - `${name}-letter-spacing`
12
+ * - `${name}-font-weight`
13
+ * - `${name}-bold-font-weight` (if defined)
14
+ * - `${name}-icon-size` (if defined)
15
+ * - `${name}-text-transform` (if defined)
16
+ * - `${name}-font-family` (if defined)
17
+ * - `${name}-font-style` (if defined)
18
+ *
19
+ * @param presets - Typography presets object (defaults to TYPOGRAPHY_PRESETS)
20
+ * @returns Styles object with $ prefixed keys
21
+ *
22
+ * @example
23
+ * // Using default presets
24
+ * const tokens = generateTypographyTokens();
25
+ * // tokens['$h1-font-size'] === '36px'
26
+ *
27
+ * @example
28
+ * // Using custom presets
29
+ * const customTokens = generateTypographyTokens({
30
+ * myHeading: { fontSize: '24px', lineHeight: '32px', fontWeight: '700' }
31
+ * });
32
+ */
33
+ declare function generateTypographyTokens(presets?: Record<string, TypographyPreset>): Styles;
34
+ //#endregion
35
+ export { generateTypographyTokens };
36
+ //# sourceMappingURL=typography.d.ts.map
@@ -0,0 +1,53 @@
1
+ import { TYPOGRAPHY_PRESETS } from "../tokens/typography.js";
2
+
3
+ //#region src/utils/typography.ts
4
+ /**
5
+ * Generate typography tokens with $ prefix for CSS custom properties.
6
+ *
7
+ * Each preset generates the following CSS custom properties:
8
+ * - `${name}-font-size`
9
+ * - `${name}-line-height`
10
+ * - `${name}-letter-spacing`
11
+ * - `${name}-font-weight`
12
+ * - `${name}-bold-font-weight` (if defined)
13
+ * - `${name}-icon-size` (if defined)
14
+ * - `${name}-text-transform` (if defined)
15
+ * - `${name}-font-family` (if defined)
16
+ * - `${name}-font-style` (if defined)
17
+ *
18
+ * @param presets - Typography presets object (defaults to TYPOGRAPHY_PRESETS)
19
+ * @returns Styles object with $ prefixed keys
20
+ *
21
+ * @example
22
+ * // Using default presets
23
+ * const tokens = generateTypographyTokens();
24
+ * // tokens['$h1-font-size'] === '36px'
25
+ *
26
+ * @example
27
+ * // Using custom presets
28
+ * const customTokens = generateTypographyTokens({
29
+ * myHeading: { fontSize: '24px', lineHeight: '32px', fontWeight: '700' }
30
+ * });
31
+ */
32
+ function generateTypographyTokens(presets = TYPOGRAPHY_PRESETS) {
33
+ const tokens = {};
34
+ for (const [name, preset] of Object.entries(presets)) {
35
+ tokens[`$${name}-font-size`] = preset.fontSize;
36
+ tokens[`$${name}-line-height`] = preset.lineHeight;
37
+ tokens[`$${name}-letter-spacing`] = preset.letterSpacing ?? "0";
38
+ tokens[`$${name}-font-weight`] = preset.fontWeight;
39
+ if (preset.boldFontWeight !== void 0) {
40
+ const boldKey = name === "c1" ? `$${name}-font-bold-weight` : `$${name}-bold-font-weight`;
41
+ tokens[boldKey] = preset.boldFontWeight;
42
+ }
43
+ if (preset.iconSize !== void 0) tokens[`$${name}-icon-size`] = preset.iconSize;
44
+ if (preset.textTransform !== void 0) tokens[`$${name}-text-transform`] = preset.textTransform;
45
+ if (preset.fontFamily !== void 0) tokens[`$${name}-font-family`] = preset.fontFamily;
46
+ if (preset.fontStyle !== void 0) tokens[`$${name}-font-style`] = preset.fontStyle;
47
+ }
48
+ return tokens;
49
+ }
50
+
51
+ //#endregion
52
+ export { generateTypographyTokens };
53
+ //# sourceMappingURL=typography.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typography.js","names":[],"sources":["../../src/utils/typography.ts"],"sourcesContent":["import type { TypographyPreset } from '../tokens/typography';\nimport { TYPOGRAPHY_PRESETS } from '../tokens/typography';\n\nimport type { Styles } from '../styles/types';\n\n// Re-export types for convenience\nexport type { TypographyPreset };\n\n/**\n * Generate typography tokens with $ prefix for CSS custom properties.\n *\n * Each preset generates the following CSS custom properties:\n * - `${name}-font-size`\n * - `${name}-line-height`\n * - `${name}-letter-spacing`\n * - `${name}-font-weight`\n * - `${name}-bold-font-weight` (if defined)\n * - `${name}-icon-size` (if defined)\n * - `${name}-text-transform` (if defined)\n * - `${name}-font-family` (if defined)\n * - `${name}-font-style` (if defined)\n *\n * @param presets - Typography presets object (defaults to TYPOGRAPHY_PRESETS)\n * @returns Styles object with $ prefixed keys\n *\n * @example\n * // Using default presets\n * const tokens = generateTypographyTokens();\n * // tokens['$h1-font-size'] === '36px'\n *\n * @example\n * // Using custom presets\n * const customTokens = generateTypographyTokens({\n * myHeading: { fontSize: '24px', lineHeight: '32px', fontWeight: '700' }\n * });\n */\nexport function generateTypographyTokens(\n presets: Record<string, TypographyPreset> = TYPOGRAPHY_PRESETS,\n): Styles {\n const tokens: Record<string, string | number> = {};\n\n for (const [name, preset] of Object.entries(presets)) {\n tokens[`$${name}-font-size`] = preset.fontSize;\n tokens[`$${name}-line-height`] = preset.lineHeight;\n tokens[`$${name}-letter-spacing`] = preset.letterSpacing ?? '0';\n tokens[`$${name}-font-weight`] = preset.fontWeight;\n\n if (preset.boldFontWeight !== undefined) {\n // Handle different property naming for c1 (uses font-bold-weight instead of bold-font-weight)\n const boldKey =\n name === 'c1'\n ? `$${name}-font-bold-weight`\n : `$${name}-bold-font-weight`;\n tokens[boldKey] = preset.boldFontWeight;\n }\n\n if (preset.iconSize !== undefined) {\n tokens[`$${name}-icon-size`] = preset.iconSize;\n }\n\n if (preset.textTransform !== undefined) {\n tokens[`$${name}-text-transform`] = preset.textTransform;\n }\n\n if (preset.fontFamily !== undefined) {\n tokens[`$${name}-font-family`] = preset.fontFamily;\n }\n\n if (preset.fontStyle !== undefined) {\n tokens[`$${name}-font-style`] = preset.fontStyle;\n }\n }\n\n return tokens as Styles;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,yBACd,UAA4C,oBACpC;CACR,MAAM,SAA0C,EAAE;AAElD,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,QAAQ,EAAE;AACpD,SAAO,IAAI,KAAK,eAAe,OAAO;AACtC,SAAO,IAAI,KAAK,iBAAiB,OAAO;AACxC,SAAO,IAAI,KAAK,oBAAoB,OAAO,iBAAiB;AAC5D,SAAO,IAAI,KAAK,iBAAiB,OAAO;AAExC,MAAI,OAAO,mBAAmB,QAAW;GAEvC,MAAM,UACJ,SAAS,OACL,IAAI,KAAK,qBACT,IAAI,KAAK;AACf,UAAO,WAAW,OAAO;;AAG3B,MAAI,OAAO,aAAa,OACtB,QAAO,IAAI,KAAK,eAAe,OAAO;AAGxC,MAAI,OAAO,kBAAkB,OAC3B,QAAO,IAAI,KAAK,oBAAoB,OAAO;AAG7C,MAAI,OAAO,eAAe,OACxB,QAAO,IAAI,KAAK,iBAAiB,OAAO;AAG1C,MAAI,OAAO,cAAc,OACvB,QAAO,IAAI,KAAK,gBAAgB,OAAO;;AAI3C,QAAO"}
@@ -0,0 +1,16 @@
1
+ //#region src/utils/warnings.d.ts
2
+ declare function warn(...args: unknown[]): void;
3
+ declare function deprecationWarning(condition: unknown, {
4
+ property,
5
+ name,
6
+ betterAlternative,
7
+ reason
8
+ }: {
9
+ property: string;
10
+ name: string;
11
+ betterAlternative: (() => string) | string;
12
+ reason?: (() => string) | string;
13
+ }): void;
14
+ //#endregion
15
+ export { deprecationWarning, warn };
16
+ //# sourceMappingURL=warnings.d.ts.map
@@ -0,0 +1,16 @@
1
+ //#region src/utils/warnings.ts
2
+ const PREFIX = "Tasty";
3
+ function warn(...args) {
4
+ console.warn(`${PREFIX}:`, ...args);
5
+ }
6
+ function deprecationWarning(condition, { property, name, betterAlternative, reason }) {
7
+ if (condition) return;
8
+ console.group(`⚠️ ${PREFIX}: Deprecation in ${name}`);
9
+ warn(`"${property}" is deprecated, consider better alternative: ${typeof betterAlternative === "function" ? betterAlternative() : betterAlternative}`);
10
+ if (reason) warn(`Reason: ${typeof reason === "function" ? reason() : reason}`);
11
+ console.groupEnd();
12
+ }
13
+
14
+ //#endregion
15
+ export { deprecationWarning, warn };
16
+ //# sourceMappingURL=warnings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warnings.js","names":[],"sources":["../../src/utils/warnings.ts"],"sourcesContent":["/* eslint-disable no-console */\nconst PREFIX = 'Tasty';\n\nexport function warn(...args: unknown[]) {\n console.warn(`${PREFIX}:`, ...args);\n}\n\nexport function deprecationWarning(\n condition: unknown,\n {\n property,\n name,\n betterAlternative,\n reason,\n }: {\n property: string;\n name: string;\n betterAlternative: (() => string) | string;\n reason?: (() => string) | string;\n },\n) {\n if (condition) return;\n\n if (process.env.NODE_ENV === 'production') {\n return warn(\n `DEPRECATION ${name} \"${property}\" -> ${\n typeof betterAlternative === 'function'\n ? betterAlternative()\n : betterAlternative\n }`,\n );\n }\n\n // we can make deprecations even better if we add the md syntax in the console.\n // anyway, everything down below will be stripped in the production build\n console.group(`⚠️ ${PREFIX}: Deprecation in ${name}`);\n warn(\n `\"${property}\" is deprecated, consider better alternative: ${\n typeof betterAlternative === 'function'\n ? betterAlternative()\n : betterAlternative\n }`,\n );\n if (reason) {\n warn(`Reason: ${typeof reason === 'function' ? reason() : reason}`);\n }\n console.groupEnd();\n}\n"],"mappings":";AACA,MAAM,SAAS;AAEf,SAAgB,KAAK,GAAG,MAAiB;AACvC,SAAQ,KAAK,GAAG,OAAO,IAAI,GAAG,KAAK;;AAGrC,SAAgB,mBACd,WACA,EACE,UACA,MACA,mBACA,UAOF;AACA,KAAI,UAAW;AAcf,SAAQ,MAAM,MAAM,OAAO,mBAAmB,OAAO;AACrD,MACE,IAAI,SAAS,gDACX,OAAO,sBAAsB,aACzB,mBAAmB,GACnB,oBAEP;AACD,KAAI,OACF,MAAK,WAAW,OAAO,WAAW,aAAa,QAAQ,GAAG,SAAS;AAErE,SAAQ,UAAU"}