@tenphi/tasty 3.11.2 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/dist/{babel-types-BKDTT4--.d.ts → babel-types-docs8f4c.d.ts} +2 -2
- package/dist/chunks/{build-config-DlxpZKk_.js → build-config-DmSCYjYl.js} +5 -5
- package/dist/chunks/{build-config-DlxpZKk_.js.map → build-config-DmSCYjYl.js.map} +1 -1
- package/dist/chunks/{collector-B4-yqFEs.js → collector-8w5r-xFl.js} +4 -4
- package/dist/chunks/{collector-B4-yqFEs.js.map → collector-8w5r-xFl.js.map} +1 -1
- package/dist/chunks/{config-engine-DJsb5WYu.js → config-engine-DjRv6Axa.js} +5 -5
- package/dist/chunks/config-engine-DjRv6Axa.js.map +1 -0
- package/dist/chunks/{css-definitions-DW1TGGiy.js → css-definitions-_UidGa56.js} +3 -3
- package/dist/chunks/{css-definitions-DW1TGGiy.js.map → css-definitions-_UidGa56.js.map} +1 -1
- package/dist/chunks/{debug-DMMwe1rY.js → debug-B6dZq3uH.js} +4 -4
- package/dist/chunks/{debug-DMMwe1rY.js.map → debug-B6dZq3uH.js.map} +1 -1
- package/dist/chunks/{dsl-DYSJc1-T.js → dsl-rgu6XQcD.js} +42 -39
- package/dist/chunks/dsl-rgu6XQcD.js.map +1 -0
- package/dist/chunks/{react-runtime-DhPtFlZs.js → react-runtime-DS1cEAMK.js} +5 -5
- package/dist/chunks/react-runtime-DS1cEAMK.js.map +1 -0
- package/dist/chunks/{runtime-engine-BlrVXv8l.js → runtime-engine-DFCZN1nF.js} +6 -6
- package/dist/chunks/runtime-engine-DFCZN1nF.js.map +1 -0
- package/dist/chunks/{runtime-state-BLyMRYFF.js → runtime-state-C8MzPjBR.js} +2 -2
- package/dist/chunks/{runtime-state-BLyMRYFF.js.map → runtime-state-C8MzPjBR.js.map} +1 -1
- package/dist/chunks/{style-engine-of5Xbc27.js → style-engine-DoGrZPBB.js} +17 -12
- package/dist/chunks/style-engine-DoGrZPBB.js.map +1 -0
- package/dist/chunks/{zero-engine-D2jPSpWA.js → zero-engine-CiVidroC.js} +5 -5
- package/dist/chunks/{zero-engine-D2jPSpWA.js.map → zero-engine-CiVidroC.js.map} +1 -1
- package/dist/{config-CcxqSZI2.d.ts → config-DDY7NlZ1.d.ts} +7 -8
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +7 -7
- package/dist/{index--GdqCPlp.d.ts → index-enN6b6o_.d.ts} +5 -5
- package/dist/index.d.ts +3 -3
- package/dist/index.js +8 -8
- package/dist/ssr/astro.js +2 -2
- package/dist/ssr/index.js +2 -2
- package/dist/ssr/next-config.d.ts +1 -1
- package/dist/ssr/next-config.js +3 -3
- package/dist/ssr/next.js +3 -3
- package/dist/zero/babel.d.ts +9 -3
- package/dist/zero/babel.js +8 -8
- package/dist/zero/babel.js.map +1 -1
- package/dist/zero/index.d.ts +3 -2
- package/dist/zero/index.js +5 -4
- package/dist/zero/index.js.map +1 -1
- package/dist/zero/next.d.ts +1 -1
- package/docs/ai-agents.md +1 -0
- package/docs/configuration.md +12 -10
- package/docs/dsl.md +56 -42
- package/docs/styles.md +4 -0
- package/docs/tasty-static.md +21 -7
- package/package.json +26 -27
- package/dist/chunks/config-engine-DJsb5WYu.js.map +0 -1
- package/dist/chunks/dsl-DYSJc1-T.js.map +0 -1
- package/dist/chunks/react-runtime-DhPtFlZs.js.map +0 -1
- package/dist/chunks/runtime-engine-BlrVXv8l.js.map +0 -1
- package/dist/chunks/style-engine-of5Xbc27.js.map +0 -1
package/dist/zero/babel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"babel.js","names":[],"sources":["../../src/zero/writer-cache.ts","../../src/zero/babel.ts"],"sourcesContent":["/**\n * Internal shared CSSWriter cache for the zero-runtime Babel plugin.\n *\n * Kept in a separate non-exported module so `clearWriterCache` is not part\n * of the public `@tenphi/tasty/babel-plugin` entry surface. The Babel plugin\n * and its tests import from here directly.\n */\n\nimport type { CSSWriter } from './css-writer';\nimport type { Styles } from '../styles/types';\nimport type { ResolvedZeroConfig } from './config';\n\n/**\n * Registry of static styles keyed by their source identifier.\n * Used to resolve base styles when extending.\n */\nexport type StaticStyleRegistry = Record<\n string,\n {\n styles: Styles;\n className: string;\n }\n>;\n\nexport interface WriterCacheEntry {\n writer: CSSWriter;\n configKey: string;\n registry: StaticStyleRegistry;\n config: ResolvedZeroConfig;\n}\n\nexport const writerCache = new Map<string, WriterCacheEntry>();\n\n/** Clear the shared CSSWriter cache. Exposed for testing. */\nexport function clearWriterCache(): void {\n writerCache.clear();\n}\n","/**\n * Babel plugin for zero-runtime tasty static site generation.\n *\n * Transforms:\n * - `tastyStatic(styles)` → StaticStyle object { className, styles, toString() }\n * - `tastyStatic(base, styles)` → StaticStyle object with merged styles\n * - `tastyStatic(selector, styles)` → removed entirely\n *\n * Usage:\n * ```javascript\n * // babel.config.js\n * module.exports = {\n * plugins: [\n * ['@tenphi/tasty/babel-plugin', { output: 'public/tasty.css' }]\n * ]\n * };\n * ```\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { declare } from '@babel/helper-plugin-utils';\nimport * as t from '@babel/types';\n\nimport type { ConfigTokens, RecipeStyles, Styles } from '../styles/types';\nimport { mergeStyles } from '../utils/merge-styles';\nimport { DEFAULT_ZERO_NAME_PREFIX } from '../utils/name-prefix';\nimport { resolveRecipesWith } from '../utils/resolve-recipes-core';\n\nimport { loadConfigFile } from './config-file';\nimport { CSSWriter } from './css-writer';\nimport type { TastyZeroConfig } from './babel-types';\nexport type { TastyZeroConfig } from './babel-types';\nimport {\n configureZero,\n functionsForExtraction,\n reapplyZeroConfig,\n resetZeroConfig,\n} from './config';\nimport { writerCache, type StaticStyleRegistry } from './writer-cache';\nimport {\n extractConfigProperties,\n extractCounterStyleFromStyles,\n extractFontFaceFromStyles,\n extractFunctionsFromStyles,\n extractKeyframesFromStyles,\n extractPropertiesFromStyles,\n extractChunks,\n extractSelectorCSS,\n renderSelectorCSS,\n replaceAnimationNamesInCSS,\n setExtractorNamePrefix,\n} from './extractor';\nimport type {\n ExtractedChunk,\n ExtractedCounterStyle,\n ExtractedFontFace,\n ExtractedFunction,\n ExtractedKeyframes,\n ExtractedProperty,\n PropertyExtractionOptions,\n} from './extractor';\n\nimport type { NodePath, PluginPass } from '@babel/core';\nimport type {\n CounterStyleDescriptors,\n FontFaceInput,\n FunctionDefinition,\n KeyframesSteps,\n} from '../injector/types';\n\n/**\n * Options for the `@tenphi/tasty/babel-plugin` Babel plugin.\n */\nexport interface TastyZeroBabelOptions {\n /** Output path for generated CSS (default: 'tasty.css') */\n output?: string;\n /**\n * Tasty configuration for build-time processing.\n * Can be a static object or a factory function that returns fresh config.\n * A factory is called on each plugin invocation, enabling hot reload\n * of config values that depend on external files (e.g. theme tokens).\n */\n config?: TastyZeroConfig | (() => TastyZeroConfig);\n /**\n * Absolute path to a TypeScript/JavaScript module that default-exports\n * a `TastyZeroConfig` object. The module is loaded via jiti on each\n * plugin invocation, enabling hot reload when the file changes.\n *\n * This option is JSON-serializable and is the primary way Turbopack\n * passes config to the Babel plugin (since Turbopack loader options\n * must be plain primitives/objects/arrays).\n *\n * When both `config` and `configFile` are set, `config` takes precedence.\n *\n * @example '/absolute/path/to/tasty-zero.config.ts'\n */\n configFile?: string;\n /**\n * Absolute file paths whose content affects the generated CSS.\n * When any of these files change, babel-loader invalidates its cache\n * and re-runs the plugin with fresh config values.\n *\n * Typically includes theme files that define Glaze palettes or token values.\n * Paths must be absolute (resolved by the Next.js wrapper).\n */\n configDeps?: string[];\n /**\n * Automatically replace `@tenphi/tasty/static` imports with an import\n * of the generated CSS file. This eliminates the need for users to\n * manually import the CSS in their app entry point.\n *\n * @default true\n */\n injectImport?: boolean;\n /**\n * Output mode for extracted CSS.\n *\n * - `'file'` (default): CSS is written to a single output file and\n * the `@tenphi/tasty/static` import is rewritten to import that file.\n * - `'inject'`: CSS is embedded inline in the JS output and injected\n * at runtime via a tiny injector from `@tenphi/tasty/static/inject`.\n * No CSS file is written. Each `tastyStatic` call becomes\n * self-contained. Best for reusable components and extensions.\n *\n * When `mode` is `'inject'`, `output` and `injectImport` are ignored.\n *\n * @default 'file'\n */\n mode?: 'file' | 'inject';\n}\n\ninterface PluginState extends PluginPass {\n staticStyleRegistry: StaticStyleRegistry;\n /** Current source file path (for devMode source comments) */\n sourceFile?: string;\n /** Whether this file added CSS blocks to the writer (via tastyStatic calls) */\n _fileAddedCSS?: boolean;\n}\n\nfunction mtime(filePath: string): number | null {\n try {\n return fs.statSync(filePath).mtimeMs;\n } catch {\n return null;\n }\n}\n\nfunction clearRequireCacheTree(filePath: string): void {\n let resolved: string;\n\n try {\n resolved = require.resolve(filePath);\n } catch {\n return;\n }\n\n const mod = require.cache[resolved];\n\n if (!mod) return;\n\n const dir = resolved.substring(0, resolved.lastIndexOf('/'));\n\n if (mod.children) {\n for (const child of mod.children) {\n if (child.id.startsWith(dir) && !child.id.includes('node_modules')) {\n clearRequireCacheTree(child.id);\n }\n }\n }\n\n delete require.cache[resolved];\n}\n\n// @ts-expect-error PluginState vs PluginPass type mismatch in @babel/helper-plugin-utils\nexport default declare<TastyZeroBabelOptions>((api, options) => {\n api.assertVersion(7);\n\n const mode = options.mode ?? 'file';\n const outputPath = options.output || 'tasty.css';\n const resolvedOutputPath = path.resolve(outputPath);\n const injectImport = options.injectImport ?? true;\n\n if (mode === 'file' && injectImport) {\n const dir = path.dirname(resolvedOutputPath);\n\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n if (!fs.existsSync(resolvedOutputPath)) {\n fs.writeFileSync(\n resolvedOutputPath,\n '/* Generated by @tenphi/tasty/zero - DO NOT EDIT */\\n',\n );\n }\n }\n\n const configDeps = [\n ...(options.configFile ? [options.configFile] : []),\n ...(options.configDeps || []),\n ];\n\n // Fingerprint for config deps — used to detect config changes\n // and invalidate the shared CSSWriter cache.\n const configKey =\n configDeps.length > 0 ? configDeps.map(mtime).join(',') : '';\n\n // Register external dependencies for babel-loader cache invalidation.\n // When any configDeps file changes, babel-loader discards the cached\n // transform result and re-runs the plugin, picking up fresh config.\n if (configDeps.length > 0) {\n api.cache.using(() => configKey);\n\n for (const dep of configDeps) {\n try {\n (\n api as unknown as { addExternalDependency(path: string): void }\n ).addExternalDependency(dep);\n } catch {\n // addExternalDependency may not be available in all environments\n }\n }\n } else {\n api.cache.forever();\n }\n\n // When configDeps are set, clear the require cache so we get fresh values.\n if (configDeps.length > 0) {\n for (const dep of configDeps) {\n clearRequireCacheTree(dep);\n }\n }\n\n // Look up or create the shared CSSWriter for this output path.\n // When config deps change (different configKey), discard the old writer\n // and reset pipeline state so configure() can run again.\n const cached = writerCache.get(resolvedOutputPath);\n const configChanged = !cached || cached.configKey !== configKey;\n\n if (configChanged) {\n const configOption = options.config;\n let resolvedConfig: TastyZeroConfig;\n\n if (configOption) {\n resolvedConfig =\n typeof configOption === 'function' ? configOption() : configOption;\n } else if (options.configFile) {\n resolvedConfig = loadConfigFile<TastyZeroConfig>(options.configFile);\n } else {\n resolvedConfig = {};\n }\n\n const devMode = resolvedConfig.devMode ?? false;\n\n resetZeroConfig();\n\n // Default to the zero-runtime prefix ('ts') unless the user opts out.\n // Using the same `namePrefix` config entry as the runtime keeps the\n // API uniform; the different default prevents collisions when both\n // runtime and zero-runtime classes appear on the same page.\n const finalConfig: TastyZeroConfig = {\n namePrefix: DEFAULT_ZERO_NAME_PREFIX,\n ...resolvedConfig,\n };\n\n const config = configureZero(finalConfig);\n setExtractorNamePrefix(finalConfig.namePrefix ?? DEFAULT_ZERO_NAME_PREFIX);\n\n const newWriter = new CSSWriter(outputPath, { devMode });\n\n // Emit registered properties, configured tokens and global styles (file\n // mode only; inject mode handles injection per-file in the post hook).\n if (mode !== 'inject') {\n for (const prop of extractConfigProperties(\n config.normalized.properties,\n )) {\n newWriter.add(`@property:${prop.name}`, prop.css);\n }\n\n const tokenCSS = extractCSSFromStyles(':root', config.normalized.tokens);\n if (tokenCSS) newWriter.add(':root:tokens', tokenCSS);\n\n for (const [selector, styles] of Object.entries(\n config.normalized.globalStyles,\n )) {\n writeGlobalStyles(\n newWriter,\n selector,\n styles,\n config.normalized.keyframes,\n );\n }\n }\n\n writerCache.set(resolvedOutputPath, {\n writer: newWriter,\n configKey,\n registry: {},\n config,\n });\n }\n\n const entry = writerCache.get(resolvedOutputPath)!;\n // The engine state is process-wide: another output's build, `withTastyNext()`\n // or `/zero` `configure()` may have replaced this one's since it was cached.\n entry.config = reapplyZeroConfig(entry.config);\n const cssWriter = entry.writer;\n const globalRegistry = entry.registry;\n const config = entry.config;\n const sourceConfig = config.source;\n const devMode = sourceConfig.devMode ?? false;\n // When the writer entry was reused from a previous Babel invocation\n // (configChanged=false), make sure the extractor's module-level prefix\n // still matches this build's config — module state can outlive a\n // single configure() call across worker reuse.\n setExtractorNamePrefix(sourceConfig.namePrefix ?? DEFAULT_ZERO_NAME_PREFIX);\n\n // Tasty's default properties (`#white`, `$gap`, …) and `config.properties`\n // are registered once per output, as the runtime registers them, and\n // inference leaves them alone so the explicit definitions apply.\n const configProperties = extractConfigProperties(\n config.normalized.properties,\n );\n const propertyOptions: PropertyExtractionOptions = {\n autoPropertyTypes: sourceConfig.autoPropertyTypes,\n defined: new Set(configProperties.map((prop) => prop.name)),\n };\n\n // Precompute property, token and global styles CSS for inject mode\n let propertyCSS: string | undefined;\n let tokenCSS: string | undefined;\n let globalStylesCSS: Map<string, string> | undefined;\n if (mode === 'inject') {\n propertyCSS =\n configProperties.map((prop) => prop.css).join('\\n') || undefined;\n tokenCSS = extractCSSFromStyles(':root', config.normalized.tokens);\n const gs = config.normalized.globalStyles;\n if (Object.keys(gs).length > 0) {\n globalStylesCSS = new Map();\n for (const [selector, styles] of Object.entries(gs)) {\n const css = extractCSSFromStyles(\n selector,\n styles,\n config.normalized.keyframes,\n );\n if (css) globalStylesCSS.set(selector, css);\n }\n if (globalStylesCSS.size === 0) globalStylesCSS = undefined;\n }\n }\n\n return {\n name: 'tasty-zero',\n\n pre(this: PluginState) {\n // Babel reuses this plugin instance across files, and another build,\n // `withTastyNext()` or `/zero` `configure()` may have replaced the\n // process-wide engine state in between.\n entry.config = reapplyZeroConfig(entry.config);\n setExtractorNamePrefix(\n sourceConfig.namePrefix ?? DEFAULT_ZERO_NAME_PREFIX,\n );\n\n // Initialize per-file registry\n this.staticStyleRegistry = {};\n this._fileAddedCSS = false;\n // Extract source filename for devMode comments\n if (devMode && this.filename) {\n // Get relative path or just filename\n this.sourceFile = this.filename.split('/').pop() || this.filename;\n }\n },\n\n visitor: {\n ImportDeclaration(\n nodePath: NodePath<t.ImportDeclaration>,\n state: PluginState,\n ) {\n const source = nodePath.node.source.value;\n\n if (\n source === '@tenphi/tasty/static' ||\n source.endsWith('/tasty/static')\n ) {\n if (mode === 'inject') {\n nodePath.replaceWith(\n t.importDeclaration(\n [\n t.importSpecifier(\n t.identifier('_$i'),\n t.identifier('injectCSS'),\n ),\n ],\n t.stringLiteral('@tenphi/tasty/static/inject'),\n ),\n );\n } else if (injectImport) {\n let importPath = resolvedOutputPath;\n\n if (state.filename) {\n const sourceDir = path.dirname(state.filename);\n importPath = path.relative(sourceDir, resolvedOutputPath);\n\n if (!importPath.startsWith('.')) {\n importPath = './' + importPath;\n }\n }\n\n nodePath.replaceWith(\n t.importDeclaration([], t.stringLiteral(importPath)),\n );\n } else {\n nodePath.remove();\n }\n }\n },\n\n // Transform tastyStatic() calls\n CallExpression(path: NodePath<t.CallExpression>, state: PluginState) {\n const callee = path.node.callee;\n\n // Match tastyStatic(...) calls\n if (!t.isIdentifier(callee, { name: 'tastyStatic' })) {\n return;\n }\n\n state._fileAddedCSS = true;\n\n const args = path.node.arguments;\n\n if (args.length === 0) {\n throw path.buildCodeFrameError(\n 'tastyStatic() requires at least one argument',\n );\n }\n\n const firstArg = args[0];\n\n if (t.isStringLiteral(firstArg)) {\n // Selector mode: tastyStatic(selector, styles)\n handleSelectorMode(\n path,\n args,\n cssWriter,\n mode,\n state.sourceFile,\n config.normalized.keyframes,\n propertyOptions,\n config.normalized.fontFaces,\n config.normalized.counterStyles,\n functionsForExtraction(config),\n config.normalized.recipes,\n );\n } else if (t.isObjectExpression(firstArg)) {\n // Styles mode: tastyStatic(styles)\n handleStylesMode(\n path,\n args,\n cssWriter,\n state,\n globalRegistry,\n mode,\n config.normalized.keyframes,\n propertyOptions,\n config.normalized.fontFaces,\n config.normalized.counterStyles,\n functionsForExtraction(config),\n config.normalized.recipes,\n );\n } else if (t.isIdentifier(firstArg)) {\n // Extension mode: tastyStatic(base, styles)\n handleExtensionMode(\n path,\n args,\n cssWriter,\n state,\n globalRegistry,\n mode,\n config.normalized.keyframes,\n propertyOptions,\n config.normalized.fontFaces,\n config.normalized.counterStyles,\n functionsForExtraction(config),\n config.normalized.recipes,\n );\n } else {\n throw path.buildCodeFrameError(\n 'tastyStatic() first argument must be an object (styles), ' +\n 'identifier (base StaticStyle), or string (selector)',\n );\n }\n },\n\n // Track variable declarations to register StaticStyle objects\n VariableDeclarator(\n path: NodePath<t.VariableDeclarator>,\n state: PluginState,\n ) {\n const init = path.node.init;\n const id = path.node.id;\n\n // Check if this is a StaticStyle object (has className and styles properties)\n if (\n t.isIdentifier(id) &&\n t.isObjectExpression(init) &&\n isStaticStyleObject(init)\n ) {\n const variableName = id.name;\n const styles = extractStylesFromStaticStyleObject(init, path);\n const className = extractClassNameFromStaticStyleObject(init);\n\n if (styles && className) {\n state.staticStyleRegistry[variableName] = { styles, className };\n globalRegistry[variableName] = { styles, className };\n }\n }\n },\n },\n\n post(this: PluginState) {\n if (mode === 'inject') {\n // In inject mode, inject property/token/global CSS as top-level\n // statements when this file had tastyStatic calls and config CSS exists.\n if (\n this._fileAddedCSS &&\n (propertyCSS || tokenCSS || globalStylesCSS)\n ) {\n const program = this.file.ast.program;\n\n // Find the position after the inject import\n let insertIndex = 0;\n for (let i = 0; i < program.body.length; i++) {\n if (t.isImportDeclaration(program.body[i])) {\n insertIndex = i + 1;\n }\n }\n\n if (propertyCSS) {\n const injectCall = createInjectCallAST('@property', propertyCSS);\n program.body.splice(\n insertIndex,\n 0,\n t.expressionStatement(injectCall),\n );\n insertIndex++;\n }\n\n if (tokenCSS) {\n const injectCall = createInjectCallAST(':root', tokenCSS);\n program.body.splice(\n insertIndex,\n 0,\n t.expressionStatement(injectCall),\n );\n insertIndex++;\n }\n\n if (globalStylesCSS) {\n for (const [selector, css] of globalStylesCSS) {\n const injectCall = createInjectCallAST(selector, css);\n program.body.splice(\n insertIndex,\n 0,\n t.expressionStatement(injectCall),\n );\n insertIndex++;\n }\n }\n }\n return;\n }\n\n // Only write when this file contributed CSS (had tastyStatic calls).\n // In Turbopack, separate workers each have their own CSSWriter with\n // only token CSS. Letting those workers write would overwrite the\n // complete CSS produced by the worker that processed tastyStatic files.\n if (this._fileAddedCSS && cssWriter.size > 0) {\n cssWriter.write();\n }\n },\n };\n});\n\n/**\n * Check if an object expression looks like a StaticStyle object\n */\nfunction isStaticStyleObject(node: t.ObjectExpression): boolean {\n const hasClassName = node.properties.some(\n (p) =>\n t.isObjectProperty(p) && t.isIdentifier(p.key, { name: 'className' }),\n );\n const hasStyles = node.properties.some(\n (p) => t.isObjectProperty(p) && t.isIdentifier(p.key, { name: 'styles' }),\n );\n return hasClassName && hasStyles;\n}\n\n/**\n * Extract styles object from a StaticStyle object expression\n */\nfunction extractStylesFromStaticStyleObject(\n node: t.ObjectExpression,\n path: NodePath,\n): Styles | null {\n for (const prop of node.properties) {\n if (\n t.isObjectProperty(prop) &&\n t.isIdentifier(prop.key, { name: 'styles' }) &&\n t.isObjectExpression(prop.value)\n ) {\n return evaluateObjectExpression(prop.value, path) as Styles;\n }\n }\n return null;\n}\n\n/**\n * Extract className from a StaticStyle object expression\n */\nfunction extractClassNameFromStaticStyleObject(\n node: t.ObjectExpression,\n): string | null {\n for (const prop of node.properties) {\n if (\n t.isObjectProperty(prop) &&\n t.isIdentifier(prop.key, { name: 'className' }) &&\n t.isStringLiteral(prop.value)\n ) {\n return prop.value.value;\n }\n }\n return null;\n}\n\n/**\n * Handle tastyStatic(styles) - returns StaticStyle object\n */\nfunction handleStylesMode(\n path: NodePath<t.CallExpression>,\n args: t.CallExpression['arguments'],\n cssWriter: CSSWriter,\n state: PluginState,\n globalRegistry: StaticStyleRegistry,\n mode: 'file' | 'inject',\n globalKeyframes?: Record<string, KeyframesSteps>,\n propertyOptions?: PropertyExtractionOptions,\n globalFontFace?: Record<string, FontFaceInput>,\n globalCounterStyle?: Record<string, CounterStyleDescriptors>,\n globalFunction?: Record<string, FunctionDefinition>,\n globalRecipes?: Record<string, RecipeStyles>,\n): void {\n const stylesArg = args[0];\n\n if (!t.isObjectExpression(stylesArg)) {\n throw path.buildCodeFrameError(\n 'tastyStatic(styles) argument must be a static object literal',\n );\n }\n\n // Evaluate styles object at build time\n const rawStyles = evaluateObjectExpression(stylesArg, path) as Styles;\n\n // Resolve recipes before extraction\n const styles = resolveRecipesWith(rawStyles, globalRecipes ?? null);\n\n // Extract keyframes (deduplicated by content)\n const { keyframes, nameMap } = extractKeyframesFromStyles(\n styles,\n globalKeyframes,\n );\n\n // Extract and add auto-inferred @property rules\n const properties = extractPropertiesFromStyles(styles, propertyOptions);\n\n // Extract @font-face rules\n const fontFaces = extractFontFaceFromStyles(styles, globalFontFace);\n\n // Extract @counter-style rules\n const counterStyles = extractCounterStyleFromStyles(\n styles,\n globalCounterStyle,\n );\n\n // Extract @function rules\n const functions = extractFunctionsFromStyles(styles, globalFunction);\n\n // Extract styles with chunking\n const chunks = extractChunks(styles);\n\n const className =\n chunks.length > 0 ? chunks.map((c) => c.className).join(' ') : '';\n const staticStyleObject = createStaticStyleAST(className, styles);\n\n if (mode === 'inject') {\n const allCSS = collectAllCSS(\n keyframes,\n properties,\n fontFaces,\n counterStyles,\n functions,\n chunks,\n nameMap,\n );\n const injectCall = createInjectCallAST(className, allCSS);\n\n path.replaceWith(t.sequenceExpression([injectCall, staticStyleObject]));\n } else {\n writeCSSToWriter(\n cssWriter,\n keyframes,\n properties,\n fontFaces,\n counterStyles,\n functions,\n chunks,\n nameMap,\n state.sourceFile,\n );\n path.replaceWith(staticStyleObject);\n }\n\n registerIfVariableDeclaration(path, className, styles, state, globalRegistry);\n}\n\n/**\n * Handle tastyStatic(base, styles) - extends base with additional styles\n */\nfunction handleExtensionMode(\n path: NodePath<t.CallExpression>,\n args: t.CallExpression['arguments'],\n cssWriter: CSSWriter,\n state: PluginState,\n globalRegistry: StaticStyleRegistry,\n mode: 'file' | 'inject',\n globalKeyframes?: Record<string, KeyframesSteps>,\n propertyOptions?: PropertyExtractionOptions,\n globalFontFace?: Record<string, FontFaceInput>,\n globalCounterStyle?: Record<string, CounterStyleDescriptors>,\n globalFunction?: Record<string, FunctionDefinition>,\n globalRecipes?: Record<string, RecipeStyles>,\n): void {\n if (args.length < 2) {\n throw path.buildCodeFrameError(\n 'tastyStatic(base, styles) requires two arguments',\n );\n }\n\n const baseArg = args[0];\n const stylesArg = args[1];\n\n if (!t.isIdentifier(baseArg)) {\n throw path.buildCodeFrameError(\n 'tastyStatic(base, styles) first argument must be an identifier',\n );\n }\n\n if (!t.isObjectExpression(stylesArg)) {\n throw path.buildCodeFrameError(\n 'tastyStatic(base, styles) second argument must be a static object literal',\n );\n }\n\n const baseName = baseArg.name;\n\n // Look up base styles in registry\n const baseEntry =\n state.staticStyleRegistry[baseName] || globalRegistry[baseName];\n\n if (!baseEntry) {\n throw path.buildCodeFrameError(\n `Cannot find base StaticStyle '${baseName}'. ` +\n 'Make sure it is defined before being extended.',\n );\n }\n\n // Evaluate override styles\n const overrideStyles = evaluateObjectExpression(stylesArg, path) as Styles;\n\n // Merge styles using mergeStyles, then resolve recipes\n const mergedStyles = resolveRecipesWith(\n mergeStyles(baseEntry.styles, overrideStyles),\n globalRecipes ?? null,\n );\n\n // Extract keyframes (deduplicated by content)\n const { keyframes, nameMap } = extractKeyframesFromStyles(\n mergedStyles,\n globalKeyframes,\n );\n\n // Extract auto-inferred @property rules\n const properties = extractPropertiesFromStyles(mergedStyles, propertyOptions);\n\n // Extract @font-face rules\n const fontFaces = extractFontFaceFromStyles(mergedStyles, globalFontFace);\n\n // Extract @counter-style rules\n const counterStyles = extractCounterStyleFromStyles(\n mergedStyles,\n globalCounterStyle,\n );\n\n // Extract @function rules\n const functions = extractFunctionsFromStyles(mergedStyles, globalFunction);\n\n // Extract styles with chunking\n const chunks = extractChunks(mergedStyles);\n\n const className =\n chunks.length > 0 ? chunks.map((c) => c.className).join(' ') : '';\n const staticStyleObject = createStaticStyleAST(className, mergedStyles);\n\n if (mode === 'inject') {\n const allCSS = collectAllCSS(\n keyframes,\n properties,\n fontFaces,\n counterStyles,\n functions,\n chunks,\n nameMap,\n );\n const injectCall = createInjectCallAST(className, allCSS);\n\n path.replaceWith(t.sequenceExpression([injectCall, staticStyleObject]));\n } else {\n writeCSSToWriter(\n cssWriter,\n keyframes,\n properties,\n fontFaces,\n counterStyles,\n functions,\n chunks,\n nameMap,\n state.sourceFile,\n );\n path.replaceWith(staticStyleObject);\n }\n\n registerIfVariableDeclaration(\n path,\n className,\n mergedStyles,\n state,\n globalRegistry,\n );\n}\n\n/**\n * Handle tastyStatic(selector, styles) - removes the call entirely\n */\nfunction handleSelectorMode(\n path: NodePath<t.CallExpression>,\n args: t.CallExpression['arguments'],\n cssWriter: CSSWriter,\n mode: 'file' | 'inject',\n sourceFile?: string,\n globalKeyframes?: Record<string, KeyframesSteps>,\n propertyOptions?: PropertyExtractionOptions,\n globalFontFace?: Record<string, FontFaceInput>,\n globalCounterStyle?: Record<string, CounterStyleDescriptors>,\n globalFunction?: Record<string, FunctionDefinition>,\n globalRecipes?: Record<string, RecipeStyles>,\n): void {\n if (args.length < 2) {\n throw path.buildCodeFrameError(\n 'tastyStatic(selector, styles) requires two arguments',\n );\n }\n\n const selectorArg = args[0];\n const stylesArg = args[1];\n\n if (!t.isStringLiteral(selectorArg)) {\n throw path.buildCodeFrameError(\n 'tastyStatic(selector, styles) first argument must be a string literal',\n );\n }\n\n if (!t.isObjectExpression(stylesArg)) {\n throw path.buildCodeFrameError(\n 'tastyStatic(selector, styles) second argument must be a static object literal',\n );\n }\n\n const selector = selectorArg.value;\n const rawStyles = evaluateObjectExpression(stylesArg, path) as Styles;\n\n // Resolve recipes before extraction\n const styles = resolveRecipesWith(rawStyles, globalRecipes ?? null);\n\n // Extract keyframes (deduplicated by content)\n const { keyframes, nameMap } = extractKeyframesFromStyles(\n styles,\n globalKeyframes,\n );\n\n // Extract auto-inferred @property rules\n const properties = extractPropertiesFromStyles(styles, propertyOptions);\n\n // Extract @font-face rules\n const fontFaces = extractFontFaceFromStyles(styles, globalFontFace);\n\n // Extract @counter-style rules\n const counterStyles = extractCounterStyleFromStyles(\n styles,\n globalCounterStyle,\n );\n\n // Extract @function rules\n const functions = extractFunctionsFromStyles(styles, globalFunction);\n\n // Extract styles for selector; the keyframes above are emitted separately\n const css = renderSelectorCSS(selector, styles);\n\n const selectorCSS =\n nameMap.size > 0 ? replaceAnimationNamesInCSS(css, nameMap) : css;\n\n if (mode === 'inject') {\n const cssParts: string[] = [];\n\n for (const kf of keyframes) cssParts.push(kf.css);\n for (const prop of properties) cssParts.push(prop.css);\n for (const ff of fontFaces) cssParts.push(ff.css);\n for (const cs of counterStyles) cssParts.push(cs.css);\n for (const fn of functions) cssParts.push(fn.css);\n cssParts.push(selectorCSS);\n\n const injectCall = createInjectCallAST(selector, cssParts.join('\\n'));\n\n const parent = path.parentPath;\n if (parent && t.isExpressionStatement(parent.node)) {\n parent.replaceWith(t.expressionStatement(injectCall));\n } else {\n path.replaceWith(injectCall);\n }\n } else {\n writeCSSToWriter(\n cssWriter,\n keyframes,\n properties,\n fontFaces,\n counterStyles,\n functions,\n [],\n nameMap,\n sourceFile,\n );\n cssWriter.add(selector, selectorCSS, sourceFile);\n\n const parent = path.parentPath;\n if (parent && t.isExpressionStatement(parent.node)) {\n parent.remove();\n } else {\n path.replaceWith(t.identifier('undefined'));\n }\n }\n}\n\n/**\n * Collect all extracted CSS parts into a single string (for inject mode).\n */\nfunction collectAllCSS(\n keyframes: ExtractedKeyframes[],\n properties: ExtractedProperty[],\n fontFaces: ExtractedFontFace[],\n counterStyles: ExtractedCounterStyle[],\n functions: ExtractedFunction[],\n chunks: ExtractedChunk[],\n nameMap: Map<string, string>,\n): string {\n const parts: string[] = [];\n\n for (const kf of keyframes) parts.push(kf.css);\n for (const prop of properties) parts.push(prop.css);\n for (const ff of fontFaces) parts.push(ff.css);\n for (const cs of counterStyles) parts.push(cs.css);\n for (const fn of functions) parts.push(fn.css);\n\n for (const chunk of chunks) {\n parts.push(\n nameMap.size > 0\n ? replaceAnimationNamesInCSS(chunk.css, nameMap)\n : chunk.css,\n );\n }\n\n return parts.join('\\n');\n}\n\n/**\n * Write all extracted CSS parts to a CSSWriter (for file mode).\n */\nfunction writeCSSToWriter(\n cssWriter: CSSWriter,\n keyframes: ExtractedKeyframes[],\n properties: ExtractedProperty[],\n fontFaces: ExtractedFontFace[],\n counterStyles: ExtractedCounterStyle[],\n functions: ExtractedFunction[],\n chunks: ExtractedChunk[],\n nameMap: Map<string, string>,\n sourceFile?: string,\n): void {\n for (const kf of keyframes) {\n cssWriter.add(kf.css, kf.css, sourceFile);\n }\n for (const prop of properties) {\n cssWriter.add(prop.css, prop.css, sourceFile);\n }\n for (const ff of fontFaces) {\n cssWriter.add(ff.css, ff.css, sourceFile);\n }\n for (const cs of counterStyles) {\n cssWriter.add(cs.css, cs.css, sourceFile);\n }\n for (const fn of functions) {\n cssWriter.add(fn.css, fn.css, sourceFile);\n }\n\n for (const chunk of chunks) {\n const css =\n nameMap.size > 0\n ? replaceAnimationNamesInCSS(chunk.css, nameMap)\n : chunk.css;\n cssWriter.add(chunk.className, css, sourceFile);\n }\n}\n\n/**\n * Extract CSS for a selector from a styles/tokens object, with the keyframes\n * it animates. Returns undefined when there are no styles or no CSS output.\n */\nfunction extractCSSFromStyles(\n selector: string,\n styles: Styles | ConfigTokens | null,\n globalKeyframes?: Record<string, KeyframesSteps>,\n): string | undefined {\n if (!styles || Object.keys(styles).length === 0) return undefined;\n return (\n extractSelectorCSS(selector, styles as Styles, globalKeyframes) || undefined\n );\n}\n\n/**\n * Write a configured global selector's CSS, with the keyframes it animates\n * keyed by their CSS so selectors sharing one emit it once.\n */\nfunction writeGlobalStyles(\n cssWriter: CSSWriter,\n selector: string,\n styles: Styles,\n globalKeyframes: Record<string, KeyframesSteps>,\n): void {\n const { keyframes, nameMap } = extractKeyframesFromStyles(\n styles,\n globalKeyframes,\n );\n for (const kf of keyframes) {\n cssWriter.add(kf.css, kf.css);\n }\n\n const css = replaceAnimationNamesInCSS(\n renderSelectorCSS(selector, styles),\n nameMap,\n );\n if (css) cssWriter.add(`global:${selector}`, css);\n}\n\n/**\n * Create an `_$i(id, css)` call expression AST node for inject mode.\n */\nfunction createInjectCallAST(id: string, css: string): t.CallExpression {\n return t.callExpression(t.identifier('_$i'), [\n t.stringLiteral(id),\n t.stringLiteral(css),\n ]);\n}\n\n/**\n * Create a StaticStyle object AST node\n */\nfunction createStaticStyleAST(\n className: string,\n styles: Styles,\n): t.ObjectExpression {\n return t.objectExpression([\n t.objectProperty(t.identifier('className'), t.stringLiteral(className)),\n t.objectProperty(t.identifier('styles'), valueToAST(styles)),\n t.objectMethod(\n 'method',\n t.identifier('toString'),\n [],\n t.blockStatement([\n t.returnStatement(\n t.memberExpression(t.thisExpression(), t.identifier('className')),\n ),\n ]),\n ),\n ]);\n}\n\n/**\n * Register a StaticStyle in the registry if it's being assigned to a variable\n */\nfunction registerIfVariableDeclaration(\n path: NodePath,\n className: string,\n styles: Styles,\n state: PluginState,\n globalRegistry: StaticStyleRegistry,\n): void {\n const parent = path.parentPath;\n if (parent && t.isVariableDeclarator(parent.node)) {\n const id = parent.node.id;\n if (t.isIdentifier(id)) {\n const variableName = id.name;\n state.staticStyleRegistry[variableName] = { styles, className };\n globalRegistry[variableName] = { styles, className };\n }\n }\n}\n\n/**\n * Convert a JavaScript value to an AST node\n */\nfunction valueToAST(value: unknown): t.Expression {\n if (value === null) {\n return t.nullLiteral();\n }\n if (value === undefined) {\n return t.identifier('undefined');\n }\n if (typeof value === 'string') {\n return t.stringLiteral(value);\n }\n if (typeof value === 'number') {\n return t.numericLiteral(value);\n }\n if (typeof value === 'boolean') {\n return t.booleanLiteral(value);\n }\n if (Array.isArray(value)) {\n return t.arrayExpression(value.map(valueToAST));\n }\n if (typeof value === 'object') {\n const properties = Object.entries(value).map(([key, val]) =>\n t.objectProperty(\n /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)\n ? t.identifier(key)\n : t.stringLiteral(key),\n valueToAST(val),\n ),\n );\n return t.objectExpression(properties);\n }\n // Fallback for unsupported types\n return t.identifier('undefined');\n}\n\n/**\n * Evaluate an ObjectExpression to a plain JavaScript object.\n * Only supports static values that can be determined at build time.\n */\nfunction evaluateObjectExpression(\n node: t.ObjectExpression,\n path: NodePath,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const prop of node.properties) {\n if (t.isSpreadElement(prop)) {\n throw path.buildCodeFrameError(\n 'Spread elements are not supported in tastyStatic() - styles must be fully static',\n );\n }\n\n if (!t.isObjectProperty(prop)) {\n throw path.buildCodeFrameError(\n 'Only object properties are supported in tastyStatic()',\n );\n }\n\n // Get key\n let key: string;\n if (t.isIdentifier(prop.key)) {\n key = prop.key.name;\n } else if (t.isStringLiteral(prop.key)) {\n key = prop.key.value;\n } else {\n throw path.buildCodeFrameError(\n 'Dynamic property keys are not supported in tastyStatic()',\n );\n }\n\n // Get value\n const value = evaluateExpression(prop.value, path);\n result[key] = value;\n }\n\n return result;\n}\n\n/**\n * Evaluate an expression to a JavaScript value.\n */\nfunction evaluateExpression(node: t.Node, path: NodePath): unknown {\n if (t.isStringLiteral(node)) {\n return node.value;\n }\n\n if (t.isNumericLiteral(node)) {\n return node.value;\n }\n\n if (t.isBooleanLiteral(node)) {\n return node.value;\n }\n\n if (t.isNullLiteral(node)) {\n return null;\n }\n\n if (t.isIdentifier(node, { name: 'undefined' })) {\n return undefined;\n }\n\n if (t.isArrayExpression(node)) {\n return node.elements.map((el) => {\n if (el === null) return null;\n if (t.isSpreadElement(el)) {\n throw path.buildCodeFrameError(\n 'Spread elements are not supported in tastyStatic()',\n );\n }\n return evaluateExpression(el, path);\n });\n }\n\n if (t.isObjectExpression(node)) {\n return evaluateObjectExpression(node, path);\n }\n\n if (t.isTemplateLiteral(node)) {\n // Only support template literals without expressions\n if (node.expressions.length > 0) {\n throw path.buildCodeFrameError(\n 'Template literals with expressions are not supported in tastyStatic()',\n );\n }\n return node.quasis.map((q) => q.value.cooked).join('');\n }\n\n if (t.isUnaryExpression(node, { operator: '-' })) {\n const arg = evaluateExpression(node.argument, path);\n if (typeof arg === 'number') {\n return -arg;\n }\n }\n\n throw path.buildCodeFrameError(\n `Dynamic expressions are not supported in tastyStatic() - got ${node.type}. ` +\n 'All values must be static literals.',\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"babel.js","names":[],"sources":["../../src/zero/writer-cache.ts","../../src/zero/babel.ts"],"sourcesContent":["/**\n * Internal shared CSSWriter cache for the zero-runtime Babel plugin.\n *\n * Kept in a separate non-exported module so `clearWriterCache` is not part\n * of the public `@tenphi/tasty/babel-plugin` entry surface. The Babel plugin\n * and its tests import from here directly.\n */\n\nimport type { CSSWriter } from './css-writer';\nimport type { Styles } from '../styles/types';\nimport type { ResolvedZeroConfig } from './config';\n\n/**\n * Registry of static styles keyed by their source identifier.\n * Used to resolve base styles when extending.\n */\nexport type StaticStyleRegistry = Record<\n string,\n {\n styles: Styles;\n className: string;\n }\n>;\n\nexport interface WriterCacheEntry {\n writer: CSSWriter;\n configKey: string;\n registry: StaticStyleRegistry;\n config: ResolvedZeroConfig;\n}\n\nexport const writerCache = new Map<string, WriterCacheEntry>();\n\n/** Clear the shared CSSWriter cache. Exposed for testing. */\nexport function clearWriterCache(): void {\n writerCache.clear();\n}\n","/**\n * Babel plugin for zero-runtime tasty static site generation.\n *\n * Transforms:\n * - `tastyStatic(styles)` → StaticStyle object { className, styles, toString() }\n * - `tastyStatic(base, styles)` → StaticStyle object with merged styles\n * - `tastyStatic(selector, styles)` → removed entirely\n *\n * Usage:\n * ```javascript\n * // babel.config.js\n * module.exports = {\n * plugins: [\n * ['@tenphi/tasty/babel-plugin', { output: 'public/tasty.css' }]\n * ]\n * };\n * ```\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { declare } from '@babel/helper-plugin-utils';\nimport * as t from '@babel/types';\n\nimport type { ConfigTokens, RecipeStyles, Styles } from '../styles/types';\nimport { mergeStyles } from '../utils/merge-styles';\nimport { DEFAULT_ZERO_NAME_PREFIX } from '../utils/name-prefix';\nimport { resolveRecipesWith } from '../utils/resolve-recipes-core';\n\nimport { loadConfigFile } from './config-file';\nimport { CSSWriter } from './css-writer';\nimport type { TastyZeroConfig } from './babel-types';\nexport type { TastyZeroConfig } from './babel-types';\nimport {\n configureZero,\n functionsForExtraction,\n reapplyZeroConfig,\n resetZeroConfig,\n} from './config';\nimport { writerCache, type StaticStyleRegistry } from './writer-cache';\nimport {\n extractConfigProperties,\n extractCounterStyleFromStyles,\n extractFontFaceFromStyles,\n extractFunctionsFromStyles,\n extractKeyframesFromStyles,\n extractPropertiesFromStyles,\n extractChunks,\n extractSelectorCSS,\n renderSelectorCSS,\n replaceAnimationNamesInCSS,\n setExtractorNamePrefix,\n} from './extractor';\nimport type {\n ExtractedChunk,\n ExtractedCounterStyle,\n ExtractedFontFace,\n ExtractedFunction,\n ExtractedKeyframes,\n ExtractedProperty,\n PropertyExtractionOptions,\n} from './extractor';\n\nimport type { NodePath, PluginPass } from '@babel/core';\nimport type {\n CounterStyleDescriptors,\n FontFaceInput,\n FunctionDefinition,\n KeyframesSteps,\n} from '../injector/types';\n\n/**\n * Options for the `@tenphi/tasty/babel-plugin` Babel plugin.\n */\nexport interface TastyZeroBabelOptions {\n /** Output path for generated CSS (default: 'tasty.css') */\n output?: string;\n /**\n * Tasty configuration for build-time processing.\n * Can be a static object or a factory function that returns fresh config.\n * A factory is called on each plugin invocation, enabling hot reload\n * of config values that depend on external files (e.g. theme tokens).\n */\n config?: TastyZeroConfig | (() => TastyZeroConfig);\n /**\n * Absolute path to a TypeScript/JavaScript module that default-exports\n * a `TastyZeroConfig` object. The module is loaded via jiti on each\n * plugin invocation, enabling hot reload when the file changes.\n *\n * This option is JSON-serializable and is the primary way Turbopack\n * passes config to the Babel plugin (since Turbopack loader options\n * must be plain primitives/objects/arrays).\n *\n * When both `config` and `configFile` are set, `config` takes precedence.\n *\n * @example '/absolute/path/to/tasty-zero.config.ts'\n */\n configFile?: string;\n /**\n * Absolute file paths whose content affects the generated CSS.\n * When any of these files change, babel-loader invalidates its cache\n * and re-runs the plugin with fresh config values.\n *\n * Typically includes theme files that define Glaze palettes or token values.\n * Paths must be absolute (resolved by the Next.js wrapper).\n */\n configDeps?: string[];\n /**\n * Automatically replace `@tenphi/tasty/static` imports with an import\n * of the generated CSS file. This eliminates the need for users to\n * manually import the CSS in their app entry point.\n *\n * @default true\n */\n injectImport?: boolean;\n /**\n * Output mode for extracted CSS.\n *\n * - `'file'` (default): CSS is written to a single output file and\n * the `@tenphi/tasty/static` import is rewritten to import that file.\n * - `'inject'`: CSS is embedded inline in the JS output and injected\n * at runtime via a tiny injector from `@tenphi/tasty/static/inject`.\n * No CSS file is written. Each `tastyStatic` call becomes\n * self-contained. Best for reusable components and extensions.\n *\n * When `mode` is `'inject'`, `output` and `injectImport` are ignored.\n *\n * @default 'file'\n */\n mode?: 'file' | 'inject';\n}\n\ninterface PluginState extends PluginPass {\n staticStyleRegistry: StaticStyleRegistry;\n /** Current source file path (for devMode source comments) */\n sourceFile?: string;\n /** Whether this file added CSS blocks to the writer (via tastyStatic calls) */\n _fileAddedCSS?: boolean;\n}\n\n/**\n * The plugin's call signature, written out rather than inferred from\n * `declare()` so the published declaration names no Babel types: Babel 7's\n * come from `@types/babel__core`, Babel 8 ships its own, and the two name the\n * plugin object differently.\n */\ntype TastyZeroBabelPlugin = (\n api: object,\n options: TastyZeroBabelOptions | null | undefined,\n dirname: string,\n) => object;\n\nfunction mtime(filePath: string): number | null {\n try {\n return fs.statSync(filePath).mtimeMs;\n } catch {\n return null;\n }\n}\n\nfunction clearRequireCacheTree(filePath: string): void {\n let resolved: string;\n\n try {\n resolved = require.resolve(filePath);\n } catch {\n return;\n }\n\n const mod = require.cache[resolved];\n\n if (!mod) return;\n\n const dir = resolved.substring(0, resolved.lastIndexOf('/'));\n\n if (mod.children) {\n for (const child of mod.children) {\n if (child.id.startsWith(dir) && !child.id.includes('node_modules')) {\n clearRequireCacheTree(child.id);\n }\n }\n }\n\n delete require.cache[resolved];\n}\n\nconst plugin = declare<PluginState, TastyZeroBabelOptions>((api, options) => {\n // `^7.0.0-0` is what `assertVersion(7)` checks; Babel 8 rejects that number.\n api.assertVersion('^7.0.0-0 || ^8.0.0-0');\n\n const mode = options.mode ?? 'file';\n const outputPath = options.output || 'tasty.css';\n const resolvedOutputPath = path.resolve(outputPath);\n const injectImport = options.injectImport ?? true;\n\n if (mode === 'file' && injectImport) {\n const dir = path.dirname(resolvedOutputPath);\n\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n if (!fs.existsSync(resolvedOutputPath)) {\n fs.writeFileSync(\n resolvedOutputPath,\n '/* Generated by @tenphi/tasty/zero - DO NOT EDIT */\\n',\n );\n }\n }\n\n const configDeps = [\n ...(options.configFile ? [options.configFile] : []),\n ...(options.configDeps || []),\n ];\n\n // Fingerprint for config deps — used to detect config changes\n // and invalidate the shared CSSWriter cache.\n const configKey =\n configDeps.length > 0 ? configDeps.map(mtime).join(',') : '';\n\n // Register external dependencies for babel-loader cache invalidation.\n // When any configDeps file changes, babel-loader discards the cached\n // transform result and re-runs the plugin, picking up fresh config.\n if (configDeps.length > 0) {\n api.cache.using(() => configKey);\n\n for (const dep of configDeps) {\n try {\n (\n api as unknown as { addExternalDependency(path: string): void }\n ).addExternalDependency(dep);\n } catch {\n // addExternalDependency may not be available in all environments\n }\n }\n } else {\n api.cache.forever();\n }\n\n // When configDeps are set, clear the require cache so we get fresh values.\n if (configDeps.length > 0) {\n for (const dep of configDeps) {\n clearRequireCacheTree(dep);\n }\n }\n\n // Look up or create the shared CSSWriter for this output path.\n // When config deps change (different configKey), discard the old writer\n // and reset pipeline state so configure() can run again.\n const cached = writerCache.get(resolvedOutputPath);\n const configChanged = !cached || cached.configKey !== configKey;\n\n if (configChanged) {\n const configOption = options.config;\n let resolvedConfig: TastyZeroConfig;\n\n if (configOption) {\n resolvedConfig =\n typeof configOption === 'function' ? configOption() : configOption;\n } else if (options.configFile) {\n resolvedConfig = loadConfigFile<TastyZeroConfig>(options.configFile);\n } else {\n resolvedConfig = {};\n }\n\n const devMode = resolvedConfig.devMode ?? false;\n\n resetZeroConfig();\n\n // Default to the zero-runtime prefix ('ts') unless the user opts out.\n // Using the same `namePrefix` config entry as the runtime keeps the\n // API uniform; the different default prevents collisions when both\n // runtime and zero-runtime classes appear on the same page.\n const finalConfig: TastyZeroConfig = {\n namePrefix: DEFAULT_ZERO_NAME_PREFIX,\n ...resolvedConfig,\n };\n\n const config = configureZero(finalConfig);\n setExtractorNamePrefix(finalConfig.namePrefix ?? DEFAULT_ZERO_NAME_PREFIX);\n\n const newWriter = new CSSWriter(outputPath, { devMode });\n\n // Emit registered properties, configured tokens and global styles (file\n // mode only; inject mode handles injection per-file in the post hook).\n if (mode !== 'inject') {\n for (const prop of extractConfigProperties(\n config.normalized.properties,\n )) {\n newWriter.add(`@property:${prop.name}`, prop.css);\n }\n\n const tokenCSS = extractCSSFromStyles(':root', config.normalized.tokens);\n if (tokenCSS) newWriter.add(':root:tokens', tokenCSS);\n\n for (const [selector, styles] of Object.entries(\n config.normalized.globalStyles,\n )) {\n writeGlobalStyles(\n newWriter,\n selector,\n styles,\n config.normalized.keyframes,\n );\n }\n }\n\n writerCache.set(resolvedOutputPath, {\n writer: newWriter,\n configKey,\n registry: {},\n config,\n });\n }\n\n const entry = writerCache.get(resolvedOutputPath)!;\n // The engine state is process-wide: another output's build, `withTastyNext()`\n // or `/zero` `configure()` may have replaced this one's since it was cached.\n entry.config = reapplyZeroConfig(entry.config);\n const cssWriter = entry.writer;\n const globalRegistry = entry.registry;\n const config = entry.config;\n const sourceConfig = config.source;\n const devMode = sourceConfig.devMode ?? false;\n // When the writer entry was reused from a previous Babel invocation\n // (configChanged=false), make sure the extractor's module-level prefix\n // still matches this build's config — module state can outlive a\n // single configure() call across worker reuse.\n setExtractorNamePrefix(sourceConfig.namePrefix ?? DEFAULT_ZERO_NAME_PREFIX);\n\n // Tasty's default properties (`#white`, `$gap`, …) and `config.properties`\n // are registered once per output, as the runtime registers them, and\n // inference leaves them alone so the explicit definitions apply.\n const configProperties = extractConfigProperties(\n config.normalized.properties,\n );\n const propertyOptions: PropertyExtractionOptions = {\n autoPropertyTypes: sourceConfig.autoPropertyTypes,\n defined: new Set(configProperties.map((prop) => prop.name)),\n };\n\n // Precompute property, token and global styles CSS for inject mode\n let propertyCSS: string | undefined;\n let tokenCSS: string | undefined;\n let globalStylesCSS: Map<string, string> | undefined;\n if (mode === 'inject') {\n propertyCSS =\n configProperties.map((prop) => prop.css).join('\\n') || undefined;\n tokenCSS = extractCSSFromStyles(':root', config.normalized.tokens);\n const gs = config.normalized.globalStyles;\n if (Object.keys(gs).length > 0) {\n globalStylesCSS = new Map();\n for (const [selector, styles] of Object.entries(gs)) {\n const css = extractCSSFromStyles(\n selector,\n styles,\n config.normalized.keyframes,\n );\n if (css) globalStylesCSS.set(selector, css);\n }\n if (globalStylesCSS.size === 0) globalStylesCSS = undefined;\n }\n }\n\n return {\n name: 'tasty-zero',\n\n pre(this: PluginState) {\n // Babel reuses this plugin instance across files, and another build,\n // `withTastyNext()` or `/zero` `configure()` may have replaced the\n // process-wide engine state in between.\n entry.config = reapplyZeroConfig(entry.config);\n setExtractorNamePrefix(\n sourceConfig.namePrefix ?? DEFAULT_ZERO_NAME_PREFIX,\n );\n\n // Initialize per-file registry\n this.staticStyleRegistry = {};\n this._fileAddedCSS = false;\n // Extract source filename for devMode comments\n if (devMode && this.filename) {\n // Get relative path or just filename\n this.sourceFile = this.filename.split('/').pop() || this.filename;\n }\n },\n\n visitor: {\n ImportDeclaration(\n nodePath: NodePath<t.ImportDeclaration>,\n state: PluginState,\n ) {\n const source = nodePath.node.source.value;\n\n if (\n source === '@tenphi/tasty/static' ||\n source.endsWith('/tasty/static')\n ) {\n if (mode === 'inject') {\n nodePath.replaceWith(\n t.importDeclaration(\n [\n t.importSpecifier(\n t.identifier('_$i'),\n t.identifier('injectCSS'),\n ),\n ],\n t.stringLiteral('@tenphi/tasty/static/inject'),\n ),\n );\n } else if (injectImport) {\n let importPath = resolvedOutputPath;\n\n if (state.filename) {\n const sourceDir = path.dirname(state.filename);\n importPath = path.relative(sourceDir, resolvedOutputPath);\n\n if (!importPath.startsWith('.')) {\n importPath = './' + importPath;\n }\n }\n\n nodePath.replaceWith(\n t.importDeclaration([], t.stringLiteral(importPath)),\n );\n } else {\n nodePath.remove();\n }\n }\n },\n\n // Transform tastyStatic() calls\n CallExpression(path: NodePath<t.CallExpression>, state: PluginState) {\n const callee = path.node.callee;\n\n // Match tastyStatic(...) calls\n if (!t.isIdentifier(callee, { name: 'tastyStatic' })) {\n return;\n }\n\n state._fileAddedCSS = true;\n\n const args = path.node.arguments;\n\n if (args.length === 0) {\n throw path.buildCodeFrameError(\n 'tastyStatic() requires at least one argument',\n );\n }\n\n const firstArg = args[0];\n\n if (t.isStringLiteral(firstArg)) {\n // Selector mode: tastyStatic(selector, styles)\n handleSelectorMode(\n path,\n args,\n cssWriter,\n mode,\n state.sourceFile,\n config.normalized.keyframes,\n propertyOptions,\n config.normalized.fontFaces,\n config.normalized.counterStyles,\n functionsForExtraction(config),\n config.normalized.recipes,\n );\n } else if (t.isObjectExpression(firstArg)) {\n // Styles mode: tastyStatic(styles)\n handleStylesMode(\n path,\n args,\n cssWriter,\n state,\n globalRegistry,\n mode,\n config.normalized.keyframes,\n propertyOptions,\n config.normalized.fontFaces,\n config.normalized.counterStyles,\n functionsForExtraction(config),\n config.normalized.recipes,\n );\n } else if (t.isIdentifier(firstArg)) {\n // Extension mode: tastyStatic(base, styles)\n handleExtensionMode(\n path,\n args,\n cssWriter,\n state,\n globalRegistry,\n mode,\n config.normalized.keyframes,\n propertyOptions,\n config.normalized.fontFaces,\n config.normalized.counterStyles,\n functionsForExtraction(config),\n config.normalized.recipes,\n );\n } else {\n throw path.buildCodeFrameError(\n 'tastyStatic() first argument must be an object (styles), ' +\n 'identifier (base StaticStyle), or string (selector)',\n );\n }\n },\n\n // Track variable declarations to register StaticStyle objects\n VariableDeclarator(\n path: NodePath<t.VariableDeclarator>,\n state: PluginState,\n ) {\n const init = path.node.init;\n const id = path.node.id;\n\n // Check if this is a StaticStyle object (has className and styles properties)\n if (\n t.isIdentifier(id) &&\n t.isObjectExpression(init) &&\n isStaticStyleObject(init)\n ) {\n const variableName = id.name;\n const styles = extractStylesFromStaticStyleObject(init, path);\n const className = extractClassNameFromStaticStyleObject(init);\n\n if (styles && className) {\n state.staticStyleRegistry[variableName] = { styles, className };\n globalRegistry[variableName] = { styles, className };\n }\n }\n },\n },\n\n post(this: PluginState) {\n if (mode === 'inject') {\n // In inject mode, inject property/token/global CSS as top-level\n // statements when this file had tastyStatic calls and config CSS exists.\n if (\n this._fileAddedCSS &&\n (propertyCSS || tokenCSS || globalStylesCSS)\n ) {\n const program = this.file.ast.program;\n\n // Find the position after the inject import\n let insertIndex = 0;\n for (let i = 0; i < program.body.length; i++) {\n if (t.isImportDeclaration(program.body[i])) {\n insertIndex = i + 1;\n }\n }\n\n if (propertyCSS) {\n const injectCall = createInjectCallAST('@property', propertyCSS);\n program.body.splice(\n insertIndex,\n 0,\n t.expressionStatement(injectCall),\n );\n insertIndex++;\n }\n\n if (tokenCSS) {\n const injectCall = createInjectCallAST(':root', tokenCSS);\n program.body.splice(\n insertIndex,\n 0,\n t.expressionStatement(injectCall),\n );\n insertIndex++;\n }\n\n if (globalStylesCSS) {\n for (const [selector, css] of globalStylesCSS) {\n const injectCall = createInjectCallAST(selector, css);\n program.body.splice(\n insertIndex,\n 0,\n t.expressionStatement(injectCall),\n );\n insertIndex++;\n }\n }\n }\n return;\n }\n\n // Only write when this file contributed CSS (had tastyStatic calls).\n // In Turbopack, separate workers each have their own CSSWriter with\n // only token CSS. Letting those workers write would overwrite the\n // complete CSS produced by the worker that processed tastyStatic files.\n if (this._fileAddedCSS && cssWriter.size > 0) {\n cssWriter.write();\n }\n },\n };\n});\n\nexport default plugin as TastyZeroBabelPlugin;\n\n/**\n * Check if an object expression looks like a StaticStyle object\n */\nfunction isStaticStyleObject(node: t.ObjectExpression): boolean {\n const hasClassName = node.properties.some(\n (p) =>\n t.isObjectProperty(p) && t.isIdentifier(p.key, { name: 'className' }),\n );\n const hasStyles = node.properties.some(\n (p) => t.isObjectProperty(p) && t.isIdentifier(p.key, { name: 'styles' }),\n );\n return hasClassName && hasStyles;\n}\n\n/**\n * Extract styles object from a StaticStyle object expression\n */\nfunction extractStylesFromStaticStyleObject(\n node: t.ObjectExpression,\n path: NodePath,\n): Styles | null {\n for (const prop of node.properties) {\n if (\n t.isObjectProperty(prop) &&\n t.isIdentifier(prop.key, { name: 'styles' }) &&\n t.isObjectExpression(prop.value)\n ) {\n return evaluateObjectExpression(prop.value, path) as Styles;\n }\n }\n return null;\n}\n\n/**\n * Extract className from a StaticStyle object expression\n */\nfunction extractClassNameFromStaticStyleObject(\n node: t.ObjectExpression,\n): string | null {\n for (const prop of node.properties) {\n if (\n t.isObjectProperty(prop) &&\n t.isIdentifier(prop.key, { name: 'className' }) &&\n t.isStringLiteral(prop.value)\n ) {\n return prop.value.value;\n }\n }\n return null;\n}\n\n/**\n * Handle tastyStatic(styles) - returns StaticStyle object\n */\nfunction handleStylesMode(\n path: NodePath<t.CallExpression>,\n args: t.CallExpression['arguments'],\n cssWriter: CSSWriter,\n state: PluginState,\n globalRegistry: StaticStyleRegistry,\n mode: 'file' | 'inject',\n globalKeyframes?: Record<string, KeyframesSteps>,\n propertyOptions?: PropertyExtractionOptions,\n globalFontFace?: Record<string, FontFaceInput>,\n globalCounterStyle?: Record<string, CounterStyleDescriptors>,\n globalFunction?: Record<string, FunctionDefinition>,\n globalRecipes?: Record<string, RecipeStyles>,\n): void {\n const stylesArg = args[0];\n\n if (!t.isObjectExpression(stylesArg)) {\n throw path.buildCodeFrameError(\n 'tastyStatic(styles) argument must be a static object literal',\n );\n }\n\n // Evaluate styles object at build time\n const rawStyles = evaluateObjectExpression(stylesArg, path) as Styles;\n\n // Resolve recipes before extraction\n const styles = resolveRecipesWith(rawStyles, globalRecipes ?? null);\n\n // Extract keyframes (deduplicated by content)\n const { keyframes, nameMap } = extractKeyframesFromStyles(\n styles,\n globalKeyframes,\n );\n\n // Extract and add auto-inferred @property rules\n const properties = extractPropertiesFromStyles(styles, propertyOptions);\n\n // Extract @font-face rules\n const fontFaces = extractFontFaceFromStyles(styles, globalFontFace);\n\n // Extract @counter-style rules\n const counterStyles = extractCounterStyleFromStyles(\n styles,\n globalCounterStyle,\n );\n\n // Extract @function rules\n const functions = extractFunctionsFromStyles(styles, globalFunction);\n\n // Extract styles with chunking\n const chunks = extractChunks(styles);\n\n const className =\n chunks.length > 0 ? chunks.map((c) => c.className).join(' ') : '';\n const staticStyleObject = createStaticStyleAST(className, styles);\n\n if (mode === 'inject') {\n const allCSS = collectAllCSS(\n keyframes,\n properties,\n fontFaces,\n counterStyles,\n functions,\n chunks,\n nameMap,\n );\n const injectCall = createInjectCallAST(className, allCSS);\n\n path.replaceWith(t.sequenceExpression([injectCall, staticStyleObject]));\n } else {\n writeCSSToWriter(\n cssWriter,\n keyframes,\n properties,\n fontFaces,\n counterStyles,\n functions,\n chunks,\n nameMap,\n state.sourceFile,\n );\n path.replaceWith(staticStyleObject);\n }\n\n registerIfVariableDeclaration(path, className, styles, state, globalRegistry);\n}\n\n/**\n * Handle tastyStatic(base, styles) - extends base with additional styles\n */\nfunction handleExtensionMode(\n path: NodePath<t.CallExpression>,\n args: t.CallExpression['arguments'],\n cssWriter: CSSWriter,\n state: PluginState,\n globalRegistry: StaticStyleRegistry,\n mode: 'file' | 'inject',\n globalKeyframes?: Record<string, KeyframesSteps>,\n propertyOptions?: PropertyExtractionOptions,\n globalFontFace?: Record<string, FontFaceInput>,\n globalCounterStyle?: Record<string, CounterStyleDescriptors>,\n globalFunction?: Record<string, FunctionDefinition>,\n globalRecipes?: Record<string, RecipeStyles>,\n): void {\n if (args.length < 2) {\n throw path.buildCodeFrameError(\n 'tastyStatic(base, styles) requires two arguments',\n );\n }\n\n const baseArg = args[0];\n const stylesArg = args[1];\n\n if (!t.isIdentifier(baseArg)) {\n throw path.buildCodeFrameError(\n 'tastyStatic(base, styles) first argument must be an identifier',\n );\n }\n\n if (!t.isObjectExpression(stylesArg)) {\n throw path.buildCodeFrameError(\n 'tastyStatic(base, styles) second argument must be a static object literal',\n );\n }\n\n const baseName = baseArg.name;\n\n // Look up base styles in registry\n const baseEntry =\n state.staticStyleRegistry[baseName] || globalRegistry[baseName];\n\n if (!baseEntry) {\n throw path.buildCodeFrameError(\n `Cannot find base StaticStyle '${baseName}'. ` +\n 'Make sure it is defined before being extended.',\n );\n }\n\n // Evaluate override styles\n const overrideStyles = evaluateObjectExpression(stylesArg, path) as Styles;\n\n // Merge styles using mergeStyles, then resolve recipes\n const mergedStyles = resolveRecipesWith(\n mergeStyles(baseEntry.styles, overrideStyles),\n globalRecipes ?? null,\n );\n\n // Extract keyframes (deduplicated by content)\n const { keyframes, nameMap } = extractKeyframesFromStyles(\n mergedStyles,\n globalKeyframes,\n );\n\n // Extract auto-inferred @property rules\n const properties = extractPropertiesFromStyles(mergedStyles, propertyOptions);\n\n // Extract @font-face rules\n const fontFaces = extractFontFaceFromStyles(mergedStyles, globalFontFace);\n\n // Extract @counter-style rules\n const counterStyles = extractCounterStyleFromStyles(\n mergedStyles,\n globalCounterStyle,\n );\n\n // Extract @function rules\n const functions = extractFunctionsFromStyles(mergedStyles, globalFunction);\n\n // Extract styles with chunking\n const chunks = extractChunks(mergedStyles);\n\n const className =\n chunks.length > 0 ? chunks.map((c) => c.className).join(' ') : '';\n const staticStyleObject = createStaticStyleAST(className, mergedStyles);\n\n if (mode === 'inject') {\n const allCSS = collectAllCSS(\n keyframes,\n properties,\n fontFaces,\n counterStyles,\n functions,\n chunks,\n nameMap,\n );\n const injectCall = createInjectCallAST(className, allCSS);\n\n path.replaceWith(t.sequenceExpression([injectCall, staticStyleObject]));\n } else {\n writeCSSToWriter(\n cssWriter,\n keyframes,\n properties,\n fontFaces,\n counterStyles,\n functions,\n chunks,\n nameMap,\n state.sourceFile,\n );\n path.replaceWith(staticStyleObject);\n }\n\n registerIfVariableDeclaration(\n path,\n className,\n mergedStyles,\n state,\n globalRegistry,\n );\n}\n\n/**\n * Handle tastyStatic(selector, styles) - removes the call entirely\n */\nfunction handleSelectorMode(\n path: NodePath<t.CallExpression>,\n args: t.CallExpression['arguments'],\n cssWriter: CSSWriter,\n mode: 'file' | 'inject',\n sourceFile?: string,\n globalKeyframes?: Record<string, KeyframesSteps>,\n propertyOptions?: PropertyExtractionOptions,\n globalFontFace?: Record<string, FontFaceInput>,\n globalCounterStyle?: Record<string, CounterStyleDescriptors>,\n globalFunction?: Record<string, FunctionDefinition>,\n globalRecipes?: Record<string, RecipeStyles>,\n): void {\n if (args.length < 2) {\n throw path.buildCodeFrameError(\n 'tastyStatic(selector, styles) requires two arguments',\n );\n }\n\n const selectorArg = args[0];\n const stylesArg = args[1];\n\n if (!t.isStringLiteral(selectorArg)) {\n throw path.buildCodeFrameError(\n 'tastyStatic(selector, styles) first argument must be a string literal',\n );\n }\n\n if (!t.isObjectExpression(stylesArg)) {\n throw path.buildCodeFrameError(\n 'tastyStatic(selector, styles) second argument must be a static object literal',\n );\n }\n\n const selector = selectorArg.value;\n const rawStyles = evaluateObjectExpression(stylesArg, path) as Styles;\n\n // Resolve recipes before extraction\n const styles = resolveRecipesWith(rawStyles, globalRecipes ?? null);\n\n // Extract keyframes (deduplicated by content)\n const { keyframes, nameMap } = extractKeyframesFromStyles(\n styles,\n globalKeyframes,\n );\n\n // Extract auto-inferred @property rules\n const properties = extractPropertiesFromStyles(styles, propertyOptions);\n\n // Extract @font-face rules\n const fontFaces = extractFontFaceFromStyles(styles, globalFontFace);\n\n // Extract @counter-style rules\n const counterStyles = extractCounterStyleFromStyles(\n styles,\n globalCounterStyle,\n );\n\n // Extract @function rules\n const functions = extractFunctionsFromStyles(styles, globalFunction);\n\n // Extract styles for selector; the keyframes above are emitted separately\n const css = renderSelectorCSS(selector, styles);\n\n const selectorCSS =\n nameMap.size > 0 ? replaceAnimationNamesInCSS(css, nameMap) : css;\n\n if (mode === 'inject') {\n const cssParts: string[] = [];\n\n for (const kf of keyframes) cssParts.push(kf.css);\n for (const prop of properties) cssParts.push(prop.css);\n for (const ff of fontFaces) cssParts.push(ff.css);\n for (const cs of counterStyles) cssParts.push(cs.css);\n for (const fn of functions) cssParts.push(fn.css);\n cssParts.push(selectorCSS);\n\n const injectCall = createInjectCallAST(selector, cssParts.join('\\n'));\n\n const parent = path.parentPath;\n if (parent && t.isExpressionStatement(parent.node)) {\n parent.replaceWith(t.expressionStatement(injectCall));\n } else {\n path.replaceWith(injectCall);\n }\n } else {\n writeCSSToWriter(\n cssWriter,\n keyframes,\n properties,\n fontFaces,\n counterStyles,\n functions,\n [],\n nameMap,\n sourceFile,\n );\n cssWriter.add(selector, selectorCSS, sourceFile);\n\n const parent = path.parentPath;\n if (parent && t.isExpressionStatement(parent.node)) {\n parent.remove();\n } else {\n path.replaceWith(t.identifier('undefined'));\n }\n }\n}\n\n/**\n * Collect all extracted CSS parts into a single string (for inject mode).\n */\nfunction collectAllCSS(\n keyframes: ExtractedKeyframes[],\n properties: ExtractedProperty[],\n fontFaces: ExtractedFontFace[],\n counterStyles: ExtractedCounterStyle[],\n functions: ExtractedFunction[],\n chunks: ExtractedChunk[],\n nameMap: Map<string, string>,\n): string {\n const parts: string[] = [];\n\n for (const kf of keyframes) parts.push(kf.css);\n for (const prop of properties) parts.push(prop.css);\n for (const ff of fontFaces) parts.push(ff.css);\n for (const cs of counterStyles) parts.push(cs.css);\n for (const fn of functions) parts.push(fn.css);\n\n for (const chunk of chunks) {\n parts.push(\n nameMap.size > 0\n ? replaceAnimationNamesInCSS(chunk.css, nameMap)\n : chunk.css,\n );\n }\n\n return parts.join('\\n');\n}\n\n/**\n * Write all extracted CSS parts to a CSSWriter (for file mode).\n */\nfunction writeCSSToWriter(\n cssWriter: CSSWriter,\n keyframes: ExtractedKeyframes[],\n properties: ExtractedProperty[],\n fontFaces: ExtractedFontFace[],\n counterStyles: ExtractedCounterStyle[],\n functions: ExtractedFunction[],\n chunks: ExtractedChunk[],\n nameMap: Map<string, string>,\n sourceFile?: string,\n): void {\n for (const kf of keyframes) {\n cssWriter.add(kf.css, kf.css, sourceFile);\n }\n for (const prop of properties) {\n cssWriter.add(prop.css, prop.css, sourceFile);\n }\n for (const ff of fontFaces) {\n cssWriter.add(ff.css, ff.css, sourceFile);\n }\n for (const cs of counterStyles) {\n cssWriter.add(cs.css, cs.css, sourceFile);\n }\n for (const fn of functions) {\n cssWriter.add(fn.css, fn.css, sourceFile);\n }\n\n for (const chunk of chunks) {\n const css =\n nameMap.size > 0\n ? replaceAnimationNamesInCSS(chunk.css, nameMap)\n : chunk.css;\n cssWriter.add(chunk.className, css, sourceFile);\n }\n}\n\n/**\n * Extract CSS for a selector from a styles/tokens object, with the keyframes\n * it animates. Returns undefined when there are no styles or no CSS output.\n */\nfunction extractCSSFromStyles(\n selector: string,\n styles: Styles | ConfigTokens | null,\n globalKeyframes?: Record<string, KeyframesSteps>,\n): string | undefined {\n if (!styles || Object.keys(styles).length === 0) return undefined;\n return (\n extractSelectorCSS(selector, styles as Styles, globalKeyframes) || undefined\n );\n}\n\n/**\n * Write a configured global selector's CSS, with the keyframes it animates\n * keyed by their CSS so selectors sharing one emit it once.\n */\nfunction writeGlobalStyles(\n cssWriter: CSSWriter,\n selector: string,\n styles: Styles,\n globalKeyframes: Record<string, KeyframesSteps>,\n): void {\n const { keyframes, nameMap } = extractKeyframesFromStyles(\n styles,\n globalKeyframes,\n );\n for (const kf of keyframes) {\n cssWriter.add(kf.css, kf.css);\n }\n\n const css = replaceAnimationNamesInCSS(\n renderSelectorCSS(selector, styles),\n nameMap,\n );\n if (css) cssWriter.add(`global:${selector}`, css);\n}\n\n/**\n * Create an `_$i(id, css)` call expression AST node for inject mode.\n */\nfunction createInjectCallAST(id: string, css: string): t.CallExpression {\n return t.callExpression(t.identifier('_$i'), [\n t.stringLiteral(id),\n t.stringLiteral(css),\n ]);\n}\n\n/**\n * Create a StaticStyle object AST node\n */\nfunction createStaticStyleAST(\n className: string,\n styles: Styles,\n): t.ObjectExpression {\n return t.objectExpression([\n t.objectProperty(t.identifier('className'), t.stringLiteral(className)),\n t.objectProperty(t.identifier('styles'), valueToAST(styles)),\n t.objectMethod(\n 'method',\n t.identifier('toString'),\n [],\n t.blockStatement([\n t.returnStatement(\n t.memberExpression(t.thisExpression(), t.identifier('className')),\n ),\n ]),\n ),\n ]);\n}\n\n/**\n * Register a StaticStyle in the registry if it's being assigned to a variable\n */\nfunction registerIfVariableDeclaration(\n path: NodePath,\n className: string,\n styles: Styles,\n state: PluginState,\n globalRegistry: StaticStyleRegistry,\n): void {\n const parent = path.parentPath;\n if (parent && t.isVariableDeclarator(parent.node)) {\n const id = parent.node.id;\n if (t.isIdentifier(id)) {\n const variableName = id.name;\n state.staticStyleRegistry[variableName] = { styles, className };\n globalRegistry[variableName] = { styles, className };\n }\n }\n}\n\n/**\n * Convert a JavaScript value to an AST node\n */\nfunction valueToAST(value: unknown): t.Expression {\n if (value === null) {\n return t.nullLiteral();\n }\n if (value === undefined) {\n return t.identifier('undefined');\n }\n if (typeof value === 'string') {\n return t.stringLiteral(value);\n }\n if (typeof value === 'number') {\n // Babel 8's `numericLiteral` rejects negative and non-finite numbers.\n return t.valueToNode(value);\n }\n if (typeof value === 'boolean') {\n return t.booleanLiteral(value);\n }\n if (Array.isArray(value)) {\n return t.arrayExpression(value.map(valueToAST));\n }\n if (typeof value === 'object') {\n const properties = Object.entries(value).map(([key, val]) =>\n t.objectProperty(\n /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)\n ? t.identifier(key)\n : t.stringLiteral(key),\n valueToAST(val),\n ),\n );\n return t.objectExpression(properties);\n }\n // Fallback for unsupported types\n return t.identifier('undefined');\n}\n\n/**\n * Evaluate an ObjectExpression to a plain JavaScript object.\n * Only supports static values that can be determined at build time.\n */\nfunction evaluateObjectExpression(\n node: t.ObjectExpression,\n path: NodePath,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const prop of node.properties) {\n if (t.isSpreadElement(prop)) {\n throw path.buildCodeFrameError(\n 'Spread elements are not supported in tastyStatic() - styles must be fully static',\n );\n }\n\n if (!t.isObjectProperty(prop)) {\n throw path.buildCodeFrameError(\n 'Only object properties are supported in tastyStatic()',\n );\n }\n\n // Get key\n let key: string;\n if (t.isIdentifier(prop.key)) {\n key = prop.key.name;\n } else if (t.isStringLiteral(prop.key)) {\n key = prop.key.value;\n } else {\n throw path.buildCodeFrameError(\n 'Dynamic property keys are not supported in tastyStatic()',\n );\n }\n\n // Get value\n const value = evaluateExpression(prop.value, path);\n result[key] = value;\n }\n\n return result;\n}\n\n/**\n * Evaluate an expression to a JavaScript value.\n */\nfunction evaluateExpression(node: t.Node, path: NodePath): unknown {\n if (t.isStringLiteral(node)) {\n return node.value;\n }\n\n if (t.isNumericLiteral(node)) {\n return node.value;\n }\n\n if (t.isBooleanLiteral(node)) {\n return node.value;\n }\n\n if (t.isNullLiteral(node)) {\n return null;\n }\n\n if (t.isIdentifier(node, { name: 'undefined' })) {\n return undefined;\n }\n\n if (t.isArrayExpression(node)) {\n return node.elements.map((el) => {\n if (el === null) return null;\n if (t.isSpreadElement(el)) {\n throw path.buildCodeFrameError(\n 'Spread elements are not supported in tastyStatic()',\n );\n }\n return evaluateExpression(el, path);\n });\n }\n\n if (t.isObjectExpression(node)) {\n return evaluateObjectExpression(node, path);\n }\n\n if (t.isTemplateLiteral(node)) {\n // Only support template literals without expressions\n if (node.expressions.length > 0) {\n throw path.buildCodeFrameError(\n 'Template literals with expressions are not supported in tastyStatic()',\n );\n }\n return node.quasis.map((q) => q.value.cooked).join('');\n }\n\n if (t.isUnaryExpression(node, { operator: '-' })) {\n const arg = evaluateExpression(node.argument, path);\n if (typeof arg === 'number') {\n return -arg;\n }\n }\n\n throw path.buildCodeFrameError(\n `Dynamic expressions are not supported in tastyStatic() - got ${node.type}. ` +\n 'All values must be static literals.',\n );\n}\n"],"mappings":"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"}
|
package/dist/zero/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Y as Styles, v as PropertyDefinition } from "../types-DJEM_BOJ.js";
|
|
2
|
-
import { t as
|
|
2
|
+
import { t as mergeStyles } from "../merge-styles-DSkVc6CD.js";
|
|
3
|
+
import { t as TastyZeroConfig } from "../babel-types-docs8f4c.js";
|
|
3
4
|
//#region src/zero/configure.d.ts
|
|
4
5
|
/**
|
|
5
6
|
* Configure `extractStylesForSelector()` and `extractStylesWithChunks()`.
|
|
@@ -131,5 +132,5 @@ export declare class CSSWriter {
|
|
|
131
132
|
*/
|
|
132
133
|
export declare function createCSSWriter(outputPath: string, options?: CSSWriterOptions): CSSWriter;
|
|
133
134
|
//#endregion
|
|
134
|
-
export type
|
|
135
|
+
export { type CSSWriterOptions, type ExtractedChunk, type ExtractedProperty, type ExtractedSelector, type Styles, type TastyZeroConfig, mergeStyles };
|
|
135
136
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/zero/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { t as mergeStyles } from "../chunks/shared-utils-y-HjvPN4.js";
|
|
2
|
+
import { M as validateNamePrefix } from "../chunks/css-definitions-_UidGa56.js";
|
|
3
|
+
import { a as resetZeroConfig, o as setActiveZeroConfig, t as configureZero } from "../chunks/build-config-DmSCYjYl.js";
|
|
4
|
+
import { d as extractStylesForSelector, f as extractStylesWithChunks, h as setExtractorNamePrefix, i as extractConfigProperties, n as createCSSWriter, t as CSSWriter } from "../chunks/zero-engine-CiVidroC.js";
|
|
4
5
|
//#region src/zero/configure.ts
|
|
5
6
|
function configure(config = {}) {
|
|
6
7
|
const namePrefix = config.namePrefix ?? "ts";
|
|
@@ -19,6 +20,6 @@ function resetConfig() {
|
|
|
19
20
|
setExtractorNamePrefix("ts");
|
|
20
21
|
}
|
|
21
22
|
//#endregion
|
|
22
|
-
export { CSSWriter, configure, createCSSWriter, extractConfigProperties, extractStylesForSelector, extractStylesWithChunks, resetConfig };
|
|
23
|
+
export { CSSWriter, configure, createCSSWriter, extractConfigProperties, extractStylesForSelector, extractStylesWithChunks, mergeStyles, resetConfig };
|
|
23
24
|
|
|
24
25
|
//# sourceMappingURL=index.js.map
|
package/dist/zero/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/zero/configure.ts"],"sourcesContent":["/**\n * React-free configuration for the programmatic zero-runtime API.\n *\n * The main entry's `configure()` also sets up the browser injector and the\n * React runtime around it; a build script that only turns styles into CSS\n * needs neither, nor `react` installed.\n */\n\nimport {\n DEFAULT_ZERO_NAME_PREFIX,\n validateNamePrefix,\n} from '../utils/name-prefix';\n\nimport type { TastyZeroConfig } from './babel-types';\nimport { configureZero, resetZeroConfig, setActiveZeroConfig } from './config';\nimport { setExtractorNamePrefix } from './extractor';\n\n/**\n * Configure `extractStylesForSelector()` and `extractStylesWithChunks()`.\n *\n * Takes the build-time subset of the main `configure()` options. Those that\n * shape generated CSS apply: `states`, `units`, parse `functions`, `handlers`,\n * `replaceTokens`, `recipes`, `plugins`, `namePrefix` (default `'ts'`).\n * Configured `keyframes` are emitted by `extractStylesForSelector()`, with the\n * rules that animate them; `extractStylesWithChunks()` returns class rules\n * only. Each call replaces the previous configuration.\n *\n * `tokens`, `globalStyles`, `fontFaces`, `counterStyles`, `properties` and\n * `$$` `@function` definitions are not emitted with the rules; render tokens\n * and global styles with `extractStylesForSelector(':root', tokens)` and\n * `extractStylesForSelector(selector, styles)`, and the `@property` rules\n * (Tasty's defaults plus `properties`) with `extractConfigProperties()`.\n *\n * The configuration is process-wide, shared with the Babel plugin and with\n * the runtime `configure()` from `@tenphi/tasty`. The extractors re-apply it\n * after the Babel plugin replaced it, but not after a runtime `configure()`:\n * don't mix the runtime and build-time configuration in one process.\n *\n * @example\n * ```ts\n * import { configure, extractStylesForSelector } from '@tenphi/tasty/zero';\n *\n * configure({ units: { x: 'var(--gap)' } });\n * extractStylesForSelector('.card', { padding: '2x' }).css;\n * ```\n */\nexport function configure(config: TastyZeroConfig = {}): void {\n // Validated before anything is reset, so a rejected prefix changes nothing.\n const namePrefix = config.namePrefix ?? DEFAULT_ZERO_NAME_PREFIX;\n validateNamePrefix(namePrefix);\n\n resetZeroConfig();\n\n const resolved = configureZero({ ...config, namePrefix });\n setExtractorNamePrefix(namePrefix);\n setActiveZeroConfig(resolved);\n}\n\n/**\n * Drop the configuration set by `configure()`, returning the extractors to\n * their defaults.\n */\nexport function resetConfig(): void {\n resetZeroConfig();\n setActiveZeroConfig(null);\n setExtractorNamePrefix(DEFAULT_ZERO_NAME_PREFIX);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/zero/configure.ts"],"sourcesContent":["/**\n * React-free configuration for the programmatic zero-runtime API.\n *\n * The main entry's `configure()` also sets up the browser injector and the\n * React runtime around it; a build script that only turns styles into CSS\n * needs neither, nor `react` installed.\n */\n\nimport {\n DEFAULT_ZERO_NAME_PREFIX,\n validateNamePrefix,\n} from '../utils/name-prefix';\n\nimport type { TastyZeroConfig } from './babel-types';\nimport { configureZero, resetZeroConfig, setActiveZeroConfig } from './config';\nimport { setExtractorNamePrefix } from './extractor';\n\n/**\n * Configure `extractStylesForSelector()` and `extractStylesWithChunks()`.\n *\n * Takes the build-time subset of the main `configure()` options. Those that\n * shape generated CSS apply: `states`, `units`, parse `functions`, `handlers`,\n * `replaceTokens`, `recipes`, `plugins`, `namePrefix` (default `'ts'`).\n * Configured `keyframes` are emitted by `extractStylesForSelector()`, with the\n * rules that animate them; `extractStylesWithChunks()` returns class rules\n * only. Each call replaces the previous configuration.\n *\n * `tokens`, `globalStyles`, `fontFaces`, `counterStyles`, `properties` and\n * `$$` `@function` definitions are not emitted with the rules; render tokens\n * and global styles with `extractStylesForSelector(':root', tokens)` and\n * `extractStylesForSelector(selector, styles)`, and the `@property` rules\n * (Tasty's defaults plus `properties`) with `extractConfigProperties()`.\n *\n * The configuration is process-wide, shared with the Babel plugin and with\n * the runtime `configure()` from `@tenphi/tasty`. The extractors re-apply it\n * after the Babel plugin replaced it, but not after a runtime `configure()`:\n * don't mix the runtime and build-time configuration in one process.\n *\n * @example\n * ```ts\n * import { configure, extractStylesForSelector } from '@tenphi/tasty/zero';\n *\n * configure({ units: { x: 'var(--gap)' } });\n * extractStylesForSelector('.card', { padding: '2x' }).css;\n * ```\n */\nexport function configure(config: TastyZeroConfig = {}): void {\n // Validated before anything is reset, so a rejected prefix changes nothing.\n const namePrefix = config.namePrefix ?? DEFAULT_ZERO_NAME_PREFIX;\n validateNamePrefix(namePrefix);\n\n resetZeroConfig();\n\n const resolved = configureZero({ ...config, namePrefix });\n setExtractorNamePrefix(namePrefix);\n setActiveZeroConfig(resolved);\n}\n\n/**\n * Drop the configuration set by `configure()`, returning the extractors to\n * their defaults.\n */\nexport function resetConfig(): void {\n resetZeroConfig();\n setActiveZeroConfig(null);\n setExtractorNamePrefix(DEFAULT_ZERO_NAME_PREFIX);\n}\n"],"mappings":";;;;;AA8CA,SAAgB,UAAU,SAA0B,CAAC,GAAS;CAE5D,MAAM,aAAa,OAAO,cAAA;CAC1B,mBAAmB,UAAU;CAE7B,gBAAgB;CAEhB,MAAM,WAAW,cAAc;EAAE,GAAG;EAAQ;CAAW,CAAC;CACxD,uBAAuB,UAAU;CACjC,oBAAoB,QAAQ;AAC9B;AAMA,SAAgB,cAAoB;CAClC,gBAAgB;CAChB,oBAAoB,IAAI;CACxB,uBAAA,IAA+C;AACjD"}
|
package/dist/zero/next.d.ts
CHANGED
package/docs/ai-agents.md
CHANGED
|
@@ -78,6 +78,7 @@ The last row goes the other way — longhands over the shorthand — because `fl
|
|
|
78
78
|
| `$$name(…)` | call a CSS `@function` declared via `@function`, `useFunction`, or config |
|
|
79
79
|
|
|
80
80
|
- ❌ `#f5f5f5`, `rgb(0 0 0)`, `oklch(…)`, `okhsl(…)`, `okhst(…)`, `red` → ✅ `#surface` (add the token to the config if it doesn't exist).
|
|
81
|
+
- CSS system colors (`Canvas`, `CanvasText`, `Highlight`, `ButtonText`, `GrayText`, …) are the exception, for `forced-colors` styles: hold one in a token (`'#forced-border': 'CanvasText'`) or write it under a `@media(forced-colors: active)` state.
|
|
81
82
|
- ❌ `var(--gap)` → ✅ `$gap` · ❌ `$accent-color` → ✅ `#accent` · ❌ `transparent` → ✅ `#clear` · ❌ `currentColor` → ✅ `#current`.
|
|
82
83
|
- `#clear` is a default replace token for `transparent`, so `#clear.5` and `#clear.$opacity` stay transparent. It does not read `--clear-color`; override it through `replaceTokens` if needed.
|
|
83
84
|
- A `$name` must be declared as a `'$name': value` key in the same styles object, or in the config.
|
package/docs/configuration.md
CHANGED
|
@@ -212,9 +212,9 @@ useLayoutEffect(() => {
|
|
|
212
212
|
A `#name` token's value used to be rewritten into a configured color space, so
|
|
213
213
|
`#brand: '#ff8800'` declared `--brand-color: oklch(0.75 0.16 55)`. That existed
|
|
214
214
|
to serve the opacity suffix, which needed numeric channels to write an alpha
|
|
215
|
-
into. Opacity now
|
|
216
|
-
`
|
|
217
|
-
|
|
215
|
+
into. Opacity now mixes the token with `transparent` —
|
|
216
|
+
`color-mix(in oklab, var(--brand-color) 50%, transparent)` — which the browser
|
|
217
|
+
resolves against any color, so there is nothing left for the setting to decide.
|
|
218
218
|
|
|
219
219
|
A color is emitted exactly as authored:
|
|
220
220
|
|
|
@@ -235,9 +235,10 @@ background: oklch(from var(--brand-color) calc(l * 1.2) c h);
|
|
|
235
235
|
```
|
|
236
236
|
|
|
237
237
|
This works on any `<color>`, including the ones no build-time conversion could
|
|
238
|
-
have evaluated
|
|
239
|
-
|
|
240
|
-
|
|
238
|
+
have evaluated, and `oklch` is unbounded, so a wide-gamut color survives a round
|
|
239
|
+
trip a narrower space would clamp. Relative color syntax is Baseline 2024 (Chrome
|
|
240
|
+
125, Firefox 128, Safari 18), so the [opacity suffix](dsl.md#color-tokens--opacity)
|
|
241
|
+
uses the widely available `color-mix()` instead.
|
|
241
242
|
|
|
242
243
|
### Migrating off `colorSpace`
|
|
243
244
|
|
|
@@ -270,14 +271,15 @@ color: oklch(var(--brand-color-oklch) / 0.5);
|
|
|
270
271
|
background: oklch(var(--brand-color-oklch));
|
|
271
272
|
|
|
272
273
|
/* after */
|
|
273
|
-
color:
|
|
274
|
+
color: color-mix(in oklab, var(--brand-color) 50%, transparent);
|
|
274
275
|
background: var(--brand-color);
|
|
275
276
|
```
|
|
276
277
|
|
|
277
278
|
The replacement is strictly more capable — the companion could only be
|
|
278
|
-
decomposed for a color the engine could evaluate at build time, while
|
|
279
|
-
color
|
|
280
|
-
`light-dark()`, and a variable Tasty never defined.
|
|
279
|
+
decomposed for a color the engine could evaluate at build time, while
|
|
280
|
+
`color-mix()` works on every `<color>`, including a `color-mix()`, a
|
|
281
|
+
`light-dark()`, and a variable Tasty never defined. It is also what
|
|
282
|
+
`#brand.5` emits.
|
|
281
283
|
|
|
282
284
|
---
|
|
283
285
|
|
package/docs/dsl.md
CHANGED
|
@@ -144,7 +144,7 @@ Keep conditions such as `:last-child` out of `$` and write them as `@own(:last-c
|
|
|
144
144
|
Named color prefixed with `#` that maps to CSS custom properties. Supports opacity with `.N` suffix:
|
|
145
145
|
|
|
146
146
|
```jsx
|
|
147
|
-
fill: '#purple.5'; // →
|
|
147
|
+
fill: '#purple.5'; // → color-mix(in oklab, var(--purple-color) 50%, transparent)
|
|
148
148
|
```
|
|
149
149
|
|
|
150
150
|
### Modifier
|
|
@@ -173,18 +173,17 @@ color: '(#primary, #secondary)', // Fallback syntax
|
|
|
173
173
|
|
|
174
174
|
`#white`, `#black`, `#border`, and `#outline` are registered by default (see [Default properties](#default-properties)), and `#clear` is a built-in alias for `transparent` (see [below](#clear-is-transparent)), so they work before you define any tokens.
|
|
175
175
|
|
|
176
|
-
A name that is also a hex color is read as a token with the literal as its fallback, in every color style: `color: '#ddd'` emits `var(--ddd-color, #ddd)`, and `#ddd.5` emits `
|
|
176
|
+
A name that is also a hex color is read as a token with the literal as its fallback, in every color style: `color: '#ddd'` emits `var(--ddd-color, #ddd)`, and `#ddd.5` emits `color-mix(in oklab, var(--ddd-color, #ddd) 50%, transparent)`. A `#ddd` token, if you define one, wins over the literal.
|
|
177
177
|
|
|
178
|
-
The suffix
|
|
178
|
+
The suffix fades the token's color by mixing it with `transparent`:
|
|
179
179
|
|
|
180
180
|
```jsx
|
|
181
181
|
fill: '#purple.5';
|
|
182
|
-
// →
|
|
182
|
+
// → color-mix(in oklab, var(--purple-color) 50%, transparent)
|
|
183
183
|
```
|
|
184
184
|
|
|
185
|
-
The
|
|
186
|
-
|
|
187
|
-
these:
|
|
185
|
+
The mix asks nothing of the color beyond _being_ a color. That means the suffix
|
|
186
|
+
works on every one of these:
|
|
188
187
|
|
|
189
188
|
- a token holding a `color-mix()`, a `light-dark()`, or a `color()` in a space
|
|
190
189
|
Tasty cannot convert — none of which have channels to decompose
|
|
@@ -192,13 +191,18 @@ these:
|
|
|
192
191
|
- a `--name-color` variable declared in your own CSS, with no Tasty token
|
|
193
192
|
definition behind it
|
|
194
193
|
|
|
195
|
-
|
|
194
|
+
`color-mix()` is Baseline widely available (Chrome 111, Firefox 113, Safari
|
|
195
|
+
16.2). Two properties follow from mixing rather than writing an alpha channel:
|
|
196
196
|
|
|
197
|
-
- **Alpha
|
|
198
|
-
faded
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
197
|
+
- **Alpha composes.** The mix is premultiplied, so a color that is already
|
|
198
|
+
translucent is faded further: a token holding `rgb(255 0 0 / .8)` faded to
|
|
199
|
+
`.5` is alpha `.4`. An opaque token — the usual case — ends at exactly the
|
|
200
|
+
suffix. System colors are whatever the platform draws, and some are
|
|
201
|
+
translucent: Chrome and Safari on macOS give `Highlight` an alpha of `.6`, so
|
|
202
|
+
a token holding it faded to `.5` ends at `.3` there.
|
|
203
|
+
- **A `$prop` alpha must be a number.** `#purple.$fade` emits
|
|
204
|
+
`calc(var(--fade) * 100%)`, because a mix percentage cannot be a `<number>`,
|
|
205
|
+
so `$fade` has to hold `.5`, not `50%`.
|
|
202
206
|
|
|
203
207
|
### `#clear` is transparent
|
|
204
208
|
|
|
@@ -232,42 +236,23 @@ A color that already reads the color it inherits — `#current`, a `#current` fa
|
|
|
232
236
|
— is not published into it: resolving such a value a second time at a descendant
|
|
233
237
|
would fade it twice.
|
|
234
238
|
|
|
235
|
-
|
|
236
|
-
and then faded gives relative color syntax a `currentcolor` origin, which Safari
|
|
237
|
-
supports only from 18:
|
|
239
|
+
### `#current` fades compose
|
|
238
240
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
// --ink-color: currentcolor
|
|
242
|
-
// fill: oklch(from currentcolor l c h / .5) → Chrome, Firefox, Safari 18+
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
Put the fade in the token instead — `{ '#ink': '#current.5' }` — and it goes
|
|
246
|
-
through `color-mix()`, which works from Safari 16.2 and composes like every other
|
|
247
|
-
`#current` fade.
|
|
248
|
-
|
|
249
|
-
### `#current` composes instead
|
|
250
|
-
|
|
251
|
-
`#current` composes alpha, and the difference is deliberate. A token _names_
|
|
252
|
-
a color, so fading it sets its alpha. `currentcolor` is the color an element
|
|
253
|
-
**inherits**, which an ancestor may already have faded — `#current.4` means "40%
|
|
254
|
-
of what reaches me":
|
|
241
|
+
`currentcolor` is the color an element **inherits**, which an ancestor may
|
|
242
|
+
already have faded, so `#current.4` means "40% of what reaches me":
|
|
255
243
|
|
|
256
244
|
```jsx
|
|
257
245
|
fill: '#current.4';
|
|
258
246
|
// → color-mix(in oklab, currentcolor 40%, transparent)
|
|
259
247
|
```
|
|
260
248
|
|
|
261
|
-
|
|
249
|
+
A `#current` fade nested inside another one composes: a label at `#current.4`
|
|
262
250
|
with a fill of `#current.18` under it lands at `.072`. Color ramps built on
|
|
263
|
-
`#current` depend on that
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
Token fades always use `oklch(from …)`: it is unbounded, so a wide-gamut color
|
|
269
|
-
survives a round trip that a gamut-limited space would clamp. `#current` fades
|
|
270
|
-
mix `in oklab`. Nothing configures either — see
|
|
251
|
+
`#current` depend on that.
|
|
252
|
+
|
|
253
|
+
Fades always mix `in oklab`: it is unbounded, so a wide-gamut color is not
|
|
254
|
+
clamped, and rectangular, so there is no hue to interpolate against
|
|
255
|
+
`transparent`. Nothing configures it — see
|
|
271
256
|
[Color space](configuration.md#color-space).
|
|
272
257
|
|
|
273
258
|
---
|
|
@@ -319,9 +304,38 @@ configure({
|
|
|
319
304
|
});
|
|
320
305
|
|
|
321
306
|
fill: '#solid.5'; // → hsl(220 90% 50% / .5)
|
|
322
|
-
fill: '#adaptive.5'; // →
|
|
307
|
+
fill: '#adaptive.5'; // → color-mix(in oklab, light-dark(…) 50%, transparent)
|
|
323
308
|
```
|
|
324
309
|
|
|
310
|
+
### Color keywords
|
|
311
|
+
|
|
312
|
+
CSS named colors (`rebeccapurple`) and system colors (`Canvas`, `CanvasText`,
|
|
313
|
+
`Highlight`, `ButtonText`, `GrayText`, `LinkText`, …) are colors too: they land
|
|
314
|
+
in the color slot of any style and can be a color token's value. System colors
|
|
315
|
+
are what `forced-colors` styles are written in:
|
|
316
|
+
|
|
317
|
+
```jsx
|
|
318
|
+
const Checkbox = tasty({
|
|
319
|
+
styles: {
|
|
320
|
+
'#forced-border': 'CanvasText',
|
|
321
|
+
border: {
|
|
322
|
+
'': '1bw #border',
|
|
323
|
+
'@media(forced-colors: active)': '1bw #forced-border',
|
|
324
|
+
},
|
|
325
|
+
outline: { '': false, focused: '2px Highlight' },
|
|
326
|
+
},
|
|
327
|
+
});
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
A custom property whose fallback is a single color is read as a color, so it
|
|
331
|
+
also fills the color slot: `border: '1bw var(--accent, Highlight)'`, as does
|
|
332
|
+
`($accent, Highlight)`. Keywords are case-insensitive: a color token keeps the
|
|
333
|
+
case it was written in, and a property value such as `border` or `fill` emits
|
|
334
|
+
them lowercase.
|
|
335
|
+
|
|
336
|
+
The deprecated system colors (`Menu`, `Window`, `ButtonHighlight`, …) are not
|
|
337
|
+
recognized.
|
|
338
|
+
|
|
325
339
|
---
|
|
326
340
|
|
|
327
341
|
## Built-in Units
|
package/docs/styles.md
CHANGED
|
@@ -394,6 +394,7 @@ Border shorthand with directional and multi-group support. Use **comma-separated
|
|
|
394
394
|
| `"1bw longhand"` | All sides: 1bw solid `#border`, output as 4 individual `border-*` properties |
|
|
395
395
|
| `"1bw #red, 2bw #blue top"` | All sides: 1bw solid `#red`, top overridden to 2bw solid `#blue` |
|
|
396
396
|
| `"1bw, dashed top bottom, #purple left right"` | Base: 1bw solid `#border`, top/bottom: 1bw dashed `#border`, left/right: 1bw solid `#purple` |
|
|
397
|
+
| `"1bw CanvasText"` | All sides: 1bw solid in the system color `CanvasText` (see [Color keywords](dsl.md#color-keywords)) |
|
|
397
398
|
|
|
398
399
|
Later comma-separated groups override earlier groups for conflicting directions.
|
|
399
400
|
|
|
@@ -611,8 +612,11 @@ transition="fade $transition ease-in"
|
|
|
611
612
|
transition="fill ease-in" // easing without duration (uses default timing)
|
|
612
613
|
transition="radius ease-in-out" // easing keyword only
|
|
613
614
|
transition="$$custom-prop" // custom property transition
|
|
615
|
+
transition="none" // no transition at all, e.g. under @media(prefers-reduced-motion: reduce)
|
|
614
616
|
```
|
|
615
617
|
|
|
618
|
+
`none` and the CSS-wide keywords (`inherit`, `initial`, `unset`, `revert`, `revert-layer`) are the whole value, not a name to transition.
|
|
619
|
+
|
|
616
620
|
**Recognized easing keywords:** `ease`, `ease-in`, `ease-out`, `ease-in-out`, `linear`, `step-start`, `step-end`. CSS easing functions (`cubic-bezier(...)`, `steps(...)`, `linear(...)`) are also recognized.
|
|
617
621
|
|
|
618
622
|
If the name is not a semantic name, it is used as a literal CSS property name.
|
package/docs/tasty-static.md
CHANGED
|
@@ -19,13 +19,15 @@ If the styles depend on props, keep `tasty()`: rendered only on the server, it a
|
|
|
19
19
|
|
|
20
20
|
Build-time extraction is part of the main `@tenphi/tasty` package but requires additional peer dependencies depending on your setup:
|
|
21
21
|
|
|
22
|
-
| Dependency | Version
|
|
23
|
-
| ---------------------------- |
|
|
24
|
-
| `@babel/core` |
|
|
25
|
-
| `@babel/helper-plugin-utils` |
|
|
26
|
-
| `@babel/types` |
|
|
27
|
-
| `jiti` | >= 2.6
|
|
28
|
-
| `babel-loader` | any
|
|
22
|
+
| Dependency | Version | Required for |
|
|
23
|
+
| ---------------------------- | ---------------------- | ---------------------------------------------------- |
|
|
24
|
+
| `@babel/core` | 7.24+ or 8 | Babel plugin (`@tenphi/tasty/babel-plugin`) |
|
|
25
|
+
| `@babel/helper-plugin-utils` | 7.24+ or 8 | Babel plugin |
|
|
26
|
+
| `@babel/types` | 7.24+ or 8 | Babel plugin |
|
|
27
|
+
| `jiti` | >= 2.6 | `configFile` only (Babel plugin and Next.js wrapper) |
|
|
28
|
+
| `babel-loader` | any (10+ with Babel 8) | Next.js wrapper (`@tenphi/tasty/zero/next`) |
|
|
29
|
+
|
|
30
|
+
Install the three Babel packages from the same major. Babel 8 itself needs Node 22.18+ or 24.11+, and `babel-loader` accepts it from version 10.
|
|
29
31
|
|
|
30
32
|
The Babel packages and `jiti` are optional peer dependencies of `@tenphi/tasty`; `babel-loader` is resolved from your project. `jiti` is loaded only to read a `configFile`, so a setup that passes `config` directly does not need it; without it, `configFile` fails with an error that says to install it. Install what your setup requires:
|
|
31
33
|
|
|
@@ -341,6 +343,18 @@ The configuration is process-wide and shared with the Babel plugin and the runti
|
|
|
341
343
|
|
|
342
344
|
`extractStylesForSelector()` output starts with the `@keyframes` its rules animate — local `@keyframes` and configured `keyframes` — under hashed names the `animation` declarations are rewritten to. `extractStylesWithChunks()` returns class rules only.
|
|
343
345
|
|
|
346
|
+
`mergeStyles()` merges style objects with the rules `tasty(Base, { styles })` extends by — state maps with and without a `''` key, `null`, `false`, `'@inherit'` and sub-elements (see [Extending vs. Replacing State Maps](dsl.md#extending-vs-replacing-state-maps)) — so a build script can layer overrides onto source styles before extracting them, without React:
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
import { extractStylesForSelector, mergeStyles } from '@tenphi/tasty/zero';
|
|
350
|
+
|
|
351
|
+
const styles = mergeStyles(checkboxStyles, {
|
|
352
|
+
Indicator: { radius: '0.5r' },
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
extractStylesForSelector('.checkbox', styles).css;
|
|
356
|
+
```
|
|
357
|
+
|
|
344
358
|
To write the results to a file the way the Babel plugin does, use `createCSSWriter()`. It deduplicates blocks by key and prepends the generated-file header:
|
|
345
359
|
|
|
346
360
|
```ts
|