@tenphi/tasty 0.0.0-snapshot.a7fb1f5 → 0.0.0-snapshot.ae900bb
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 +2 -1
- package/dist/config.d.ts +3 -2
- package/dist/config.js.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/injector/index.d.ts +5 -10
- package/dist/injector/index.js +5 -12
- package/dist/injector/index.js.map +1 -1
- package/dist/injector/injector.d.ts +11 -13
- package/dist/injector/injector.js +50 -73
- package/dist/injector/injector.js.map +1 -1
- package/dist/injector/sheet-manager.js +2 -1
- package/dist/injector/sheet-manager.js.map +1 -1
- package/dist/injector/types.d.ts +21 -28
- package/dist/ssr/astro-client.d.ts +1 -0
- package/dist/ssr/astro-client.js +24 -0
- package/dist/ssr/astro-client.js.map +1 -0
- package/dist/ssr/astro-middleware.d.ts +15 -0
- package/dist/ssr/astro-middleware.js +19 -0
- package/dist/ssr/astro-middleware.js.map +1 -0
- package/dist/ssr/astro.d.ts +85 -8
- package/dist/ssr/astro.js +110 -20
- package/dist/ssr/astro.js.map +1 -1
- package/dist/ssr/index.d.ts +1 -1
- package/dist/tasty.d.ts +1 -1
- package/docs/injector.md +18 -19
- package/docs/ssr.md +106 -31
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -465,7 +465,8 @@ See the [full SSR guide](docs/ssr.md).
|
|
|
465
465
|
| `@tenphi/tasty/next` | Next.js integration wrapper | Node |
|
|
466
466
|
| `@tenphi/tasty/ssr` | Core SSR API (collector, context, hydration) | Node |
|
|
467
467
|
| `@tenphi/tasty/ssr/next` | Next.js App Router SSR integration | Node |
|
|
468
|
-
| `@tenphi/tasty/ssr/astro` | Astro
|
|
468
|
+
| `@tenphi/tasty/ssr/astro` | Astro integration + middleware | Node |
|
|
469
|
+
| `@tenphi/tasty/ssr/astro-client` | Astro client-side cache hydration | Browser |
|
|
469
470
|
|
|
470
471
|
## Browser Requirements
|
|
471
472
|
|
package/dist/config.d.ts
CHANGED
|
@@ -63,11 +63,12 @@ interface TastyConfig {
|
|
|
63
63
|
autoPropertyTypes?: boolean;
|
|
64
64
|
/**
|
|
65
65
|
* Garbage collection configuration for unused styles.
|
|
66
|
-
*
|
|
66
|
+
* GC is triggered by touch count: every `touchInterval` touches, the
|
|
67
|
+
* oldest unused styles are evicted when their count exceeds `capacity`.
|
|
67
68
|
* @example
|
|
68
69
|
* ```ts
|
|
69
70
|
* configure({
|
|
70
|
-
* gc: {
|
|
71
|
+
* gc: { touchInterval: 1000, capacity: 1000 },
|
|
71
72
|
* });
|
|
72
73
|
* ```
|
|
73
74
|
*/
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["/**\n * Tasty Configuration Module\n *\n * Centralizes all tasty configuration, including:\n * - Style injector settings (nonce, cleanup thresholds, etc.)\n * - Global predefined states for advanced state mapping\n * - stylesGenerated flag that locks configuration after first style generation\n *\n * Configuration must be done BEFORE any styles are generated.\n * After the first `inject()` call, configuration is locked and attempts to\n * reconfigure will emit a warning and be ignored.\n */\n\nimport { StyleInjector } from './injector/injector';\nimport { clearPipelineCache, isSelector, renderStyles } from './pipeline';\nimport { setGlobalPredefinedStates } from './states';\nimport {\n normalizeHandlerDefinition,\n registerHandler,\n resetHandlers,\n} from './styles/predefined';\nimport { resetColorSpace, setColorSpace } from './utils/color-space';\nimport { isDevEnv } from './utils/is-dev-env';\nimport {\n CUSTOM_UNITS,\n getGlobalFuncs,\n getGlobalParser,\n normalizeColorTokenValue,\n resetGlobalPredefinedTokens,\n setGlobalPredefinedTokens,\n} from './utils/styles';\n\nimport type { ColorSpace } from './utils/color-space';\n\nimport type {\n CounterStyleDescriptors,\n FontFaceInput,\n GCConfig,\n KeyframesSteps,\n PropertyDefinition,\n} from './injector/types';\nimport type { StyleDetails, UnitHandler } from './parser/types';\nimport type { StyleResult } from './pipeline';\nimport type { TastyPlugin } from './plugins/types';\nimport type { RecipeStyles, ConfigTokens } from './styles/types';\nimport type { StyleHandlerDefinition } from './utils/styles';\n\n/**\n * Configuration options for the Tasty style system\n */\nexport interface TastyConfig {\n /** CSP nonce for style elements */\n nonce?: string;\n /** Maximum rules per stylesheet (default: 8192) */\n maxRulesPerSheet?: number;\n /** Force text injection mode, auto-detected in test environments (default: auto) */\n forceTextInjection?: boolean;\n /** Enable development mode features: performance metrics and debug info (default: auto) */\n devMode?: boolean;\n /**\n * Global predefined states for advanced state mapping.\n * These are state aliases that can be used in any component.\n * Example: { '@mobile': '@media(w < 920px)', '@dark': '@root(theme=dark)' }\n */\n states?: Record<string, string>;\n /**\n * Parser LRU cache size (default: 1000).\n * Larger values improve performance for apps with many unique style values.\n */\n parserCacheSize?: number;\n /**\n * Custom units for the style parser (merged with built-in units).\n * Units transform numeric values like `2x` → `calc(2 * var(--gap))`.\n * @example { em: 'em', vw: 'vw', custom: (n) => `${n * 10}px` }\n */\n units?: Record<string, string | UnitHandler>;\n /**\n * Custom functions for the style parser (merged with existing).\n * Functions process parsed style groups and return CSS values.\n * @example { myFunc: (groups) => groups.map(g => g.output).join(' ') }\n */\n funcs?: Record<string, (groups: StyleDetails[]) => string>;\n /**\n * Color space used for decomposed color token companion variables.\n * Controls the CSS function and suffix for alpha composition.\n *\n * - `'rgb'` — suffix `-rgb`, e.g. `rgb(var(--name-color-rgb) / .5)`\n * - `'hsl'` — suffix `-hsl`, e.g. `hsl(var(--name-color-hsl) / .5)`\n * - `'oklch'` — suffix `-oklch`, e.g. `oklch(var(--name-color-oklch) / .5)`\n *\n * @default 'oklch'\n */\n colorSpace?: ColorSpace;\n /**\n * Automatically infer and register CSS @property declarations\n * from custom property values found in styles, keyframes, and global config.\n * Covers all types: \\<color\\>, \\<number\\>, \\<length\\>, \\<angle\\>, \\<percentage\\>, \\<time\\>.\n * When false, only explicitly declared @properties are registered.\n * @default true\n */\n autoPropertyTypes?: boolean;\n /**\n * Garbage collection configuration for unused styles.\n * Controls popularity-aware style eviction with DOM safety guard.\n * @example\n * ```ts\n * configure({\n * gc: { auto: true, baseMaxAge: 60000, cooldown: 30000 },\n * });\n * ```\n */\n gc?: GCConfig;\n /**\n * Plugins that extend tasty with custom functions, units, or states.\n * Plugins are processed in order, with later plugins overriding earlier ones.\n * @example\n * ```ts\n * import { okhslPlugin } from '@tenphi/tasty';\n *\n * configure({\n * plugins: [okhslPlugin()],\n * });\n * ```\n */\n plugins?: TastyPlugin[];\n /**\n * Global keyframes definitions that can be referenced by animation names in styles.\n * Keys are animation names, values are keyframes step definitions.\n * Keyframes are only injected when actually used in styles.\n * @example\n * ```ts\n * configure({\n * keyframes: {\n * fadeIn: { from: { opacity: 0 }, to: { opacity: 1 } },\n * pulse: { '0%, 100%': { transform: 'scale(1)' }, '50%': { transform: 'scale(1.05)' } },\n * },\n * });\n * ```\n */\n keyframes?: Record<string, KeyframesSteps>;\n /**\n * Global CSS @property definitions for custom properties.\n * Keys use tasty token syntax ($name for properties, #name for colors).\n *\n * Tasty ships with `DEFAULT_PROPERTIES` (e.g. `$gap`, `$radius`, `#white`,\n * `#black`, `#clear`, `#border`, etc.) that are always included.\n * Properties you specify here are merged on top, so you can override any\n * default by using the same key.\n *\n * For color tokens (#name), `syntax: '<color>'` is auto-set and\n * `initialValue` defaults to `'transparent'` if not specified.\n *\n * @example\n * ```ts\n * configure({\n * properties: {\n * '$rotation': { syntax: '<angle>', initialValue: '0deg' },\n * '$scale': { syntax: '<number>', inherits: false, initialValue: 1 },\n * '#accent': { initialValue: 'purple' }, // syntax: '<color>' auto-set\n * // Override a default property:\n * '$gap': { syntax: '<length>', inherits: true, initialValue: '8px' },\n * },\n * });\n *\n * // Now use in styles - properties are registered when component renders:\n * const Spinner = tasty({\n * styles: {\n * transform: 'rotate($rotation)',\n * transition: '$$rotation 0.3s', // outputs: --rotation 0.3s\n * },\n * });\n * ```\n */\n properties?: Record<string, PropertyDefinition>;\n /**\n * Global @font-face definitions.\n * Keys are font-family names, values are descriptors or arrays of descriptors\n * (for multiple weights/styles of the same family).\n * Injected eagerly when styles are first generated.\n * @example\n * ```ts\n * configure({\n * fontFace: {\n * 'Brand Sans': [\n * { src: 'url(\"/fonts/brand-regular.woff2\") format(\"woff2\")', fontWeight: 400, fontDisplay: 'swap' },\n * { src: 'url(\"/fonts/brand-bold.woff2\") format(\"woff2\")', fontWeight: 700, fontDisplay: 'swap' },\n * ],\n * Icons: { src: 'url(\"/fonts/icons.woff2\") format(\"woff2\")', fontDisplay: 'block' },\n * },\n * });\n * ```\n */\n fontFace?: Record<string, FontFaceInput>;\n /**\n * Global @counter-style definitions.\n * Keys are counter-style names, values are descriptor objects.\n * Injected eagerly when styles are first generated.\n * @example\n * ```ts\n * configure({\n * counterStyle: {\n * thumbs: { system: 'cyclic', symbols: '\"👍\"', suffix: '\" \"' },\n * },\n * });\n * ```\n */\n counterStyle?: Record<string, CounterStyleDescriptors>;\n /**\n * Custom style handlers that transform style properties into CSS declarations.\n * Handlers replace built-in handlers for the same style name.\n * @example\n * ```ts\n * import { styleHandlers } from '@tenphi/tasty';\n *\n * configure({\n * handlers: {\n * // Override fill with custom behavior\n * fill: ({ fill }) => {\n * if (fill?.startsWith('gradient:')) {\n * return { background: fill.slice(9) };\n * }\n * return styleHandlers.fill({ fill });\n * },\n * // Add new custom style\n * elevation: ({ elevation }) => {\n * const level = parseInt(elevation) || 1;\n * return {\n * 'box-shadow': `0 ${level * 2}px ${level * 4}px rgba(0,0,0,0.1)`,\n * 'z-index': String(level * 100),\n * };\n * },\n * },\n * });\n * ```\n */\n handlers?: Record<string, StyleHandlerDefinition>;\n /**\n * Design tokens injected as CSS custom properties on `:root`.\n * Values are parsed through the Tasty DSL. Supports state maps\n * for responsive/theme-aware tokens.\n *\n * - `$name` keys become `--name` CSS custom properties\n * - `#name` keys become `--name-color` and `--name-color-{colorSpace}` properties\n *\n * Tokens are injected once when the first style is rendered.\n *\n * @example\n * ```ts\n * configure({\n * tokens: {\n * '$gap': '4px',\n * '#primary': {\n * '': '#purple',\n * '@dark': '#light-purple',\n * },\n * },\n * });\n * ```\n */\n tokens?: ConfigTokens;\n /**\n * Predefined tokens that are replaced during style parsing (parse-time substitution).\n * Use `$name` for custom properties and `#name` for color tokens.\n * Values are substituted inline before CSS generation, unlike `tokens` which\n * inject CSS custom properties on `:root`.\n *\n * For color tokens (#name), boolean `true` is converted to `transparent`.\n *\n * @example\n * ```ts\n * configure({\n * replaceTokens: {\n * $spacing: '2x',\n * '#accent': '#purple',\n * '#overlay': true, // → transparent\n * },\n * });\n *\n * // Now use in styles - tokens are replaced at parse time:\n * const Card = tasty({\n * styles: {\n * padding: '$spacing', // → calc(2 * var(--gap))\n * fill: '#accent', // → var(--purple-color)\n * },\n * });\n * ```\n */\n replaceTokens?: Record<`$${string}`, string | number | boolean> &\n Record<`#${string}`, string | number | boolean>;\n /**\n * Predefined style recipes -- named style bundles that can be applied via `recipe` style property.\n * Recipe values are flat tasty styles (no sub-element keys). They may contain base styles,\n * tokens (`$name`/`#name` definitions), local states, `@keyframes`, and `@properties`.\n *\n * Components reference recipes via: `recipe: 'name1 name2'` in their styles.\n * Use `/` to separate base recipes from post recipes: `recipe: 'base1 base2 / post1'`.\n * Use `none` to skip base recipes: `recipe: 'none / post1'`.\n * Resolution order: `base_recipes → component styles → post_recipes`.\n *\n * Recipes cannot reference other recipes.\n *\n * @example\n * ```ts\n * configure({\n * recipes: {\n * card: { padding: '4x', fill: '#surface', radius: '1r', border: true },\n * elevated: { shadow: '2x 2x 4x #shadow' },\n * },\n * });\n *\n * // Usage in styles:\n * const Card = tasty({\n * styles: {\n * recipe: 'card elevated',\n * color: '#text', // Overrides recipe values\n * },\n * });\n * ```\n */\n recipes?: Record<string, RecipeStyles>;\n}\n\n// Warnings tracking to avoid duplicates\nconst emittedWarnings = new Set<string>();\n\nconst devMode = isDevEnv();\n\n/**\n * Emit a warning only once\n */\nfunction warnOnce(key: string, message: string): void {\n if (devMode && !emittedWarnings.has(key)) {\n emittedWarnings.add(key);\n console.warn(message);\n }\n}\n\n// ============================================================================\n// Configuration State\n// ============================================================================\n\n// Track whether styles have been generated (locks configuration)\nlet stylesGenerated = false;\n\n// Current configuration (null until first configure() or auto-configured on first use)\nlet currentConfig: TastyConfig | null = null;\n\n// Global keyframes storage (null = no keyframes configured, empty object checked via hasGlobalKeyframes)\nlet globalKeyframes: Record<string, KeyframesSteps> | null = null;\n\n// Global font-face storage (null = no font faces configured)\nlet globalFontFace: Record<string, FontFaceInput> | null = null;\n\n// Global counter-style storage (null = no counter styles configured)\nlet globalCounterStyle: Record<string, CounterStyleDescriptors> | null = null;\n\n// Global properties storage (null = no properties configured)\nlet globalProperties: Record<string, PropertyDefinition> | null = null;\n\n// Global recipes storage (null = no recipes configured)\nlet globalRecipes: Record<string, RecipeStyles> | null = null;\n\n// Global token styles storage (injected as :root CSS custom properties)\nlet globalConfigTokens: ConfigTokens | null = null;\n\n/**\n * Default properties shipped with tasty.\n * These are always included unless explicitly overridden via `configure({ properties })`.\n * Keys use tasty token syntax (#name for colors, $name for other properties).\n *\n * For properties with CSS @property-compatible types (length, time, number, color),\n * an `initialValue` is provided so the property works even without a project-level token.\n */\nexport const DEFAULT_PROPERTIES: Record<string, PropertyDefinition> = {\n // Used by dual-fill feature to enable CSS transitions on the second fill color\n '#tasty-second-fill': {\n inherits: false,\n initialValue: 'transparent',\n },\n // Current color context variable (set by the color style handler).\n '#current': {\n inherits: true,\n initialValue: 'transparent',\n },\n // White and black are fundamental colors that need explicit initial values.\n '#white': {\n inherits: true,\n initialValue: 'rgb(255 255 255)',\n },\n '#black': {\n inherits: true,\n initialValue: 'rgb(0 0 0)',\n },\n // Shorthand for transparent\n '#clear': {\n inherits: true,\n initialValue: 'transparent',\n },\n // Default border color\n '#border': {\n inherits: true,\n initialValue: 'rgb(0 0 0)',\n },\n\n // ---- Core design tokens used by style handlers ----\n // These provide sensible defaults so tasty works standalone without a design system.\n // Consuming projects (e.g. uikit) override these by defining tokens on :root.\n\n $gap: {\n syntax: '<length>',\n inherits: true,\n initialValue: '4px',\n },\n $radius: {\n syntax: '<length>',\n inherits: true,\n initialValue: '6px',\n },\n '$border-width': {\n syntax: '<length>',\n inherits: true,\n initialValue: '1px',\n },\n '$outline-width': {\n syntax: '<length>',\n inherits: true,\n initialValue: '3px',\n },\n $transition: {\n syntax: '<time>',\n inherits: true,\n initialValue: '80ms',\n },\n // Used by radius.ts for `radius=\"leaf\"` modifier\n '$sharp-radius': {\n syntax: '<length>',\n inherits: true,\n initialValue: '0px',\n },\n // Used by preset.ts for `preset=\"name / strong\"`\n '$bold-font-weight': {\n syntax: '<number>',\n inherits: true,\n initialValue: '700',\n },\n // Used by preset.ts as fallback font stacks\n '$font-sans-fallback': {\n syntax: '*',\n inherits: true,\n initialValue:\n 'system-ui, -apple-system, \"Segoe UI\", Roboto, Helvetica, Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\", sans-serif',\n },\n '$font-mono-fallback': {\n syntax: '*',\n inherits: true,\n initialValue:\n 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace',\n },\n};\n\n// Global injector instance key\nconst GLOBAL_INJECTOR_KEY = '__TASTY_GLOBAL_INJECTOR__';\n\ninterface TastyGlobalStorage {\n [GLOBAL_INJECTOR_KEY]?: StyleInjector;\n}\n\ndeclare global {\n interface Window {\n [GLOBAL_INJECTOR_KEY]?: StyleInjector;\n }\n\n var __TASTY_GLOBAL_INJECTOR__: StyleInjector | undefined;\n}\n\n/**\n * Detect if we're running in a test environment\n */\nexport function isTestEnvironment(): boolean {\n // Check Node.js environment\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'test') {\n return true;\n }\n\n // Check for test runner globals (safely)\n if (typeof global !== 'undefined') {\n const g = global as unknown as Record<string, unknown>;\n if (g.vi || g.jest || g.expect || g.describe || g.it) {\n return true;\n }\n }\n\n // Check for jsdom environment (common in tests)\n if (\n typeof window !== 'undefined' &&\n window.navigator?.userAgent?.includes('jsdom')\n ) {\n return true;\n }\n\n // Check for other test runners\n if (typeof globalThis !== 'undefined') {\n const gt = globalThis as unknown as Record<string, unknown>;\n if (gt.vitest || gt.mocha) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Create default configuration with optional test environment detection\n */\nfunction createDefaultConfig(isTest?: boolean): TastyConfig {\n return {\n maxRulesPerSheet: 8192,\n forceTextInjection: isTest ?? false,\n devMode: isDevEnv(),\n };\n}\n\n// ============================================================================\n// stylesGenerated Flag Management\n// ============================================================================\n\n/**\n * Mark that styles have been generated (called by injector on first inject)\n * This locks the configuration - no further changes allowed.\n * Also injects internal and global properties.\n */\nexport function markStylesGenerated(): void {\n if (stylesGenerated) return; // Already marked, skip\n\n stylesGenerated = true;\n\n const injector = getGlobalInjector();\n\n // Inject all properties (defaults merged with user-configured overrides)\n for (const [token, definition] of Object.entries(getEffectiveProperties())) {\n injector.property(token, definition);\n }\n\n // Inject global @font-face rules (eagerly — fonts should be available before render)\n if (globalFontFace && Object.keys(globalFontFace).length > 0) {\n for (const [family, input] of Object.entries(globalFontFace)) {\n const descriptors = Array.isArray(input) ? input : [input];\n for (const desc of descriptors) {\n injector.fontFace(family, desc);\n }\n }\n }\n\n // Inject global @counter-style rules (eagerly)\n if (globalCounterStyle && Object.keys(globalCounterStyle).length > 0) {\n for (const [name, descriptors] of Object.entries(globalCounterStyle)) {\n injector.counterStyle(name, descriptors);\n }\n }\n\n // Inject configured tokens as :root CSS custom properties\n if (globalConfigTokens && Object.keys(globalConfigTokens).length > 0) {\n const tokenRules = renderStyles(\n globalConfigTokens,\n ':root',\n ) as StyleResult[];\n if (tokenRules.length > 0) {\n injector.injectGlobal(tokenRules);\n }\n }\n}\n\n/**\n * Check if styles have been generated (configuration is locked)\n */\nexport function hasStylesGenerated(): boolean {\n return stylesGenerated;\n}\n\n/**\n * Reset styles generated flag (for testing only)\n */\nexport function resetStylesGenerated(): void {\n stylesGenerated = false;\n emittedWarnings.clear();\n}\n\n// ============================================================================\n// Global Keyframes Management\n// ============================================================================\n\nlet _hasGlobalKeyframes = false;\n\n/**\n * Check if any global keyframes are configured.\n * Uses a pre-computed flag to avoid Object.keys() allocation on every call.\n */\nexport function hasGlobalKeyframes(): boolean {\n return _hasGlobalKeyframes;\n}\n\n/**\n * Get global keyframes configuration.\n * Returns null if no keyframes configured (fast path for zero-overhead).\n */\nexport function getGlobalKeyframes(): Record<string, KeyframesSteps> | null {\n return globalKeyframes;\n}\n\n/**\n * Set global keyframes (called from configure).\n * Internal use only.\n */\nfunction setGlobalKeyframes(keyframes: Record<string, KeyframesSteps>): void {\n if (stylesGenerated) {\n warnOnce(\n 'keyframes-after-styles',\n `[Tasty] Cannot update keyframes after styles have been generated.\\n` +\n `The new keyframes will be ignored.`,\n );\n return;\n }\n globalKeyframes = keyframes;\n _hasGlobalKeyframes = Object.keys(keyframes).length > 0;\n}\n\n// ============================================================================\n// Global Properties Management\n// ============================================================================\n\n/**\n * Check if any global properties are configured.\n * Fast path: returns false if no properties were ever set.\n */\nexport function hasGlobalProperties(): boolean {\n return globalProperties !== null && Object.keys(globalProperties).length > 0;\n}\n\n/**\n * Get global properties configuration.\n * Returns null if no properties configured (fast path for zero-overhead).\n */\nexport function getGlobalProperties(): Record<\n string,\n PropertyDefinition\n> | null {\n return globalProperties;\n}\n\n/**\n * Set global properties (called from configure).\n * Internal use only.\n */\nfunction setGlobalProperties(\n properties: Record<string, PropertyDefinition>,\n): void {\n if (stylesGenerated) {\n warnOnce(\n 'properties-after-styles',\n `[Tasty] Cannot update properties after styles have been generated.\\n` +\n `The new properties will be ignored.`,\n );\n return;\n }\n globalProperties = properties;\n}\n\n/**\n * Get the effective properties: DEFAULT_PROPERTIES merged with user-configured\n * properties. User properties override defaults with matching keys.\n */\nexport function getEffectiveProperties(): Record<string, PropertyDefinition> {\n if (!globalProperties) return DEFAULT_PROPERTIES;\n return { ...DEFAULT_PROPERTIES, ...globalProperties };\n}\n\n// ============================================================================\n// Global Font Face Management\n// ============================================================================\n\n/**\n * Get global font-face configuration.\n * Returns null if no font faces configured.\n */\nexport function getGlobalFontFace(): Record<string, FontFaceInput> | null {\n return globalFontFace;\n}\n\n/**\n * Set global font faces (called from configure).\n * Internal use only.\n */\nfunction setGlobalFontFace(fontFace: Record<string, FontFaceInput>): void {\n if (stylesGenerated) {\n warnOnce(\n 'fontface-after-styles',\n `[Tasty] Cannot update fontFace after styles have been generated.\\n` +\n `The new font faces will be ignored.`,\n );\n return;\n }\n globalFontFace = fontFace;\n}\n\n// ============================================================================\n// Global Counter Style Management\n// ============================================================================\n\n/**\n * Get global counter-style configuration.\n * Returns null if no counter styles configured.\n */\nexport function getGlobalCounterStyle(): Record<\n string,\n CounterStyleDescriptors\n> | null {\n return globalCounterStyle;\n}\n\n/**\n * Set global counter styles (called from configure).\n * Internal use only.\n */\nfunction setGlobalCounterStyle(\n counterStyle: Record<string, CounterStyleDescriptors>,\n): void {\n if (stylesGenerated) {\n warnOnce(\n 'counterstyle-after-styles',\n `[Tasty] Cannot update counterStyle after styles have been generated.\\n` +\n `The new counter styles will be ignored.`,\n );\n return;\n }\n globalCounterStyle = counterStyle;\n}\n\n// ============================================================================\n// Global Recipes Management\n// ============================================================================\n\n/**\n * Check if any global recipes are configured.\n * Fast path: returns false if no recipes were ever set.\n */\nexport function hasGlobalRecipes(): boolean {\n return globalRecipes !== null && Object.keys(globalRecipes).length > 0;\n}\n\n/**\n * Get global recipes configuration.\n * Returns null if no recipes configured (fast path for zero-overhead).\n */\nexport function getGlobalRecipes(): Record<string, RecipeStyles> | null {\n return globalRecipes;\n}\n\n/**\n * Set global recipes (called from configure).\n * Internal use only.\n */\nfunction setGlobalRecipes(recipes: Record<string, RecipeStyles>): void {\n if (stylesGenerated) {\n warnOnce(\n 'recipes-after-styles',\n `[Tasty] Cannot update recipes after styles have been generated.\\n` +\n `The new recipes will be ignored.`,\n );\n return;\n }\n\n // Dev-mode validation\n if (devMode) {\n for (const [name, recipeStyles] of Object.entries(recipes)) {\n if (name === 'none') {\n warnOnce(\n 'recipe-reserved-none',\n `[Tasty] Recipe name \"none\" is reserved. ` +\n `It is used as a keyword meaning \"no base recipes\" ` +\n `(e.g. recipe: 'none / post-recipe'). ` +\n `Choose a different name for your recipe.`,\n );\n }\n\n for (const key of Object.keys(recipeStyles)) {\n if (isSelector(key)) {\n warnOnce(\n `recipe-selector-${name}-${key}`,\n `[Tasty] Recipe \"${name}\" contains sub-element key \"${key}\". ` +\n `Recipes must be flat styles without sub-element keys. ` +\n `Remove the sub-element key from the recipe definition.`,\n );\n }\n if (key === 'recipe') {\n warnOnce(\n `recipe-recursive-${name}`,\n `[Tasty] Recipe \"${name}\" contains a \"recipe\" key. ` +\n `Recipes cannot reference other recipes. ` +\n `Use space-separated names for composition: recipe: 'base elevated'.`,\n );\n }\n }\n }\n }\n\n globalRecipes = recipes;\n}\n\n// ============================================================================\n// Global Token Styles Management\n// ============================================================================\n\n/**\n * Get global token styles for :root injection.\n * Returns null if no tokens configured.\n */\nexport function getGlobalConfigTokens(): ConfigTokens | null {\n return globalConfigTokens;\n}\n\n/**\n * Set global token styles (called from configure).\n * Internal use only.\n */\nfunction setGlobalConfigTokens(styles: ConfigTokens): void {\n if (stylesGenerated) {\n warnOnce(\n 'tokens-after-styles',\n `[Tasty] Cannot update tokens after styles have been generated.\\n` +\n `The new tokens will be ignored.`,\n );\n return;\n }\n globalConfigTokens = globalConfigTokens\n ? { ...globalConfigTokens, ...styles }\n : styles;\n}\n\n/**\n * Check if configuration is locked (styles have been generated)\n */\nexport function isConfigLocked(): boolean {\n return stylesGenerated;\n}\n\n// ============================================================================\n// Configuration API\n// ============================================================================\n\n/**\n * Configure the Tasty style system.\n *\n * Must be called BEFORE any styles are generated (before first render that uses tasty).\n * After styles are generated, configuration is locked and calls to configure() will\n * emit a warning and be ignored.\n *\n * @example\n * ```ts\n * import { configure } from '@tenphi/tasty';\n *\n * // Configure before app renders\n * configure({\n * nonce: 'abc123',\n * states: {\n * '@mobile': '@media(w < 768px)',\n * '@dark': '@root(theme=dark)',\n * },\n * });\n * ```\n */\nexport function configure(config: Partial<TastyConfig> = {}): void {\n if (stylesGenerated) {\n warnOnce(\n 'configure-after-styles',\n `[Tasty] Cannot call configure() after styles have been generated.\\n` +\n `Configuration must be done before the first render. The configuration will be ignored.`,\n );\n return;\n }\n\n // Collect merged values from plugins first, then override with direct config\n let mergedStates: Record<string, string> = {};\n let mergedUnits: Record<string, string | UnitHandler> = {};\n let mergedFuncs: Record<string, (groups: StyleDetails[]) => string> = {};\n let mergedHandlers: Record<string, StyleHandlerDefinition> = {};\n let mergedReplaceTokens: Record<string, string | number | boolean> = {};\n let mergedConfigTokens: ConfigTokens = {} as ConfigTokens;\n let mergedRecipes: Record<string, RecipeStyles> = {};\n\n // Process plugins in order\n if (config.plugins) {\n for (const plugin of config.plugins) {\n if (plugin.states) {\n mergedStates = { ...mergedStates, ...plugin.states };\n }\n if (plugin.units) {\n mergedUnits = { ...mergedUnits, ...plugin.units };\n }\n if (plugin.funcs) {\n mergedFuncs = { ...mergedFuncs, ...plugin.funcs };\n }\n if (plugin.handlers) {\n mergedHandlers = { ...mergedHandlers, ...plugin.handlers };\n }\n if (plugin.replaceTokens) {\n mergedReplaceTokens = {\n ...mergedReplaceTokens,\n ...plugin.replaceTokens,\n };\n }\n if (plugin.tokens) {\n mergedConfigTokens = { ...mergedConfigTokens, ...plugin.tokens };\n }\n if (plugin.recipes) {\n mergedRecipes = { ...mergedRecipes, ...plugin.recipes };\n }\n }\n }\n\n // Direct config overrides plugins\n if (config.states) {\n mergedStates = { ...mergedStates, ...config.states };\n }\n if (config.units) {\n mergedUnits = { ...mergedUnits, ...config.units };\n }\n if (config.funcs) {\n mergedFuncs = { ...mergedFuncs, ...config.funcs };\n }\n if (config.handlers) {\n mergedHandlers = { ...mergedHandlers, ...config.handlers };\n }\n if (config.replaceTokens) {\n mergedReplaceTokens = { ...mergedReplaceTokens, ...config.replaceTokens };\n }\n if (config.tokens) {\n mergedConfigTokens = { ...mergedConfigTokens, ...config.tokens };\n }\n if (config.recipes) {\n mergedRecipes = { ...mergedRecipes, ...config.recipes };\n }\n\n // Warn on tokens/replaceTokens key conflicts\n if (devMode) {\n const tokenKeys = new Set(Object.keys(mergedConfigTokens));\n for (const key of Object.keys(mergedReplaceTokens)) {\n if (tokenKeys.has(key)) {\n warnOnce(\n `token-conflict-${key}`,\n `[Tasty] Token \"${key}\" is defined in both \\`tokens\\` and \\`replaceTokens\\`. ` +\n `\\`replaceTokens\\` performs parse-time substitution, so the \\`tokens\\` ` +\n `CSS custom property will be injected but never used by Tasty styles. ` +\n `Remove it from one of the two.`,\n );\n }\n }\n }\n\n // Handle color space (must be set before any token processing)\n if (config.colorSpace) {\n setColorSpace(config.colorSpace);\n // Color space affects parser output (e.g. #name.5 → oklch(...) vs rgb(...))\n getGlobalParser().clearCache();\n }\n\n // Handle predefined states\n if (Object.keys(mergedStates).length > 0) {\n setGlobalPredefinedStates(mergedStates);\n }\n\n // Handle parser configuration (merge semantics - extend, not replace)\n const parser = getGlobalParser();\n\n if (config.parserCacheSize !== undefined) {\n parser.updateOptions({ cacheSize: config.parserCacheSize });\n }\n\n if (Object.keys(mergedUnits).length > 0) {\n // Merge with existing units\n const currentUnits = parser.getUnits() ?? CUSTOM_UNITS;\n parser.setUnits({ ...currentUnits, ...mergedUnits });\n }\n\n if (Object.keys(mergedFuncs).length > 0) {\n // Merge with existing funcs\n const currentFuncs = getGlobalFuncs();\n const finalFuncs = { ...currentFuncs, ...mergedFuncs };\n parser.setFuncs(finalFuncs);\n // Also update the global registry so customFunc() continues to work\n Object.assign(currentFuncs, mergedFuncs);\n }\n\n // Handle keyframes\n if (config.keyframes) {\n setGlobalKeyframes(config.keyframes);\n }\n\n // Handle properties\n if (config.properties) {\n setGlobalProperties(config.properties);\n }\n\n // Handle font faces\n if (config.fontFace) {\n setGlobalFontFace(config.fontFace);\n }\n\n // Handle counter styles\n if (config.counterStyle) {\n setGlobalCounterStyle(config.counterStyle);\n }\n\n // Handle custom handlers\n if (Object.keys(mergedHandlers).length > 0) {\n for (const [name, definition] of Object.entries(mergedHandlers)) {\n const handler = normalizeHandlerDefinition(name, definition);\n registerHandler(handler);\n }\n }\n\n // Handle replaceTokens (parse-time substitution)\n if (Object.keys(mergedReplaceTokens).length > 0) {\n const processedTokens: Record<string, string> = {};\n for (const [key, value] of Object.entries(mergedReplaceTokens)) {\n if (key.startsWith('#')) {\n const normalized = normalizeColorTokenValue(value);\n if (normalized === null) continue;\n processedTokens[key] = String(normalized);\n } else if (value === false) {\n continue;\n } else {\n processedTokens[key] = String(value);\n }\n }\n setGlobalPredefinedTokens(processedTokens);\n }\n\n // Handle tokens (CSS custom properties on :root)\n if (Object.keys(mergedConfigTokens).length > 0) {\n setGlobalConfigTokens(mergedConfigTokens);\n }\n\n // Handle recipes\n if (Object.keys(mergedRecipes).length > 0) {\n setGlobalRecipes(mergedRecipes);\n }\n\n const {\n states: _states,\n parserCacheSize: _parserCacheSize,\n units: _units,\n funcs: _funcs,\n plugins: _plugins,\n keyframes: _keyframes,\n properties: _properties,\n fontFace: _fontFace,\n counterStyle: _counterStyle,\n handlers: _handlers,\n tokens: _tokens,\n replaceTokens: _replaceTokens,\n recipes: _recipes,\n colorSpace: _colorSpace,\n ...injectorConfig\n } = config;\n\n const fullConfig: TastyConfig = {\n ...createDefaultConfig(),\n ...currentConfig,\n ...injectorConfig,\n };\n\n // Store the config\n currentConfig = fullConfig;\n\n // Create/replace the global injector\n const storage: TastyGlobalStorage =\n typeof window !== 'undefined' ? window : globalThis;\n storage[GLOBAL_INJECTOR_KEY] = new StyleInjector(fullConfig);\n}\n\n/**\n * Get the current configuration.\n * If not configured, returns default configuration.\n */\nexport function getConfig(): TastyConfig {\n if (!currentConfig) {\n currentConfig = createDefaultConfig(isTestEnvironment());\n }\n return currentConfig;\n}\n\n/**\n * Get the global injector instance.\n * Auto-configures with defaults if not already configured.\n */\nexport function getGlobalInjector(): StyleInjector {\n const storage: TastyGlobalStorage =\n typeof window !== 'undefined' ? window : globalThis;\n\n if (!storage[GLOBAL_INJECTOR_KEY]) {\n configure();\n }\n\n return storage[GLOBAL_INJECTOR_KEY]!;\n}\n\n/**\n * Reset configuration (for testing only).\n * Clears the global injector and allows reconfiguration.\n */\nexport function resetConfig(): void {\n stylesGenerated = false;\n currentConfig = null;\n globalKeyframes = null;\n _hasGlobalKeyframes = false;\n globalProperties = null;\n globalFontFace = null;\n globalCounterStyle = null;\n globalRecipes = null;\n globalConfigTokens = null;\n resetGlobalPredefinedTokens();\n resetHandlers();\n resetColorSpace();\n clearPipelineCache();\n emittedWarnings.clear();\n\n const storage: TastyGlobalStorage =\n typeof window !== 'undefined' ? window : globalThis;\n delete storage[GLOBAL_INJECTOR_KEY];\n}\n\n// Re-export TastyConfig as StyleInjectorConfig for backward compatibility\nexport type { TastyConfig as StyleInjectorConfig };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["/**\n * Tasty Configuration Module\n *\n * Centralizes all tasty configuration, including:\n * - Style injector settings (nonce, cleanup thresholds, etc.)\n * - Global predefined states for advanced state mapping\n * - stylesGenerated flag that locks configuration after first style generation\n *\n * Configuration must be done BEFORE any styles are generated.\n * After the first `inject()` call, configuration is locked and attempts to\n * reconfigure will emit a warning and be ignored.\n */\n\nimport { StyleInjector } from './injector/injector';\nimport { clearPipelineCache, isSelector, renderStyles } from './pipeline';\nimport { setGlobalPredefinedStates } from './states';\nimport {\n normalizeHandlerDefinition,\n registerHandler,\n resetHandlers,\n} from './styles/predefined';\nimport { resetColorSpace, setColorSpace } from './utils/color-space';\nimport { isDevEnv } from './utils/is-dev-env';\nimport {\n CUSTOM_UNITS,\n getGlobalFuncs,\n getGlobalParser,\n normalizeColorTokenValue,\n resetGlobalPredefinedTokens,\n setGlobalPredefinedTokens,\n} from './utils/styles';\n\nimport type { ColorSpace } from './utils/color-space';\n\nimport type {\n CounterStyleDescriptors,\n FontFaceInput,\n GCConfig,\n KeyframesSteps,\n PropertyDefinition,\n} from './injector/types';\nimport type { StyleDetails, UnitHandler } from './parser/types';\nimport type { StyleResult } from './pipeline';\nimport type { TastyPlugin } from './plugins/types';\nimport type { RecipeStyles, ConfigTokens } from './styles/types';\nimport type { StyleHandlerDefinition } from './utils/styles';\n\n/**\n * Configuration options for the Tasty style system\n */\nexport interface TastyConfig {\n /** CSP nonce for style elements */\n nonce?: string;\n /** Maximum rules per stylesheet (default: 8192) */\n maxRulesPerSheet?: number;\n /** Force text injection mode, auto-detected in test environments (default: auto) */\n forceTextInjection?: boolean;\n /** Enable development mode features: performance metrics and debug info (default: auto) */\n devMode?: boolean;\n /**\n * Global predefined states for advanced state mapping.\n * These are state aliases that can be used in any component.\n * Example: { '@mobile': '@media(w < 920px)', '@dark': '@root(theme=dark)' }\n */\n states?: Record<string, string>;\n /**\n * Parser LRU cache size (default: 1000).\n * Larger values improve performance for apps with many unique style values.\n */\n parserCacheSize?: number;\n /**\n * Custom units for the style parser (merged with built-in units).\n * Units transform numeric values like `2x` → `calc(2 * var(--gap))`.\n * @example { em: 'em', vw: 'vw', custom: (n) => `${n * 10}px` }\n */\n units?: Record<string, string | UnitHandler>;\n /**\n * Custom functions for the style parser (merged with existing).\n * Functions process parsed style groups and return CSS values.\n * @example { myFunc: (groups) => groups.map(g => g.output).join(' ') }\n */\n funcs?: Record<string, (groups: StyleDetails[]) => string>;\n /**\n * Color space used for decomposed color token companion variables.\n * Controls the CSS function and suffix for alpha composition.\n *\n * - `'rgb'` — suffix `-rgb`, e.g. `rgb(var(--name-color-rgb) / .5)`\n * - `'hsl'` — suffix `-hsl`, e.g. `hsl(var(--name-color-hsl) / .5)`\n * - `'oklch'` — suffix `-oklch`, e.g. `oklch(var(--name-color-oklch) / .5)`\n *\n * @default 'oklch'\n */\n colorSpace?: ColorSpace;\n /**\n * Automatically infer and register CSS @property declarations\n * from custom property values found in styles, keyframes, and global config.\n * Covers all types: \\<color\\>, \\<number\\>, \\<length\\>, \\<angle\\>, \\<percentage\\>, \\<time\\>.\n * When false, only explicitly declared @properties are registered.\n * @default true\n */\n autoPropertyTypes?: boolean;\n /**\n * Garbage collection configuration for unused styles.\n * GC is triggered by touch count: every `touchInterval` touches, the\n * oldest unused styles are evicted when their count exceeds `capacity`.\n * @example\n * ```ts\n * configure({\n * gc: { touchInterval: 1000, capacity: 1000 },\n * });\n * ```\n */\n gc?: GCConfig;\n /**\n * Plugins that extend tasty with custom functions, units, or states.\n * Plugins are processed in order, with later plugins overriding earlier ones.\n * @example\n * ```ts\n * import { okhslPlugin } from '@tenphi/tasty';\n *\n * configure({\n * plugins: [okhslPlugin()],\n * });\n * ```\n */\n plugins?: TastyPlugin[];\n /**\n * Global keyframes definitions that can be referenced by animation names in styles.\n * Keys are animation names, values are keyframes step definitions.\n * Keyframes are only injected when actually used in styles.\n * @example\n * ```ts\n * configure({\n * keyframes: {\n * fadeIn: { from: { opacity: 0 }, to: { opacity: 1 } },\n * pulse: { '0%, 100%': { transform: 'scale(1)' }, '50%': { transform: 'scale(1.05)' } },\n * },\n * });\n * ```\n */\n keyframes?: Record<string, KeyframesSteps>;\n /**\n * Global CSS @property definitions for custom properties.\n * Keys use tasty token syntax ($name for properties, #name for colors).\n *\n * Tasty ships with `DEFAULT_PROPERTIES` (e.g. `$gap`, `$radius`, `#white`,\n * `#black`, `#clear`, `#border`, etc.) that are always included.\n * Properties you specify here are merged on top, so you can override any\n * default by using the same key.\n *\n * For color tokens (#name), `syntax: '<color>'` is auto-set and\n * `initialValue` defaults to `'transparent'` if not specified.\n *\n * @example\n * ```ts\n * configure({\n * properties: {\n * '$rotation': { syntax: '<angle>', initialValue: '0deg' },\n * '$scale': { syntax: '<number>', inherits: false, initialValue: 1 },\n * '#accent': { initialValue: 'purple' }, // syntax: '<color>' auto-set\n * // Override a default property:\n * '$gap': { syntax: '<length>', inherits: true, initialValue: '8px' },\n * },\n * });\n *\n * // Now use in styles - properties are registered when component renders:\n * const Spinner = tasty({\n * styles: {\n * transform: 'rotate($rotation)',\n * transition: '$$rotation 0.3s', // outputs: --rotation 0.3s\n * },\n * });\n * ```\n */\n properties?: Record<string, PropertyDefinition>;\n /**\n * Global @font-face definitions.\n * Keys are font-family names, values are descriptors or arrays of descriptors\n * (for multiple weights/styles of the same family).\n * Injected eagerly when styles are first generated.\n * @example\n * ```ts\n * configure({\n * fontFace: {\n * 'Brand Sans': [\n * { src: 'url(\"/fonts/brand-regular.woff2\") format(\"woff2\")', fontWeight: 400, fontDisplay: 'swap' },\n * { src: 'url(\"/fonts/brand-bold.woff2\") format(\"woff2\")', fontWeight: 700, fontDisplay: 'swap' },\n * ],\n * Icons: { src: 'url(\"/fonts/icons.woff2\") format(\"woff2\")', fontDisplay: 'block' },\n * },\n * });\n * ```\n */\n fontFace?: Record<string, FontFaceInput>;\n /**\n * Global @counter-style definitions.\n * Keys are counter-style names, values are descriptor objects.\n * Injected eagerly when styles are first generated.\n * @example\n * ```ts\n * configure({\n * counterStyle: {\n * thumbs: { system: 'cyclic', symbols: '\"👍\"', suffix: '\" \"' },\n * },\n * });\n * ```\n */\n counterStyle?: Record<string, CounterStyleDescriptors>;\n /**\n * Custom style handlers that transform style properties into CSS declarations.\n * Handlers replace built-in handlers for the same style name.\n * @example\n * ```ts\n * import { styleHandlers } from '@tenphi/tasty';\n *\n * configure({\n * handlers: {\n * // Override fill with custom behavior\n * fill: ({ fill }) => {\n * if (fill?.startsWith('gradient:')) {\n * return { background: fill.slice(9) };\n * }\n * return styleHandlers.fill({ fill });\n * },\n * // Add new custom style\n * elevation: ({ elevation }) => {\n * const level = parseInt(elevation) || 1;\n * return {\n * 'box-shadow': `0 ${level * 2}px ${level * 4}px rgba(0,0,0,0.1)`,\n * 'z-index': String(level * 100),\n * };\n * },\n * },\n * });\n * ```\n */\n handlers?: Record<string, StyleHandlerDefinition>;\n /**\n * Design tokens injected as CSS custom properties on `:root`.\n * Values are parsed through the Tasty DSL. Supports state maps\n * for responsive/theme-aware tokens.\n *\n * - `$name` keys become `--name` CSS custom properties\n * - `#name` keys become `--name-color` and `--name-color-{colorSpace}` properties\n *\n * Tokens are injected once when the first style is rendered.\n *\n * @example\n * ```ts\n * configure({\n * tokens: {\n * '$gap': '4px',\n * '#primary': {\n * '': '#purple',\n * '@dark': '#light-purple',\n * },\n * },\n * });\n * ```\n */\n tokens?: ConfigTokens;\n /**\n * Predefined tokens that are replaced during style parsing (parse-time substitution).\n * Use `$name` for custom properties and `#name` for color tokens.\n * Values are substituted inline before CSS generation, unlike `tokens` which\n * inject CSS custom properties on `:root`.\n *\n * For color tokens (#name), boolean `true` is converted to `transparent`.\n *\n * @example\n * ```ts\n * configure({\n * replaceTokens: {\n * $spacing: '2x',\n * '#accent': '#purple',\n * '#overlay': true, // → transparent\n * },\n * });\n *\n * // Now use in styles - tokens are replaced at parse time:\n * const Card = tasty({\n * styles: {\n * padding: '$spacing', // → calc(2 * var(--gap))\n * fill: '#accent', // → var(--purple-color)\n * },\n * });\n * ```\n */\n replaceTokens?: Record<`$${string}`, string | number | boolean> &\n Record<`#${string}`, string | number | boolean>;\n /**\n * Predefined style recipes -- named style bundles that can be applied via `recipe` style property.\n * Recipe values are flat tasty styles (no sub-element keys). They may contain base styles,\n * tokens (`$name`/`#name` definitions), local states, `@keyframes`, and `@properties`.\n *\n * Components reference recipes via: `recipe: 'name1 name2'` in their styles.\n * Use `/` to separate base recipes from post recipes: `recipe: 'base1 base2 / post1'`.\n * Use `none` to skip base recipes: `recipe: 'none / post1'`.\n * Resolution order: `base_recipes → component styles → post_recipes`.\n *\n * Recipes cannot reference other recipes.\n *\n * @example\n * ```ts\n * configure({\n * recipes: {\n * card: { padding: '4x', fill: '#surface', radius: '1r', border: true },\n * elevated: { shadow: '2x 2x 4x #shadow' },\n * },\n * });\n *\n * // Usage in styles:\n * const Card = tasty({\n * styles: {\n * recipe: 'card elevated',\n * color: '#text', // Overrides recipe values\n * },\n * });\n * ```\n */\n recipes?: Record<string, RecipeStyles>;\n}\n\n// Warnings tracking to avoid duplicates\nconst emittedWarnings = new Set<string>();\n\nconst devMode = isDevEnv();\n\n/**\n * Emit a warning only once\n */\nfunction warnOnce(key: string, message: string): void {\n if (devMode && !emittedWarnings.has(key)) {\n emittedWarnings.add(key);\n console.warn(message);\n }\n}\n\n// ============================================================================\n// Configuration State\n// ============================================================================\n\n// Track whether styles have been generated (locks configuration)\nlet stylesGenerated = false;\n\n// Current configuration (null until first configure() or auto-configured on first use)\nlet currentConfig: TastyConfig | null = null;\n\n// Global keyframes storage (null = no keyframes configured, empty object checked via hasGlobalKeyframes)\nlet globalKeyframes: Record<string, KeyframesSteps> | null = null;\n\n// Global font-face storage (null = no font faces configured)\nlet globalFontFace: Record<string, FontFaceInput> | null = null;\n\n// Global counter-style storage (null = no counter styles configured)\nlet globalCounterStyle: Record<string, CounterStyleDescriptors> | null = null;\n\n// Global properties storage (null = no properties configured)\nlet globalProperties: Record<string, PropertyDefinition> | null = null;\n\n// Global recipes storage (null = no recipes configured)\nlet globalRecipes: Record<string, RecipeStyles> | null = null;\n\n// Global token styles storage (injected as :root CSS custom properties)\nlet globalConfigTokens: ConfigTokens | null = null;\n\n/**\n * Default properties shipped with tasty.\n * These are always included unless explicitly overridden via `configure({ properties })`.\n * Keys use tasty token syntax (#name for colors, $name for other properties).\n *\n * For properties with CSS @property-compatible types (length, time, number, color),\n * an `initialValue` is provided so the property works even without a project-level token.\n */\nexport const DEFAULT_PROPERTIES: Record<string, PropertyDefinition> = {\n // Used by dual-fill feature to enable CSS transitions on the second fill color\n '#tasty-second-fill': {\n inherits: false,\n initialValue: 'transparent',\n },\n // Current color context variable (set by the color style handler).\n '#current': {\n inherits: true,\n initialValue: 'transparent',\n },\n // White and black are fundamental colors that need explicit initial values.\n '#white': {\n inherits: true,\n initialValue: 'rgb(255 255 255)',\n },\n '#black': {\n inherits: true,\n initialValue: 'rgb(0 0 0)',\n },\n // Shorthand for transparent\n '#clear': {\n inherits: true,\n initialValue: 'transparent',\n },\n // Default border color\n '#border': {\n inherits: true,\n initialValue: 'rgb(0 0 0)',\n },\n\n // ---- Core design tokens used by style handlers ----\n // These provide sensible defaults so tasty works standalone without a design system.\n // Consuming projects (e.g. uikit) override these by defining tokens on :root.\n\n $gap: {\n syntax: '<length>',\n inherits: true,\n initialValue: '4px',\n },\n $radius: {\n syntax: '<length>',\n inherits: true,\n initialValue: '6px',\n },\n '$border-width': {\n syntax: '<length>',\n inherits: true,\n initialValue: '1px',\n },\n '$outline-width': {\n syntax: '<length>',\n inherits: true,\n initialValue: '3px',\n },\n $transition: {\n syntax: '<time>',\n inherits: true,\n initialValue: '80ms',\n },\n // Used by radius.ts for `radius=\"leaf\"` modifier\n '$sharp-radius': {\n syntax: '<length>',\n inherits: true,\n initialValue: '0px',\n },\n // Used by preset.ts for `preset=\"name / strong\"`\n '$bold-font-weight': {\n syntax: '<number>',\n inherits: true,\n initialValue: '700',\n },\n // Used by preset.ts as fallback font stacks\n '$font-sans-fallback': {\n syntax: '*',\n inherits: true,\n initialValue:\n 'system-ui, -apple-system, \"Segoe UI\", Roboto, Helvetica, Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\", sans-serif',\n },\n '$font-mono-fallback': {\n syntax: '*',\n inherits: true,\n initialValue:\n 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace',\n },\n};\n\n// Global injector instance key\nconst GLOBAL_INJECTOR_KEY = '__TASTY_GLOBAL_INJECTOR__';\n\ninterface TastyGlobalStorage {\n [GLOBAL_INJECTOR_KEY]?: StyleInjector;\n}\n\ndeclare global {\n interface Window {\n [GLOBAL_INJECTOR_KEY]?: StyleInjector;\n }\n\n var __TASTY_GLOBAL_INJECTOR__: StyleInjector | undefined;\n}\n\n/**\n * Detect if we're running in a test environment\n */\nexport function isTestEnvironment(): boolean {\n // Check Node.js environment\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'test') {\n return true;\n }\n\n // Check for test runner globals (safely)\n if (typeof global !== 'undefined') {\n const g = global as unknown as Record<string, unknown>;\n if (g.vi || g.jest || g.expect || g.describe || g.it) {\n return true;\n }\n }\n\n // Check for jsdom environment (common in tests)\n if (\n typeof window !== 'undefined' &&\n window.navigator?.userAgent?.includes('jsdom')\n ) {\n return true;\n }\n\n // Check for other test runners\n if (typeof globalThis !== 'undefined') {\n const gt = globalThis as unknown as Record<string, unknown>;\n if (gt.vitest || gt.mocha) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Create default configuration with optional test environment detection\n */\nfunction createDefaultConfig(isTest?: boolean): TastyConfig {\n return {\n maxRulesPerSheet: 8192,\n forceTextInjection: isTest ?? false,\n devMode: isDevEnv(),\n };\n}\n\n// ============================================================================\n// stylesGenerated Flag Management\n// ============================================================================\n\n/**\n * Mark that styles have been generated (called by injector on first inject)\n * This locks the configuration - no further changes allowed.\n * Also injects internal and global properties.\n */\nexport function markStylesGenerated(): void {\n if (stylesGenerated) return; // Already marked, skip\n\n stylesGenerated = true;\n\n const injector = getGlobalInjector();\n\n // Inject all properties (defaults merged with user-configured overrides)\n for (const [token, definition] of Object.entries(getEffectiveProperties())) {\n injector.property(token, definition);\n }\n\n // Inject global @font-face rules (eagerly — fonts should be available before render)\n if (globalFontFace && Object.keys(globalFontFace).length > 0) {\n for (const [family, input] of Object.entries(globalFontFace)) {\n const descriptors = Array.isArray(input) ? input : [input];\n for (const desc of descriptors) {\n injector.fontFace(family, desc);\n }\n }\n }\n\n // Inject global @counter-style rules (eagerly)\n if (globalCounterStyle && Object.keys(globalCounterStyle).length > 0) {\n for (const [name, descriptors] of Object.entries(globalCounterStyle)) {\n injector.counterStyle(name, descriptors);\n }\n }\n\n // Inject configured tokens as :root CSS custom properties\n if (globalConfigTokens && Object.keys(globalConfigTokens).length > 0) {\n const tokenRules = renderStyles(\n globalConfigTokens,\n ':root',\n ) as StyleResult[];\n if (tokenRules.length > 0) {\n injector.injectGlobal(tokenRules);\n }\n }\n}\n\n/**\n * Check if styles have been generated (configuration is locked)\n */\nexport function hasStylesGenerated(): boolean {\n return stylesGenerated;\n}\n\n/**\n * Reset styles generated flag (for testing only)\n */\nexport function resetStylesGenerated(): void {\n stylesGenerated = false;\n emittedWarnings.clear();\n}\n\n// ============================================================================\n// Global Keyframes Management\n// ============================================================================\n\nlet _hasGlobalKeyframes = false;\n\n/**\n * Check if any global keyframes are configured.\n * Uses a pre-computed flag to avoid Object.keys() allocation on every call.\n */\nexport function hasGlobalKeyframes(): boolean {\n return _hasGlobalKeyframes;\n}\n\n/**\n * Get global keyframes configuration.\n * Returns null if no keyframes configured (fast path for zero-overhead).\n */\nexport function getGlobalKeyframes(): Record<string, KeyframesSteps> | null {\n return globalKeyframes;\n}\n\n/**\n * Set global keyframes (called from configure).\n * Internal use only.\n */\nfunction setGlobalKeyframes(keyframes: Record<string, KeyframesSteps>): void {\n if (stylesGenerated) {\n warnOnce(\n 'keyframes-after-styles',\n `[Tasty] Cannot update keyframes after styles have been generated.\\n` +\n `The new keyframes will be ignored.`,\n );\n return;\n }\n globalKeyframes = keyframes;\n _hasGlobalKeyframes = Object.keys(keyframes).length > 0;\n}\n\n// ============================================================================\n// Global Properties Management\n// ============================================================================\n\n/**\n * Check if any global properties are configured.\n * Fast path: returns false if no properties were ever set.\n */\nexport function hasGlobalProperties(): boolean {\n return globalProperties !== null && Object.keys(globalProperties).length > 0;\n}\n\n/**\n * Get global properties configuration.\n * Returns null if no properties configured (fast path for zero-overhead).\n */\nexport function getGlobalProperties(): Record<\n string,\n PropertyDefinition\n> | null {\n return globalProperties;\n}\n\n/**\n * Set global properties (called from configure).\n * Internal use only.\n */\nfunction setGlobalProperties(\n properties: Record<string, PropertyDefinition>,\n): void {\n if (stylesGenerated) {\n warnOnce(\n 'properties-after-styles',\n `[Tasty] Cannot update properties after styles have been generated.\\n` +\n `The new properties will be ignored.`,\n );\n return;\n }\n globalProperties = properties;\n}\n\n/**\n * Get the effective properties: DEFAULT_PROPERTIES merged with user-configured\n * properties. User properties override defaults with matching keys.\n */\nexport function getEffectiveProperties(): Record<string, PropertyDefinition> {\n if (!globalProperties) return DEFAULT_PROPERTIES;\n return { ...DEFAULT_PROPERTIES, ...globalProperties };\n}\n\n// ============================================================================\n// Global Font Face Management\n// ============================================================================\n\n/**\n * Get global font-face configuration.\n * Returns null if no font faces configured.\n */\nexport function getGlobalFontFace(): Record<string, FontFaceInput> | null {\n return globalFontFace;\n}\n\n/**\n * Set global font faces (called from configure).\n * Internal use only.\n */\nfunction setGlobalFontFace(fontFace: Record<string, FontFaceInput>): void {\n if (stylesGenerated) {\n warnOnce(\n 'fontface-after-styles',\n `[Tasty] Cannot update fontFace after styles have been generated.\\n` +\n `The new font faces will be ignored.`,\n );\n return;\n }\n globalFontFace = fontFace;\n}\n\n// ============================================================================\n// Global Counter Style Management\n// ============================================================================\n\n/**\n * Get global counter-style configuration.\n * Returns null if no counter styles configured.\n */\nexport function getGlobalCounterStyle(): Record<\n string,\n CounterStyleDescriptors\n> | null {\n return globalCounterStyle;\n}\n\n/**\n * Set global counter styles (called from configure).\n * Internal use only.\n */\nfunction setGlobalCounterStyle(\n counterStyle: Record<string, CounterStyleDescriptors>,\n): void {\n if (stylesGenerated) {\n warnOnce(\n 'counterstyle-after-styles',\n `[Tasty] Cannot update counterStyle after styles have been generated.\\n` +\n `The new counter styles will be ignored.`,\n );\n return;\n }\n globalCounterStyle = counterStyle;\n}\n\n// ============================================================================\n// Global Recipes Management\n// ============================================================================\n\n/**\n * Check if any global recipes are configured.\n * Fast path: returns false if no recipes were ever set.\n */\nexport function hasGlobalRecipes(): boolean {\n return globalRecipes !== null && Object.keys(globalRecipes).length > 0;\n}\n\n/**\n * Get global recipes configuration.\n * Returns null if no recipes configured (fast path for zero-overhead).\n */\nexport function getGlobalRecipes(): Record<string, RecipeStyles> | null {\n return globalRecipes;\n}\n\n/**\n * Set global recipes (called from configure).\n * Internal use only.\n */\nfunction setGlobalRecipes(recipes: Record<string, RecipeStyles>): void {\n if (stylesGenerated) {\n warnOnce(\n 'recipes-after-styles',\n `[Tasty] Cannot update recipes after styles have been generated.\\n` +\n `The new recipes will be ignored.`,\n );\n return;\n }\n\n // Dev-mode validation\n if (devMode) {\n for (const [name, recipeStyles] of Object.entries(recipes)) {\n if (name === 'none') {\n warnOnce(\n 'recipe-reserved-none',\n `[Tasty] Recipe name \"none\" is reserved. ` +\n `It is used as a keyword meaning \"no base recipes\" ` +\n `(e.g. recipe: 'none / post-recipe'). ` +\n `Choose a different name for your recipe.`,\n );\n }\n\n for (const key of Object.keys(recipeStyles)) {\n if (isSelector(key)) {\n warnOnce(\n `recipe-selector-${name}-${key}`,\n `[Tasty] Recipe \"${name}\" contains sub-element key \"${key}\". ` +\n `Recipes must be flat styles without sub-element keys. ` +\n `Remove the sub-element key from the recipe definition.`,\n );\n }\n if (key === 'recipe') {\n warnOnce(\n `recipe-recursive-${name}`,\n `[Tasty] Recipe \"${name}\" contains a \"recipe\" key. ` +\n `Recipes cannot reference other recipes. ` +\n `Use space-separated names for composition: recipe: 'base elevated'.`,\n );\n }\n }\n }\n }\n\n globalRecipes = recipes;\n}\n\n// ============================================================================\n// Global Token Styles Management\n// ============================================================================\n\n/**\n * Get global token styles for :root injection.\n * Returns null if no tokens configured.\n */\nexport function getGlobalConfigTokens(): ConfigTokens | null {\n return globalConfigTokens;\n}\n\n/**\n * Set global token styles (called from configure).\n * Internal use only.\n */\nfunction setGlobalConfigTokens(styles: ConfigTokens): void {\n if (stylesGenerated) {\n warnOnce(\n 'tokens-after-styles',\n `[Tasty] Cannot update tokens after styles have been generated.\\n` +\n `The new tokens will be ignored.`,\n );\n return;\n }\n globalConfigTokens = globalConfigTokens\n ? { ...globalConfigTokens, ...styles }\n : styles;\n}\n\n/**\n * Check if configuration is locked (styles have been generated)\n */\nexport function isConfigLocked(): boolean {\n return stylesGenerated;\n}\n\n// ============================================================================\n// Configuration API\n// ============================================================================\n\n/**\n * Configure the Tasty style system.\n *\n * Must be called BEFORE any styles are generated (before first render that uses tasty).\n * After styles are generated, configuration is locked and calls to configure() will\n * emit a warning and be ignored.\n *\n * @example\n * ```ts\n * import { configure } from '@tenphi/tasty';\n *\n * // Configure before app renders\n * configure({\n * nonce: 'abc123',\n * states: {\n * '@mobile': '@media(w < 768px)',\n * '@dark': '@root(theme=dark)',\n * },\n * });\n * ```\n */\nexport function configure(config: Partial<TastyConfig> = {}): void {\n if (stylesGenerated) {\n warnOnce(\n 'configure-after-styles',\n `[Tasty] Cannot call configure() after styles have been generated.\\n` +\n `Configuration must be done before the first render. The configuration will be ignored.`,\n );\n return;\n }\n\n // Collect merged values from plugins first, then override with direct config\n let mergedStates: Record<string, string> = {};\n let mergedUnits: Record<string, string | UnitHandler> = {};\n let mergedFuncs: Record<string, (groups: StyleDetails[]) => string> = {};\n let mergedHandlers: Record<string, StyleHandlerDefinition> = {};\n let mergedReplaceTokens: Record<string, string | number | boolean> = {};\n let mergedConfigTokens: ConfigTokens = {} as ConfigTokens;\n let mergedRecipes: Record<string, RecipeStyles> = {};\n\n // Process plugins in order\n if (config.plugins) {\n for (const plugin of config.plugins) {\n if (plugin.states) {\n mergedStates = { ...mergedStates, ...plugin.states };\n }\n if (plugin.units) {\n mergedUnits = { ...mergedUnits, ...plugin.units };\n }\n if (plugin.funcs) {\n mergedFuncs = { ...mergedFuncs, ...plugin.funcs };\n }\n if (plugin.handlers) {\n mergedHandlers = { ...mergedHandlers, ...plugin.handlers };\n }\n if (plugin.replaceTokens) {\n mergedReplaceTokens = {\n ...mergedReplaceTokens,\n ...plugin.replaceTokens,\n };\n }\n if (plugin.tokens) {\n mergedConfigTokens = { ...mergedConfigTokens, ...plugin.tokens };\n }\n if (plugin.recipes) {\n mergedRecipes = { ...mergedRecipes, ...plugin.recipes };\n }\n }\n }\n\n // Direct config overrides plugins\n if (config.states) {\n mergedStates = { ...mergedStates, ...config.states };\n }\n if (config.units) {\n mergedUnits = { ...mergedUnits, ...config.units };\n }\n if (config.funcs) {\n mergedFuncs = { ...mergedFuncs, ...config.funcs };\n }\n if (config.handlers) {\n mergedHandlers = { ...mergedHandlers, ...config.handlers };\n }\n if (config.replaceTokens) {\n mergedReplaceTokens = { ...mergedReplaceTokens, ...config.replaceTokens };\n }\n if (config.tokens) {\n mergedConfigTokens = { ...mergedConfigTokens, ...config.tokens };\n }\n if (config.recipes) {\n mergedRecipes = { ...mergedRecipes, ...config.recipes };\n }\n\n // Warn on tokens/replaceTokens key conflicts\n if (devMode) {\n const tokenKeys = new Set(Object.keys(mergedConfigTokens));\n for (const key of Object.keys(mergedReplaceTokens)) {\n if (tokenKeys.has(key)) {\n warnOnce(\n `token-conflict-${key}`,\n `[Tasty] Token \"${key}\" is defined in both \\`tokens\\` and \\`replaceTokens\\`. ` +\n `\\`replaceTokens\\` performs parse-time substitution, so the \\`tokens\\` ` +\n `CSS custom property will be injected but never used by Tasty styles. ` +\n `Remove it from one of the two.`,\n );\n }\n }\n }\n\n // Handle color space (must be set before any token processing)\n if (config.colorSpace) {\n setColorSpace(config.colorSpace);\n // Color space affects parser output (e.g. #name.5 → oklch(...) vs rgb(...))\n getGlobalParser().clearCache();\n }\n\n // Handle predefined states\n if (Object.keys(mergedStates).length > 0) {\n setGlobalPredefinedStates(mergedStates);\n }\n\n // Handle parser configuration (merge semantics - extend, not replace)\n const parser = getGlobalParser();\n\n if (config.parserCacheSize !== undefined) {\n parser.updateOptions({ cacheSize: config.parserCacheSize });\n }\n\n if (Object.keys(mergedUnits).length > 0) {\n // Merge with existing units\n const currentUnits = parser.getUnits() ?? CUSTOM_UNITS;\n parser.setUnits({ ...currentUnits, ...mergedUnits });\n }\n\n if (Object.keys(mergedFuncs).length > 0) {\n // Merge with existing funcs\n const currentFuncs = getGlobalFuncs();\n const finalFuncs = { ...currentFuncs, ...mergedFuncs };\n parser.setFuncs(finalFuncs);\n // Also update the global registry so customFunc() continues to work\n Object.assign(currentFuncs, mergedFuncs);\n }\n\n // Handle keyframes\n if (config.keyframes) {\n setGlobalKeyframes(config.keyframes);\n }\n\n // Handle properties\n if (config.properties) {\n setGlobalProperties(config.properties);\n }\n\n // Handle font faces\n if (config.fontFace) {\n setGlobalFontFace(config.fontFace);\n }\n\n // Handle counter styles\n if (config.counterStyle) {\n setGlobalCounterStyle(config.counterStyle);\n }\n\n // Handle custom handlers\n if (Object.keys(mergedHandlers).length > 0) {\n for (const [name, definition] of Object.entries(mergedHandlers)) {\n const handler = normalizeHandlerDefinition(name, definition);\n registerHandler(handler);\n }\n }\n\n // Handle replaceTokens (parse-time substitution)\n if (Object.keys(mergedReplaceTokens).length > 0) {\n const processedTokens: Record<string, string> = {};\n for (const [key, value] of Object.entries(mergedReplaceTokens)) {\n if (key.startsWith('#')) {\n const normalized = normalizeColorTokenValue(value);\n if (normalized === null) continue;\n processedTokens[key] = String(normalized);\n } else if (value === false) {\n continue;\n } else {\n processedTokens[key] = String(value);\n }\n }\n setGlobalPredefinedTokens(processedTokens);\n }\n\n // Handle tokens (CSS custom properties on :root)\n if (Object.keys(mergedConfigTokens).length > 0) {\n setGlobalConfigTokens(mergedConfigTokens);\n }\n\n // Handle recipes\n if (Object.keys(mergedRecipes).length > 0) {\n setGlobalRecipes(mergedRecipes);\n }\n\n const {\n states: _states,\n parserCacheSize: _parserCacheSize,\n units: _units,\n funcs: _funcs,\n plugins: _plugins,\n keyframes: _keyframes,\n properties: _properties,\n fontFace: _fontFace,\n counterStyle: _counterStyle,\n handlers: _handlers,\n tokens: _tokens,\n replaceTokens: _replaceTokens,\n recipes: _recipes,\n colorSpace: _colorSpace,\n ...injectorConfig\n } = config;\n\n const fullConfig: TastyConfig = {\n ...createDefaultConfig(),\n ...currentConfig,\n ...injectorConfig,\n };\n\n // Store the config\n currentConfig = fullConfig;\n\n // Create/replace the global injector\n const storage: TastyGlobalStorage =\n typeof window !== 'undefined' ? window : globalThis;\n storage[GLOBAL_INJECTOR_KEY] = new StyleInjector(fullConfig);\n}\n\n/**\n * Get the current configuration.\n * If not configured, returns default configuration.\n */\nexport function getConfig(): TastyConfig {\n if (!currentConfig) {\n currentConfig = createDefaultConfig(isTestEnvironment());\n }\n return currentConfig;\n}\n\n/**\n * Get the global injector instance.\n * Auto-configures with defaults if not already configured.\n */\nexport function getGlobalInjector(): StyleInjector {\n const storage: TastyGlobalStorage =\n typeof window !== 'undefined' ? window : globalThis;\n\n if (!storage[GLOBAL_INJECTOR_KEY]) {\n configure();\n }\n\n return storage[GLOBAL_INJECTOR_KEY]!;\n}\n\n/**\n * Reset configuration (for testing only).\n * Clears the global injector and allows reconfiguration.\n */\nexport function resetConfig(): void {\n stylesGenerated = false;\n currentConfig = null;\n globalKeyframes = null;\n _hasGlobalKeyframes = false;\n globalProperties = null;\n globalFontFace = null;\n globalCounterStyle = null;\n globalRecipes = null;\n globalConfigTokens = null;\n resetGlobalPredefinedTokens();\n resetHandlers();\n resetColorSpace();\n clearPipelineCache();\n emittedWarnings.clear();\n\n const storage: TastyGlobalStorage =\n typeof window !== 'undefined' ? window : globalThis;\n delete storage[GLOBAL_INJECTOR_KEY];\n}\n\n// Re-export TastyConfig as StyleInjectorConfig for backward compatibility\nexport type { TastyConfig as StyleInjectorConfig };\n"],"mappings":"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"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ import { BASE_STYLES, BLOCK_INNER_STYLES, BLOCK_OUTER_STYLES, BLOCK_STYLES, COLO
|
|
|
20
20
|
import { BaseStyleProps, BlockInnerStyleProps, BlockOuterStyleProps, BlockStyleProps, ColorStyleProps, ContainerStyleProps, DimensionStyleProps, FlowStyleProps, GlobalStyledProps, InnerStyleProps, ModValue, Mods, OuterStyleProps, PositionStyleProps, Props, ShortGridStyles, TagName, TastyExtensionConfig, TastyThemeNames, TextStyleProps, TokenValue, Tokens } from "../types.js";
|
|
21
21
|
import { styleHandlers } from "../styles/predefined.js";
|
|
22
22
|
import { ComputeStylesOptions, ComputeStylesResult, computeStyles } from "../compute-styles.js";
|
|
23
|
-
import { PropertyOptions, cleanup, counterStyle, createInjector, destroy, fontFace, gc, getCssText, getCssTextForNode, getIsTestEnvironment, getRawCSSText, inject, injectGlobal, injectRawCSS, injector, isPropertyDefined, keyframes,
|
|
23
|
+
import { PropertyOptions, cleanup, counterStyle, createInjector, destroy, fontFace, gc, getCssText, getCssTextForNode, getIsTestEnvironment, getRawCSSText, inject, injectGlobal, injectRawCSS, injector, isPropertyDefined, keyframes, property, touch } from "../injector/index.js";
|
|
24
24
|
import { filterBaseProps } from "../utils/filter-base-props.js";
|
|
25
25
|
import { color } from "../utils/colors.js";
|
|
26
26
|
import { _modAttrs } from "../utils/mod-attrs.js";
|
|
@@ -31,4 +31,4 @@ import { deprecationWarning, warn } from "../utils/warnings.js";
|
|
|
31
31
|
import { processTokens } from "../utils/process-tokens.js";
|
|
32
32
|
import { TypographyPreset, generateTypographyTokens } from "../utils/typography.js";
|
|
33
33
|
import { tastyDebug } from "../debug.js";
|
|
34
|
-
export { type AtRuleContext, BASE_STYLES, BLOCK_INNER_STYLES, BLOCK_OUTER_STYLES, BLOCK_STYLES, type BaseStyleProps, type BlockInnerStyleProps, type BlockOuterStyleProps, type BlockStyleProps, Bucket, CHUNK_NAMES, COLOR_STYLES, CONTAINER_STYLES, CSSMap, type CSSProperties, CUSTOM_UNITS, CacheMetrics, type ChunkInfo, type ChunkName, type ColorSpace, type ColorStyleProps, type ComputeStylesOptions, type ComputeStylesResult, type ConditionNode, type ConfigTokenValue, type ConfigTokens, type ContainerStyleProps, CounterStyleDescriptors, DIMENSION_STYLES, DIRECTIONS, type DimensionStyleProps, DisposeFunction, FLOW_STYLES, type FlowStyleProps, FontFaceDescriptors, FontFaceInput, GCConfig, GCOptions, type GlobalStyledProps, INNER_STYLES, InjectResult, type InnerStyleProps, KeyframesCacheEntry, KeyframesInfo, KeyframesResult, KeyframesSteps, type ModValue, type Mods, type NoType, type NotSelector, OUTER_STYLES, type OuterStyleProps, POSITION_STYLES, type ParseStateKeyOptions, type ParsedAdvancedState, ParsedColor, type ParserOptions, type PositionStyleProps, type ProcessedStyle, PropertyDefinition, PropertyOptions, type Props, RawCSSResult, RawStyleHandler, type RecipeStyles, type RenderResult, RootRegistry, RuleInfo, STYLE_TO_CHUNK, type Selector, SheetInfo, SheetManager, type ShortGridStyles, type StateParserContext, type StyleDetails, type StyleDetailsPart, StyleHandler, StyleHandlerDefinition, StyleHandlerResult, StyleInjector, StyleInjectorConfig, StyleMap, StyleParser, StylePropValue, type StyleResult, StyleRule, StyleUsage, StyleValue, StyleValueStateMap, type Styles, type StylesInterface, type StylesWithoutSelectors, type SuffixForSelector, TEXT_STYLES, type TagName, type TastyConfig, type TastyExtensionConfig, type TastyNamedColors, type TastyPlugin, type TastyPluginFactory, type TastyPresetNames, type TastyThemeNames, type TextStyleProps, type TokenValue, type Tokens, TypographyPreset, type UnitHandler, categorizeStyleKeys, cleanup, color, computeStyles, configure, counterStyle, createInjector, createStateParserContext, customFunc, deprecationWarning, destroy, dotize, filterBaseProps, filterMods, fontFace, gc, generateTypographyTokens, getConfig, getCssText, getCssTextForNode, getGlobalCounterStyle, getGlobalFontFace, getGlobalFuncs, getGlobalKeyframes, getGlobalParser, getGlobalPredefinedStates, getGlobalPredefinedTokens, getGlobalRecipes, getIsTestEnvironment, getNamedColorHex, getRawCSSText, getRgbValuesFromRgbaString, hasGlobalKeyframes, hasGlobalRecipes, hasStylesGenerated, hexToRgb, hslToRgbValues, inject, injectGlobal, injectRawCSS, injector, isConfigLocked, isPropertyDefined, isSelector, isTestEnvironment, keyframes,
|
|
34
|
+
export { type AtRuleContext, BASE_STYLES, BLOCK_INNER_STYLES, BLOCK_OUTER_STYLES, BLOCK_STYLES, type BaseStyleProps, type BlockInnerStyleProps, type BlockOuterStyleProps, type BlockStyleProps, Bucket, CHUNK_NAMES, COLOR_STYLES, CONTAINER_STYLES, CSSMap, type CSSProperties, CUSTOM_UNITS, CacheMetrics, type ChunkInfo, type ChunkName, type ColorSpace, type ColorStyleProps, type ComputeStylesOptions, type ComputeStylesResult, type ConditionNode, type ConfigTokenValue, type ConfigTokens, type ContainerStyleProps, CounterStyleDescriptors, DIMENSION_STYLES, DIRECTIONS, type DimensionStyleProps, DisposeFunction, FLOW_STYLES, type FlowStyleProps, FontFaceDescriptors, FontFaceInput, GCConfig, GCOptions, type GlobalStyledProps, INNER_STYLES, InjectResult, type InnerStyleProps, KeyframesCacheEntry, KeyframesInfo, KeyframesResult, KeyframesSteps, type ModValue, type Mods, type NoType, type NotSelector, OUTER_STYLES, type OuterStyleProps, POSITION_STYLES, type ParseStateKeyOptions, type ParsedAdvancedState, ParsedColor, type ParserOptions, type PositionStyleProps, type ProcessedStyle, PropertyDefinition, PropertyOptions, type Props, RawCSSResult, RawStyleHandler, type RecipeStyles, type RenderResult, RootRegistry, RuleInfo, STYLE_TO_CHUNK, type Selector, SheetInfo, SheetManager, type ShortGridStyles, type StateParserContext, type StyleDetails, type StyleDetailsPart, StyleHandler, StyleHandlerDefinition, StyleHandlerResult, StyleInjector, StyleInjectorConfig, StyleMap, StyleParser, StylePropValue, type StyleResult, StyleRule, StyleUsage, StyleValue, StyleValueStateMap, type Styles, type StylesInterface, type StylesWithoutSelectors, type SuffixForSelector, TEXT_STYLES, type TagName, type TastyConfig, type TastyExtensionConfig, type TastyNamedColors, type TastyPlugin, type TastyPluginFactory, type TastyPresetNames, type TastyThemeNames, type TextStyleProps, type TokenValue, type Tokens, TypographyPreset, type UnitHandler, categorizeStyleKeys, cleanup, color, computeStyles, configure, counterStyle, createInjector, createStateParserContext, customFunc, deprecationWarning, destroy, dotize, filterBaseProps, filterMods, fontFace, gc, generateTypographyTokens, getConfig, getCssText, getCssTextForNode, getGlobalCounterStyle, getGlobalFontFace, getGlobalFuncs, getGlobalKeyframes, getGlobalParser, getGlobalPredefinedStates, getGlobalPredefinedTokens, getGlobalRecipes, getIsTestEnvironment, getNamedColorHex, getRawCSSText, getRgbValuesFromRgbaString, hasGlobalKeyframes, hasGlobalRecipes, hasStylesGenerated, hexToRgb, hslToRgbValues, inject, injectGlobal, injectRawCSS, injector, isConfigLocked, isPropertyDefined, isSelector, isTestEnvironment, keyframes, mergeStyles, _modAttrs as modAttrs, normalizeColorTokenValue, okhslFunc, okhslPlugin, parseColor, parseStateKey, parseStyle, processTokens, property, renderStyles, resetConfig, resetGlobalPredefinedTokens, resolveRecipes, setGlobalPredefinedStates, setGlobalPredefinedTokens, strToRgb, stringifyStyles, styleHandlers, tastyDebug, touch, warn };
|
package/dist/core/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import { isSelector, renderStyles } from "../pipeline/index.js";
|
|
|
13
13
|
import { configure, getConfig, getGlobalCounterStyle, getGlobalFontFace, getGlobalKeyframes, getGlobalRecipes, hasGlobalKeyframes, hasGlobalRecipes, hasStylesGenerated, isConfigLocked, isTestEnvironment, resetConfig } from "../config.js";
|
|
14
14
|
import { CHUNK_NAMES, STYLE_TO_CHUNK, categorizeStyleKeys } from "../chunks/definitions.js";
|
|
15
15
|
import { BASE_STYLES, BLOCK_INNER_STYLES, BLOCK_OUTER_STYLES, BLOCK_STYLES, COLOR_STYLES, CONTAINER_STYLES, DIMENSION_STYLES, FLOW_STYLES, INNER_STYLES, OUTER_STYLES, POSITION_STYLES, TEXT_STYLES } from "../styles/list.js";
|
|
16
|
-
import { cleanup, counterStyle, createInjector, destroy, fontFace, gc, getCssText, getCssTextForNode, getIsTestEnvironment, getRawCSSText, inject, injectGlobal, injectRawCSS, injector, isPropertyDefined, keyframes,
|
|
16
|
+
import { cleanup, counterStyle, createInjector, destroy, fontFace, gc, getCssText, getCssTextForNode, getIsTestEnvironment, getRawCSSText, inject, injectGlobal, injectRawCSS, injector, isPropertyDefined, keyframes, property, touch } from "../injector/index.js";
|
|
17
17
|
import { mergeStyles } from "../utils/merge-styles.js";
|
|
18
18
|
import { resolveRecipes } from "../utils/resolve-recipes.js";
|
|
19
19
|
import { computeStyles } from "../compute-styles.js";
|
|
@@ -24,4 +24,4 @@ import { dotize } from "../utils/dotize.js";
|
|
|
24
24
|
import { processTokens } from "../utils/process-tokens.js";
|
|
25
25
|
import { generateTypographyTokens } from "../utils/typography.js";
|
|
26
26
|
import { tastyDebug } from "../debug.js";
|
|
27
|
-
export { BASE_STYLES, BLOCK_INNER_STYLES, BLOCK_OUTER_STYLES, BLOCK_STYLES, Bucket, CHUNK_NAMES, COLOR_STYLES, CONTAINER_STYLES, CUSTOM_UNITS, DIMENSION_STYLES, DIRECTIONS, FLOW_STYLES, INNER_STYLES, OUTER_STYLES, POSITION_STYLES, STYLE_TO_CHUNK, SheetManager, StyleInjector, StyleParser, TEXT_STYLES, categorizeStyleKeys, cleanup, color, computeStyles, configure, counterStyle, createInjector, createStateParserContext, customFunc, deprecationWarning, destroy, dotize, filterBaseProps, filterMods, fontFace, gc, generateTypographyTokens, getConfig, getCssText, getCssTextForNode, getGlobalCounterStyle, getGlobalFontFace, getGlobalFuncs, getGlobalKeyframes, getGlobalParser, getGlobalPredefinedStates, getGlobalPredefinedTokens, getGlobalRecipes, getIsTestEnvironment, getNamedColorHex, getRawCSSText, getRgbValuesFromRgbaString, hasGlobalKeyframes, hasGlobalRecipes, hasStylesGenerated, hexToRgb, hslToRgbValues, inject, injectGlobal, injectRawCSS, injector, isConfigLocked, isPropertyDefined, isSelector, isTestEnvironment, keyframes,
|
|
27
|
+
export { BASE_STYLES, BLOCK_INNER_STYLES, BLOCK_OUTER_STYLES, BLOCK_STYLES, Bucket, CHUNK_NAMES, COLOR_STYLES, CONTAINER_STYLES, CUSTOM_UNITS, DIMENSION_STYLES, DIRECTIONS, FLOW_STYLES, INNER_STYLES, OUTER_STYLES, POSITION_STYLES, STYLE_TO_CHUNK, SheetManager, StyleInjector, StyleParser, TEXT_STYLES, categorizeStyleKeys, cleanup, color, computeStyles, configure, counterStyle, createInjector, createStateParserContext, customFunc, deprecationWarning, destroy, dotize, filterBaseProps, filterMods, fontFace, gc, generateTypographyTokens, getConfig, getCssText, getCssTextForNode, getGlobalCounterStyle, getGlobalFontFace, getGlobalFuncs, getGlobalKeyframes, getGlobalParser, getGlobalPredefinedStates, getGlobalPredefinedTokens, getGlobalRecipes, getIsTestEnvironment, getNamedColorHex, getRawCSSText, getRgbValuesFromRgbaString, hasGlobalKeyframes, hasGlobalRecipes, hasStylesGenerated, hexToRgb, hslToRgbValues, inject, injectGlobal, injectRawCSS, injector, isConfigLocked, isPropertyDefined, isSelector, isTestEnvironment, keyframes, mergeStyles, _modAttrs as modAttrs, normalizeColorTokenValue, okhslFunc, okhslPlugin, parseColor, parseStateKey, parseStyle, processTokens, property, renderStyles, resetConfig, resetGlobalPredefinedTokens, resolveRecipes, setGlobalPredefinedStates, setGlobalPredefinedTokens, strToRgb, stringifyStyles, styleHandlers, tastyDebug, touch, warn };
|
package/dist/index.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ import { useCounterStyle } from "./hooks/useCounterStyle.js";
|
|
|
29
29
|
import { getDisplayName } from "./utils/get-display-name.js";
|
|
30
30
|
import { styleHandlers } from "./styles/predefined.js";
|
|
31
31
|
import { ComputeStylesOptions, ComputeStylesResult, computeStyles } from "./compute-styles.js";
|
|
32
|
-
import { PropertyOptions, cleanup, counterStyle, createInjector, destroy, fontFace, gc, getCssText, getCssTextForNode, getIsTestEnvironment, getRawCSSText, inject, injectGlobal, injectRawCSS, injector, isPropertyDefined, keyframes,
|
|
32
|
+
import { PropertyOptions, cleanup, counterStyle, createInjector, destroy, fontFace, gc, getCssText, getCssTextForNode, getIsTestEnvironment, getRawCSSText, inject, injectGlobal, injectRawCSS, injector, isPropertyDefined, keyframes, property, touch } from "./injector/index.js";
|
|
33
33
|
import { filterBaseProps } from "./utils/filter-base-props.js";
|
|
34
34
|
import { color } from "./utils/colors.js";
|
|
35
35
|
import { _modAttrs } from "./utils/mod-attrs.js";
|
|
@@ -47,5 +47,5 @@ declare module './utils/css-types' {
|
|
|
47
47
|
interface CSSProperties extends CSSProperties$1 {}
|
|
48
48
|
}
|
|
49
49
|
//#endregion
|
|
50
|
-
export { type AllBaseProps, type AllBasePropsWithMods, AtRuleContext, BASE_STYLES, BLOCK_INNER_STYLES, BLOCK_OUTER_STYLES, BLOCK_STYLES, type BaseProps, type BasePropsWithoutChildren, BaseStyleProps, BlockInnerStyleProps, BlockOuterStyleProps, BlockStyleProps, Bucket, CHUNK_NAMES, COLOR_STYLES, CONTAINER_STYLES, CSSMap, CSSProperties, CUSTOM_UNITS, CacheMetrics, ChunkInfo, ChunkName, ColorSpace, ColorStyleProps, ComputeStylesOptions, ComputeStylesResult, ConditionNode, ConfigTokenValue, ConfigTokens, ContainerStyleProps, CounterStyleDescriptors, DIMENSION_STYLES, DIRECTIONS, DimensionStyleProps, DisposeFunction, Element, type ElementsDefinition, FLOW_STYLES, FlowStyleProps, FontFaceDescriptors, FontFaceInput, GCConfig, GCOptions, GlobalStyledProps, INNER_STYLES, InjectResult, InnerStyleProps, KeyframesCacheEntry, KeyframesInfo, KeyframesResult, KeyframesSteps, type ModPropDef, type ModPropsInput, ModValue, Mods, NoType, NotSelector, OUTER_STYLES, OuterStyleProps, POSITION_STYLES, ParseStateKeyOptions, ParsedAdvancedState, ParsedColor, ParserOptions, PositionStyleProps, ProcessedStyle, PropertyDefinition, PropertyOptions, Props, RawCSSResult, RawStyleHandler, RecipeStyles, RenderResult, type ResolveModPropDef, type ResolveModProps, type ResolveTokenProps, RootRegistry, RuleInfo, STYLE_TO_CHUNK, Selector, SheetInfo, SheetManager, ShortGridStyles, StateParserContext, StyleDetails, StyleDetailsPart, StyleHandler, StyleHandlerDefinition, StyleHandlerResult, StyleInjector, StyleInjectorConfig, StyleMap, StyleParser, StylePropValue, StyleResult, StyleRule, StyleUsage, StyleValue, StyleValueStateMap, Styles, StylesInterface, StylesWithoutSelectors, type SubElementDefinition, type SubElementProps, SuffixForSelector, TEXT_STYLES, TagName, TastyConfig, type TastyElementOptions, type TastyElementProps, TastyExtensionConfig, TastyNamedColors, TastyPlugin, TastyPluginFactory, TastyPresetNames, type TastyProps, TastyThemeNames, TextStyleProps, type TokenPropsInput, TokenValue, Tokens, TypographyPreset, UnitHandler, type UsePropertyOptions, type UseStylesOptions, type UseStylesResult, type VariantMap, type WithVariant, categorizeStyleKeys, cleanup, color, computeStyles, configure, counterStyle, createInjector, createStateParserContext, customFunc, deprecationWarning, destroy, dotize, filterBaseProps, filterMods, fontFace, gc, generateTypographyTokens, getConfig, getCssText, getCssTextForNode, getDisplayName, getGlobalCounterStyle, getGlobalFontFace, getGlobalFuncs, getGlobalKeyframes, getGlobalParser, getGlobalPredefinedStates, getGlobalPredefinedTokens, getGlobalRecipes, getIsTestEnvironment, getNamedColorHex, getRawCSSText, getRgbValuesFromRgbaString, hasGlobalKeyframes, hasGlobalRecipes, hasStylesGenerated, hexToRgb, hslToRgbValues, inject, injectGlobal, injectRawCSS, injector, isConfigLocked, isPropertyDefined, isSelector, isTestEnvironment, keyframes,
|
|
50
|
+
export { type AllBaseProps, type AllBasePropsWithMods, AtRuleContext, BASE_STYLES, BLOCK_INNER_STYLES, BLOCK_OUTER_STYLES, BLOCK_STYLES, type BaseProps, type BasePropsWithoutChildren, BaseStyleProps, BlockInnerStyleProps, BlockOuterStyleProps, BlockStyleProps, Bucket, CHUNK_NAMES, COLOR_STYLES, CONTAINER_STYLES, CSSMap, CSSProperties, CUSTOM_UNITS, CacheMetrics, ChunkInfo, ChunkName, ColorSpace, ColorStyleProps, ComputeStylesOptions, ComputeStylesResult, ConditionNode, ConfigTokenValue, ConfigTokens, ContainerStyleProps, CounterStyleDescriptors, DIMENSION_STYLES, DIRECTIONS, DimensionStyleProps, DisposeFunction, Element, type ElementsDefinition, FLOW_STYLES, FlowStyleProps, FontFaceDescriptors, FontFaceInput, GCConfig, GCOptions, GlobalStyledProps, INNER_STYLES, InjectResult, InnerStyleProps, KeyframesCacheEntry, KeyframesInfo, KeyframesResult, KeyframesSteps, type ModPropDef, type ModPropsInput, ModValue, Mods, NoType, NotSelector, OUTER_STYLES, OuterStyleProps, POSITION_STYLES, ParseStateKeyOptions, ParsedAdvancedState, ParsedColor, ParserOptions, PositionStyleProps, ProcessedStyle, PropertyDefinition, PropertyOptions, Props, RawCSSResult, RawStyleHandler, RecipeStyles, RenderResult, type ResolveModPropDef, type ResolveModProps, type ResolveTokenProps, RootRegistry, RuleInfo, STYLE_TO_CHUNK, Selector, SheetInfo, SheetManager, ShortGridStyles, StateParserContext, StyleDetails, StyleDetailsPart, StyleHandler, StyleHandlerDefinition, StyleHandlerResult, StyleInjector, StyleInjectorConfig, StyleMap, StyleParser, StylePropValue, StyleResult, StyleRule, StyleUsage, StyleValue, StyleValueStateMap, Styles, StylesInterface, StylesWithoutSelectors, type SubElementDefinition, type SubElementProps, SuffixForSelector, TEXT_STYLES, TagName, TastyConfig, type TastyElementOptions, type TastyElementProps, TastyExtensionConfig, TastyNamedColors, TastyPlugin, TastyPluginFactory, TastyPresetNames, type TastyProps, TastyThemeNames, TextStyleProps, type TokenPropsInput, TokenValue, Tokens, TypographyPreset, UnitHandler, type UsePropertyOptions, type UseStylesOptions, type UseStylesResult, type VariantMap, type WithVariant, categorizeStyleKeys, cleanup, color, computeStyles, configure, counterStyle, createInjector, createStateParserContext, customFunc, deprecationWarning, destroy, dotize, filterBaseProps, filterMods, fontFace, gc, generateTypographyTokens, getConfig, getCssText, getCssTextForNode, getDisplayName, getGlobalCounterStyle, getGlobalFontFace, getGlobalFuncs, getGlobalKeyframes, getGlobalParser, getGlobalPredefinedStates, getGlobalPredefinedTokens, getGlobalRecipes, getIsTestEnvironment, getNamedColorHex, getRawCSSText, getRgbValuesFromRgbaString, hasGlobalKeyframes, hasGlobalRecipes, hasStylesGenerated, hexToRgb, hslToRgbValues, inject, injectGlobal, injectRawCSS, injector, isConfigLocked, isPropertyDefined, isSelector, isTestEnvironment, keyframes, mergeStyles, _modAttrs as modAttrs, normalizeColorTokenValue, okhslFunc, okhslPlugin, parseColor, parseStateKey, parseStyle, processTokens, property, renderStyles, resetConfig, resetGlobalPredefinedTokens, resolveRecipes, setGlobalPredefinedStates, setGlobalPredefinedTokens, strToRgb, stringifyStyles, styleHandlers, tasty, tastyDebug, touch, useCounterStyle, useFontFace, useGlobalStyles, useKeyframes, useProperty, useRawCSS, useStyles, warn };
|
|
51
51
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import { isSelector, renderStyles } from "./pipeline/index.js";
|
|
|
13
13
|
import { configure, getConfig, getGlobalCounterStyle, getGlobalFontFace, getGlobalKeyframes, getGlobalRecipes, hasGlobalKeyframes, hasGlobalRecipes, hasStylesGenerated, isConfigLocked, isTestEnvironment, resetConfig } from "./config.js";
|
|
14
14
|
import { CHUNK_NAMES, STYLE_TO_CHUNK, categorizeStyleKeys } from "./chunks/definitions.js";
|
|
15
15
|
import { BASE_STYLES, BLOCK_INNER_STYLES, BLOCK_OUTER_STYLES, BLOCK_STYLES, COLOR_STYLES, CONTAINER_STYLES, DIMENSION_STYLES, FLOW_STYLES, INNER_STYLES, OUTER_STYLES, POSITION_STYLES, TEXT_STYLES } from "./styles/list.js";
|
|
16
|
-
import { cleanup, counterStyle, createInjector, destroy, fontFace, gc, getCssText, getCssTextForNode, getIsTestEnvironment, getRawCSSText, inject, injectGlobal, injectRawCSS, injector, isPropertyDefined, keyframes,
|
|
16
|
+
import { cleanup, counterStyle, createInjector, destroy, fontFace, gc, getCssText, getCssTextForNode, getIsTestEnvironment, getRawCSSText, inject, injectGlobal, injectRawCSS, injector, isPropertyDefined, keyframes, property, touch } from "./injector/index.js";
|
|
17
17
|
import { mergeStyles } from "./utils/merge-styles.js";
|
|
18
18
|
import { resolveRecipes } from "./utils/resolve-recipes.js";
|
|
19
19
|
import { computeStyles } from "./compute-styles.js";
|
|
@@ -33,4 +33,4 @@ import { useKeyframes } from "./hooks/useKeyframes.js";
|
|
|
33
33
|
import { useProperty } from "./hooks/useProperty.js";
|
|
34
34
|
import { useFontFace } from "./hooks/useFontFace.js";
|
|
35
35
|
import { useCounterStyle } from "./hooks/useCounterStyle.js";
|
|
36
|
-
export { BASE_STYLES, BLOCK_INNER_STYLES, BLOCK_OUTER_STYLES, BLOCK_STYLES, Bucket, CHUNK_NAMES, COLOR_STYLES, CONTAINER_STYLES, CUSTOM_UNITS, DIMENSION_STYLES, DIRECTIONS, Element, FLOW_STYLES, INNER_STYLES, OUTER_STYLES, POSITION_STYLES, STYLE_TO_CHUNK, SheetManager, StyleInjector, StyleParser, TEXT_STYLES, categorizeStyleKeys, cleanup, color, computeStyles, configure, counterStyle, createInjector, createStateParserContext, customFunc, deprecationWarning, destroy, dotize, filterBaseProps, filterMods, fontFace, gc, generateTypographyTokens, getConfig, getCssText, getCssTextForNode, getDisplayName, getGlobalCounterStyle, getGlobalFontFace, getGlobalFuncs, getGlobalKeyframes, getGlobalParser, getGlobalPredefinedStates, getGlobalPredefinedTokens, getGlobalRecipes, getIsTestEnvironment, getNamedColorHex, getRawCSSText, getRgbValuesFromRgbaString, hasGlobalKeyframes, hasGlobalRecipes, hasStylesGenerated, hexToRgb, hslToRgbValues, inject, injectGlobal, injectRawCSS, injector, isConfigLocked, isPropertyDefined, isSelector, isTestEnvironment, keyframes,
|
|
36
|
+
export { BASE_STYLES, BLOCK_INNER_STYLES, BLOCK_OUTER_STYLES, BLOCK_STYLES, Bucket, CHUNK_NAMES, COLOR_STYLES, CONTAINER_STYLES, CUSTOM_UNITS, DIMENSION_STYLES, DIRECTIONS, Element, FLOW_STYLES, INNER_STYLES, OUTER_STYLES, POSITION_STYLES, STYLE_TO_CHUNK, SheetManager, StyleInjector, StyleParser, TEXT_STYLES, categorizeStyleKeys, cleanup, color, computeStyles, configure, counterStyle, createInjector, createStateParserContext, customFunc, deprecationWarning, destroy, dotize, filterBaseProps, filterMods, fontFace, gc, generateTypographyTokens, getConfig, getCssText, getCssTextForNode, getDisplayName, getGlobalCounterStyle, getGlobalFontFace, getGlobalFuncs, getGlobalKeyframes, getGlobalParser, getGlobalPredefinedStates, getGlobalPredefinedTokens, getGlobalRecipes, getIsTestEnvironment, getNamedColorHex, getRawCSSText, getRgbValuesFromRgbaString, hasGlobalKeyframes, hasGlobalRecipes, hasStylesGenerated, hexToRgb, hslToRgbValues, inject, injectGlobal, injectRawCSS, injector, isConfigLocked, isPropertyDefined, isSelector, isTestEnvironment, keyframes, mergeStyles, _modAttrs as modAttrs, normalizeColorTokenValue, okhslFunc, okhslPlugin, parseColor, parseStateKey, parseStyle, processTokens, property, renderStyles, resetConfig, resetGlobalPredefinedTokens, resolveRecipes, setGlobalPredefinedStates, setGlobalPredefinedTokens, strToRgb, stringifyStyles, styleHandlers, tasty, tastyDebug, touch, useCounterStyle, useFontFace, useGlobalStyles, useKeyframes, useProperty, useRawCSS, useStyles, warn };
|
package/dist/injector/index.d.ts
CHANGED
|
@@ -145,25 +145,20 @@ declare function getCssTextForNode(node: ParentNode | Element | DocumentFragment
|
|
|
145
145
|
declare function cleanup(root?: Document | ShadowRoot): void;
|
|
146
146
|
/**
|
|
147
147
|
* Record a render-time usage hit for one or more classNames.
|
|
148
|
-
* Used internally by computeStyles and tasty() to track
|
|
148
|
+
* Used internally by computeStyles and tasty() to track usage for GC.
|
|
149
|
+
* When the global touch counter reaches `touchInterval`, schedules GC.
|
|
149
150
|
*/
|
|
150
151
|
declare function touch(className: string, options?: {
|
|
151
152
|
root?: Document | ShadowRoot;
|
|
152
153
|
}): void;
|
|
153
154
|
/**
|
|
154
155
|
* Synchronous garbage collection of unused styles.
|
|
155
|
-
*
|
|
156
|
-
*
|
|
156
|
+
* Evicts the oldest unused styles when usageMap exceeds capacity.
|
|
157
|
+
* With `{ force: true }`, removes ALL unused styles regardless of capacity.
|
|
157
158
|
*
|
|
158
159
|
* @returns Number of styles evicted.
|
|
159
160
|
*/
|
|
160
161
|
declare function gc(options?: GCOptions): number;
|
|
161
|
-
/**
|
|
162
|
-
* Event-driven GC with cooldown.
|
|
163
|
-
* Skips if called within the configured cooldown of the last run.
|
|
164
|
-
* Schedules via requestIdleCallback when available.
|
|
165
|
-
*/
|
|
166
|
-
declare function maybeGC(options?: GCOptions): void;
|
|
167
162
|
/**
|
|
168
163
|
* Check if we're currently running in a test environment
|
|
169
164
|
*/
|
|
@@ -183,5 +178,5 @@ declare function destroy(root?: Document | ShadowRoot): void;
|
|
|
183
178
|
*/
|
|
184
179
|
declare function createInjector(config?: Partial<StyleInjectorConfig>): StyleInjector;
|
|
185
180
|
//#endregion
|
|
186
|
-
export { PropertyOptions, cleanup, counterStyle, createInjector, destroy, fontFace, gc, getCssText, getCssTextForNode, getIsTestEnvironment, getRawCSSText, inject, injectGlobal, injectRawCSS, injector, isPropertyDefined, keyframes,
|
|
181
|
+
export { PropertyOptions, cleanup, counterStyle, createInjector, destroy, fontFace, gc, getCssText, getCssTextForNode, getIsTestEnvironment, getRawCSSText, inject, injectGlobal, injectRawCSS, injector, isPropertyDefined, keyframes, property, touch };
|
|
187
182
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/injector/index.js
CHANGED
|
@@ -134,7 +134,8 @@ function cleanup(root) {
|
|
|
134
134
|
}
|
|
135
135
|
/**
|
|
136
136
|
* Record a render-time usage hit for one or more classNames.
|
|
137
|
-
* Used internally by computeStyles and tasty() to track
|
|
137
|
+
* Used internally by computeStyles and tasty() to track usage for GC.
|
|
138
|
+
* When the global touch counter reaches `touchInterval`, schedules GC.
|
|
138
139
|
*/
|
|
139
140
|
function touch(className, options) {
|
|
140
141
|
if (!getConfig().gc) return;
|
|
@@ -142,8 +143,8 @@ function touch(className, options) {
|
|
|
142
143
|
}
|
|
143
144
|
/**
|
|
144
145
|
* Synchronous garbage collection of unused styles.
|
|
145
|
-
*
|
|
146
|
-
*
|
|
146
|
+
* Evicts the oldest unused styles when usageMap exceeds capacity.
|
|
147
|
+
* With `{ force: true }`, removes ALL unused styles regardless of capacity.
|
|
147
148
|
*
|
|
148
149
|
* @returns Number of styles evicted.
|
|
149
150
|
*/
|
|
@@ -151,14 +152,6 @@ function gc(options) {
|
|
|
151
152
|
return getGlobalInjector().gc(options);
|
|
152
153
|
}
|
|
153
154
|
/**
|
|
154
|
-
* Event-driven GC with cooldown.
|
|
155
|
-
* Skips if called within the configured cooldown of the last run.
|
|
156
|
-
* Schedules via requestIdleCallback when available.
|
|
157
|
-
*/
|
|
158
|
-
function maybeGC(options) {
|
|
159
|
-
return getGlobalInjector().maybeGC(options);
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
155
|
* Check if we're currently running in a test environment
|
|
163
156
|
*/
|
|
164
157
|
function getIsTestEnvironment() {
|
|
@@ -187,6 +180,6 @@ function createInjector(config = {}) {
|
|
|
187
180
|
});
|
|
188
181
|
}
|
|
189
182
|
//#endregion
|
|
190
|
-
export { cleanup, counterStyle, createInjector, destroy, fontFace, gc, getCssText, getCssTextForNode, getIsTestEnvironment, getRawCSSText, inject, injectGlobal, injectRawCSS, injector, isPropertyDefined, keyframes,
|
|
183
|
+
export { cleanup, counterStyle, createInjector, destroy, fontFace, gc, getCssText, getCssTextForNode, getIsTestEnvironment, getRawCSSText, inject, injectGlobal, injectRawCSS, injector, isPropertyDefined, keyframes, property, touch };
|
|
191
184
|
|
|
192
185
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/injector/index.ts"],"sourcesContent":["import {\n getConfig,\n getGlobalInjector,\n isTestEnvironment,\n markStylesGenerated,\n} from '../config';\nimport type { StyleResult } from '../pipeline';\n\nimport { StyleInjector } from './injector';\nimport type {\n CounterStyleDescriptors,\n FontFaceDescriptors,\n GCOptions,\n GlobalInjectResult,\n InjectResult,\n KeyframesResult,\n KeyframesSteps,\n StyleInjectorConfig,\n} from './types';\n\n/**\n * Inject styles and return className with dispose function\n */\nexport function inject(\n rules: StyleResult[],\n options?: { root?: Document | ShadowRoot; cacheKey?: string },\n): InjectResult {\n const injector = getGlobalInjector();\n\n markStylesGenerated();\n\n return injector.inject(rules, options);\n}\n\n/**\n * Inject global rules that should not reserve tasty class names\n */\nexport function injectGlobal(\n rules: StyleResult[],\n options?: { root?: Document | ShadowRoot },\n): GlobalInjectResult {\n return getGlobalInjector().injectGlobal(rules, options);\n}\n\n/**\n * Inject raw CSS text directly without parsing\n * This is a low-overhead method for injecting raw CSS that doesn't need tasty processing.\n * The CSS is inserted into a separate style element to avoid conflicts with tasty's chunking.\n *\n * @example\n * ```tsx\n * // Inject raw CSS\n * const { dispose } = injectRawCSS(`\n * body { margin: 0; padding: 0; }\n * .my-class { color: red; }\n * `);\n *\n * // Later, remove the injected CSS\n * dispose();\n * ```\n */\nexport function injectRawCSS(\n css: string,\n options?: { root?: Document | ShadowRoot },\n): { dispose: () => void } {\n return getGlobalInjector().injectRawCSS(css, options);\n}\n\n/**\n * Get raw CSS text for SSR\n */\nexport function getRawCSSText(options?: {\n root?: Document | ShadowRoot;\n}): string {\n return getGlobalInjector().getRawCSSText(options);\n}\n\n/**\n * Inject keyframes and return object with toString() and dispose()\n */\nexport function keyframes(\n steps: KeyframesSteps,\n nameOrOptions?: string | { root?: Document | ShadowRoot; name?: string },\n): KeyframesResult {\n return getGlobalInjector().keyframes(steps, nameOrOptions);\n}\n\nexport interface PropertyOptions {\n /**\n * CSS syntax string for the property (e.g., '<color>', '<length>', '<angle>')\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/@property/syntax\n */\n syntax?: string;\n /**\n * Whether the property inherits from parent elements\n * @default true\n */\n inherits?: boolean;\n /**\n * Initial value for the property\n */\n initialValue?: string | number;\n /**\n * Shadow root or document to inject into\n */\n root?: Document | ShadowRoot;\n}\n\n/**\n * Define a CSS @property custom property.\n * This enables advanced features like animating custom properties.\n *\n * Note: @property rules are global and persistent once defined.\n * Re-registering the same property name is a no-op.\n *\n * @param name - The custom property name (must start with --)\n * @param options - Property configuration\n *\n * @example\n * ```ts\n * // Define a color property that can be animated\n * property('--my-color', {\n * syntax: '<color>',\n * initialValue: 'red',\n * });\n *\n * // Define an angle property\n * property('--rotation', {\n * syntax: '<angle>',\n * inherits: false,\n * initialValue: '0deg',\n * });\n * ```\n */\nexport function property(name: string, options?: PropertyOptions): void {\n return getGlobalInjector().property(name, options);\n}\n\n/**\n * Check if a CSS @property has already been defined\n *\n * @param name - The custom property name to check\n * @param options - Options including root\n */\nexport function isPropertyDefined(\n name: string,\n options?: { root?: Document | ShadowRoot },\n): boolean {\n return getGlobalInjector().isPropertyDefined(name, options);\n}\n\n/**\n * Inject a CSS @font-face rule.\n *\n * Permanent and global — no dispose or ref-counting.\n * Deduplicates by content hash (family + descriptors).\n */\nexport function fontFace(\n family: string,\n descriptors: FontFaceDescriptors,\n options?: { root?: Document | ShadowRoot },\n): void {\n return getGlobalInjector().fontFace(family, descriptors, options);\n}\n\n/**\n * Inject a CSS @counter-style rule.\n *\n * Permanent and global — no dispose or ref-counting.\n * Deduplicates by name (first definition wins).\n */\nexport function counterStyle(\n name: string,\n descriptors: CounterStyleDescriptors,\n options?: { root?: Document | ShadowRoot },\n): void {\n return getGlobalInjector().counterStyle(name, descriptors, options);\n}\n\n/**\n * Get CSS text from all sheets (for SSR)\n */\nexport function getCssText(options?: { root?: Document | ShadowRoot }): string {\n return getGlobalInjector().getCssText(options);\n}\n\n/**\n * Collect only CSS used by a rendered subtree (like jest-styled-components).\n * Pass the container returned by render(...).\n */\nexport function getCssTextForNode(\n node: ParentNode | Element | DocumentFragment,\n options?: { root?: Document | ShadowRoot },\n): string {\n // Collect tasty-generated class names (t<number>) from the subtree\n const classSet = new Set<string>();\n\n const readClasses = (el: Element) => {\n const cls = el.getAttribute('class');\n if (!cls) return;\n for (const token of cls.split(/\\s+/)) {\n if (/^t\\d+$/.test(token)) classSet.add(token);\n }\n };\n\n // Include node itself if it's an Element\n if ((node as Element).getAttribute) {\n readClasses(node as Element);\n }\n // Walk descendants\n const elements = (node as ParentNode).querySelectorAll\n ? (node as ParentNode).querySelectorAll('[class]')\n : ([] as unknown as NodeListOf<Element>);\n if (elements) elements.forEach(readClasses);\n\n return getGlobalInjector().getCssTextForClasses(classSet, options);\n}\n\n/**\n * Force cleanup of unused rules\n */\nexport function cleanup(root?: Document | ShadowRoot): void {\n return getGlobalInjector().cleanup(root);\n}\n\n/**\n * Record a render-time usage hit for one or more classNames.\n * Used internally by computeStyles and tasty() to track style popularity for GC.\n */\nexport function touch(\n className: string,\n options?: { root?: Document | ShadowRoot },\n): void {\n if (!getConfig().gc) return;\n getGlobalInjector().touch(className, options);\n}\n\n/**\n * Synchronous garbage collection of unused styles.\n * Scans the DOM for live classNames (never evicts them), then evicts\n * absent styles whose age exceeds their popularity-weighted TTL.\n *\n * @returns Number of styles evicted.\n */\nexport function gc(options?: GCOptions): number {\n return getGlobalInjector().gc(options);\n}\n\n/**\n * Event-driven GC with cooldown.\n * Skips if called within the configured cooldown of the last run.\n * Schedules via requestIdleCallback when available.\n */\nexport function maybeGC(options?: GCOptions): void {\n return getGlobalInjector().maybeGC(options);\n}\n\n/**\n * Check if we're currently running in a test environment\n */\nexport function getIsTestEnvironment(): boolean {\n return isTestEnvironment();\n}\n\n/**\n * Get the global injector instance for debugging\n */\nexport const injector = {\n get instance() {\n return getGlobalInjector();\n },\n};\n\n/**\n * Destroy all resources and clean up\n */\nexport function destroy(root?: Document | ShadowRoot): void {\n return getGlobalInjector().destroy(root);\n}\n\n/**\n * Create a new isolated injector instance\n */\nexport function createInjector(\n config: Partial<StyleInjectorConfig> = {},\n): StyleInjector {\n const defaultConfig = getConfig();\n\n const fullConfig: StyleInjectorConfig = {\n ...defaultConfig,\n // Auto-enable forceTextInjection in test environments\n forceTextInjection: config.forceTextInjection ?? isTestEnvironment(),\n ...config,\n };\n\n return new StyleInjector(fullConfig);\n}\n\n// Re-export types\nexport type {\n StyleInjectorConfig,\n InjectResult,\n DisposeFunction,\n RuleInfo,\n SheetInfo,\n RootRegistry,\n StyleRule,\n KeyframesInfo,\n KeyframesResult,\n KeyframesSteps,\n KeyframesCacheEntry,\n CacheMetrics,\n RawCSSResult,\n PropertyDefinition,\n FontFaceDescriptors,\n FontFaceInput,\n CounterStyleDescriptors,\n StyleUsage,\n GCConfig,\n GCOptions,\n} from './types';\n\nexport { StyleInjector } from './injector';\nexport { SheetManager } from './sheet-manager';\n"],"mappings":";;;;;;;AAuBA,SAAgB,OACd,OACA,SACc;CACd,MAAM,WAAW,mBAAmB;AAEpC,sBAAqB;AAErB,QAAO,SAAS,OAAO,OAAO,QAAQ;;;;;AAMxC,SAAgB,aACd,OACA,SACoB;AACpB,QAAO,mBAAmB,CAAC,aAAa,OAAO,QAAQ;;;;;;;;;;;;;;;;;;;AAoBzD,SAAgB,aACd,KACA,SACyB;AACzB,QAAO,mBAAmB,CAAC,aAAa,KAAK,QAAQ;;;;;AAMvD,SAAgB,cAAc,SAEnB;AACT,QAAO,mBAAmB,CAAC,cAAc,QAAQ;;;;;AAMnD,SAAgB,UACd,OACA,eACiB;AACjB,QAAO,mBAAmB,CAAC,UAAU,OAAO,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkD5D,SAAgB,SAAS,MAAc,SAAiC;AACtE,QAAO,mBAAmB,CAAC,SAAS,MAAM,QAAQ;;;;;;;;AASpD,SAAgB,kBACd,MACA,SACS;AACT,QAAO,mBAAmB,CAAC,kBAAkB,MAAM,QAAQ;;;;;;;;AAS7D,SAAgB,SACd,QACA,aACA,SACM;AACN,QAAO,mBAAmB,CAAC,SAAS,QAAQ,aAAa,QAAQ;;;;;;;;AASnE,SAAgB,aACd,MACA,aACA,SACM;AACN,QAAO,mBAAmB,CAAC,aAAa,MAAM,aAAa,QAAQ;;;;;AAMrE,SAAgB,WAAW,SAAoD;AAC7E,QAAO,mBAAmB,CAAC,WAAW,QAAQ;;;;;;AAOhD,SAAgB,kBACd,MACA,SACQ;CAER,MAAM,2BAAW,IAAI,KAAa;CAElC,MAAM,eAAe,OAAgB;EACnC,MAAM,MAAM,GAAG,aAAa,QAAQ;AACpC,MAAI,CAAC,IAAK;AACV,OAAK,MAAM,SAAS,IAAI,MAAM,MAAM,CAClC,KAAI,SAAS,KAAK,MAAM,CAAE,UAAS,IAAI,MAAM;;AAKjD,KAAK,KAAiB,aACpB,aAAY,KAAgB;CAG9B,MAAM,WAAY,KAAoB,mBACjC,KAAoB,iBAAiB,UAAU,GAC/C,EAAE;AACP,KAAI,SAAU,UAAS,QAAQ,YAAY;AAE3C,QAAO,mBAAmB,CAAC,qBAAqB,UAAU,QAAQ;;;;;AAMpE,SAAgB,QAAQ,MAAoC;AAC1D,QAAO,mBAAmB,CAAC,QAAQ,KAAK;;;;;;AAO1C,SAAgB,MACd,WACA,SACM;AACN,KAAI,CAAC,WAAW,CAAC,GAAI;AACrB,oBAAmB,CAAC,MAAM,WAAW,QAAQ;;;;;;;;;AAU/C,SAAgB,GAAG,SAA6B;AAC9C,QAAO,mBAAmB,CAAC,GAAG,QAAQ;;;;;;;AAQxC,SAAgB,QAAQ,SAA2B;AACjD,QAAO,mBAAmB,CAAC,QAAQ,QAAQ;;;;;AAM7C,SAAgB,uBAAgC;AAC9C,QAAO,mBAAmB;;;;;AAM5B,MAAa,WAAW,EACtB,IAAI,WAAW;AACb,QAAO,mBAAmB;GAE7B;;;;AAKD,SAAgB,QAAQ,MAAoC;AAC1D,QAAO,mBAAmB,CAAC,QAAQ,KAAK;;;;;AAM1C,SAAgB,eACd,SAAuC,EAAE,EAC1B;AAUf,QAAO,IAAI,cAP6B;EACtC,GAHoB,WAAW;EAK/B,oBAAoB,OAAO,sBAAsB,mBAAmB;EACpE,GAAG;EACJ,CAEmC"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/injector/index.ts"],"sourcesContent":["import {\n getConfig,\n getGlobalInjector,\n isTestEnvironment,\n markStylesGenerated,\n} from '../config';\nimport type { StyleResult } from '../pipeline';\n\nimport { StyleInjector } from './injector';\nimport type {\n CounterStyleDescriptors,\n FontFaceDescriptors,\n GCOptions,\n GlobalInjectResult,\n InjectResult,\n KeyframesResult,\n KeyframesSteps,\n StyleInjectorConfig,\n} from './types';\n\n/**\n * Inject styles and return className with dispose function\n */\nexport function inject(\n rules: StyleResult[],\n options?: { root?: Document | ShadowRoot; cacheKey?: string },\n): InjectResult {\n const injector = getGlobalInjector();\n\n markStylesGenerated();\n\n return injector.inject(rules, options);\n}\n\n/**\n * Inject global rules that should not reserve tasty class names\n */\nexport function injectGlobal(\n rules: StyleResult[],\n options?: { root?: Document | ShadowRoot },\n): GlobalInjectResult {\n return getGlobalInjector().injectGlobal(rules, options);\n}\n\n/**\n * Inject raw CSS text directly without parsing\n * This is a low-overhead method for injecting raw CSS that doesn't need tasty processing.\n * The CSS is inserted into a separate style element to avoid conflicts with tasty's chunking.\n *\n * @example\n * ```tsx\n * // Inject raw CSS\n * const { dispose } = injectRawCSS(`\n * body { margin: 0; padding: 0; }\n * .my-class { color: red; }\n * `);\n *\n * // Later, remove the injected CSS\n * dispose();\n * ```\n */\nexport function injectRawCSS(\n css: string,\n options?: { root?: Document | ShadowRoot },\n): { dispose: () => void } {\n return getGlobalInjector().injectRawCSS(css, options);\n}\n\n/**\n * Get raw CSS text for SSR\n */\nexport function getRawCSSText(options?: {\n root?: Document | ShadowRoot;\n}): string {\n return getGlobalInjector().getRawCSSText(options);\n}\n\n/**\n * Inject keyframes and return object with toString() and dispose()\n */\nexport function keyframes(\n steps: KeyframesSteps,\n nameOrOptions?: string | { root?: Document | ShadowRoot; name?: string },\n): KeyframesResult {\n return getGlobalInjector().keyframes(steps, nameOrOptions);\n}\n\nexport interface PropertyOptions {\n /**\n * CSS syntax string for the property (e.g., '<color>', '<length>', '<angle>')\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/@property/syntax\n */\n syntax?: string;\n /**\n * Whether the property inherits from parent elements\n * @default true\n */\n inherits?: boolean;\n /**\n * Initial value for the property\n */\n initialValue?: string | number;\n /**\n * Shadow root or document to inject into\n */\n root?: Document | ShadowRoot;\n}\n\n/**\n * Define a CSS @property custom property.\n * This enables advanced features like animating custom properties.\n *\n * Note: @property rules are global and persistent once defined.\n * Re-registering the same property name is a no-op.\n *\n * @param name - The custom property name (must start with --)\n * @param options - Property configuration\n *\n * @example\n * ```ts\n * // Define a color property that can be animated\n * property('--my-color', {\n * syntax: '<color>',\n * initialValue: 'red',\n * });\n *\n * // Define an angle property\n * property('--rotation', {\n * syntax: '<angle>',\n * inherits: false,\n * initialValue: '0deg',\n * });\n * ```\n */\nexport function property(name: string, options?: PropertyOptions): void {\n return getGlobalInjector().property(name, options);\n}\n\n/**\n * Check if a CSS @property has already been defined\n *\n * @param name - The custom property name to check\n * @param options - Options including root\n */\nexport function isPropertyDefined(\n name: string,\n options?: { root?: Document | ShadowRoot },\n): boolean {\n return getGlobalInjector().isPropertyDefined(name, options);\n}\n\n/**\n * Inject a CSS @font-face rule.\n *\n * Permanent and global — no dispose or ref-counting.\n * Deduplicates by content hash (family + descriptors).\n */\nexport function fontFace(\n family: string,\n descriptors: FontFaceDescriptors,\n options?: { root?: Document | ShadowRoot },\n): void {\n return getGlobalInjector().fontFace(family, descriptors, options);\n}\n\n/**\n * Inject a CSS @counter-style rule.\n *\n * Permanent and global — no dispose or ref-counting.\n * Deduplicates by name (first definition wins).\n */\nexport function counterStyle(\n name: string,\n descriptors: CounterStyleDescriptors,\n options?: { root?: Document | ShadowRoot },\n): void {\n return getGlobalInjector().counterStyle(name, descriptors, options);\n}\n\n/**\n * Get CSS text from all sheets (for SSR)\n */\nexport function getCssText(options?: { root?: Document | ShadowRoot }): string {\n return getGlobalInjector().getCssText(options);\n}\n\n/**\n * Collect only CSS used by a rendered subtree (like jest-styled-components).\n * Pass the container returned by render(...).\n */\nexport function getCssTextForNode(\n node: ParentNode | Element | DocumentFragment,\n options?: { root?: Document | ShadowRoot },\n): string {\n // Collect tasty-generated class names (t<number>) from the subtree\n const classSet = new Set<string>();\n\n const readClasses = (el: Element) => {\n const cls = el.getAttribute('class');\n if (!cls) return;\n for (const token of cls.split(/\\s+/)) {\n if (/^t\\d+$/.test(token)) classSet.add(token);\n }\n };\n\n // Include node itself if it's an Element\n if ((node as Element).getAttribute) {\n readClasses(node as Element);\n }\n // Walk descendants\n const elements = (node as ParentNode).querySelectorAll\n ? (node as ParentNode).querySelectorAll('[class]')\n : ([] as unknown as NodeListOf<Element>);\n if (elements) elements.forEach(readClasses);\n\n return getGlobalInjector().getCssTextForClasses(classSet, options);\n}\n\n/**\n * Force cleanup of unused rules\n */\nexport function cleanup(root?: Document | ShadowRoot): void {\n return getGlobalInjector().cleanup(root);\n}\n\n/**\n * Record a render-time usage hit for one or more classNames.\n * Used internally by computeStyles and tasty() to track usage for GC.\n * When the global touch counter reaches `touchInterval`, schedules GC.\n */\nexport function touch(\n className: string,\n options?: { root?: Document | ShadowRoot },\n): void {\n if (!getConfig().gc) return;\n getGlobalInjector().touch(className, options);\n}\n\n/**\n * Synchronous garbage collection of unused styles.\n * Evicts the oldest unused styles when usageMap exceeds capacity.\n * With `{ force: true }`, removes ALL unused styles regardless of capacity.\n *\n * @returns Number of styles evicted.\n */\nexport function gc(options?: GCOptions): number {\n return getGlobalInjector().gc(options);\n}\n\n/**\n * Check if we're currently running in a test environment\n */\nexport function getIsTestEnvironment(): boolean {\n return isTestEnvironment();\n}\n\n/**\n * Get the global injector instance for debugging\n */\nexport const injector = {\n get instance() {\n return getGlobalInjector();\n },\n};\n\n/**\n * Destroy all resources and clean up\n */\nexport function destroy(root?: Document | ShadowRoot): void {\n return getGlobalInjector().destroy(root);\n}\n\n/**\n * Create a new isolated injector instance\n */\nexport function createInjector(\n config: Partial<StyleInjectorConfig> = {},\n): StyleInjector {\n const defaultConfig = getConfig();\n\n const fullConfig: StyleInjectorConfig = {\n ...defaultConfig,\n // Auto-enable forceTextInjection in test environments\n forceTextInjection: config.forceTextInjection ?? isTestEnvironment(),\n ...config,\n };\n\n return new StyleInjector(fullConfig);\n}\n\n// Re-export types\nexport type {\n StyleInjectorConfig,\n InjectResult,\n DisposeFunction,\n RuleInfo,\n SheetInfo,\n RootRegistry,\n StyleRule,\n KeyframesInfo,\n KeyframesResult,\n KeyframesSteps,\n KeyframesCacheEntry,\n CacheMetrics,\n RawCSSResult,\n PropertyDefinition,\n FontFaceDescriptors,\n FontFaceInput,\n CounterStyleDescriptors,\n StyleUsage,\n GCConfig,\n GCOptions,\n} from './types';\n\nexport { StyleInjector } from './injector';\nexport { SheetManager } from './sheet-manager';\n"],"mappings":";;;;;;;AAuBA,SAAgB,OACd,OACA,SACc;CACd,MAAM,WAAW,mBAAmB;AAEpC,sBAAqB;AAErB,QAAO,SAAS,OAAO,OAAO,QAAQ;;;;;AAMxC,SAAgB,aACd,OACA,SACoB;AACpB,QAAO,mBAAmB,CAAC,aAAa,OAAO,QAAQ;;;;;;;;;;;;;;;;;;;AAoBzD,SAAgB,aACd,KACA,SACyB;AACzB,QAAO,mBAAmB,CAAC,aAAa,KAAK,QAAQ;;;;;AAMvD,SAAgB,cAAc,SAEnB;AACT,QAAO,mBAAmB,CAAC,cAAc,QAAQ;;;;;AAMnD,SAAgB,UACd,OACA,eACiB;AACjB,QAAO,mBAAmB,CAAC,UAAU,OAAO,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkD5D,SAAgB,SAAS,MAAc,SAAiC;AACtE,QAAO,mBAAmB,CAAC,SAAS,MAAM,QAAQ;;;;;;;;AASpD,SAAgB,kBACd,MACA,SACS;AACT,QAAO,mBAAmB,CAAC,kBAAkB,MAAM,QAAQ;;;;;;;;AAS7D,SAAgB,SACd,QACA,aACA,SACM;AACN,QAAO,mBAAmB,CAAC,SAAS,QAAQ,aAAa,QAAQ;;;;;;;;AASnE,SAAgB,aACd,MACA,aACA,SACM;AACN,QAAO,mBAAmB,CAAC,aAAa,MAAM,aAAa,QAAQ;;;;;AAMrE,SAAgB,WAAW,SAAoD;AAC7E,QAAO,mBAAmB,CAAC,WAAW,QAAQ;;;;;;AAOhD,SAAgB,kBACd,MACA,SACQ;CAER,MAAM,2BAAW,IAAI,KAAa;CAElC,MAAM,eAAe,OAAgB;EACnC,MAAM,MAAM,GAAG,aAAa,QAAQ;AACpC,MAAI,CAAC,IAAK;AACV,OAAK,MAAM,SAAS,IAAI,MAAM,MAAM,CAClC,KAAI,SAAS,KAAK,MAAM,CAAE,UAAS,IAAI,MAAM;;AAKjD,KAAK,KAAiB,aACpB,aAAY,KAAgB;CAG9B,MAAM,WAAY,KAAoB,mBACjC,KAAoB,iBAAiB,UAAU,GAC/C,EAAE;AACP,KAAI,SAAU,UAAS,QAAQ,YAAY;AAE3C,QAAO,mBAAmB,CAAC,qBAAqB,UAAU,QAAQ;;;;;AAMpE,SAAgB,QAAQ,MAAoC;AAC1D,QAAO,mBAAmB,CAAC,QAAQ,KAAK;;;;;;;AAQ1C,SAAgB,MACd,WACA,SACM;AACN,KAAI,CAAC,WAAW,CAAC,GAAI;AACrB,oBAAmB,CAAC,MAAM,WAAW,QAAQ;;;;;;;;;AAU/C,SAAgB,GAAG,SAA6B;AAC9C,QAAO,mBAAmB,CAAC,GAAG,QAAQ;;;;;AAMxC,SAAgB,uBAAgC;AAC9C,QAAO,mBAAmB;;;;;AAM5B,MAAa,WAAW,EACtB,IAAI,WAAW;AACb,QAAO,mBAAmB;GAE7B;;;;AAKD,SAAgB,QAAQ,MAAoC;AAC1D,QAAO,mBAAmB,CAAC,QAAQ,KAAK;;;;;AAM1C,SAAgB,eACd,SAAuC,EAAE,EAC1B;AAUf,QAAO,IAAI,cAP6B;EACtC,GAHoB,WAAW;EAK/B,oBAAoB,OAAO,sBAAsB,mBAAmB;EACpE,GAAG;EACJ,CAEmC"}
|
|
@@ -7,8 +7,6 @@ declare class StyleInjector {
|
|
|
7
7
|
private sheetManager;
|
|
8
8
|
private config;
|
|
9
9
|
private globalRuleCounter;
|
|
10
|
-
private lastGCTime;
|
|
11
|
-
private backgroundSweepTimeout;
|
|
12
10
|
private pendingGCHandle;
|
|
13
11
|
/** @internal — exposed for debug utilities only */
|
|
14
12
|
get _sheetManager(): SheetManager;
|
|
@@ -158,33 +156,33 @@ declare class StyleInjector {
|
|
|
158
156
|
* Dispose keyframes
|
|
159
157
|
*/
|
|
160
158
|
private disposeKeyframes;
|
|
161
|
-
private static readonly TOUCH_THROTTLE_MS;
|
|
162
159
|
private static readonly TASTY_CLASS_RE;
|
|
163
160
|
/**
|
|
164
161
|
* Record a render-time usage hit for one or more classNames.
|
|
165
162
|
* Handles space-separated multi-chunk classNames.
|
|
163
|
+
* When the global touch counter reaches `touchInterval`, schedules a GC
|
|
164
|
+
* via `requestIdleCallback`.
|
|
166
165
|
* No-op on the server.
|
|
167
166
|
*/
|
|
168
167
|
touch(className: string, options?: {
|
|
169
168
|
root?: Document | ShadowRoot;
|
|
170
169
|
}): void;
|
|
170
|
+
/**
|
|
171
|
+
* Schedule a GC via `requestIdleCallback` (or synchronously as fallback).
|
|
172
|
+
* Runs GC on all active roots. Avoids double-scheduling via `pendingGCHandle`.
|
|
173
|
+
*/
|
|
174
|
+
private scheduleGC;
|
|
171
175
|
/**
|
|
172
176
|
* Synchronous garbage collection.
|
|
173
177
|
*
|
|
174
|
-
* 1.
|
|
175
|
-
* 2.
|
|
176
|
-
* 3.
|
|
177
|
-
*
|
|
178
|
+
* 1. Quick upper-bound check: skip if unused count can't exceed capacity.
|
|
179
|
+
* 2. Scans the DOM for live tasty classNames (safety guard).
|
|
180
|
+
* 3. With `force: true`: deletes all unused entries inline.
|
|
181
|
+
* Without `force`: collects unused, sorts oldest-first, evicts over capacity.
|
|
178
182
|
*
|
|
179
183
|
* @returns Number of styles evicted.
|
|
180
184
|
*/
|
|
181
185
|
gc(options?: GCOptions): number;
|
|
182
|
-
/**
|
|
183
|
-
* Event-driven GC with cooldown.
|
|
184
|
-
* Skips if called within `cooldown` ms of the last run.
|
|
185
|
-
* Schedules the actual GC via `requestIdleCallback` when available.
|
|
186
|
-
*/
|
|
187
|
-
maybeGC(options?: GCOptions): void;
|
|
188
186
|
/**
|
|
189
187
|
* Destroy all resources for a root
|
|
190
188
|
*/
|