@tenphi/tasty 0.0.0-snapshot.27b6708 → 0.0.0-snapshot.28eb83c

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 (106) hide show
  1. package/README.md +38 -54
  2. package/dist/{babel-BUQGeOXA.d.ts → babel-D6lOuSwk.d.ts} +2 -2
  3. package/dist/chunks/async-storage-DKK-wTD4.js.map +1 -0
  4. package/dist/chunks/build-config-BBThSdlo.js +45 -0
  5. package/dist/chunks/build-config-BBThSdlo.js.map +1 -0
  6. package/dist/{collector-DTahQUiV.js → chunks/collector-DcViW2ZQ.js} +28 -14
  7. package/dist/chunks/collector-DcViW2ZQ.js.map +1 -0
  8. package/dist/chunks/config-engine-DQVQK4NU.js +403 -0
  9. package/dist/chunks/config-engine-DQVQK4NU.js.map +1 -0
  10. package/dist/chunks/css-definitions-BZ9vm0ci.js +1284 -0
  11. package/dist/chunks/css-definitions-BZ9vm0ci.js.map +1 -0
  12. package/dist/chunks/css-resources-Cyl_axbI.js +149 -0
  13. package/dist/chunks/css-resources-Cyl_axbI.js.map +1 -0
  14. package/dist/chunks/debug-Vyauml7U.js +583 -0
  15. package/dist/chunks/debug-Vyauml7U.js.map +1 -0
  16. package/dist/chunks/dsl-CXvoaLnj.js +2097 -0
  17. package/dist/chunks/dsl-CXvoaLnj.js.map +1 -0
  18. package/dist/chunks/hydration-CLdVKcH2.js +59 -0
  19. package/dist/chunks/hydration-CLdVKcH2.js.map +1 -0
  20. package/dist/chunks/react-runtime-so_X_yMo.js +1526 -0
  21. package/dist/chunks/react-runtime-so_X_yMo.js.map +1 -0
  22. package/dist/chunks/runtime-engine-DQ5laRou.js +3056 -0
  23. package/dist/chunks/runtime-engine-DQ5laRou.js.map +1 -0
  24. package/dist/{merge-styles-oklji0KB.js → chunks/shared-utils-OIg0N_dp.js} +42 -3
  25. package/dist/chunks/shared-utils-OIg0N_dp.js.map +1 -0
  26. package/dist/{config-B5kHzuNz.js → chunks/style-engine-CBuOt1e4.js} +2387 -7442
  27. package/dist/chunks/style-engine-CBuOt1e4.js.map +1 -0
  28. package/dist/{css-writer-B-J87ncv.js → chunks/zero-engine-BFh7gKbK.js} +3 -3
  29. package/dist/chunks/zero-engine-BFh7gKbK.js.map +1 -0
  30. package/dist/{collector-DUaHCcTS.d.ts → collector-CAmndLXe.d.ts} +23 -3
  31. package/dist/{config-YsxGv4tq.d.ts → config-BWYrv_Aa.d.ts} +141 -37
  32. package/dist/core/index.d.ts +5 -5
  33. package/dist/core/index.js +9 -6
  34. package/dist/{index-Cd45t5NM.d.ts → index-BzAC3p06.d.ts} +118 -23
  35. package/dist/{index-PqN-DIpn.d.ts → index-D4kRLj2o.d.ts} +128 -68
  36. package/dist/index.d.ts +5 -5
  37. package/dist/index.js +10 -922
  38. package/dist/{merge-styles-CU7JbEwg.d.ts → merge-styles-BFktNP8J.d.ts} +2 -2
  39. package/dist/ssr/astro-client.js +1 -1
  40. package/dist/ssr/astro-middleware-extract-static.d.ts +11 -0
  41. package/dist/ssr/astro-middleware-extract-static.js +9 -0
  42. package/dist/ssr/astro-middleware-extract-static.js.map +1 -0
  43. package/dist/ssr/astro-middleware-extract.d.ts +11 -0
  44. package/dist/ssr/astro-middleware-extract.js +9 -0
  45. package/dist/ssr/astro-middleware-extract.js.map +1 -0
  46. package/dist/ssr/astro-middleware-static.d.ts +3 -1
  47. package/dist/ssr/astro-middleware.d.ts +3 -1
  48. package/dist/ssr/astro.d.ts +45 -3
  49. package/dist/ssr/astro.js +157 -14
  50. package/dist/ssr/astro.js.map +1 -1
  51. package/dist/ssr/index.d.ts +7 -7
  52. package/dist/ssr/index.js +4 -4
  53. package/dist/ssr/index.js.map +1 -1
  54. package/dist/ssr/next-config.d.ts +66 -0
  55. package/dist/ssr/next-config.js +135 -0
  56. package/dist/ssr/next-config.js.map +1 -0
  57. package/dist/ssr/next.d.ts +9 -2
  58. package/dist/ssr/next.js +26 -10
  59. package/dist/ssr/next.js.map +1 -1
  60. package/dist/static/index.d.ts +2 -2
  61. package/dist/static/index.js +1 -1
  62. package/dist/zero/babel.d.ts +1 -1
  63. package/dist/zero/babel.js +25 -24
  64. package/dist/zero/babel.js.map +1 -1
  65. package/dist/zero/index.d.ts +1 -1
  66. package/dist/zero/index.js +1 -1
  67. package/dist/zero/next.d.ts +1 -1
  68. package/docs/README.md +5 -3
  69. package/docs/adoption.md +3 -3
  70. package/docs/ai-agents.md +83 -78
  71. package/docs/comparison.md +12 -12
  72. package/docs/configuration.md +47 -47
  73. package/docs/debug.md +19 -7
  74. package/docs/dsl.md +3 -3
  75. package/docs/getting-started.md +10 -10
  76. package/docs/injector.md +62 -25
  77. package/docs/methodology.md +3 -3
  78. package/docs/migration-v3.md +49 -49
  79. package/docs/plugins.md +37 -33
  80. package/docs/react-api.md +2 -2
  81. package/docs/runtime-benchmarks.md +351 -0
  82. package/docs/ssr.md +219 -61
  83. package/docs/styles.md +43 -11
  84. package/docs/tasty-static.md +136 -103
  85. package/package.json +80 -11
  86. package/dist/async-storage-DKK-wTD4.js.map +0 -1
  87. package/dist/collector-DTahQUiV.js.map +0 -1
  88. package/dist/config-B5kHzuNz.js.map +0 -1
  89. package/dist/context-CA8YKeMn.js +0 -24
  90. package/dist/context-CA8YKeMn.js.map +0 -1
  91. package/dist/core-Dr4u1NVD.js +0 -1566
  92. package/dist/core-Dr4u1NVD.js.map +0 -1
  93. package/dist/css-writer-B-J87ncv.js.map +0 -1
  94. package/dist/format-global-rules-DklyaXv-.js +0 -22
  95. package/dist/format-global-rules-DklyaXv-.js.map +0 -1
  96. package/dist/format-rules-DKOA-6qu.js +0 -130
  97. package/dist/format-rules-DKOA-6qu.js.map +0 -1
  98. package/dist/hydrate-OeMX99We.js +0 -37
  99. package/dist/hydrate-OeMX99We.js.map +0 -1
  100. package/dist/index.js.map +0 -1
  101. package/dist/keyframes-CV8azJf3.js +0 -493
  102. package/dist/keyframes-CV8azJf3.js.map +0 -1
  103. package/dist/merge-styles-oklji0KB.js.map +0 -1
  104. package/dist/resolve-recipes-DTG81rzl.js +0 -144
  105. package/dist/resolve-recipes-DTG81rzl.js.map +0 -1
  106. /package/dist/{async-storage-DKK-wTD4.js → chunks/async-storage-DKK-wTD4.js} +0 -0
@@ -0,0 +1,135 @@
1
+ import { H as formatFunctionRule, S as formatFontFaceRule, W as parseFunctionName, _ as formatCounterStyleRule, a as formatPropertyCSS, b as fontFaceContentHash, m as DEFAULT_PROPERTIES, n as formatGlobalRules, t as createServerStyleArtifact } from "../chunks/css-definitions-BZ9vm0ci.js";
2
+ import { b as renderStyles } from "../chunks/style-engine-CBuOt1e4.js";
3
+ import { n as functionsForExtraction, r as resetZeroConfig, t as configureZero } from "../chunks/build-config-BBThSdlo.js";
4
+ import { t as findUnsafeCSSResource } from "../chunks/css-resources-Cyl_axbI.js";
5
+ import { createHash } from "node:crypto";
6
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
7
+ import { createRequire } from "node:module";
8
+ import { isAbsolute, join, relative, resolve, sep } from "node:path";
9
+ //#region src/ssr/next-config.ts
10
+ /**
11
+ * Next.js configuration wrapper for extracting Tasty's configured global CSS.
12
+ *
13
+ * Import this Node-only module from `next.config.ts`. The client-safe registry
14
+ * remains available from `@tenphi/tasty/ssr/next`.
15
+ */
16
+ const ENV_KEY = "TASTY_NEXT_SHARED_CSS_HREF";
17
+ const packageRequire = createRequire(import.meta.url);
18
+ function loadConfig(projectDir, options) {
19
+ if (options.config) return options.config;
20
+ if (!options.configFile) throw new Error("[Tasty] withTastyNext() requires either `config` or `configFile`.");
21
+ const configPath = resolve(projectDir, options.configFile);
22
+ let jitiPath;
23
+ try {
24
+ jitiPath = packageRequire.resolve("jiti");
25
+ } catch (error) {
26
+ if (error instanceof Error && "code" in error && error.code === "MODULE_NOT_FOUND") throw new Error("[Tasty] `configFile` requires the optional `jiti` package. Install `jiti` or pass the imported config through `config` instead.", { cause: error });
27
+ throw error;
28
+ }
29
+ const { createJiti } = packageRequire(jitiPath);
30
+ const loaded = createJiti(projectDir, { moduleCache: false })(configPath);
31
+ return loaded && typeof loaded === "object" && "default" in loaded ? loaded.default : loaded;
32
+ }
33
+ function collectSharedCSS(config) {
34
+ resetZeroConfig();
35
+ try {
36
+ const resolved = configureZero(config);
37
+ const { normalized } = resolved;
38
+ const artifacts = [];
39
+ const append = (kind, key, css) => {
40
+ if (!css) return;
41
+ artifacts.push(createServerStyleArtifact(kind, key, css, artifacts.length));
42
+ };
43
+ for (const [token, definition] of Object.entries({
44
+ ...DEFAULT_PROPERTIES,
45
+ ...normalized.properties
46
+ })) append("property", `__prop:${token}`, formatPropertyCSS(token, definition));
47
+ for (const [family, input] of Object.entries(normalized.fontFaces)) {
48
+ const descriptors = Array.isArray(input) ? input : [input];
49
+ for (const descriptor of descriptors) append("font-face", fontFaceContentHash(family, descriptor), formatFontFaceRule(family, descriptor));
50
+ }
51
+ for (const [name, descriptors] of Object.entries(normalized.counterStyles)) append("counter-style", name, formatCounterStyleRule(name, descriptors));
52
+ for (const [name, definition] of Object.entries(functionsForExtraction(resolved) ?? {})) append("function", parseFunctionName(name), formatFunctionRule(name, definition));
53
+ if (Object.keys(normalized.tokens).length > 0) append("global", "__global:tokens", formatGlobalRules(renderStyles(normalized.tokens, ":root")));
54
+ for (const [selector, styles] of Object.entries(normalized.globalStyles)) {
55
+ if (Object.keys(styles).length === 0) continue;
56
+ const rules = renderStyles(styles, selector);
57
+ append("global", `__global:styles:${selector}`, formatGlobalRules(rules));
58
+ }
59
+ for (const artifact of artifacts) {
60
+ const unsafe = findUnsafeCSSResource(artifact.css, false);
61
+ if (unsafe) throw new Error(`[Tasty] Next.js shared CSS extraction cannot preserve page-relative CSS URL "${unsafe.url}" in ${artifact.kind} artifact ${artifact.id}. Use an absolute URL, a data URL, or a root-relative URL such as url(/path/to/asset).`);
62
+ }
63
+ return artifacts.map(({ css }) => css).join("\n");
64
+ } finally {
65
+ resetZeroConfig();
66
+ }
67
+ }
68
+ function inferPublicPath(projectDir, outputDir) {
69
+ const relativePath = relative(resolve(projectDir, "public"), outputDir);
70
+ if (relativePath === ".." || relativePath.startsWith(`..${sep}`) || isAbsolute(relativePath)) throw new Error("[Tasty] `publicPath` is required when `outputDir` is outside the Next.js public directory.");
71
+ return `/${relativePath.split(sep).filter(Boolean).join("/")}`;
72
+ }
73
+ function normalizeURLPath(path, option) {
74
+ if (!path.startsWith("/") || path.startsWith("//") || path.includes("?") || path.includes("#") || path.includes("\\")) throw new Error(`[Tasty] \`${option}\` must be a root-relative URL path.`);
75
+ let end = path.length;
76
+ while (end > 0 && path[end - 1] === "/") end--;
77
+ return path.slice(0, end);
78
+ }
79
+ function writeSharedCSS(outputDir, css) {
80
+ mkdirSync(outputDir, { recursive: true });
81
+ const filename = `tasty.shared.${createHash("sha256").update(css).digest("hex").slice(0, 12)}.css`;
82
+ const outputPath = join(outputDir, filename);
83
+ let existing;
84
+ try {
85
+ existing = readFileSync(outputPath, "utf8");
86
+ } catch {}
87
+ if (existing !== css) writeFileSync(outputPath, css);
88
+ return filename;
89
+ }
90
+ /**
91
+ * Add a cacheable, content-hashed stylesheet for Tasty configuration globals.
92
+ * Route-dependent component and hook styles continue to stream through
93
+ * `TastyRegistry` so App Router navigation and Suspense remain correct.
94
+ */
95
+ function withTastyNext(options) {
96
+ return (nextConfig = {}) => {
97
+ if (options.enabled === false) return nextConfig;
98
+ const projectDir = resolve(process.cwd(), options.rootDir ?? ".");
99
+ const outputDir = resolve(projectDir, options.outputDir ?? "public/_tasty");
100
+ const publicPath = normalizeURLPath(options.publicPath ?? inferPublicPath(projectDir, outputDir), "publicPath");
101
+ const basePath = normalizeURLPath(nextConfig.basePath || "/", "basePath");
102
+ const css = collectSharedCSS(loadConfig(projectDir, options));
103
+ if (!css) return nextConfig;
104
+ const filename = writeSharedCSS(outputDir, css);
105
+ const href = `${basePath}${publicPath}/${filename}`;
106
+ const headerSource = `${publicPath}/${filename}`;
107
+ const existingEnv = nextConfig.env ?? {};
108
+ const existingHeaders = nextConfig.headers;
109
+ if (existingEnv[ENV_KEY] && existingEnv[ENV_KEY] !== href) throw new Error(`[Tasty] Next.js env key ${ENV_KEY} is reserved by withTastyNext().`);
110
+ const generatedConfig = {
111
+ ...nextConfig,
112
+ env: {
113
+ ...existingEnv,
114
+ [ENV_KEY]: href
115
+ }
116
+ };
117
+ if (nextConfig.output === "export") return generatedConfig;
118
+ return {
119
+ ...generatedConfig,
120
+ async headers() {
121
+ return [...existingHeaders ? await existingHeaders() : [], {
122
+ source: headerSource,
123
+ headers: [{
124
+ key: "Cache-Control",
125
+ value: "public, max-age=31536000, immutable"
126
+ }]
127
+ }];
128
+ }
129
+ };
130
+ };
131
+ }
132
+ //#endregion
133
+ export { withTastyNext };
134
+
135
+ //# sourceMappingURL=next-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-config.js","names":[],"sources":["../../src/ssr/next-config.ts"],"sourcesContent":["/**\n * Next.js configuration wrapper for extracting Tasty's configured global CSS.\n *\n * Import this Node-only module from `next.config.ts`. The client-safe registry\n * remains available from `@tenphi/tasty/ssr/next`.\n */\n\nimport { createHash } from 'node:crypto';\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { isAbsolute, join, relative, resolve, sep } from 'node:path';\nimport type { createJiti as createJitiType } from 'jiti';\n\nimport type { TastyConfig } from '../config';\nimport { formatCounterStyleRule } from '../counter-style';\nimport { fontFaceContentHash, formatFontFaceRule } from '../font-face';\nimport { formatFunctionRule, parseFunctionName } from '../functions';\nimport { renderStyles } from '../pipeline';\nimport type { StyleResult } from '../pipeline';\nimport { DEFAULT_PROPERTIES } from '../properties/defaults';\nimport {\n configureZero,\n functionsForExtraction,\n resetZeroConfig,\n} from '../zero/config';\nimport { createServerStyleArtifact } from './artifacts';\nimport type { ServerStyleArtifact, ServerStyleArtifactKind } from './artifacts';\nimport { findUnsafeCSSResource } from './css-resources';\nimport { formatGlobalRules } from './format-global-rules';\nimport { formatPropertyCSS } from './format-property';\n\nconst ENV_KEY = 'TASTY_NEXT_SHARED_CSS_HREF';\nconst packageRequire = createRequire(import.meta.url);\n\ninterface NextConfig {\n basePath?: string;\n env?: Record<string, string | undefined>;\n headers?: () => Promise<NextHeader[]>;\n output?: string;\n [key: string]: unknown;\n}\n\ninterface NextHeader {\n source: string;\n headers: { key: string; value: string }[];\n [key: string]: unknown;\n}\n\nexport interface TastyNextOptions {\n /**\n * Next.js project directory. Useful when the build command runs from a\n * monorepo root rather than the app directory.\n *\n * @default process.cwd()\n */\n rootDir?: string;\n\n /**\n * Tasty configuration used to generate the shared stylesheet.\n * `config` takes precedence when both config sources are provided.\n */\n config?: TastyConfig;\n\n /**\n * Project-relative path to a TypeScript/JavaScript module whose default\n * export is a Tasty configuration object.\n *\n * @example './app/tasty.config.ts'\n */\n configFile?: string;\n\n /**\n * Filesystem directory for generated stylesheets. When it is inside the\n * project's `public` directory, its public URL is inferred automatically.\n *\n * @default 'public/_tasty'\n */\n outputDir?: string;\n\n /**\n * Root-relative URL path corresponding to `outputDir`. This is required\n * when `outputDir` is outside the project's `public` directory.\n * The Next.js `basePath` is prepended automatically.\n *\n * @default inferred from outputDir\n * @example '/assets/tasty'\n */\n publicPath?: string;\n\n /** Whether to generate and register the shared stylesheet. @default true */\n enabled?: boolean;\n}\n\nfunction loadConfig(\n projectDir: string,\n options: TastyNextOptions,\n): TastyConfig {\n if (options.config) return options.config;\n if (!options.configFile) {\n throw new Error(\n '[Tasty] withTastyNext() requires either `config` or `configFile`.',\n );\n }\n\n const configPath = resolve(projectDir, options.configFile);\n let jitiPath: string;\n try {\n jitiPath = packageRequire.resolve('jiti');\n } catch (error) {\n if (\n error instanceof Error &&\n 'code' in error &&\n error.code === 'MODULE_NOT_FOUND'\n ) {\n throw new Error(\n '[Tasty] `configFile` requires the optional `jiti` package. Install `jiti` or pass the imported config through `config` instead.',\n { cause: error },\n );\n }\n throw error;\n }\n const { createJiti } = packageRequire(jitiPath) as {\n createJiti: typeof createJitiType;\n };\n const jiti = createJiti(projectDir, { moduleCache: false });\n const loaded = jiti(configPath) as TastyConfig | { default: TastyConfig };\n\n return loaded && typeof loaded === 'object' && 'default' in loaded\n ? loaded.default\n : loaded;\n}\n\nfunction collectSharedCSS(config: TastyConfig): string {\n resetZeroConfig();\n try {\n const resolved = configureZero(config);\n const { normalized } = resolved;\n const artifacts: ServerStyleArtifact[] = [];\n const append = (\n kind: ServerStyleArtifactKind,\n key: string,\n css: string,\n ) => {\n if (!css) return;\n\n artifacts.push(\n createServerStyleArtifact(kind, key, css, artifacts.length),\n );\n };\n\n for (const [token, definition] of Object.entries({\n ...DEFAULT_PROPERTIES,\n ...normalized.properties,\n })) {\n append(\n 'property',\n `__prop:${token}`,\n formatPropertyCSS(token, definition),\n );\n }\n\n for (const [family, input] of Object.entries(normalized.fontFaces)) {\n const descriptors = Array.isArray(input) ? input : [input];\n for (const descriptor of descriptors) {\n append(\n 'font-face',\n fontFaceContentHash(family, descriptor),\n formatFontFaceRule(family, descriptor),\n );\n }\n }\n\n for (const [name, descriptors] of Object.entries(\n normalized.counterStyles,\n )) {\n append('counter-style', name, formatCounterStyleRule(name, descriptors));\n }\n\n for (const [name, definition] of Object.entries(\n functionsForExtraction(resolved) ?? {},\n )) {\n append(\n 'function',\n parseFunctionName(name),\n formatFunctionRule(name, definition),\n );\n }\n\n if (Object.keys(normalized.tokens).length > 0) {\n const rules = renderStyles(normalized.tokens, ':root') as StyleResult[];\n append('global', '__global:tokens', formatGlobalRules(rules));\n }\n\n for (const [selector, styles] of Object.entries(normalized.globalStyles)) {\n if (Object.keys(styles).length === 0) continue;\n const rules = renderStyles(styles, selector) as StyleResult[];\n append('global', `__global:styles:${selector}`, formatGlobalRules(rules));\n }\n\n for (const artifact of artifacts) {\n const unsafe = findUnsafeCSSResource(artifact.css, false);\n if (unsafe) {\n throw new Error(\n `[Tasty] Next.js shared CSS extraction cannot preserve page-relative CSS URL \"${unsafe.url}\" in ${artifact.kind} artifact ${artifact.id}. Use an absolute URL, a data URL, or a root-relative URL such as url(/path/to/asset).`,\n );\n }\n }\n\n return artifacts.map(({ css }) => css).join('\\n');\n } finally {\n resetZeroConfig();\n }\n}\n\nfunction inferPublicPath(projectDir: string, outputDir: string): string {\n const publicDir = resolve(projectDir, 'public');\n const relativePath = relative(publicDir, outputDir);\n if (\n relativePath === '..' ||\n relativePath.startsWith(`..${sep}`) ||\n isAbsolute(relativePath)\n ) {\n throw new Error(\n '[Tasty] `publicPath` is required when `outputDir` is outside the Next.js public directory.',\n );\n }\n\n return `/${relativePath.split(sep).filter(Boolean).join('/')}`;\n}\n\nfunction normalizeURLPath(path: string, option: string): string {\n if (\n !path.startsWith('/') ||\n path.startsWith('//') ||\n path.includes('?') ||\n path.includes('#') ||\n path.includes('\\\\')\n ) {\n throw new Error(`[Tasty] \\`${option}\\` must be a root-relative URL path.`);\n }\n\n let end = path.length;\n while (end > 0 && path[end - 1] === '/') end--;\n return path.slice(0, end);\n}\n\nfunction writeSharedCSS(outputDir: string, css: string): string {\n mkdirSync(outputDir, { recursive: true });\n const hash = createHash('sha256').update(css).digest('hex').slice(0, 12);\n const filename = `tasty.shared.${hash}.css`;\n\n const outputPath = join(outputDir, filename);\n let existing: string | undefined;\n try {\n existing = readFileSync(outputPath, 'utf8');\n } catch {\n // The file does not exist yet (or is unreadable); write it below.\n }\n if (existing !== css) writeFileSync(outputPath, css);\n\n return filename;\n}\n\n/**\n * Add a cacheable, content-hashed stylesheet for Tasty configuration globals.\n * Route-dependent component and hook styles continue to stream through\n * `TastyRegistry` so App Router navigation and Suspense remain correct.\n */\nexport function withTastyNext(options: TastyNextOptions) {\n return (nextConfig: NextConfig = {}): NextConfig => {\n if (options.enabled === false) return nextConfig;\n\n const projectDir = resolve(process.cwd(), options.rootDir ?? '.');\n const outputDir = resolve(projectDir, options.outputDir ?? 'public/_tasty');\n const publicPath = normalizeURLPath(\n options.publicPath ?? inferPublicPath(projectDir, outputDir),\n 'publicPath',\n );\n const basePath = normalizeURLPath(nextConfig.basePath || '/', 'basePath');\n const css = collectSharedCSS(loadConfig(projectDir, options));\n\n if (!css) return nextConfig;\n\n const filename = writeSharedCSS(outputDir, css);\n const href = `${basePath}${publicPath}/${filename}`;\n const headerSource = `${publicPath}/${filename}`;\n const existingEnv = nextConfig.env ?? {};\n const existingHeaders = nextConfig.headers;\n if (existingEnv[ENV_KEY] && existingEnv[ENV_KEY] !== href) {\n throw new Error(\n `[Tasty] Next.js env key ${ENV_KEY} is reserved by withTastyNext().`,\n );\n }\n\n const generatedConfig: NextConfig = {\n ...nextConfig,\n env: {\n ...existingEnv,\n [ENV_KEY]: href,\n },\n };\n\n // `headers()` is not emitted by Next's static export. Avoid introducing an\n // unsupported-config warning; the content hash still makes the asset safe\n // for the static host to cache immutably.\n if (nextConfig.output === 'export') return generatedConfig;\n\n return {\n ...generatedConfig,\n async headers() {\n const headers = existingHeaders ? await existingHeaders() : [];\n return [\n ...headers,\n {\n source: headerSource,\n headers: [\n {\n key: 'Cache-Control',\n value: 'public, max-age=31536000, immutable',\n },\n ],\n },\n ];\n },\n };\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;AA+BA,MAAM,UAAU;AAChB,MAAM,iBAAiB,cAAc,OAAO,KAAK,GAAG;AA6DpD,SAAS,WACP,YACA,SACa;CACb,IAAI,QAAQ,QAAQ,OAAO,QAAQ;CACnC,IAAI,CAAC,QAAQ,YACX,MAAM,IAAI,MACR,mEACF;CAGF,MAAM,aAAa,QAAQ,YAAY,QAAQ,UAAU;CACzD,IAAI;CACJ,IAAI;EACF,WAAW,eAAe,QAAQ,MAAM;CAC1C,SAAS,OAAO;EACd,IACE,iBAAiB,SACjB,UAAU,SACV,MAAM,SAAS,oBAEf,MAAM,IAAI,MACR,mIACA,EAAE,OAAO,MAAM,CACjB;EAEF,MAAM;CACR;CACA,MAAM,EAAE,eAAe,eAAe,QAAQ;CAI9C,MAAM,SADO,WAAW,YAAY,EAAE,aAAa,MAAM,CACvC,CAAC,CAAC,UAAU;CAE9B,OAAO,UAAU,OAAO,WAAW,YAAY,aAAa,SACxD,OAAO,UACP;AACN;AAEA,SAAS,iBAAiB,QAA6B;CACrD,gBAAgB;CAChB,IAAI;EACF,MAAM,WAAW,cAAc,MAAM;EACrC,MAAM,EAAE,eAAe;EACvB,MAAM,YAAmC,CAAC;EAC1C,MAAM,UACJ,MACA,KACA,QACG;GACH,IAAI,CAAC,KAAK;GAEV,UAAU,KACR,0BAA0B,MAAM,KAAK,KAAK,UAAU,MAAM,CAC5D;EACF;EAEA,KAAK,MAAM,CAAC,OAAO,eAAe,OAAO,QAAQ;GAC/C,GAAG;GACH,GAAG,WAAW;EAChB,CAAC,GACC,OACE,YACA,UAAU,SACV,kBAAkB,OAAO,UAAU,CACrC;EAGF,KAAK,MAAM,CAAC,QAAQ,UAAU,OAAO,QAAQ,WAAW,SAAS,GAAG;GAClE,MAAM,cAAc,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;GACzD,KAAK,MAAM,cAAc,aACvB,OACE,aACA,oBAAoB,QAAQ,UAAU,GACtC,mBAAmB,QAAQ,UAAU,CACvC;EAEJ;EAEA,KAAK,MAAM,CAAC,MAAM,gBAAgB,OAAO,QACvC,WAAW,aACb,GACE,OAAO,iBAAiB,MAAM,uBAAuB,MAAM,WAAW,CAAC;EAGzE,KAAK,MAAM,CAAC,MAAM,eAAe,OAAO,QACtC,uBAAuB,QAAQ,KAAK,CAAC,CACvC,GACE,OACE,YACA,kBAAkB,IAAI,GACtB,mBAAmB,MAAM,UAAU,CACrC;EAGF,IAAI,OAAO,KAAK,WAAW,MAAM,CAAC,CAAC,SAAS,GAE1C,OAAO,UAAU,mBAAmB,kBADtB,aAAa,WAAW,QAAQ,OACY,CAAC,CAAC;EAG9D,KAAK,MAAM,CAAC,UAAU,WAAW,OAAO,QAAQ,WAAW,YAAY,GAAG;GACxE,IAAI,OAAO,KAAK,MAAM,CAAC,CAAC,WAAW,GAAG;GACtC,MAAM,QAAQ,aAAa,QAAQ,QAAQ;GAC3C,OAAO,UAAU,mBAAmB,YAAY,kBAAkB,KAAK,CAAC;EAC1E;EAEA,KAAK,MAAM,YAAY,WAAW;GAChC,MAAM,SAAS,sBAAsB,SAAS,KAAK,KAAK;GACxD,IAAI,QACF,MAAM,IAAI,MACR,gFAAgF,OAAO,IAAI,OAAO,SAAS,KAAK,YAAY,SAAS,GAAG,uFAC1I;EAEJ;EAEA,OAAO,UAAU,KAAK,EAAE,UAAU,GAAG,CAAC,CAAC,KAAK,IAAI;CAClD,UAAU;EACR,gBAAgB;CAClB;AACF;AAEA,SAAS,gBAAgB,YAAoB,WAA2B;CAEtE,MAAM,eAAe,SADH,QAAQ,YAAY,QACA,GAAG,SAAS;CAClD,IACE,iBAAiB,QACjB,aAAa,WAAW,KAAK,KAAK,KAClC,WAAW,YAAY,GAEvB,MAAM,IAAI,MACR,4FACF;CAGF,OAAO,IAAI,aAAa,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AAC7D;AAEA,SAAS,iBAAiB,MAAc,QAAwB;CAC9D,IACE,CAAC,KAAK,WAAW,GAAG,KACpB,KAAK,WAAW,IAAI,KACpB,KAAK,SAAS,GAAG,KACjB,KAAK,SAAS,GAAG,KACjB,KAAK,SAAS,IAAI,GAElB,MAAM,IAAI,MAAM,aAAa,OAAO,qCAAqC;CAG3E,IAAI,MAAM,KAAK;CACf,OAAO,MAAM,KAAK,KAAK,MAAM,OAAO,KAAK;CACzC,OAAO,KAAK,MAAM,GAAG,GAAG;AAC1B;AAEA,SAAS,eAAe,WAAmB,KAAqB;CAC9D,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;CAExC,MAAM,WAAW,gBADJ,WAAW,QAAQ,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,EACjC,EAAE;CAEtC,MAAM,aAAa,KAAK,WAAW,QAAQ;CAC3C,IAAI;CACJ,IAAI;EACF,WAAW,aAAa,YAAY,MAAM;CAC5C,QAAQ,CAER;CACA,IAAI,aAAa,KAAK,cAAc,YAAY,GAAG;CAEnD,OAAO;AACT;;;;;;AAOA,SAAgB,cAAc,SAA2B;CACvD,QAAQ,aAAyB,CAAC,MAAkB;EAClD,IAAI,QAAQ,YAAY,OAAO,OAAO;EAEtC,MAAM,aAAa,QAAQ,QAAQ,IAAI,GAAG,QAAQ,WAAW,GAAG;EAChE,MAAM,YAAY,QAAQ,YAAY,QAAQ,aAAa,eAAe;EAC1E,MAAM,aAAa,iBACjB,QAAQ,cAAc,gBAAgB,YAAY,SAAS,GAC3D,YACF;EACA,MAAM,WAAW,iBAAiB,WAAW,YAAY,KAAK,UAAU;EACxE,MAAM,MAAM,iBAAiB,WAAW,YAAY,OAAO,CAAC;EAE5D,IAAI,CAAC,KAAK,OAAO;EAEjB,MAAM,WAAW,eAAe,WAAW,GAAG;EAC9C,MAAM,OAAO,GAAG,WAAW,WAAW,GAAG;EACzC,MAAM,eAAe,GAAG,WAAW,GAAG;EACtC,MAAM,cAAc,WAAW,OAAO,CAAC;EACvC,MAAM,kBAAkB,WAAW;EACnC,IAAI,YAAY,YAAY,YAAY,aAAa,MACnD,MAAM,IAAI,MACR,2BAA2B,QAAQ,iCACrC;EAGF,MAAM,kBAA8B;GAClC,GAAG;GACH,KAAK;IACH,GAAG;KACF,UAAU;GACb;EACF;EAKA,IAAI,WAAW,WAAW,UAAU,OAAO;EAE3C,OAAO;GACL,GAAG;GACH,MAAM,UAAU;IAEd,OAAO,CACL,GAFc,kBAAkB,MAAM,gBAAgB,IAAI,CAAC,GAG3D;KACE,QAAQ;KACR,SAAS,CACP;MACE,KAAK;MACL,OAAO;KACT,CACF;IACF,CACF;GACF;EACF;CACF;AACF"}
@@ -1,4 +1,4 @@
1
- import { t as ServerStyleCollector } from "../collector-DUaHCcTS.js";
1
+ import { t as ServerStyleCollector } from "../collector-CAmndLXe.js";
2
2
  import { ReactNode } from "react";
3
3
 
4
4
  //#region src/ssr/next.d.ts
@@ -11,6 +11,12 @@ interface TastyRegistryProps {
11
11
  * in server-rendered `<style>` tags. Default: true.
12
12
  */
13
13
  transferCache?: boolean;
14
+ /**
15
+ * URL of a stylesheet containing Tasty's configured global CSS.
16
+ * `withTastyNext()` sets this automatically. Pass false to disable it for
17
+ * this registry, or a URL to use a manually generated stylesheet.
18
+ */
19
+ sharedStylesheet?: string | false;
14
20
  }
15
21
  /**
16
22
  * Next.js App Router registry for Tasty SSR.
@@ -38,7 +44,8 @@ interface TastyRegistryProps {
38
44
  */
39
45
  declare function TastyRegistry({
40
46
  children,
41
- transferCache
47
+ transferCache,
48
+ sharedStylesheet
42
49
  }: TastyRegistryProps): import("react").FunctionComponentElement<import("react").ProviderProps<ServerStyleCollector | null>>;
43
50
  //#endregion
44
51
  export { TastyRegistry, TastyRegistryProps };
package/dist/ssr/next.js CHANGED
@@ -1,9 +1,8 @@
1
1
  "use client";
2
- import { n as getConfig } from "../config-B5kHzuNz.js";
3
- import { i as registerSSRCollectorGetter } from "../format-rules-DKOA-6qu.js";
4
- import { t as getTastySSRContext } from "../context-CA8YKeMn.js";
5
- import { t as ServerStyleCollector } from "../collector-DTahQUiV.js";
6
- import { t as hydrateTastyClasses } from "../hydrate-OeMX99We.js";
2
+ import { j as getConfig, o as registerSSRCollectorGetter } from "../chunks/runtime-engine-DQ5laRou.js";
3
+ import { u as getTastySSRContext } from "../chunks/react-runtime-so_X_yMo.js";
4
+ import { t as ServerStyleCollector } from "../chunks/collector-DcViW2ZQ.js";
5
+ import { t as hydrateTastyClasses } from "../chunks/hydration-CLdVKcH2.js";
7
6
  import { Fragment, createElement, useState } from "react";
8
7
  import { useServerInsertedHTML } from "next/navigation";
9
8
  //#region src/ssr/next.ts
@@ -39,32 +38,49 @@ if (typeof window !== "undefined") hydrateTastyClasses();
39
38
  * }
40
39
  * ```
41
40
  */
42
- function TastyRegistry({ children, transferCache = true }) {
41
+ function TastyRegistry({ children, transferCache = true, sharedStylesheet = process.env.TASTY_NEXT_SHARED_CSS_HREF }) {
43
42
  const isClient = typeof window !== "undefined";
44
43
  const [collector] = useState(() => {
45
44
  if (isClient) return null;
46
45
  const instance = new ServerStyleCollector();
47
46
  registerSSRCollectorGetter(() => instance);
47
+ if (sharedStylesheet) {
48
+ instance.collectInternals();
49
+ instance.flushCSS();
50
+ }
48
51
  return instance;
49
52
  });
53
+ const [streamState] = useState(() => ({ sharedStylesheetFlushed: false }));
50
54
  const nonce = getConfig().nonce;
51
55
  useServerInsertedHTML(() => {
52
56
  if (!collector) return null;
53
57
  const css = collector.flushCSS();
54
58
  const classNames = collector.getRenderedClassNames();
55
- if (!css) return null;
59
+ let linkEl = null;
60
+ if (sharedStylesheet && !streamState.sharedStylesheetFlushed) {
61
+ streamState.sharedStylesheetFlushed = true;
62
+ linkEl = createElement("link", {
63
+ key: "tasty-shared-styles",
64
+ rel: "stylesheet",
65
+ href: sharedStylesheet,
66
+ "data-tasty-ssr": "",
67
+ nonce
68
+ });
69
+ }
70
+ if (!css) return linkEl;
56
71
  const styleEl = createElement("style", {
57
72
  key: "tasty-ssr-styles",
58
73
  "data-tasty-ssr": "",
59
74
  nonce,
60
75
  dangerouslySetInnerHTML: { __html: css }
61
76
  });
62
- if (!transferCache || classNames.length === 0) return styleEl;
63
- return createElement(Fragment, null, styleEl, createElement("script", {
77
+ if (!transferCache || classNames.length === 0) return linkEl ? createElement(Fragment, null, linkEl, styleEl) : styleEl;
78
+ const scriptEl = createElement("script", {
64
79
  key: "tasty-ssr-cache",
65
80
  nonce,
66
81
  dangerouslySetInnerHTML: { __html: `(window.__TASTY__=window.__TASTY__||[]).push(${classNames.map((n) => `"${n}"`).join(",")})` }
67
- }));
82
+ });
83
+ return createElement(Fragment, null, linkEl, styleEl, scriptEl);
68
84
  });
69
85
  return createElement(getTastySSRContext().Provider, { value: collector }, children);
70
86
  }
@@ -1 +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 *\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 { getTastySSRContext } from './context';\nimport { hydrateTastyClasses } from './hydrate';\nimport { registerSSRCollectorGetter } from './ssr-collector-ref';\n\n// Auto-hydrate on module load (client only).\n// Reads the class name list from `window.__TASTY__` populated by streaming scripts.\nif (typeof window !== 'undefined') {\n hydrateTastyClasses();\n}\n\nexport interface TastyRegistryProps {\n children: ReactNode;\n /**\n * Whether to embed the class-list script for client hydration.\n * Set to false to skip class transfer (e.g. for CSP restrictions).\n * Without it, client components may re-inject CSS that already exists\n * in server-rendered `<style>` tags. 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 if (isClient) return null;\n\n const instance = new ServerStyleCollector();\n\n registerSSRCollectorGetter(() => instance);\n\n return instance;\n });\n const nonce = getConfig().nonce;\n\n useServerInsertedHTML(() => {\n if (!collector) return null;\n\n const css = collector.flushCSS();\n const classNames = collector.getRenderedClassNames();\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 || classNames.length === 0) return styleEl;\n\n const classListJSON = classNames.map((n) => `\"${n}\"`).join(',');\n\n const scriptEl = createElement('script', {\n key: 'tasty-ssr-cache',\n nonce,\n dangerouslySetInnerHTML: {\n __html: `(window.__TASTY__=window.__TASTY__||[]).push(${classListJSON})`,\n },\n });\n\n return createElement(Fragment, null, styleEl, scriptEl);\n });\n\n return createElement(\n getTastySSRContext().Provider,\n { value: collector },\n children,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,IAAI,OAAO,WAAW,aACpB,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;AAsCtB,SAAgB,cAAc,EAC5B,UACA,gBAAgB,QACK;CACrB,MAAM,WAAW,OAAO,WAAW;CAEnC,MAAM,CAAC,aAAa,eAAe;EACjC,IAAI,UAAU,OAAO;EAErB,MAAM,WAAW,IAAI,qBAAqB;EAE1C,iCAAiC,QAAQ;EAEzC,OAAO;CACT,CAAC;CACD,MAAM,QAAQ,UAAU,CAAC,CAAC;CAE1B,4BAA4B;EAC1B,IAAI,CAAC,WAAW,OAAO;EAEvB,MAAM,MAAM,UAAU,SAAS;EAC/B,MAAM,aAAa,UAAU,sBAAsB;EAEnD,IAAI,CAAC,KAAK,OAAO;EAEjB,MAAM,UAAU,cAAc,SAAS;GACrC,KAAK;GACL,kBAAkB;GAClB;GACA,yBAAyB,EAAE,QAAQ,IAAI;EACzC,CAAC;EAED,IAAI,CAAC,iBAAiB,WAAW,WAAW,GAAG,OAAO;EAYtD,OAAO,cAAc,UAAU,MAAM,SARpB,cAAc,UAAU;GACvC,KAAK;GACL;GACA,yBAAyB,EACvB,QAAQ,gDANU,WAAW,KAAK,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,GAMa,EAAE,GACxE;EACF,CAEqD,CAAC;CACxD,CAAC;CAED,OAAO,cACL,mBAAmB,CAAC,CAAC,UACrB,EAAE,OAAO,UAAU,GACnB,QACF;AACF"}
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 *\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 { getTastySSRContext } from './context';\nimport { hydrateTastyClasses } from './hydrate';\nimport { registerSSRCollectorGetter } from './ssr-collector-ref';\n\n// Auto-hydrate on module load (client only).\n// Reads the class name list from `window.__TASTY__` populated by streaming scripts.\nif (typeof window !== 'undefined') {\n hydrateTastyClasses();\n}\n\nexport interface TastyRegistryProps {\n children: ReactNode;\n /**\n * Whether to embed the class-list script for client hydration.\n * Set to false to skip class transfer (e.g. for CSP restrictions).\n * Without it, client components may re-inject CSS that already exists\n * in server-rendered `<style>` tags. Default: true.\n */\n transferCache?: boolean;\n /**\n * URL of a stylesheet containing Tasty's configured global CSS.\n * `withTastyNext()` sets this automatically. Pass false to disable it for\n * this registry, or a URL to use a manually generated stylesheet.\n */\n sharedStylesheet?: string | false;\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 sharedStylesheet = process.env.TASTY_NEXT_SHARED_CSS_HREF,\n}: TastyRegistryProps) {\n const isClient = typeof window !== 'undefined';\n\n const [collector] = useState(() => {\n if (isClient) return null;\n\n const instance = new ServerStyleCollector();\n\n registerSSRCollectorGetter(() => instance);\n\n // The generated stylesheet already contains configured global artifacts.\n // Mark that first batch as flushed so only request-specific styles stream.\n if (sharedStylesheet) {\n instance.collectInternals();\n instance.flushCSS();\n }\n\n return instance;\n });\n const [streamState] = useState(() => ({ sharedStylesheetFlushed: false }));\n const nonce = getConfig().nonce;\n\n useServerInsertedHTML(() => {\n if (!collector) return null;\n\n const css = collector.flushCSS();\n const classNames = collector.getRenderedClassNames();\n\n let linkEl = null;\n if (sharedStylesheet && !streamState.sharedStylesheetFlushed) {\n streamState.sharedStylesheetFlushed = true;\n linkEl = createElement('link', {\n key: 'tasty-shared-styles',\n rel: 'stylesheet',\n href: sharedStylesheet,\n 'data-tasty-ssr': '',\n nonce,\n });\n }\n\n if (!css) return linkEl;\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 || classNames.length === 0) {\n return linkEl ? createElement(Fragment, null, linkEl, styleEl) : styleEl;\n }\n\n const classListJSON = classNames.map((n) => `\"${n}\"`).join(',');\n\n const scriptEl = createElement('script', {\n key: 'tasty-ssr-cache',\n nonce,\n dangerouslySetInnerHTML: {\n __html: `(window.__TASTY__=window.__TASTY__||[]).push(${classListJSON})`,\n },\n });\n\n return createElement(Fragment, null, linkEl, styleEl, scriptEl);\n });\n\n return createElement(\n getTastySSRContext().Provider,\n { value: collector },\n children,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AAuBA,IAAI,OAAO,WAAW,aACpB,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;AA4CtB,SAAgB,cAAc,EAC5B,UACA,gBAAgB,MAChB,mBAAmB,QAAQ,IAAI,8BACV;CACrB,MAAM,WAAW,OAAO,WAAW;CAEnC,MAAM,CAAC,aAAa,eAAe;EACjC,IAAI,UAAU,OAAO;EAErB,MAAM,WAAW,IAAI,qBAAqB;EAE1C,iCAAiC,QAAQ;EAIzC,IAAI,kBAAkB;GACpB,SAAS,iBAAiB;GAC1B,SAAS,SAAS;EACpB;EAEA,OAAO;CACT,CAAC;CACD,MAAM,CAAC,eAAe,gBAAgB,EAAE,yBAAyB,MAAM,EAAE;CACzE,MAAM,QAAQ,UAAU,CAAC,CAAC;CAE1B,4BAA4B;EAC1B,IAAI,CAAC,WAAW,OAAO;EAEvB,MAAM,MAAM,UAAU,SAAS;EAC/B,MAAM,aAAa,UAAU,sBAAsB;EAEnD,IAAI,SAAS;EACb,IAAI,oBAAoB,CAAC,YAAY,yBAAyB;GAC5D,YAAY,0BAA0B;GACtC,SAAS,cAAc,QAAQ;IAC7B,KAAK;IACL,KAAK;IACL,MAAM;IACN,kBAAkB;IAClB;GACF,CAAC;EACH;EAEA,IAAI,CAAC,KAAK,OAAO;EAEjB,MAAM,UAAU,cAAc,SAAS;GACrC,KAAK;GACL,kBAAkB;GAClB;GACA,yBAAyB,EAAE,QAAQ,IAAI;EACzC,CAAC;EAED,IAAI,CAAC,iBAAiB,WAAW,WAAW,GAC1C,OAAO,SAAS,cAAc,UAAU,MAAM,QAAQ,OAAO,IAAI;EAKnE,MAAM,WAAW,cAAc,UAAU;GACvC,KAAK;GACL;GACA,yBAAyB,EACvB,QAAQ,gDANU,WAAW,KAAK,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,GAMa,EAAE,GACxE;EACF,CAAC;EAED,OAAO,cAAc,UAAU,MAAM,QAAQ,SAAS,QAAQ;CAChE,CAAC;CAED,OAAO,cACL,mBAAmB,CAAC,CAAC,UACrB,EAAE,OAAO,UAAU,GACnB,QACF;AACF"}
@@ -1,5 +1,5 @@
1
- import { b as Styles } from "../index-Cd45t5NM.js";
2
- import { t as mergeStyles } from "../merge-styles-CU7JbEwg.js";
1
+ import { b as Styles } from "../index-BzAC3p06.js";
2
+ import { t as mergeStyles } from "../merge-styles-BFktNP8J.js";
3
3
 
4
4
  //#region src/static/types.d.ts
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { t as mergeStyles } from "../merge-styles-oklji0KB.js";
1
+ import { t as mergeStyles } from "../chunks/shared-utils-OIg0N_dp.js";
2
2
  //#region src/static/types.ts
3
3
  /**
4
4
  * Create a StaticStyle object.
@@ -1,2 +1,2 @@
1
- import { n as _default, r as TastyZeroConfig, t as TastyZeroBabelOptions } from "../babel-BUQGeOXA.js";
1
+ import { n as _default, r as TastyZeroConfig, t as TastyZeroBabelOptions } from "../babel-D6lOuSwk.js";
2
2
  export { TastyZeroBabelOptions, type TastyZeroConfig, _default as default };
@@ -1,7 +1,8 @@
1
- import { b as resetConfig, d as getGlobalStyles, i as getGlobalConfigTokens, s as getGlobalFunctions, t as configure } from "../config-B5kHzuNz.js";
2
- import { t as mergeStyles } from "../merge-styles-oklji0KB.js";
3
- import { t as resolveRecipes } from "../resolve-recipes-DTG81rzl.js";
4
- import { a as extractFunctionsFromStyles, c as extractStylesForSelector, i as extractFontFaceFromStyles, l as extractStylesWithChunks, o as extractKeyframesFromStyles, r as extractCounterStyleFromStyles, s as extractPropertiesFromStyles, t as CSSWriter, u as setExtractorNamePrefix } from "../css-writer-B-J87ncv.js";
1
+ import { t as mergeStyles } from "../chunks/shared-utils-OIg0N_dp.js";
2
+ import "../chunks/css-definitions-BZ9vm0ci.js";
3
+ import { t as resolveRecipesWith } from "../chunks/config-engine-DQVQK4NU.js";
4
+ import { a as extractFunctionsFromStyles, c as extractStylesForSelector, i as extractFontFaceFromStyles, l as extractStylesWithChunks, o as extractKeyframesFromStyles, r as extractCounterStyleFromStyles, s as extractPropertiesFromStyles, t as CSSWriter, u as setExtractorNamePrefix } from "../chunks/zero-engine-BFh7gKbK.js";
5
+ import { n as functionsForExtraction, r as resetZeroConfig, t as configureZero } from "../chunks/build-config-BBThSdlo.js";
5
6
  import * as fs from "fs";
6
7
  import * as path from "path";
7
8
  import { declare } from "@babel/helper-plugin-utils";
@@ -87,19 +88,18 @@ var babel_default = declare((api, options) => {
87
88
  resolvedConfig = loaded && typeof loaded === "object" && "default" in loaded ? loaded.default : loaded;
88
89
  } else resolvedConfig = {};
89
90
  const devMode = resolvedConfig.devMode ?? false;
90
- if (cached) resetConfig();
91
+ resetZeroConfig();
91
92
  const finalConfig = {
92
93
  namePrefix: "ts",
93
94
  ...resolvedConfig
94
95
  };
95
- configure(finalConfig);
96
+ const config = configureZero(finalConfig);
96
97
  setExtractorNamePrefix(finalConfig.namePrefix ?? "ts");
97
98
  const newWriter = new CSSWriter(outputPath, { devMode });
98
99
  if (mode !== "inject") {
99
- const tokenCSS = extractCSSFromStyles(":root", getGlobalConfigTokens());
100
+ const tokenCSS = extractCSSFromStyles(":root", config.normalized.tokens);
100
101
  if (tokenCSS) newWriter.add(":root:tokens", tokenCSS);
101
- const globalStyles = getGlobalStyles();
102
- if (globalStyles) for (const [selector, styles] of Object.entries(globalStyles)) {
102
+ for (const [selector, styles] of Object.entries(config.normalized.globalStyles)) {
103
103
  const css = extractCSSFromStyles(selector, styles);
104
104
  if (css) newWriter.add(`global:${selector}`, css);
105
105
  }
@@ -108,21 +108,22 @@ var babel_default = declare((api, options) => {
108
108
  writer: newWriter,
109
109
  configKey,
110
110
  registry: {},
111
- config: finalConfig
111
+ config
112
112
  });
113
113
  }
114
114
  const entry = writerCache.get(resolvedOutputPath);
115
115
  const cssWriter = entry.writer;
116
116
  const globalRegistry = entry.registry;
117
117
  const config = entry.config;
118
- const devMode = config.devMode ?? false;
119
- setExtractorNamePrefix(config.namePrefix ?? "ts");
118
+ const sourceConfig = config.source;
119
+ const devMode = sourceConfig.devMode ?? false;
120
+ setExtractorNamePrefix(sourceConfig.namePrefix ?? "ts");
120
121
  let tokenCSS;
121
122
  let globalStylesCSS;
122
123
  if (mode === "inject") {
123
- tokenCSS = extractCSSFromStyles(":root", getGlobalConfigTokens());
124
- const gs = getGlobalStyles();
125
- if (gs) {
124
+ tokenCSS = extractCSSFromStyles(":root", config.normalized.tokens);
125
+ const gs = config.normalized.globalStyles;
126
+ if (Object.keys(gs).length > 0) {
126
127
  globalStylesCSS = /* @__PURE__ */ new Map();
127
128
  for (const [selector, styles] of Object.entries(gs)) {
128
129
  const css = extractCSSFromStyles(selector, styles);
@@ -159,9 +160,9 @@ var babel_default = declare((api, options) => {
159
160
  const args = path.node.arguments;
160
161
  if (args.length === 0) throw path.buildCodeFrameError("tastyStatic() requires at least one argument");
161
162
  const firstArg = args[0];
162
- if (t.isStringLiteral(firstArg)) handleSelectorMode(path, args, cssWriter, mode, state.sourceFile, config.keyframes, config.autoPropertyTypes, config.fontFaces, config.counterStyles, getGlobalFunctions() ?? void 0);
163
- else if (t.isObjectExpression(firstArg)) handleStylesMode(path, args, cssWriter, state, globalRegistry, mode, config.keyframes, config.autoPropertyTypes, config.fontFaces, config.counterStyles, getGlobalFunctions() ?? void 0);
164
- else if (t.isIdentifier(firstArg)) handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode, config.keyframes, config.autoPropertyTypes, config.fontFaces, config.counterStyles, getGlobalFunctions() ?? void 0);
163
+ if (t.isStringLiteral(firstArg)) handleSelectorMode(path, args, cssWriter, mode, state.sourceFile, config.normalized.keyframes, sourceConfig.autoPropertyTypes, config.normalized.fontFaces, config.normalized.counterStyles, functionsForExtraction(config), config.normalized.recipes);
164
+ else if (t.isObjectExpression(firstArg)) handleStylesMode(path, args, cssWriter, state, globalRegistry, mode, config.normalized.keyframes, sourceConfig.autoPropertyTypes, config.normalized.fontFaces, config.normalized.counterStyles, functionsForExtraction(config), config.normalized.recipes);
165
+ else if (t.isIdentifier(firstArg)) handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode, config.normalized.keyframes, sourceConfig.autoPropertyTypes, config.normalized.fontFaces, config.normalized.counterStyles, functionsForExtraction(config), config.normalized.recipes);
165
166
  else throw path.buildCodeFrameError("tastyStatic() first argument must be an object (styles), identifier (base StaticStyle), or string (selector)");
166
167
  },
167
168
  VariableDeclarator(path, state) {
@@ -232,10 +233,10 @@ function extractClassNameFromStaticStyleObject(node) {
232
233
  /**
233
234
  * Handle tastyStatic(styles) - returns StaticStyle object
234
235
  */
235
- function handleStylesMode(path, args, cssWriter, state, globalRegistry, mode, globalKeyframes, autoPropertyTypes, globalFontFace, globalCounterStyle, globalFunction) {
236
+ function handleStylesMode(path, args, cssWriter, state, globalRegistry, mode, globalKeyframes, autoPropertyTypes, globalFontFace, globalCounterStyle, globalFunction, globalRecipes) {
236
237
  const stylesArg = args[0];
237
238
  if (!t.isObjectExpression(stylesArg)) throw path.buildCodeFrameError("tastyStatic(styles) argument must be a static object literal");
238
- const styles = resolveRecipes(evaluateObjectExpression(stylesArg, path));
239
+ const styles = resolveRecipesWith(evaluateObjectExpression(stylesArg, path), globalRecipes ?? null);
239
240
  const { keyframes, nameMap } = extractKeyframesFromStyles(styles, globalKeyframes);
240
241
  const properties = extractPropertiesFromStyles(styles, { autoPropertyTypes });
241
242
  const fontFaces = extractFontFaceFromStyles(styles, globalFontFace);
@@ -256,7 +257,7 @@ function handleStylesMode(path, args, cssWriter, state, globalRegistry, mode, gl
256
257
  /**
257
258
  * Handle tastyStatic(base, styles) - extends base with additional styles
258
259
  */
259
- function handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode, globalKeyframes, autoPropertyTypes, globalFontFace, globalCounterStyle, globalFunction) {
260
+ function handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode, globalKeyframes, autoPropertyTypes, globalFontFace, globalCounterStyle, globalFunction, globalRecipes) {
260
261
  if (args.length < 2) throw path.buildCodeFrameError("tastyStatic(base, styles) requires two arguments");
261
262
  const baseArg = args[0];
262
263
  const stylesArg = args[1];
@@ -266,7 +267,7 @@ function handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode,
266
267
  const baseEntry = state.staticStyleRegistry[baseName] || globalRegistry[baseName];
267
268
  if (!baseEntry) throw path.buildCodeFrameError(`Cannot find base StaticStyle '${baseName}'. Make sure it is defined before being extended.`);
268
269
  const overrideStyles = evaluateObjectExpression(stylesArg, path);
269
- const mergedStyles = resolveRecipes(mergeStyles(baseEntry.styles, overrideStyles));
270
+ const mergedStyles = resolveRecipesWith(mergeStyles(baseEntry.styles, overrideStyles), globalRecipes ?? null);
270
271
  const { keyframes, nameMap } = extractKeyframesFromStyles(mergedStyles, globalKeyframes);
271
272
  const properties = extractPropertiesFromStyles(mergedStyles, { autoPropertyTypes });
272
273
  const fontFaces = extractFontFaceFromStyles(mergedStyles, globalFontFace);
@@ -287,14 +288,14 @@ function handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode,
287
288
  /**
288
289
  * Handle tastyStatic(selector, styles) - removes the call entirely
289
290
  */
290
- function handleSelectorMode(path, args, cssWriter, mode, sourceFile, globalKeyframes, autoPropertyTypes, globalFontFace, globalCounterStyle, globalFunction) {
291
+ function handleSelectorMode(path, args, cssWriter, mode, sourceFile, globalKeyframes, autoPropertyTypes, globalFontFace, globalCounterStyle, globalFunction, globalRecipes) {
291
292
  if (args.length < 2) throw path.buildCodeFrameError("tastyStatic(selector, styles) requires two arguments");
292
293
  const selectorArg = args[0];
293
294
  const stylesArg = args[1];
294
295
  if (!t.isStringLiteral(selectorArg)) throw path.buildCodeFrameError("tastyStatic(selector, styles) first argument must be a string literal");
295
296
  if (!t.isObjectExpression(stylesArg)) throw path.buildCodeFrameError("tastyStatic(selector, styles) second argument must be a static object literal");
296
297
  const selector = selectorArg.value;
297
- const styles = resolveRecipes(evaluateObjectExpression(stylesArg, path));
298
+ const styles = resolveRecipesWith(evaluateObjectExpression(stylesArg, path), globalRecipes ?? null);
298
299
  const { keyframes, nameMap } = extractKeyframesFromStyles(styles, globalKeyframes);
299
300
  const properties = extractPropertiesFromStyles(styles, { autoPropertyTypes });
300
301
  const fontFaces = extractFontFaceFromStyles(styles, globalFontFace);