@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,5 @@
1
+ import { SSRCacheState, ServerStyleCollector } from "./collector.js";
2
+ import { hydrateTastyCache } from "./hydrate.js";
3
+ import { TastySSRContext } from "./context.js";
4
+ import { getSSRCollector, runWithCollector } from "./async-storage.js";
5
+ export { type SSRCacheState, ServerStyleCollector, TastySSRContext, getSSRCollector, hydrateTastyCache, runWithCollector };
@@ -0,0 +1,12 @@
1
+ import { TastySSRContext } from "./context.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/index.ts
8
+ registerSSRCollectorGetter(getSSRCollector);
9
+
10
+ //#endregion
11
+ export { ServerStyleCollector, TastySSRContext, getSSRCollector, hydrateTastyCache, runWithCollector };
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/ssr/index.ts"],"sourcesContent":["/**\n * SSR entry point for @tenphi/tasty.\n *\n * Provides the core SSR infrastructure: ServerStyleCollector,\n * React context, AsyncLocalStorage integration, and cache hydration.\n *\n * Import from '@tenphi/tasty/ssr'.\n */\n\n// Core collector\nexport { ServerStyleCollector } from './collector';\nexport type { SSRCacheState } from './collector';\n\n// React context for Next.js streaming\nexport { TastySSRContext } from './context';\n\n// AsyncLocalStorage integration for Astro / generic frameworks\nexport { runWithCollector, getSSRCollector } from './async-storage';\n\n// Client-side cache hydration\nexport { hydrateTastyCache } from './hydrate';\n\n// Register the ALS getter so useStyles can find the collector\n// without importing 'node:async_hooks' in the browser bundle.\nimport { getSSRCollector } from './async-storage';\nimport { registerSSRCollectorGetter } from './ssr-collector-ref';\n\nregisterSSRCollectorGetter(getSSRCollector);\n"],"mappings":";;;;;;;AA2BA,2BAA2B,gBAAgB"}
@@ -0,0 +1,45 @@
1
+ import { ServerStyleCollector } from "./collector.js";
2
+ import * as react from "react";
3
+ import { ReactNode } from "react";
4
+
5
+ //#region src/ssr/next.d.ts
6
+ interface TastyRegistryProps {
7
+ children: ReactNode;
8
+ /**
9
+ * Whether to embed the cache state script for client hydration.
10
+ * Set to false to skip cache transfer (useful when cache size
11
+ * exceeds the hydration benefit). Default: true.
12
+ */
13
+ transferCache?: boolean;
14
+ }
15
+ /**
16
+ * Next.js App Router registry for Tasty SSR.
17
+ *
18
+ * Wraps the component tree with a ServerStyleCollector and flushes
19
+ * collected CSS into the HTML stream via useServerInsertedHTML.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * // app/tasty-registry.tsx
24
+ * 'use client';
25
+ * import { TastyRegistry } from '@tenphi/tasty/ssr/next';
26
+ * export default function TastyStyleRegistry({ children }) {
27
+ * return <TastyRegistry>{children}</TastyRegistry>;
28
+ * }
29
+ *
30
+ * // app/layout.tsx
31
+ * import TastyStyleRegistry from './tasty-registry';
32
+ * export default function RootLayout({ children }) {
33
+ * return <html><body>
34
+ * <TastyStyleRegistry>{children}</TastyStyleRegistry>
35
+ * </body></html>;
36
+ * }
37
+ * ```
38
+ */
39
+ declare function TastyRegistry({
40
+ children,
41
+ transferCache
42
+ }: TastyRegistryProps): react.FunctionComponentElement<react.ProviderProps<ServerStyleCollector | null>>;
43
+ //#endregion
44
+ export { TastyRegistry, TastyRegistryProps };
45
+ //# sourceMappingURL=next.d.ts.map
@@ -0,0 +1,71 @@
1
+ 'use client';
2
+
3
+ import { getConfig } from "../config.js";
4
+ import { TastySSRContext } from "./context.js";
5
+ import { ServerStyleCollector } from "./collector.js";
6
+ import { hydrateTastyCache } from "./hydrate.js";
7
+ import { Fragment, createElement, useState } from "react";
8
+ import { useServerInsertedHTML } from "next/navigation";
9
+
10
+ //#region src/ssr/next.ts
11
+ /**
12
+ * Next.js integration for Tasty SSR.
13
+ *
14
+ * Provides TastyRegistry for App Router (streaming via useServerInsertedHTML)
15
+ * and createTastySSRDocument for Pages Router (non-streaming).
16
+ *
17
+ * Import from '@tenphi/tasty/ssr/next'.
18
+ */
19
+ if (typeof window !== "undefined" && window.__TASTY_SSR_CACHE__) hydrateTastyCache(window.__TASTY_SSR_CACHE__);
20
+ /**
21
+ * Next.js App Router registry for Tasty SSR.
22
+ *
23
+ * Wraps the component tree with a ServerStyleCollector and flushes
24
+ * collected CSS into the HTML stream via useServerInsertedHTML.
25
+ *
26
+ * @example
27
+ * ```tsx
28
+ * // app/tasty-registry.tsx
29
+ * 'use client';
30
+ * import { TastyRegistry } from '@tenphi/tasty/ssr/next';
31
+ * export default function TastyStyleRegistry({ children }) {
32
+ * return <TastyRegistry>{children}</TastyRegistry>;
33
+ * }
34
+ *
35
+ * // app/layout.tsx
36
+ * import TastyStyleRegistry from './tasty-registry';
37
+ * export default function RootLayout({ children }) {
38
+ * return <html><body>
39
+ * <TastyStyleRegistry>{children}</TastyStyleRegistry>
40
+ * </body></html>;
41
+ * }
42
+ * ```
43
+ */
44
+ function TastyRegistry({ children, transferCache = true }) {
45
+ const isClient = typeof window !== "undefined";
46
+ const [collector] = useState(() => isClient ? null : new ServerStyleCollector());
47
+ const nonce = getConfig().nonce;
48
+ useServerInsertedHTML(() => {
49
+ if (!collector) return null;
50
+ const css = collector.flushCSS();
51
+ const cacheState = collector.getCacheState();
52
+ if (!css) return null;
53
+ const styleEl = createElement("style", {
54
+ key: "tasty-ssr-styles",
55
+ "data-tasty-ssr": "",
56
+ nonce,
57
+ dangerouslySetInnerHTML: { __html: css }
58
+ });
59
+ if (!transferCache) return styleEl;
60
+ return createElement(Fragment, null, styleEl, createElement("script", {
61
+ key: "tasty-ssr-cache",
62
+ nonce,
63
+ dangerouslySetInnerHTML: { __html: `(window.__TASTY_SSR_CACHE__=window.__TASTY_SSR_CACHE__||{entries:{},classCounter:0});Object.assign(window.__TASTY_SSR_CACHE__.entries,${JSON.stringify(cacheState.entries)});window.__TASTY_SSR_CACHE__.classCounter=${cacheState.classCounter};` }
64
+ }));
65
+ });
66
+ return createElement(TastySSRContext.Provider, { value: collector }, children);
67
+ }
68
+
69
+ //#endregion
70
+ export { TastyRegistry };
71
+ //# sourceMappingURL=next.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.js","names":[],"sources":["../../src/ssr/next.ts"],"sourcesContent":["/**\n * Next.js integration for Tasty SSR.\n *\n * Provides TastyRegistry for App Router (streaming via useServerInsertedHTML)\n * and createTastySSRDocument for Pages Router (non-streaming).\n *\n * Import from '@tenphi/tasty/ssr/next'.\n */\n\n'use client';\n\n/// <reference path=\"./next-navigation.d.ts\" />\n\nimport { createElement, Fragment, useState, type ReactNode } from 'react';\nimport { useServerInsertedHTML } from 'next/navigation';\n\nimport { getConfig } from '../config';\nimport { ServerStyleCollector } from './collector';\nimport { TastySSRContext } from './context';\nimport { hydrateTastyCache } from './hydrate';\n\n// Auto-hydrate on module load (client only).\n// When this module is imported by the TastyRegistry client component,\n// the streaming cache scripts have already populated __TASTY_SSR_CACHE__.\nif (typeof window !== 'undefined' && window.__TASTY_SSR_CACHE__) {\n hydrateTastyCache(window.__TASTY_SSR_CACHE__);\n}\n\nexport interface TastyRegistryProps {\n children: ReactNode;\n /**\n * Whether to embed the cache state script for client hydration.\n * Set to false to skip cache transfer (useful when cache size\n * exceeds the hydration benefit). Default: true.\n */\n transferCache?: boolean;\n}\n\n/**\n * Next.js App Router registry for Tasty SSR.\n *\n * Wraps the component tree with a ServerStyleCollector and flushes\n * collected CSS into the HTML stream via useServerInsertedHTML.\n *\n * @example\n * ```tsx\n * // app/tasty-registry.tsx\n * 'use client';\n * import { TastyRegistry } from '@tenphi/tasty/ssr/next';\n * export default function TastyStyleRegistry({ children }) {\n * return <TastyRegistry>{children}</TastyRegistry>;\n * }\n *\n * // app/layout.tsx\n * import TastyStyleRegistry from './tasty-registry';\n * export default function RootLayout({ children }) {\n * return <html><body>\n * <TastyStyleRegistry>{children}</TastyStyleRegistry>\n * </body></html>;\n * }\n * ```\n */\nexport function TastyRegistry({\n children,\n transferCache = true,\n}: TastyRegistryProps) {\n const isClient = typeof window !== 'undefined';\n\n const [collector] = useState(() =>\n isClient ? null : new ServerStyleCollector(),\n );\n const nonce = getConfig().nonce;\n\n useServerInsertedHTML(() => {\n if (!collector) return null;\n\n const css = collector.flushCSS();\n const cacheState = collector.getCacheState();\n\n if (!css) return null;\n\n const styleEl = createElement('style', {\n key: 'tasty-ssr-styles',\n 'data-tasty-ssr': '',\n nonce,\n dangerouslySetInnerHTML: { __html: css },\n });\n\n if (!transferCache) return styleEl;\n\n const scriptEl = createElement('script', {\n key: 'tasty-ssr-cache',\n nonce,\n dangerouslySetInnerHTML: {\n __html:\n `(window.__TASTY_SSR_CACHE__=window.__TASTY_SSR_CACHE__||{entries:{},classCounter:0});` +\n `Object.assign(window.__TASTY_SSR_CACHE__.entries,${JSON.stringify(cacheState.entries)});` +\n `window.__TASTY_SSR_CACHE__.classCounter=${cacheState.classCounter};`,\n },\n });\n\n return createElement(Fragment, null, styleEl, scriptEl);\n });\n\n return createElement(\n TastySSRContext.Provider,\n { value: collector },\n children,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAwBA,IAAI,OAAO,WAAW,eAAe,OAAO,oBAC1C,mBAAkB,OAAO,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;AAqC/C,SAAgB,cAAc,EAC5B,UACA,gBAAgB,QACK;CACrB,MAAM,WAAW,OAAO,WAAW;CAEnC,MAAM,CAAC,aAAa,eAClB,WAAW,OAAO,IAAI,sBAAsB,CAC7C;CACD,MAAM,QAAQ,WAAW,CAAC;AAE1B,6BAA4B;AAC1B,MAAI,CAAC,UAAW,QAAO;EAEvB,MAAM,MAAM,UAAU,UAAU;EAChC,MAAM,aAAa,UAAU,eAAe;AAE5C,MAAI,CAAC,IAAK,QAAO;EAEjB,MAAM,UAAU,cAAc,SAAS;GACrC,KAAK;GACL,kBAAkB;GAClB;GACA,yBAAyB,EAAE,QAAQ,KAAK;GACzC,CAAC;AAEF,MAAI,CAAC,cAAe,QAAO;AAa3B,SAAO,cAAc,UAAU,MAAM,SAXpB,cAAc,UAAU;GACvC,KAAK;GACL;GACA,yBAAyB,EACvB,QACE,yIACoD,KAAK,UAAU,WAAW,QAAQ,CAAC,4CAC5C,WAAW,aAAa,IACtE;GACF,CAAC,CAEqD;GACvD;AAEF,QAAO,cACL,gBAAgB,UAChB,EAAE,OAAO,WAAW,EACpB,SACD"}
@@ -0,0 +1,12 @@
1
+ //#region src/ssr/ssr-collector-ref.ts
2
+ let _getSSRCollector = null;
3
+ function registerSSRCollectorGetter(fn) {
4
+ _getSSRCollector = fn;
5
+ }
6
+ function getRegisteredSSRCollector() {
7
+ return _getSSRCollector ? _getSSRCollector() : null;
8
+ }
9
+
10
+ //#endregion
11
+ export { getRegisteredSSRCollector, registerSSRCollectorGetter };
12
+ //# sourceMappingURL=ssr-collector-ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssr-collector-ref.js","names":[],"sources":["../../src/ssr/ssr-collector-ref.ts"],"sourcesContent":["/**\n * Global reference to the SSR collector getter function.\n *\n * This indirection avoids importing 'node:async_hooks' in the browser bundle.\n * The SSR entry point sets this ref when loaded on the server. The useStyles\n * hook calls it if set; on the client it stays null and is never called.\n */\n\nimport type { ServerStyleCollector } from './collector';\n\ntype SSRCollectorGetter = () => ServerStyleCollector | null;\n\nlet _getSSRCollector: SSRCollectorGetter | null = null;\n\nexport function registerSSRCollectorGetter(fn: SSRCollectorGetter): void {\n _getSSRCollector = fn;\n}\n\nexport function getRegisteredSSRCollector(): ServerStyleCollector | null {\n return _getSSRCollector ? _getSSRCollector() : null;\n}\n"],"mappings":";AAYA,IAAI,mBAA8C;AAElD,SAAgB,2BAA2B,IAA8B;AACvE,oBAAmB;;AAGrB,SAAgB,4BAAyD;AACvE,QAAO,mBAAmB,kBAAkB,GAAG"}
@@ -0,0 +1,49 @@
1
+ import { Styles } from "../styles/types.js";
2
+
3
+ //#region src/states/index.d.ts
4
+ /**
5
+ * Parsed advanced state information
6
+ */
7
+ interface ParsedAdvancedState {
8
+ type: 'media' | 'container' | 'root' | 'parent' | 'own' | 'starting' | 'predefined' | 'modifier';
9
+ condition: string;
10
+ containerName?: string;
11
+ raw: string;
12
+ mediaType?: string;
13
+ }
14
+ /**
15
+ * Context for state parsing operations
16
+ */
17
+ interface StateParserContext {
18
+ localPredefinedStates: Record<string, string>;
19
+ globalPredefinedStates: Record<string, string>;
20
+ isSubElement?: boolean;
21
+ }
22
+ /**
23
+ * At-rule context for CSS generation
24
+ */
25
+ interface AtRuleContext {
26
+ media?: string[];
27
+ container?: {
28
+ name?: string;
29
+ condition: string;
30
+ }[];
31
+ startingStyle?: boolean;
32
+ rootStates?: string[];
33
+ negatedRootStates?: string[];
34
+ }
35
+ /**
36
+ * Configure global predefined states
37
+ */
38
+ declare function setGlobalPredefinedStates(states: Record<string, string>): void;
39
+ /**
40
+ * Get global predefined states
41
+ */
42
+ declare function getGlobalPredefinedStates(): Record<string, string>;
43
+ /**
44
+ * Create a state parser context from styles
45
+ */
46
+ declare function createStateParserContext(styles?: Styles, isSubElement?: boolean): StateParserContext;
47
+ //#endregion
48
+ export { AtRuleContext, ParsedAdvancedState, StateParserContext, createStateParserContext, getGlobalPredefinedStates, setGlobalPredefinedStates };
49
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,416 @@
1
+ import { isDevEnv } from "../utils/is-dev-env.js";
2
+ import { hasStylesGenerated } from "../config.js";
3
+
4
+ //#region src/states/index.ts
5
+ /**
6
+ * Advanced State Mapping - Predefined States Management
7
+ *
8
+ * This module handles global and local predefined states for the Tasty styling system.
9
+ * See ADVANCED_STATE_MAPPING.md for full specification.
10
+ */
11
+ const BUILTIN_STATES = new Set([
12
+ "@starting",
13
+ "@keyframes",
14
+ "@properties",
15
+ "@supports",
16
+ "@inherit"
17
+ ]);
18
+ const RESERVED_PREFIXES = [
19
+ "@media",
20
+ "@root",
21
+ "@parent",
22
+ "@own",
23
+ "@(",
24
+ "@starting",
25
+ "@keyframes",
26
+ "@properties",
27
+ "@supports",
28
+ "@inherit"
29
+ ];
30
+ let globalPredefinedStates = {};
31
+ const emittedWarnings = /* @__PURE__ */ new Set();
32
+ const devMode = isDevEnv();
33
+ /**
34
+ * Emit a warning only once
35
+ */
36
+ function warnOnce(key, message) {
37
+ if (devMode && !emittedWarnings.has(key)) {
38
+ emittedWarnings.add(key);
39
+ console.warn(message);
40
+ }
41
+ }
42
+ /**
43
+ * Configure global predefined states
44
+ */
45
+ function setGlobalPredefinedStates(states) {
46
+ if (hasStylesGenerated()) {
47
+ const newStateNames = Object.keys(states).join(", ");
48
+ warnOnce(`dynamic-states:${newStateNames}`, `[Tasty] Cannot update predefined states after styles have been generated.\nThe new definition(s) for ${newStateNames} will be ignored.`);
49
+ return;
50
+ }
51
+ for (const [name, value] of Object.entries(states)) {
52
+ if (!/^@[A-Za-z][A-Za-z0-9-]*$/.test(name)) {
53
+ warnOnce(`invalid-state-name:${name}`, `[Tasty] Invalid predefined state name '${name}'. Must start with '@' followed by a letter.`);
54
+ continue;
55
+ }
56
+ if (BUILTIN_STATES.has(name)) {
57
+ warnOnce(`reserved-state:${name}`, `[Tasty] Cannot define predefined state '${name}'. This name is reserved for built-in functionality.`);
58
+ continue;
59
+ }
60
+ if (name === "@media" || name === "@root" || name === "@parent" || name === "@own" || name.startsWith("@(")) {
61
+ warnOnce(`reserved-prefix:${name}`, `[Tasty] Cannot define predefined state '${name}'. This prefix is reserved for built-in functionality.`);
62
+ continue;
63
+ }
64
+ const crossRefs = extractPredefinedStateRefs(value);
65
+ if (crossRefs.length > 0) {
66
+ warnOnce(`cross-ref:${name}`, `[Tasty] Predefined state '${name}' references another predefined state '${crossRefs[0]}'.\nPredefined states cannot reference each other. Use the full definition instead.`);
67
+ continue;
68
+ }
69
+ if (globalPredefinedStates[name] && globalPredefinedStates[name] !== value) warnOnce(`duplicate-state:${name}`, `[Tasty] Duplicate predefined state '${name}' in configure(). The last definition will be used.`);
70
+ globalPredefinedStates[name] = value;
71
+ }
72
+ }
73
+ /**
74
+ * Get global predefined states
75
+ */
76
+ function getGlobalPredefinedStates() {
77
+ return globalPredefinedStates;
78
+ }
79
+ /**
80
+ * Regex to match predefined state references in a string
81
+ * Matches @name that is NOT followed by ( or : and is a complete word
82
+ * Uses word boundary and negative lookahead
83
+ */
84
+ const PREDEFINED_STATE_PATTERN = /@([A-Za-z][A-Za-z0-9-]*)(?![A-Za-z0-9-:(])/g;
85
+ /**
86
+ * Extract predefined state references from a string
87
+ */
88
+ function extractPredefinedStateRefs(value) {
89
+ const matches = value.matchAll(PREDEFINED_STATE_PATTERN);
90
+ const refs = [];
91
+ for (const match of matches) {
92
+ const stateName = "@" + match[1];
93
+ if (!BUILTIN_STATES.has(stateName) && !refs.includes(stateName)) refs.push(stateName);
94
+ }
95
+ return refs;
96
+ }
97
+ /**
98
+ * Check if a state key is a predefined state reference
99
+ */
100
+ function isPredefinedStateRef(stateKey) {
101
+ if (!stateKey.startsWith("@")) return false;
102
+ if (BUILTIN_STATES.has(stateKey)) return false;
103
+ for (const prefix of RESERVED_PREFIXES) if (stateKey === prefix || stateKey.startsWith(prefix)) {
104
+ if (stateKey === "@media" || stateKey.startsWith("@media(") || stateKey.startsWith("@media:")) return false;
105
+ if (stateKey === "@root" || stateKey.startsWith("@root(")) return false;
106
+ if (stateKey === "@parent" || stateKey.startsWith("@parent(")) return false;
107
+ if (stateKey === "@own" || stateKey.startsWith("@own(")) return false;
108
+ if (stateKey.startsWith("@(")) return false;
109
+ }
110
+ return /^@[A-Za-z][A-Za-z0-9-]*$/.test(stateKey);
111
+ }
112
+ /**
113
+ * Extract local predefined states from a styles object
114
+ * Local predefined states are top-level keys starting with @ that have string values
115
+ * and are valid predefined state names (not built-in like @media, @root, etc.)
116
+ */
117
+ function extractLocalPredefinedStates(styles) {
118
+ const localStates = {};
119
+ if (!styles || typeof styles !== "object") return localStates;
120
+ for (const [key, value] of Object.entries(styles)) if (key.startsWith("@") && typeof value === "string") {
121
+ if (!/^@[A-Za-z][A-Za-z0-9-]*$/.test(key)) continue;
122
+ if (BUILTIN_STATES.has(key)) continue;
123
+ if (key === "@media" || key === "@root" || key === "@parent" || key === "@own" || key.startsWith("@(")) continue;
124
+ const crossRefs = extractPredefinedStateRefs(value);
125
+ if (crossRefs.length > 0) {
126
+ warnOnce(`local-cross-ref:${key}`, `[Tasty] Predefined state '${key}' references another predefined state '${crossRefs[0]}'.\nPredefined states cannot reference each other. Use the full definition instead.`);
127
+ continue;
128
+ }
129
+ localStates[key] = value;
130
+ }
131
+ return localStates;
132
+ }
133
+ /**
134
+ * Create a state parser context from styles
135
+ */
136
+ function createStateParserContext(styles, isSubElement) {
137
+ return {
138
+ localPredefinedStates: styles ? extractLocalPredefinedStates(styles) : {},
139
+ globalPredefinedStates: getGlobalPredefinedStates(),
140
+ isSubElement
141
+ };
142
+ }
143
+ /**
144
+ * Resolve a predefined state reference to its value
145
+ * Returns the resolved value or null if not found
146
+ */
147
+ function resolvePredefinedState(stateKey, ctx) {
148
+ if (ctx.localPredefinedStates[stateKey]) return ctx.localPredefinedStates[stateKey];
149
+ if (ctx.globalPredefinedStates[stateKey]) return ctx.globalPredefinedStates[stateKey];
150
+ warnOnce(`undefined-state:${stateKey}`, `[Tasty] Undefined predefined state '${stateKey}'.\nDefine it in configure({ states: { '${stateKey}': '...' } }) or in the component's styles.`);
151
+ return null;
152
+ }
153
+ /**
154
+ * Expand dimension shorthands in a condition string
155
+ * w -> width, h -> height, is -> inline-size, bs -> block-size
156
+ */
157
+ function expandDimensionShorthands(condition) {
158
+ let result = condition;
159
+ result = result.replace(/\bw\b/g, "width");
160
+ result = result.replace(/\bh\b/g, "height");
161
+ result = result.replace(/\bis\b/g, "inline-size");
162
+ result = result.replace(/\bbs\b/g, "block-size");
163
+ return result;
164
+ }
165
+ /**
166
+ * Convert tasty units in a string (e.g., 40x -> calc(var(--gap) * 40))
167
+ */
168
+ function expandTastyUnits(value) {
169
+ return value.replace(/(\d+(?:\.\d+)?)\s*x\b/g, (_, num) => {
170
+ return `calc(var(--gap) * ${num})`;
171
+ });
172
+ }
173
+ /**
174
+ * Parse an advanced state key and return its type and components
175
+ */
176
+ function parseAdvancedState(stateKey, ctx) {
177
+ const raw = stateKey;
178
+ if (stateKey === "@starting") return {
179
+ type: "starting",
180
+ condition: "",
181
+ raw
182
+ };
183
+ if (stateKey.startsWith("@media:")) {
184
+ const mediaType = stateKey.slice(7);
185
+ if (![
186
+ "all",
187
+ "screen",
188
+ "print",
189
+ "speech"
190
+ ].includes(mediaType)) warnOnce(`unknown-media-type:${mediaType}`, `[Tasty] Unknown media type '${mediaType}'. Valid types: all, screen, print, speech.`);
191
+ return {
192
+ type: "media",
193
+ condition: "",
194
+ mediaType,
195
+ raw
196
+ };
197
+ }
198
+ if (stateKey.startsWith("@media(")) {
199
+ const endParen = findMatchingParen(stateKey, 6);
200
+ if (endParen === -1) {
201
+ warnOnce(`unclosed-media:${stateKey}`, `[Tasty] Unclosed media query '${stateKey}'. Missing closing parenthesis.`);
202
+ return {
203
+ type: "modifier",
204
+ condition: stateKey,
205
+ raw
206
+ };
207
+ }
208
+ let condition = stateKey.slice(7, endParen);
209
+ if (!condition.trim()) {
210
+ warnOnce(`empty-media:${stateKey}`, `[Tasty] Empty media query condition '${stateKey}'.`);
211
+ return {
212
+ type: "modifier",
213
+ condition: stateKey,
214
+ raw
215
+ };
216
+ }
217
+ condition = expandDimensionShorthands(condition);
218
+ condition = expandTastyUnits(condition);
219
+ return {
220
+ type: "media",
221
+ condition,
222
+ raw
223
+ };
224
+ }
225
+ if (stateKey.startsWith("@root(")) {
226
+ const endParen = findMatchingParen(stateKey, 5);
227
+ if (endParen === -1) {
228
+ warnOnce(`unclosed-root:${stateKey}`, `[Tasty] Unclosed root state '${stateKey}'. Missing closing parenthesis.`);
229
+ return {
230
+ type: "modifier",
231
+ condition: stateKey,
232
+ raw
233
+ };
234
+ }
235
+ const condition = stateKey.slice(6, endParen);
236
+ if (!condition.trim()) {
237
+ warnOnce(`empty-root:${stateKey}`, `[Tasty] Empty root state condition '${stateKey}'.`);
238
+ return {
239
+ type: "modifier",
240
+ condition: stateKey,
241
+ raw
242
+ };
243
+ }
244
+ return {
245
+ type: "root",
246
+ condition,
247
+ raw
248
+ };
249
+ }
250
+ if (stateKey.startsWith("@parent(")) {
251
+ const endParen = findMatchingParen(stateKey, 7);
252
+ if (endParen === -1) {
253
+ warnOnce(`unclosed-parent:${stateKey}`, `[Tasty] Unclosed parent state '${stateKey}'. Missing closing parenthesis.`);
254
+ return {
255
+ type: "modifier",
256
+ condition: stateKey,
257
+ raw
258
+ };
259
+ }
260
+ const condition = stateKey.slice(8, endParen);
261
+ if (!condition.trim()) {
262
+ warnOnce(`empty-parent:${stateKey}`, `[Tasty] Empty parent state condition '${stateKey}'.`);
263
+ return {
264
+ type: "modifier",
265
+ condition: stateKey,
266
+ raw
267
+ };
268
+ }
269
+ return {
270
+ type: "parent",
271
+ condition,
272
+ raw
273
+ };
274
+ }
275
+ if (stateKey.startsWith("@own(")) {
276
+ const endParen = findMatchingParen(stateKey, 4);
277
+ if (endParen === -1) {
278
+ warnOnce(`unclosed-own:${stateKey}`, `[Tasty] Unclosed own state '${stateKey}'. Missing closing parenthesis.`);
279
+ return {
280
+ type: "modifier",
281
+ condition: stateKey,
282
+ raw
283
+ };
284
+ }
285
+ const condition = stateKey.slice(5, endParen);
286
+ if (!condition.trim()) {
287
+ warnOnce(`empty-own:${stateKey}`, `[Tasty] Empty own state condition '${stateKey}'.`);
288
+ return {
289
+ type: "modifier",
290
+ condition: stateKey,
291
+ raw
292
+ };
293
+ }
294
+ if (!ctx.isSubElement) {
295
+ warnOnce(`own-outside-subelement:${stateKey}`, `[Tasty] @own(${condition}) used outside sub-element context.\n@own() is equivalent to '${condition}' at the root level. Did you mean to use it inside a sub-element?`);
296
+ return {
297
+ type: "modifier",
298
+ condition,
299
+ raw
300
+ };
301
+ }
302
+ return {
303
+ type: "own",
304
+ condition,
305
+ raw
306
+ };
307
+ }
308
+ if (stateKey.startsWith("@(")) {
309
+ const endParen = findMatchingParen(stateKey, 1);
310
+ if (endParen === -1) {
311
+ warnOnce(`unclosed-container:${stateKey}`, `[Tasty] Unclosed container query '${stateKey}'. Missing closing parenthesis.`);
312
+ return {
313
+ type: "modifier",
314
+ condition: stateKey,
315
+ raw
316
+ };
317
+ }
318
+ const content = stateKey.slice(2, endParen);
319
+ if (!content.trim()) {
320
+ warnOnce(`empty-container:${stateKey}`, `[Tasty] Empty container query '${stateKey}'.`);
321
+ return {
322
+ type: "modifier",
323
+ condition: stateKey,
324
+ raw
325
+ };
326
+ }
327
+ const commaIndex = findTopLevelComma(content);
328
+ let containerName;
329
+ let condition;
330
+ if (commaIndex !== -1) {
331
+ containerName = content.slice(0, commaIndex).trim();
332
+ condition = content.slice(commaIndex + 1).trim();
333
+ } else condition = content.trim();
334
+ if (condition.startsWith("$")) {
335
+ const styleCondition = parseStyleQuery(condition);
336
+ if (!styleCondition) {
337
+ warnOnce(`invalid-style-query:${stateKey}`, `[Tasty] Invalid style query '${condition}' in container query.`);
338
+ return {
339
+ type: "modifier",
340
+ condition: stateKey,
341
+ raw
342
+ };
343
+ }
344
+ condition = styleCondition;
345
+ } else if (/^[a-zA-Z][\w-]*\s*\(/.test(condition)) {} else {
346
+ condition = expandDimensionShorthands(condition);
347
+ condition = expandTastyUnits(condition);
348
+ }
349
+ return {
350
+ type: "container",
351
+ condition,
352
+ containerName,
353
+ raw
354
+ };
355
+ }
356
+ if (isPredefinedStateRef(stateKey)) {
357
+ const resolved = resolvePredefinedState(stateKey, ctx);
358
+ if (resolved) return {
359
+ ...parseAdvancedState(resolved, ctx),
360
+ raw
361
+ };
362
+ return {
363
+ type: "modifier",
364
+ condition: stateKey,
365
+ raw
366
+ };
367
+ }
368
+ return {
369
+ type: "modifier",
370
+ condition: stateKey,
371
+ raw
372
+ };
373
+ }
374
+ /**
375
+ * Parse a style query condition (e.g., $compact, $variant=compact, $variant="very compact")
376
+ */
377
+ function parseStyleQuery(condition) {
378
+ const query = condition.slice(1);
379
+ if (/[<>]/.test(query)) {
380
+ warnOnce(`style-query-comparison:${condition}`, `[Tasty] Style queries only support equality. '${condition}' is invalid. Use '${condition.split(/[<>]/)[0]}=...' instead.`);
381
+ return null;
382
+ }
383
+ const eqIndex = query.indexOf("=");
384
+ if (eqIndex === -1) return `style(--${query})`;
385
+ const propName = query.slice(0, eqIndex).trim();
386
+ let value = query.slice(eqIndex + 1).trim();
387
+ if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) {} else value = `"${value}"`;
388
+ value = expandTastyUnits(value);
389
+ return `style(--${propName}: ${value})`;
390
+ }
391
+ /**
392
+ * Find the index of the first comma at parentheses depth 0.
393
+ * Returns -1 if no top-level comma is found.
394
+ * This prevents splitting on commas inside function calls like scroll-state(a, b).
395
+ */
396
+ function findTopLevelComma(s) {
397
+ let depth = 0;
398
+ for (let i = 0; i < s.length; i++) if (s[i] === "(") depth++;
399
+ else if (s[i] === ")") depth--;
400
+ else if (s[i] === "," && depth === 0) return i;
401
+ return -1;
402
+ }
403
+ function findMatchingParen(str, startIndex) {
404
+ let depth = 1;
405
+ let i = startIndex + 1;
406
+ while (i < str.length && depth > 0) {
407
+ if (str[i] === "(") depth++;
408
+ else if (str[i] === ")") depth--;
409
+ i++;
410
+ }
411
+ return depth === 0 ? i - 1 : -1;
412
+ }
413
+
414
+ //#endregion
415
+ export { createStateParserContext, expandDimensionShorthands, expandTastyUnits, extractLocalPredefinedStates, extractPredefinedStateRefs, findTopLevelComma, getGlobalPredefinedStates, parseAdvancedState, resolvePredefinedState, setGlobalPredefinedStates };
416
+ //# sourceMappingURL=index.js.map