@pyreon/styler 0.13.1 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as _pyreon_core0 from "@pyreon/core";
1
+ import * as _$_pyreon_core0 from "@pyreon/core";
2
2
  import { ComponentFn, VNode, VNodeChild } from "@pyreon/core";
3
3
 
4
4
  //#region src/ThemeProvider.d.ts
@@ -16,7 +16,7 @@ type Theme = DefaultTheme & Record<string, unknown>;
16
16
  * - String-equality memoization (same CSS class = no DOM update)
17
17
  * - Untracked resolve (no exponential cascade)
18
18
  */
19
- declare const ThemeContext: _pyreon_core0.ReactiveContext<Theme>;
19
+ declare const ThemeContext: _$_pyreon_core0.ReactiveContext<Theme>;
20
20
  /**
21
21
  * Read the current theme. Returns the theme value (calls the accessor).
22
22
  * Inside a reactive scope (computed/effect), this tracks theme changes.
package/lib/index.js CHANGED
@@ -1,7 +1,8 @@
1
- import { createReactiveContext, h, provide, useContext } from "@pyreon/core";
1
+ import { createReactiveContext, h, nativeCompat, provide, useContext } from "@pyreon/core";
2
2
  import { computed, renderEffect, runUntracked } from "@pyreon/reactivity";
3
3
 
4
4
  //#region src/resolve.ts
5
+ const _countSink$2 = globalThis;
5
6
  /**
6
7
  * Lazy representation of a `css` tagged template. Stores the raw template
7
8
  * strings and interpolation values without resolving them. Resolution is
@@ -19,6 +20,7 @@ var CSSResult = class {
19
20
  };
20
21
  /** Resolve a tagged template's strings + values into a final CSS string. */
21
22
  const resolve = (strings, values, props) => {
23
+ if (process.env.NODE_ENV !== "production") _countSink$2.__pyreon_count__?.("styler.resolve");
22
24
  let result = strings[0];
23
25
  for (let i = 0; i < values.length; i++) {
24
26
  const v = values[i];
@@ -412,6 +414,8 @@ const hash = (str) => hashFinalize(hashUpdate(HASH_INIT, str));
412
414
  * Media queries (@media), @supports, and @container blocks nested inside
413
415
  * component CSS are automatically extracted into separate top-level rules.
414
416
  */
417
+ const _countSink$1 = globalThis;
418
+ const __DEV__ = process.env.NODE_ENV !== "production";
415
419
  const PREFIX = "pyr";
416
420
  const ATTR = "data-pyreon-styler";
417
421
  const DEFAULT_MAX_CACHE_SIZE = 1e4;
@@ -551,9 +555,13 @@ var StyleSheet = class {
551
555
  * via @layer order (base < rocketstyle) instead of specificity hacks.
552
556
  */
553
557
  insert(cssText, _unused = false, insertLayer) {
558
+ if (process.env.NODE_ENV !== "production") _countSink$1.__pyreon_count__?.("styler.sheet.insert");
554
559
  const icKey = insertLayer ? `${cssText}\0L:${insertLayer}` : cssText;
555
560
  const icHit = this.insertCache.get(icKey);
556
- if (icHit) return icHit;
561
+ if (icHit) {
562
+ if (process.env.NODE_ENV !== "production") _countSink$1.__pyreon_count__?.("styler.sheet.insert.hit");
563
+ return icHit;
564
+ }
557
565
  const className = `${PREFIX}-${hash(cssText)}`;
558
566
  if (this.cache.has(className)) {
559
567
  this.insertCache.set(icKey, className);
@@ -572,7 +580,7 @@ var StyleSheet = class {
572
580
  else if (this.sheet) for (const rule of finalRules) try {
573
581
  this.sheet.insertRule(rule, this.sheet.cssRules.length);
574
582
  } catch (_e) {
575
- if (process.env.NODE_ENV !== "production") console.warn("[styler] Failed to insert CSS rule:", rule, _e);
583
+ if (__DEV__) console.warn("[styler] Failed to insert CSS rule:", rule, _e);
576
584
  }
577
585
  this.insertCache.set(icKey, className);
578
586
  return className;
@@ -587,7 +595,7 @@ var StyleSheet = class {
587
595
  else if (this.sheet) try {
588
596
  this.sheet.insertRule(rule, this.sheet.cssRules.length);
589
597
  } catch (_e) {
590
- if (process.env.NODE_ENV !== "production") {}
598
+ if (__DEV__) console.warn("[styler] Failed to insert @keyframes rule:", rule, _e);
591
599
  }
592
600
  }
593
601
  /**
@@ -624,7 +632,7 @@ var StyleSheet = class {
624
632
  for (const rule of rules) try {
625
633
  this.sheet.insertRule(rule, this.sheet.cssRules.length);
626
634
  } catch (_e) {
627
- if (process.env.NODE_ENV !== "production") console.warn("[styler] Failed to insert global CSS rule:", rule, _e);
635
+ if (__DEV__) console.warn("[styler] Failed to insert global CSS rule:", rule, _e);
628
636
  }
629
637
  }
630
638
  }
@@ -736,6 +744,7 @@ function ThemeProvider({ theme, children }) {
736
744
  provide(ThemeContext, () => theme);
737
745
  return children ?? null;
738
746
  }
747
+ nativeCompat(ThemeProvider);
739
748
 
740
749
  //#endregion
741
750
  //#region src/globalStyle.ts
@@ -775,7 +784,8 @@ var KeyframesResult = class {
775
784
  name;
776
785
  constructor(strings, values) {
777
786
  const body = normalizeCSS(resolve(strings, values, {}));
778
- this.name = `pyr-kf-${hash(body)}`;
787
+ const h = hash(body);
788
+ this.name = `pyr-kf-${h}`;
779
789
  sheet.insertKeyframes(this.name, body);
780
790
  }
781
791
  /** Returns the animation name when used in string context. */
@@ -787,6 +797,7 @@ const keyframes = (strings, ...values) => new KeyframesResult(strings, values);
787
797
 
788
798
  //#endregion
789
799
  //#region src/styled.tsx
800
+ const _countSink = globalThis;
790
801
  const getDisplayName = (tag) => typeof tag === "string" ? tag : tag.displayName || tag.name || "Component";
791
802
  const staticComponentCache = /* @__PURE__ */ new WeakMap();
792
803
  let _hotStrings = null;
@@ -831,6 +842,7 @@ const createStyledComponent = (tag, strings, values, options) => {
831
842
  return StaticStyled;
832
843
  }
833
844
  const classCache = /* @__PURE__ */ new WeakMap();
845
+ const elClassCache = /* @__PURE__ */ new WeakMap();
834
846
  const DynamicStyled = (rawProps) => {
835
847
  const themeAccessor = useThemeAccessor();
836
848
  const theme = themeAccessor();
@@ -846,6 +858,19 @@ const createStyledComponent = (tag, strings, values, options) => {
846
858
  if (cached !== void 0) return cached;
847
859
  }
848
860
  }
861
+ const $el = rawProps.$element;
862
+ const $childFix = rawProps.$childFix;
863
+ const useElCache = (!rs || typeof rs !== "object" || !rsState || typeof rsState !== "object") && $el && typeof $el === "object";
864
+ if (useElCache) {
865
+ const inner = elClassCache.get($el);
866
+ if (inner) {
867
+ const cached = inner.get($childFix);
868
+ if (cached !== void 0) {
869
+ if (process.env.NODE_ENV !== "production") _countSink.__pyreon_count__?.("styler.elClassCache.hit");
870
+ return cached;
871
+ }
872
+ }
873
+ }
849
874
  const cssText = normalizeCSS(resolve(strings, values, {
850
875
  ...rawProps,
851
876
  ...isReactiveRS ? { $rocketstyle: rs } : {},
@@ -860,6 +885,13 @@ const createStyledComponent = (tag, strings, values, options) => {
860
885
  classCache.set(rs, inner);
861
886
  }
862
887
  inner.set(rsState, className);
888
+ } else if (useElCache) {
889
+ let inner = elClassCache.get($el);
890
+ if (!inner) {
891
+ inner = /* @__PURE__ */ new Map();
892
+ elClassCache.set($el, inner);
893
+ }
894
+ inner.set($childFix, className);
863
895
  }
864
896
  return className;
865
897
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/styler",
3
- "version": "0.13.1",
3
+ "version": "0.15.0",
4
4
  "description": "Lightweight CSS-in-JS engine for Pyreon",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -10,6 +10,7 @@
10
10
  },
11
11
  "files": [
12
12
  "lib",
13
+ "!lib/**/*.map",
13
14
  "!lib/analysis",
14
15
  "README.md",
15
16
  "LICENSE",
@@ -41,14 +42,14 @@
41
42
  "typecheck": "tsc --noEmit"
42
43
  },
43
44
  "devDependencies": {
44
- "@pyreon/test-utils": "^0.13.1",
45
- "@pyreon/typescript": "^0.13.1",
45
+ "@pyreon/test-utils": "^0.13.2",
46
+ "@pyreon/typescript": "^0.15.0",
46
47
  "@vitest/browser-playwright": "^4.1.4",
47
- "@vitus-labs/tools-rolldown": "^1.15.3"
48
+ "@vitus-labs/tools-rolldown": "^2.3.0"
48
49
  },
49
50
  "peerDependencies": {
50
- "@pyreon/core": "^0.13.1",
51
- "@pyreon/reactivity": "^0.13.1"
51
+ "@pyreon/core": "^0.15.0",
52
+ "@pyreon/reactivity": "^0.15.0"
52
53
  },
53
54
  "engines": {
54
55
  "node": ">= 22"
@@ -12,7 +12,7 @@
12
12
  * }
13
13
  */
14
14
  import type { VNode, VNodeChild } from '@pyreon/core'
15
- import { createReactiveContext, provide, useContext } from '@pyreon/core'
15
+ import { createReactiveContext, nativeCompat, provide, useContext } from '@pyreon/core'
16
16
 
17
17
  export interface DefaultTheme {}
18
18
 
@@ -59,3 +59,7 @@ export function ThemeProvider({
59
59
  provide(ThemeContext, () => theme)
60
60
  return (children ?? null) as VNode | null
61
61
  }
62
+
63
+ // Mark as native — compat-mode jsx() runtimes skip wrapCompatComponent so
64
+ // provide(ThemeContext, ...) reaches Pyreon's setup frame.
65
+ nativeCompat(ThemeProvider)
@@ -0,0 +1,85 @@
1
+ import { mkdtempSync, readFileSync, rmSync } from 'node:fs'
2
+ import { tmpdir } from 'node:os'
3
+ import path from 'node:path'
4
+ import { fileURLToPath } from 'node:url'
5
+ import { describe, expect, it } from 'vitest'
6
+ import { build } from 'vite'
7
+
8
+ const here = path.dirname(fileURLToPath(import.meta.url))
9
+ const SRC = path.resolve(here, '..')
10
+
11
+ // Bundle-level regression test for the styler dev-gate fix.
12
+ //
13
+ // Background — the shape of the problem:
14
+ // `process.env.NODE_ENV !== 'production'` is dead code in real Vite
15
+ // browser bundles because Vite does not polyfill `process`. The
16
+ // `console.warn` calls inside the gate were silently dropped in
17
+ // production, which masked malformed-CSS bugs (insertRule failures
18
+ // produced no diagnostic — empty <style> tag, classes assigned, no
19
+ // console output).
20
+ //
21
+ // The fix is to use bundler-agnostic `process.env.NODE_ENV !== 'production'`
22
+ // — every modern bundler auto-replaces `process.env.NODE_ENV` at consumer
23
+ // build time. This test bundles `sheet.ts` through Vite's production build
24
+ // and asserts the dev-warning strings are GONE. It also bundles in dev
25
+ // mode and asserts the strings are PRESENT, so a source-level deletion
26
+ // can't trivially pass the prod test.
27
+ //
28
+ // Mirrors `packages/core/runtime-dom/src/tests/dev-gate-treeshake.test.ts`.
29
+
30
+ const DEV_WARNING_STRINGS = [
31
+ '[styler] Failed to insert CSS rule:',
32
+ '[styler] Failed to insert @keyframes rule:',
33
+ '[styler] Failed to insert global CSS rule:',
34
+ ]
35
+
36
+ async function bundleWithVite(entry: string, dev: boolean): Promise<string> {
37
+ const outDir = mkdtempSync(path.join(tmpdir(), 'pyreon-styler-treeshake-'))
38
+ try {
39
+ await build({
40
+ mode: dev ? 'development' : 'production',
41
+ logLevel: 'error',
42
+ configFile: false,
43
+ resolve: { conditions: ['bun'] },
44
+ define: {
45
+ 'process.env.NODE_ENV': JSON.stringify(dev ? 'development' : 'production'),
46
+ },
47
+ build: {
48
+ // PINNED minifier — see runtime-dom's tree-shake test for rationale.
49
+ minify: dev ? false : 'esbuild',
50
+ target: 'esnext',
51
+ write: true,
52
+ outDir,
53
+ emptyOutDir: true,
54
+ lib: {
55
+ entry,
56
+ formats: ['es'],
57
+ fileName: 'out',
58
+ },
59
+ rollupOptions: {
60
+ external: [],
61
+ },
62
+ },
63
+ })
64
+ return readFileSync(path.join(outDir, 'out.js'), 'utf8')
65
+ } finally {
66
+ rmSync(outDir, { recursive: true, force: true })
67
+ }
68
+ }
69
+
70
+ describe('styler dev-warning gate (Vite production bundle)', () => {
71
+ it('sheet.ts → dev warnings eliminated in Vite production bundle', async () => {
72
+ const code = await bundleWithVite(path.join(SRC, 'sheet.ts'), false)
73
+ for (const warn of DEV_WARNING_STRINGS) {
74
+ expect(code, `"${warn}" survived prod tree-shake`).not.toContain(warn)
75
+ }
76
+ expect(code.length).toBeGreaterThan(0)
77
+ }, 10000)
78
+
79
+ it('sheet.ts → dev warnings PRESERVED in Vite dev bundle (sanity)', async () => {
80
+ const code = await bundleWithVite(path.join(SRC, 'sheet.ts'), true)
81
+ for (const warn of DEV_WARNING_STRINGS) {
82
+ expect(code, `"${warn}" missing from dev bundle (did source change?)`).toContain(warn)
83
+ }
84
+ }, 10000)
85
+ })
@@ -0,0 +1,9 @@
1
+ import { isNativeCompat } from '@pyreon/core'
2
+ import { describe, expect, it } from 'vitest'
3
+ import { ThemeProvider } from '../ThemeProvider'
4
+
5
+ describe('native-compat marker — @pyreon/styler', () => {
6
+ it('ThemeProvider is marked native', () => {
7
+ expect(isNativeCompat(ThemeProvider)).toBe(true)
8
+ })
9
+ })
@@ -1,6 +1,6 @@
1
- import { afterEach, beforeEach, describe, expect, it } from 'vitest'
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2
2
  import { hash } from '../hash'
3
- import { sheet } from '../sheet'
3
+ import { sheet, StyleSheet } from '../sheet'
4
4
 
5
5
  describe('StyleSheet', () => {
6
6
  beforeEach(() => {
@@ -162,4 +162,48 @@ describe('StyleSheet', () => {
162
162
  expect(sheet.has('pyr-unknown')).toBe(false)
163
163
  })
164
164
  })
165
+
166
+ // Failed insertRule used to be silently swallowed in production because
167
+ // `process.env.NODE_ENV !== 'production'` is dead code in real Vite browser
168
+ // bundles (Vite does not polyfill `process`). The dev gate now uses
169
+ // `import.meta.env.DEV` which fires the warn under vitest and tree-shakes
170
+ // away in prod. This test asserts the warn fires for malformed CSS in dev.
171
+ describe('insertRule failures fire console.warn in dev', () => {
172
+ it('warns when StyleSheet.insertRule throws on malformed CSS', () => {
173
+ const local = new StyleSheet()
174
+ const realSheet = (local as unknown as { sheet: CSSStyleSheet | null }).sheet
175
+ if (!realSheet) {
176
+ // happy-dom may not expose a real sheet — skip; the prod-bundle
177
+ // tree-shake test in dev-gate-treeshake.test.ts covers the build side.
178
+ return
179
+ }
180
+ const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
181
+ // Mock the prototype, not the instance — happy-dom's CSSStyleSheet may
182
+ // expose `insertRule` as a non-configurable own property that vi.spyOn
183
+ // can't intercept on an instance.
184
+ const proto = Object.getPrototypeOf(realSheet) as { insertRule: () => number }
185
+ const insertSpy = vi.spyOn(proto, 'insertRule').mockImplementation(() => {
186
+ throw new SyntaxError('invalid rule')
187
+ })
188
+
189
+ // Use a unique CSS string to bypass cross-instance/global insert cache
190
+ local.insert(`color: ${Math.random()};`)
191
+
192
+ const styleWarnings = warnSpy.mock.calls.filter(
193
+ (args) => typeof args[0] === 'string' && args[0].includes('[styler]'),
194
+ )
195
+ expect(styleWarnings.length).toBeGreaterThan(0)
196
+
197
+ insertSpy.mockRestore()
198
+ warnSpy.mockRestore()
199
+ })
200
+
201
+ it('uses bundler-agnostic process.env.NODE_ENV — vitest sets NODE_ENV !== "production"', () => {
202
+ // Smoke test the gate itself: vitest must set process.env.NODE_ENV to
203
+ // a non-production value for the regression test above to be meaningful.
204
+ // Every modern bundler (incl. Vitest's Vite pipeline) auto-replaces
205
+ // `process.env.NODE_ENV` at build time.
206
+ expect(process.env.NODE_ENV).not.toBe('production')
207
+ })
208
+ })
165
209
  })
package/src/env.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Minimal process type — just enough for `process.env.NODE_ENV` checks.
3
+ * Avoids requiring @types/node in consumers that import pyreon source
4
+ * via the `"bun"` export condition.
5
+ */
6
+ declare var process: { env: { NODE_ENV?: string } }
package/src/resolve.ts CHANGED
@@ -6,6 +6,11 @@
6
6
 
7
7
  import type { DefaultTheme } from './ThemeProvider'
8
8
 
9
+ // Dev-time counter sink — populated by `@pyreon/perf-harness` on install().
10
+ // Guarded on call sites with `process.env.NODE_ENV !== 'production'` so prod bundles
11
+ // tree-shake the entire reference. No cross-package import, no publish surface.
12
+ const _countSink = globalThis as { __pyreon_count__?: (name: string, n?: number) => void }
13
+
9
14
  /**
10
15
  * Props passed to interpolation functions inside tagged templates.
11
16
  * Generic `P` allows consumers to type their custom props (e.g. transient $-prefixed):
@@ -52,6 +57,7 @@ export const resolve = (
52
57
  values: Interpolation[],
53
58
  props: Record<string, any>,
54
59
  ): string => {
60
+ if (process.env.NODE_ENV !== 'production') _countSink.__pyreon_count__?.('styler.resolve')
55
61
  // Tagged templates guarantee strings.length === values.length + 1,
56
62
  // so strings[0] and strings[i+1] are always defined — no ?? needed.
57
63
  let result = strings[0] as string
package/src/sheet.ts CHANGED
@@ -8,6 +8,16 @@
8
8
  import { hash } from './hash'
9
9
  import { clearNormCache } from './resolve'
10
10
 
11
+ // Dev-time counter sink — see styler/resolve.ts for the contract.
12
+ const _countSink = globalThis as { __pyreon_count__?: (name: string, n?: number) => void }
13
+
14
+ // Dev-mode gate. `import.meta.env.DEV` is literal-replaced by Vite at build
15
+ // time and tree-shakes to zero bytes in prod. The previous
16
+ // `process.env.NODE_ENV !== 'production'` form was dead code in real Vite
17
+ // browser bundles (Vite does not polyfill `process`), so insertRule failures
18
+ // were silently swallowed in production — masking malformed CSS bugs.
19
+ const __DEV__ = process.env.NODE_ENV !== 'production'
20
+
11
21
  const PREFIX = 'pyr'
12
22
  const ATTR = 'data-pyreon-styler'
13
23
  const DEFAULT_MAX_CACHE_SIZE = 10000
@@ -200,10 +210,16 @@ export class StyleSheet {
200
210
  * via @layer order (base < rocketstyle) instead of specificity hacks.
201
211
  */
202
212
  insert(cssText: string, _unused = false, insertLayer?: string): string {
213
+ if (process.env.NODE_ENV !== 'production')
214
+ _countSink.__pyreon_count__?.('styler.sheet.insert')
203
215
  // Fast path: skip hash computation on repeated insertions of same CSS text
204
216
  const icKey = insertLayer ? `${cssText}\0L:${insertLayer}` : cssText
205
217
  const icHit = this.insertCache.get(icKey)
206
- if (icHit) return icHit
218
+ if (icHit) {
219
+ if (process.env.NODE_ENV !== 'production')
220
+ _countSink.__pyreon_count__?.('styler.sheet.insert.hit')
221
+ return icHit
222
+ }
207
223
 
208
224
  const h = hash(cssText)
209
225
  const className = `${PREFIX}-${h}`
@@ -228,7 +244,7 @@ export class StyleSheet {
228
244
  // Apply @layer wrapping — per-insert layer takes precedence over sheet-level layer.
229
245
  // In SSR, always apply layers (output goes to real browsers).
230
246
  // In client, skip if @layer isn't supported (e.g. happy-dom in tests).
231
- const layerName = (this.isSSR || this.supportsLayer) ? (insertLayer ?? this.layer) : undefined
247
+ const layerName = this.isSSR || this.supportsLayer ? (insertLayer ?? this.layer) : undefined
232
248
  const finalRules = layerName ? rules.map((r) => `@layer ${layerName}{${r}}`) : rules
233
249
 
234
250
  if (this.isSSR) {
@@ -240,7 +256,7 @@ export class StyleSheet {
240
256
  try {
241
257
  this.sheet.insertRule(rule, this.sheet.cssRules.length)
242
258
  } catch (_e) {
243
- if (process.env.NODE_ENV !== 'production') {
259
+ if (__DEV__) {
244
260
  // oxlint-disable-next-line no-console
245
261
  console.warn('[styler] Failed to insert CSS rule:', rule, _e)
246
262
  }
@@ -267,8 +283,9 @@ export class StyleSheet {
267
283
  try {
268
284
  this.sheet.insertRule(rule, this.sheet.cssRules.length)
269
285
  } catch (_e) {
270
- if (process.env.NODE_ENV !== 'production') {
271
- // silently ignore invalid CSS rules in production
286
+ if (__DEV__) {
287
+ // oxlint-disable-next-line no-console
288
+ console.warn('[styler] Failed to insert @keyframes rule:', rule, _e)
272
289
  }
273
290
  }
274
291
  }
@@ -317,7 +334,7 @@ export class StyleSheet {
317
334
  try {
318
335
  this.sheet.insertRule(rule, this.sheet.cssRules.length)
319
336
  } catch (_e) {
320
- if (process.env.NODE_ENV !== 'production') {
337
+ if (__DEV__) {
321
338
  // oxlint-disable-next-line no-console
322
339
  console.warn('[styler] Failed to insert global CSS rule:', rule, _e)
323
340
  }
package/src/styled.tsx CHANGED
@@ -24,6 +24,9 @@ import { isDynamic } from './shared'
24
24
  import { sheet } from './sheet'
25
25
  import { useThemeAccessor } from './ThemeProvider'
26
26
 
27
+ // Dev-time counter sink — see packages/internals/perf-harness/COUNTERS.md.
28
+ const _countSink = globalThis as { __pyreon_count__?: (name: string, n?: number) => void }
29
+
27
30
  type Tag = string | ComponentFn<any>
28
31
 
29
32
  export interface StyledOptions {
@@ -130,6 +133,14 @@ const createStyledComponent = (
130
133
  // Two-level WeakMap: $rocketstyle → $rocketstate → className.
131
134
  // 50 identical Items with the same resolved theme → 1 resolve + 49 hits.
132
135
  const classCache = new WeakMap<object, WeakMap<object, string>>()
136
+ // Single-key cache for non-rocketstyle styled components (e.g. Element's
137
+ // Wrapper, which depends on `$element` + `$childFix`). The key is the
138
+ // `$element` object identity; `$childFix` is folded into a `Map<bool,
139
+ // string>` per `$element` to avoid wrong-cache hits when childFix differs.
140
+ // Element-layer interning (see `@pyreon/elements` Element/component.tsx)
141
+ // gives `$element` stable identity across mounts, which is what makes this
142
+ // cache fire — analogous to PR #344's rocketstyle dimension memo.
143
+ const elClassCache = new WeakMap<object, Map<unknown, string>>()
133
144
 
134
145
  // DYNAMIC PATH: uses computed() for reactive class derivation.
135
146
  //
@@ -164,6 +175,27 @@ const createStyledComponent = (
164
175
  }
165
176
  }
166
177
 
178
+ // Element-layer cache (no rocketstyle props, but $element is present
179
+ // and an object). Fires only when the rocketstyle path didn't apply
180
+ // — they're mutually exclusive in practice.
181
+ const $el = rawProps.$element
182
+ const $childFix = rawProps.$childFix
183
+ const useElCache =
184
+ (!rs || typeof rs !== 'object' || !rsState || typeof rsState !== 'object') &&
185
+ $el &&
186
+ typeof $el === 'object'
187
+ if (useElCache) {
188
+ const inner = elClassCache.get($el as object)
189
+ if (inner) {
190
+ const cached = inner.get($childFix)
191
+ if (cached !== undefined) {
192
+ if (process.env.NODE_ENV !== 'production')
193
+ _countSink.__pyreon_count__?.('styler.elClassCache.hit')
194
+ return cached
195
+ }
196
+ }
197
+ }
198
+
167
199
  const resolveProps = {
168
200
  ...rawProps,
169
201
  ...(isReactiveRS ? { $rocketstyle: rs } : {}),
@@ -180,6 +212,13 @@ const createStyledComponent = (
180
212
  classCache.set(rs, inner)
181
213
  }
182
214
  inner.set(rsState, className)
215
+ } else if (useElCache) {
216
+ let inner = elClassCache.get($el as object)
217
+ if (!inner) {
218
+ inner = new Map()
219
+ elClassCache.set($el as object, inner)
220
+ }
221
+ inner.set($childFix, className)
183
222
  }
184
223
  return className
185
224
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index2.d.ts","names":[],"sources":["../../src/ThemeProvider.ts","../../src/resolve.ts","../../src/css.ts","../../src/forward.ts","../../src/globalStyle.ts","../../src/hash.ts","../../src/keyframes.ts","../../src/shared.ts","../../src/sheet.ts","../../src/styled.tsx","../../src/useCSS.ts"],"mappings":"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"}
package/lib/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/resolve.ts","../src/css.ts","../src/forward.ts","../src/shared.ts","../src/hash.ts","../src/sheet.ts","../src/ThemeProvider.ts","../src/globalStyle.ts","../src/keyframes.ts","../src/styled.tsx","../src/useCSS.ts"],"sourcesContent":["/**\n * Interpolation resolver: converts tagged template strings + values into a\n * final CSS string. Handles nested CSSResults, arrays, functions, and\n * primitive values.\n */\n\nimport type { DefaultTheme } from './ThemeProvider'\n\n/**\n * Props passed to interpolation functions inside tagged templates.\n * Generic `P` allows consumers to type their custom props (e.g. transient $-prefixed):\n *\n * @example\n * styled('div')<{ $color: string }>`\n * background: ${(props) => props.$color}; // props.$color is typed!\n * `\n */\nexport type StyledProps<P extends object = Record<string, unknown>> = P & {\n theme?: DefaultTheme & Record<string, unknown>\n}\n\nexport type Interpolation<P extends object = Record<string, unknown>> =\n | string\n | number\n | boolean\n | null\n | undefined\n | CSSResult\n | Interpolation<P>[]\n | ((props: StyledProps<P>) => Interpolation<P>)\n\n/**\n * Lazy representation of a `css` tagged template. Stores the raw template\n * strings and interpolation values without resolving them. Resolution is\n * deferred until a styled component renders (or until explicitly resolved).\n */\nexport class CSSResult {\n constructor(\n readonly strings: TemplateStringsArray,\n readonly values: Interpolation[],\n ) {}\n\n /** Resolve with empty props — useful for static templates, testing, and debugging. */\n toString(): string {\n return resolve(this.strings, this.values, {})\n }\n}\n\n/** Resolve a tagged template's strings + values into a final CSS string. */\nexport const resolve = (\n strings: TemplateStringsArray,\n values: Interpolation[],\n props: Record<string, any>,\n): string => {\n // Tagged templates guarantee strings.length === values.length + 1,\n // so strings[0] and strings[i+1] are always defined — no ?? needed.\n let result = strings[0] as string\n for (let i = 0; i < values.length; i++) {\n const v = values[i]\n const s = strings[i + 1] as string\n // Inline the most common value types to avoid function call overhead.\n if (typeof v === 'function') {\n const r = v(props)\n result +=\n (typeof r === 'string'\n ? r\n : r == null || r === false || r === true\n ? ''\n : resolveValue(r as Interpolation, props)) + s\n } else if (v == null || v === false || v === true) {\n result += s\n } else if (typeof v === 'string') {\n result += v + s\n } else if (typeof v === 'number') {\n result += v + s\n } else {\n result += resolveValue(v, props) + s\n }\n }\n return result\n}\n\n/**\n * Normalize resolved CSS text for strict `insertRule` compatibility.\n *\n * Single-pass scanner that handles all cleanup in one traversal:\n * - Strips block comments and line comments (preserves :// in URLs)\n * - Collapses whitespace to single spaces\n * - Removes redundant semicolons\n * - Trims leading/trailing whitespace\n */\nconst normCache = new Map<string, string>()\n/** Clear the normalizeCSS cache (called during HMR cleanup). */\nexport const clearNormCache = () => normCache.clear()\n\nexport const normalizeCSS = (css: string): string => {\n const cached = normCache.get(css)\n if (cached !== undefined) return cached\n\n const len = css.length\n let out = ''\n let space = false // pending space to emit before next non-whitespace char\n let last = 0 // charCode of last char written to output (0 = nothing yet)\n\n for (let i = 0; i < len; i++) {\n const c = css.charCodeAt(i)\n\n // /* block comment */\n if (c === 47 /* / */ && css.charCodeAt(i + 1) === 42 /* * */) {\n const end = css.indexOf('*/', i + 2)\n i = end === -1 ? len : end + 1\n space = true\n continue\n }\n\n // // line comment (but not :// in URLs)\n if (c === 47 /* / */ && css.charCodeAt(i + 1) === 47 /* / */ && last !== 58 /* : */) {\n const nl = css.indexOf('\\n', i + 2)\n i = nl === -1 ? len : nl\n space = true\n continue\n }\n\n // Whitespace → collapse\n if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {\n space = true\n continue\n }\n\n // Semicolon → skip if redundant (after start, {, }, or another ;)\n if (c === 59 /* ; */) {\n if (last === 0 || last === 123 /* { */ || last === 125 /* } */ || last === 59 /* ; */) {\n continue\n }\n space = false\n out += ';'\n last = 59\n continue\n }\n\n // Regular char — emit pending space (but not at start of output)\n if (space && last !== 0) out += ' '\n space = false\n\n out += css[i]\n last = c\n }\n\n // Evict oldest ~10% to prevent memory leaks without cliff-edge drop\n if (normCache.size > 2000) {\n let count = 0\n for (const key of normCache.keys()) {\n if (count >= 200) break\n normCache.delete(key)\n count++\n }\n }\n normCache.set(css, out)\n\n return out\n}\n\nexport const resolveValue = (value: Interpolation, props: Record<string, any>): string => {\n // null, undefined, false, true → empty (enables conditional: ${cond && css`...`})\n if (value == null || value === false || value === true) return ''\n\n // function interpolation → call with props/theme context, resolve result\n if (typeof value === 'function') return resolveValue(value(props) as Interpolation, props)\n\n // nested CSSResult → recursively resolve\n if (value instanceof CSSResult) return resolve(value.strings, value.values, props)\n\n // array of results (e.g. from makeItResponsive's breakpoints.map())\n if (Array.isArray(value)) {\n let arrayResult = ''\n for (let i = 0; i < value.length; i++) {\n arrayResult += resolveValue(value[i], props)\n }\n return arrayResult\n }\n\n return String(value)\n}\n","import { CSSResult, type Interpolation } from './resolve'\n\n/**\n * Tagged template function for CSS. Captures the template strings and\n * interpolation values as a lazy CSSResult — resolution is deferred\n * until a styled component renders.\n *\n * Works as both a tagged template (`css\\`...\\``) and a regular function\n * call (`css(...args)`) since tagged templates are syntactic sugar for\n * function calls with (TemplateStringsArray, ...values).\n */\nexport const css = (strings: TemplateStringsArray, ...values: Interpolation[]): CSSResult =>\n new CSSResult(strings, values)\n","/**\n * HTML prop filtering. Prevents unknown props from being forwarded to DOM\n * elements (which causes warnings). Props starting with `$` are\n * transient (styling-only) and are always filtered out.\n */\n\n// Common HTML attributes, event handlers, and ARIA/data attributes\nconst HTML_PROPS = new Set([\n // Core props\n 'className',\n 'class',\n 'dangerouslySetInnerHTML',\n 'htmlFor',\n 'id',\n 'key',\n 'ref',\n 'style',\n 'tabIndex',\n 'role',\n // Event handlers\n 'onAbort',\n 'onAnimationEnd',\n 'onAnimationIteration',\n 'onAnimationStart',\n 'onBlur',\n 'onChange',\n 'onClick',\n 'onCompositionEnd',\n 'onCompositionStart',\n 'onCompositionUpdate',\n 'onContextMenu',\n 'onCopy',\n 'onCut',\n 'onDoubleClick',\n 'onDrag',\n 'onDragEnd',\n 'onDragEnter',\n 'onDragLeave',\n 'onDragOver',\n 'onDragStart',\n 'onDrop',\n 'onError',\n 'onFocus',\n 'onInput',\n 'onKeyDown',\n 'onKeyPress',\n 'onKeyUp',\n 'onLoad',\n 'onMouseDown',\n 'onMouseEnter',\n 'onMouseLeave',\n 'onMouseMove',\n 'onMouseOut',\n 'onMouseOver',\n 'onMouseUp',\n 'onPaste',\n 'onPointerCancel',\n 'onPointerDown',\n 'onPointerEnter',\n 'onPointerLeave',\n 'onPointerMove',\n 'onPointerOut',\n 'onPointerOver',\n 'onPointerUp',\n 'onScroll',\n 'onSelect',\n 'onSubmit',\n 'onTouchCancel',\n 'onTouchEnd',\n 'onTouchMove',\n 'onTouchStart',\n 'onTransitionEnd',\n 'onWheel',\n // HTML attributes\n 'accept',\n 'acceptCharset',\n 'accessKey',\n 'action',\n 'allow',\n 'allowFullScreen',\n 'alt',\n 'as',\n 'async',\n 'autoCapitalize',\n 'autoComplete',\n 'autoCorrect',\n 'autoFocus',\n 'autoPlay',\n 'capture',\n 'cellPadding',\n 'cellSpacing',\n 'charSet',\n 'checked',\n 'cite',\n 'cols',\n 'colSpan',\n 'content',\n 'contentEditable',\n 'controls',\n 'controlsList',\n 'coords',\n 'crossOrigin',\n 'dateTime',\n 'decoding',\n 'default',\n 'defaultChecked',\n 'defaultValue',\n 'defer',\n 'dir',\n 'disabled',\n 'disablePictureInPicture',\n 'disableRemotePlayback',\n 'download',\n 'draggable',\n 'encType',\n 'enterKeyHint',\n 'fetchPriority',\n 'form',\n 'formAction',\n 'formEncType',\n 'formMethod',\n 'formNoValidate',\n 'formTarget',\n 'frameBorder',\n 'headers',\n 'height',\n 'hidden',\n 'high',\n 'href',\n 'hrefLang',\n 'httpEquiv',\n 'inputMode',\n 'integrity',\n 'is',\n 'label',\n 'lang',\n 'list',\n 'loading',\n 'loop',\n 'low',\n 'max',\n 'maxLength',\n 'media',\n 'method',\n 'min',\n 'minLength',\n 'multiple',\n 'muted',\n 'name',\n 'noModule',\n 'noValidate',\n 'nonce',\n 'open',\n 'optimum',\n 'pattern',\n 'placeholder',\n 'playsInline',\n 'poster',\n 'preload',\n 'readOnly',\n 'referrerPolicy',\n 'rel',\n 'required',\n 'reversed',\n 'rows',\n 'rowSpan',\n 'sandbox',\n 'scope',\n 'scoped',\n 'scrolling',\n 'selected',\n 'shape',\n 'size',\n 'sizes',\n 'slot',\n 'span',\n 'spellCheck',\n 'src',\n 'srcDoc',\n 'srcLang',\n 'srcSet',\n 'start',\n 'step',\n 'summary',\n 'target',\n 'title',\n 'translate',\n 'type',\n 'useMap',\n 'value',\n 'width',\n 'wrap',\n])\n\n/**\n * Filters props for HTML elements. Keeps valid HTML attrs, data-*, aria-*.\n * Rejects unknown props and $-prefixed transient props.\n */\nexport const filterProps = (props: Record<string, unknown>): Record<string, unknown> => {\n const filtered: Record<string, unknown> = {}\n\n for (const key in props) {\n // Skip transient props ($-prefixed) — used for styling-only props\n if (key.charCodeAt(0) === 36) continue // '$'\n\n // Skip `as` prop — handled separately by styled\n if (key === 'as') continue\n\n // Keep data-* and aria-* attributes\n if (key.startsWith('data-') || key.startsWith('aria-')) {\n filtered[key] = props[key]\n continue\n }\n\n // Keep known HTML props\n if (HTML_PROPS.has(key)) {\n filtered[key] = props[key]\n }\n }\n\n return filtered\n}\n\n/**\n * Build final props for a styled component in a single pass.\n * Combines className merging, ref injection, and prop filtering into one\n * allocation and one iteration.\n */\nexport const buildProps = (\n rawProps: Record<string, any>,\n generatedCls: string,\n isDOM: boolean,\n customFilter?: (prop: string) => boolean,\n): Record<string, any> => {\n const result: Record<string, any> = {}\n\n // Merge generated + user className\n const userCls = rawProps.class || rawProps.className\n if (generatedCls) {\n result.class = userCls ? `${generatedCls} ${userCls}` : generatedCls\n } else if (userCls) {\n result.class = userCls\n }\n\n // Component target — forward all props except as/className/class and $-prefixed\n if (!isDOM) {\n for (const key in rawProps) {\n if (key === 'as' || key === 'className' || key === 'class') continue\n if (key.charCodeAt(0) === 36) continue // $-prefixed transient\n result[key] = rawProps[key]\n }\n return result\n }\n\n // DOM element with custom shouldForwardProp\n if (customFilter) {\n for (const key in rawProps) {\n if (key === 'as' || key === 'className' || key === 'class') continue\n if (customFilter(key)) result[key] = rawProps[key]\n }\n return result\n }\n\n // DOM element with default filtering\n for (const key in rawProps) {\n if (key === 'as' || key === 'className' || key === 'class') continue\n if (key.charCodeAt(0) === 36) continue // $-prefixed transient\n if (key.startsWith('data-') || key.startsWith('aria-')) {\n result[key] = rawProps[key]\n continue\n }\n if (HTML_PROPS.has(key)) result[key] = rawProps[key]\n }\n return result\n}\n","/**\n * Shared utilities used across multiple modules.\n */\nimport { CSSResult, type Interpolation } from './resolve'\n\n/** Check if an interpolation value is dynamic (contains functions or nested dynamic CSSResults). */\nexport const isDynamic = (v: Interpolation): boolean => {\n if (typeof v === 'function') return true\n if (Array.isArray(v)) return v.some(isDynamic)\n if (v instanceof CSSResult) return v.values.some(isDynamic)\n return false\n}\n","/**\n * Fast FNV-1a non-cryptographic hash. Returns base-36 string for compact class names.\n *\n * 32-bit hash space → ~4.3 billion unique values. Collision probability is\n * negligible for typical applications (< 10,000 unique CSS rules).\n */\n\n/** FNV-1a offset basis — starting state for streaming hash. */\nexport const HASH_INIT = 2166136261\n\nconst FNV_PRIME = 16777619\n\n/**\n * Feed a string segment into the running hash state.\n * Streaming: hashUpdate(hashUpdate(HASH_INIT, 'ab'), 'cd') === hash('abcd').\n */\nexport const hashUpdate = (init: number, str: string): number => {\n let h = init\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i)\n h = Math.imul(h, FNV_PRIME)\n }\n return h\n}\n\n/** Finalize a hash state into a base-36 class name suffix. */\nexport const hashFinalize = (h: number): string => (h >>> 0).toString(36)\n\n/** Hash a complete string in one shot. Returns base-36 string. */\nexport const hash = (str: string): string => hashFinalize(hashUpdate(HASH_INIT, str))\n","/**\n * StyleSheet manager. Handles CSS rule injection, hash-based deduplication,\n * SSR buffering, client-side hydration, bounded cache, and @layer support.\n *\n * Media queries (@media), @supports, and @container blocks nested inside\n * component CSS are automatically extracted into separate top-level rules.\n */\nimport { hash } from './hash'\nimport { clearNormCache } from './resolve'\n\nconst PREFIX = 'pyr'\nconst ATTR = 'data-pyreon-styler'\nconst DEFAULT_MAX_CACHE_SIZE = 10000\n\nexport interface StyleSheetOptions {\n /** Maximum number of cached rules before eviction (default: 10000). */\n maxCacheSize?: number\n /** CSS @layer name to wrap scoped rules in. */\n layer?: string\n}\n\nexport class StyleSheet {\n private cache = new Map<string, string>()\n private insertCache = new Map<string, string>()\n private sheet: CSSStyleSheet | null = null\n private ssrBuffer: string[] = []\n private isSSR: boolean\n private maxCacheSize: number\n private layer: string | undefined\n private supportsLayer = false\n\n constructor(options: StyleSheetOptions = {}) {\n this.maxCacheSize = options.maxCacheSize ?? DEFAULT_MAX_CACHE_SIZE\n this.layer = options.layer\n this.isSSR = typeof document === 'undefined'\n if (!this.isSSR) this.mount()\n }\n\n private mount() {\n // Reuse existing <style> tag from SSR hydration\n const existing = document.querySelector(`style[${ATTR}]`) as HTMLStyleElement | null\n\n if (existing) {\n this.sheet = existing.sheet ?? null\n this.hydrateFromTag(existing)\n } else {\n const el = document.createElement('style')\n el.setAttribute(ATTR, '')\n document.head.appendChild(el)\n this.sheet = el.sheet ?? null\n }\n\n // Inject CSS @layer ordering for the framework's cascade.\n //\n // Two layers: `elements` (base layout primitives) < `rocketstyle`\n // (themed component styles). The explicit ordering declaration\n // ensures rocketstyle theme styles always override element base\n // styles regardless of source order, while media queries within\n // each layer still work correctly (media conditions are evaluated\n // within each layer independently).\n //\n // Previously this used a single `@layer pyreon` which put\n // rocketstyle and elements in the same layer, relying on source\n // order. That broke when Elements were rendered WITHOUT a layer\n // (unlayered CSS always wins over layered CSS per the cascade\n // spec), making rocketstyle themes unable to override element\n // base styles.\n if (this.sheet) {\n try {\n this.sheet.insertRule('@layer elements, rocketstyle;', 0)\n this.supportsLayer = true\n } catch {\n // @layer not supported — falls back to source order\n }\n }\n }\n\n /** Extract className from a selector like \".pyr-abc\" or \".pyr-abc.pyr-abc\" → \"pyr-abc\" */\n private extractClassName(selectorText: string): string | null {\n if (selectorText[0] !== '.') return null\n const dotIdx = selectorText.indexOf('.', 1)\n return dotIdx > 0 ? selectorText.slice(1, dotIdx) : selectorText.slice(1)\n }\n\n /** Parse existing rules from SSR-rendered <style> tag into cache. */\n private hydrateFromTag(el: HTMLStyleElement) {\n const sheet = el.sheet\n if (!sheet) return\n\n for (let i = 0; i < sheet.cssRules.length; i++) {\n const rule = sheet.cssRules[i]\n\n if (rule instanceof CSSStyleRule) {\n const className = this.extractClassName(rule.selectorText)\n if (className) this.cache.set(className, className)\n }\n\n // Handle split @media rules that wrap our selectors\n if (typeof CSSMediaRule !== 'undefined' && rule instanceof CSSMediaRule) {\n for (let j = 0; j < rule.cssRules.length; j++) {\n const inner = rule.cssRules[j]\n if (inner instanceof CSSStyleRule) {\n const className = this.extractClassName(inner.selectorText)\n if (className) this.cache.set(className, className)\n }\n }\n }\n }\n }\n\n /** Evict oldest entries when cache exceeds max size. */\n private evictIfNeeded() {\n if (this.cache.size <= this.maxCacheSize) return\n\n // Map iteration order is insertion order — delete oldest 10%\n const toDelete = Math.floor(this.maxCacheSize * 0.1)\n let count = 0\n for (const key of this.cache.keys()) {\n if (count >= toDelete) break\n this.cache.delete(key)\n count++\n }\n }\n\n /**\n * Extract nested at-rules (@media, @supports, @container) from CSS text\n * and wrap their content in the given selector as separate top-level rules.\n */\n private splitAtRules(cssText: string, selector: string): { base: string; atRules: string[] } {\n // Fast path: no at-rules to split\n if (cssText.indexOf('@') === -1) return { base: cssText, atRules: [] }\n\n const atRules: string[] = []\n const baseParts: string[] = []\n let depth = 0\n let atStart = -1\n let lastBase = 0\n\n for (let i = 0; i < cssText.length; i++) {\n const ch = cssText[i]\n\n if (ch === '{') {\n depth++\n } else if (ch === '}') {\n depth--\n if (depth === 0 && atStart >= 0) {\n // End of a tracked at-rule block — extract and wrap with selector\n const openBrace = cssText.indexOf('{', atStart)\n const atPrefix = cssText.slice(atStart, openBrace).trim()\n const innerCSS = cssText.slice(openBrace + 1, i).trim()\n if (innerCSS) {\n atRules.push(`${atPrefix}{${selector}{${innerCSS}}}`)\n }\n atStart = -1\n lastBase = i + 1\n }\n } else if (depth === 0 && ch === '@' && atStart < 0) {\n // Check if this starts a splittable at-rule (not @keyframes, @font-face, etc.)\n const remaining = cssText.slice(i, i + 20)\n if (/^@(?:media|supports|container)\\b/.test(remaining)) {\n // Save any base CSS that precedes this at-rule\n const baseBefore = cssText.slice(lastBase, i).trim()\n if (baseBefore) baseParts.push(baseBefore)\n atStart = i\n }\n }\n }\n\n // Collect remaining base CSS after the last at-rule\n if (lastBase < cssText.length && atStart < 0) {\n const remaining = cssText.slice(lastBase).trim()\n if (remaining) baseParts.push(remaining)\n }\n\n // If no at-rules were found, return original unchanged\n if (atRules.length === 0) return { base: cssText, atRules: [] }\n\n return { base: baseParts.join(' '), atRules }\n }\n\n /**\n * Compute a className from CSS text without injecting (pure function).\n */\n getClassName(cssText: string): string {\n const cached = this.insertCache.get(cssText)\n if (cached) return cached\n const h = hash(cssText)\n return `${PREFIX}-${h}`\n }\n\n /**\n * Insert CSS rules for a component. Returns the class name (deterministic, hash-based).\n * Deduplicates: same CSS text always produces the same class name and\n * the rules are only injected once.\n *\n * @param cssText - CSS declarations to insert\n * @param _unused - Reserved for backward compatibility (was `boost`)\n * @param insertLayer - CSS @layer to wrap this rule in (e.g. 'rocketstyle').\n * Used by rocketstyle to ensure wrapper styles override inner component styles\n * via @layer order (base < rocketstyle) instead of specificity hacks.\n */\n insert(cssText: string, _unused = false, insertLayer?: string): string {\n // Fast path: skip hash computation on repeated insertions of same CSS text\n const icKey = insertLayer ? `${cssText}\\0L:${insertLayer}` : cssText\n const icHit = this.insertCache.get(icKey)\n if (icHit) return icHit\n\n const h = hash(cssText)\n const className = `${PREFIX}-${h}`\n\n if (this.cache.has(className)) {\n this.insertCache.set(icKey, className)\n return className\n }\n\n this.evictIfNeeded()\n this.cache.set(className, className)\n\n const selector = `.${className}`\n\n // Split nested at-rules into separate top-level rules\n const { base, atRules } = this.splitAtRules(cssText, selector)\n\n const rules: string[] = []\n if (base) rules.push(`${selector}{${base}}`)\n rules.push(...atRules)\n\n // Apply @layer wrapping — per-insert layer takes precedence over sheet-level layer.\n // In SSR, always apply layers (output goes to real browsers).\n // In client, skip if @layer isn't supported (e.g. happy-dom in tests).\n const layerName = (this.isSSR || this.supportsLayer) ? (insertLayer ?? this.layer) : undefined\n const finalRules = layerName ? rules.map((r) => `@layer ${layerName}{${r}}`) : rules\n\n if (this.isSSR) {\n for (const rule of finalRules) {\n this.ssrBuffer.push(rule)\n }\n } else if (this.sheet) {\n for (const rule of finalRules) {\n try {\n this.sheet.insertRule(rule, this.sheet.cssRules.length)\n } catch (_e) {\n if (process.env.NODE_ENV !== 'production') {\n // oxlint-disable-next-line no-console\n console.warn('[styler] Failed to insert CSS rule:', rule, _e)\n }\n }\n }\n }\n\n this.insertCache.set(icKey, className)\n return className\n }\n\n /** Insert a @keyframes rule. Deduplicates by animation name. */\n insertKeyframes(name: string, body: string): void {\n if (this.cache.has(name)) return\n\n this.evictIfNeeded()\n this.cache.set(name, name)\n\n const rule = `@keyframes ${name}{${body}}`\n\n if (this.isSSR) {\n this.ssrBuffer.push(rule)\n } else if (this.sheet) {\n try {\n this.sheet.insertRule(rule, this.sheet.cssRules.length)\n } catch (_e) {\n if (process.env.NODE_ENV !== 'production') {\n // silently ignore invalid CSS rules in production\n }\n }\n }\n }\n\n /**\n * Split CSS text into individual top-level rules.\n * CSSStyleSheet.insertRule() only accepts one rule at a time.\n */\n private splitRules(cssText: string): string[] {\n const rules: string[] = []\n let depth = 0\n let start = 0\n\n for (let i = 0; i < cssText.length; i++) {\n const ch = cssText[i]\n if (ch === '{') depth++\n else if (ch === '}') {\n depth--\n if (depth === 0) {\n const rule = cssText.slice(start, i + 1).trim()\n if (rule) rules.push(rule)\n start = i + 1\n }\n }\n }\n\n return rules\n }\n\n /** Insert global CSS rules (no wrapper selector). Deduplicates by hash. */\n insertGlobal(cssText: string): void {\n const h = hash(cssText)\n const key = `global-${h}`\n\n if (this.cache.has(key)) return\n\n this.evictIfNeeded()\n this.cache.set(key, key)\n\n if (this.isSSR) {\n this.ssrBuffer.push(cssText)\n } else if (this.sheet) {\n const rules = this.splitRules(cssText)\n for (const rule of rules) {\n try {\n this.sheet.insertRule(rule, this.sheet.cssRules.length)\n } catch (_e) {\n if (process.env.NODE_ENV !== 'production') {\n // oxlint-disable-next-line no-console\n console.warn('[styler] Failed to insert global CSS rule:', rule, _e)\n }\n }\n }\n }\n }\n\n /** Returns collected CSS for SSR as a complete `<style>` tag string. */\n getStyleTag(): string {\n if (this.ssrBuffer.length === 0) return `<style ${ATTR}=\"\"></style>`\n // Emit the layer ordering declaration for SSR output so the cascade\n // is correct when the browser parses the SSR HTML. On the client side\n // this ordering is injected via insertRule in mount().\n const layerDecl = this.hasLayeredRules()\n ? '@layer elements, rocketstyle;'\n : this.layer\n ? `@layer ${this.layer};`\n : ''\n const css = (layerDecl + this.ssrBuffer.join('')).replace(/<\\/style/gi, '<\\\\/style')\n return `<style ${ATTR}=\"\">${css}</style>`\n }\n\n /** Returns collected CSS rules as a raw string (useful for streaming SSR). */\n getStyles(): string {\n if (this.ssrBuffer.length === 0) return ''\n const layerDecl = this.hasLayeredRules()\n ? '@layer elements, rocketstyle;'\n : this.layer\n ? `@layer ${this.layer};`\n : ''\n return layerDecl + this.ssrBuffer.join('')\n }\n\n /** Check if any buffered SSR rules use @layer wrapping. */\n private hasLayeredRules(): boolean {\n return this.ssrBuffer.some((r) => r.startsWith('@layer '))\n }\n\n /** Reset SSR buffer and cache (call between server requests). */\n reset(): void {\n this.ssrBuffer = []\n this.cache.clear()\n this.insertCache.clear()\n }\n\n /** Clear the dedup cache. Useful for HMR / dev-time reloads. */\n clearCache(): void {\n this.cache.clear()\n this.insertCache.clear()\n clearNormCache()\n }\n\n /**\n * Full cleanup: clear cache and remove all CSS rules from the DOM.\n * Intended for HMR / dev-time reloads where stale styles must be purged.\n */\n clearAll(): void {\n this.cache.clear()\n this.insertCache.clear()\n clearNormCache()\n this.ssrBuffer = []\n if (this.sheet) {\n while (this.sheet.cssRules.length > 0) {\n this.sheet.deleteRule(0)\n }\n }\n }\n\n /**\n * Compute className and full CSS rule text without injecting.\n */\n prepare(cssText: string): { className: string; rules: string } {\n const h = hash(cssText)\n const className = `${PREFIX}-${h}`\n const selector = `.${className}`\n const { base, atRules } = this.splitAtRules(cssText, selector)\n\n const allRules: string[] = []\n if (base) allRules.push(`${selector}{${base}}`)\n allRules.push(...atRules)\n\n const finalRules = this.layer ? allRules.map((r) => `@layer ${this.layer}{${r}}`) : allRules\n\n return { className, rules: finalRules.join('') }\n }\n\n /** Check if a className is already in the cache. O(1) Map lookup. */\n has(className: string): boolean {\n return this.cache.has(className)\n }\n\n /** Current number of cached rules. */\n get cacheSize(): number {\n return this.cache.size\n }\n}\n\n/** Default singleton sheet for client-side use.\n * No default layer — each consumer specifies their own:\n * Elements use `{ layer: 'elements' }`\n * Rocketstyle uses `{ layer: 'rocketstyle' }`\n * The layer ordering `@layer elements, rocketstyle` is injected\n * in mount() so rocketstyle always overrides elements.\n */\nexport const sheet = new StyleSheet()\n\n/**\n * Factory for creating isolated StyleSheet instances.\n * Use in SSR to get per-request isolation.\n */\nexport const createSheet = (options?: StyleSheetOptions): StyleSheet => new StyleSheet(options)\n","/**\n * Theme context for styled components.\n *\n * Extensible theme interface. Consumers can augment this via module\n * declaration merging for full strict types:\n *\n * declare module '@pyreon/styler' {\n * interface DefaultTheme {\n * colors: { primary: string; secondary: string }\n * spacing: (n: number) => string\n * }\n * }\n */\nimport type { VNode, VNodeChild } from '@pyreon/core'\nimport { createReactiveContext, provide, useContext } from '@pyreon/core'\n\nexport interface DefaultTheme {}\n\ntype Theme = DefaultTheme & Record<string, unknown>\n\n/**\n * Reactive theme context. Consumers get `() => Theme` from useContext.\n *\n * The DIFFERENCE from PR #258: styled components read the theme accessor\n * inside a COMPUTED (not an effect). The computed tracks theme + mode +\n * dimensions simultaneously, and the resolve itself runs untracked.\n * This gives reactive theme/mode/dimension switching with:\n * - Zero per-component effect()\n * - One lightweight computed per component\n * - String-equality memoization (same CSS class = no DOM update)\n * - Untracked resolve (no exponential cascade)\n */\nexport const ThemeContext = createReactiveContext<Theme>({} as Theme)\n\n/**\n * Read the current theme. Returns the theme value (calls the accessor).\n * Inside a reactive scope (computed/effect), this tracks theme changes.\n */\nexport const useTheme = <T extends object = Theme>(): T => useContext(ThemeContext)() as T\n\n/**\n * Returns the raw `() => Theme` accessor for use inside computeds\n * where you need explicit control over when the read happens.\n */\nexport const useThemeAccessor = <T extends object = Theme>(): (() => T) =>\n useContext(ThemeContext) as () => T\n\n/**\n * @internal Low-level provider — use `PyreonUI` from `@pyreon/ui-core` instead.\n * @deprecated Prefer `<PyreonUI theme={theme}>`\n */\nexport function ThemeProvider({\n theme,\n children,\n}: {\n theme: Theme\n children?: VNodeChild\n}): VNode | null {\n provide(ThemeContext, () => theme)\n return (children ?? null) as VNode | null\n}\n","/**\n * createGlobalStyle() — tagged template function that injects global CSS\n * rules (not scoped to a class name). Returns a component function that\n * injects styles when called and supports dynamic interpolations via\n * props/theme.\n *\n * Usage:\n * const GlobalStyle = createGlobalStyle`\n * body { margin: 0; font-family: ${({ theme }) => theme.font}; }\n * *, *::before, *::after { box-sizing: border-box; }\n * `\n */\nimport type { ComponentFn } from '@pyreon/core'\nimport { type Interpolation, normalizeCSS, resolve } from './resolve'\nimport { isDynamic } from './shared'\nimport { sheet } from './sheet'\nimport { useTheme } from './ThemeProvider'\n\nexport const createGlobalStyle = (\n strings: TemplateStringsArray,\n ...values: Interpolation[]\n): ComponentFn => {\n const hasDynamicValues = values.some(isDynamic)\n\n // STATIC FAST PATH: compute once at creation time\n if (!hasDynamicValues) {\n const cssText = normalizeCSS(resolve(strings, values, {}))\n\n // Inject into sheet immediately\n if (cssText.trim()) sheet.insertGlobal(cssText)\n\n const StaticGlobal: ComponentFn = () => null\n return StaticGlobal\n }\n\n // DYNAMIC PATH: resolve on every render with theme/props\n const DynamicGlobal: ComponentFn = (props: Record<string, any>) => {\n const theme = useTheme()\n const allProps = { ...props, theme }\n const cssText = normalizeCSS(resolve(strings, values, allProps))\n\n if (cssText.trim()) sheet.insertGlobal(cssText)\n\n return null\n }\n\n return DynamicGlobal\n}\n","/**\n * keyframes() tagged template function. Creates a CSS @keyframes rule,\n * injects it into the stylesheet, and returns the generated animation name.\n *\n * Usage:\n * const fadeIn = keyframes`\n * from { opacity: 0; }\n * to { opacity: 1; }\n * `\n * // fadeIn === \"pyr-kf-abc123\" (deterministic, hash-based)\n */\nimport { hash } from './hash'\nimport { type Interpolation, normalizeCSS, resolve } from './resolve'\nimport { sheet } from './sheet'\n\nclass KeyframesResult {\n readonly name: string\n\n constructor(strings: TemplateStringsArray, values: Interpolation[]) {\n const body = normalizeCSS(resolve(strings, values, {}))\n const h = hash(body)\n this.name = `pyr-kf-${h}`\n\n sheet.insertKeyframes(this.name, body)\n }\n\n /** Returns the animation name when used in string context. */\n toString(): string {\n return this.name\n }\n}\n\nexport const keyframes = (\n strings: TemplateStringsArray,\n ...values: Interpolation[]\n): KeyframesResult => new KeyframesResult(strings, values)\n","/**\n * styled() component factory. Creates Pyreon components that inject CSS\n * class names from tagged template literals.\n *\n * Supports:\n * - styled('div')`...` and styled(Component)`...`\n * - styled.div`...` (via Proxy)\n * - `as` prop for polymorphic rendering\n * - $-prefixed transient props (not forwarded to DOM)\n * - Custom shouldForwardProp for per-component prop filtering\n * - Static path optimization (templates with no dynamic interpolations)\n * - Boost specificity via doubled selector\n *\n * CSS nesting (`&` selectors) works natively — the resolver passes CSS\n * through without transformation, so `&:hover`, `&::before`, etc. work\n * as-is in browsers supporting CSS Nesting (all modern browsers).\n */\nimport type { ComponentFn, VNode } from '@pyreon/core'\nimport { h } from '@pyreon/core'\nimport { computed, renderEffect, runUntracked } from '@pyreon/reactivity'\nimport { buildProps } from './forward'\nimport { type Interpolation, normalizeCSS, resolve } from './resolve'\nimport { isDynamic } from './shared'\nimport { sheet } from './sheet'\nimport { useThemeAccessor } from './ThemeProvider'\n\ntype Tag = string | ComponentFn<any>\n\nexport interface StyledOptions {\n /** Custom prop filter. Return true to forward the prop to the DOM element. */\n shouldForwardProp?: (prop: string) => boolean\n /**\n * CSS @layer name. Rules are wrapped in `@layer <name> { ... }`.\n * Framework CSS uses two layers with explicit ordering:\n * `@layer elements, rocketstyle;`\n * Elements (base layout) use `'elements'`, rocketstyle themes use\n * `'rocketstyle'`. The ordering ensures themes always override base\n * styles regardless of source order.\n */\n layer?: string\n}\n\nconst getDisplayName = (tag: Tag): string =>\n typeof tag === 'string'\n ? tag\n : (tag as ComponentFn<any> & { displayName?: string }).displayName || tag.name || 'Component'\n\n// Component cache: same template literal + tag + no options → same component.\n// WeakMap on `strings` (TemplateStringsArray is object-identity per source location).\nconst staticComponentCache = new WeakMap<TemplateStringsArray, Map<Tag, ComponentFn>>()\n\n// Single-entry hot cache — just 3 reference comparisons, no Map/WeakMap overhead.\nlet _hotStrings: TemplateStringsArray | null = null\nlet _hotTag: Tag | null = null\nlet _hotComponent: ComponentFn | null = null\n\nconst createStyledComponent = (\n tag: Tag,\n strings: TemplateStringsArray,\n values: Interpolation[],\n options?: StyledOptions,\n): ComponentFn => {\n // Ultra-fast hot cache: 3 reference comparisons → return immediately\n if (values.length === 0 && !options) {\n if (strings === _hotStrings && tag === _hotTag) return _hotComponent as ComponentFn\n\n // WeakMap fallback for alternating patterns\n const tagMap = staticComponentCache.get(strings)\n if (tagMap) {\n const cached = tagMap.get(tag)\n if (cached) {\n _hotStrings = strings\n _hotTag = tag\n _hotComponent = cached\n return cached\n }\n }\n }\n\n // Fast check: no values means no dynamic interpolations — avoids .some() scan\n const hasDynamicValues = values.length > 0 && values.some(isDynamic)\n const customFilter = options ? options.shouldForwardProp : undefined\n const insertLayer = options?.layer\n\n // STATIC FAST PATH: no function interpolations → compute class once at creation time\n if (!hasDynamicValues) {\n // Inline resolve for the common no-values case\n const raw = values.length === 0 ? (strings[0] as string) : resolve(strings, values, {})\n const cssText = normalizeCSS(raw)\n const hasCss = cssText.length > 0\n\n const staticClassName = hasCss ? sheet.insert(cssText, false, insertLayer) : ''\n\n const StaticStyled: ComponentFn = (rawProps: Record<string, any>): VNode | null => {\n const finalTag = rawProps.as || tag\n const isDOM = typeof finalTag === 'string'\n const finalProps = buildProps(rawProps, staticClassName, isDOM, customFilter)\n\n return h(\n finalTag as string,\n finalProps,\n ...(Array.isArray(rawProps.children)\n ? rawProps.children\n : rawProps.children != null\n ? [rawProps.children]\n : []),\n )\n }\n\n ;(StaticStyled as ComponentFn & { displayName?: string }).displayName =\n `styled(${getDisplayName(tag)})`\n\n // Store in component cache + hot cache for future reuse\n if (!options && values.length === 0) {\n let tagMap = staticComponentCache.get(strings)\n if (!tagMap) {\n tagMap = new Map()\n staticComponentCache.set(strings, tagMap)\n }\n tagMap.set(tag, StaticStyled)\n _hotStrings = strings\n _hotTag = tag\n _hotComponent = StaticStyled\n }\n\n return StaticStyled\n }\n\n // ─── Tier 2: Per-definition class cache ───────────────────────────────────\n // Two-level WeakMap: $rocketstyle → $rocketstate → className.\n // 50 identical Items with the same resolved theme → 1 resolve + 49 hits.\n const classCache = new WeakMap<object, WeakMap<object, string>>()\n\n // DYNAMIC PATH: uses computed() for reactive class derivation.\n //\n // Architecture:\n // - $rocketstyle/$rocketstate may be function ACCESSORS (from rocketstyle)\n // or plain objects (from direct styled() usage).\n // - When they're accessors, a computed() tracks them so mode/dimension\n // signal changes produce a new CSS class reactively.\n // - The resolve() itself runs UNTRACKED inside the computed to prevent\n // exponential cascade from theme deep-reads in interpolation functions.\n // - The computed memoizes by string equality — same CSS class = no DOM update.\n // - Pyreon's built-in renderEffect handles the DOM class attribute update\n // when the computed value changes.\n //\n // This gives reactive mode/dimension switching WITHOUT per-component effect().\n const DynamicStyled: ComponentFn = (rawProps: Record<string, any>): VNode | null => {\n const themeAccessor = useThemeAccessor()\n const theme = themeAccessor() // snapshot for initial + static path\n const $rs = rawProps.$rocketstyle\n const $rsState = rawProps.$rocketstate\n const isReactiveRS = typeof $rs === 'function'\n const isReactiveState = typeof $rsState === 'function'\n\n // Helper: resolve CSS + cache result\n const doResolve = (rs: any, rsState: any, t: any): string => {\n // Tier 2 cache: skip resolve if same object identity seen before\n if (rs && typeof rs === 'object' && rsState && typeof rsState === 'object') {\n const inner = classCache.get(rs)\n if (inner) {\n const cached = inner.get(rsState)\n if (cached !== undefined) return cached\n }\n }\n\n const resolveProps = {\n ...rawProps,\n ...(isReactiveRS ? { $rocketstyle: rs } : {}),\n ...(isReactiveState ? { $rocketstate: rsState } : {}),\n theme: t,\n }\n const cssText = normalizeCSS(resolve(strings, values, resolveProps))\n const className = cssText.length > 0 ? sheet.insert(cssText, false, insertLayer) : ''\n\n if (rs && typeof rs === 'object' && rsState && typeof rsState === 'object') {\n let inner = classCache.get(rs)\n if (!inner) {\n inner = new WeakMap()\n classCache.set(rs, inner)\n }\n inner.set(rsState, className)\n }\n return className\n }\n\n // If any axis is reactive, wrap in computed that tracks all three:\n // 1. $rocketstyle accessor (mode + dimension signals)\n // 2. $rocketstate accessor (state descriptor)\n // 3. themeAccessor (user-preference theme swap)\n // The resolve itself runs UNTRACKED to prevent exponential cascade.\n const hasReactive = isReactiveRS || isReactiveState\n const cssClass = hasReactive\n ? computed(() => {\n // TRACKED reads:\n const rs = isReactiveRS ? $rs() : $rs\n const rsState = isReactiveState ? $rsState() : $rsState\n const t = themeAccessor() // TRACKED — theme swap\n\n // UNTRACKED: resolve + sheet insert\n return runUntracked(() => doResolve(rs, rsState, t))\n }, { equals: (a, b) => a === b })\n : null\n\n const finalTag = rawProps.as || tag\n const isDOM = typeof finalTag === 'string'\n\n // Initial class: computed (reactive) or direct resolve (static)\n const className = cssClass\n ? cssClass()\n : doResolve($rs, $rsState, theme)\n const finalProps = buildProps(rawProps, className, isDOM, customFilter)\n\n // Reactive path: lightweight renderEffect that reads the pre-computed\n // class string and toggles classList. This is NOT the old PR #258\n // approach — the expensive resolve() already happened inside the\n // computed. This renderEffect only does: read string → compare → toggle.\n if (cssClass) {\n let el: Element | null = null\n let currentClassName = className\n\n const originalRef = finalProps.ref\n finalProps.ref = (node: Element | null) => {\n el = node\n if (originalRef) {\n if (typeof originalRef === 'function') originalRef(node)\n else if (originalRef && typeof originalRef === 'object') (originalRef as any).current = node\n }\n }\n\n renderEffect(() => {\n const newClass = cssClass() // reads computed — O(1), just string\n if (el && newClass !== currentClassName) {\n if (currentClassName) el.classList.remove(currentClassName)\n if (newClass) el.classList.add(newClass)\n currentClassName = newClass\n }\n })\n }\n\n return h(\n finalTag as string,\n finalProps,\n ...(Array.isArray(rawProps.children)\n ? rawProps.children\n : rawProps.children != null\n ? [rawProps.children]\n : []),\n )\n }\n\n ;(DynamicStyled as ComponentFn & { displayName?: string }).displayName =\n `styled(${getDisplayName(tag)})`\n return DynamicStyled\n}\n\n/** Factory function: styled(tag) returns a tagged template function. */\nconst styledFactory = (tag: Tag, options?: StyledOptions) => {\n const templateFn = (strings: TemplateStringsArray, ...values: Interpolation[]) =>\n createStyledComponent(tag, strings, values, options)\n\n return templateFn\n}\n\n/**\n * Main styled export. Supports both calling conventions:\n * - `styled('div')` or `styled(Component)` → returns tagged template function\n * - `styled('div', { shouldForwardProp })` → with custom prop filtering\n * - `styled.div` → shorthand via Proxy (no options)\n */\n// Cache template functions per tag to avoid closure allocation on every Proxy get\nconst proxyCache = new Map<string, (...args: any[]) => any>()\n\n/**\n * Generic tagged template function returned by `styled(tag)` and `styled.tag`.\n *\n * Accepts an optional type parameter `<P>` for consumer-defined props\n * (typically transient $-prefixed props that aren't forwarded to the DOM).\n *\n * @example\n * const Box = styled('div')<{ $color: string }>`\n * background: ${(props) => props.$color};\n * `\n * <Box $color=\"red\" /> // $color is required and typed\n */\ntype TagTemplateFn = <P extends object = Record<string, unknown>>(\n strings: TemplateStringsArray,\n ...values: Interpolation<P>[]\n) => ComponentFn<P & Record<string, unknown>>\n\ntype HtmlTags =\n | 'a'\n | 'abbr'\n | 'address'\n | 'article'\n | 'aside'\n | 'audio'\n | 'b'\n | 'blockquote'\n | 'body'\n | 'br'\n | 'button'\n | 'canvas'\n | 'caption'\n | 'code'\n | 'col'\n | 'colgroup'\n | 'dd'\n | 'details'\n | 'div'\n | 'dl'\n | 'dt'\n | 'em'\n | 'fieldset'\n | 'figcaption'\n | 'figure'\n | 'footer'\n | 'form'\n | 'h1'\n | 'h2'\n | 'h3'\n | 'h4'\n | 'h5'\n | 'h6'\n | 'head'\n | 'header'\n | 'hr'\n | 'html'\n | 'i'\n | 'iframe'\n | 'img'\n | 'input'\n | 'label'\n | 'legend'\n | 'li'\n | 'link'\n | 'main'\n | 'mark'\n | 'menu'\n | 'meta'\n | 'nav'\n | 'ol'\n | 'optgroup'\n | 'option'\n | 'output'\n | 'p'\n | 'picture'\n | 'pre'\n | 'progress'\n | 'q'\n | 'section'\n | 'select'\n | 'small'\n | 'source'\n | 'span'\n | 'strong'\n | 'style'\n | 'sub'\n | 'summary'\n | 'sup'\n | 'svg'\n | 'table'\n | 'tbody'\n | 'td'\n | 'template'\n | 'textarea'\n | 'tfoot'\n | 'th'\n | 'thead'\n | 'time'\n | 'tr'\n | 'u'\n | 'ul'\n | 'video'\n\nexport type StyledFunction = ((tag: Tag, options?: StyledOptions) => TagTemplateFn) & {\n [K in HtmlTags]: TagTemplateFn\n}\n\n// Proxy is needed to support styled.div`...` syntax; the cast bridges\n// styledFactory's call signature to StyledFunction which adds HTML tag properties.\n// Proxy target uses `as any` because TS can't resolve Proxy<StyledFunction> with mapped types\nexport const styled: StyledFunction = new Proxy(styledFactory as any, {\n get(_target: unknown, prop: string) {\n if (prop === 'prototype' || prop === '$$typeof') return undefined\n // styled.div`...`, styled.span`...`, etc.\n let fn = proxyCache.get(prop)\n if (!fn) {\n fn = (strings: TemplateStringsArray, ...values: Interpolation[]) =>\n createStyledComponent(prop, strings, values)\n proxyCache.set(prop, fn)\n }\n return fn\n },\n})\n","/**\n * Hook that resolves a CSSResult template with props, injects CSS\n * into the shared stylesheet, and returns the className.\n *\n * Use this when you need computed CSS class names on plain elements\n * without the overhead of a styled component layer.\n */\nimport { type CSSResult, normalizeCSS, resolve } from './resolve'\nimport { sheet } from './sheet'\nimport { useTheme } from './ThemeProvider'\n\nexport function useCSS(template: CSSResult, props?: Record<string, any>, boost?: boolean): string {\n const theme = useTheme()\n const allProps = theme ? { ...props, theme } : (props ?? {})\n const cssText = normalizeCSS(resolve(template.strings, template.values, allProps))\n\n if (!cssText.trim()) return ''\n\n return sheet.insert(cssText, boost)\n}\n"],"mappings":"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"}