@tenphi/tasty 0.0.0-snapshot.08a6610

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 (288) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +666 -0
  3. package/dist/_virtual/_rolldown/runtime.js +8 -0
  4. package/dist/chunks/cacheKey.js +70 -0
  5. package/dist/chunks/cacheKey.js.map +1 -0
  6. package/dist/chunks/definitions.d.ts +37 -0
  7. package/dist/chunks/definitions.js +259 -0
  8. package/dist/chunks/definitions.js.map +1 -0
  9. package/dist/chunks/renderChunk.js +61 -0
  10. package/dist/chunks/renderChunk.js.map +1 -0
  11. package/dist/config.d.ts +311 -0
  12. package/dist/config.js +458 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/core/index.d.ts +32 -0
  15. package/dist/core/index.js +26 -0
  16. package/dist/debug.d.ts +204 -0
  17. package/dist/debug.js +733 -0
  18. package/dist/debug.js.map +1 -0
  19. package/dist/hooks/useGlobalStyles.d.ts +30 -0
  20. package/dist/hooks/useGlobalStyles.js +83 -0
  21. package/dist/hooks/useGlobalStyles.js.map +1 -0
  22. package/dist/hooks/useKeyframes.d.ts +56 -0
  23. package/dist/hooks/useKeyframes.js +69 -0
  24. package/dist/hooks/useKeyframes.js.map +1 -0
  25. package/dist/hooks/useProperty.d.ts +79 -0
  26. package/dist/hooks/useProperty.js +114 -0
  27. package/dist/hooks/useProperty.js.map +1 -0
  28. package/dist/hooks/useRawCSS.d.ts +53 -0
  29. package/dist/hooks/useRawCSS.js +40 -0
  30. package/dist/hooks/useRawCSS.js.map +1 -0
  31. package/dist/hooks/useStyles.d.ts +45 -0
  32. package/dist/hooks/useStyles.js +248 -0
  33. package/dist/hooks/useStyles.js.map +1 -0
  34. package/dist/index.d.ts +47 -0
  35. package/dist/index.js +33 -0
  36. package/dist/injector/index.d.ts +165 -0
  37. package/dist/injector/index.js +162 -0
  38. package/dist/injector/index.js.map +1 -0
  39. package/dist/injector/injector.d.ts +148 -0
  40. package/dist/injector/injector.js +430 -0
  41. package/dist/injector/injector.js.map +1 -0
  42. package/dist/injector/sheet-manager.d.ts +136 -0
  43. package/dist/injector/sheet-manager.js +729 -0
  44. package/dist/injector/sheet-manager.js.map +1 -0
  45. package/dist/injector/types.d.ts +144 -0
  46. package/dist/keyframes/index.js +206 -0
  47. package/dist/keyframes/index.js.map +1 -0
  48. package/dist/parser/classify.js +319 -0
  49. package/dist/parser/classify.js.map +1 -0
  50. package/dist/parser/const.js +33 -0
  51. package/dist/parser/const.js.map +1 -0
  52. package/dist/parser/lru.js +109 -0
  53. package/dist/parser/lru.js.map +1 -0
  54. package/dist/parser/parser.d.ts +25 -0
  55. package/dist/parser/parser.js +116 -0
  56. package/dist/parser/parser.js.map +1 -0
  57. package/dist/parser/tokenizer.js +69 -0
  58. package/dist/parser/tokenizer.js.map +1 -0
  59. package/dist/parser/types.d.ts +51 -0
  60. package/dist/parser/types.js +46 -0
  61. package/dist/parser/types.js.map +1 -0
  62. package/dist/pipeline/conditions.d.ts +134 -0
  63. package/dist/pipeline/conditions.js +406 -0
  64. package/dist/pipeline/conditions.js.map +1 -0
  65. package/dist/pipeline/exclusive.js +231 -0
  66. package/dist/pipeline/exclusive.js.map +1 -0
  67. package/dist/pipeline/index.d.ts +53 -0
  68. package/dist/pipeline/index.js +660 -0
  69. package/dist/pipeline/index.js.map +1 -0
  70. package/dist/pipeline/materialize.js +856 -0
  71. package/dist/pipeline/materialize.js.map +1 -0
  72. package/dist/pipeline/parseStateKey.d.ts +15 -0
  73. package/dist/pipeline/parseStateKey.js +451 -0
  74. package/dist/pipeline/parseStateKey.js.map +1 -0
  75. package/dist/pipeline/simplify.js +516 -0
  76. package/dist/pipeline/simplify.js.map +1 -0
  77. package/dist/pipeline/warnings.js +18 -0
  78. package/dist/pipeline/warnings.js.map +1 -0
  79. package/dist/plugins/okhsl-plugin.d.ts +35 -0
  80. package/dist/plugins/okhsl-plugin.js +371 -0
  81. package/dist/plugins/okhsl-plugin.js.map +1 -0
  82. package/dist/plugins/types.d.ts +76 -0
  83. package/dist/properties/index.js +236 -0
  84. package/dist/properties/index.js.map +1 -0
  85. package/dist/properties/property-type-resolver.d.ts +24 -0
  86. package/dist/properties/property-type-resolver.js +91 -0
  87. package/dist/properties/property-type-resolver.js.map +1 -0
  88. package/dist/ssr/astro.d.ts +29 -0
  89. package/dist/ssr/astro.js +65 -0
  90. package/dist/ssr/astro.js.map +1 -0
  91. package/dist/ssr/async-storage.d.ts +17 -0
  92. package/dist/ssr/async-storage.js +35 -0
  93. package/dist/ssr/async-storage.js.map +1 -0
  94. package/dist/ssr/collect-auto-properties.js +40 -0
  95. package/dist/ssr/collect-auto-properties.js.map +1 -0
  96. package/dist/ssr/collector.d.ts +85 -0
  97. package/dist/ssr/collector.js +183 -0
  98. package/dist/ssr/collector.js.map +1 -0
  99. package/dist/ssr/context.d.ts +8 -0
  100. package/dist/ssr/context.js +14 -0
  101. package/dist/ssr/context.js.map +1 -0
  102. package/dist/ssr/format-global-rules.js +22 -0
  103. package/dist/ssr/format-global-rules.js.map +1 -0
  104. package/dist/ssr/format-keyframes.js +70 -0
  105. package/dist/ssr/format-keyframes.js.map +1 -0
  106. package/dist/ssr/format-property.js +48 -0
  107. package/dist/ssr/format-property.js.map +1 -0
  108. package/dist/ssr/format-rules.js +70 -0
  109. package/dist/ssr/format-rules.js.map +1 -0
  110. package/dist/ssr/hydrate.d.ts +22 -0
  111. package/dist/ssr/hydrate.js +50 -0
  112. package/dist/ssr/hydrate.js.map +1 -0
  113. package/dist/ssr/index.d.ts +5 -0
  114. package/dist/ssr/index.js +12 -0
  115. package/dist/ssr/index.js.map +1 -0
  116. package/dist/ssr/next.d.ts +45 -0
  117. package/dist/ssr/next.js +71 -0
  118. package/dist/ssr/next.js.map +1 -0
  119. package/dist/ssr/ssr-collector-ref.js +12 -0
  120. package/dist/ssr/ssr-collector-ref.js.map +1 -0
  121. package/dist/states/index.d.ts +49 -0
  122. package/dist/states/index.js +416 -0
  123. package/dist/states/index.js.map +1 -0
  124. package/dist/static/index.d.ts +5 -0
  125. package/dist/static/index.js +5 -0
  126. package/dist/static/tastyStatic.d.ts +46 -0
  127. package/dist/static/tastyStatic.js +31 -0
  128. package/dist/static/tastyStatic.js.map +1 -0
  129. package/dist/static/types.d.ts +49 -0
  130. package/dist/static/types.js +24 -0
  131. package/dist/static/types.js.map +1 -0
  132. package/dist/styles/align.d.ts +15 -0
  133. package/dist/styles/align.js +14 -0
  134. package/dist/styles/align.js.map +1 -0
  135. package/dist/styles/border.d.ts +25 -0
  136. package/dist/styles/border.js +114 -0
  137. package/dist/styles/border.js.map +1 -0
  138. package/dist/styles/color.d.ts +14 -0
  139. package/dist/styles/color.js +23 -0
  140. package/dist/styles/color.js.map +1 -0
  141. package/dist/styles/createStyle.js +77 -0
  142. package/dist/styles/createStyle.js.map +1 -0
  143. package/dist/styles/dimension.js +97 -0
  144. package/dist/styles/dimension.js.map +1 -0
  145. package/dist/styles/display.d.ts +37 -0
  146. package/dist/styles/display.js +67 -0
  147. package/dist/styles/display.js.map +1 -0
  148. package/dist/styles/fade.d.ts +15 -0
  149. package/dist/styles/fade.js +58 -0
  150. package/dist/styles/fade.js.map +1 -0
  151. package/dist/styles/fill.d.ts +42 -0
  152. package/dist/styles/fill.js +52 -0
  153. package/dist/styles/fill.js.map +1 -0
  154. package/dist/styles/flow.d.ts +16 -0
  155. package/dist/styles/flow.js +12 -0
  156. package/dist/styles/flow.js.map +1 -0
  157. package/dist/styles/gap.d.ts +31 -0
  158. package/dist/styles/gap.js +37 -0
  159. package/dist/styles/gap.js.map +1 -0
  160. package/dist/styles/height.d.ts +17 -0
  161. package/dist/styles/height.js +20 -0
  162. package/dist/styles/height.js.map +1 -0
  163. package/dist/styles/index.d.ts +2 -0
  164. package/dist/styles/index.js +9 -0
  165. package/dist/styles/index.js.map +1 -0
  166. package/dist/styles/inset.d.ts +52 -0
  167. package/dist/styles/inset.js +150 -0
  168. package/dist/styles/inset.js.map +1 -0
  169. package/dist/styles/justify.d.ts +15 -0
  170. package/dist/styles/justify.js +14 -0
  171. package/dist/styles/justify.js.map +1 -0
  172. package/dist/styles/list.d.ts +16 -0
  173. package/dist/styles/list.js +98 -0
  174. package/dist/styles/list.js.map +1 -0
  175. package/dist/styles/margin.d.ts +24 -0
  176. package/dist/styles/margin.js +104 -0
  177. package/dist/styles/margin.js.map +1 -0
  178. package/dist/styles/outline.d.ts +29 -0
  179. package/dist/styles/outline.js +65 -0
  180. package/dist/styles/outline.js.map +1 -0
  181. package/dist/styles/padding.d.ts +24 -0
  182. package/dist/styles/padding.js +104 -0
  183. package/dist/styles/padding.js.map +1 -0
  184. package/dist/styles/predefined.d.ts +71 -0
  185. package/dist/styles/predefined.js +238 -0
  186. package/dist/styles/predefined.js.map +1 -0
  187. package/dist/styles/preset.d.ts +47 -0
  188. package/dist/styles/preset.js +126 -0
  189. package/dist/styles/preset.js.map +1 -0
  190. package/dist/styles/radius.d.ts +14 -0
  191. package/dist/styles/radius.js +51 -0
  192. package/dist/styles/radius.js.map +1 -0
  193. package/dist/styles/scrollbar.d.ts +25 -0
  194. package/dist/styles/scrollbar.js +48 -0
  195. package/dist/styles/scrollbar.js.map +1 -0
  196. package/dist/styles/shadow.d.ts +14 -0
  197. package/dist/styles/shadow.js +24 -0
  198. package/dist/styles/shadow.js.map +1 -0
  199. package/dist/styles/transition.d.ts +14 -0
  200. package/dist/styles/transition.js +158 -0
  201. package/dist/styles/transition.js.map +1 -0
  202. package/dist/styles/types.d.ts +508 -0
  203. package/dist/styles/width.d.ts +17 -0
  204. package/dist/styles/width.js +20 -0
  205. package/dist/styles/width.js.map +1 -0
  206. package/dist/tasty.d.ts +981 -0
  207. package/dist/tasty.js +206 -0
  208. package/dist/tasty.js.map +1 -0
  209. package/dist/types.d.ts +184 -0
  210. package/dist/utils/cache-wrapper.js +26 -0
  211. package/dist/utils/cache-wrapper.js.map +1 -0
  212. package/dist/utils/case-converter.js +8 -0
  213. package/dist/utils/case-converter.js.map +1 -0
  214. package/dist/utils/colors.d.ts +5 -0
  215. package/dist/utils/colors.js +9 -0
  216. package/dist/utils/colors.js.map +1 -0
  217. package/dist/utils/css-types.d.ts +7 -0
  218. package/dist/utils/dotize.d.ts +26 -0
  219. package/dist/utils/dotize.js +122 -0
  220. package/dist/utils/dotize.js.map +1 -0
  221. package/dist/utils/filter-base-props.d.ts +15 -0
  222. package/dist/utils/filter-base-props.js +45 -0
  223. package/dist/utils/filter-base-props.js.map +1 -0
  224. package/dist/utils/get-display-name.d.ts +7 -0
  225. package/dist/utils/get-display-name.js +10 -0
  226. package/dist/utils/get-display-name.js.map +1 -0
  227. package/dist/utils/hsl-to-rgb.js +38 -0
  228. package/dist/utils/hsl-to-rgb.js.map +1 -0
  229. package/dist/utils/is-dev-env.js +19 -0
  230. package/dist/utils/is-dev-env.js.map +1 -0
  231. package/dist/utils/is-valid-element-type.js +15 -0
  232. package/dist/utils/is-valid-element-type.js.map +1 -0
  233. package/dist/utils/merge-styles.d.ts +7 -0
  234. package/dist/utils/merge-styles.js +146 -0
  235. package/dist/utils/merge-styles.js.map +1 -0
  236. package/dist/utils/mod-attrs.d.ts +8 -0
  237. package/dist/utils/mod-attrs.js +21 -0
  238. package/dist/utils/mod-attrs.js.map +1 -0
  239. package/dist/utils/okhsl-to-rgb.js +296 -0
  240. package/dist/utils/okhsl-to-rgb.js.map +1 -0
  241. package/dist/utils/process-tokens.d.ts +31 -0
  242. package/dist/utils/process-tokens.js +171 -0
  243. package/dist/utils/process-tokens.js.map +1 -0
  244. package/dist/utils/resolve-recipes.d.ts +17 -0
  245. package/dist/utils/resolve-recipes.js +147 -0
  246. package/dist/utils/resolve-recipes.js.map +1 -0
  247. package/dist/utils/selector-transform.js +32 -0
  248. package/dist/utils/selector-transform.js.map +1 -0
  249. package/dist/utils/string.js +8 -0
  250. package/dist/utils/string.js.map +1 -0
  251. package/dist/utils/styles.d.ts +177 -0
  252. package/dist/utils/styles.js +730 -0
  253. package/dist/utils/styles.js.map +1 -0
  254. package/dist/utils/typography.d.ts +47 -0
  255. package/dist/utils/typography.js +43 -0
  256. package/dist/utils/typography.js.map +1 -0
  257. package/dist/utils/warnings.d.ts +16 -0
  258. package/dist/utils/warnings.js +16 -0
  259. package/dist/utils/warnings.js.map +1 -0
  260. package/dist/zero/babel.d.ts +147 -0
  261. package/dist/zero/babel.js +331 -0
  262. package/dist/zero/babel.js.map +1 -0
  263. package/dist/zero/css-writer.d.ts +45 -0
  264. package/dist/zero/css-writer.js +74 -0
  265. package/dist/zero/css-writer.js.map +1 -0
  266. package/dist/zero/extractor.d.ts +24 -0
  267. package/dist/zero/extractor.js +215 -0
  268. package/dist/zero/extractor.js.map +1 -0
  269. package/dist/zero/index.d.ts +3 -0
  270. package/dist/zero/index.js +4 -0
  271. package/dist/zero/next.d.ts +74 -0
  272. package/dist/zero/next.js +129 -0
  273. package/dist/zero/next.js.map +1 -0
  274. package/docs/adoption.md +286 -0
  275. package/docs/comparison.md +413 -0
  276. package/docs/configuration.md +242 -0
  277. package/docs/debug.md +505 -0
  278. package/docs/design-system.md +401 -0
  279. package/docs/dsl.md +540 -0
  280. package/docs/getting-started.md +201 -0
  281. package/docs/injector.md +528 -0
  282. package/docs/methodology.md +501 -0
  283. package/docs/runtime.md +291 -0
  284. package/docs/ssr.md +382 -0
  285. package/docs/styles.md +574 -0
  286. package/docs/tasty-static.md +421 -0
  287. package/package.json +209 -0
  288. package/tasty.config.ts +14 -0
@@ -0,0 +1,236 @@
1
+ import { RE_NUMBER, RE_RAW_UNIT } from "../parser/const.js";
2
+
3
+ //#region src/properties/index.ts
4
+ const PROPERTIES_KEY = "@properties";
5
+ /**
6
+ * Valid CSS custom property name pattern (after the -- prefix).
7
+ * Must start with a letter or underscore, followed by letters, digits, hyphens, or underscores.
8
+ */
9
+ const VALID_PROPERTY_NAME_PATTERN = /^[a-z_][a-z0-9-_]*$/i;
10
+ /**
11
+ * Validate a CSS custom property name (the part after --).
12
+ * Returns true if the name is valid for use as a CSS custom property.
13
+ */
14
+ function isValidPropertyName(name) {
15
+ return VALID_PROPERTY_NAME_PATTERN.test(name);
16
+ }
17
+ /**
18
+ * Check if styles object has local @properties definition.
19
+ * Fast path: single property lookup.
20
+ */
21
+ function hasLocalProperties(styles) {
22
+ return PROPERTIES_KEY in styles;
23
+ }
24
+ /**
25
+ * Extract local @properties from styles object.
26
+ * Returns null if no local properties (fast path).
27
+ */
28
+ function extractLocalProperties(styles) {
29
+ const properties = styles[PROPERTIES_KEY];
30
+ if (!properties || typeof properties !== "object") return null;
31
+ return properties;
32
+ }
33
+ /**
34
+ * Parse a property token name and return the CSS property name and whether it's a color.
35
+ * Supports tasty token syntax and validates the property name.
36
+ *
37
+ * Token formats:
38
+ * - `$name` → { cssName: '--name', isColor: false }
39
+ * - `#name` → { cssName: '--name-color', isColor: true }
40
+ * - `--name` → { cssName: '--name', isColor: false } (legacy, auto-detect color by suffix)
41
+ * - `name` → { cssName: '--name', isColor: false } (legacy)
42
+ *
43
+ * @param token - The property token to parse
44
+ * @returns Parsed result with cssName, isColor, isValid, and optional error
45
+ */
46
+ function parsePropertyToken(token) {
47
+ if (!token || typeof token !== "string") return {
48
+ cssName: "",
49
+ isColor: false,
50
+ isValid: false,
51
+ error: "Property token must be a non-empty string"
52
+ };
53
+ let name;
54
+ let isColor;
55
+ if (token.startsWith("$")) {
56
+ name = token.slice(1);
57
+ isColor = false;
58
+ } else if (token.startsWith("#")) {
59
+ name = token.slice(1);
60
+ isColor = true;
61
+ } else if (token.startsWith("--")) {
62
+ name = token.slice(2);
63
+ isColor = token.endsWith("-color");
64
+ } else {
65
+ name = token;
66
+ isColor = token.endsWith("-color");
67
+ }
68
+ if (!name) return {
69
+ cssName: "",
70
+ isColor,
71
+ isValid: false,
72
+ error: "Property name cannot be empty"
73
+ };
74
+ if (!isValidPropertyName(name)) return {
75
+ cssName: "",
76
+ isColor,
77
+ isValid: false,
78
+ error: `Invalid property name "${name}". Must start with a letter or underscore, followed by letters, digits, hyphens, or underscores.`
79
+ };
80
+ let cssName;
81
+ if (token.startsWith("#")) cssName = `--${name}-color`;
82
+ else cssName = `--${name}`;
83
+ return {
84
+ cssName,
85
+ isColor,
86
+ isValid: true
87
+ };
88
+ }
89
+ /**
90
+ * Normalize a property definition to a consistent string representation.
91
+ * Used for comparing definitions to detect type conflicts.
92
+ *
93
+ * Only `syntax` and `inherits` are compared — `initialValue` is intentionally
94
+ * excluded because different components may set different defaults for the
95
+ * same typed property (e.g. auto-inferred `0px` vs explicit `6px`).
96
+ *
97
+ * Keys are sorted alphabetically to ensure consistent comparison:
98
+ * { inherits: true, syntax: '<color>' } === { syntax: '<color>', inherits: true }
99
+ */
100
+ function normalizePropertyDefinition(def) {
101
+ const normalized = {};
102
+ if (def.inherits !== void 0) normalized.inherits = def.inherits;
103
+ if (def.syntax !== void 0) normalized.syntax = def.syntax;
104
+ return JSON.stringify(normalized);
105
+ }
106
+ /**
107
+ * Get the effective property definition for a token.
108
+ * For color tokens (#name), auto-sets syntax to '<color>' and defaults initialValue to 'transparent'.
109
+ *
110
+ * @param token - Property token ($name, #name, --name, or plain name)
111
+ * @param userDefinition - User-provided definition options
112
+ * @returns Effective definition with cssName, definition, isValid, and optional error
113
+ */
114
+ function getEffectiveDefinition(token, userDefinition) {
115
+ const parsed = parsePropertyToken(token);
116
+ if (!parsed.isValid) return {
117
+ cssName: "",
118
+ definition: userDefinition,
119
+ isColor: false,
120
+ isValid: false,
121
+ error: parsed.error
122
+ };
123
+ if (parsed.isColor) return {
124
+ cssName: parsed.cssName,
125
+ definition: {
126
+ syntax: "<color>",
127
+ inherits: userDefinition.inherits,
128
+ initialValue: userDefinition.initialValue ?? "transparent"
129
+ },
130
+ isColor: true,
131
+ isValid: true
132
+ };
133
+ return {
134
+ cssName: parsed.cssName,
135
+ definition: userDefinition,
136
+ isColor: false,
137
+ isValid: true
138
+ };
139
+ }
140
+ /**
141
+ * Convert a color initialValue to an RGB string for the companion `-rgb` property.
142
+ * Used by SSR to emit `@property --name-color-rgb { syntax: "<number>+"; ... }`.
143
+ */
144
+ function colorInitialValueToRgb(initialValue) {
145
+ if (initialValue == null) return "0 0 0";
146
+ const val = String(initialValue).trim().toLowerCase();
147
+ if (val === "transparent" || val === "rgba(0,0,0,0)" || val === "") return "0 0 0";
148
+ if (val === "white") return "255 255 255";
149
+ if (val === "black") return "0 0 0";
150
+ const rgbMatch = val.match(/^rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/);
151
+ if (rgbMatch) return `${rgbMatch[1]} ${rgbMatch[2]} ${rgbMatch[3]}`;
152
+ return "0 0 0";
153
+ }
154
+ const UNIT_TO_SYNTAX = {};
155
+ const LENGTH_UNITS = [
156
+ "px",
157
+ "em",
158
+ "rem",
159
+ "vw",
160
+ "vh",
161
+ "vmin",
162
+ "vmax",
163
+ "ch",
164
+ "ex",
165
+ "cap",
166
+ "ic",
167
+ "lh",
168
+ "rlh",
169
+ "svw",
170
+ "svh",
171
+ "lvw",
172
+ "lvh",
173
+ "dvw",
174
+ "dvh",
175
+ "cqw",
176
+ "cqh",
177
+ "cqi",
178
+ "cqb",
179
+ "cqmin",
180
+ "cqmax"
181
+ ];
182
+ const ANGLE_UNITS = [
183
+ "deg",
184
+ "rad",
185
+ "grad",
186
+ "turn"
187
+ ];
188
+ const TIME_UNITS = ["ms", "s"];
189
+ for (const u of LENGTH_UNITS) UNIT_TO_SYNTAX[u] = {
190
+ syntax: "<length-percentage>",
191
+ initialValue: "0px"
192
+ };
193
+ UNIT_TO_SYNTAX["%"] = {
194
+ syntax: "<length-percentage>",
195
+ initialValue: "0px"
196
+ };
197
+ for (const u of ANGLE_UNITS) UNIT_TO_SYNTAX[u] = {
198
+ syntax: "<angle>",
199
+ initialValue: "0deg"
200
+ };
201
+ for (const u of TIME_UNITS) UNIT_TO_SYNTAX[u] = {
202
+ syntax: "<time>",
203
+ initialValue: "0s"
204
+ };
205
+ /**
206
+ * Infer CSS @property syntax from a concrete value.
207
+ * Detects numeric types: \<number\>, \<length-percentage\>, \<angle\>, \<time\>.
208
+ * Length and percentage values both map to \<length-percentage\> for maximum flexibility.
209
+ * Color properties are handled separately via the #name token convention
210
+ * (--name-color gets \<color\> syntax automatically in getEffectiveDefinition).
211
+ *
212
+ * @param value - The CSS value to infer from (e.g. '10px', '1', '45deg')
213
+ * @returns Inferred syntax and initial value, or null if not inferable
214
+ */
215
+ function inferSyntaxFromValue(value) {
216
+ if (!value || typeof value !== "string") return null;
217
+ const trimmed = value.trim();
218
+ if (!trimmed) return null;
219
+ if (RE_NUMBER.test(trimmed)) {
220
+ if (parseFloat(trimmed) === 0) return null;
221
+ return {
222
+ syntax: "<number>",
223
+ initialValue: "0"
224
+ };
225
+ }
226
+ const unitMatch = trimmed.match(RE_RAW_UNIT);
227
+ if (unitMatch) {
228
+ const mapping = UNIT_TO_SYNTAX[unitMatch[2]];
229
+ if (mapping) return mapping;
230
+ }
231
+ return null;
232
+ }
233
+
234
+ //#endregion
235
+ export { colorInitialValueToRgb, extractLocalProperties, getEffectiveDefinition, hasLocalProperties, inferSyntaxFromValue, normalizePropertyDefinition, parsePropertyToken };
236
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/properties/index.ts"],"sourcesContent":["/**\n * Properties Utilities\n *\n * Utilities for extracting and processing CSS @property definitions in styles.\n * Unlike keyframes, properties are permanent once registered and don't need cleanup.\n *\n * Property names use tasty token syntax:\n * - `$name` for regular properties → `--name`\n * - `#name` for color properties → `--name-color` (auto-sets syntax: '<color>')\n */\n\nimport type { PropertyDefinition } from '../injector/types';\nimport { RE_NUMBER, RE_RAW_UNIT } from '../parser/const';\nimport type { Styles } from '../styles/types';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst PROPERTIES_KEY = '@properties';\n\n/**\n * Valid CSS custom property name pattern (after the -- prefix).\n * Must start with a letter or underscore, followed by letters, digits, hyphens, or underscores.\n */\nconst VALID_PROPERTY_NAME_PATTERN = /^[a-z_][a-z0-9-_]*$/i;\n\n// ============================================================================\n// Validation Functions\n// ============================================================================\n\n/**\n * Validate a CSS custom property name (the part after --).\n * Returns true if the name is valid for use as a CSS custom property.\n */\nexport function isValidPropertyName(name: string): boolean {\n return VALID_PROPERTY_NAME_PATTERN.test(name);\n}\n\n/**\n * Result of parsing a property token.\n */\nexport interface ParsedPropertyToken {\n /** The CSS custom property name (e.g., '--my-prop') */\n cssName: string;\n /** Whether this is a color property */\n isColor: boolean;\n /** Whether the token was valid */\n isValid: boolean;\n /** Error message if invalid */\n error?: string;\n}\n\n// ============================================================================\n// Extraction Functions\n// ============================================================================\n\n/**\n * Check if styles object has local @properties definition.\n * Fast path: single property lookup.\n */\nexport function hasLocalProperties(styles: Styles): boolean {\n return PROPERTIES_KEY in styles;\n}\n\n/**\n * Extract local @properties from styles object.\n * Returns null if no local properties (fast path).\n */\nexport function extractLocalProperties(\n styles: Styles,\n): Record<string, PropertyDefinition> | null {\n const properties = styles[PROPERTIES_KEY];\n if (!properties || typeof properties !== 'object') {\n return null;\n }\n return properties as Record<string, PropertyDefinition>;\n}\n\n// ============================================================================\n// Token Parsing Functions\n// ============================================================================\n\n/**\n * Parse a property token name and return the CSS property name and whether it's a color.\n * Supports tasty token syntax and validates the property name.\n *\n * Token formats:\n * - `$name` → { cssName: '--name', isColor: false }\n * - `#name` → { cssName: '--name-color', isColor: true }\n * - `--name` → { cssName: '--name', isColor: false } (legacy, auto-detect color by suffix)\n * - `name` → { cssName: '--name', isColor: false } (legacy)\n *\n * @param token - The property token to parse\n * @returns Parsed result with cssName, isColor, isValid, and optional error\n */\nexport function parsePropertyToken(token: string): ParsedPropertyToken {\n if (!token || typeof token !== 'string') {\n return {\n cssName: '',\n isColor: false,\n isValid: false,\n error: 'Property token must be a non-empty string',\n };\n }\n\n let name: string;\n let isColor: boolean;\n\n if (token.startsWith('$')) {\n // Regular property token: $name → --name\n name = token.slice(1);\n isColor = false;\n } else if (token.startsWith('#')) {\n // Color property token: #name → --name-color\n name = token.slice(1);\n isColor = true;\n } else if (token.startsWith('--')) {\n // Legacy format with -- prefix\n name = token.slice(2);\n isColor = token.endsWith('-color');\n } else {\n // Legacy format without prefix\n name = token;\n isColor = token.endsWith('-color');\n }\n\n // Validate the name\n if (!name) {\n return {\n cssName: '',\n isColor,\n isValid: false,\n error: 'Property name cannot be empty',\n };\n }\n\n if (!isValidPropertyName(name)) {\n return {\n cssName: '',\n isColor,\n isValid: false,\n error: `Invalid property name \"${name}\". Must start with a letter or underscore, followed by letters, digits, hyphens, or underscores.`,\n };\n }\n\n // Build the CSS custom property name\n // For #name tokens, we add -color suffix\n // For legacy formats (--name-color or name-color), the name already includes -color\n let cssName: string;\n if (token.startsWith('#')) {\n // Color token: #name → --name-color\n cssName = `--${name}-color`;\n } else {\n // All other formats: just add -- prefix\n cssName = `--${name}`;\n }\n\n return {\n cssName,\n isColor,\n isValid: true,\n };\n}\n\n// ============================================================================\n// Normalization Functions\n// ============================================================================\n\n/**\n * Normalize a property name to the CSS custom property format.\n *\n * @deprecated Use parsePropertyToken instead for proper token handling\n */\nexport function normalizePropertyName(name: string): string {\n const result = parsePropertyToken(name);\n return result.isValid ? result.cssName : `--${name}`;\n}\n\n/**\n * Normalize a property definition to a consistent string representation.\n * Used for comparing definitions to detect type conflicts.\n *\n * Only `syntax` and `inherits` are compared — `initialValue` is intentionally\n * excluded because different components may set different defaults for the\n * same typed property (e.g. auto-inferred `0px` vs explicit `6px`).\n *\n * Keys are sorted alphabetically to ensure consistent comparison:\n * { inherits: true, syntax: '<color>' } === { syntax: '<color>', inherits: true }\n */\nexport function normalizePropertyDefinition(def: PropertyDefinition): string {\n const normalized: Record<string, unknown> = {};\n\n if (def.inherits !== undefined) {\n normalized.inherits = def.inherits;\n }\n if (def.syntax !== undefined) {\n normalized.syntax = def.syntax;\n }\n\n return JSON.stringify(normalized);\n}\n\n/**\n * Result of getEffectiveDefinition.\n */\nexport interface EffectiveDefinitionResult {\n /** The CSS custom property name */\n cssName: string;\n /** The effective property definition */\n definition: PropertyDefinition;\n /** Whether this is a color property */\n isColor: boolean;\n /** Whether the token was valid */\n isValid: boolean;\n /** Error message if invalid */\n error?: string;\n}\n\n/**\n * Get the effective property definition for a token.\n * For color tokens (#name), auto-sets syntax to '<color>' and defaults initialValue to 'transparent'.\n *\n * @param token - Property token ($name, #name, --name, or plain name)\n * @param userDefinition - User-provided definition options\n * @returns Effective definition with cssName, definition, isValid, and optional error\n */\nexport function getEffectiveDefinition(\n token: string,\n userDefinition: PropertyDefinition,\n): EffectiveDefinitionResult {\n const parsed = parsePropertyToken(token);\n\n if (!parsed.isValid) {\n return {\n cssName: '',\n definition: userDefinition,\n isColor: false,\n isValid: false,\n error: parsed.error,\n };\n }\n\n if (parsed.isColor) {\n // Color properties have fixed syntax and default initialValue\n return {\n cssName: parsed.cssName,\n definition: {\n syntax: '<color>', // Always '<color>' for color tokens, cannot be overridden\n inherits: userDefinition.inherits, // Allow inherits to be customized\n initialValue: userDefinition.initialValue ?? 'transparent', // Default to transparent\n },\n isColor: true,\n isValid: true,\n };\n }\n\n // Regular properties use the definition as-is\n return {\n cssName: parsed.cssName,\n definition: userDefinition,\n isColor: false,\n isValid: true,\n };\n}\n\n// ============================================================================\n// Color Utilities\n// ============================================================================\n\n/**\n * Convert a color initialValue to an RGB string for the companion `-rgb` property.\n * Used by SSR to emit `@property --name-color-rgb { syntax: \"<number>+\"; ... }`.\n */\nexport function colorInitialValueToRgb(\n initialValue: string | number | undefined,\n): string {\n if (initialValue == null) return '0 0 0';\n\n const val = String(initialValue).trim().toLowerCase();\n\n if (val === 'transparent' || val === 'rgba(0,0,0,0)' || val === '') {\n return '0 0 0';\n }\n\n // Named color: white\n if (val === 'white') return '255 255 255';\n if (val === 'black') return '0 0 0';\n\n // rgb(R G B) or rgb(R, G, B) — extract components\n const rgbMatch = val.match(/^rgba?\\(\\s*(\\d+)[,\\s]+(\\d+)[,\\s]+(\\d+)/);\n if (rgbMatch) {\n return `${rgbMatch[1]} ${rgbMatch[2]} ${rgbMatch[3]}`;\n }\n\n // Fallback for any other value\n return '0 0 0';\n}\n\n// ============================================================================\n// Value Type Inference\n// ============================================================================\n\n/**\n * Result of inferring a CSS @property syntax from a value.\n */\nexport interface InferredSyntax {\n syntax: string;\n initialValue: string;\n}\n\nconst UNIT_TO_SYNTAX: Record<string, InferredSyntax> = {};\n\nconst LENGTH_UNITS = [\n 'px',\n 'em',\n 'rem',\n 'vw',\n 'vh',\n 'vmin',\n 'vmax',\n 'ch',\n 'ex',\n 'cap',\n 'ic',\n 'lh',\n 'rlh',\n 'svw',\n 'svh',\n 'lvw',\n 'lvh',\n 'dvw',\n 'dvh',\n 'cqw',\n 'cqh',\n 'cqi',\n 'cqb',\n 'cqmin',\n 'cqmax',\n];\n\nconst ANGLE_UNITS = ['deg', 'rad', 'grad', 'turn'];\nconst TIME_UNITS = ['ms', 's'];\n\nfor (const u of LENGTH_UNITS) {\n UNIT_TO_SYNTAX[u] = { syntax: '<length-percentage>', initialValue: '0px' };\n}\nUNIT_TO_SYNTAX['%'] = { syntax: '<length-percentage>', initialValue: '0px' };\nfor (const u of ANGLE_UNITS) {\n UNIT_TO_SYNTAX[u] = { syntax: '<angle>', initialValue: '0deg' };\n}\nfor (const u of TIME_UNITS) {\n UNIT_TO_SYNTAX[u] = { syntax: '<time>', initialValue: '0s' };\n}\n\n/**\n * Infer CSS @property syntax from a concrete value.\n * Detects numeric types: \\<number\\>, \\<length-percentage\\>, \\<angle\\>, \\<time\\>.\n * Length and percentage values both map to \\<length-percentage\\> for maximum flexibility.\n * Color properties are handled separately via the #name token convention\n * (--name-color gets \\<color\\> syntax automatically in getEffectiveDefinition).\n *\n * @param value - The CSS value to infer from (e.g. '10px', '1', '45deg')\n * @returns Inferred syntax and initial value, or null if not inferable\n */\nexport function inferSyntaxFromValue(value: string): InferredSyntax | null {\n if (!value || typeof value !== 'string') return null;\n\n const trimmed = value.trim();\n if (!trimmed) return null;\n\n if (RE_NUMBER.test(trimmed)) {\n // Bare zero is ambiguous (could be <length>, <angle>, <percentage>, etc.)\n if (parseFloat(trimmed) === 0) return null;\n return { syntax: '<number>', initialValue: '0' };\n }\n\n const unitMatch = trimmed.match(RE_RAW_UNIT);\n if (unitMatch) {\n const unit = unitMatch[2];\n const mapping = UNIT_TO_SYNTAX[unit];\n if (mapping) return mapping;\n }\n\n return null;\n}\n"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ //#region src/properties/property-type-resolver.d.ts
2
+ /**
3
+ * PropertyTypeResolver
4
+ *
5
+ * Automatically infers CSS @property types from custom property values.
6
+ * Supports deferred resolution for var() reference chains of arbitrary depth.
7
+ */
8
+ declare class PropertyTypeResolver {
9
+ /** propName → the prop it depends on */
10
+ private pendingDeps;
11
+ /** propName → list of props waiting on it */
12
+ private reverseDeps;
13
+ /**
14
+ * Scan CSS declarations and auto-register @property for custom properties
15
+ * whose types can be inferred from their values.
16
+ */
17
+ scanDeclarations(declarations: string, isPropertyDefined: (name: string) => boolean, registerProperty: (name: string, syntax: string, initialValue: string) => void): void;
18
+ private addDependency;
19
+ private resolve;
20
+ private isComplexValue;
21
+ }
22
+ //#endregion
23
+ export { PropertyTypeResolver };
24
+ //# sourceMappingURL=property-type-resolver.d.ts.map
@@ -0,0 +1,91 @@
1
+ import { inferSyntaxFromValue } from "./index.js";
2
+
3
+ //#region src/properties/property-type-resolver.ts
4
+ /**
5
+ * PropertyTypeResolver
6
+ *
7
+ * Automatically infers CSS @property types from custom property values.
8
+ * Supports deferred resolution for var() reference chains of arbitrary depth.
9
+ */
10
+ const CUSTOM_PROP_DECL = /^\s*(--[a-z0-9_-]+)\s*:\s*(.+?)\s*$/i;
11
+ const SINGLE_VAR_REF = /^var\((--[a-z0-9_-]+)\)$/i;
12
+ var PropertyTypeResolver = class {
13
+ /** propName → the prop it depends on */
14
+ pendingDeps = /* @__PURE__ */ new Map();
15
+ /** propName → list of props waiting on it */
16
+ reverseDeps = /* @__PURE__ */ new Map();
17
+ /**
18
+ * Scan CSS declarations and auto-register @property for custom properties
19
+ * whose types can be inferred from their values.
20
+ */
21
+ scanDeclarations(declarations, isPropertyDefined, registerProperty) {
22
+ if (!declarations.includes("--")) return;
23
+ const parts = declarations.split(/;+/);
24
+ for (const part of parts) {
25
+ if (!part.trim()) continue;
26
+ const match = CUSTOM_PROP_DECL.exec(part);
27
+ if (!match) continue;
28
+ const propName = match[1];
29
+ const value = match[2].trim();
30
+ if (isPropertyDefined(propName)) continue;
31
+ if (propName.endsWith("-color")) {
32
+ registerProperty(propName, "<color>", "transparent");
33
+ continue;
34
+ }
35
+ if (propName.endsWith("-line-height")) {
36
+ registerProperty(propName, "<number> | <length-percentage>", "0");
37
+ continue;
38
+ }
39
+ if (propName.endsWith("-opacity")) {
40
+ registerProperty(propName, "<number> | <percentage>", "0");
41
+ continue;
42
+ }
43
+ const varMatch = SINGLE_VAR_REF.exec(value);
44
+ if (varMatch) {
45
+ const depName = varMatch[1];
46
+ this.addDependency(propName, depName);
47
+ continue;
48
+ }
49
+ if (this.isComplexValue(value)) continue;
50
+ const inferred = inferSyntaxFromValue(value);
51
+ if (!inferred) continue;
52
+ this.resolve(propName, inferred.syntax, inferred.initialValue, isPropertyDefined, registerProperty);
53
+ }
54
+ }
55
+ addDependency(propName, depName) {
56
+ if (propName === depName) return;
57
+ this.pendingDeps.set(propName, depName);
58
+ let dependents = this.reverseDeps.get(depName);
59
+ if (!dependents) {
60
+ dependents = [];
61
+ this.reverseDeps.set(depName, dependents);
62
+ }
63
+ if (!dependents.includes(propName)) dependents.push(propName);
64
+ }
65
+ resolve(propName, syntax, initialValue, isPropertyDefined, registerProperty, resolving) {
66
+ if (!resolving) resolving = /* @__PURE__ */ new Set();
67
+ if (resolving.has(propName)) return;
68
+ resolving.add(propName);
69
+ if (!isPropertyDefined(propName)) registerProperty(propName, syntax, initialValue);
70
+ const dependents = this.reverseDeps.get(propName);
71
+ if (dependents) {
72
+ this.reverseDeps.delete(propName);
73
+ for (const dependent of dependents) {
74
+ this.pendingDeps.delete(dependent);
75
+ if (isPropertyDefined(dependent)) continue;
76
+ this.resolve(dependent, syntax, initialValue, isPropertyDefined, registerProperty, resolving);
77
+ }
78
+ }
79
+ }
80
+ isComplexValue(value) {
81
+ if (value.includes("calc(")) return true;
82
+ const firstVar = value.indexOf("var(");
83
+ if (firstVar === -1) return false;
84
+ if (value.indexOf("var(", firstVar + 4) !== -1) return true;
85
+ return !SINGLE_VAR_REF.test(value);
86
+ }
87
+ };
88
+
89
+ //#endregion
90
+ export { PropertyTypeResolver };
91
+ //# sourceMappingURL=property-type-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-type-resolver.js","names":[],"sources":["../../src/properties/property-type-resolver.ts"],"sourcesContent":["/**\n * PropertyTypeResolver\n *\n * Automatically infers CSS @property types from custom property values.\n * Supports deferred resolution for var() reference chains of arbitrary depth.\n */\n\nimport { inferSyntaxFromValue } from './index';\n\nconst CUSTOM_PROP_DECL = /^\\s*(--[a-z0-9_-]+)\\s*:\\s*(.+?)\\s*$/i;\nconst SINGLE_VAR_REF = /^var\\((--[a-z0-9_-]+)\\)$/i;\n\nexport class PropertyTypeResolver {\n /** propName → the prop it depends on */\n private pendingDeps = new Map<string, string>();\n /** propName → list of props waiting on it */\n private reverseDeps = new Map<string, string[]>();\n\n /**\n * Scan CSS declarations and auto-register @property for custom properties\n * whose types can be inferred from their values.\n */\n scanDeclarations(\n declarations: string,\n isPropertyDefined: (name: string) => boolean,\n registerProperty: (\n name: string,\n syntax: string,\n initialValue: string,\n ) => void,\n ): void {\n if (!declarations.includes('--')) return;\n\n const parts = declarations.split(/;+/);\n\n for (const part of parts) {\n if (!part.trim()) continue;\n\n const match = CUSTOM_PROP_DECL.exec(part);\n if (!match) continue;\n\n const propName = match[1];\n const value = match[2].trim();\n\n if (isPropertyDefined(propName)) continue;\n\n // Name-based: --*-color properties are always <color> (from #name tokens)\n if (propName.endsWith('-color')) {\n registerProperty(propName, '<color>', 'transparent');\n continue;\n }\n\n // Name-based: --*-line-height accepts numbers, lengths, and percentages\n if (propName.endsWith('-line-height')) {\n registerProperty(propName, '<number> | <length-percentage>', '0');\n continue;\n }\n\n // Name-based: --*-opacity accepts numbers and percentages\n if (propName.endsWith('-opacity')) {\n registerProperty(propName, '<number> | <percentage>', '0');\n continue;\n }\n\n // Single var() reference → record dependency for deferred resolution\n const varMatch = SINGLE_VAR_REF.exec(value);\n if (varMatch) {\n const depName = varMatch[1];\n this.addDependency(propName, depName);\n continue;\n }\n\n // Skip complex expressions (calc, multiple var, etc.)\n if (this.isComplexValue(value)) continue;\n\n const inferred = inferSyntaxFromValue(value);\n if (!inferred) continue;\n\n this.resolve(\n propName,\n inferred.syntax,\n inferred.initialValue,\n isPropertyDefined,\n registerProperty,\n );\n }\n }\n\n private addDependency(propName: string, depName: string): void {\n if (propName === depName) return;\n\n this.pendingDeps.set(propName, depName);\n\n let dependents = this.reverseDeps.get(depName);\n if (!dependents) {\n dependents = [];\n this.reverseDeps.set(depName, dependents);\n }\n if (!dependents.includes(propName)) {\n dependents.push(propName);\n }\n }\n\n private resolve(\n propName: string,\n syntax: string,\n initialValue: string,\n isPropertyDefined: (name: string) => boolean,\n registerProperty: (\n name: string,\n syntax: string,\n initialValue: string,\n ) => void,\n resolving?: Set<string>,\n ): void {\n if (!resolving) resolving = new Set();\n if (resolving.has(propName)) return;\n resolving.add(propName);\n\n if (!isPropertyDefined(propName)) {\n registerProperty(propName, syntax, initialValue);\n }\n\n const dependents = this.reverseDeps.get(propName);\n if (dependents) {\n this.reverseDeps.delete(propName);\n\n for (const dependent of dependents) {\n this.pendingDeps.delete(dependent);\n\n if (isPropertyDefined(dependent)) continue;\n\n this.resolve(\n dependent,\n syntax,\n initialValue,\n isPropertyDefined,\n registerProperty,\n resolving,\n );\n }\n }\n }\n\n private isComplexValue(value: string): boolean {\n if (value.includes('calc(')) return true;\n const firstVar = value.indexOf('var(');\n if (firstVar === -1) return false;\n if (value.indexOf('var(', firstVar + 4) !== -1) return true;\n return !SINGLE_VAR_REF.test(value);\n }\n}\n"],"mappings":";;;;;;;;;AASA,MAAM,mBAAmB;AACzB,MAAM,iBAAiB;AAEvB,IAAa,uBAAb,MAAkC;;CAEhC,AAAQ,8BAAc,IAAI,KAAqB;;CAE/C,AAAQ,8BAAc,IAAI,KAAuB;;;;;CAMjD,iBACE,cACA,mBACA,kBAKM;AACN,MAAI,CAAC,aAAa,SAAS,KAAK,CAAE;EAElC,MAAM,QAAQ,aAAa,MAAM,KAAK;AAEtC,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,CAAC,KAAK,MAAM,CAAE;GAElB,MAAM,QAAQ,iBAAiB,KAAK,KAAK;AACzC,OAAI,CAAC,MAAO;GAEZ,MAAM,WAAW,MAAM;GACvB,MAAM,QAAQ,MAAM,GAAG,MAAM;AAE7B,OAAI,kBAAkB,SAAS,CAAE;AAGjC,OAAI,SAAS,SAAS,SAAS,EAAE;AAC/B,qBAAiB,UAAU,WAAW,cAAc;AACpD;;AAIF,OAAI,SAAS,SAAS,eAAe,EAAE;AACrC,qBAAiB,UAAU,kCAAkC,IAAI;AACjE;;AAIF,OAAI,SAAS,SAAS,WAAW,EAAE;AACjC,qBAAiB,UAAU,2BAA2B,IAAI;AAC1D;;GAIF,MAAM,WAAW,eAAe,KAAK,MAAM;AAC3C,OAAI,UAAU;IACZ,MAAM,UAAU,SAAS;AACzB,SAAK,cAAc,UAAU,QAAQ;AACrC;;AAIF,OAAI,KAAK,eAAe,MAAM,CAAE;GAEhC,MAAM,WAAW,qBAAqB,MAAM;AAC5C,OAAI,CAAC,SAAU;AAEf,QAAK,QACH,UACA,SAAS,QACT,SAAS,cACT,mBACA,iBACD;;;CAIL,AAAQ,cAAc,UAAkB,SAAuB;AAC7D,MAAI,aAAa,QAAS;AAE1B,OAAK,YAAY,IAAI,UAAU,QAAQ;EAEvC,IAAI,aAAa,KAAK,YAAY,IAAI,QAAQ;AAC9C,MAAI,CAAC,YAAY;AACf,gBAAa,EAAE;AACf,QAAK,YAAY,IAAI,SAAS,WAAW;;AAE3C,MAAI,CAAC,WAAW,SAAS,SAAS,CAChC,YAAW,KAAK,SAAS;;CAI7B,AAAQ,QACN,UACA,QACA,cACA,mBACA,kBAKA,WACM;AACN,MAAI,CAAC,UAAW,6BAAY,IAAI,KAAK;AACrC,MAAI,UAAU,IAAI,SAAS,CAAE;AAC7B,YAAU,IAAI,SAAS;AAEvB,MAAI,CAAC,kBAAkB,SAAS,CAC9B,kBAAiB,UAAU,QAAQ,aAAa;EAGlD,MAAM,aAAa,KAAK,YAAY,IAAI,SAAS;AACjD,MAAI,YAAY;AACd,QAAK,YAAY,OAAO,SAAS;AAEjC,QAAK,MAAM,aAAa,YAAY;AAClC,SAAK,YAAY,OAAO,UAAU;AAElC,QAAI,kBAAkB,UAAU,CAAE;AAElC,SAAK,QACH,WACA,QACA,cACA,mBACA,kBACA,UACD;;;;CAKP,AAAQ,eAAe,OAAwB;AAC7C,MAAI,MAAM,SAAS,QAAQ,CAAE,QAAO;EACpC,MAAM,WAAW,MAAM,QAAQ,OAAO;AACtC,MAAI,aAAa,GAAI,QAAO;AAC5B,MAAI,MAAM,QAAQ,QAAQ,WAAW,EAAE,KAAK,GAAI,QAAO;AACvD,SAAO,CAAC,eAAe,KAAK,MAAM"}
@@ -0,0 +1,29 @@
1
+ import { hydrateTastyCache } from "./hydrate.js";
2
+
3
+ //#region src/ssr/astro.d.ts
4
+ interface TastyMiddlewareOptions {
5
+ /**
6
+ * Whether to embed the cache state script for client hydration.
7
+ * Set to false to skip cache transfer. Default: true.
8
+ */
9
+ transferCache?: boolean;
10
+ }
11
+ /**
12
+ * Create an Astro middleware that collects Tasty styles during SSR.
13
+ *
14
+ * All React components rendered during the request (both static
15
+ * and islands) will have their useStyles() calls captured by the
16
+ * collector via AsyncLocalStorage. After rendering, the middleware
17
+ * injects the collected CSS into </head>.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * // src/middleware.ts
22
+ * import { tastyMiddleware } from '@tenphi/tasty/ssr/astro';
23
+ * export const onRequest = tastyMiddleware();
24
+ * ```
25
+ */
26
+ declare function tastyMiddleware(options?: TastyMiddlewareOptions): (_context: unknown, next: () => Promise<Response>) => Promise<Response>;
27
+ //#endregion
28
+ export { TastyMiddlewareOptions, hydrateTastyCache, tastyMiddleware };
29
+ //# sourceMappingURL=astro.d.ts.map
@@ -0,0 +1,65 @@
1
+ import { getConfig } from "../config.js";
2
+ import { registerSSRCollectorGetter } from "./ssr-collector-ref.js";
3
+ import { ServerStyleCollector } from "./collector.js";
4
+ import { getSSRCollector, runWithCollector } from "./async-storage.js";
5
+ import { hydrateTastyCache } from "./hydrate.js";
6
+
7
+ //#region src/ssr/astro.ts
8
+ /**
9
+ * Astro integration for Tasty SSR.
10
+ *
11
+ * Provides tastyMiddleware() for Astro's middleware system.
12
+ * The middleware wraps request handling in a ServerStyleCollector
13
+ * via AsyncLocalStorage, then injects collected CSS into </head>.
14
+ *
15
+ * Import from '@tenphi/tasty/ssr/astro'.
16
+ */
17
+ registerSSRCollectorGetter(getSSRCollector);
18
+ /**
19
+ * Create an Astro middleware that collects Tasty styles during SSR.
20
+ *
21
+ * All React components rendered during the request (both static
22
+ * and islands) will have their useStyles() calls captured by the
23
+ * collector via AsyncLocalStorage. After rendering, the middleware
24
+ * injects the collected CSS into </head>.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * // src/middleware.ts
29
+ * import { tastyMiddleware } from '@tenphi/tasty/ssr/astro';
30
+ * export const onRequest = tastyMiddleware();
31
+ * ```
32
+ */
33
+ function tastyMiddleware(options) {
34
+ const { transferCache = true } = options ?? {};
35
+ return async (_context, next) => {
36
+ const collector = new ServerStyleCollector();
37
+ const response = await runWithCollector(collector, () => next());
38
+ const css = collector.getCSS();
39
+ if (!css) return response;
40
+ const nonce = getConfig().nonce;
41
+ const nonceAttr = nonce ? ` nonce="${nonce}"` : "";
42
+ const html = await response.text();
43
+ const styleTag = `<style data-tasty-ssr${nonceAttr}>${css}</style>`;
44
+ let cacheTag = "";
45
+ if (transferCache) {
46
+ const cacheState = collector.getCacheState();
47
+ if (Object.keys(cacheState.entries).length > 0) cacheTag = `<script data-tasty-cache type="application/json"${nonceAttr}>${JSON.stringify(cacheState)}<\/script>`;
48
+ }
49
+ const modifiedHtml = html.replace("</head>", `${styleTag}${cacheTag}</head>`);
50
+ return new Response(modifiedHtml, {
51
+ status: response.status,
52
+ headers: response.headers
53
+ });
54
+ };
55
+ }
56
+ if (typeof window !== "undefined") {
57
+ const script = document.querySelector("script[data-tasty-cache]");
58
+ if (script) try {
59
+ hydrateTastyCache(JSON.parse(script.textContent));
60
+ } catch {}
61
+ }
62
+
63
+ //#endregion
64
+ export { hydrateTastyCache, tastyMiddleware };
65
+ //# sourceMappingURL=astro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"astro.js","names":[],"sources":["../../src/ssr/astro.ts"],"sourcesContent":["/**\n * Astro integration for Tasty SSR.\n *\n * Provides tastyMiddleware() for Astro's middleware system.\n * The middleware wraps request handling in a ServerStyleCollector\n * via AsyncLocalStorage, then injects collected CSS into </head>.\n *\n * Import from '@tenphi/tasty/ssr/astro'.\n */\n\nimport { getConfig } from '../config';\nimport { getSSRCollector, runWithCollector } from './async-storage';\nimport { ServerStyleCollector } from './collector';\nimport { hydrateTastyCache } from './hydrate';\nimport { registerSSRCollectorGetter } from './ssr-collector-ref';\n\n// Wire up ALS-based collector discovery so useStyles can find\n// the collector set by tastyMiddleware's runWithCollector().\nregisterSSRCollectorGetter(getSSRCollector);\n\n// Re-export for convenience\nexport { hydrateTastyCache };\n\nexport interface TastyMiddlewareOptions {\n /**\n * Whether to embed the cache state script for client hydration.\n * Set to false to skip cache transfer. Default: true.\n */\n transferCache?: boolean;\n}\n\n/**\n * Create an Astro middleware that collects Tasty styles during SSR.\n *\n * All React components rendered during the request (both static\n * and islands) will have their useStyles() calls captured by the\n * collector via AsyncLocalStorage. After rendering, the middleware\n * injects the collected CSS into </head>.\n *\n * @example\n * ```ts\n * // src/middleware.ts\n * import { tastyMiddleware } from '@tenphi/tasty/ssr/astro';\n * export const onRequest = tastyMiddleware();\n * ```\n */\nexport function tastyMiddleware(options?: TastyMiddlewareOptions) {\n const { transferCache = true } = options ?? {};\n\n return async (\n _context: unknown,\n next: () => Promise<Response>,\n ): Promise<Response> => {\n const collector = new ServerStyleCollector();\n\n const response = await runWithCollector(collector, () => next());\n\n const css = collector.getCSS();\n if (!css) return response;\n\n const nonce = getConfig().nonce;\n const nonceAttr = nonce ? ` nonce=\"${nonce}\"` : '';\n const html = await response.text();\n const styleTag = `<style data-tasty-ssr${nonceAttr}>${css}</style>`;\n\n let cacheTag = '';\n if (transferCache) {\n const cacheState = collector.getCacheState();\n const hasHydratableStyles = Object.keys(cacheState.entries).length > 0;\n if (hasHydratableStyles) {\n cacheTag = `<script data-tasty-cache type=\"application/json\"${nonceAttr}>${JSON.stringify(cacheState)}</script>`;\n }\n }\n\n const modifiedHtml = html.replace(\n '</head>',\n `${styleTag}${cacheTag}</head>`,\n );\n\n return new Response(modifiedHtml, {\n status: response.status,\n headers: response.headers,\n });\n };\n}\n\n// Client-side auto-hydration.\n// When imported in the browser, reads the cache state from the DOM\n// and pre-populates the injector before any island hydrates.\nif (typeof window !== 'undefined') {\n const script = document.querySelector('script[data-tasty-cache]');\n if (script) {\n try {\n const state = JSON.parse(script.textContent!);\n hydrateTastyCache(state);\n } catch {\n // Ignore malformed cache state\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkBA,2BAA2B,gBAAgB;;;;;;;;;;;;;;;;AA4B3C,SAAgB,gBAAgB,SAAkC;CAChE,MAAM,EAAE,gBAAgB,SAAS,WAAW,EAAE;AAE9C,QAAO,OACL,UACA,SACsB;EACtB,MAAM,YAAY,IAAI,sBAAsB;EAE5C,MAAM,WAAW,MAAM,iBAAiB,iBAAiB,MAAM,CAAC;EAEhE,MAAM,MAAM,UAAU,QAAQ;AAC9B,MAAI,CAAC,IAAK,QAAO;EAEjB,MAAM,QAAQ,WAAW,CAAC;EAC1B,MAAM,YAAY,QAAQ,WAAW,MAAM,KAAK;EAChD,MAAM,OAAO,MAAM,SAAS,MAAM;EAClC,MAAM,WAAW,wBAAwB,UAAU,GAAG,IAAI;EAE1D,IAAI,WAAW;AACf,MAAI,eAAe;GACjB,MAAM,aAAa,UAAU,eAAe;AAE5C,OAD4B,OAAO,KAAK,WAAW,QAAQ,CAAC,SAAS,EAEnE,YAAW,mDAAmD,UAAU,GAAG,KAAK,UAAU,WAAW,CAAC;;EAI1G,MAAM,eAAe,KAAK,QACxB,WACA,GAAG,WAAW,SAAS,SACxB;AAED,SAAO,IAAI,SAAS,cAAc;GAChC,QAAQ,SAAS;GACjB,SAAS,SAAS;GACnB,CAAC;;;AAON,IAAI,OAAO,WAAW,aAAa;CACjC,MAAM,SAAS,SAAS,cAAc,2BAA2B;AACjE,KAAI,OACF,KAAI;AAEF,oBADc,KAAK,MAAM,OAAO,YAAa,CACrB;SAClB"}
@@ -0,0 +1,17 @@
1
+ import { ServerStyleCollector } from "./collector.js";
2
+
3
+ //#region src/ssr/async-storage.d.ts
4
+ /**
5
+ * Run a function with a ServerStyleCollector bound to the current
6
+ * async context. All useStyles() calls within `fn` (and any async
7
+ * continuations) will find this collector via getSSRCollector().
8
+ */
9
+ declare function runWithCollector<T>(collector: ServerStyleCollector, fn: () => T): T;
10
+ /**
11
+ * Retrieve the ServerStyleCollector bound to the current async context.
12
+ * Returns null when called outside of runWithCollector() or on the client.
13
+ */
14
+ declare function getSSRCollector(): ServerStyleCollector | null;
15
+ //#endregion
16
+ export { getSSRCollector, runWithCollector };
17
+ //# sourceMappingURL=async-storage.d.ts.map
@@ -0,0 +1,35 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+
3
+ //#region src/ssr/async-storage.ts
4
+ /**
5
+ * AsyncLocalStorage integration for SSR collector discovery.
6
+ *
7
+ * Used by Astro middleware and generic framework integrations where
8
+ * the library cannot wrap the React tree with a context provider.
9
+ * The middleware calls runWithCollector() around the render, and
10
+ * useStyles() calls getSSRCollector() to find it.
11
+ *
12
+ * This module imports from 'node:async_hooks' — it must be excluded
13
+ * from client bundles via the build configuration.
14
+ */
15
+ const tastySSRStorage = new AsyncLocalStorage();
16
+ /**
17
+ * Run a function with a ServerStyleCollector bound to the current
18
+ * async context. All useStyles() calls within `fn` (and any async
19
+ * continuations) will find this collector via getSSRCollector().
20
+ */
21
+ function runWithCollector(collector, fn) {
22
+ return tastySSRStorage.run(collector, fn);
23
+ }
24
+ /**
25
+ * Retrieve the ServerStyleCollector bound to the current async context.
26
+ * Returns null when called outside of runWithCollector() or on the client.
27
+ */
28
+ function getSSRCollector() {
29
+ if (typeof tastySSRStorage?.getStore !== "function") return null;
30
+ return tastySSRStorage.getStore() ?? null;
31
+ }
32
+
33
+ //#endregion
34
+ export { getSSRCollector, runWithCollector };
35
+ //# sourceMappingURL=async-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async-storage.js","names":[],"sources":["../../src/ssr/async-storage.ts"],"sourcesContent":["/**\n * AsyncLocalStorage integration for SSR collector discovery.\n *\n * Used by Astro middleware and generic framework integrations where\n * the library cannot wrap the React tree with a context provider.\n * The middleware calls runWithCollector() around the render, and\n * useStyles() calls getSSRCollector() to find it.\n *\n * This module imports from 'node:async_hooks' — it must be excluded\n * from client bundles via the build configuration.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\nimport type { ServerStyleCollector } from './collector';\n\nconst tastySSRStorage = new AsyncLocalStorage<ServerStyleCollector>();\n\n/**\n * Run a function with a ServerStyleCollector bound to the current\n * async context. All useStyles() calls within `fn` (and any async\n * continuations) will find this collector via getSSRCollector().\n */\nexport function runWithCollector<T>(\n collector: ServerStyleCollector,\n fn: () => T,\n): T {\n return tastySSRStorage.run(collector, fn);\n}\n\n/**\n * Retrieve the ServerStyleCollector bound to the current async context.\n * Returns null when called outside of runWithCollector() or on the client.\n */\nexport function getSSRCollector(): ServerStyleCollector | null {\n if (typeof tastySSRStorage?.getStore !== 'function') return null;\n return tastySSRStorage.getStore() ?? null;\n}\n"],"mappings":";;;;;;;;;;;;;;AAgBA,MAAM,kBAAkB,IAAI,mBAAyC;;;;;;AAOrE,SAAgB,iBACd,WACA,IACG;AACH,QAAO,gBAAgB,IAAI,WAAW,GAAG;;;;;;AAO3C,SAAgB,kBAA+C;AAC7D,KAAI,OAAO,iBAAiB,aAAa,WAAY,QAAO;AAC5D,QAAO,gBAAgB,UAAU,IAAI"}
@@ -0,0 +1,40 @@
1
+ import { parsePropertyToken } from "../properties/index.js";
2
+ import { PropertyTypeResolver } from "../properties/property-type-resolver.js";
3
+ import { formatPropertyCSS } from "./format-property.js";
4
+
5
+ //#region src/ssr/collect-auto-properties.ts
6
+ /**
7
+ * Scan rendered rules for custom property declarations and collect
8
+ * auto-inferred @property rules via the SSR collector.
9
+ *
10
+ * @param rules - Rendered style rules containing CSS declarations
11
+ * @param collector - SSR collector to emit @property CSS into
12
+ * @param styles - Original styles object (used to skip explicit @properties)
13
+ */
14
+ function collectAutoInferredProperties(rules, collector, styles) {
15
+ const registered = /* @__PURE__ */ new Set();
16
+ if (styles) {
17
+ const localProps = styles["@properties"];
18
+ if (localProps && typeof localProps === "object") for (const token of Object.keys(localProps)) {
19
+ const parsed = parsePropertyToken(token);
20
+ if (parsed.isValid) registered.add(parsed.cssName);
21
+ }
22
+ }
23
+ const resolver = new PropertyTypeResolver();
24
+ for (const rule of rules) {
25
+ if (!rule.declarations) continue;
26
+ resolver.scanDeclarations(rule.declarations, (name) => registered.has(name), (name, syntax, initialValue) => {
27
+ registered.add(name);
28
+ const css = formatPropertyCSS(name, {
29
+ syntax,
30
+ inherits: true,
31
+ initialValue
32
+ });
33
+ if (css) collector.collectProperty(`__auto:${name}`, css);
34
+ });
35
+ }
36
+ }
37
+
38
+ //#endregion
39
+ export { collectAutoInferredProperties };
40
+ //# sourceMappingURL=collect-auto-properties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect-auto-properties.js","names":[],"sources":["../../src/ssr/collect-auto-properties.ts"],"sourcesContent":["/**\n * SSR auto-property inference.\n *\n * Scans rendered CSS declarations for custom properties whose types\n * can be inferred from their values (e.g. `--angle: 30deg` → `<angle>`).\n * Mirrors the client-side auto-inference in StyleInjector.inject().\n */\n\nimport type { StyleResult } from '../pipeline';\nimport { parsePropertyToken } from '../properties';\nimport { PropertyTypeResolver } from '../properties/property-type-resolver';\nimport type { Styles } from '../styles/types';\n\nimport type { ServerStyleCollector } from './collector';\nimport { formatPropertyCSS } from './format-property';\n\n/**\n * Scan rendered rules for custom property declarations and collect\n * auto-inferred @property rules via the SSR collector.\n *\n * @param rules - Rendered style rules containing CSS declarations\n * @param collector - SSR collector to emit @property CSS into\n * @param styles - Original styles object (used to skip explicit @properties)\n */\nexport function collectAutoInferredProperties(\n rules: StyleResult[],\n collector: ServerStyleCollector,\n styles?: Styles,\n): void {\n const registered = new Set<string>();\n\n if (styles) {\n const localProps = styles['@properties'];\n if (localProps && typeof localProps === 'object') {\n for (const token of Object.keys(localProps as Record<string, unknown>)) {\n const parsed = parsePropertyToken(token);\n if (parsed.isValid) {\n registered.add(parsed.cssName);\n }\n }\n }\n }\n\n const resolver = new PropertyTypeResolver();\n\n for (const rule of rules) {\n if (!rule.declarations) continue;\n resolver.scanDeclarations(\n rule.declarations,\n (name) => registered.has(name),\n (name, syntax, initialValue) => {\n registered.add(name);\n const css = formatPropertyCSS(name, {\n syntax,\n inherits: true,\n initialValue,\n });\n if (css) {\n collector.collectProperty(`__auto:${name}`, css);\n }\n },\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAwBA,SAAgB,8BACd,OACA,WACA,QACM;CACN,MAAM,6BAAa,IAAI,KAAa;AAEpC,KAAI,QAAQ;EACV,MAAM,aAAa,OAAO;AAC1B,MAAI,cAAc,OAAO,eAAe,SACtC,MAAK,MAAM,SAAS,OAAO,KAAK,WAAsC,EAAE;GACtE,MAAM,SAAS,mBAAmB,MAAM;AACxC,OAAI,OAAO,QACT,YAAW,IAAI,OAAO,QAAQ;;;CAMtC,MAAM,WAAW,IAAI,sBAAsB;AAE3C,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,CAAC,KAAK,aAAc;AACxB,WAAS,iBACP,KAAK,eACJ,SAAS,WAAW,IAAI,KAAK,GAC7B,MAAM,QAAQ,iBAAiB;AAC9B,cAAW,IAAI,KAAK;GACpB,MAAM,MAAM,kBAAkB,MAAM;IAClC;IACA,UAAU;IACV;IACD,CAAC;AACF,OAAI,IACF,WAAU,gBAAgB,UAAU,QAAQ,IAAI;IAGrD"}