@tenphi/tasty 3.11.0 → 3.11.2
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 +13 -9
- package/dist/chunks/{build-config-5d8WlQbq.js → build-config-DlxpZKk_.js} +4 -4
- package/dist/chunks/{build-config-5d8WlQbq.js.map → build-config-DlxpZKk_.js.map} +1 -1
- package/dist/chunks/{collector-CjCak4iE.js → collector-B4-yqFEs.js} +4 -4
- package/dist/chunks/{collector-CjCak4iE.js.map → collector-B4-yqFEs.js.map} +1 -1
- package/dist/chunks/{config-engine-uOFYZidB.js → config-engine-DJsb5WYu.js} +3 -3
- package/dist/chunks/{config-engine-uOFYZidB.js.map → config-engine-DJsb5WYu.js.map} +1 -1
- package/dist/chunks/{css-definitions-ubrHP97m.js → css-definitions-DW1TGGiy.js} +2 -2
- package/dist/chunks/{css-definitions-ubrHP97m.js.map → css-definitions-DW1TGGiy.js.map} +1 -1
- package/dist/chunks/{debug-CJ31U_WE.js → debug-DMMwe1rY.js} +4 -4
- package/dist/chunks/{debug-CJ31U_WE.js.map → debug-DMMwe1rY.js.map} +1 -1
- package/dist/chunks/{react-runtime-CyyCI02N.js → react-runtime-DhPtFlZs.js} +5 -5
- package/dist/chunks/react-runtime-DhPtFlZs.js.map +1 -0
- package/dist/chunks/{runtime-engine-BQmOu5-W.js → runtime-engine-BlrVXv8l.js} +5 -5
- package/dist/chunks/{runtime-engine-BQmOu5-W.js.map → runtime-engine-BlrVXv8l.js.map} +1 -1
- package/dist/chunks/{runtime-state-DEsyUMU-.js → runtime-state-BLyMRYFF.js} +2 -2
- package/dist/chunks/{runtime-state-DEsyUMU-.js.map → runtime-state-BLyMRYFF.js.map} +1 -1
- package/dist/chunks/{style-engine-BX2LshDZ.js → style-engine-of5Xbc27.js} +139 -34
- package/dist/chunks/style-engine-of5Xbc27.js.map +1 -0
- package/dist/chunks/{zero-engine-Dw0P4yGM.js → zero-engine-D2jPSpWA.js} +5 -5
- package/dist/chunks/{zero-engine-Dw0P4yGM.js.map → zero-engine-D2jPSpWA.js.map} +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +6 -6
- package/dist/{index-xtey-KDu.d.ts → index--GdqCPlp.d.ts} +16 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -7
- package/dist/ssr/astro.js +2 -2
- package/dist/ssr/index.js +2 -2
- package/dist/ssr/next-config.js +3 -3
- package/dist/ssr/next.js +3 -3
- package/dist/zero/babel.js +4 -4
- package/dist/zero/index.js +3 -3
- package/docs/ai-agents.md +5 -1
- package/docs/configuration.md +2 -1
- package/docs/design-system.md +1 -1
- package/docs/dsl.md +42 -3
- package/docs/injector.md +3 -1
- package/docs/methodology.md +7 -7
- package/docs/migration-v3.md +1 -1
- package/docs/pipeline.md +1 -1
- package/docs/plugins.md +1 -1
- package/docs/react-api.md +51 -8
- package/docs/ssr.md +29 -23
- package/docs/styles.md +6 -0
- package/docs/tasty-static.md +33 -16
- package/package.json +5 -5
- package/dist/chunks/react-runtime-CyyCI02N.js.map +0 -1
- package/dist/chunks/style-engine-BX2LshDZ.js.map +0 -1
package/README.md
CHANGED
|
@@ -170,7 +170,7 @@ const DangerButton = tasty(Button, {
|
|
|
170
170
|
});
|
|
171
171
|
```
|
|
172
172
|
|
|
173
|
-
A state map with a `''` key replaces the parent's map; a map without one extends it. `@inherit` pulls a single branch from the parent, `null` removes one, and `false` blocks it entirely. See [Extending vs. replacing state maps](docs/dsl.md#extending-vs-replacing-state-maps).
|
|
173
|
+
A state map with a `''` key replaces the parent's map; a map without one extends it. `@inherit` pulls a single branch from the parent, `null` removes one, and `false` blocks it entirely. See [Extending vs. replacing state maps](docs/dsl.md#extending-vs-replacing-state-maps). An extension can also declare its own `styleProps`, `modProps`, `tokenProps`, `variants`, and `elements`, and it keeps the base's sub-elements.
|
|
174
174
|
|
|
175
175
|
[Getting Started](docs/getting-started.md) continues from here with setup, linting, editor tooling, and choosing a rendering mode.
|
|
176
176
|
|
|
@@ -371,7 +371,7 @@ const Progress = tasty({
|
|
|
371
371
|
|
|
372
372
|
### Variants
|
|
373
373
|
|
|
374
|
-
Variants are named style sets. `variant` is typed from their keys, `default` applies when no `variant` is passed, and only the variants actually rendered emit CSS:
|
|
374
|
+
Variants are named style sets. `variant` is typed from their keys, `default` (or the variant named by the `variant` option) applies when no `variant` is passed, and only the variants actually rendered emit CSS:
|
|
375
375
|
|
|
376
376
|
```tsx
|
|
377
377
|
const Badge = tasty({
|
|
@@ -519,7 +519,7 @@ Tasty also ships its own style properties (`fill`, `flow`, `radius`, `preset`, `
|
|
|
519
519
|
|
|
520
520
|
### Style functions
|
|
521
521
|
|
|
522
|
-
When you don't need a component, call the style functions directly: `useStyles` for a class name, `useGlobalStyles` for selector-scoped global CSS, `useRawCSS` for raw rules, plus `useKeyframes`, `useProperty`, `useFontFace`, `useCounterStyle`, and `useFunction`. Apart from `useStyles`, which reads React context, they are plain functions despite the `use` prefix, so they work
|
|
522
|
+
When you don't need a component, call the style functions directly: `useStyles` for a class name, `useGlobalStyles` for selector-scoped global CSS, `useRawCSS` for raw rules, plus `useKeyframes`, `useProperty`, `useFontFace`, `useCounterStyle`, and `useFunction`. All of them work in React Server Components. Apart from `useStyles`, which reads React context on the client, they are plain functions despite the `use` prefix, so they also work outside React; `computeStyles` is the hook-free equivalent of `useStyles`. See [React API — Style Functions](docs/react-api.md#style-functions).
|
|
523
523
|
|
|
524
524
|
## Rendering Modes
|
|
525
525
|
|
|
@@ -531,7 +531,7 @@ The DSL, tokens, units, state maps, and recipes are the same everywhere. What ch
|
|
|
531
531
|
| **Hydrated React** | `tasty()` plus `@tenphi/tasty/ssr/*` | During SSR, then on demand in React | Only in hydrated components | Interactive React apps, Next.js client components, Astro islands |
|
|
532
532
|
| **Build-time extraction** | `tastyStatic()` from `@tenphi/tasty/static` | During the build | None in file mode | Non-React frameworks, CSS needed before rendering |
|
|
533
533
|
|
|
534
|
-
- **`tasty()` renders on the server.** Components are hook-free and render as React Server Components by default. Rendered only on the server, they keep the full React API (`styleProps`, sub-elements, variants) and ship no styling runtime. Astro's `tastyIntegration({ islands: false })` is the verified zero-JavaScript setup; server-only Next.js RSC follows the same architecture. Without an integration, each element inlines its own CSS and configured tokens
|
|
534
|
+
- **`tasty()` renders on the server.** Components are hook-free and render as React Server Components by default. Rendered only on the server, they keep the full React API (`styleProps`, sub-elements, variants) and ship no styling runtime. Astro's `tastyIntegration({ islands: false })` is the verified zero-JavaScript setup; server-only Next.js RSC follows the same architecture. Without an integration, each element inlines its own CSS, and configured tokens, global styles, and Tasty's default `@property` set are not emitted (Tasty warns in development), so use one for anything that relies on `configure()` or on those defaults.
|
|
535
535
|
- **SSR integrations** add CSS batching, cross-tree deduplication, FOUC prevention, and client cache hydration for apps that also render on the client: `TastyRegistry` from `@tenphi/tasty/ssr/next` (plus `withTastyNext()` from `@tenphi/tasty/ssr/next-config` for a shared global stylesheet), `tastyIntegration()` from `@tenphi/tasty/ssr/astro`, and a core API for other React SSR setups. Streaming is supported.
|
|
536
536
|
- **`tastyStatic()`** returns class names and extracts CSS during the build through a Babel plugin, with no React dependency. File mode ships no runtime; inject mode ships a tiny CSS injector.
|
|
537
537
|
|
|
@@ -593,13 +593,14 @@ Measured with [size-limit](https://github.com/ai/size-limit): minified and brotl
|
|
|
593
593
|
|
|
594
594
|
| Entry point | Size |
|
|
595
595
|
| ------------------------------------------------- | -------- |
|
|
596
|
-
| `@tenphi/tasty`, importing `tasty` |
|
|
597
|
-
| `@tenphi/tasty`, everything |
|
|
598
|
-
| `@tenphi/tasty/core`, everything (no SSR) |
|
|
596
|
+
| `@tenphi/tasty`, importing `tasty` | 52.26 kB |
|
|
597
|
+
| `@tenphi/tasty`, everything | 58.9 kB |
|
|
598
|
+
| `@tenphi/tasty/core`, everything (no SSR) | 55.2 kB |
|
|
599
599
|
| `@tenphi/tasty/static` (build-time authoring API) | 920 B |
|
|
600
|
+
| `@tenphi/tasty/ssr/client` | 277 B |
|
|
600
601
|
| `@tenphi/tasty/ssr/astro-client` | 283 B |
|
|
601
|
-
| `@tenphi/tasty/zero` (Node, build time) |
|
|
602
|
-
| `@tenphi/tasty/babel-plugin` (Node, build time) |
|
|
602
|
+
| `@tenphi/tasty/zero` (Node, build time) | 38.87 kB |
|
|
603
|
+
| `@tenphi/tasty/babel-plugin` (Node, build time) | 43.05 kB |
|
|
603
604
|
|
|
604
605
|
Run `pnpm size` to reproduce; numbers shift slightly between releases.
|
|
605
606
|
|
|
@@ -620,6 +621,8 @@ Reproducible benchmarks cover the core pipeline, the React overhead of an empty
|
|
|
620
621
|
|
|
621
622
|
Exclusive selectors rely on `:is()`, `:where()`, and level-4 `:not()` with selector lists: Chrome and Edge 88+, Firefox 84+, Safari 14+. Internet Explorer is not supported.
|
|
622
623
|
|
|
624
|
+
The defaults that style handlers read, such as the `#border` color and the `$transition` duration, are registered with `@property` (Chrome and Edge 85+, Firefox 128+, Safari 16.4+). For older engines, define those tokens yourself; see [Default properties](docs/dsl.md#default-properties).
|
|
625
|
+
|
|
623
626
|
## Entry Points
|
|
624
627
|
|
|
625
628
|
| Import | Description | Platform |
|
|
@@ -635,6 +638,7 @@ Exclusive selectors rely on `:is()`, `:where()`, and level-4 `:not()` with selec
|
|
|
635
638
|
| `@tenphi/tasty/ssr/next` | Next.js App Router SSR integration (`TastyRegistry`) | Node |
|
|
636
639
|
| `@tenphi/tasty/ssr/next-config` | Next.js config wrapper for a shared global stylesheet (`withTastyNext`) | Node |
|
|
637
640
|
| `@tenphi/tasty/ssr/astro` | Astro integration and middleware | Node |
|
|
641
|
+
| `@tenphi/tasty/ssr/client` | Browser-safe SSR hydration for any framework (`hydrateTastyClasses`) | Browser |
|
|
638
642
|
| `@tenphi/tasty/ssr/astro-client` | Astro client-side cache hydration | Browser |
|
|
639
643
|
|
|
640
644
|
## Built with Tasty
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { c as getGlobalParser, m as resetGlobalPredefinedTokens, p as resetGlobalParseFunctions, r as CUSTOM_UNITS } from "./dsl-DYSJc1-T.js";
|
|
2
2
|
import { o as isDevEnv, r as resetStyleWarnings } from "./shared-utils-y-HjvPN4.js";
|
|
3
|
-
import { M as validateNamePrefix, Y as resetFunctionPolyfills } from "./css-definitions-
|
|
4
|
-
import { H as clearGlobalPredefinedStates, V as resetStyleChunks, X as resetStylesGeneratedState, Y as resetGlobalPolyfillsState, k as resetHandlers, q as isFunctionsPolyfillEnabled, x as clearParseCache, y as clearPipelineCache } from "./style-engine-
|
|
5
|
-
import { n as applyStyleConfig, r as normalizeConfig } from "./config-engine-
|
|
3
|
+
import { M as validateNamePrefix, Y as resetFunctionPolyfills } from "./css-definitions-DW1TGGiy.js";
|
|
4
|
+
import { H as clearGlobalPredefinedStates, V as resetStyleChunks, X as resetStylesGeneratedState, Y as resetGlobalPolyfillsState, k as resetHandlers, q as isFunctionsPolyfillEnabled, x as clearParseCache, y as clearPipelineCache } from "./style-engine-of5Xbc27.js";
|
|
5
|
+
import { n as applyStyleConfig, r as normalizeConfig } from "./config-engine-DJsb5WYu.js";
|
|
6
6
|
//#region src/zero/config.ts
|
|
7
7
|
const emittedWarnings = /* @__PURE__ */ new Set();
|
|
8
8
|
const devMode = isDevEnv();
|
|
@@ -57,4 +57,4 @@ function functionsForExtraction(config) {
|
|
|
57
57
|
//#endregion
|
|
58
58
|
export { resetZeroConfig as a, reapplyZeroConfig as i, functionsForExtraction as n, setActiveZeroConfig as o, getActiveZeroConfig as r, configureZero as t };
|
|
59
59
|
|
|
60
|
-
//# sourceMappingURL=build-config-
|
|
60
|
+
//# sourceMappingURL=build-config-DlxpZKk_.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-config-
|
|
1
|
+
{"version":3,"file":"build-config-DlxpZKk_.js","names":[],"sources":["../../src/zero/config.ts"],"sourcesContent":["/** Build-time configuration without the browser injector/runtime registries. */\n\nimport { resetStyleChunks } from '../chunks/style-chunk-map';\nimport {\n applyStyleConfig,\n normalizeConfig,\n type NormalizedConfig,\n} from '../config-normalize';\nimport {\n isFunctionsPolyfillEnabled,\n resetGlobalPolyfillsState,\n resetStylesGeneratedState,\n} from '../config-state';\nimport { resetFunctionPolyfills } from '../functions';\nimport { clearPipelineCache } from '../pipeline';\nimport { clearParseCache } from '../pipeline/parseStateKey';\nimport { clearGlobalPredefinedStates } from '../states';\nimport { resetHandlers } from '../styles/predefined';\nimport { isDevEnv } from '../utils/is-dev-env';\nimport { validateNamePrefix } from '../utils/name-prefix';\nimport {\n CUSTOM_UNITS,\n getGlobalParser,\n resetGlobalParseFunctions,\n resetGlobalPredefinedTokens,\n} from '../utils/styles';\nimport { resetStyleWarnings } from '../utils/warnings';\n\nimport type { FunctionDefinition } from '../injector/types';\nimport type { TastyZeroConfig } from './babel-types';\n\nexport interface ResolvedZeroConfig {\n source: TastyZeroConfig;\n normalized: NormalizedConfig;\n functions: Record<string, FunctionDefinition>;\n}\n\nconst emittedWarnings = new Set<string>();\nconst devMode = isDevEnv();\n\n/**\n * Configuration set through the public `/zero` `configure()`, which the\n * programmatic extractors read for recipes and global keyframes. The Babel\n * plugin passes its configuration explicitly and leaves this unset.\n */\nlet activeConfig: ResolvedZeroConfig | null = null;\n\n/**\n * The configuration the engine state currently reflects. The state is\n * process-wide, so the Babel plugin, `withTastyNext()` and `/zero`\n * `configure()` can replace one another's; each re-applies its own when this\n * is not it.\n */\nlet appliedConfig: ResolvedZeroConfig | null = null;\n\nexport function getActiveZeroConfig(): ResolvedZeroConfig | null {\n return activeConfig;\n}\n\nexport function setActiveZeroConfig(config: ResolvedZeroConfig | null): void {\n activeConfig = config;\n}\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/** Resolve and apply the style-engine subset used during static extraction. */\nexport function configureZero(config: TastyZeroConfig): ResolvedZeroConfig {\n if (config.namePrefix !== undefined) validateNamePrefix(config.namePrefix);\n\n const normalized = normalizeConfig(config);\n const functions = applyStyleConfig(config, normalized, warnOnce);\n\n appliedConfig = { source: config, normalized, functions };\n return appliedConfig;\n}\n\n/**\n * Apply `config` again if another configuration replaced it since, and return\n * the configuration now applied (a fresh one when it was re-applied).\n */\nexport function reapplyZeroConfig(\n config: ResolvedZeroConfig,\n): ResolvedZeroConfig {\n if (appliedConfig === config) return config;\n\n resetZeroConfig();\n return configureZero(config.source);\n}\n\n/** Reset only state that the build-time configuration path can mutate. */\nexport function resetZeroConfig(): void {\n resetStylesGeneratedState();\n resetGlobalPolyfillsState();\n resetGlobalPredefinedTokens();\n resetGlobalParseFunctions();\n // State aliases and units are merged into, never replaced, so a new\n // configuration would otherwise keep the previous one's. Parsed state keys\n // are cached on the assumption that aliases do not change.\n clearGlobalPredefinedStates();\n clearParseCache();\n getGlobalParser().setUnits(CUSTOM_UNITS);\n resetFunctionPolyfills();\n resetHandlers();\n resetStyleChunks();\n clearPipelineCache();\n emittedWarnings.clear();\n resetStyleWarnings();\n appliedConfig = null;\n}\n\nexport function functionsForExtraction(\n config: ResolvedZeroConfig,\n): Record<string, FunctionDefinition> | undefined {\n return isFunctionsPolyfillEnabled() ? undefined : config.functions;\n}\n"],"mappings":";;;;;;AAqCA,MAAM,kCAAkB,IAAI,IAAY;AACxC,MAAM,UAAU,SAAS;AAOzB,IAAI,eAA0C;AAQ9C,IAAI,gBAA2C;AAE/C,SAAgB,sBAAiD;CAC/D,OAAO;AACT;AAEA,SAAgB,oBAAoB,QAAyC;CAC3E,eAAe;AACjB;AAEA,SAAS,SAAS,KAAa,SAAuB;CACpD,IAAI,WAAW,CAAC,gBAAgB,IAAI,GAAG,GAAG;EACxC,gBAAgB,IAAI,GAAG;EACvB,QAAQ,KAAK,OAAO;CACtB;AACF;AAGA,SAAgB,cAAc,QAA6C;CACzE,IAAI,OAAO,eAAe,KAAA,GAAW,mBAAmB,OAAO,UAAU;CAEzE,MAAM,aAAa,gBAAgB,MAAM;CAGzC,gBAAgB;EAAE,QAAQ;EAAQ;EAAY,WAF5B,iBAAiB,QAAQ,YAAY,QAED;CAAE;CACxD,OAAO;AACT;AAMA,SAAgB,kBACd,QACoB;CACpB,IAAI,kBAAkB,QAAQ,OAAO;CAErC,gBAAgB;CAChB,OAAO,cAAc,OAAO,MAAM;AACpC;AAGA,SAAgB,kBAAwB;CACtC,0BAA0B;CAC1B,0BAA0B;CAC1B,4BAA4B;CAC5B,0BAA0B;CAI1B,4BAA4B;CAC5B,gBAAgB;CAChB,gBAAgB,CAAC,CAAC,SAAS,YAAY;CACvC,uBAAuB;CACvB,cAAc;CACd,iBAAiB;CACjB,mBAAmB;CACnB,gBAAgB,MAAM;CACtB,mBAAmB;CACnB,gBAAgB;AAClB;AAEA,SAAgB,uBACd,QACgD;CAChD,OAAO,2BAA2B,IAAI,KAAA,IAAY,OAAO;AAC3D"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { D as makeClassName, K as parseFunctionName, M as validateNamePrefix, N as hashString, O as makeCounterStyleName, S as formatFontFaceRule, W as formatFunctionRule, _ as formatCounterStyleRule, b as fontFaceContentHash, i as formatKeyframesCSS, k as makeKeyframeName, m as resolveSelectorKeyframes, n as formatGlobalRules, o as formatPropertyCSS, r as formatRules, t as createServerStyleArtifact } from "./css-definitions-
|
|
2
|
-
import { b as renderStyles } from "./style-engine-
|
|
3
|
-
import { c as getGlobalFontFaces, d as getGlobalStyles, f as getRuntimeConfigState, i as getEffectiveProperties, l as getGlobalFunctions, o as getGlobalConfigTokens, s as getGlobalCounterStyles, u as getGlobalKeyframes } from "./runtime-state-
|
|
1
|
+
import { D as makeClassName, K as parseFunctionName, M as validateNamePrefix, N as hashString, O as makeCounterStyleName, S as formatFontFaceRule, W as formatFunctionRule, _ as formatCounterStyleRule, b as fontFaceContentHash, i as formatKeyframesCSS, k as makeKeyframeName, m as resolveSelectorKeyframes, n as formatGlobalRules, o as formatPropertyCSS, r as formatRules, t as createServerStyleArtifact } from "./css-definitions-DW1TGGiy.js";
|
|
2
|
+
import { b as renderStyles } from "./style-engine-of5Xbc27.js";
|
|
3
|
+
import { c as getGlobalFontFaces, d as getGlobalStyles, f as getRuntimeConfigState, i as getEffectiveProperties, l as getGlobalFunctions, o as getGlobalConfigTokens, s as getGlobalCounterStyles, u as getGlobalKeyframes } from "./runtime-state-BLyMRYFF.js";
|
|
4
4
|
//#region src/ssr/collector.ts
|
|
5
5
|
var ServerStyleCollector = class {
|
|
6
6
|
chunks = /* @__PURE__ */ new Map();
|
|
@@ -207,4 +207,4 @@ function createServerStyleCollector(namePrefix) {
|
|
|
207
207
|
//#endregion
|
|
208
208
|
export { createServerStyleCollector as n, ServerStyleCollector as t };
|
|
209
209
|
|
|
210
|
-
//# sourceMappingURL=collector-
|
|
210
|
+
//# sourceMappingURL=collector-B4-yqFEs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector-CjCak4iE.js","names":[],"sources":["../../src/ssr/collector.ts"],"sourcesContent":["/**\n * ServerStyleCollector — server-safe style collector for SSR.\n *\n * Accumulates CSS rules and cache metadata during server rendering.\n * This is the server-side counterpart to StyleInjector: it allocates\n * hash-based class names using the configured `namePrefix` (defaults\n * to `'t'`), formats CSS rules into text, and tracks rendered class\n * names for lightweight client transfer.\n *\n * One instance is created per HTTP request. Concurrent requests\n * each get their own collector (via AsyncLocalStorage or React context).\n */\n\nimport {\n getEffectiveProperties,\n getGlobalConfigTokens,\n getGlobalCounterStyles,\n getGlobalFontFaces,\n getGlobalFunctions,\n getGlobalKeyframes,\n getGlobalStyles,\n getRuntimeConfigState,\n} from '../config-resources';\nimport { formatCounterStyleRule } from '../counter-style';\nimport { fontFaceContentHash, formatFontFaceRule } from '../font-face';\nimport { formatFunctionRule, parseFunctionName } from '../functions';\nimport { resolveSelectorKeyframes } from '../keyframes';\nimport { renderStyles } from '../pipeline';\nimport type { StyleResult } from '../pipeline';\nimport { hashString } from '../utils/hash';\nimport {\n DEFAULT_NAME_PREFIX,\n makeClassName,\n makeCounterStyleName,\n makeKeyframeName,\n validateNamePrefix,\n} from '../utils/name-prefix';\nimport { createServerStyleArtifact } from './artifacts';\nimport type { ServerStyleArtifact, ServerStyleArtifactKind } from './artifacts';\nimport { formatPropertyCSS } from './format-property';\nimport { formatGlobalRules } from './format-global-rules';\nimport { formatKeyframesCSS } from './format-keyframes';\nimport { formatRules } from './format-rules';\n\nexport type { ServerStyleArtifact, ServerStyleArtifactKind } from './artifacts';\n\nexport class ServerStyleCollector {\n private chunks = new Map<string, string>();\n private cacheKeyToClassName = new Map<string, string>();\n private flushedKeys = new Set<string>();\n private propertyRules = new Map<string, string>();\n private flushedPropertyKeys = new Set<string>();\n private keyframeRules = new Map<string, string>();\n private flushedKeyframeKeys = new Set<string>();\n private globalStyles = new Map<string, string>();\n private flushedGlobalKeys = new Set<string>();\n private rawCSS = new Map<string, string>();\n private flushedRawKeys = new Set<string>();\n private fontFaceRules = new Map<string, string>();\n private flushedFontFaceKeys = new Set<string>();\n private counterStyleRules = new Map<string, string>();\n private flushedCounterStyleKeys = new Set<string>();\n private functionRules = new Map<string, string>();\n private flushedFunctionKeys = new Set<string>();\n private keyframesCounter = 0;\n private counterStyleCounter = 0;\n private internalsCollected = false;\n private namePrefix: string;\n\n /**\n * @param namePrefix - Optional override for the configured prefix.\n * Defaults to the value from `configure({ namePrefix })` (or `'t'`).\n * Pass an explicit prefix when constructing a collector outside the\n * normal configure() lifecycle (e.g. in tests). Validated eagerly\n * so misconfiguration fails before any CSS is collected.\n */\n constructor(namePrefix?: string) {\n if (namePrefix !== undefined) {\n validateNamePrefix(namePrefix);\n }\n this.namePrefix =\n namePrefix ?? getRuntimeConfigState()?.namePrefix ?? DEFAULT_NAME_PREFIX;\n }\n\n private generateClassName(cacheKey: string): string {\n return makeClassName(this.namePrefix, hashString(cacheKey));\n }\n\n /**\n * Collect internal @property rules and :root token defaults.\n * Mirrors markStylesGenerated() from the client-side injector.\n * Called automatically on first chunk collection; idempotent.\n *\n * Internals are always emitted here — the RSC path deliberately\n * defers to SSR so that tokens appear exactly once per page in\n * <style data-tasty-ssr> (avoiding duplication of large token sets).\n */\n collectInternals(): void {\n if (this.internalsCollected) return;\n this.internalsCollected = true;\n\n for (const [token, definition] of Object.entries(\n getEffectiveProperties(),\n )) {\n const css = formatPropertyCSS(token, definition);\n if (css) {\n this.collectProperty(`__prop:${token}`, css);\n }\n }\n\n const tokenStyles = getGlobalConfigTokens();\n if (tokenStyles && Object.keys(tokenStyles).length > 0) {\n const tokenRules = renderStyles(tokenStyles, ':root') as StyleResult[];\n if (tokenRules.length > 0) {\n const css = formatGlobalRules(tokenRules);\n if (css) {\n this.collectGlobalStyles('__global:tokens', css);\n }\n }\n }\n\n const globalFF = getGlobalFontFaces();\n if (globalFF) {\n for (const [family, input] of Object.entries(globalFF)) {\n const descriptors = Array.isArray(input) ? input : [input];\n for (const desc of descriptors) {\n const hash = fontFaceContentHash(family, desc);\n const css = formatFontFaceRule(family, desc);\n this.collectFontFace(hash, css);\n }\n }\n }\n\n const globalCS = getGlobalCounterStyles();\n if (globalCS) {\n for (const [name, descriptors] of Object.entries(globalCS)) {\n const css = formatCounterStyleRule(name, descriptors);\n this.collectCounterStyle(name, css, { weak: true });\n }\n }\n\n const globalFn = getGlobalFunctions();\n if (globalFn) {\n for (const [name, definition] of Object.entries(globalFn)) {\n const css = formatFunctionRule(name, definition);\n this.collectFunction(parseFunctionName(name), css, { weak: true });\n }\n }\n\n const globalStyles = getGlobalStyles();\n if (globalStyles) {\n for (const [selector, styles] of Object.entries(globalStyles)) {\n if (Object.keys(styles).length > 0) {\n const rendered = renderStyles(styles, selector) as StyleResult[];\n if (rendered.length > 0) {\n const { rules, keyframes } = resolveSelectorKeyframes(\n styles,\n rendered,\n getGlobalKeyframes(),\n );\n for (const [name, steps] of keyframes ?? []) {\n this.collectKeyframes(name, formatKeyframesCSS(name, steps));\n }\n const css = formatGlobalRules(rules);\n if (css) {\n this.collectGlobalStyles(`__global:styles:${selector}`, css);\n }\n }\n }\n }\n }\n }\n\n /**\n * Allocate a className for a cache key, server-side.\n * Mirrors StyleInjector.allocateClassName but without DOM access.\n */\n allocateClassName(cacheKey: string): {\n className: string;\n isNewAllocation: boolean;\n } {\n const existing = this.cacheKeyToClassName.get(cacheKey);\n if (existing) {\n return { className: existing, isNewAllocation: false };\n }\n\n const className = this.generateClassName(cacheKey);\n this.cacheKeyToClassName.set(cacheKey, className);\n\n return { className, isNewAllocation: true };\n }\n\n /**\n * Record CSS rules for a chunk.\n * Called by useStyles during server render.\n */\n collectChunk(\n cacheKey: string,\n className: string,\n rules: StyleResult[],\n ): void {\n if (this.chunks.has(cacheKey)) return;\n const css = formatRules(rules, className);\n if (css) {\n this.chunks.set(cacheKey, css);\n }\n }\n\n /**\n * Record a @property rule. Deduplicated by name.\n */\n collectProperty(name: string, css: string): void {\n if (!this.propertyRules.has(name)) {\n this.propertyRules.set(name, css);\n }\n }\n\n /**\n * Record a @keyframes rule. Deduplicated by name.\n */\n collectKeyframes(name: string, css: string): void {\n if (!this.keyframeRules.has(name)) {\n this.keyframeRules.set(name, css);\n }\n }\n\n /**\n * Allocate a keyframe name for SSR. Uses provided name or generates one.\n */\n allocateKeyframeName(providedName?: string): string {\n return (\n providedName ??\n makeKeyframeName(this.namePrefix, String(this.keyframesCounter++))\n );\n }\n\n /**\n * Record a @font-face rule. Deduplicated by key (content hash).\n */\n collectFontFace(key: string, css: string): void {\n if (!this.fontFaceRules.has(key)) {\n this.fontFaceRules.set(key, css);\n }\n }\n\n /**\n * Record a @counter-style rule. Deduplicated by name and overrides an\n * existing rule by default. Pass `weak: true` for global `configure()`\n * definitions, which never clobber an existing rule.\n */\n collectCounterStyle(\n name: string,\n css: string,\n options?: { weak?: boolean },\n ): void {\n const existing = this.counterStyleRules.get(name);\n if (existing === undefined) {\n this.counterStyleRules.set(name, css);\n return;\n }\n if (options?.weak || existing === css) return;\n this.counterStyleRules.set(name, css);\n // If a rule with this name was already flushed (streaming), allow the\n // overriding rule to be flushed again so it wins by source order.\n this.flushedCounterStyleKeys.delete(name);\n }\n\n /**\n * Record a @function rule. Deduplicated by CSS function name and overrides an\n * existing rule by default. Pass `weak: true` for global `configure()`\n * definitions, which never clobber an existing rule.\n */\n collectFunction(\n name: string,\n css: string,\n options?: { weak?: boolean },\n ): void {\n const existing = this.functionRules.get(name);\n if (existing === undefined) {\n this.functionRules.set(name, css);\n return;\n }\n if (options?.weak || existing === css) return;\n this.functionRules.set(name, css);\n // If a rule with this name was already flushed (streaming), allow the\n // overriding rule to be flushed again so it wins by source order.\n this.flushedFunctionKeys.delete(name);\n }\n\n /**\n * Allocate a counter-style name for SSR. Uses provided name or generates one.\n */\n allocateCounterStyleName(providedName?: string): string {\n return (\n providedName ??\n makeCounterStyleName(this.namePrefix, String(this.counterStyleCounter++))\n );\n }\n\n /**\n * Record global styles (from useGlobalStyles). Deduplicated by key.\n *\n * Pass `replace` for slot-keyed entries (an explicit `id`), where the last\n * write must win to match the client's update-tracking behavior.\n */\n collectGlobalStyles(key: string, css: string, replace?: boolean): void {\n if (replace || !this.globalStyles.has(key)) {\n this.globalStyles.set(key, css);\n }\n }\n\n /**\n * Record raw CSS text (from useRawCSS). Deduplicated by key.\n *\n * Pass `replace` for slot-keyed entries (an explicit `id`), where the last\n * write must win to match the client's update-tracking behavior.\n */\n collectRawCSS(key: string, css: string, replace?: boolean): void {\n if (replace || !this.rawCSS.has(key)) {\n this.rawCSS.set(key, css);\n }\n }\n\n /**\n * Return the collected CSS as structured, ordered artifacts.\n *\n * Artifact boundaries are part of the collector output so build tools never\n * need to split or parse CSS text. IDs include the logical collection key\n * and content, making them stable across equivalent page renders while a CSS\n * change always produces a different ID.\n */\n getArtifacts(): ServerStyleArtifact[] {\n const artifacts: ServerStyleArtifact[] = [];\n\n const append = (\n kind: ServerStyleArtifactKind,\n entries: Iterable<[string, string]>,\n ) => {\n for (const [key, css] of entries) {\n artifacts.push(\n createServerStyleArtifact(kind, key, css, artifacts.length),\n );\n }\n };\n\n append('property', this.propertyRules);\n append('font-face', this.fontFaceRules);\n append('counter-style', this.counterStyleRules);\n append('function', this.functionRules);\n append('raw', this.rawCSS);\n append('global', this.globalStyles);\n append('chunk', this.chunks);\n append('keyframes', this.keyframeRules);\n\n return artifacts;\n }\n\n /**\n * Extract all CSS collected so far as a single string.\n * Includes @property and @keyframes rules.\n * Used for non-streaming SSR (renderToString).\n */\n getCSS(): string {\n return this.getArtifacts()\n .map(({ css }) => css)\n .join('\\n');\n }\n\n /**\n * Flush only newly collected CSS since the last flush.\n * Used for streaming SSR (renderToPipeableStream + useServerInsertedHTML).\n */\n flushCSS(): string {\n const parts: string[] = [];\n\n for (const [name, css] of this.propertyRules) {\n if (!this.flushedPropertyKeys.has(name)) {\n parts.push(css);\n this.flushedPropertyKeys.add(name);\n }\n }\n\n for (const [key, css] of this.fontFaceRules) {\n if (!this.flushedFontFaceKeys.has(key)) {\n parts.push(css);\n this.flushedFontFaceKeys.add(key);\n }\n }\n\n for (const [key, css] of this.counterStyleRules) {\n if (!this.flushedCounterStyleKeys.has(key)) {\n parts.push(css);\n this.flushedCounterStyleKeys.add(key);\n }\n }\n\n for (const [key, css] of this.functionRules) {\n if (!this.flushedFunctionKeys.has(key)) {\n parts.push(css);\n this.flushedFunctionKeys.add(key);\n }\n }\n\n for (const [key, css] of this.rawCSS) {\n if (!this.flushedRawKeys.has(key)) {\n parts.push(css);\n this.flushedRawKeys.add(key);\n }\n }\n\n for (const [key, css] of this.globalStyles) {\n if (!this.flushedGlobalKeys.has(key)) {\n parts.push(css);\n this.flushedGlobalKeys.add(key);\n }\n }\n\n for (const [key, css] of this.chunks) {\n if (!this.flushedKeys.has(key)) {\n parts.push(css);\n this.flushedKeys.add(key);\n }\n }\n\n for (const [name, css] of this.keyframeRules) {\n if (!this.flushedKeyframeKeys.has(name)) {\n parts.push(css);\n this.flushedKeyframeKeys.add(name);\n }\n }\n\n return parts.join('\\n');\n }\n\n private flushedClassNames = new Set<string>();\n\n /**\n * Return class names rendered since the last call (for streaming).\n * Used to emit lightweight class-list scripts for client hydration.\n */\n getRenderedClassNames(): string[] {\n const names: string[] = [];\n for (const className of this.cacheKeyToClassName.values()) {\n if (!this.flushedClassNames.has(className)) {\n this.flushedClassNames.add(className);\n names.push(className);\n }\n }\n return names;\n }\n}\n\n/**\n * Factory for creating a {@link ServerStyleCollector} instance.\n *\n * Canonical functional entry point; the `ServerStyleCollector` class remains\n * exported for advanced/internal use.\n *\n * @param namePrefix - Optional override for the configured class-name prefix.\n * Defaults to the value from `configure({ namePrefix })` (or `'t'`).\n *\n * @example\n * ```ts\n * import { createServerStyleCollector } from '@tenphi/tasty/ssr';\n *\n * const collector = createServerStyleCollector();\n * ```\n */\nexport function createServerStyleCollector(\n namePrefix?: string,\n): ServerStyleCollector {\n return new ServerStyleCollector(namePrefix);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"collector-B4-yqFEs.js","names":[],"sources":["../../src/ssr/collector.ts"],"sourcesContent":["/**\n * ServerStyleCollector — server-safe style collector for SSR.\n *\n * Accumulates CSS rules and cache metadata during server rendering.\n * This is the server-side counterpart to StyleInjector: it allocates\n * hash-based class names using the configured `namePrefix` (defaults\n * to `'t'`), formats CSS rules into text, and tracks rendered class\n * names for lightweight client transfer.\n *\n * One instance is created per HTTP request. Concurrent requests\n * each get their own collector (via AsyncLocalStorage or React context).\n */\n\nimport {\n getEffectiveProperties,\n getGlobalConfigTokens,\n getGlobalCounterStyles,\n getGlobalFontFaces,\n getGlobalFunctions,\n getGlobalKeyframes,\n getGlobalStyles,\n getRuntimeConfigState,\n} from '../config-resources';\nimport { formatCounterStyleRule } from '../counter-style';\nimport { fontFaceContentHash, formatFontFaceRule } from '../font-face';\nimport { formatFunctionRule, parseFunctionName } from '../functions';\nimport { resolveSelectorKeyframes } from '../keyframes';\nimport { renderStyles } from '../pipeline';\nimport type { StyleResult } from '../pipeline';\nimport { hashString } from '../utils/hash';\nimport {\n DEFAULT_NAME_PREFIX,\n makeClassName,\n makeCounterStyleName,\n makeKeyframeName,\n validateNamePrefix,\n} from '../utils/name-prefix';\nimport { createServerStyleArtifact } from './artifacts';\nimport type { ServerStyleArtifact, ServerStyleArtifactKind } from './artifacts';\nimport { formatPropertyCSS } from './format-property';\nimport { formatGlobalRules } from './format-global-rules';\nimport { formatKeyframesCSS } from './format-keyframes';\nimport { formatRules } from './format-rules';\n\nexport type { ServerStyleArtifact, ServerStyleArtifactKind } from './artifacts';\n\nexport class ServerStyleCollector {\n private chunks = new Map<string, string>();\n private cacheKeyToClassName = new Map<string, string>();\n private flushedKeys = new Set<string>();\n private propertyRules = new Map<string, string>();\n private flushedPropertyKeys = new Set<string>();\n private keyframeRules = new Map<string, string>();\n private flushedKeyframeKeys = new Set<string>();\n private globalStyles = new Map<string, string>();\n private flushedGlobalKeys = new Set<string>();\n private rawCSS = new Map<string, string>();\n private flushedRawKeys = new Set<string>();\n private fontFaceRules = new Map<string, string>();\n private flushedFontFaceKeys = new Set<string>();\n private counterStyleRules = new Map<string, string>();\n private flushedCounterStyleKeys = new Set<string>();\n private functionRules = new Map<string, string>();\n private flushedFunctionKeys = new Set<string>();\n private keyframesCounter = 0;\n private counterStyleCounter = 0;\n private internalsCollected = false;\n private namePrefix: string;\n\n /**\n * @param namePrefix - Optional override for the configured prefix.\n * Defaults to the value from `configure({ namePrefix })` (or `'t'`).\n * Pass an explicit prefix when constructing a collector outside the\n * normal configure() lifecycle (e.g. in tests). Validated eagerly\n * so misconfiguration fails before any CSS is collected.\n */\n constructor(namePrefix?: string) {\n if (namePrefix !== undefined) {\n validateNamePrefix(namePrefix);\n }\n this.namePrefix =\n namePrefix ?? getRuntimeConfigState()?.namePrefix ?? DEFAULT_NAME_PREFIX;\n }\n\n private generateClassName(cacheKey: string): string {\n return makeClassName(this.namePrefix, hashString(cacheKey));\n }\n\n /**\n * Collect internal @property rules and :root token defaults.\n * Mirrors markStylesGenerated() from the client-side injector.\n * Called automatically on first chunk collection; idempotent.\n *\n * Internals are always emitted here — the RSC path deliberately\n * defers to SSR so that tokens appear exactly once per page in\n * <style data-tasty-ssr> (avoiding duplication of large token sets).\n */\n collectInternals(): void {\n if (this.internalsCollected) return;\n this.internalsCollected = true;\n\n for (const [token, definition] of Object.entries(\n getEffectiveProperties(),\n )) {\n const css = formatPropertyCSS(token, definition);\n if (css) {\n this.collectProperty(`__prop:${token}`, css);\n }\n }\n\n const tokenStyles = getGlobalConfigTokens();\n if (tokenStyles && Object.keys(tokenStyles).length > 0) {\n const tokenRules = renderStyles(tokenStyles, ':root') as StyleResult[];\n if (tokenRules.length > 0) {\n const css = formatGlobalRules(tokenRules);\n if (css) {\n this.collectGlobalStyles('__global:tokens', css);\n }\n }\n }\n\n const globalFF = getGlobalFontFaces();\n if (globalFF) {\n for (const [family, input] of Object.entries(globalFF)) {\n const descriptors = Array.isArray(input) ? input : [input];\n for (const desc of descriptors) {\n const hash = fontFaceContentHash(family, desc);\n const css = formatFontFaceRule(family, desc);\n this.collectFontFace(hash, css);\n }\n }\n }\n\n const globalCS = getGlobalCounterStyles();\n if (globalCS) {\n for (const [name, descriptors] of Object.entries(globalCS)) {\n const css = formatCounterStyleRule(name, descriptors);\n this.collectCounterStyle(name, css, { weak: true });\n }\n }\n\n const globalFn = getGlobalFunctions();\n if (globalFn) {\n for (const [name, definition] of Object.entries(globalFn)) {\n const css = formatFunctionRule(name, definition);\n this.collectFunction(parseFunctionName(name), css, { weak: true });\n }\n }\n\n const globalStyles = getGlobalStyles();\n if (globalStyles) {\n for (const [selector, styles] of Object.entries(globalStyles)) {\n if (Object.keys(styles).length > 0) {\n const rendered = renderStyles(styles, selector) as StyleResult[];\n if (rendered.length > 0) {\n const { rules, keyframes } = resolveSelectorKeyframes(\n styles,\n rendered,\n getGlobalKeyframes(),\n );\n for (const [name, steps] of keyframes ?? []) {\n this.collectKeyframes(name, formatKeyframesCSS(name, steps));\n }\n const css = formatGlobalRules(rules);\n if (css) {\n this.collectGlobalStyles(`__global:styles:${selector}`, css);\n }\n }\n }\n }\n }\n }\n\n /**\n * Allocate a className for a cache key, server-side.\n * Mirrors StyleInjector.allocateClassName but without DOM access.\n */\n allocateClassName(cacheKey: string): {\n className: string;\n isNewAllocation: boolean;\n } {\n const existing = this.cacheKeyToClassName.get(cacheKey);\n if (existing) {\n return { className: existing, isNewAllocation: false };\n }\n\n const className = this.generateClassName(cacheKey);\n this.cacheKeyToClassName.set(cacheKey, className);\n\n return { className, isNewAllocation: true };\n }\n\n /**\n * Record CSS rules for a chunk.\n * Called by useStyles during server render.\n */\n collectChunk(\n cacheKey: string,\n className: string,\n rules: StyleResult[],\n ): void {\n if (this.chunks.has(cacheKey)) return;\n const css = formatRules(rules, className);\n if (css) {\n this.chunks.set(cacheKey, css);\n }\n }\n\n /**\n * Record a @property rule. Deduplicated by name.\n */\n collectProperty(name: string, css: string): void {\n if (!this.propertyRules.has(name)) {\n this.propertyRules.set(name, css);\n }\n }\n\n /**\n * Record a @keyframes rule. Deduplicated by name.\n */\n collectKeyframes(name: string, css: string): void {\n if (!this.keyframeRules.has(name)) {\n this.keyframeRules.set(name, css);\n }\n }\n\n /**\n * Allocate a keyframe name for SSR. Uses provided name or generates one.\n */\n allocateKeyframeName(providedName?: string): string {\n return (\n providedName ??\n makeKeyframeName(this.namePrefix, String(this.keyframesCounter++))\n );\n }\n\n /**\n * Record a @font-face rule. Deduplicated by key (content hash).\n */\n collectFontFace(key: string, css: string): void {\n if (!this.fontFaceRules.has(key)) {\n this.fontFaceRules.set(key, css);\n }\n }\n\n /**\n * Record a @counter-style rule. Deduplicated by name and overrides an\n * existing rule by default. Pass `weak: true` for global `configure()`\n * definitions, which never clobber an existing rule.\n */\n collectCounterStyle(\n name: string,\n css: string,\n options?: { weak?: boolean },\n ): void {\n const existing = this.counterStyleRules.get(name);\n if (existing === undefined) {\n this.counterStyleRules.set(name, css);\n return;\n }\n if (options?.weak || existing === css) return;\n this.counterStyleRules.set(name, css);\n // If a rule with this name was already flushed (streaming), allow the\n // overriding rule to be flushed again so it wins by source order.\n this.flushedCounterStyleKeys.delete(name);\n }\n\n /**\n * Record a @function rule. Deduplicated by CSS function name and overrides an\n * existing rule by default. Pass `weak: true` for global `configure()`\n * definitions, which never clobber an existing rule.\n */\n collectFunction(\n name: string,\n css: string,\n options?: { weak?: boolean },\n ): void {\n const existing = this.functionRules.get(name);\n if (existing === undefined) {\n this.functionRules.set(name, css);\n return;\n }\n if (options?.weak || existing === css) return;\n this.functionRules.set(name, css);\n // If a rule with this name was already flushed (streaming), allow the\n // overriding rule to be flushed again so it wins by source order.\n this.flushedFunctionKeys.delete(name);\n }\n\n /**\n * Allocate a counter-style name for SSR. Uses provided name or generates one.\n */\n allocateCounterStyleName(providedName?: string): string {\n return (\n providedName ??\n makeCounterStyleName(this.namePrefix, String(this.counterStyleCounter++))\n );\n }\n\n /**\n * Record global styles (from useGlobalStyles). Deduplicated by key.\n *\n * Pass `replace` for slot-keyed entries (an explicit `id`), where the last\n * write must win to match the client's update-tracking behavior.\n */\n collectGlobalStyles(key: string, css: string, replace?: boolean): void {\n if (replace || !this.globalStyles.has(key)) {\n this.globalStyles.set(key, css);\n }\n }\n\n /**\n * Record raw CSS text (from useRawCSS). Deduplicated by key.\n *\n * Pass `replace` for slot-keyed entries (an explicit `id`), where the last\n * write must win to match the client's update-tracking behavior.\n */\n collectRawCSS(key: string, css: string, replace?: boolean): void {\n if (replace || !this.rawCSS.has(key)) {\n this.rawCSS.set(key, css);\n }\n }\n\n /**\n * Return the collected CSS as structured, ordered artifacts.\n *\n * Artifact boundaries are part of the collector output so build tools never\n * need to split or parse CSS text. IDs include the logical collection key\n * and content, making them stable across equivalent page renders while a CSS\n * change always produces a different ID.\n */\n getArtifacts(): ServerStyleArtifact[] {\n const artifacts: ServerStyleArtifact[] = [];\n\n const append = (\n kind: ServerStyleArtifactKind,\n entries: Iterable<[string, string]>,\n ) => {\n for (const [key, css] of entries) {\n artifacts.push(\n createServerStyleArtifact(kind, key, css, artifacts.length),\n );\n }\n };\n\n append('property', this.propertyRules);\n append('font-face', this.fontFaceRules);\n append('counter-style', this.counterStyleRules);\n append('function', this.functionRules);\n append('raw', this.rawCSS);\n append('global', this.globalStyles);\n append('chunk', this.chunks);\n append('keyframes', this.keyframeRules);\n\n return artifacts;\n }\n\n /**\n * Extract all CSS collected so far as a single string.\n * Includes @property and @keyframes rules.\n * Used for non-streaming SSR (renderToString).\n */\n getCSS(): string {\n return this.getArtifacts()\n .map(({ css }) => css)\n .join('\\n');\n }\n\n /**\n * Flush only newly collected CSS since the last flush.\n * Used for streaming SSR (renderToPipeableStream + useServerInsertedHTML).\n */\n flushCSS(): string {\n const parts: string[] = [];\n\n for (const [name, css] of this.propertyRules) {\n if (!this.flushedPropertyKeys.has(name)) {\n parts.push(css);\n this.flushedPropertyKeys.add(name);\n }\n }\n\n for (const [key, css] of this.fontFaceRules) {\n if (!this.flushedFontFaceKeys.has(key)) {\n parts.push(css);\n this.flushedFontFaceKeys.add(key);\n }\n }\n\n for (const [key, css] of this.counterStyleRules) {\n if (!this.flushedCounterStyleKeys.has(key)) {\n parts.push(css);\n this.flushedCounterStyleKeys.add(key);\n }\n }\n\n for (const [key, css] of this.functionRules) {\n if (!this.flushedFunctionKeys.has(key)) {\n parts.push(css);\n this.flushedFunctionKeys.add(key);\n }\n }\n\n for (const [key, css] of this.rawCSS) {\n if (!this.flushedRawKeys.has(key)) {\n parts.push(css);\n this.flushedRawKeys.add(key);\n }\n }\n\n for (const [key, css] of this.globalStyles) {\n if (!this.flushedGlobalKeys.has(key)) {\n parts.push(css);\n this.flushedGlobalKeys.add(key);\n }\n }\n\n for (const [key, css] of this.chunks) {\n if (!this.flushedKeys.has(key)) {\n parts.push(css);\n this.flushedKeys.add(key);\n }\n }\n\n for (const [name, css] of this.keyframeRules) {\n if (!this.flushedKeyframeKeys.has(name)) {\n parts.push(css);\n this.flushedKeyframeKeys.add(name);\n }\n }\n\n return parts.join('\\n');\n }\n\n private flushedClassNames = new Set<string>();\n\n /**\n * Return class names rendered since the last call (for streaming).\n * Used to emit lightweight class-list scripts for client hydration.\n */\n getRenderedClassNames(): string[] {\n const names: string[] = [];\n for (const className of this.cacheKeyToClassName.values()) {\n if (!this.flushedClassNames.has(className)) {\n this.flushedClassNames.add(className);\n names.push(className);\n }\n }\n return names;\n }\n}\n\n/**\n * Factory for creating a {@link ServerStyleCollector} instance.\n *\n * Canonical functional entry point; the `ServerStyleCollector` class remains\n * exported for advanced/internal use.\n *\n * @param namePrefix - Optional override for the configured class-name prefix.\n * Defaults to the value from `configure({ namePrefix })` (or `'t'`).\n *\n * @example\n * ```ts\n * import { createServerStyleCollector } from '@tenphi/tasty/ssr';\n *\n * const collector = createServerStyleCollector();\n * ```\n */\nexport function createServerStyleCollector(\n namePrefix?: string,\n): ServerStyleCollector {\n return new ServerStyleCollector(namePrefix);\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { c as getGlobalParser, g as setGlobalPredefinedTokens, r as CUSTOM_UNITS, s as getGlobalParseFunctions, u as normalizeColorTokenValue } from "./dsl-DYSJc1-T.js";
|
|
2
2
|
import { n as isSelector, o as isDevEnv, t as mergeStyles } from "./shared-utils-y-HjvPN4.js";
|
|
3
|
-
import { X as splitFunctions, q as registerFunctionPolyfill } from "./css-definitions-
|
|
4
|
-
import { D as normalizeHandlerDefinition, G as setGlobalPredefinedStates, O as registerHandler, Z as setGlobalPolyfillsState, q as isFunctionsPolyfillEnabled } from "./style-engine-
|
|
3
|
+
import { X as splitFunctions, q as registerFunctionPolyfill } from "./css-definitions-DW1TGGiy.js";
|
|
4
|
+
import { D as normalizeHandlerDefinition, G as setGlobalPredefinedStates, O as registerHandler, Z as setGlobalPolyfillsState, q as isFunctionsPolyfillEnabled } from "./style-engine-of5Xbc27.js";
|
|
5
5
|
//#region src/utils/typography.ts
|
|
6
6
|
const RESERVED_PRESET_NAMES = /* @__PURE__ */ new Set([
|
|
7
7
|
"strong",
|
|
@@ -269,4 +269,4 @@ function resolveRecipesWith(styles, recipes) {
|
|
|
269
269
|
//#endregion
|
|
270
270
|
export { generateTypographyTokens as i, applyStyleConfig as n, normalizeConfig as r, resolveRecipesWith as t };
|
|
271
271
|
|
|
272
|
-
//# sourceMappingURL=config-engine-
|
|
272
|
+
//# sourceMappingURL=config-engine-DJsb5WYu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-engine-uOFYZidB.js","names":[],"sources":["../../src/utils/typography.ts","../../src/config-normalize.ts","../../src/utils/resolve-recipes-core.ts"],"sourcesContent":["import type { ConfigTokens } from '../styles/types';\n\nconst RESERVED_PRESET_NAMES = new Set([\n 'strong',\n 'bold',\n 'italic',\n 'icon',\n 'tight',\n]);\n\n/**\n * A typography token value: plain value or a state map for responsive/theme-aware presets.\n *\n * @example\n * // Plain value\n * fontWeight: '400'\n * // State map\n * fontWeight: { '': '400', '@dark': '300' }\n */\nexport type TypographyTokenValue =\n | string\n | number\n | Record<string, string | number | undefined | null | '@inherit'>;\n\n/**\n * Typography preset configuration.\n * Each preset defines font properties that get expanded into CSS custom properties.\n * All fields accept plain values or state maps for responsive/theme-aware tokens.\n *\n * Use with `generateTypographyTokens()` to create typography tokens for your design system.\n */\nexport interface TypographyPreset {\n fontSize: TypographyTokenValue;\n lineHeight: TypographyTokenValue;\n letterSpacing?: TypographyTokenValue;\n fontWeight: TypographyTokenValue;\n boldFontWeight?: TypographyTokenValue;\n iconSize?: TypographyTokenValue;\n textTransform?: TypographyTokenValue;\n fontFamily?: TypographyTokenValue;\n fontStyle?: TypographyTokenValue;\n}\n\n/**\n * Generate typography tokens with $ prefix for CSS custom properties.\n *\n * Each preset generates the following CSS custom properties:\n * - `${name}-font-size`\n * - `${name}-line-height`\n * - `${name}-letter-spacing`\n * - `${name}-font-weight`\n * - `${name}-bold-font-weight` (if defined)\n * - `${name}-icon-size` (if defined)\n * - `${name}-text-transform` (if defined)\n * - `${name}-font-family` (if defined)\n * - `${name}-font-style` (if defined)\n *\n * @param presets - Typography presets object\n * @returns ConfigTokens object with $ prefixed keys\n *\n * @example\n * const customTokens = generateTypographyTokens({\n * myHeading: { fontSize: '24px', lineHeight: '32px', fontWeight: '700' },\n * body: { fontSize: '16px', lineHeight: '24px', fontWeight: '400' },\n * });\n */\nexport function generateTypographyTokens(\n presets: Record<string, TypographyPreset>,\n): ConfigTokens {\n const tokens: ConfigTokens = {} as ConfigTokens;\n\n for (const [name, preset] of Object.entries(presets)) {\n if (RESERVED_PRESET_NAMES.has(name)) {\n throw new Error(\n `Invalid typography preset name \"${name}\". This name is reserved as a preset modifier.`,\n );\n }\n\n tokens[`$${name}-font-size`] = preset.fontSize;\n tokens[`$${name}-line-height`] = preset.lineHeight;\n tokens[`$${name}-letter-spacing`] = preset.letterSpacing ?? 'normal';\n tokens[`$${name}-font-weight`] = preset.fontWeight;\n\n if (preset.boldFontWeight !== undefined) {\n tokens[`$${name}-bold-font-weight`] = preset.boldFontWeight;\n }\n\n if (preset.iconSize !== undefined) {\n tokens[`$${name}-icon-size`] = preset.iconSize;\n }\n\n if (preset.textTransform !== undefined) {\n tokens[`$${name}-text-transform`] = preset.textTransform;\n }\n\n if (preset.fontFamily !== undefined) {\n tokens[`$${name}-font-family`] = preset.fontFamily;\n }\n\n if (preset.fontStyle !== undefined) {\n tokens[`$${name}-font-style`] = preset.fontStyle;\n }\n }\n\n return tokens;\n}\n","/**\n * Configuration processing shared by runtime and build-time paths.\n *\n * Plugins are folded first and direct configuration wins. Keeping this step\n * independent from the DOM injector lets zero-runtime tooling reuse the exact\n * same precedence and style-engine setup without loading browser infrastructure.\n */\n\nimport { registerFunctionPolyfill, splitFunctions } from './functions';\nimport {\n isFunctionsPolyfillEnabled,\n setGlobalPolyfillsState,\n} from './config-state';\nimport { setGlobalPredefinedStates } from './states';\nimport {\n normalizeHandlerDefinition,\n registerHandler,\n} from './styles/predefined';\nimport {\n CUSTOM_UNITS,\n getGlobalParseFunctions,\n getGlobalParser,\n normalizeColorTokenValue,\n setGlobalPredefinedTokens,\n} from './utils/styles';\nimport { generateTypographyTokens } from './utils/typography';\n\nimport type { TastyConfig } from './config';\nimport type { FunctionsConfig } from './functions';\nimport type {\n CounterStyleDescriptors,\n FontFaceInput,\n FunctionDefinition,\n KeyframesSteps,\n PropertyDefinition,\n} from './injector/types';\nimport type { UnitHandler } from './parser/types';\nimport type { PropHandlerDefinition } from './prop-handlers';\nimport type { ConfigTokens, RecipeStyles, Styles } from './styles/types';\nimport type { StyleHandlerDefinition } from './utils/styles';\nimport type { TypographyPreset } from './utils/typography';\n\nexport interface NormalizedConfig {\n states: Record<string, string>;\n units: Record<string, string | UnitHandler>;\n functions: FunctionsConfig;\n handlers: Record<string, StyleHandlerDefinition>;\n handlerSources: Map<string, string>;\n propHandlers: Record<string, PropHandlerDefinition>;\n propHandlerSources: Map<string, string>;\n baseStyleProps: string[];\n properties: Record<string, PropertyDefinition>;\n keyframes: Record<string, KeyframesSteps>;\n fontFaces: Record<string, FontFaceInput>;\n counterStyles: Record<string, CounterStyleDescriptors>;\n replaceTokens: Record<string, string | number | boolean>;\n tokens: ConfigTokens;\n recipes: Record<string, RecipeStyles>;\n globalStyles: Record<string, Styles>;\n}\n\ntype WarnOnce = (key: string, message: string) => void;\n\n/** Apply parser and style-engine configuration shared by every renderer. */\nexport function applyStyleConfig(\n config: Partial<TastyConfig>,\n normalized: NormalizedConfig,\n warnOnce: WarnOnce,\n): Record<string, FunctionDefinition> {\n const tokenKeys = new Set(Object.keys(normalized.tokens));\n for (const key of Object.keys(normalized.replaceTokens)) {\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 if (config.colorSpace) {\n warnOnce(\n 'colorSpace-deprecated',\n '[Tasty] configure({ colorSpace }) no longer has any effect and will be ' +\n 'removed in the next major. Colors are emitted as authored, and opacity ' +\n \"is applied with relative color syntax, which reads a color's channels \" +\n 'in the browser. To address channels yourself, write ' +\n '`oklch(from var(--name-color) l c h)` against the token.',\n );\n }\n\n if (Object.keys(normalized.states).length > 0) {\n setGlobalPredefinedStates(normalized.states);\n }\n\n const parser = getGlobalParser();\n if (config.parserCacheSize !== undefined) {\n parser.updateOptions({ cacheSize: config.parserCacheSize });\n }\n if (Object.keys(normalized.units).length > 0) {\n const currentUnits = parser.getUnits() ?? CUSTOM_UNITS;\n parser.setUnits({ ...currentUnits, ...normalized.units });\n }\n\n if (config.polyfills) setGlobalPolyfillsState(config.polyfills);\n\n const { parseFuncs, functionDefs } = splitFunctions(\n normalized.functions,\n (key, kind) => {\n warnOnce(\n `functions-mismatch-${key}`,\n kind === 'expected-definition'\n ? `[Tasty] functions[\"${key}\"]: a \"$$\"-prefixed key denotes a CSS @function ` +\n `and expects a definition object, but received a function. Entry ignored.`\n : `[Tasty] functions[\"${key}\"]: a bare key denotes a parse function and ` +\n `expects a function value, but received an object. ` +\n `Did you mean \"$$${key}\"? Entry ignored.`,\n );\n },\n );\n\n if (Object.keys(parseFuncs).length > 0) {\n const currentFuncs = getGlobalParseFunctions();\n parser.setFunctions({ ...currentFuncs, ...parseFuncs });\n Object.assign(currentFuncs, parseFuncs);\n }\n\n if (isFunctionsPolyfillEnabled()) {\n for (const [name, definition] of Object.entries(functionDefs)) {\n registerFunctionPolyfill(name, definition);\n }\n }\n\n for (const [name, definition] of Object.entries(normalized.handlers)) {\n const handler = normalizeHandlerDefinition(name, definition);\n registerHandler(handler, {\n key: name,\n source: normalized.handlerSources.get(name),\n });\n }\n\n if (Object.keys(normalized.replaceTokens).length > 0) {\n const processedTokens: Record<string, string> = {};\n for (const [key, value] of Object.entries(normalized.replaceTokens)) {\n if (key.startsWith('#')) {\n const normalizedValue = normalizeColorTokenValue(value);\n if (normalizedValue === null) continue;\n processedTokens[key] = String(normalizedValue);\n } else if (value !== false) {\n processedTokens[key] = String(value);\n }\n }\n setGlobalPredefinedTokens(processedTokens);\n }\n\n return functionDefs;\n}\n\n/** Merge an optional configuration record into an accumulated record. */\nfunction mergeRecord<T extends object>(target: T, source?: Partial<T>): T {\n return source ? { ...target, ...source } : target;\n}\n\n/** Merge a named extension record and retain where each winning entry came from. */\nfunction mergeSourcedRecord<T>(\n target: Record<string, T>,\n source: Record<string, T> | undefined,\n sources: Map<string, string>,\n pluginName?: string,\n): Record<string, T> {\n if (!source) return target;\n\n const label =\n pluginName === undefined ? 'configure()' : `plugin \"${pluginName}\"`;\n for (const key of Object.keys(source)) sources.set(key, label);\n\n return { ...target, ...source };\n}\n\nexport function normalizeConfig(\n config: Partial<TastyConfig>,\n): NormalizedConfig {\n let states: Record<string, string> = {};\n let units: Record<string, string | UnitHandler> = {};\n let functions: FunctionsConfig = {};\n let handlers: Record<string, StyleHandlerDefinition> = {};\n const handlerSources = new Map<string, string>();\n let propHandlers: Record<string, PropHandlerDefinition> = {};\n const propHandlerSources = new Map<string, string>();\n const baseStyleProps: string[] = [];\n let properties: Record<string, PropertyDefinition> = {};\n let keyframes: Record<string, KeyframesSteps> = {};\n let fontFaces: Record<string, FontFaceInput> = {};\n let counterStyles: Record<string, CounterStyleDescriptors> = {};\n let replaceTokens: Record<string, string | number | boolean> = {};\n let tokens: ConfigTokens = {} as ConfigTokens;\n let recipes: Record<string, RecipeStyles> = {};\n let presets: Record<string, TypographyPreset> = {};\n const globalStyles: Record<string, Styles> = {};\n\n for (const plugin of config.plugins ?? []) {\n states = mergeRecord(states, plugin.states);\n units = mergeRecord(units, plugin.units);\n functions = mergeRecord(functions, plugin.functions);\n handlers = mergeSourcedRecord(\n handlers,\n plugin.handlers,\n handlerSources,\n plugin.name,\n );\n propHandlers = mergeSourcedRecord(\n propHandlers,\n plugin.propHandlers,\n propHandlerSources,\n plugin.name,\n );\n if (plugin.baseStyleProps) baseStyleProps.push(...plugin.baseStyleProps);\n properties = mergeRecord(properties, plugin.properties);\n keyframes = mergeRecord(keyframes, plugin.keyframes);\n fontFaces = mergeRecord(fontFaces, plugin.fontFaces);\n counterStyles = mergeRecord(counterStyles, plugin.counterStyles);\n replaceTokens = mergeRecord(replaceTokens, plugin.replaceTokens);\n tokens = mergeRecord(tokens, plugin.tokens);\n recipes = mergeRecord(recipes, plugin.recipes);\n presets = mergeRecord(presets, plugin.presets);\n mergeGlobalStyles(globalStyles, plugin.globalStyles);\n }\n\n states = mergeRecord(states, config.states);\n units = mergeRecord(units, config.units);\n functions = mergeRecord(functions, config.functions);\n handlers = mergeSourcedRecord(handlers, config.handlers, handlerSources);\n propHandlers = mergeSourcedRecord(\n propHandlers,\n config.propHandlers,\n propHandlerSources,\n );\n if (config.baseStyleProps) baseStyleProps.push(...config.baseStyleProps);\n properties = mergeRecord(properties, config.properties);\n keyframes = mergeRecord(keyframes, config.keyframes);\n fontFaces = mergeRecord(fontFaces, config.fontFaces);\n counterStyles = mergeRecord(counterStyles, config.counterStyles);\n replaceTokens = mergeRecord(replaceTokens, config.replaceTokens);\n presets = mergeRecord(presets, config.presets);\n\n if (Object.keys(presets).length > 0) {\n tokens = { ...generateTypographyTokens(presets), ...tokens };\n }\n\n tokens = mergeRecord(tokens, config.tokens);\n recipes = mergeRecord(recipes, config.recipes);\n mergeGlobalStyles(globalStyles, config.globalStyles);\n\n return {\n states,\n units,\n functions,\n handlers,\n handlerSources,\n propHandlers,\n propHandlerSources,\n baseStyleProps,\n properties,\n keyframes,\n fontFaces,\n counterStyles,\n replaceTokens,\n tokens,\n recipes,\n globalStyles,\n };\n}\n\nfunction mergeGlobalStyles(\n target: Record<string, Styles>,\n source?: Record<string, Styles>,\n): void {\n if (!source) return;\n\n for (const [selector, styles] of Object.entries(source)) {\n target[selector] = target[selector]\n ? { ...target[selector], ...styles }\n : styles;\n }\n}\n","/**\n * Recipe resolution utility.\n *\n * Resolves `recipe` style properties by looking up predefined recipe styles\n * from global configuration and merging them with the component's own styles.\n *\n * Resolution order per level (top-level and each sub-element independently):\n * base_recipe_1 base_recipe_2 → component styles → post_recipe_1 post_recipe_2\n *\n * The `/` separator splits base recipes (before component styles)\n * from post recipes (after component styles). All merges use mergeStyles\n * semantics: primitives and state maps with '' key fully replace;\n * state maps without '' key extend the existing value.\n *\n * Returns the same object reference if no recipes are present (zero overhead).\n */\n\nimport type { RecipeStyles, Styles } from '../styles/types';\n\nimport { isDevEnv } from './is-dev-env';\nimport { isSelector } from './is-selector';\nimport { mergeStyles } from './merge-styles';\n\nconst devMode = isDevEnv();\n\ninterface ParsedRecipeGroups {\n base: string[] | null;\n post: string[] | null;\n}\n\n/**\n * Parse a recipe string into base and post recipe name groups.\n *\n * Syntax: `'base1 base2 / post1 post2'`\n * - Names are space-separated within each group\n * - `/` separates base (before component) from post (after component) groups\n * - `/` is optional; if absent, all names are base\n * - `none` as the sole base value means \"no base recipes\"\n *\n * Returns `{ base: null, post: null }` if the string is empty or invalid.\n */\nfunction parseRecipeNames(value: unknown): ParsedRecipeGroups {\n const empty: ParsedRecipeGroups = { base: null, post: null };\n\n if (typeof value !== 'string') return empty;\n const trimmed = value.trim();\n if (trimmed === '') return empty;\n\n const slashIndex = trimmed.indexOf('/');\n\n if (slashIndex === -1) {\n if (trimmed === 'none') return empty;\n const names = splitNames(trimmed);\n return { base: names, post: null };\n }\n\n const basePart = trimmed.slice(0, slashIndex);\n const postPart = trimmed.slice(slashIndex + 1);\n\n return {\n base: basePart.trim() === 'none' ? null : splitNames(basePart),\n post: splitNames(postPart),\n };\n}\n\nfunction splitNames(s: string): string[] | null {\n const names = s.split(/\\s+/).filter(Boolean);\n return names.length > 0 ? names : null;\n}\n\n/**\n * Collect merged styles for a list of recipe names.\n * Each recipe is flat-spread on top of the previous.\n */\nfunction collectRecipeStyles(\n names: string[],\n recipes: Record<string, RecipeStyles>,\n): Record<string, unknown> {\n let merged: Record<string, unknown> = {};\n\n for (const name of names) {\n const recipeStyles = recipes[name];\n\n if (!recipeStyles) {\n if (devMode) {\n console.warn(\n `[Tasty] Recipe \"${name}\" not found. ` +\n `Make sure it is defined in configure({ recipes: { ... } }).`,\n );\n }\n continue;\n }\n\n merged = { ...merged, ...(recipeStyles as Record<string, unknown>) };\n }\n\n return merged;\n}\n\n/**\n * Resolve recipe references in a flat styles object (no sub-elements).\n * Returns null if no `recipe` key is present.\n *\n * Resolution: base recipes → component styles → post recipes (all via mergeStyles)\n */\nfunction resolveRecipesForLevel(\n styles: Record<string, unknown>,\n recipes: Record<string, RecipeStyles>,\n): Record<string, unknown> | null {\n if (!('recipe' in styles)) return null;\n\n const { base, post } = parseRecipeNames(styles.recipe);\n\n // Separate selector keys (sub-elements) from flat style properties.\n // mergeStyles handles selectors with its own semantics (e.g. false = delete),\n // but at this level we only want recipe merging on flat properties.\n\n const { recipe: _recipe, ...allRest } = styles;\n const flatStyles: Record<string, unknown> = {};\n const selectorStyles: Record<string, unknown> = {};\n\n for (const key of Object.keys(allRest)) {\n if (isSelector(key)) {\n selectorStyles[key] = allRest[key];\n } else {\n flatStyles[key] = allRest[key];\n }\n }\n\n if (!base && !post) {\n return allRest;\n }\n\n // 1. Merge base recipes, then component styles on top (via mergeStyles)\n let result: Record<string, unknown>;\n\n if (base) {\n const baseStyles = collectRecipeStyles(base, recipes);\n result = mergeStyles(baseStyles as Styles, flatStyles as Styles) as Record<\n string,\n unknown\n >;\n } else {\n result = { ...flatStyles };\n }\n\n // 2. Apply post recipes via mergeStyles (state map extend semantics)\n if (post) {\n const postStyles = collectRecipeStyles(post, recipes);\n result = mergeStyles(result as Styles, postStyles as Styles) as Record<\n string,\n unknown\n >;\n }\n\n // Re-attach selector keys unchanged\n for (const key of Object.keys(selectorStyles)) {\n result[key] = selectorStyles[key];\n }\n\n return result;\n}\n\n/**\n * Resolve all `recipe` style properties in a styles object.\n *\n * Handles both top-level and sub-element recipe references.\n * Returns the same object reference if no recipes are present anywhere\n * (zero overhead for the common case).\n *\n * @param styles - The styles object potentially containing `recipe` keys\n * @returns Resolved styles with recipe values merged in, or the original object if unchanged\n */\nexport function resolveRecipesWith(\n styles: Styles,\n recipes: Record<string, RecipeStyles> | null,\n): Styles {\n // Fast path: no recipes configured\n if (!recipes) return styles;\n\n let changed = false;\n\n // Resolve top-level recipe\n const topResolved = resolveRecipesForLevel(\n styles as Record<string, unknown>,\n recipes,\n );\n\n let result: Record<string, unknown>;\n\n if (topResolved) {\n changed = true;\n result = topResolved;\n } else {\n // Keep reference; a shallow copy is deferred until a sub-element actually changes\n result = styles as Record<string, unknown>;\n }\n\n // Resolve sub-element recipes\n const keys = Object.keys(result);\n\n for (const key of keys) {\n if (!isSelector(key)) continue;\n\n const subStyles = result[key];\n\n if (\n !subStyles ||\n typeof subStyles !== 'object' ||\n Array.isArray(subStyles)\n ) {\n continue;\n }\n\n const subRecord = subStyles as Record<string, unknown>;\n\n if (!('recipe' in subRecord)) continue;\n\n const subResolved = resolveRecipesForLevel(subRecord, recipes);\n\n if (subResolved) {\n if (!changed) {\n // First change in sub-elements -- need to shallow-copy the top level\n changed = true;\n result = { ...(styles as Record<string, unknown>) };\n }\n // Define an own data property so even an untrusted key cannot invoke an\n // inherited setter such as Object.prototype.__proto__.\n Object.defineProperty(result, key, {\n configurable: true,\n enumerable: true,\n value: subResolved,\n writable: true,\n });\n }\n }\n\n return changed ? (result as Styles) : styles;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config-engine-DJsb5WYu.js","names":[],"sources":["../../src/utils/typography.ts","../../src/config-normalize.ts","../../src/utils/resolve-recipes-core.ts"],"sourcesContent":["import type { ConfigTokens } from '../styles/types';\n\nconst RESERVED_PRESET_NAMES = new Set([\n 'strong',\n 'bold',\n 'italic',\n 'icon',\n 'tight',\n]);\n\n/**\n * A typography token value: plain value or a state map for responsive/theme-aware presets.\n *\n * @example\n * // Plain value\n * fontWeight: '400'\n * // State map\n * fontWeight: { '': '400', '@dark': '300' }\n */\nexport type TypographyTokenValue =\n | string\n | number\n | Record<string, string | number | undefined | null | '@inherit'>;\n\n/**\n * Typography preset configuration.\n * Each preset defines font properties that get expanded into CSS custom properties.\n * All fields accept plain values or state maps for responsive/theme-aware tokens.\n *\n * Use with `generateTypographyTokens()` to create typography tokens for your design system.\n */\nexport interface TypographyPreset {\n fontSize: TypographyTokenValue;\n lineHeight: TypographyTokenValue;\n letterSpacing?: TypographyTokenValue;\n fontWeight: TypographyTokenValue;\n boldFontWeight?: TypographyTokenValue;\n iconSize?: TypographyTokenValue;\n textTransform?: TypographyTokenValue;\n fontFamily?: TypographyTokenValue;\n fontStyle?: TypographyTokenValue;\n}\n\n/**\n * Generate typography tokens with $ prefix for CSS custom properties.\n *\n * Each preset generates the following CSS custom properties:\n * - `${name}-font-size`\n * - `${name}-line-height`\n * - `${name}-letter-spacing`\n * - `${name}-font-weight`\n * - `${name}-bold-font-weight` (if defined)\n * - `${name}-icon-size` (if defined)\n * - `${name}-text-transform` (if defined)\n * - `${name}-font-family` (if defined)\n * - `${name}-font-style` (if defined)\n *\n * @param presets - Typography presets object\n * @returns ConfigTokens object with $ prefixed keys\n *\n * @example\n * const customTokens = generateTypographyTokens({\n * myHeading: { fontSize: '24px', lineHeight: '32px', fontWeight: '700' },\n * body: { fontSize: '16px', lineHeight: '24px', fontWeight: '400' },\n * });\n */\nexport function generateTypographyTokens(\n presets: Record<string, TypographyPreset>,\n): ConfigTokens {\n const tokens: ConfigTokens = {} as ConfigTokens;\n\n for (const [name, preset] of Object.entries(presets)) {\n if (RESERVED_PRESET_NAMES.has(name)) {\n throw new Error(\n `Invalid typography preset name \"${name}\". This name is reserved as a preset modifier.`,\n );\n }\n\n tokens[`$${name}-font-size`] = preset.fontSize;\n tokens[`$${name}-line-height`] = preset.lineHeight;\n tokens[`$${name}-letter-spacing`] = preset.letterSpacing ?? 'normal';\n tokens[`$${name}-font-weight`] = preset.fontWeight;\n\n if (preset.boldFontWeight !== undefined) {\n tokens[`$${name}-bold-font-weight`] = preset.boldFontWeight;\n }\n\n if (preset.iconSize !== undefined) {\n tokens[`$${name}-icon-size`] = preset.iconSize;\n }\n\n if (preset.textTransform !== undefined) {\n tokens[`$${name}-text-transform`] = preset.textTransform;\n }\n\n if (preset.fontFamily !== undefined) {\n tokens[`$${name}-font-family`] = preset.fontFamily;\n }\n\n if (preset.fontStyle !== undefined) {\n tokens[`$${name}-font-style`] = preset.fontStyle;\n }\n }\n\n return tokens;\n}\n","/**\n * Configuration processing shared by runtime and build-time paths.\n *\n * Plugins are folded first and direct configuration wins. Keeping this step\n * independent from the DOM injector lets zero-runtime tooling reuse the exact\n * same precedence and style-engine setup without loading browser infrastructure.\n */\n\nimport { registerFunctionPolyfill, splitFunctions } from './functions';\nimport {\n isFunctionsPolyfillEnabled,\n setGlobalPolyfillsState,\n} from './config-state';\nimport { setGlobalPredefinedStates } from './states';\nimport {\n normalizeHandlerDefinition,\n registerHandler,\n} from './styles/predefined';\nimport {\n CUSTOM_UNITS,\n getGlobalParseFunctions,\n getGlobalParser,\n normalizeColorTokenValue,\n setGlobalPredefinedTokens,\n} from './utils/styles';\nimport { generateTypographyTokens } from './utils/typography';\n\nimport type { TastyConfig } from './config';\nimport type { FunctionsConfig } from './functions';\nimport type {\n CounterStyleDescriptors,\n FontFaceInput,\n FunctionDefinition,\n KeyframesSteps,\n PropertyDefinition,\n} from './injector/types';\nimport type { UnitHandler } from './parser/types';\nimport type { PropHandlerDefinition } from './prop-handlers';\nimport type { ConfigTokens, RecipeStyles, Styles } from './styles/types';\nimport type { StyleHandlerDefinition } from './utils/styles';\nimport type { TypographyPreset } from './utils/typography';\n\nexport interface NormalizedConfig {\n states: Record<string, string>;\n units: Record<string, string | UnitHandler>;\n functions: FunctionsConfig;\n handlers: Record<string, StyleHandlerDefinition>;\n handlerSources: Map<string, string>;\n propHandlers: Record<string, PropHandlerDefinition>;\n propHandlerSources: Map<string, string>;\n baseStyleProps: string[];\n properties: Record<string, PropertyDefinition>;\n keyframes: Record<string, KeyframesSteps>;\n fontFaces: Record<string, FontFaceInput>;\n counterStyles: Record<string, CounterStyleDescriptors>;\n replaceTokens: Record<string, string | number | boolean>;\n tokens: ConfigTokens;\n recipes: Record<string, RecipeStyles>;\n globalStyles: Record<string, Styles>;\n}\n\ntype WarnOnce = (key: string, message: string) => void;\n\n/** Apply parser and style-engine configuration shared by every renderer. */\nexport function applyStyleConfig(\n config: Partial<TastyConfig>,\n normalized: NormalizedConfig,\n warnOnce: WarnOnce,\n): Record<string, FunctionDefinition> {\n const tokenKeys = new Set(Object.keys(normalized.tokens));\n for (const key of Object.keys(normalized.replaceTokens)) {\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 if (config.colorSpace) {\n warnOnce(\n 'colorSpace-deprecated',\n '[Tasty] configure({ colorSpace }) no longer has any effect and will be ' +\n 'removed in the next major. Colors are emitted as authored, and opacity ' +\n \"is applied with relative color syntax, which reads a color's channels \" +\n 'in the browser. To address channels yourself, write ' +\n '`oklch(from var(--name-color) l c h)` against the token.',\n );\n }\n\n if (Object.keys(normalized.states).length > 0) {\n setGlobalPredefinedStates(normalized.states);\n }\n\n const parser = getGlobalParser();\n if (config.parserCacheSize !== undefined) {\n parser.updateOptions({ cacheSize: config.parserCacheSize });\n }\n if (Object.keys(normalized.units).length > 0) {\n const currentUnits = parser.getUnits() ?? CUSTOM_UNITS;\n parser.setUnits({ ...currentUnits, ...normalized.units });\n }\n\n if (config.polyfills) setGlobalPolyfillsState(config.polyfills);\n\n const { parseFuncs, functionDefs } = splitFunctions(\n normalized.functions,\n (key, kind) => {\n warnOnce(\n `functions-mismatch-${key}`,\n kind === 'expected-definition'\n ? `[Tasty] functions[\"${key}\"]: a \"$$\"-prefixed key denotes a CSS @function ` +\n `and expects a definition object, but received a function. Entry ignored.`\n : `[Tasty] functions[\"${key}\"]: a bare key denotes a parse function and ` +\n `expects a function value, but received an object. ` +\n `Did you mean \"$$${key}\"? Entry ignored.`,\n );\n },\n );\n\n if (Object.keys(parseFuncs).length > 0) {\n const currentFuncs = getGlobalParseFunctions();\n parser.setFunctions({ ...currentFuncs, ...parseFuncs });\n Object.assign(currentFuncs, parseFuncs);\n }\n\n if (isFunctionsPolyfillEnabled()) {\n for (const [name, definition] of Object.entries(functionDefs)) {\n registerFunctionPolyfill(name, definition);\n }\n }\n\n for (const [name, definition] of Object.entries(normalized.handlers)) {\n const handler = normalizeHandlerDefinition(name, definition);\n registerHandler(handler, {\n key: name,\n source: normalized.handlerSources.get(name),\n });\n }\n\n if (Object.keys(normalized.replaceTokens).length > 0) {\n const processedTokens: Record<string, string> = {};\n for (const [key, value] of Object.entries(normalized.replaceTokens)) {\n if (key.startsWith('#')) {\n const normalizedValue = normalizeColorTokenValue(value);\n if (normalizedValue === null) continue;\n processedTokens[key] = String(normalizedValue);\n } else if (value !== false) {\n processedTokens[key] = String(value);\n }\n }\n setGlobalPredefinedTokens(processedTokens);\n }\n\n return functionDefs;\n}\n\n/** Merge an optional configuration record into an accumulated record. */\nfunction mergeRecord<T extends object>(target: T, source?: Partial<T>): T {\n return source ? { ...target, ...source } : target;\n}\n\n/** Merge a named extension record and retain where each winning entry came from. */\nfunction mergeSourcedRecord<T>(\n target: Record<string, T>,\n source: Record<string, T> | undefined,\n sources: Map<string, string>,\n pluginName?: string,\n): Record<string, T> {\n if (!source) return target;\n\n const label =\n pluginName === undefined ? 'configure()' : `plugin \"${pluginName}\"`;\n for (const key of Object.keys(source)) sources.set(key, label);\n\n return { ...target, ...source };\n}\n\nexport function normalizeConfig(\n config: Partial<TastyConfig>,\n): NormalizedConfig {\n let states: Record<string, string> = {};\n let units: Record<string, string | UnitHandler> = {};\n let functions: FunctionsConfig = {};\n let handlers: Record<string, StyleHandlerDefinition> = {};\n const handlerSources = new Map<string, string>();\n let propHandlers: Record<string, PropHandlerDefinition> = {};\n const propHandlerSources = new Map<string, string>();\n const baseStyleProps: string[] = [];\n let properties: Record<string, PropertyDefinition> = {};\n let keyframes: Record<string, KeyframesSteps> = {};\n let fontFaces: Record<string, FontFaceInput> = {};\n let counterStyles: Record<string, CounterStyleDescriptors> = {};\n let replaceTokens: Record<string, string | number | boolean> = {};\n let tokens: ConfigTokens = {} as ConfigTokens;\n let recipes: Record<string, RecipeStyles> = {};\n let presets: Record<string, TypographyPreset> = {};\n const globalStyles: Record<string, Styles> = {};\n\n for (const plugin of config.plugins ?? []) {\n states = mergeRecord(states, plugin.states);\n units = mergeRecord(units, plugin.units);\n functions = mergeRecord(functions, plugin.functions);\n handlers = mergeSourcedRecord(\n handlers,\n plugin.handlers,\n handlerSources,\n plugin.name,\n );\n propHandlers = mergeSourcedRecord(\n propHandlers,\n plugin.propHandlers,\n propHandlerSources,\n plugin.name,\n );\n if (plugin.baseStyleProps) baseStyleProps.push(...plugin.baseStyleProps);\n properties = mergeRecord(properties, plugin.properties);\n keyframes = mergeRecord(keyframes, plugin.keyframes);\n fontFaces = mergeRecord(fontFaces, plugin.fontFaces);\n counterStyles = mergeRecord(counterStyles, plugin.counterStyles);\n replaceTokens = mergeRecord(replaceTokens, plugin.replaceTokens);\n tokens = mergeRecord(tokens, plugin.tokens);\n recipes = mergeRecord(recipes, plugin.recipes);\n presets = mergeRecord(presets, plugin.presets);\n mergeGlobalStyles(globalStyles, plugin.globalStyles);\n }\n\n states = mergeRecord(states, config.states);\n units = mergeRecord(units, config.units);\n functions = mergeRecord(functions, config.functions);\n handlers = mergeSourcedRecord(handlers, config.handlers, handlerSources);\n propHandlers = mergeSourcedRecord(\n propHandlers,\n config.propHandlers,\n propHandlerSources,\n );\n if (config.baseStyleProps) baseStyleProps.push(...config.baseStyleProps);\n properties = mergeRecord(properties, config.properties);\n keyframes = mergeRecord(keyframes, config.keyframes);\n fontFaces = mergeRecord(fontFaces, config.fontFaces);\n counterStyles = mergeRecord(counterStyles, config.counterStyles);\n replaceTokens = mergeRecord(replaceTokens, config.replaceTokens);\n presets = mergeRecord(presets, config.presets);\n\n if (Object.keys(presets).length > 0) {\n tokens = { ...generateTypographyTokens(presets), ...tokens };\n }\n\n tokens = mergeRecord(tokens, config.tokens);\n recipes = mergeRecord(recipes, config.recipes);\n mergeGlobalStyles(globalStyles, config.globalStyles);\n\n return {\n states,\n units,\n functions,\n handlers,\n handlerSources,\n propHandlers,\n propHandlerSources,\n baseStyleProps,\n properties,\n keyframes,\n fontFaces,\n counterStyles,\n replaceTokens,\n tokens,\n recipes,\n globalStyles,\n };\n}\n\nfunction mergeGlobalStyles(\n target: Record<string, Styles>,\n source?: Record<string, Styles>,\n): void {\n if (!source) return;\n\n for (const [selector, styles] of Object.entries(source)) {\n target[selector] = target[selector]\n ? { ...target[selector], ...styles }\n : styles;\n }\n}\n","/**\n * Recipe resolution utility.\n *\n * Resolves `recipe` style properties by looking up predefined recipe styles\n * from global configuration and merging them with the component's own styles.\n *\n * Resolution order per level (top-level and each sub-element independently):\n * base_recipe_1 base_recipe_2 → component styles → post_recipe_1 post_recipe_2\n *\n * The `/` separator splits base recipes (before component styles)\n * from post recipes (after component styles). All merges use mergeStyles\n * semantics: primitives and state maps with '' key fully replace;\n * state maps without '' key extend the existing value.\n *\n * Returns the same object reference if no recipes are present (zero overhead).\n */\n\nimport type { RecipeStyles, Styles } from '../styles/types';\n\nimport { isDevEnv } from './is-dev-env';\nimport { isSelector } from './is-selector';\nimport { mergeStyles } from './merge-styles';\n\nconst devMode = isDevEnv();\n\ninterface ParsedRecipeGroups {\n base: string[] | null;\n post: string[] | null;\n}\n\n/**\n * Parse a recipe string into base and post recipe name groups.\n *\n * Syntax: `'base1 base2 / post1 post2'`\n * - Names are space-separated within each group\n * - `/` separates base (before component) from post (after component) groups\n * - `/` is optional; if absent, all names are base\n * - `none` as the sole base value means \"no base recipes\"\n *\n * Returns `{ base: null, post: null }` if the string is empty or invalid.\n */\nfunction parseRecipeNames(value: unknown): ParsedRecipeGroups {\n const empty: ParsedRecipeGroups = { base: null, post: null };\n\n if (typeof value !== 'string') return empty;\n const trimmed = value.trim();\n if (trimmed === '') return empty;\n\n const slashIndex = trimmed.indexOf('/');\n\n if (slashIndex === -1) {\n if (trimmed === 'none') return empty;\n const names = splitNames(trimmed);\n return { base: names, post: null };\n }\n\n const basePart = trimmed.slice(0, slashIndex);\n const postPart = trimmed.slice(slashIndex + 1);\n\n return {\n base: basePart.trim() === 'none' ? null : splitNames(basePart),\n post: splitNames(postPart),\n };\n}\n\nfunction splitNames(s: string): string[] | null {\n const names = s.split(/\\s+/).filter(Boolean);\n return names.length > 0 ? names : null;\n}\n\n/**\n * Collect merged styles for a list of recipe names.\n * Each recipe is flat-spread on top of the previous.\n */\nfunction collectRecipeStyles(\n names: string[],\n recipes: Record<string, RecipeStyles>,\n): Record<string, unknown> {\n let merged: Record<string, unknown> = {};\n\n for (const name of names) {\n const recipeStyles = recipes[name];\n\n if (!recipeStyles) {\n if (devMode) {\n console.warn(\n `[Tasty] Recipe \"${name}\" not found. ` +\n `Make sure it is defined in configure({ recipes: { ... } }).`,\n );\n }\n continue;\n }\n\n merged = { ...merged, ...(recipeStyles as Record<string, unknown>) };\n }\n\n return merged;\n}\n\n/**\n * Resolve recipe references in a flat styles object (no sub-elements).\n * Returns null if no `recipe` key is present.\n *\n * Resolution: base recipes → component styles → post recipes (all via mergeStyles)\n */\nfunction resolveRecipesForLevel(\n styles: Record<string, unknown>,\n recipes: Record<string, RecipeStyles>,\n): Record<string, unknown> | null {\n if (!('recipe' in styles)) return null;\n\n const { base, post } = parseRecipeNames(styles.recipe);\n\n // Separate selector keys (sub-elements) from flat style properties.\n // mergeStyles handles selectors with its own semantics (e.g. false = delete),\n // but at this level we only want recipe merging on flat properties.\n\n const { recipe: _recipe, ...allRest } = styles;\n const flatStyles: Record<string, unknown> = {};\n const selectorStyles: Record<string, unknown> = {};\n\n for (const key of Object.keys(allRest)) {\n if (isSelector(key)) {\n selectorStyles[key] = allRest[key];\n } else {\n flatStyles[key] = allRest[key];\n }\n }\n\n if (!base && !post) {\n return allRest;\n }\n\n // 1. Merge base recipes, then component styles on top (via mergeStyles)\n let result: Record<string, unknown>;\n\n if (base) {\n const baseStyles = collectRecipeStyles(base, recipes);\n result = mergeStyles(baseStyles as Styles, flatStyles as Styles) as Record<\n string,\n unknown\n >;\n } else {\n result = { ...flatStyles };\n }\n\n // 2. Apply post recipes via mergeStyles (state map extend semantics)\n if (post) {\n const postStyles = collectRecipeStyles(post, recipes);\n result = mergeStyles(result as Styles, postStyles as Styles) as Record<\n string,\n unknown\n >;\n }\n\n // Re-attach selector keys unchanged\n for (const key of Object.keys(selectorStyles)) {\n result[key] = selectorStyles[key];\n }\n\n return result;\n}\n\n/**\n * Resolve all `recipe` style properties in a styles object.\n *\n * Handles both top-level and sub-element recipe references.\n * Returns the same object reference if no recipes are present anywhere\n * (zero overhead for the common case).\n *\n * @param styles - The styles object potentially containing `recipe` keys\n * @returns Resolved styles with recipe values merged in, or the original object if unchanged\n */\nexport function resolveRecipesWith(\n styles: Styles,\n recipes: Record<string, RecipeStyles> | null,\n): Styles {\n // Fast path: no recipes configured\n if (!recipes) return styles;\n\n let changed = false;\n\n // Resolve top-level recipe\n const topResolved = resolveRecipesForLevel(\n styles as Record<string, unknown>,\n recipes,\n );\n\n let result: Record<string, unknown>;\n\n if (topResolved) {\n changed = true;\n result = topResolved;\n } else {\n // Keep reference; a shallow copy is deferred until a sub-element actually changes\n result = styles as Record<string, unknown>;\n }\n\n // Resolve sub-element recipes\n const keys = Object.keys(result);\n\n for (const key of keys) {\n if (!isSelector(key)) continue;\n\n const subStyles = result[key];\n\n if (\n !subStyles ||\n typeof subStyles !== 'object' ||\n Array.isArray(subStyles)\n ) {\n continue;\n }\n\n const subRecord = subStyles as Record<string, unknown>;\n\n if (!('recipe' in subRecord)) continue;\n\n const subResolved = resolveRecipesForLevel(subRecord, recipes);\n\n if (subResolved) {\n if (!changed) {\n // First change in sub-elements -- need to shallow-copy the top level\n changed = true;\n result = { ...(styles as Record<string, unknown>) };\n }\n // Define an own data property so even an untrusted key cannot invoke an\n // inherited setter such as Object.prototype.__proto__.\n Object.defineProperty(result, key, {\n configurable: true,\n enumerable: true,\n value: subResolved,\n writable: true,\n });\n }\n }\n\n return changed ? (result as Styles) : styles;\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { F as RE_RAW_UNIT, P as RE_NUMBER, a as customFunction, f as parseStyle } from "./dsl-DYSJc1-T.js";
|
|
2
|
-
import { M as createStyle, T as STYLE_HANDLER_MAP, j as scanAnimationNames } from "./style-engine-
|
|
2
|
+
import { M as createStyle, T as STYLE_HANDLER_MAP, j as scanAnimationNames } from "./style-engine-of5Xbc27.js";
|
|
3
3
|
//#region src/functions/index.ts
|
|
4
4
|
const FUNCTION_KEY = "@function";
|
|
5
5
|
const RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -907,4 +907,4 @@ function createServerStyleArtifact(kind, key, css, order) {
|
|
|
907
907
|
//#endregion
|
|
908
908
|
export { rscClassRegexGlobal as A, parsePropertyToken as B, hasLocalFontFace as C, makeClassName as D, DEFAULT_ZERO_NAME_PREFIX as E, extractLocalProperties as F, hasLocalFunctions as G, formatFunctionDeclarations as H, getEffectiveDefinition as I, registerLocalFunctionPolyfills as J, parseFunctionName as K, hasLocalProperties as L, validateNamePrefix as M, hashString as N, makeCounterStyleName as O, DEFAULT_PROPERTIES as P, indexPropertiesByName as R, formatFontFaceRule as S, DEFAULT_NAME_PREFIX as T, formatFunctionPrelude as U, extractLocalFunctions as V, formatFunctionRule as W, splitFunctions as X, resetFunctionPolyfills as Y, formatCounterStyleRule as _, formatKeyframesSteps as a, fontFaceContentHash as b, extractLocalKeyframes as c, mergeKeyframes as d, replaceAnimationNames as f, formatCounterStyleDeclarations as g, extractLocalCounterStyle as h, formatKeyframesCSS as i, tastyClassRegex as j, makeKeyframeName as k, filterUsedKeyframes as l, resolveSelectorKeyframes as m, formatGlobalRules as n, formatPropertyCSS as o, resolveKeyframesNames as p, registerFunctionPolyfill as q, formatRules as r, extractAnimationNamesFromStyles as s, createServerStyleArtifact as t, hasLocalKeyframes as u, hasLocalCounterStyle as v, PropertyTypeResolver as w, formatFontFaceDeclarations as x, extractLocalFontFace as y, normalizePropertyDefinition as z };
|
|
909
909
|
|
|
910
|
-
//# sourceMappingURL=css-definitions-
|
|
910
|
+
//# sourceMappingURL=css-definitions-DW1TGGiy.js.map
|