@tenphi/tasty 0.0.0-snapshot.fdb16ea → 0.0.0-snapshot.fde6cf3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/astro-Dj8YpRd7.js +301 -0
  2. package/dist/astro-Dj8YpRd7.js.map +1 -0
  3. package/dist/{babel-CMYf4JZ2.d.ts → babel-Cbp2C2bj.d.ts} +2 -2
  4. package/dist/{collector-Ctn5s74s.d.ts → collector-DBY6liC2.d.ts} +94 -11
  5. package/dist/collector-NjmUiB8f.js +529 -0
  6. package/dist/collector-NjmUiB8f.js.map +1 -0
  7. package/dist/{config-B23gZrfP.js → config-Bd2vOF0Z.js} +454 -105
  8. package/dist/config-Bd2vOF0Z.js.map +1 -0
  9. package/dist/{config-CZx8_DCu.d.ts → config-CA7iAlEI.d.ts} +112 -22
  10. package/dist/core/index.d.ts +5 -5
  11. package/dist/core/index.js +6 -6
  12. package/dist/{core-B1tyn69d.js → core-ClInK6YG.js} +386 -107
  13. package/dist/core-ClInK6YG.js.map +1 -0
  14. package/dist/css-resources-Cyl_axbI.js +149 -0
  15. package/dist/css-resources-Cyl_axbI.js.map +1 -0
  16. package/dist/{css-writer-CvAxkR6S.js → css-writer-BDQXG9Jo.js} +3 -3
  17. package/dist/{css-writer-CvAxkR6S.js.map → css-writer-BDQXG9Jo.js.map} +1 -1
  18. package/dist/{format-rules-BCTWVvcS.js → format-rules-CGhgoVLR.js} +22 -32
  19. package/dist/format-rules-CGhgoVLR.js.map +1 -0
  20. package/dist/{hydrate-BCPvkJj3.js → hydrate-CqbxwVh_.js} +2 -2
  21. package/dist/{hydrate-BCPvkJj3.js.map → hydrate-CqbxwVh_.js.map} +1 -1
  22. package/dist/{index-B3o0aCYV.d.ts → index-C8RFYeFW.d.ts} +61 -12
  23. package/dist/{index-CsvB0EXZ.d.ts → index-FpYK0H5g.d.ts} +49 -8
  24. package/dist/index.d.ts +5 -5
  25. package/dist/index.js +43 -27
  26. package/dist/index.js.map +1 -1
  27. package/dist/{keyframes-Dxdx3KOo.js → keyframes-BjfNVhaB.js} +45 -3
  28. package/dist/keyframes-BjfNVhaB.js.map +1 -0
  29. package/dist/{merge-styles-DJTSfz_M.d.ts → merge-styles-BQv7d3fx.d.ts} +2 -2
  30. package/dist/{merge-styles-C-uwpoNW.js → merge-styles-BbJhjesV.js} +2 -2
  31. package/dist/{merge-styles-C-uwpoNW.js.map → merge-styles-BbJhjesV.js.map} +1 -1
  32. package/dist/precompile/index.d.ts +11 -0
  33. package/dist/precompile/index.js +72 -0
  34. package/dist/precompile/index.js.map +1 -0
  35. package/dist/precompile/register.d.ts +13 -0
  36. package/dist/precompile/register.js +2 -0
  37. package/dist/register-BkC-8Zuy.js +333 -0
  38. package/dist/register-BkC-8Zuy.js.map +1 -0
  39. package/dist/{resolve-recipes-BuOvSEa2.js → resolve-recipes-B2Sf36AH.js} +3 -3
  40. package/dist/{resolve-recipes-BuOvSEa2.js.map → resolve-recipes-B2Sf36AH.js.map} +1 -1
  41. package/dist/ssr/astro-client.js +1 -1
  42. package/dist/ssr/astro-middleware-extract-static.d.ts +11 -0
  43. package/dist/ssr/astro-middleware-extract-static.js +9 -0
  44. package/dist/ssr/astro-middleware-extract-static.js.map +1 -0
  45. package/dist/ssr/astro-middleware-extract.d.ts +11 -0
  46. package/dist/ssr/astro-middleware-extract.js +9 -0
  47. package/dist/ssr/astro-middleware-extract.js.map +1 -0
  48. package/dist/ssr/astro-middleware-static.d.ts +3 -1
  49. package/dist/ssr/astro-middleware-static.js +1 -1
  50. package/dist/ssr/astro-middleware.d.ts +3 -1
  51. package/dist/ssr/astro-middleware.js +1 -1
  52. package/dist/ssr/astro.d.ts +45 -3
  53. package/dist/ssr/astro.js +1 -156
  54. package/dist/ssr/index.d.ts +2 -2
  55. package/dist/ssr/index.js +3 -3
  56. package/dist/ssr/index.js.map +1 -1
  57. package/dist/ssr/next-config.d.ts +66 -0
  58. package/dist/ssr/next-config.js +115 -0
  59. package/dist/ssr/next-config.js.map +1 -0
  60. package/dist/ssr/next.d.ts +9 -2
  61. package/dist/ssr/next.js +26 -9
  62. package/dist/ssr/next.js.map +1 -1
  63. package/dist/ssr-collector-ref-COs_ioWl.js +29 -0
  64. package/dist/ssr-collector-ref-COs_ioWl.js.map +1 -0
  65. package/dist/static/index.d.ts +2 -2
  66. package/dist/static/index.js +1 -1
  67. package/dist/types-Bo5ePLZh.d.ts +111 -0
  68. package/dist/zero/babel.d.ts +1 -1
  69. package/dist/zero/babel.js +4 -4
  70. package/dist/zero/babel.js.map +1 -1
  71. package/dist/zero/index.d.ts +1 -1
  72. package/dist/zero/index.js +1 -1
  73. package/dist/zero/next.d.ts +1 -1
  74. package/docs/README.md +3 -1
  75. package/docs/debug.md +17 -6
  76. package/docs/injector.md +23 -3
  77. package/docs/precompile.md +202 -0
  78. package/docs/runtime-benchmarks.md +143 -72
  79. package/docs/ssr.md +179 -20
  80. package/package.json +44 -10
  81. package/dist/collector-DMSR6ANK.js +0 -304
  82. package/dist/collector-DMSR6ANK.js.map +0 -1
  83. package/dist/config-B23gZrfP.js.map +0 -1
  84. package/dist/core-B1tyn69d.js.map +0 -1
  85. package/dist/format-rules-BCTWVvcS.js.map +0 -1
  86. package/dist/keyframes-Dxdx3KOo.js.map +0 -1
  87. package/dist/ssr/astro.js.map +0 -1
@@ -1,7 +1,8 @@
1
- import { Bt as getGlobalParseFunctions, G as StyleInjector, Gt as parseStyle, It as registerLocalFunctionPolyfills, J as hasLocalCounterStyle, K as extractLocalCounterStyle, Mt as formatFunctionRule, Nt as hasLocalFunctions, Pt as parseFunctionName, Q as hasLocalFontFace, Qt as isDevEnv, Ut as normalizeColorTokenValue, Vt as getGlobalParser, X as fontFaceContentHash, Y as extractLocalFontFace, Z as formatFontFaceRule, _ as isFunctionsPolyfillEnabled, _t as hashString, bt as hasLocalProperties, c as getGlobalInjector, en as Lru, et as STYLE_HANDLER_MAP, f as getNamePrefix, ft as makeClassName, ht as tastyClassRegex, it as PropertyTypeResolver, jt as extractLocalFunctions, l as getGlobalKeyframes, n as getConfig, p as hasGlobalKeyframes, q as formatCounterStyleRule, rt as createStyle, sn as normalizeDslName, tn as overrideColorAlpha, v as isTestEnvironment, vt as extractLocalProperties, wt as CHUNK_NAMES, xt as parsePropertyToken, y as markStylesGenerated, z as camelToKebab } from "./config-B23gZrfP.js";
2
- import { a as mergeKeyframes, c as generateChunkCacheKey, i as hasLocalKeyframes, l as categorizeStyleKeys, n as extractLocalKeyframes, o as replaceAnimationNames, r as filterUsedKeyframes, s as renderStylesForChunk, t as extractAnimationNamesFromStyles } from "./keyframes-Dxdx3KOo.js";
3
- import { n as formatPropertyCSS, r as getRegisteredSSRCollector, t as formatRules } from "./format-rules-BCTWVvcS.js";
4
- import { t as resolveRecipes } from "./resolve-recipes-BuOvSEa2.js";
1
+ import { $t as getGlobalParseFunctions, At as extractLocalProperties, B as camelToKebab, Dt as tastyClassRegex, Gt as formatFunctionRule, K as applyRegisteredDependenciesToInjector, Kt as hasLocalFunctions, Lt as CHUNK_NAMES, Mt as hasLocalProperties, Nt as normalizePropertyDefinition, Pt as parsePropertyToken, Wt as extractLocalFunctions, X as findPrecompiledChunk, Yt as registerLocalFunctionPolyfills, at as formatCounterStyleRule, b as markStylesGenerated, bn as normalizeDslName, ct as fontFaceContentHash, dn as isDevEnv, en as getGlobalParser, et as getRegisteredPrecompiledStats, ft as STYLE_HANDLER_MAP, gt as PropertyTypeResolver, ht as createStyle, in as parseStyle, it as extractLocalCounterStyle, jt as getEffectiveDefinition, kt as hashString, l as getGlobalInjector, lt as formatFontFaceRule, m as hasGlobalKeyframes, mn as overrideColorAlpha, n as getConfig, nn as normalizeColorTokenValue, ot as hasLocalCounterStyle, p as getNamePrefix, pn as Lru, q as applyRegisteredDependenciesToRSC, qt as parseFunctionName, rt as StyleInjector, st as extractLocalFontFace, tt as precompileRuntimeState, u as getGlobalKeyframes, ut as hasLocalFontFace, v as isFunctionsPolyfillEnabled, vt as flushStyles, wt as makeClassName, y as isTestEnvironment } from "./config-Bd2vOF0Z.js";
2
+ import { a as mergeKeyframes, c as resolveKeyframesNames, d as categorizeStyleKeys, i as hasLocalKeyframes, l as renderStylesForChunk, n as extractLocalKeyframes, o as referencesAnimation, r as filterUsedKeyframes, s as replaceAnimationNames, t as extractAnimationNamesFromStyles, u as generateChunkCacheKey } from "./keyframes-BjfNVhaB.js";
3
+ import { t as getRegisteredSSRCollector } from "./ssr-collector-ref-COs_ioWl.js";
4
+ import { r as formatPropertyCSS, t as formatRules } from "./format-rules-CGhgoVLR.js";
5
+ import { t as resolveRecipes } from "./resolve-recipes-B2Sf36AH.js";
5
6
  import { cache } from "react";
6
7
  //#region src/utils/function-color.ts
7
8
  const RE_FUNC_NAME = /^([a-z][a-z0-9-]*)\s*\(/i;
@@ -245,6 +246,21 @@ function getCSSTextForNode(node, options) {
245
246
  return getGlobalInjector().getCSSTextForClasses(classSet, options);
246
247
  }
247
248
  /**
249
+ * Take a reference on local `@keyframes` under the deterministic names the
250
+ * caller resolved, and report which entry holds each. Pair with
251
+ * `ownKeyframes()` once the rules exist to inspect.
252
+ */
253
+ function holdKeyframes(steps, names, options) {
254
+ return getGlobalInjector().holdKeyframes(steps, names, options);
255
+ }
256
+ /**
257
+ * Record that a class animates these keyframes, so the reference is released
258
+ * when the last such class is collected.
259
+ */
260
+ function ownKeyframes(key, className, options) {
261
+ getGlobalInjector().ownKeyframes(key, className, options);
262
+ }
263
+ /**
248
264
  * Remove every injected rule that is neither in the DOM nor held by an
249
265
  * outstanding `inject()` handle. Equivalent to `gc({ force: true })`.
250
266
  */
@@ -252,9 +268,12 @@ function cleanup(root) {
252
268
  return getGlobalInjector().cleanup(root);
253
269
  }
254
270
  /**
255
- * Record a render-time usage hit for one or more classNames.
256
- * Used internally by computeStyles and tasty() to track usage for GC.
257
- * When the global touch counter reaches `touchInterval`, schedules GC.
271
+ * Count a render, so that a collection pass is scheduled every
272
+ * `gc.touchInterval` of them. Used internally by computeStyles and tasty().
273
+ *
274
+ * @deprecated The class name is ignored — collection asks the DOM what is
275
+ * rendered rather than recording usage per class. The argument is kept so
276
+ * existing calls still compile.
258
277
  */
259
278
  function touch(className, options) {
260
279
  if (!getConfig().gc) return;
@@ -314,8 +333,15 @@ const getRSCCache = cache(() => ({
314
333
  internalsEmitted: false,
315
334
  pendingCSS: [],
316
335
  keyToIndex: /* @__PURE__ */ new Map(),
317
- generatedNames: /* @__PURE__ */ new Map()
336
+ generatedNames: /* @__PURE__ */ new Map(),
337
+ precompiledRevision: -1,
338
+ precompiledEmittedKeys: /* @__PURE__ */ new Set(),
339
+ precompiledGeneratedNames: /* @__PURE__ */ new Map()
318
340
  }));
341
+ function prepareRSCCache(cache) {
342
+ applyRegisteredDependenciesToRSC(cache, getNamePrefix());
343
+ return cache;
344
+ }
319
345
  function rscAllocateClassName(rscCache, cacheKey) {
320
346
  const existing = rscCache.cacheKeyToClassName.get(cacheKey);
321
347
  if (existing) return {
@@ -375,7 +401,7 @@ function getStyleTarget() {
375
401
  };
376
402
  if (typeof document === "undefined") return {
377
403
  mode: "rsc",
378
- cache: getRSCCache()
404
+ cache: prepareRSCCache(getRSCCache())
379
405
  };
380
406
  return { mode: "client" };
381
407
  }
@@ -399,12 +425,13 @@ function scanAndEmitAutoProperties(rules, styles, emit) {
399
425
  if (!rule.declarations) continue;
400
426
  resolver.scanDeclarations(rule.declarations, (name) => registered.has(name), (name, syntax, initialValue) => {
401
427
  registered.add(name);
402
- const css = formatPropertyCSS(name, {
428
+ const definition = {
403
429
  syntax,
404
430
  inherits: true,
405
431
  initialValue
406
- });
407
- if (css) emit(name, css);
432
+ };
433
+ const css = formatPropertyCSS(name, definition);
434
+ if (css) emit(name, css, definition);
408
435
  });
409
436
  }
410
437
  }
@@ -416,9 +443,14 @@ function scanAndEmitAutoProperties(rules, styles, emit) {
416
443
  * @param collector - SSR collector to emit @property CSS into
417
444
  * @param styles - Original styles object (used to skip explicit @property)
418
445
  */
419
- function collectAutoInferredProperties(rules, collector, styles) {
420
- scanAndEmitAutoProperties(rules, styles, (name, css) => {
421
- collector.collectProperty(`__auto:${name}`, css);
446
+ function collectAutoInferredProperties(rules, collector, styles, source = "component") {
447
+ scanAndEmitAutoProperties(rules, styles, (name, css, definition) => {
448
+ collector.collectProperty(`__auto:${name}`, css, {
449
+ source,
450
+ cssName: name,
451
+ normalizedDefinition: normalizePropertyDefinition(definition),
452
+ rscKey: `__auto:${name}`
453
+ });
422
454
  });
423
455
  }
424
456
  /**
@@ -519,6 +551,17 @@ function hasKeys(obj) {
519
551
  * This enables tasty() components to work as React Server Components.
520
552
  */
521
553
  const EMPTY_RESULT = { className: "" };
554
+ function keyframeLookupSignature(names) {
555
+ if (!names || names.size === 0) return "";
556
+ return [...names].map(([authored, resolved]) => `${authored}=${resolved}`).sort().join(",");
557
+ }
558
+ function precompiledLookupKey(baseKey, signature) {
559
+ return signature ? `${baseKey}\0pkf:${signature}` : baseKey;
560
+ }
561
+ function lookupPrecompiledChunk(baseKey, signature, root) {
562
+ if (root && !(typeof document !== "undefined" && root === document)) return null;
563
+ return findPrecompiledChunk(precompiledLookupKey(baseKey, signature), getNamePrefix());
564
+ }
522
565
  /**
523
566
  * Mark internals as emitted for this RSC request.
524
567
  *
@@ -544,8 +587,10 @@ function collectInternalsRSC(rscCache) {
544
587
  function collectAncillaryRSC(rscCache, styles) {
545
588
  const parts = [];
546
589
  const usedKf = getUsedKeyframes(styles);
547
- if (usedKf) for (const [name, steps] of Object.entries(usedKf)) {
548
- const key = `__kf:${name}:${JSON.stringify(steps)}`;
590
+ const rscKeyframeNames = usedKf ? resolveKeyframesNames(usedKf) : null;
591
+ if (usedKf && rscKeyframeNames) for (const [authored, steps] of Object.entries(usedKf)) {
592
+ const name = rscKeyframeNames.get(authored);
593
+ const key = `__kf:${name}`;
549
594
  if (!rscCache.emittedKeys.has(key)) {
550
595
  rscCache.emittedKeys.add(key);
551
596
  parts.push(formatKeyframesCSS(name, steps));
@@ -601,24 +646,33 @@ function collectAncillaryRSC(rscCache, styles) {
601
646
  * Process all chunks in RSC mode: render CSS to strings, allocate classNames,
602
647
  * and return combined { className, css }.
603
648
  */
604
- function computeStylesRSC(styles, chunkMap, stableStyles) {
605
- const rscCache = getRSCCache();
649
+ function computeStylesRSC(styles, chunkMap, stableStyles, precompiledEnabled = false) {
650
+ const rscCache = prepareRSCCache(getRSCCache());
606
651
  const cssParts = [];
607
652
  const classNames = [];
653
+ const rscUsedKf = getUsedKeyframes(styles);
654
+ const rscKeyframeNames = rscUsedKf ? resolveKeyframesNames(rscUsedKf) : null;
655
+ const lookupSignature = precompiledEnabled ? keyframeLookupSignature(rscKeyframeNames) : "";
608
656
  const pendingCSS = flushPendingCSS(rscCache);
609
657
  if (pendingCSS) cssParts.push(pendingCSS);
610
658
  const internalsCSS = collectInternalsRSC(rscCache);
611
659
  if (internalsCSS) cssParts.push(internalsCSS);
612
660
  for (const [chunkName, chunkStyleKeys] of chunkMap) {
613
661
  if (chunkStyleKeys.length === 0) continue;
614
- const { className, isNew } = rscAllocateClassName(rscCache, generateChunkCacheKey(styles, chunkName, chunkStyleKeys, stableStyles));
662
+ const baseKey = generateChunkCacheKey(styles, chunkName, chunkStyleKeys, stableStyles);
663
+ const precompiled = precompiledEnabled ? lookupPrecompiledChunk(baseKey, lookupSignature) : null;
664
+ if (precompiled) {
665
+ classNames.push(precompiled.className);
666
+ continue;
667
+ }
668
+ const renderResult = renderStylesForChunk(styles, chunkName, chunkStyleKeys);
669
+ if (renderResult.rules.length === 0) continue;
670
+ const { rules, cacheKey } = applyKeyframeNames(renderResult.rules, baseKey, rscKeyframeNames);
671
+ const { className, isNew } = rscAllocateClassName(rscCache, cacheKey);
615
672
  classNames.push(className);
616
673
  if (isNew) {
617
- const renderResult = renderStylesForChunk(styles, chunkName, chunkStyleKeys);
618
- if (renderResult.rules.length > 0) {
619
- const css = formatRules(renderResult.rules, className);
620
- if (css) cssParts.push(css);
621
- }
674
+ const css = formatRules(rules, className);
675
+ if (css) cssParts.push(css);
622
676
  }
623
677
  }
624
678
  const ancillaryCSS = collectAncillaryRSC(rscCache, styles);
@@ -645,23 +699,26 @@ function getUsedKeyframes(styles) {
645
699
  /**
646
700
  * Process a chunk on the SSR path: allocate via collector, render, collect CSS.
647
701
  */
648
- function processChunkSSR(collector, styles, chunkName, styleKeys, stableStyles) {
702
+ function processChunkSSR(collector, styles, chunkName, styleKeys, stableStyles, keyframeNames) {
649
703
  if (styleKeys.length === 0) return null;
650
- const cacheKey = generateChunkCacheKey(styles, chunkName, styleKeys, stableStyles);
704
+ const baseKey = generateChunkCacheKey(styles, chunkName, styleKeys, stableStyles);
705
+ const renderResult = renderStylesForChunk(styles, chunkName, styleKeys);
706
+ if (renderResult.rules.length === 0) return null;
707
+ const { animations, rules, cacheKey } = applyKeyframeNames(renderResult.rules, baseKey, keyframeNames);
651
708
  const { className, isNewAllocation } = collector.allocateClassName(cacheKey);
652
709
  if (isNewAllocation) {
653
- const renderResult = renderStylesForChunk(styles, chunkName, styleKeys);
654
- if (renderResult.rules.length > 0) {
655
- collector.collectChunk(cacheKey, className, renderResult.rules);
656
- return {
657
- name: chunkName,
658
- styleKeys,
659
- cacheKey,
660
- renderResult,
661
- className
662
- };
663
- }
664
- return null;
710
+ collector.collectChunk(cacheKey, className, rules);
711
+ return {
712
+ name: chunkName,
713
+ styleKeys,
714
+ cacheKey,
715
+ renderResult: {
716
+ ...renderResult,
717
+ rules
718
+ },
719
+ className,
720
+ animations
721
+ };
665
722
  }
666
723
  return {
667
724
  name: chunkName,
@@ -671,58 +728,126 @@ function processChunkSSR(collector, styles, chunkName, styleKeys, stableStyles)
671
728
  className
672
729
  };
673
730
  }
674
- /**
675
- * Process a chunk on the client: render, allocate className, and inject
676
- * CSS synchronously. The injector's cache makes this idempotent.
677
- */
678
- function processChunkSync(styles, chunkName, styleKeys, stableStyles, root) {
731
+ /** Catalog-aware SSR path, kept off the unregistered runtime hot path. */
732
+ function processChunkSSRPrecompiled(collector, styles, chunkName, styleKeys, stableStyles, keyframeNames, lookupSignature = "", precompiledEnabled = false) {
679
733
  if (styleKeys.length === 0) return null;
680
- const cacheKey = generateChunkCacheKey(styles, chunkName, styleKeys, stableStyles);
681
- const renderResult = renderStylesForChunk(styles, chunkName, styleKeys, cacheKey);
734
+ const baseKey = generateChunkCacheKey(styles, chunkName, styleKeys, stableStyles);
735
+ if (precompiledEnabled && !collector.isPrecompileRecording()) {
736
+ const precompiled = lookupPrecompiledChunk(baseKey, lookupSignature);
737
+ if (precompiled) return {
738
+ name: chunkName,
739
+ styleKeys,
740
+ cacheKey: baseKey,
741
+ renderResult: { rules: [] },
742
+ className: precompiled.className,
743
+ animations: [...precompiled.animations]
744
+ };
745
+ }
746
+ const renderResult = renderStylesForChunk(styles, chunkName, styleKeys);
682
747
  if (renderResult.rules.length === 0) return null;
683
- const { className } = inject(renderResult.rules, {
684
- cacheKey,
685
- root,
686
- pin: false
687
- });
748
+ const { animations, rules, cacheKey } = applyKeyframeNames(renderResult.rules, baseKey, keyframeNames);
749
+ const { className, isNewAllocation } = collector.allocateClassName(cacheKey);
750
+ if (collector.isPrecompileRecording()) collector.recordPrecompiledChunk(precompiledLookupKey(baseKey, lookupSignature), className, animations);
751
+ if (isNewAllocation) {
752
+ collector.collectChunk(cacheKey, className, rules);
753
+ return {
754
+ name: chunkName,
755
+ styleKeys,
756
+ cacheKey,
757
+ renderResult: {
758
+ ...renderResult,
759
+ rules
760
+ },
761
+ className,
762
+ animations
763
+ };
764
+ }
688
765
  return {
689
766
  name: chunkName,
690
767
  styleKeys,
691
768
  cacheKey,
692
- renderResult,
769
+ renderResult: { rules: [] },
693
770
  className
694
771
  };
695
772
  }
696
773
  /**
697
- * Inject keyframes synchronously and return a name replacement map.
698
- * On the client, keyframes are injected into the DOM.
774
+ * Point a chunk's rules at the resolved keyframe names, and fold those names
775
+ * into its cache key.
776
+ *
777
+ * Both halves matter, and both have to happen before the rules are written
778
+ * anywhere: the declarations have to name the animation that will exist, and
779
+ * the key has to distinguish two components that authored the same shorthand
780
+ * over different definitions. Shared by the client and the server so they
781
+ * cannot disagree about either.
699
782
  */
700
- function injectKeyframesSync(usedKeyframes, root) {
701
- let nameMap = null;
702
- for (const [name, steps] of Object.entries(usedKeyframes)) {
703
- const injectedName = keyframes(steps, {
704
- name,
705
- root
706
- }).toString();
707
- if (injectedName !== name) {
708
- if (!nameMap) nameMap = /* @__PURE__ */ new Map();
709
- nameMap.set(name, injectedName);
710
- }
711
- }
712
- return nameMap;
783
+ function applyKeyframeNames(ruleset, baseKey, keyframeNames) {
784
+ if (!keyframeNames || keyframeNames.size === 0) return {
785
+ animations: [],
786
+ rules: ruleset,
787
+ cacheKey: baseKey
788
+ };
789
+ const animations = [...keyframeNames.keys()].filter((authored) => ruleset.some((rule) => referencesAnimation(rule.declarations, authored)));
790
+ if (animations.length === 0) return {
791
+ animations,
792
+ rules: ruleset,
793
+ cacheKey: baseKey
794
+ };
795
+ return {
796
+ animations,
797
+ rules: ruleset.map((rule) => ({
798
+ ...rule,
799
+ declarations: replaceAnimationNames(rule.declarations, keyframeNames)
800
+ })),
801
+ cacheKey: `${baseKey}\u0000kf:${animations.map((authored) => `${authored}=${keyframeNames.get(authored)}`).sort().join(",")}`
802
+ };
713
803
  }
714
804
  /**
715
- * Inject chunk rules synchronously, replacing animation names if needed.
805
+ * Process a chunk on the client: render, allocate className, and inject
806
+ * CSS synchronously. The injector's cache makes this idempotent.
716
807
  */
717
- function injectChunkRulesSync(chunks, nameMap, root) {
718
- for (const chunk of chunks) if (chunk.renderResult.rules.length > 0) inject(nameMap ? chunk.renderResult.rules.map((rule) => ({
719
- ...rule,
720
- declarations: replaceAnimationNames(rule.declarations, nameMap)
721
- })) : chunk.renderResult.rules, {
722
- cacheKey: chunk.cacheKey,
808
+ function processChunkSync(styles, chunkName, styleKeys, stableStyles, root, keyframeNames, lookupSignature = "", clientInjector, precompiledEnabled = false) {
809
+ if (styleKeys.length === 0) return null;
810
+ const cacheKey = generateChunkCacheKey(styles, chunkName, styleKeys, stableStyles);
811
+ const precompiled = precompiledEnabled ? lookupPrecompiledChunk(cacheKey, lookupSignature, root) : null;
812
+ if (precompiled) {
813
+ clientInjector?.recordPrecompiledHit(precompiled.className, { root });
814
+ return {
815
+ name: chunkName,
816
+ styleKeys,
817
+ cacheKey,
818
+ renderResult: { rules: [] },
819
+ className: precompiled.className,
820
+ animations: [...precompiled.animations]
821
+ };
822
+ }
823
+ const prepared = clientInjector?.prepareClassName(cacheKey, { root });
824
+ if (prepared?.isExisting) return {
825
+ name: chunkName,
826
+ styleKeys,
827
+ cacheKey,
828
+ renderResult: { rules: [] },
829
+ className: prepared.className
830
+ };
831
+ const renderResult = renderStylesForChunk(styles, chunkName, styleKeys, cacheKey);
832
+ if (renderResult.rules.length === 0) return null;
833
+ const { animations, rules, cacheKey: injectKey } = applyKeyframeNames(renderResult.rules, cacheKey, keyframeNames);
834
+ const { className } = (clientInjector ?? getGlobalInjector()).inject(rules, {
835
+ cacheKey: injectKey,
723
836
  root,
724
- pin: false
837
+ pin: false,
838
+ preparedClassName: injectKey === cacheKey ? prepared?.className : void 0
725
839
  });
840
+ return {
841
+ name: chunkName,
842
+ styleKeys,
843
+ cacheKey: injectKey,
844
+ renderResult: {
845
+ ...renderResult,
846
+ rules
847
+ },
848
+ className,
849
+ animations
850
+ };
726
851
  }
727
852
  /**
728
853
  * Inject all ancillary rules (properties, font-faces, counter-styles) synchronously.
@@ -756,15 +881,30 @@ function injectAncillarySync(styles, root) {
756
881
  */
757
882
  function collectAncillarySSR(collector, styles, chunks) {
758
883
  const usedKf = getUsedKeyframes(styles);
759
- if (usedKf) for (const [name, steps] of Object.entries(usedKf)) {
760
- const css = formatKeyframesCSS(name, steps);
761
- collector.collectKeyframes(name, css);
884
+ if (usedKf) {
885
+ const names = resolveKeyframesNames(usedKf);
886
+ for (const [authored, steps] of Object.entries(usedKf)) {
887
+ const name = names.get(authored);
888
+ collector.collectKeyframes(name, formatKeyframesCSS(name, steps), {
889
+ source: "component",
890
+ contentKey: `${name}\0${JSON.stringify(steps)}`,
891
+ rscKeys: [`__kf:${name}`]
892
+ });
893
+ }
762
894
  }
763
895
  if (hasLocalProperties(styles)) {
764
896
  const localProperties = extractLocalProperties(styles);
765
897
  if (localProperties) for (const [token, definition] of Object.entries(localProperties)) {
766
898
  const css = formatPropertyCSS(token, definition);
767
- if (css) collector.collectProperty(token, css);
899
+ if (css) {
900
+ const effective = getEffectiveDefinition(token, definition);
901
+ collector.collectProperty(token, css, {
902
+ source: "component",
903
+ cssName: effective.isValid ? effective.cssName : void 0,
904
+ normalizedDefinition: effective.isValid ? normalizePropertyDefinition(effective.definition) : void 0,
905
+ rscKey: `__prop:${token}`
906
+ });
907
+ }
768
908
  }
769
909
  }
770
910
  if (hasLocalFontFace(styles)) {
@@ -774,7 +914,7 @@ function collectAncillarySSR(collector, styles, chunks) {
774
914
  for (const desc of descriptors) {
775
915
  const hash = fontFaceContentHash(family, desc);
776
916
  const css = formatFontFaceRule(family, desc);
777
- collector.collectFontFace(hash, css);
917
+ collector.collectFontFace(hash, css, { source: "component" });
778
918
  }
779
919
  }
780
920
  }
@@ -782,14 +922,17 @@ function collectAncillarySSR(collector, styles, chunks) {
782
922
  const localCounterStyle = extractLocalCounterStyle(styles);
783
923
  if (localCounterStyle) for (const [name, descriptors] of Object.entries(localCounterStyle)) {
784
924
  const css = formatCounterStyleRule(name, descriptors);
785
- collector.collectCounterStyle(name, css);
925
+ collector.collectCounterStyle(name, css, {
926
+ source: "component",
927
+ rscKeys: [`__cs:${name}:${JSON.stringify(descriptors)}`]
928
+ });
786
929
  }
787
930
  }
788
931
  if (!isFunctionsPolyfillEnabled() && hasLocalFunctions(styles)) {
789
932
  const localFunctions = extractLocalFunctions(styles);
790
933
  if (localFunctions) for (const [name, definition] of Object.entries(localFunctions)) {
791
934
  const css = formatFunctionRule(name, definition);
792
- collector.collectFunction(parseFunctionName(name), css);
935
+ collector.collectFunction(parseFunctionName(name), css, { source: "component" });
793
936
  }
794
937
  }
795
938
  if (getConfig().autoPropertyTypes !== false) {
@@ -818,26 +961,44 @@ function computeStyles(styles, options) {
818
961
  const stableStyles = options?.stableStyles === true && resolved === styles;
819
962
  if (isFunctionsPolyfillEnabled() && hasLocalFunctions(resolved)) registerLocalFunctionPolyfills(resolved);
820
963
  const chunkMap = categorizeStyleKeys(resolved);
964
+ const precompiledEnabled = precompileRuntimeState.active === true;
821
965
  const collector = options?.ssrCollector !== void 0 ? options.ssrCollector : getRegisteredSSRCollector();
822
966
  const chunks = [];
823
967
  if (collector) {
968
+ if (precompiledEnabled) collector.applyRegisteredPrecompiledDependencies();
824
969
  collector.collectInternals();
825
- for (const [chunkName, chunkStyleKeys] of chunkMap) {
826
- const chunk = processChunkSSR(collector, resolved, chunkName, chunkStyleKeys, stableStyles);
970
+ const ssrKf = getUsedKeyframes(resolved);
971
+ const ssrKeyframeNames = ssrKf ? resolveKeyframesNames(ssrKf) : null;
972
+ if (precompiledEnabled) {
973
+ const lookupSignature = keyframeLookupSignature(ssrKeyframeNames);
974
+ for (const [chunkName, chunkStyleKeys] of chunkMap) {
975
+ const chunk = processChunkSSRPrecompiled(collector, resolved, chunkName, chunkStyleKeys, stableStyles, ssrKeyframeNames, lookupSignature, precompiledEnabled);
976
+ if (chunk) chunks.push(chunk);
977
+ }
978
+ } else for (const [chunkName, chunkStyleKeys] of chunkMap) {
979
+ const chunk = processChunkSSR(collector, resolved, chunkName, chunkStyleKeys, stableStyles, ssrKeyframeNames);
827
980
  if (chunk) chunks.push(chunk);
828
981
  }
829
982
  collectAncillarySSR(collector, resolved, chunks);
830
- } else if (typeof document === "undefined") return computeStylesRSC(resolved, chunkMap, stableStyles);
983
+ } else if (typeof document === "undefined") return computeStylesRSC(resolved, chunkMap, stableStyles, precompiledEnabled);
831
984
  else {
832
985
  const root = options?.root;
986
+ const clientInjector = getGlobalInjector();
987
+ if (precompiledEnabled && (!root || typeof ShadowRoot === "undefined" || !(root instanceof ShadowRoot))) applyRegisteredDependenciesToInjector(clientInjector, getNamePrefix());
988
+ markStylesGenerated();
833
989
  injectAncillarySync(resolved, root);
834
990
  const usedKf = getUsedKeyframes(resolved);
835
- const nameMap = usedKf ? injectKeyframesSync(usedKf, root) : null;
991
+ const keyframeNames = usedKf ? resolveKeyframesNames(usedKf) : null;
992
+ const lookupSignature = precompiledEnabled ? keyframeLookupSignature(keyframeNames) : "";
993
+ const keyframeKeys = usedKf && keyframeNames ? holdKeyframes(usedKf, keyframeNames, { root }) : null;
836
994
  for (const [chunkName, chunkStyleKeys] of chunkMap) {
837
- const chunk = processChunkSync(resolved, chunkName, chunkStyleKeys, stableStyles, root);
995
+ const chunk = processChunkSync(resolved, chunkName, chunkStyleKeys, stableStyles, root, keyframeNames, lookupSignature, clientInjector, precompiledEnabled);
838
996
  if (chunk) chunks.push(chunk);
839
997
  }
840
- if (nameMap) injectChunkRulesSync(chunks, nameMap, root);
998
+ if (keyframeKeys) for (const chunk of chunks) for (const authored of chunk.animations ?? []) {
999
+ const key = keyframeKeys.get(authored);
1000
+ if (key) ownKeyframes(key, chunk.className, { root });
1001
+ }
841
1002
  for (const chunk of chunks) touch(chunk.className, { root });
842
1003
  }
843
1004
  if (chunks.length === 0) return EMPTY_RESULT;
@@ -1118,7 +1279,17 @@ function countRules(css) {
1118
1279
  function sortTastyClasses(classes) {
1119
1280
  return Array.from(classes).sort((a, b) => a.localeCompare(b));
1120
1281
  }
1282
+ /**
1283
+ * The registry for `root`, with every queued write landed first.
1284
+ *
1285
+ * Every injector read API is a flush point, and the reads below reach past
1286
+ * those APIs straight into the registry and the sheet manager. Without this
1287
+ * they would report a batch window's contents as absent — a rule that is
1288
+ * enqueued but not yet in a sheet is missing from `globalRules`, from the
1289
+ * sheets, and from anything counting either.
1290
+ */
1121
1291
  function getRegistry(root = document) {
1292
+ flushStyles();
1122
1293
  return injector.instance._sheetManager?.getRegistry(root);
1123
1294
  }
1124
1295
  function findDomTastyClasses(root = document) {
@@ -1134,6 +1305,17 @@ function findDomTastyClasses(root = document) {
1134
1305
  return sortTastyClasses(classes);
1135
1306
  }
1136
1307
  /**
1308
+ * Everything this injector holds in `root`, in the order the engine applies it,
1309
+ * with the sources kept byte-for-byte — trimming would report a total smaller
1310
+ * than one of its own parts whenever raw CSS has edge whitespace.
1311
+ */
1312
+ function getAllCSS(root = document) {
1313
+ const registry = getRegistry(root);
1314
+ const sheetManager = injector.instance._sheetManager;
1315
+ if (!registry || !sheetManager) return "";
1316
+ return sheetManager.getOwnedCSSInOrder(registry, root).join("\n");
1317
+ }
1318
+ /**
1137
1319
  * Injected classes that no element carries and nobody pinned — the exact set
1138
1320
  * `gc({ force: true })` would delete.
1139
1321
  *
@@ -1144,6 +1326,22 @@ function findDomTastyClasses(root = document) {
1144
1326
  function getUnusedClasses(root = document) {
1145
1327
  return sortTastyClasses(injector.instance.getUnusedClasses({ root }));
1146
1328
  }
1329
+ /** Every class this injector holds CSS for in `root`. */
1330
+ function getOwnedClasses(root = document) {
1331
+ const registry = getRegistry(root);
1332
+ if (!registry) return [];
1333
+ const owned = [];
1334
+ for (const [className, info] of registry.rules) if (info.sheetIndex >= 0) owned.push(className);
1335
+ return sortTastyClasses(owned);
1336
+ }
1337
+ function getPrecompiledDebugStats(root) {
1338
+ return typeof ShadowRoot !== "undefined" && root instanceof ShadowRoot ? {
1339
+ manifestCount: 0,
1340
+ classNames: [],
1341
+ cssSize: 0,
1342
+ ruleCount: 0
1343
+ } : getRegisteredPrecompiledStats(getNamePrefix());
1344
+ }
1147
1345
  function prettifyCSS(css) {
1148
1346
  if (!css || !css.trim()) return "";
1149
1347
  const out = [];
@@ -1238,6 +1436,18 @@ function buildChunkBreakdown(root = document) {
1238
1436
  totalClasses
1239
1437
  };
1240
1438
  }
1439
+ /**
1440
+ * Every prefix `registry.globalRules` is keyed by. Anything missing here is a
1441
+ * rule the summary would hold but never count, which is how the totals stopped
1442
+ * adding up the first time.
1443
+ */
1444
+ const GLOBAL_RULE_PREFIXES = {
1445
+ global: "global:",
1446
+ property: "property:",
1447
+ fontFace: "fontface:",
1448
+ counterStyle: "counterstyle:",
1449
+ function: "function:"
1450
+ };
1241
1451
  function getGlobalTypeCSS(type, root = document) {
1242
1452
  const registry = getRegistry(root);
1243
1453
  if (!registry) return {
@@ -1247,6 +1457,15 @@ function getGlobalTypeCSS(type, root = document) {
1247
1457
  };
1248
1458
  const chunks = [];
1249
1459
  let rc = 0;
1460
+ if (type === "raw") {
1461
+ const css = injector.instance.getRawCSSText({ root });
1462
+ const sheetManager = injector.instance._sheetManager;
1463
+ return {
1464
+ css: prettifyCSS(css),
1465
+ ruleCount: sheetManager?.getRawRuleCount(root) ?? 0,
1466
+ size: css.length
1467
+ };
1468
+ }
1250
1469
  if (type === "keyframes") for (const [, entry] of registry.keyframesCache) {
1251
1470
  const info = entry.info;
1252
1471
  const sheetInfo = registry.sheets[info.sheetIndex];
@@ -1264,7 +1483,7 @@ function getGlobalTypeCSS(type, root = document) {
1264
1483
  }
1265
1484
  }
1266
1485
  else {
1267
- const prefix = type === "global" ? "global:" : type === "raw" ? "raw:" : "property:";
1486
+ const prefix = GLOBAL_RULE_PREFIXES[type];
1268
1487
  for (const [key, ri] of registry.globalRules) {
1269
1488
  if (!key.startsWith(prefix)) continue;
1270
1489
  const sheetInfo = registry.sheets[ri.sheetIndex];
@@ -1354,7 +1573,7 @@ const tastyDebug = {
1354
1573
  if (!raw) console.warn("[Tasty] source CSS not available. Falling back to live CSSOM.");
1355
1574
  css = injector.instance.getCSSTextForClasses(target, { root });
1356
1575
  }
1357
- } else if (typeof target === "string") if (target === "all") css = injector.instance.getCSSText({ root });
1576
+ } else if (typeof target === "string") if (target === "all") css = getAllCSS(root);
1358
1577
  else if (target === "global") {
1359
1578
  css = getGlobalTypeCSS("global", root).css;
1360
1579
  return css;
@@ -1430,38 +1649,79 @@ const tastyDebug = {
1430
1649
  const { root = document, raw = false } = opts || {};
1431
1650
  const activeClasses = findDomTastyClasses(root);
1432
1651
  const unusedClasses = getUnusedClasses(root);
1433
- const totalStyledClasses = [...activeClasses, ...unusedClasses];
1652
+ const ownedClasses = getOwnedClasses(root);
1653
+ const precompiled = getPrecompiledDebugStats(root);
1654
+ const precompiledClasses = sortTastyClasses(precompiled.classNames);
1655
+ const precompiledSet = new Set(precompiledClasses);
1656
+ const runtimeActiveClasses = activeClasses.filter((className) => !precompiledSet.has(className));
1657
+ const precompiledActiveClasses = activeClasses.filter((className) => precompiledSet.has(className));
1658
+ const activeSet = new Set(activeClasses);
1659
+ const precompiledInactiveClasses = precompiledClasses.filter((className) => !activeSet.has(className));
1660
+ const precompiledUsedClasses = sortTastyClasses(getRegistry(root)?.precompiledUsedClasses ?? []);
1661
+ const totalStyledClasses = sortTastyClasses(new Set([
1662
+ ...activeClasses,
1663
+ ...ownedClasses,
1664
+ ...precompiledClasses
1665
+ ]));
1666
+ const unusedSet = new Set(unusedClasses);
1667
+ const hotClasses = ownedClasses.filter((className) => !activeSet.has(className) && !unusedSet.has(className));
1668
+ const hotCSS = injector.instance.getCSSTextForClasses(hotClasses, { root });
1434
1669
  const activeCSS = injector.instance.getCSSTextForClasses(activeClasses, { root });
1435
1670
  const unusedCSS = injector.instance.getCSSTextForClasses(unusedClasses, { root });
1436
- const allCSS = injector.instance.getCSSText({ root });
1671
+ const allCSS = getAllCSS(root);
1437
1672
  const activeRuleCount = countRules(activeCSS);
1438
1673
  const unusedRuleCount = countRules(unusedCSS);
1439
1674
  const globalData = getGlobalTypeCSS("global", root);
1440
1675
  const rawData = getGlobalTypeCSS("raw", root);
1441
1676
  const kfData = getGlobalTypeCSS("keyframes", root);
1442
1677
  const propData = getGlobalTypeCSS("property", root);
1443
- const totalRuleCount = activeRuleCount + unusedRuleCount + globalData.ruleCount + rawData.ruleCount + kfData.ruleCount + propData.ruleCount;
1678
+ const atRuleData = [
1679
+ "fontFace",
1680
+ "counterStyle",
1681
+ "function"
1682
+ ].reduce((all, type) => {
1683
+ const data = getGlobalTypeCSS(type, root);
1684
+ return {
1685
+ css: data.css ? `${all.css}\n${data.css}`.trim() : all.css,
1686
+ ruleCount: all.ruleCount + data.ruleCount,
1687
+ size: all.size + data.size
1688
+ };
1689
+ }, {
1690
+ css: "",
1691
+ ruleCount: 0,
1692
+ size: 0
1693
+ });
1694
+ const totalRuleCountWithPrecompiled = activeRuleCount + unusedRuleCount + countRules(hotCSS) + globalData.ruleCount + atRuleData.ruleCount + rawData.ruleCount + kfData.ruleCount + propData.ruleCount + precompiled.ruleCount;
1444
1695
  const metrics = injector.instance.getMetrics({ root });
1445
1696
  const defs = getDefs(root);
1446
1697
  const chunkBreakdown = buildChunkBreakdown(root);
1447
1698
  const summary = {
1448
1699
  activeClasses,
1700
+ runtimeActiveClasses,
1701
+ precompiledActiveClasses,
1702
+ precompiledInactiveClasses,
1703
+ precompiledUsedClasses,
1449
1704
  unusedClasses,
1705
+ hotClasses,
1450
1706
  totalStyledClasses,
1707
+ precompiledClasses,
1708
+ precompiledManifestCount: precompiled.manifestCount,
1451
1709
  activeCSSSize: activeCSS.length,
1452
1710
  unusedCSSSize: unusedCSS.length,
1453
- globalCSSSize: globalData.size,
1711
+ globalCSSSize: globalData.size + atRuleData.size,
1454
1712
  rawCSSSize: rawData.size,
1455
1713
  keyframesCSSSize: kfData.size,
1456
1714
  propertyCSSSize: propData.size,
1457
- totalCSSSize: allCSS.length,
1715
+ precompiledCSSSize: precompiled.cssSize,
1716
+ totalCSSSize: allCSS.length + precompiled.cssSize,
1458
1717
  activeRuleCount,
1459
1718
  unusedRuleCount,
1460
- globalRuleCount: globalData.ruleCount,
1719
+ globalRuleCount: globalData.ruleCount + atRuleData.ruleCount,
1461
1720
  rawRuleCount: rawData.ruleCount,
1462
1721
  keyframesRuleCount: kfData.ruleCount,
1463
1722
  propertyRuleCount: propData.ruleCount,
1464
- totalRuleCount,
1723
+ precompiledRuleCount: precompiled.ruleCount,
1724
+ totalRuleCount: totalRuleCountWithPrecompiled,
1465
1725
  metrics,
1466
1726
  definedProperties: defs.properties,
1467
1727
  definedKeyframes: defs.keyframes,
@@ -1469,17 +1729,20 @@ const tastyDebug = {
1469
1729
  };
1470
1730
  if (!raw) {
1471
1731
  console.group("Tasty Summary");
1472
- console.log(`Active: ${activeClasses.length} classes, ${activeRuleCount} rules, ${fmtSize(activeCSS.length)}`);
1473
- console.log(`Unused: ${unusedClasses.length} classes, ${unusedRuleCount} rules, ${fmtSize(unusedCSS.length)}`);
1474
- console.log(`Global: ${globalData.ruleCount} rules, ${fmtSize(globalData.size)}`);
1732
+ console.log(`Active: ${activeClasses.length} classes (${runtimeActiveClasses.length} runtime, ${precompiledActiveClasses.length} precompiled), ${activeRuleCount} runtime rules, ${fmtSize(activeCSS.length)} runtime CSS`);
1733
+ console.log(`Unused: ${unusedClasses.length} runtime classes, ${unusedRuleCount} rules, ${fmtSize(unusedCSS.length)}`);
1734
+ if (hotClasses.length) console.log(`Held: ${hotClasses.length} classes, ${countRules(hotCSS)} rules, ${fmtSize(hotCSS.length)} (not rendered, not yet collectable)`);
1735
+ console.log(`Global: ${globalData.ruleCount + atRuleData.ruleCount} rules, ${fmtSize(globalData.size + atRuleData.size)}`);
1475
1736
  if (rawData.ruleCount) console.log(`Raw: ${rawData.ruleCount} rules, ${fmtSize(rawData.size)}`);
1476
1737
  if (kfData.ruleCount) console.log(`Keyframes: ${kfData.ruleCount} rules, ${fmtSize(kfData.size)}`);
1477
1738
  if (propData.ruleCount) console.log(`@property: ${propData.ruleCount} rules, ${fmtSize(propData.size)}`);
1478
- console.log(`Total: ${totalStyledClasses.length} classes, ${totalRuleCount} rules, ${fmtSize(allCSS.length)}`);
1739
+ if (precompiled.manifestCount) console.log(`Precompiled: ${precompiledActiveClasses.length} active, ${precompiledInactiveClasses.length} inactive, ${precompiledUsedClasses.length}/${precompiledClasses.length} used since reset; ${precompiled.ruleCount} rules, ${fmtSize(precompiled.cssSize)} (${precompiled.manifestCount} ${precompiled.manifestCount === 1 ? "manifest" : "manifests"})`);
1740
+ console.log(`Total: ${totalStyledClasses.length} classes, ${totalRuleCountWithPrecompiled} rules, ${fmtSize(allCSS.length + precompiled.cssSize)}`);
1479
1741
  if (metrics) {
1480
1742
  const total = metrics.hits + metrics.misses;
1481
1743
  const rate = total > 0 ? (metrics.hits / total * 100).toFixed(1) : 0;
1482
- console.log(`Cache: ${rate}% hit rate (${total} lookups)`);
1744
+ const runtimeHits = metrics.hits - metrics.precompiledHits;
1745
+ console.log(`Lookups: ${total} (${metrics.precompiledHits} precompiled across ${metrics.precompiledUniqueHits} classes, ${runtimeHits} runtime cache hits, ${metrics.misses} generated; ${rate}% reused)`);
1483
1746
  }
1484
1747
  if (chunkBreakdown.totalChunkTypes > 0) {
1485
1748
  console.groupCollapsed(`Chunks (${chunkBreakdown.totalChunkTypes} types, ${chunkBreakdown.totalClasses} classes)`);
@@ -1514,21 +1777,37 @@ const tastyDebug = {
1514
1777
  const active = findDomTastyClasses(root);
1515
1778
  const unused = getUnusedClasses(root);
1516
1779
  const metrics = injector.instance.getMetrics({ root });
1780
+ const precompiled = getPrecompiledDebugStats(root);
1781
+ const precompiledSet = new Set(precompiled.classNames);
1782
+ const runtimeActive = active.filter((className) => !precompiledSet.has(className));
1783
+ const precompiledActive = active.filter((className) => precompiledSet.has(className));
1784
+ const activeSet = new Set(active);
1785
+ const precompiledInactive = sortTastyClasses(precompiled.classNames.filter((className) => !activeSet.has(className)));
1786
+ const precompiledUsed = sortTastyClasses(getRegistry(root)?.precompiledUsedClasses ?? []);
1517
1787
  const status = {
1518
1788
  classes: {
1519
1789
  active,
1520
1790
  unused,
1521
- all: [...active, ...unused]
1791
+ all: sortTastyClasses(new Set([
1792
+ ...active,
1793
+ ...getOwnedClasses(root),
1794
+ ...precompiled.classNames
1795
+ ])),
1796
+ runtimeActive,
1797
+ precompiledActive,
1798
+ precompiledInactive,
1799
+ precompiledUsed
1522
1800
  },
1523
1801
  metrics
1524
1802
  };
1525
1803
  if (!raw) {
1526
1804
  console.group("Cache");
1527
- console.log(`Active: ${active.length}, Unused: ${unused.length}`);
1805
+ console.log(`Active: ${active.length} (${runtimeActive.length} runtime, ${precompiledActive.length} precompiled), Unused: ${unused.length} runtime, Inactive precompiled: ${precompiledInactive.length}`);
1528
1806
  if (metrics) {
1529
1807
  const total = metrics.hits + metrics.misses;
1530
1808
  const rate = total > 0 ? (metrics.hits / total * 100).toFixed(1) : 0;
1531
- console.log(`Hits: ${metrics.hits}, Misses: ${metrics.misses}, Rate: ${rate}%`);
1809
+ const runtimeHits = metrics.hits - metrics.precompiledHits;
1810
+ console.log(`Precompiled: ${metrics.precompiledHits} hits across ${metrics.precompiledUniqueHits} classes, Runtime cache: ${runtimeHits} hits, Generated: ${metrics.misses}, Reuse: ${rate}%`);
1532
1811
  }
1533
1812
  console.groupEnd();
1534
1813
  }
@@ -1568,6 +1847,6 @@ function getPageCSS(root = document) {
1568
1847
  }
1569
1848
  if (typeof window !== "undefined" && isDevEnv()) tastyDebug.install();
1570
1849
  //#endregion
1571
- export { property as A, getRawCSSText as C, injector as D, injectRawCSS as E, ChunkSheetRegistry as M, chunkSheetRegistry as N, isPropertyDefined as O, resolveFunctionColor as P, getCSSTextForNode as S, injectGlobal as T, destroy as _, color as a, gc as b, hasKeys as c, collectAutoInferredPropertiesRSC as d, getStyleTarget as f, createInjector as g, counterStyle as h, _modAttrs as i, touch as j, keyframes as k, formatKeyframesCSS as l, cleanup as m, processTokens as n, filterBaseProps as o, pushRSCCSS as p, dotize as r, computeStyles as s, tastyDebug as t, collectAutoInferredProperties as u, fontFace as v, inject as w, getCSSText as x, func as y };
1850
+ export { keyframes as A, getRawCSSText as C, injectRawCSS as D, injectGlobal as E, chunkSheetRegistry as F, resolveFunctionColor as I, property as M, touch as N, injector as O, ChunkSheetRegistry as P, getCSSTextForNode as S, inject as T, destroy as _, color as a, gc as b, hasKeys as c, collectAutoInferredPropertiesRSC as d, getStyleTarget as f, createInjector as g, counterStyle as h, _modAttrs as i, ownKeyframes as j, isPropertyDefined as k, formatKeyframesCSS as l, cleanup as m, processTokens as n, filterBaseProps as o, pushRSCCSS as p, dotize as r, computeStyles as s, tastyDebug as t, collectAutoInferredProperties as u, fontFace as v, holdKeyframes as w, getCSSText as x, func as y };
1572
1851
 
1573
- //# sourceMappingURL=core-B1tyn69d.js.map
1852
+ //# sourceMappingURL=core-ClInK6YG.js.map