@tenphi/tasty 3.10.0 → 3.11.1

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 (88) hide show
  1. package/README.md +403 -380
  2. package/dist/{babel-types-C_7kRP38.d.ts → babel-types-BKDTT4--.d.ts} +2 -2
  3. package/dist/chunks/async-storage-f9j9JRtq.js +37 -0
  4. package/dist/chunks/async-storage-f9j9JRtq.js.map +1 -0
  5. package/dist/chunks/{build-config-l2Ys-AJr.js → build-config-5d8WlQbq.js} +5 -5
  6. package/dist/chunks/{build-config-l2Ys-AJr.js.map → build-config-5d8WlQbq.js.map} +1 -1
  7. package/dist/chunks/{collector-CaNtsRtn.js → collector-CjCak4iE.js} +4 -4
  8. package/dist/chunks/{collector-CaNtsRtn.js.map → collector-CjCak4iE.js.map} +1 -1
  9. package/dist/chunks/{config-engine-CpExZO_T.js → config-engine-uOFYZidB.js} +4 -4
  10. package/dist/chunks/{config-engine-CpExZO_T.js.map → config-engine-uOFYZidB.js.map} +1 -1
  11. package/dist/chunks/config-file-DlZXJMj8.js +25 -0
  12. package/dist/chunks/config-file-DlZXJMj8.js.map +1 -0
  13. package/dist/chunks/{css-definitions-DAIJxzFY.js → css-definitions-ubrHP97m.js} +88 -77
  14. package/dist/chunks/css-definitions-ubrHP97m.js.map +1 -0
  15. package/dist/chunks/{debug-CKy49GEr.js → debug-CJ31U_WE.js} +6 -6
  16. package/dist/chunks/{debug-CKy49GEr.js.map → debug-CJ31U_WE.js.map} +1 -1
  17. package/dist/chunks/{dsl-DRhFWQzo.js → dsl-DYSJc1-T.js} +11 -6
  18. package/dist/chunks/dsl-DYSJc1-T.js.map +1 -0
  19. package/dist/chunks/{react-runtime-oi6i3ELR.js → react-runtime-CyyCI02N.js} +168 -61
  20. package/dist/chunks/react-runtime-CyyCI02N.js.map +1 -0
  21. package/dist/chunks/{runtime-engine-DoULyhPt.js → runtime-engine-BQmOu5-W.js} +53 -36
  22. package/dist/chunks/runtime-engine-BQmOu5-W.js.map +1 -0
  23. package/dist/chunks/{runtime-state-CZ2J5QiZ.js → runtime-state-DEsyUMU-.js} +14 -3
  24. package/dist/chunks/runtime-state-DEsyUMU-.js.map +1 -0
  25. package/dist/chunks/{style-engine-CeKsjtIr.js → style-engine-BX2LshDZ.js} +116 -56
  26. package/dist/chunks/style-engine-BX2LshDZ.js.map +1 -0
  27. package/dist/chunks/{zero-engine-fxKu8Jbn.js → zero-engine-Dw0P4yGM.js} +22 -7
  28. package/dist/chunks/zero-engine-Dw0P4yGM.js.map +1 -0
  29. package/dist/{collector-w4mBj5gd.d.ts → collector-CTU-nl0g.d.ts} +2 -2
  30. package/dist/{config-CrZOfNJ5.d.ts → config-CcxqSZI2.d.ts} +28 -9
  31. package/dist/core/index.d.ts +4 -4
  32. package/dist/core/index.js +7 -7
  33. package/dist/hydrate-CRyjjAyl.d.ts +22 -0
  34. package/dist/{index-CYJtAI9a.d.ts → index--GdqCPlp.d.ts} +58 -16
  35. package/dist/index.d.ts +4 -4
  36. package/dist/index.js +8 -8
  37. package/dist/{merge-styles-VXwJ0Frr.d.ts → merge-styles-DSkVc6CD.d.ts} +2 -2
  38. package/dist/ssr/astro.js +4 -4
  39. package/dist/ssr/client.d.ts +2 -0
  40. package/dist/ssr/client.js +2 -0
  41. package/dist/ssr/index.d.ts +3 -22
  42. package/dist/ssr/index.js +4 -4
  43. package/dist/ssr/index.js.map +1 -1
  44. package/dist/ssr/next-config.d.ts +1 -1
  45. package/dist/ssr/next-config.js +6 -17
  46. package/dist/ssr/next-config.js.map +1 -1
  47. package/dist/ssr/next.d.ts +1 -1
  48. package/dist/ssr/next.js +3 -3
  49. package/dist/static/index.d.ts +2 -2
  50. package/dist/{types-JEY8PVYP.d.ts → types-DJEM_BOJ.d.ts} +6 -6
  51. package/dist/zero/babel.d.ts +1 -1
  52. package/dist/zero/babel.js +30 -19
  53. package/dist/zero/babel.js.map +1 -1
  54. package/dist/zero/index.d.ts +24 -6
  55. package/dist/zero/index.js +4 -4
  56. package/dist/zero/index.js.map +1 -1
  57. package/dist/zero/next.d.ts +1 -1
  58. package/dist/zero/next.js +3 -7
  59. package/dist/zero/next.js.map +1 -1
  60. package/docs/README.md +4 -1
  61. package/docs/adoption.md +25 -17
  62. package/docs/ai-agents.md +39 -34
  63. package/docs/comparison.md +9 -8
  64. package/docs/configuration.md +174 -58
  65. package/docs/debug.md +3 -2
  66. package/docs/design-system.md +117 -15
  67. package/docs/dsl.md +145 -81
  68. package/docs/getting-started.md +81 -24
  69. package/docs/injector.md +41 -40
  70. package/docs/methodology.md +46 -21
  71. package/docs/migration-v3.md +3 -3
  72. package/docs/pipeline.md +19 -16
  73. package/docs/plugins.md +21 -41
  74. package/docs/react-api.md +61 -9
  75. package/docs/runtime-benchmarks.md +4 -4
  76. package/docs/ssr.md +92 -66
  77. package/docs/styles.md +33 -17
  78. package/docs/tasty-static.md +129 -58
  79. package/package.json +23 -9
  80. package/dist/chunks/async-storage-CG5HnUT5.js +0 -20
  81. package/dist/chunks/async-storage-CG5HnUT5.js.map +0 -1
  82. package/dist/chunks/css-definitions-DAIJxzFY.js.map +0 -1
  83. package/dist/chunks/dsl-DRhFWQzo.js.map +0 -1
  84. package/dist/chunks/react-runtime-oi6i3ELR.js.map +0 -1
  85. package/dist/chunks/runtime-engine-DoULyhPt.js.map +0 -1
  86. package/dist/chunks/runtime-state-CZ2J5QiZ.js.map +0 -1
  87. package/dist/chunks/style-engine-CeKsjtIr.js.map +0 -1
  88. package/dist/chunks/zero-engine-fxKu8Jbn.js.map +0 -1
package/dist/ssr/astro.js CHANGED
@@ -1,9 +1,9 @@
1
- import { d as getRuntimeConfigState, r as registerSSRCollectorGetterGlobal } from "../chunks/runtime-state-CZ2J5QiZ.js";
2
- import { t as ServerStyleCollector } from "../chunks/collector-CaNtsRtn.js";
3
- import { n as runWithCollector, t as getSSRCollector } from "../chunks/async-storage-CG5HnUT5.js";
1
+ import { f as getRuntimeConfigState, r as registerSSRCollectorGetterGlobal } from "../chunks/runtime-state-DEsyUMU-.js";
2
+ import { t as ServerStyleCollector } from "../chunks/collector-CjCak4iE.js";
3
+ import { r as runWithCollector, t as getSSRCollector } from "../chunks/async-storage-f9j9JRtq.js";
4
4
  import { t as findUnsafeCSSResource } from "../chunks/css-resources-P7IBUUZs.js";
5
- import { createHash } from "node:crypto";
6
5
  import { join } from "node:path";
6
+ import { createHash } from "node:crypto";
7
7
  import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
8
8
  import { fileURLToPath } from "node:url";
9
9
  //#region src/ssr/astro-extraction.ts
@@ -0,0 +1,2 @@
1
+ import { t as hydrateTastyClasses } from "../hydrate-CRyjjAyl.js";
2
+ export { hydrateTastyClasses };
@@ -0,0 +1,2 @@
1
+ import { t as hydrateTastyClasses } from "../chunks/hydration-TRcz5vnk.js";
2
+ export { hydrateTastyClasses };
@@ -1,4 +1,5 @@
1
- import { i as ServerStyleArtifactKind, n as createServerStyleCollector, r as ServerStyleArtifact, t as ServerStyleCollector } from "../collector-w4mBj5gd.js";
1
+ import { i as ServerStyleArtifactKind, n as createServerStyleCollector, r as ServerStyleArtifact, t as ServerStyleCollector } from "../collector-CTU-nl0g.js";
2
+ import { t as hydrateTastyClasses } from "../hydrate-CRyjjAyl.js";
2
3
  //#region src/ssr/async-storage.d.ts
3
4
  /**
4
5
  * Run a function with a ServerStyleCollector bound to the current
@@ -12,25 +13,5 @@ export declare function runWithCollector<T>(collector: ServerStyleCollector, fn:
12
13
  */
13
14
  export declare function getSSRCollector(): ServerStyleCollector | null;
14
15
  //#endregion
15
- //#region src/ssr/hydrate.d.ts
16
- /**
17
- * Client-side cache hydration for SSR/RSC.
18
- *
19
- * Registers class names rendered on the server with the client injector. If
20
- * the runtime is not initialized yet, registration is deferred until its first
21
- * use. With hash-based naming, only the class name list needs to cross the
22
- * wire — no cache keys or counters.
23
- */
24
- /**
25
- * Hydrate the client-side style registry from the server's class name list.
26
- *
27
- * Call this before ReactDOM.hydrateRoot() or ensure it runs before
28
- * any tasty() component renders on the client.
29
- *
30
- * When called without arguments, reads the class list from `window.__TASTY__`
31
- * (populated by inline scripts emitted during SSR/RSC streaming).
32
- */
33
- export declare function hydrateTastyClasses(classes?: string[]): void;
34
- //#endregion
35
- export { type ServerStyleArtifact, type ServerStyleArtifactKind, ServerStyleCollector, createServerStyleCollector };
16
+ export { type ServerStyleArtifact, type ServerStyleArtifactKind, ServerStyleCollector, createServerStyleCollector, hydrateTastyClasses };
36
17
  //# sourceMappingURL=index.d.ts.map
package/dist/ssr/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import { r as registerSSRCollectorGetterGlobal } from "../chunks/runtime-state-CZ2J5QiZ.js";
2
- import { n as createServerStyleCollector, t as ServerStyleCollector } from "../chunks/collector-CaNtsRtn.js";
3
- import { n as runWithCollector, t as getSSRCollector } from "../chunks/async-storage-CG5HnUT5.js";
1
+ import { r as registerSSRCollectorGetterGlobal } from "../chunks/runtime-state-DEsyUMU-.js";
2
+ import { n as createServerStyleCollector, t as ServerStyleCollector } from "../chunks/collector-CjCak4iE.js";
3
+ import { n as isAsyncStorageAvailable, r as runWithCollector, t as getSSRCollector } from "../chunks/async-storage-f9j9JRtq.js";
4
4
  import { t as hydrateTastyClasses } from "../chunks/hydration-TRcz5vnk.js";
5
5
  //#region src/ssr/index.ts
6
- registerSSRCollectorGetterGlobal(getSSRCollector);
6
+ if (isAsyncStorageAvailable()) registerSSRCollectorGetterGlobal(getSSRCollector);
7
7
  //#endregion
8
8
  export { ServerStyleCollector, createServerStyleCollector, getSSRCollector, hydrateTastyClasses, runWithCollector };
9
9
 
@@ -1 +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 * AsyncLocalStorage integration, and cache hydration.\n *\n * Import from '@tenphi/tasty/ssr'.\n */\n\n// Core collector\nexport { ServerStyleCollector, createServerStyleCollector } from './collector';\nexport type { ServerStyleArtifact, ServerStyleArtifactKind } from './collector';\n\n// AsyncLocalStorage integration for Astro / generic frameworks\nexport { runWithCollector, getSSRCollector } from './async-storage';\n\n// Client-side cache hydration\nexport { hydrateTastyClasses } from './hydrate';\n\n// Register the ALS getter so hooks can find the collector\n// without importing 'node:async_hooks' in the browser bundle.\n// Uses globalThis so the getter is visible across separate module graphs.\nimport { getSSRCollector } from './async-storage';\nimport { registerSSRCollectorGetterGlobal } from './ssr-collector-ref';\n\nregisterSSRCollectorGetterGlobal(getSSRCollector);\n"],"mappings":";;;;;AAyBA,iCAAiC,eAAe"}
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 * AsyncLocalStorage integration, and cache hydration.\n *\n * Import from '@tenphi/tasty/ssr'.\n */\n\n// Core collector\nexport { ServerStyleCollector, createServerStyleCollector } from './collector';\nexport type { ServerStyleArtifact, ServerStyleArtifactKind } from './collector';\n\n// AsyncLocalStorage integration for Astro / generic frameworks\nexport { runWithCollector, getSSRCollector } from './async-storage';\n\n// Client-side cache hydration\nexport { hydrateTastyClasses } from './hydrate';\n\n// Register the ALS getter so hooks can find the collector\n// without importing 'node:async_hooks' in the browser bundle.\n// Uses globalThis so the getter is visible across separate module graphs.\n// A browser bundle that imports this entry has no storage to look in.\nimport { getSSRCollector, isAsyncStorageAvailable } from './async-storage';\nimport { registerSSRCollectorGetterGlobal } from './ssr-collector-ref';\n\nif (isAsyncStorageAvailable()) {\n registerSSRCollectorGetterGlobal(getSSRCollector);\n}\n"],"mappings":";;;;;AA0BA,IAAI,wBAAwB,GAC1B,iCAAiC,eAAe"}
@@ -1,4 +1,4 @@
1
- import { t as TastyConfig } from "../config-CrZOfNJ5.js";
1
+ import { t as TastyConfig } from "../config-CcxqSZI2.js";
2
2
  //#region src/ssr/next-config.d.ts
3
3
  interface NextConfig {
4
4
  basePath?: string;
@@ -1,28 +1,17 @@
1
- import { G as parseFunctionName, S as formatFontFaceRule, U as formatFunctionRule, _ as formatCounterStyleRule, b as fontFaceContentHash, i as formatKeyframesCSS, m as resolveSelectorKeyframes, n as formatGlobalRules, o as formatPropertyCSS, t as createServerStyleArtifact, z as DEFAULT_PROPERTIES } from "../chunks/css-definitions-DAIJxzFY.js";
2
- import { b as renderStyles } from "../chunks/style-engine-CeKsjtIr.js";
3
- import { a as resetZeroConfig, n as functionsForExtraction, t as configureZero } from "../chunks/build-config-l2Ys-AJr.js";
1
+ import { K as parseFunctionName, P as DEFAULT_PROPERTIES, S as formatFontFaceRule, W as formatFunctionRule, _ as formatCounterStyleRule, b as fontFaceContentHash, i as formatKeyframesCSS, m as resolveSelectorKeyframes, n as formatGlobalRules, o as formatPropertyCSS, t as createServerStyleArtifact } from "../chunks/css-definitions-ubrHP97m.js";
2
+ import { b as renderStyles } from "../chunks/style-engine-BX2LshDZ.js";
3
+ import { a as resetZeroConfig, n as functionsForExtraction, t as configureZero } from "../chunks/build-config-5d8WlQbq.js";
4
+ import { t as loadConfigFile } from "../chunks/config-file-DlZXJMj8.js";
4
5
  import { t as findUnsafeCSSResource } from "../chunks/css-resources-P7IBUUZs.js";
6
+ import { isAbsolute, join, relative, resolve, sep } from "node:path";
5
7
  import { createHash } from "node:crypto";
6
8
  import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
7
- import { createRequire } from "node:module";
8
- import { isAbsolute, join, relative, resolve, sep } from "node:path";
9
9
  //#region src/ssr/next-config.ts
10
10
  const ENV_KEY = "TASTY_NEXT_SHARED_CSS_HREF";
11
- const packageRequire = createRequire(import.meta.url);
12
11
  function loadConfig(projectDir, options) {
13
12
  if (options.config) return options.config;
14
13
  if (!options.configFile) throw new Error("[Tasty] withTastyNext() requires either `config` or `configFile`.");
15
- const configPath = resolve(projectDir, options.configFile);
16
- let jitiPath;
17
- try {
18
- jitiPath = packageRequire.resolve("jiti");
19
- } catch (error) {
20
- 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 });
21
- throw error;
22
- }
23
- const { createJiti } = packageRequire(jitiPath);
24
- const loaded = createJiti(projectDir, { moduleCache: false })(configPath);
25
- return loaded && typeof loaded === "object" && "default" in loaded ? loaded.default : loaded;
14
+ return loadConfigFile(resolve(projectDir, options.configFile), projectDir);
26
15
  }
27
16
  function collectSharedCSS(config) {
28
17
  resetZeroConfig();
@@ -1 +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 { resolveSelectorKeyframes } from '../keyframes';\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 { formatKeyframesCSS } from './format-keyframes';\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 const keyframeNames = new Set<string>();\n for (const [selector, styles] of Object.entries(normalized.globalStyles)) {\n if (Object.keys(styles).length === 0) continue;\n const { rules, keyframes } = resolveSelectorKeyframes(\n styles,\n renderStyles(styles, selector) as StyleResult[],\n normalized.keyframes,\n );\n for (const [name, steps] of keyframes ?? []) {\n if (keyframeNames.has(name)) continue;\n keyframeNames.add(name);\n append('keyframes', name, formatKeyframesCSS(name, steps));\n }\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":"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"}
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 { isAbsolute, join, relative, resolve, sep } from 'node:path';\n\nimport type { TastyConfig } from '../config';\nimport { formatCounterStyleRule } from '../counter-style';\nimport { fontFaceContentHash, formatFontFaceRule } from '../font-face';\nimport { formatFunctionRule, parseFunctionName } from '../functions';\nimport { resolveSelectorKeyframes } from '../keyframes';\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 { loadConfigFile } from '../zero/config-file';\nimport { createServerStyleArtifact } from './artifacts';\nimport type { ServerStyleArtifact, ServerStyleArtifactKind } from './artifacts';\nimport { findUnsafeCSSResource } from './css-resources';\nimport { formatGlobalRules } from './format-global-rules';\nimport { formatKeyframesCSS } from './format-keyframes';\nimport { formatPropertyCSS } from './format-property';\n\nconst ENV_KEY = 'TASTY_NEXT_SHARED_CSS_HREF';\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 return loadConfigFile<TastyConfig>(\n resolve(projectDir, options.configFile),\n projectDir,\n );\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 const keyframeNames = new Set<string>();\n for (const [selector, styles] of Object.entries(normalized.globalStyles)) {\n if (Object.keys(styles).length === 0) continue;\n const { rules, keyframes } = resolveSelectorKeyframes(\n styles,\n renderStyles(styles, selector) as StyleResult[],\n normalized.keyframes,\n );\n for (const [name, steps] of keyframes ?? []) {\n if (keyframeNames.has(name)) continue;\n keyframeNames.add(name);\n append('keyframes', name, formatKeyframesCSS(name, steps));\n }\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":"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"}
@@ -1,4 +1,4 @@
1
- import { t as ServerStyleCollector } from "../collector-w4mBj5gd.js";
1
+ import { t as ServerStyleCollector } from "../collector-CTU-nl0g.js";
2
2
  import { ReactNode } from "react";
3
3
  //#region src/ssr/next.d.ts
4
4
  export interface TastyRegistryProps {
package/dist/ssr/next.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { d as getRuntimeConfigState, n as registerSSRCollectorGetter } from "../chunks/runtime-state-CZ2J5QiZ.js";
3
- import { u as getTastySSRContext } from "../chunks/react-runtime-oi6i3ELR.js";
4
- import { t as ServerStyleCollector } from "../chunks/collector-CaNtsRtn.js";
2
+ import { f as getRuntimeConfigState, n as registerSSRCollectorGetter } from "../chunks/runtime-state-DEsyUMU-.js";
3
+ import { u as getTastySSRContext } from "../chunks/react-runtime-CyyCI02N.js";
4
+ import { t as ServerStyleCollector } from "../chunks/collector-CjCak4iE.js";
5
5
  import { t as hydrateTastyClasses } from "../chunks/hydration-TRcz5vnk.js";
6
6
  import { Fragment, createElement, useState } from "react";
7
7
  import { useServerInsertedHTML } from "next/navigation";
@@ -1,5 +1,5 @@
1
- import { Y as Styles } from "../types-JEY8PVYP.js";
2
- import { t as mergeStyles } from "../merge-styles-VXwJ0Frr.js";
1
+ import { Y as Styles } from "../types-DJEM_BOJ.js";
2
+ import { t as mergeStyles } from "../merge-styles-DSkVc6CD.js";
3
3
  //#region src/static/types.d.ts
4
4
  /**
5
5
  * Static style definition returned by tastyStatic().
@@ -157,10 +157,9 @@ declare const DIRECTIONS: string[];
157
157
  */
158
158
  declare function getGlobalParser(): StyleParser;
159
159
  /**
160
- * Get the current global predefined tokens.
161
- * Returns null if no tokens are configured.
160
+ * Get the current global predefined tokens, including built-in defaults.
162
161
  */
163
- declare function getGlobalPredefinedTokens(): Record<string, string> | null;
162
+ declare function getGlobalPredefinedTokens(): Record<string, string>;
164
163
  /**
165
164
  *
166
165
  * @param {String} value
@@ -247,7 +246,8 @@ interface StylesInterface extends Omit<CSSProperties, 'color' | 'fill' | 'font'
247
246
  * - `fill="okhsl(200 100% 50%)"` // perceptually uniform OKHSL color
248
247
  * - `fill="oklch(0.7 0.15 200)"` // OKLCH color
249
248
  * - `fill="#primary #secondary"` // double color (second as foreground overlay)
250
- * - `fill={true}` // default fill color
249
+ *
250
+ * `fill={false}` sets no fill. `fill={true}` names no color and is ignored.
251
251
  */
252
252
  fill?: ColorValue | boolean;
253
253
  /**
@@ -500,7 +500,7 @@ interface StylesInterface extends Omit<CSSProperties, 'color' | 'fill' | 'font'
500
500
  * Corner modifiers: `top-left`, `top-right`, `bottom-right`, `bottom-left` — a single corner
501
501
  *
502
502
  * Examples:
503
- * - `radius="2r"` // border-radius: calc(var(--radius) * 2)
503
+ * - `radius="2r"` // border-radius: 12px
504
504
  * - `radius={true}` // default radius (1r)
505
505
  * - `radius="round"` // fully rounded (9999rem)
506
506
  * - `radius="leaf"` // asymmetric leaf shape
@@ -1564,4 +1564,4 @@ interface RawCSSResult {
1564
1564
  }
1565
1565
  //#endregion
1566
1566
  export { TastyNamedColors as $, resetStyleBatch as A, getGlobalPredefinedStates as B, SheetInfo as C, StyleParser as Ct, QueuedWrite as D, StyleDetailsPart as Dt, StyleUsage as E, StyleDetails as Et, parseStateKey as F, NoType as G, ConditionNode as H, AtRuleContext as I, Selector as J, NotSelector as K, ParsedAdvancedState as L, StyleResult as M, renderStyles as N, flushStyles as O, UnitHandler as Ot, ParseStateKeyOptions as P, SuffixForSelector as Q, StateParserContext as R, RuleInfo as S, stringifyStyles as St, StyleRule as T, ProcessedStyle as Tt, ConfigTokenValue as U, setGlobalPredefinedStates as V, ConfigTokens as W, StylesInterface as X, Styles as Y, StylesWithoutSelectors as Z, KeyframesSteps as _, getGlobalParser as _t, FontFaceInput as a, ParsedColor as at, RawCSSResult as b, parseColor as bt, GCConfig as c, StyleHandler as ct, InjectOptions as d, StyleHandlerResult as dt, TastyPresetNames as et, InjectResult as f, StyleMap as ft, KeyframesResult as g, filterMods as gt, KeyframesInfo as h, StyleValueStateMap as ht, FontFaceDescriptors as i, DIRECTIONS as it, RenderResult as j, hasPendingStyleWrites as k, CSSProperties as kt, GCOptions as l, StyleHandlerDefinition as lt, KeyframesCacheEntry as m, StyleValue as mt, CounterStyleDescriptors as n, CSSMap as nt, FunctionDefinition as o, RawStyleHandler as ot, InjectionMode as p, StylePropValue as pt, RecipeStyles as q, DisposeFunction as r, CUSTOM_UNITS as rt, FunctionParameter as s, ResolvedStyleValue as st, CacheMetrics as t, AnyStyleHandler as tt, GlobalInjectResult as u, StyleHandlerProps as ut, PropertyDefinition as v, getGlobalPredefinedTokens as vt, StyleInjectorConfig as w, ParserOptions as wt, RootRegistry as x, parseStyle as xt, PropertyOptions as y, normalizeColorTokenValue as yt, createStateParserContext as z };
1567
- //# sourceMappingURL=types-JEY8PVYP.d.ts.map
1567
+ //# sourceMappingURL=types-DJEM_BOJ.d.ts.map
@@ -1,4 +1,4 @@
1
- import { t as TastyZeroConfig } from "../babel-types-C_7kRP38.js";
1
+ import { t as TastyZeroConfig } from "../babel-types-BKDTT4--.js";
2
2
  import { PluginPass } from "@babel/core";
3
3
  //#region src/zero/babel.d.ts
4
4
  /**
@@ -1,13 +1,13 @@
1
1
  import { t as mergeStyles } from "../chunks/shared-utils-y-HjvPN4.js";
2
- import "../chunks/css-definitions-DAIJxzFY.js";
3
- import { t as resolveRecipesWith } from "../chunks/config-engine-CpExZO_T.js";
4
- import { a as resetZeroConfig, i as reapplyZeroConfig, n as functionsForExtraction, t as configureZero } from "../chunks/build-config-l2Ys-AJr.js";
5
- import { a as extractFontFaceFromStyles, c as extractPropertiesFromStyles, f as renderSelectorCSS, i as extractCounterStyleFromStyles, l as extractSelectorCSS, m as setExtractorNamePrefix, o as extractFunctionsFromStyles, p as replaceAnimationNamesInCSS, r as extractChunks, s as extractKeyframesFromStyles, t as CSSWriter } from "../chunks/zero-engine-fxKu8Jbn.js";
2
+ import "../chunks/css-definitions-ubrHP97m.js";
3
+ import { t as resolveRecipesWith } from "../chunks/config-engine-uOFYZidB.js";
4
+ import { a as resetZeroConfig, i as reapplyZeroConfig, n as functionsForExtraction, t as configureZero } from "../chunks/build-config-5d8WlQbq.js";
5
+ import { a as extractCounterStyleFromStyles, c as extractKeyframesFromStyles, h as setExtractorNamePrefix, i as extractConfigProperties, l as extractPropertiesFromStyles, m as replaceAnimationNamesInCSS, o as extractFontFaceFromStyles, p as renderSelectorCSS, r as extractChunks, s as extractFunctionsFromStyles, t as CSSWriter, u as extractSelectorCSS } from "../chunks/zero-engine-Dw0P4yGM.js";
6
+ import { t as loadConfigFile } from "../chunks/config-file-DlZXJMj8.js";
6
7
  import * as fs from "fs";
7
8
  import * as path from "path";
8
9
  import { declare } from "@babel/helper-plugin-utils";
9
10
  import * as t from "@babel/types";
10
- import { createJiti } from "jiti";
11
11
  //#region \0rolldown/runtime.js
12
12
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
13
13
  if (typeof require !== "undefined") return require.apply(this, arguments);
@@ -65,10 +65,8 @@ var babel_default = declare((api, options) => {
65
65
  const configOption = options.config;
66
66
  let resolvedConfig;
67
67
  if (configOption) resolvedConfig = typeof configOption === "function" ? configOption() : configOption;
68
- else if (options.configFile) {
69
- const loaded = createJiti(path.dirname(options.configFile), { moduleCache: false })(options.configFile);
70
- resolvedConfig = loaded && typeof loaded === "object" && "default" in loaded ? loaded.default : loaded;
71
- } else resolvedConfig = {};
68
+ else if (options.configFile) resolvedConfig = loadConfigFile(options.configFile);
69
+ else resolvedConfig = {};
72
70
  const devMode = resolvedConfig.devMode ?? false;
73
71
  resetZeroConfig();
74
72
  const finalConfig = {
@@ -79,6 +77,7 @@ var babel_default = declare((api, options) => {
79
77
  setExtractorNamePrefix(finalConfig.namePrefix ?? "ts");
80
78
  const newWriter = new CSSWriter(outputPath, { devMode });
81
79
  if (mode !== "inject") {
80
+ for (const prop of extractConfigProperties(config.normalized.properties)) newWriter.add(`@property:${prop.name}`, prop.css);
82
81
  const tokenCSS = extractCSSFromStyles(":root", config.normalized.tokens);
83
82
  if (tokenCSS) newWriter.add(":root:tokens", tokenCSS);
84
83
  for (const [selector, styles] of Object.entries(config.normalized.globalStyles)) writeGlobalStyles(newWriter, selector, styles, config.normalized.keyframes);
@@ -98,9 +97,16 @@ var babel_default = declare((api, options) => {
98
97
  const sourceConfig = config.source;
99
98
  const devMode = sourceConfig.devMode ?? false;
100
99
  setExtractorNamePrefix(sourceConfig.namePrefix ?? "ts");
100
+ const configProperties = extractConfigProperties(config.normalized.properties);
101
+ const propertyOptions = {
102
+ autoPropertyTypes: sourceConfig.autoPropertyTypes,
103
+ defined: new Set(configProperties.map((prop) => prop.name))
104
+ };
105
+ let propertyCSS;
101
106
  let tokenCSS;
102
107
  let globalStylesCSS;
103
108
  if (mode === "inject") {
109
+ propertyCSS = configProperties.map((prop) => prop.css).join("\n") || void 0;
104
110
  tokenCSS = extractCSSFromStyles(":root", config.normalized.tokens);
105
111
  const gs = config.normalized.globalStyles;
106
112
  if (Object.keys(gs).length > 0) {
@@ -144,9 +150,9 @@ var babel_default = declare((api, options) => {
144
150
  const args = path.node.arguments;
145
151
  if (args.length === 0) throw path.buildCodeFrameError("tastyStatic() requires at least one argument");
146
152
  const firstArg = args[0];
147
- 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);
148
- 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);
149
- 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);
153
+ if (t.isStringLiteral(firstArg)) handleSelectorMode(path, args, cssWriter, mode, state.sourceFile, config.normalized.keyframes, propertyOptions, config.normalized.fontFaces, config.normalized.counterStyles, functionsForExtraction(config), config.normalized.recipes);
154
+ else if (t.isObjectExpression(firstArg)) handleStylesMode(path, args, cssWriter, state, globalRegistry, mode, config.normalized.keyframes, propertyOptions, config.normalized.fontFaces, config.normalized.counterStyles, functionsForExtraction(config), config.normalized.recipes);
155
+ else if (t.isIdentifier(firstArg)) handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode, config.normalized.keyframes, propertyOptions, config.normalized.fontFaces, config.normalized.counterStyles, functionsForExtraction(config), config.normalized.recipes);
150
156
  else throw path.buildCodeFrameError("tastyStatic() first argument must be an object (styles), identifier (base StaticStyle), or string (selector)");
151
157
  },
152
158
  VariableDeclarator(path, state) {
@@ -171,10 +177,15 @@ var babel_default = declare((api, options) => {
171
177
  },
172
178
  post() {
173
179
  if (mode === "inject") {
174
- if (this._fileAddedCSS && (tokenCSS || globalStylesCSS)) {
180
+ if (this._fileAddedCSS && (propertyCSS || tokenCSS || globalStylesCSS)) {
175
181
  const program = this.file.ast.program;
176
182
  let insertIndex = 0;
177
183
  for (let i = 0; i < program.body.length; i++) if (t.isImportDeclaration(program.body[i])) insertIndex = i + 1;
184
+ if (propertyCSS) {
185
+ const injectCall = createInjectCallAST("@property", propertyCSS);
186
+ program.body.splice(insertIndex, 0, t.expressionStatement(injectCall));
187
+ insertIndex++;
188
+ }
178
189
  if (tokenCSS) {
179
190
  const injectCall = createInjectCallAST(":root", tokenCSS);
180
191
  program.body.splice(insertIndex, 0, t.expressionStatement(injectCall));
@@ -205,13 +216,13 @@ function extractClassNameFromStaticStyleObject(node) {
205
216
  for (const prop of node.properties) if (t.isObjectProperty(prop) && t.isIdentifier(prop.key, { name: "className" }) && t.isStringLiteral(prop.value)) return prop.value.value;
206
217
  return null;
207
218
  }
208
- function handleStylesMode(path, args, cssWriter, state, globalRegistry, mode, globalKeyframes, autoPropertyTypes, globalFontFace, globalCounterStyle, globalFunction, globalRecipes) {
219
+ function handleStylesMode(path, args, cssWriter, state, globalRegistry, mode, globalKeyframes, propertyOptions, globalFontFace, globalCounterStyle, globalFunction, globalRecipes) {
209
220
  const stylesArg = args[0];
210
221
  if (!t.isObjectExpression(stylesArg)) throw path.buildCodeFrameError("tastyStatic(styles) argument must be a static object literal");
211
222
  const rawStyles = evaluateObjectExpression(stylesArg, path);
212
223
  const styles = resolveRecipesWith(rawStyles, globalRecipes ?? null);
213
224
  const { keyframes, nameMap } = extractKeyframesFromStyles(styles, globalKeyframes);
214
- const properties = extractPropertiesFromStyles(styles, { autoPropertyTypes });
225
+ const properties = extractPropertiesFromStyles(styles, propertyOptions);
215
226
  const fontFaces = extractFontFaceFromStyles(styles, globalFontFace);
216
227
  const counterStyles = extractCounterStyleFromStyles(styles, globalCounterStyle);
217
228
  const functions = extractFunctionsFromStyles(styles, globalFunction);
@@ -227,7 +238,7 @@ function handleStylesMode(path, args, cssWriter, state, globalRegistry, mode, gl
227
238
  }
228
239
  registerIfVariableDeclaration(path, className, styles, state, globalRegistry);
229
240
  }
230
- function handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode, globalKeyframes, autoPropertyTypes, globalFontFace, globalCounterStyle, globalFunction, globalRecipes) {
241
+ function handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode, globalKeyframes, propertyOptions, globalFontFace, globalCounterStyle, globalFunction, globalRecipes) {
231
242
  if (args.length < 2) throw path.buildCodeFrameError("tastyStatic(base, styles) requires two arguments");
232
243
  const baseArg = args[0];
233
244
  const stylesArg = args[1];
@@ -239,7 +250,7 @@ function handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode,
239
250
  const overrideStyles = evaluateObjectExpression(stylesArg, path);
240
251
  const mergedStyles = resolveRecipesWith(mergeStyles(baseEntry.styles, overrideStyles), globalRecipes ?? null);
241
252
  const { keyframes, nameMap } = extractKeyframesFromStyles(mergedStyles, globalKeyframes);
242
- const properties = extractPropertiesFromStyles(mergedStyles, { autoPropertyTypes });
253
+ const properties = extractPropertiesFromStyles(mergedStyles, propertyOptions);
243
254
  const fontFaces = extractFontFaceFromStyles(mergedStyles, globalFontFace);
244
255
  const counterStyles = extractCounterStyleFromStyles(mergedStyles, globalCounterStyle);
245
256
  const functions = extractFunctionsFromStyles(mergedStyles, globalFunction);
@@ -255,7 +266,7 @@ function handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode,
255
266
  }
256
267
  registerIfVariableDeclaration(path, className, mergedStyles, state, globalRegistry);
257
268
  }
258
- function handleSelectorMode(path, args, cssWriter, mode, sourceFile, globalKeyframes, autoPropertyTypes, globalFontFace, globalCounterStyle, globalFunction, globalRecipes) {
269
+ function handleSelectorMode(path, args, cssWriter, mode, sourceFile, globalKeyframes, propertyOptions, globalFontFace, globalCounterStyle, globalFunction, globalRecipes) {
259
270
  if (args.length < 2) throw path.buildCodeFrameError("tastyStatic(selector, styles) requires two arguments");
260
271
  const selectorArg = args[0];
261
272
  const stylesArg = args[1];
@@ -265,7 +276,7 @@ function handleSelectorMode(path, args, cssWriter, mode, sourceFile, globalKeyfr
265
276
  const rawStyles = evaluateObjectExpression(stylesArg, path);
266
277
  const styles = resolveRecipesWith(rawStyles, globalRecipes ?? null);
267
278
  const { keyframes, nameMap } = extractKeyframesFromStyles(styles, globalKeyframes);
268
- const properties = extractPropertiesFromStyles(styles, { autoPropertyTypes });
279
+ const properties = extractPropertiesFromStyles(styles, propertyOptions);
269
280
  const fontFaces = extractFontFaceFromStyles(styles, globalFontFace);
270
281
  const counterStyles = extractCounterStyleFromStyles(styles, globalCounterStyle);
271
282
  const functions = extractFunctionsFromStyles(styles, globalFunction);