rnwind 0.0.8 → 0.0.9

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 (131) hide show
  1. package/lib/cjs/core/parser/color.cjs +33 -1
  2. package/lib/cjs/core/parser/color.cjs.map +1 -1
  3. package/lib/cjs/core/parser/color.d.ts +10 -0
  4. package/lib/cjs/core/parser/declaration.cjs +121 -9
  5. package/lib/cjs/core/parser/declaration.cjs.map +1 -1
  6. package/lib/cjs/core/parser/gradient.cjs +46 -12
  7. package/lib/cjs/core/parser/gradient.cjs.map +1 -1
  8. package/lib/cjs/core/parser/gradient.d.ts +2 -1
  9. package/lib/cjs/core/parser/keyframes.cjs +27 -12
  10. package/lib/cjs/core/parser/keyframes.cjs.map +1 -1
  11. package/lib/cjs/core/parser/keyframes.d.ts +11 -0
  12. package/lib/cjs/core/parser/layout-dispatcher.cjs +33 -10
  13. package/lib/cjs/core/parser/layout-dispatcher.cjs.map +1 -1
  14. package/lib/cjs/core/parser/length.cjs +17 -1
  15. package/lib/cjs/core/parser/length.cjs.map +1 -1
  16. package/lib/cjs/core/parser/safe-area.cjs +24 -3
  17. package/lib/cjs/core/parser/safe-area.cjs.map +1 -1
  18. package/lib/cjs/core/parser/theme-vars.cjs +58 -8
  19. package/lib/cjs/core/parser/theme-vars.cjs.map +1 -1
  20. package/lib/cjs/core/parser/tokens.cjs +77 -9
  21. package/lib/cjs/core/parser/tokens.cjs.map +1 -1
  22. package/lib/cjs/core/parser/tokens.d.ts +9 -0
  23. package/lib/cjs/core/parser/transform.cjs +18 -9
  24. package/lib/cjs/core/parser/transform.cjs.map +1 -1
  25. package/lib/cjs/core/parser/tw-parser.cjs +93 -33
  26. package/lib/cjs/core/parser/tw-parser.cjs.map +1 -1
  27. package/lib/cjs/core/parser/typography-dispatcher.cjs +19 -1
  28. package/lib/cjs/core/parser/typography-dispatcher.cjs.map +1 -1
  29. package/lib/cjs/core/parser/typography.cjs +15 -18
  30. package/lib/cjs/core/parser/typography.cjs.map +1 -1
  31. package/lib/cjs/core/parser/typography.d.ts +5 -5
  32. package/lib/cjs/core/style-builder/union-builder.cjs +0 -10
  33. package/lib/cjs/core/style-builder/union-builder.cjs.map +1 -1
  34. package/lib/cjs/core/style-builder/union-builder.d.ts +0 -8
  35. package/lib/cjs/metro/dts.cjs +6 -1
  36. package/lib/cjs/metro/dts.cjs.map +1 -1
  37. package/lib/cjs/metro/transformer.cjs +42 -77
  38. package/lib/cjs/metro/transformer.cjs.map +1 -1
  39. package/lib/cjs/metro/with-config.cjs +9 -29
  40. package/lib/cjs/metro/with-config.cjs.map +1 -1
  41. package/lib/cjs/runtime/hooks/use-scheme.cjs +9 -6
  42. package/lib/cjs/runtime/hooks/use-scheme.cjs.map +1 -1
  43. package/lib/cjs/runtime/hooks/use-scheme.d.ts +7 -4
  44. package/lib/cjs/runtime/index.cjs +1 -1
  45. package/lib/cjs/runtime/index.cjs.map +1 -1
  46. package/lib/cjs/runtime/index.d.ts +1 -1
  47. package/lib/cjs/runtime/lookup-css.cjs +14 -0
  48. package/lib/cjs/runtime/lookup-css.cjs.map +1 -1
  49. package/lib/cjs/runtime/lookup-css.d.ts +11 -0
  50. package/lib/cjs/runtime/resolve.cjs +8 -6
  51. package/lib/cjs/runtime/resolve.cjs.map +1 -1
  52. package/lib/cjs/runtime/wrap.cjs +50 -57
  53. package/lib/cjs/runtime/wrap.cjs.map +1 -1
  54. package/lib/cjs/runtime/wrap.d.ts +10 -4
  55. package/lib/esm/core/parser/color.d.ts +10 -0
  56. package/lib/esm/core/parser/color.mjs +33 -2
  57. package/lib/esm/core/parser/color.mjs.map +1 -1
  58. package/lib/esm/core/parser/declaration.mjs +122 -10
  59. package/lib/esm/core/parser/declaration.mjs.map +1 -1
  60. package/lib/esm/core/parser/gradient.d.ts +2 -1
  61. package/lib/esm/core/parser/gradient.mjs +45 -11
  62. package/lib/esm/core/parser/gradient.mjs.map +1 -1
  63. package/lib/esm/core/parser/keyframes.d.ts +11 -0
  64. package/lib/esm/core/parser/keyframes.mjs +27 -12
  65. package/lib/esm/core/parser/keyframes.mjs.map +1 -1
  66. package/lib/esm/core/parser/layout-dispatcher.mjs +33 -10
  67. package/lib/esm/core/parser/layout-dispatcher.mjs.map +1 -1
  68. package/lib/esm/core/parser/length.mjs +17 -1
  69. package/lib/esm/core/parser/length.mjs.map +1 -1
  70. package/lib/esm/core/parser/safe-area.mjs +24 -3
  71. package/lib/esm/core/parser/safe-area.mjs.map +1 -1
  72. package/lib/esm/core/parser/theme-vars.mjs +58 -8
  73. package/lib/esm/core/parser/theme-vars.mjs.map +1 -1
  74. package/lib/esm/core/parser/tokens.d.ts +9 -0
  75. package/lib/esm/core/parser/tokens.mjs +77 -10
  76. package/lib/esm/core/parser/tokens.mjs.map +1 -1
  77. package/lib/esm/core/parser/transform.mjs +18 -9
  78. package/lib/esm/core/parser/transform.mjs.map +1 -1
  79. package/lib/esm/core/parser/tw-parser.mjs +95 -35
  80. package/lib/esm/core/parser/tw-parser.mjs.map +1 -1
  81. package/lib/esm/core/parser/typography-dispatcher.mjs +19 -1
  82. package/lib/esm/core/parser/typography-dispatcher.mjs.map +1 -1
  83. package/lib/esm/core/parser/typography.d.ts +5 -5
  84. package/lib/esm/core/parser/typography.mjs +15 -18
  85. package/lib/esm/core/parser/typography.mjs.map +1 -1
  86. package/lib/esm/core/style-builder/union-builder.d.ts +0 -8
  87. package/lib/esm/core/style-builder/union-builder.mjs +0 -10
  88. package/lib/esm/core/style-builder/union-builder.mjs.map +1 -1
  89. package/lib/esm/metro/dts.mjs +6 -1
  90. package/lib/esm/metro/dts.mjs.map +1 -1
  91. package/lib/esm/metro/transformer.mjs +42 -77
  92. package/lib/esm/metro/transformer.mjs.map +1 -1
  93. package/lib/esm/metro/with-config.mjs +10 -30
  94. package/lib/esm/metro/with-config.mjs.map +1 -1
  95. package/lib/esm/runtime/hooks/use-scheme.d.ts +7 -4
  96. package/lib/esm/runtime/hooks/use-scheme.mjs +9 -6
  97. package/lib/esm/runtime/hooks/use-scheme.mjs.map +1 -1
  98. package/lib/esm/runtime/index.d.ts +1 -1
  99. package/lib/esm/runtime/index.mjs +1 -1
  100. package/lib/esm/runtime/index.mjs.map +1 -1
  101. package/lib/esm/runtime/lookup-css.d.ts +11 -0
  102. package/lib/esm/runtime/lookup-css.mjs +14 -1
  103. package/lib/esm/runtime/lookup-css.mjs.map +1 -1
  104. package/lib/esm/runtime/resolve.mjs +9 -7
  105. package/lib/esm/runtime/resolve.mjs.map +1 -1
  106. package/lib/esm/runtime/wrap.d.ts +10 -4
  107. package/lib/esm/runtime/wrap.mjs +50 -57
  108. package/lib/esm/runtime/wrap.mjs.map +1 -1
  109. package/package.json +1 -1
  110. package/src/core/parser/color.ts +32 -1
  111. package/src/core/parser/declaration.ts +119 -10
  112. package/src/core/parser/gradient.ts +48 -11
  113. package/src/core/parser/keyframes.ts +31 -3
  114. package/src/core/parser/layout-dispatcher.ts +32 -9
  115. package/src/core/parser/length.ts +18 -1
  116. package/src/core/parser/safe-area.ts +23 -2
  117. package/src/core/parser/theme-vars.ts +75 -8
  118. package/src/core/parser/tokens.ts +76 -9
  119. package/src/core/parser/transform.ts +19 -8
  120. package/src/core/parser/tw-parser.ts +95 -30
  121. package/src/core/parser/typography-dispatcher.ts +20 -1
  122. package/src/core/parser/typography.ts +15 -15
  123. package/src/core/style-builder/union-builder.ts +0 -11
  124. package/src/metro/dts.ts +6 -1
  125. package/src/metro/transformer.ts +42 -78
  126. package/src/metro/with-config.ts +10 -29
  127. package/src/runtime/hooks/use-scheme.ts +9 -6
  128. package/src/runtime/index.ts +1 -1
  129. package/src/runtime/lookup-css.ts +14 -0
  130. package/src/runtime/resolve.ts +9 -7
  131. package/src/runtime/wrap.tsx +57 -61
@@ -1 +1 @@
1
- {"version":3,"file":"lookup-css.mjs","sources":["../../../../src/runtime/lookup-css.ts"],"sourcesContent":["/**\n * Runtime resolver for rnwind-transformed files.\n *\n * Hot path is ONE WeakMap.get + cached-array return for stable atoms\n * (no `active:`/`focus:`/`*-safe` variance beyond what the cache key\n * captures). First call per (hoist, scheme, stateIndex) walks the\n * atoms once, looks each up as\n *\n * `cache.atoms[scheme]?.[atom] ?? cache.atoms.common?.[atom]`\n *\n * and caches the result. `registerAtoms(scheme, record)` bumps a\n * version counter; the next lookup notices the mismatch and rebuilds.\n *\n * Keyframes are inlined directly into atom values via `animationName`\n * at build time — no separate registry.\n */\n\nimport type { RnwindState } from './components/rnwind-provider'\n\n/** Empty sentinel returned when the input is null / undefined / empty. */\nconst EMPTY_STYLES: readonly unknown[] = []\n\n/** Registry key for the always-loaded fallback scheme. */\nconst COMMON_SCHEME = 'common'\n\n/** Atom name prefix marking a press-state-gated atom. */\nconst ACTIVE_PREFIX = 'active:'\n\n/** Atom name prefix marking a focus-state-gated atom. */\nconst FOCUS_PREFIX = 'focus:'\n\n/** Partial record — missing keys resolve to undefined, which the fallback handles. */\ntype SchemeAtomsRecord = Partial<Record<string, unknown>>\n\n/** 0 = idle, 1 = active, 2 = focus, 3 = both. */\ntype StateIndex = 0 | 1 | 2 | 3\n\n/**\n * One entry in the sorted-by-threshold breakpoints array. The runtime\n * derives an atom's threshold by matching its `<prefix>:` against\n * `name`; the array form is preferred over a Map so the hot-path\n * `tierFor(width)` walk is a tight numeric loop.\n */\ninterface BreakpointEntry {\n readonly name: string\n readonly minWidth: number\n}\n\n/**\n * Process-global style cache. Replaced key-by-key by {@link registerAtoms}.\n * Plain record-of-records: `scheme → atom → style`. Active scheme\n * lookup is `cache.atoms[scheme]?.[atom]` — two property reads with\n * an `?? cache.atoms.common[atom]` fallback. No loops over the\n * registry, ever.\n *\n * `breakpoints` mirrors the build-time table the manifest module\n * registers via {@link registerBreakpoints} — `name → px-threshold` for\n * fast prefix-based atom filtering plus the sorted-by-threshold list\n * for cheap tier-index computation in `lookupCss`.\n */\nconst cache = {\n atoms: Object.create(null) as Partial<Record<string, SchemeAtomsRecord>>,\n breakpoints: Object.create(null) as Partial<Record<string, number>>,\n breakpointList: [] as readonly BreakpointEntry[],\n}\n\n/**\n * Bumps on every {@link registerAtoms} call. {@link HoistCache} entries\n * stamp themselves with the current version; a mismatch on read\n * triggers a rebuild so HMR-reloaded atoms propagate without manual\n * invalidation.\n */\nlet atomVersion = 0\n\n/** Optional window-height provider for the `screen-minus-y` marker. */\ntype WindowHeightProvider = () => number\nlet windowHeightProvider: WindowHeightProvider | null = null\n\n/**\n * Optional scheme loader. Registered by the generated manifest module\n * (`rnwind/__generated/schemes`) once at import time. SchemeProvider\n * calls it synchronously on every render with the active scheme name;\n * first call per scheme pulls the scheme's style module in via an\n * inline `require()` — subsequent calls are a no-op through Metro's\n * module cache.\n */\ntype SchemeLoader = (scheme: string) => void\nlet schemeLoader: SchemeLoader | null = null\n\n/** Module-scope flag so the missing-insets warning fires at most once. */\nlet WARNED_MISSING_INSETS = false\n\n/** Atoms we've already dev-warned about — keeps the noise to ONE line per typo per session. */\nconst WARNED_UNKNOWN_ATOMS = new Set<string>()\n\n/**\n * Compute the state-array index from the live interactState. Bit-or\n * encoding: 0 = idle, 1 = active, 2 = focus, 3 = both.\n * @param interactState Snapshot from `useInteract()` (or undefined).\n * @returns 0 / 1 / 2 / 3.\n */\nfunction stateIndexFor(interactState: InteractState | undefined): StateIndex {\n if (!interactState) return 0\n return (((interactState.active ? 1 : 0) | (interactState.focus ? 2 : 0)) as StateIndex)\n}\n\n/**\n * Fetch the px inset for one side. Falls back to 0 when insets is undefined.\n * @param side Compact side tag (`t` / `r` / `b` / `l`).\n * @param insets Active insets.\n * @returns Px value for that side.\n */\nfunction insetOf(side: string, insets: LookupInsets | undefined): number {\n if (!insets) return 0\n if (side === 't') return insets.top\n if (side === 'r') return insets.right\n if (side === 'b') return insets.bottom\n if (side === 'l') return insets.left\n return 0\n}\n\n/**\n * Collapse one safe-area marker into a concrete px number using the\n * active insets.\n * @param spec Marker spec tuple `[cssKey, sideTag, or, offset]`.\n * @param insets Active insets (or undefined → 0).\n * @returns Resolved px number.\n */\nfunction resolveMarker(spec: SafeMarkerSpec, insets: LookupInsets | undefined): number {\n const [, side, or_, offset] = spec\n if (side === 'screen-minus-y') {\n const h = windowHeightProvider ? windowHeightProvider() : 0\n return Math.max(0, h - insetOf('t', insets) - insetOf('b', insets))\n }\n let base = insetOf(side, insets)\n if (or_ !== undefined) base = Math.max(base, or_)\n if (offset !== undefined) base += offset\n return base\n}\n\n/**\n * Emit a one-shot dev warning when a safe-area atom resolves without\n * real insets in scope.\n * @param insets Insets received by the resolver.\n */\nfunction warnMissingInsetsOnce(insets: LookupInsets | undefined): void {\n if (WARNED_MISSING_INSETS) return\n const isDevelopment = typeof __DEV__ === 'undefined' || __DEV__\n if (!isDevelopment) return\n if (insets && (insets.top !== 0 || insets.right !== 0 || insets.bottom !== 0 || insets.left !== 0)) return\n WARNED_MISSING_INSETS = true\n // eslint-disable-next-line no-console\n console.warn(\n 'rnwind: a `*-safe` utility resolved with zero insets. Wire `insets` on <SchemeProvider> ' +\n '(e.g. `insets={useSafeAreaInsets()}` from react-native-safe-area-context).',\n )\n}\n\n/**\n * Resolve precomputed safe-area marker specs into a fresh RN style\n * object. Cannot be cached — insets vary per render with rotation /\n * keyboard.\n * @param specs Array of spec tuples.\n * @param insets Live safe-area insets.\n * @returns Fresh RN style object with concrete numbers.\n */\nfunction resolveSafe(specs: readonly SafeMarkerSpec[], insets: LookupInsets | undefined): Record<string, number> {\n warnMissingInsetsOnce(insets)\n const out: Record<string, number> = {}\n for (const spec of specs) out[spec[0]] = resolveMarker(spec, insets)\n return out\n}\n\n/**\n * Multiply `fontSize` / `lineHeight` in a resolved atom value by the\n * active font scale. Early-returns the original reference for any atom\n * that doesn't carry either property (most of them) — zero allocation\n * on the hot path for non-text atoms.\n * @param value Atom value as registered in the global table.\n * @param fontScale Multiplier from `useWindowDimensions().fontScale`.\n * @returns Scaled style object, or the original when no scaling applied.\n */\nfunction applyFontScale(value: unknown, fontScale: number): unknown {\n if (fontScale === 1) return value\n if (typeof value !== 'object' || value === null) return value\n const record = value as Record<string, unknown>\n const fs = record.fontSize\n const lh = record.lineHeight\n if (typeof fs !== 'number' && typeof lh !== 'number') return value\n const scaled: Record<string, unknown> = { ...record }\n if (typeof fs === 'number') scaled.fontSize = fs * fontScale\n if (typeof lh === 'number') scaled.lineHeight = lh * fontScale\n return scaled\n}\n\n/**\n * Read the precomputed safe-area marker spec list off an atom value.\n * Build-side `envelopeSafeMarkers` wraps safe atoms in\n * `{__safeStyle: [...]}`; this is a single property access.\n * @param value Atom value as registered in the global table.\n * @returns Spec array when the atom is safe-area, else null.\n */\nfunction readSafeSpecs(value: unknown): readonly SafeMarkerSpec[] | null {\n if (typeof value !== 'object' || value === null) return null\n const safe = (value as { __safeStyle?: readonly SafeMarkerSpec[] }).__safeStyle\n return safe ?? null\n}\n\n/**\n * Per-atom lookup. Two property reads: scheme's own table then the\n * common fallback. Returns `undefined` for unknown atoms — the caller\n * skips them.\n * @param scheme Active scheme.\n * @param atom Atom name.\n * @returns Resolved value, or undefined.\n */\nfunction lookupAtom(scheme: string, atom: string): unknown {\n const schemeTable = cache.atoms[scheme]\n if (schemeTable !== undefined) {\n const own = schemeTable[atom]\n if (own !== undefined) return own\n }\n const common = cache.atoms[COMMON_SCHEME]\n return common === undefined ? undefined : common[atom]\n}\n\n/**\n * Whether an atom should participate in a given interact-state index.\n * - idle (0): no `active:` / `focus:` atoms.\n * - active (1): base + `active:`.\n * - focus (2): base + `focus:`.\n * - both (3): base + `active:` + `focus:`.\n * @param atom Atom name.\n * @param stateIndex Encoded state (0/1/2/3).\n * @returns True when the atom should be emitted for this state.\n */\nfunction atomMatchesState(atom: string, stateIndex: StateIndex): boolean {\n // Cheap prefix check — check the first code point before the full\n // `startsWith` so we skip it for any atom whose first letter isn't\n // `a` / `f`.\n const code = atom.codePointAt(0)\n if (code === 97 /* a */ && atom.startsWith(ACTIVE_PREFIX)) return (stateIndex & 1) !== 0\n if (code === 102 /* f */ && atom.startsWith(FOCUS_PREFIX)) return (stateIndex & 2) !== 0\n return true\n}\n\n/**\n * Whether an atom passes the responsive-breakpoint gate for the\n * current `windowWidth`. Atoms without a registered `<prefix>:` are\n * always-on (the common case — `bg-red-500`, `active:bg-blue-700`).\n * Atoms whose first prefix matches a registered breakpoint name pass\n * only when `windowWidth >= threshold`.\n * @param atom Atom name.\n * @param windowWidth Live `useWindowDimensions().width` snapshot.\n * @returns True when the atom should be emitted for this width.\n */\nfunction atomMatchesBreakpoint(atom: string, windowWidth: number): boolean {\n const colon = atom.indexOf(':')\n if (colon === -1) return true\n const prefix = atom.slice(0, colon)\n const threshold = cache.breakpoints[prefix]\n if (threshold === undefined) return true\n return windowWidth >= threshold\n}\n\n/**\n * Tier index — count of registered breakpoints whose threshold is\n * `<= windowWidth`. Bounded by the breakpoint count, so it's a stable\n * cache-key dimension instead of the unbounded raw width. Crossings\n * happen ~5 times across the device-width spectrum, not per-pixel.\n * @param windowWidth Live width.\n * @returns Tier 0..N where N = `cache.breakpointList.length`.\n */\nfunction tierFor(windowWidth: number): number {\n let tier = 0\n for (const entry of cache.breakpointList) {\n if (windowWidth >= entry.minWidth) tier += 1\n else break\n }\n return tier\n}\n\n/**\n * Build the style array for a (hoist, scheme, state, width) tuple.\n * Walks the atom list, applies the interact-state and breakpoint\n * filters, resolves each atom via scheme→common fallback, and\n * envelopes safe values via {@link resolveSafe}.\n * @param atoms Atom name list (build-time constant).\n * @param scheme Active scheme.\n * @param stateIndex Encoded active/focus state.\n * @param insets Live safe-area insets.\n * @param fontScale Font scale multiplier.\n * @param windowWidth Live window width — gates `md:*` / `lg:*` atoms.\n * @returns Fresh style array.\n */\nfunction buildStyleArray(\n atoms: readonly string[],\n scheme: string,\n stateIndex: StateIndex,\n insets: LookupInsets | undefined,\n fontScale: number,\n windowWidth: number,\n): readonly unknown[] {\n const out: unknown[] = []\n for (const atom of atoms) {\n if (!atomMatchesState(atom, stateIndex)) continue\n if (!atomMatchesBreakpoint(atom, windowWidth)) continue\n const value = lookupAtom(scheme, atom)\n if (value === undefined) {\n warnUnknownAtomOnce(atom)\n continue\n }\n const safe = readSafeSpecs(value)\n const resolved = safe === null ? value : resolveSafe(safe, insets)\n out.push(applyFontScale(resolved, fontScale))\n }\n return out\n}\n\n/**\n * Emit a one-shot dev warning when an atom name doesn't resolve in the\n * registry. The two real causes are a typo (`bg-red-501`) or a class\n * the build-time scanner never saw because it lives in a string the\n * oxide tokeniser can't see (e.g. computed at runtime). Either way, a\n * silent empty style is the worst possible UX — surface it.\n *\n * Filters cosmetic non-issues: empty strings, build-time `__safeStyle`\n * envelopes that wandered in, etc.\n * @param atom Class name that didn't resolve.\n */\nfunction warnUnknownAtomOnce(atom: string): void {\n if (atom.length === 0) return\n const isDevelopment = typeof __DEV__ === 'undefined' || __DEV__\n if (!isDevelopment) return\n if (WARNED_UNKNOWN_ATOMS.has(atom)) return\n WARNED_UNKNOWN_ATOMS.add(atom)\n // eslint-disable-next-line no-console\n console.warn(\n `rnwind: unknown class \"${atom}\" — typo, or the class is built dynamically and the build-time ` +\n `scanner never saw it. Static literals + ternaries are scanned automatically; runtime-built ` +\n `strings need to appear somewhere as a literal so oxide can pick them up.`,\n )\n}\n\n/**\n * Per-hoist cache entry. `version` stamps `atomVersion` at build time\n * so HMR reloads (which bump the counter) invalidate cleanly on next\n * read. `hasSafe` prevents caching results whose values depend on\n * per-render insets. `byKey` maps `\"${scheme}|${stateIndex}\"` to the\n * cached result.\n */\ninterface HoistCache {\n version: number\n hasSafe: boolean\n byKey: Partial<Record<string, readonly unknown[]>>\n}\n\n/**\n * Per-atom-list cache keyed on the hoist reference. WeakMap so\n * hoists GC with their host module on HMR.\n */\nconst resultCache = new WeakMap<readonly string[], HoistCache>()\n\n/**\n * Walk the atom list once to detect safe-area atoms — results that\n * vary per render with `insets`. When any atom envelopes safe specs\n * we skip the cache and rebuild every call.\n * @param atoms Hoist atom list.\n * @param scheme Active scheme.\n * @returns Whether the hoist resolves a safe atom under this scheme.\n */\nfunction detectHasSafe(atoms: readonly string[], scheme: string): boolean {\n for (const atom of atoms) {\n const value = lookupAtom(scheme, atom)\n if (readSafeSpecs(value) !== null) return true\n }\n return false\n}\n\n/**\n * Cache-keyed resolution for the common static-schema case. Returns a\n * stable array reference across renders until `atomVersion` bumps.\n * For hoists containing safe atoms — which depend on per-render\n * insets — rebuilds every call.\n *\n * The `tier` dimension keeps the cache bounded under responsive\n * variants: instead of keying on raw `windowWidth` (which would explode\n * the cache to one entry per pixel), we key on the count of registered\n * breakpoints whose threshold is reached. That gives at most\n * `breakpointCount + 1` cache rows per (scheme, state, fontScale).\n * @param atoms Hoist atom list.\n * @param scheme Active scheme.\n * @param stateIndex Encoded interact state.\n * @param insets Live safe-area insets.\n * @param fontScale Font scale multiplier.\n * @param windowWidth Live window width.\n * @returns Style array.\n */\nfunction lookupCached(\n atoms: readonly string[],\n scheme: string,\n stateIndex: StateIndex,\n insets: LookupInsets | undefined,\n fontScale: number,\n windowWidth: number,\n): readonly unknown[] {\n let entry = resultCache.get(atoms)\n if (entry?.version !== atomVersion) {\n entry = { version: atomVersion, hasSafe: detectHasSafe(atoms, scheme), byKey: Object.create(null) }\n resultCache.set(atoms, entry)\n }\n if (entry.hasSafe) return buildStyleArray(atoms, scheme, stateIndex, insets, fontScale, windowWidth)\n const tier = tierFor(windowWidth)\n const key = `${scheme}|${stateIndex}|${fontScale}|${tier}`\n const cached = entry.byKey[key]\n if (cached !== undefined) return cached\n const fresh = buildStyleArray(atoms, scheme, stateIndex, insets, fontScale, windowWidth)\n entry.byKey[key] = fresh\n return fresh\n}\n\n/**\n * Per-render snapshot of which interactive states (active, focus) are\n * currently engaged. Forwarded from the `useInteract()` hook the\n * transformer injects.\n */\nexport interface InteractState {\n active?: boolean\n focus?: boolean\n}\n\n/**\n * Safe-area insets bundle the transformer passes to `lookupCss` when a\n * file uses any `*-safe` utility.\n */\nexport interface LookupInsets {\n top: number\n right: number\n bottom: number\n left: number\n}\n\n\n/**\n * Precomputed safe-area marker spec emitted by the build-side\n * `envelopeSafeMarkers`. Tuple form: `[cssKey, sideTag, or, offset]`.\n */\nexport type SafeMarkerSpec = readonly [string, string, number | undefined, number | undefined]\n\n/** Type alias: the atom-list build output the transformer emits. */\nexport type HoistedClassName = readonly string[]\n\n/**\n * Register a window-height provider used by the `screen-minus-y`\n * safe-area variant. When not wired, `h-screen-safe` resolves to `0`.\n * @param provider Callback returning the current window height in px.\n */\nexport function setWindowHeightProvider(provider: WindowHeightProvider | null): void {\n windowHeightProvider = provider\n}\n\n/**\n * Register the scheme-loader function exported by the generated\n * manifest module. Called once at manifest-module evaluation time —\n * subsequent registrations override the previous loader (useful for\n * tests).\n * @param loader Manifest's `ensureSchemeLoaded` function, or null to\n * detach (tests).\n */\nexport function registerSchemeLoader(loader: SchemeLoader | null): void {\n schemeLoader = loader\n}\n\n/**\n * Ensure the given scheme's style module is loaded. Safe to call in\n * render — zero-cost after the first call per scheme thanks to\n * Metro's module cache, and a no-op when no loader is registered\n * (tests, or a bundle without rnwind-transformed sources).\n * @param scheme Active scheme name.\n */\nexport function loadScheme(scheme: string): void {\n if (schemeLoader) schemeLoader(scheme)\n}\n\n/**\n * Register (or re-register) one scheme's atoms in the global registry.\n * Pure property assignment — no iteration, no allocation. The version\n * counter bump invalidates every hoist-level result cache lazily on\n * next read.\n * @param scheme Registry key — `'common'` for the always-loaded\n * fallback, or a variant name (`'dark'`, `'light'`, `'brand'`, ...).\n * @param atoms Plain record keyed by atom name.\n */\nexport function registerAtoms(scheme: string, atoms: Record<string, unknown>): void {\n cache.atoms[scheme] = atoms\n atomVersion += 1\n}\n\n/**\n * Current registry version — bumps on every `registerAtoms` /\n * `registerBreakpoints`. The molecule resolver folds it into its cache\n * key so an HMR atom reload invalidates derived results.\n * @returns Monotonic version counter.\n */\nexport function getStyleVersion(): number {\n return atomVersion\n}\n\n/**\n * Register the responsive-breakpoint table the manifest module emits at\n * load time. Replaces the prior table — calling with `{}` clears it.\n * Bumps `atomVersion` so any cached lookup invalidates on next read,\n * which matters during a theme HMR cycle that adds/removes breakpoints.\n * @param breakpoints Breakpoint name → minimum-width threshold (px).\n */\nexport function registerBreakpoints(breakpoints: Record<string, number>): void {\n const fresh: Partial<Record<string, number>> = Object.create(null)\n const list: BreakpointEntry[] = []\n for (const name of Object.keys(breakpoints)) {\n const minWidth = breakpoints[name]\n if (!Number.isFinite(minWidth) || minWidth <= 0) continue\n fresh[name] = minWidth\n list.push({ name, minWidth })\n }\n list.sort((a, b) => a.minWidth - b.minWidth || a.name.localeCompare(b.name))\n cache.breakpoints = fresh\n cache.breakpointList = list\n atomVersion += 1\n}\n\n/**\n * Snapshot of the registered breakpoints, for callers that want to\n * compute their own derivations (e.g. the provider deriving the active\n * breakpoint name). Returns a fresh array — callers can iterate without\n * worrying about concurrent mutation from a manifest reload.\n * @returns Breakpoints sorted by ascending min-width threshold.\n */\nexport function getBreakpoints(): readonly BreakpointEntry[] {\n return cache.breakpointList\n}\n\n/**\n * Sentinel name returned by {@link activeBreakpointFor} ONLY when no\n * breakpoints are registered at all (bundle without rnwind-transformed\n * sources, fresh test setup). When at least one breakpoint is\n * registered, the function falls back to the smallest registered name\n * instead — so phone-width devices (402 dp on a stock iPhone, well\n * below `sm = 640`) report `activeBreakpoint === 'sm'` rather than the\n * abstract `'base'`. This matches the user expectation that the value\n * is always a real Tailwind breakpoint label they can branch on.\n *\n * Note: this is decoupled from the className filter. `sm:*` atoms\n * still only fire at `windowWidth >= 640` per Tailwind's mobile-first\n * spec — `activeBreakpoint === 'sm'` at 402 means \"I'm in the smallest\n * tier\", not \"`sm:` classes are firing\".\n */\nexport const BASE_BREAKPOINT = 'base'\n\n/**\n * Resolve the currently-active breakpoint name for a width:\n * - `windowWidth >= some threshold` → the highest matching breakpoint name.\n * - below every registered threshold → the smallest registered name.\n * - no breakpoints registered → {@link BASE_BREAKPOINT}.\n * Always returns a string so consumers can branch on it without\n * null-handling.\n * @param windowWidth Live window width in px.\n * @returns Active breakpoint name (never null).\n */\nexport function activeBreakpointFor(windowWidth: number): string {\n const list = cache.breakpointList\n if (list.length === 0) return BASE_BREAKPOINT\n let active: string = list[0]!.name\n for (const entry of list) {\n if (windowWidth >= entry.minWidth) active = entry.name\n else break\n }\n return active\n}\n\n/**\n * Resolve a className input against the active rnwind context. Hot\n * path:\n * - Array input (build hoist): ONE WeakMap.get + ONE record-access\n * + cached array return. No per-render allocation when there's no\n * userStyle and the hoist has no safe atoms.\n * - String input (dynamic `className={expr}`): tokenise + walk.\n * @param input Hoisted atom list or raw className string.\n * @param ctx Rnwind context — `{scheme, fontScale, insets}` (extra\n * fields ignored). Pass the result of `useRnwind()` directly.\n * @param userStyle Optional caller-supplied style appended last.\n * @param interactState Live active/focus flags from `useInteract()`.\n * @returns Style array for React Native's `style` prop.\n */\nexport function lookupCss(\n input: HoistedClassName | string | null | undefined,\n ctx: RnwindState,\n userStyle?: unknown,\n interactState?: InteractState,\n): readonly unknown[] {\n if (input === null || input === undefined) {\n return userStyle === undefined || userStyle === null ? EMPTY_STYLES : [userStyle]\n }\n const { scheme, insets, fontScale, windowWidth } = ctx\n if (typeof input === 'string') {\n const trimmed = input.trim()\n if (trimmed.length === 0) {\n return userStyle === undefined || userStyle === null ? EMPTY_STYLES : [userStyle]\n }\n const atoms = trimmed.split(/\\s+/)\n const out = buildStyleArray(atoms, scheme, stateIndexFor(interactState), insets, fontScale, windowWidth)\n if (userStyle === undefined || userStyle === null) return out\n return [...out, userStyle]\n }\n const base = lookupCached(input, scheme, stateIndexFor(interactState), insets, fontScale, windowWidth)\n if (userStyle === undefined || userStyle === null) return base\n return [...base, userStyle]\n}\n\n/** Test-only — clear the global registry between suites. */\nexport function __resetLookupCssState(): void {\n for (const key of Object.keys(cache.atoms)) delete cache.atoms[key]\n for (const key of Object.keys(cache.breakpoints)) delete cache.breakpoints[key]\n cache.breakpointList = []\n windowHeightProvider = null\n schemeLoader = null\n WARNED_MISSING_INSETS = false\n WARNED_UNKNOWN_ATOMS.clear()\n atomVersion += 1\n}\n\n/**\n * Test-only sugar: accept a single-scheme record and register it as the\n * `common` table.\n * @param record Atom name → value record (registered under `common`).\n */\nexport function __registerAtomsFromRecord(record: Record<string, unknown>): void {\n registerAtoms(COMMON_SCHEME, record)\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lookup-css.mjs","sources":["../../../../src/runtime/lookup-css.ts"],"sourcesContent":["/**\n * Runtime resolver for rnwind-transformed files.\n *\n * Hot path is ONE WeakMap.get + cached-array return for stable atoms\n * (no `active:`/`focus:`/`*-safe` variance beyond what the cache key\n * captures). First call per (hoist, scheme, stateIndex) walks the\n * atoms once, looks each up as\n *\n * `cache.atoms[scheme]?.[atom] ?? cache.atoms.common?.[atom]`\n *\n * and caches the result. `registerAtoms(scheme, record)` bumps a\n * version counter; the next lookup notices the mismatch and rebuilds.\n *\n * Keyframes are inlined directly into atom values via `animationName`\n * at build time — no separate registry.\n */\n\nimport type { RnwindState } from './components/rnwind-provider'\n\n/** Empty sentinel returned when the input is null / undefined / empty. */\nconst EMPTY_STYLES: readonly unknown[] = []\n\n/** Registry key for the always-loaded fallback scheme. */\nconst COMMON_SCHEME = 'common'\n\n/** Atom name prefix marking a press-state-gated atom. */\nconst ACTIVE_PREFIX = 'active:'\n\n/** Atom name prefix marking a focus-state-gated atom. */\nconst FOCUS_PREFIX = 'focus:'\n\n/** Partial record — missing keys resolve to undefined, which the fallback handles. */\ntype SchemeAtomsRecord = Partial<Record<string, unknown>>\n\n/** 0 = idle, 1 = active, 2 = focus, 3 = both. */\ntype StateIndex = 0 | 1 | 2 | 3\n\n/**\n * One entry in the sorted-by-threshold breakpoints array. The runtime\n * derives an atom's threshold by matching its `<prefix>:` against\n * `name`; the array form is preferred over a Map so the hot-path\n * `tierFor(width)` walk is a tight numeric loop.\n */\ninterface BreakpointEntry {\n readonly name: string\n readonly minWidth: number\n}\n\n/**\n * Process-global style cache. Replaced key-by-key by {@link registerAtoms}.\n * Plain record-of-records: `scheme → atom → style`. Active scheme\n * lookup is `cache.atoms[scheme]?.[atom]` — two property reads with\n * an `?? cache.atoms.common[atom]` fallback. No loops over the\n * registry, ever.\n *\n * `breakpoints` mirrors the build-time table the manifest module\n * registers via {@link registerBreakpoints} — `name → px-threshold` for\n * fast prefix-based atom filtering plus the sorted-by-threshold list\n * for cheap tier-index computation in `lookupCss`.\n */\nconst cache = {\n atoms: Object.create(null) as Partial<Record<string, SchemeAtomsRecord>>,\n breakpoints: Object.create(null) as Partial<Record<string, number>>,\n breakpointList: [] as readonly BreakpointEntry[],\n}\n\n/**\n * Bumps on every {@link registerAtoms} call. {@link HoistCache} entries\n * stamp themselves with the current version; a mismatch on read\n * triggers a rebuild so HMR-reloaded atoms propagate without manual\n * invalidation.\n */\nlet atomVersion = 0\n\n/** Optional window-height provider for the `screen-minus-y` marker. */\ntype WindowHeightProvider = () => number\nlet windowHeightProvider: WindowHeightProvider | null = null\n\n/**\n * Optional scheme loader. Registered by the generated manifest module\n * (`rnwind/__generated/schemes`) once at import time. SchemeProvider\n * calls it synchronously on every render with the active scheme name;\n * first call per scheme pulls the scheme's style module in via an\n * inline `require()` — subsequent calls are a no-op through Metro's\n * module cache.\n */\ntype SchemeLoader = (scheme: string) => void\nlet schemeLoader: SchemeLoader | null = null\n\n/** Module-scope flag so the missing-insets warning fires at most once. */\nlet WARNED_MISSING_INSETS = false\n\n/** Atoms we've already dev-warned about — keeps the noise to ONE line per typo per session. */\nconst WARNED_UNKNOWN_ATOMS = new Set<string>()\n\n/**\n * Compute the state-array index from the live interactState. Bit-or\n * encoding: 0 = idle, 1 = active, 2 = focus, 3 = both.\n * @param interactState Snapshot from `useInteract()` (or undefined).\n * @returns 0 / 1 / 2 / 3.\n */\nfunction stateIndexFor(interactState: InteractState | undefined): StateIndex {\n if (!interactState) return 0\n return (((interactState.active ? 1 : 0) | (interactState.focus ? 2 : 0)) as StateIndex)\n}\n\n/**\n * Fetch the px inset for one side. Falls back to 0 when insets is undefined.\n * @param side Compact side tag (`t` / `r` / `b` / `l`).\n * @param insets Active insets.\n * @returns Px value for that side.\n */\nfunction insetOf(side: string, insets: LookupInsets | undefined): number {\n if (!insets) return 0\n if (side === 't') return insets.top\n if (side === 'r') return insets.right\n if (side === 'b') return insets.bottom\n if (side === 'l') return insets.left\n return 0\n}\n\n/**\n * Collapse one safe-area marker into a concrete px number using the\n * active insets.\n * @param spec Marker spec tuple `[cssKey, sideTag, or, offset]`.\n * @param insets Active insets (or undefined → 0).\n * @returns Resolved px number.\n */\nfunction resolveMarker(spec: SafeMarkerSpec, insets: LookupInsets | undefined): number {\n const [, side, or_, offset] = spec\n if (side === 'screen-minus-y') {\n const h = windowHeightProvider ? windowHeightProvider() : 0\n return Math.max(0, h - insetOf('t', insets) - insetOf('b', insets))\n }\n let base = insetOf(side, insets)\n if (or_ !== undefined) base = Math.max(base, or_)\n if (offset !== undefined) base += offset\n return base\n}\n\n/**\n * Emit a one-shot dev warning when a safe-area atom resolves without\n * real insets in scope.\n * @param insets Insets received by the resolver.\n */\nfunction warnMissingInsetsOnce(insets: LookupInsets | undefined): void {\n if (WARNED_MISSING_INSETS) return\n const isDevelopment = typeof __DEV__ === 'undefined' || __DEV__\n if (!isDevelopment) return\n if (insets && (insets.top !== 0 || insets.right !== 0 || insets.bottom !== 0 || insets.left !== 0)) return\n WARNED_MISSING_INSETS = true\n // eslint-disable-next-line no-console\n console.warn(\n 'rnwind: a `*-safe` utility resolved with zero insets. Wire `insets` on <SchemeProvider> ' +\n '(e.g. `insets={useSafeAreaInsets()}` from react-native-safe-area-context).',\n )\n}\n\n/**\n * Resolve precomputed safe-area marker specs into a fresh RN style\n * object. Cannot be cached — insets vary per render with rotation /\n * keyboard.\n * @param specs Array of spec tuples.\n * @param insets Live safe-area insets.\n * @returns Fresh RN style object with concrete numbers.\n */\nfunction resolveSafe(specs: readonly SafeMarkerSpec[], insets: LookupInsets | undefined): Record<string, number> {\n warnMissingInsetsOnce(insets)\n const out: Record<string, number> = {}\n for (const spec of specs) out[spec[0]] = resolveMarker(spec, insets)\n return out\n}\n\n/**\n * Multiply `fontSize` / `lineHeight` in a resolved atom value by the\n * active font scale. Early-returns the original reference for any atom\n * that doesn't carry either property (most of them) — zero allocation\n * on the hot path for non-text atoms.\n * @param value Atom value as registered in the global table.\n * @param fontScale Multiplier from `useWindowDimensions().fontScale`.\n * @returns Scaled style object, or the original when no scaling applied.\n */\nfunction applyFontScale(value: unknown, fontScale: number): unknown {\n if (fontScale === 1) return value\n if (typeof value !== 'object' || value === null) return value\n const record = value as Record<string, unknown>\n const fs = record.fontSize\n const lh = record.lineHeight\n if (typeof fs !== 'number' && typeof lh !== 'number') return value\n const scaled: Record<string, unknown> = { ...record }\n if (typeof fs === 'number') scaled.fontSize = fs * fontScale\n if (typeof lh === 'number') scaled.lineHeight = lh * fontScale\n return scaled\n}\n\n/**\n * Read the precomputed safe-area marker spec list off an atom value.\n * Build-side `envelopeSafeMarkers` wraps safe atoms in\n * `{__safeStyle: [...]}`; this is a single property access.\n * @param value Atom value as registered in the global table.\n * @returns Spec array when the atom is safe-area, else null.\n */\nfunction readSafeSpecs(value: unknown): readonly SafeMarkerSpec[] | null {\n if (typeof value !== 'object' || value === null) return null\n const safe = (value as { __safeStyle?: readonly SafeMarkerSpec[] }).__safeStyle\n return safe ?? null\n}\n\n/**\n * Per-atom lookup. Two property reads: scheme's own table then the\n * common fallback. Returns `undefined` for unknown atoms — the caller\n * skips them.\n * @param scheme Active scheme.\n * @param atom Atom name.\n * @returns Resolved value, or undefined.\n */\nfunction lookupAtom(scheme: string, atom: string): unknown {\n const schemeTable = cache.atoms[scheme]\n if (schemeTable !== undefined) {\n const own = schemeTable[atom]\n if (own !== undefined) return own\n }\n const common = cache.atoms[COMMON_SCHEME]\n return common === undefined ? undefined : common[atom]\n}\n\n/**\n * Whether an atom should participate in a given interact-state index.\n * - idle (0): no `active:` / `focus:` atoms.\n * - active (1): base + `active:`.\n * - focus (2): base + `focus:`.\n * - both (3): base + `active:` + `focus:`.\n * @param atom Atom name.\n * @param stateIndex Encoded state (0/1/2/3).\n * @returns True when the atom should be emitted for this state.\n */\nfunction atomMatchesState(atom: string, stateIndex: StateIndex): boolean {\n // Cheap prefix check — check the first code point before the full\n // `startsWith` so we skip it for any atom whose first letter isn't\n // `a` / `f`.\n const code = atom.codePointAt(0)\n if (code === 97 /* a */ && atom.startsWith(ACTIVE_PREFIX)) return (stateIndex & 1) !== 0\n if (code === 102 /* f */ && atom.startsWith(FOCUS_PREFIX)) return (stateIndex & 2) !== 0\n return true\n}\n\n/**\n * Whether an atom passes the responsive-breakpoint gate for the\n * current `windowWidth`. Atoms without a registered `<prefix>:` are\n * always-on (the common case — `bg-red-500`, `active:bg-blue-700`).\n * Atoms whose first prefix matches a registered breakpoint name pass\n * only when `windowWidth >= threshold`.\n * @param atom Atom name.\n * @param windowWidth Live `useWindowDimensions().width` snapshot.\n * @returns True when the atom should be emitted for this width.\n */\nfunction atomMatchesBreakpoint(atom: string, windowWidth: number): boolean {\n const colon = atom.indexOf(':')\n if (colon === -1) return true\n const prefix = atom.slice(0, colon)\n const threshold = cache.breakpoints[prefix]\n if (threshold === undefined) return true\n return windowWidth >= threshold\n}\n\n/**\n * Tier index — count of registered breakpoints whose threshold is\n * `<= windowWidth`. Bounded by the breakpoint count, so it's a stable\n * cache-key dimension instead of the unbounded raw width. Crossings\n * happen ~5 times across the device-width spectrum, not per-pixel.\n * @param windowWidth Live width.\n * @returns Tier 0..N where N = `cache.breakpointList.length`.\n */\nfunction tierFor(windowWidth: number): number {\n let tier = 0\n for (const entry of cache.breakpointList) {\n if (windowWidth >= entry.minWidth) tier += 1\n else break\n }\n return tier\n}\n\n/**\n * Public breakpoint-tier for a width — the count of registered breakpoints\n * whose threshold is reached. Used by the runtime resolver as its width\n * cache dimension: the numeric tier is bounded AND exact, unlike the\n * clamped `activeBreakpoint` NAME (which collapses tier-0 into the smallest\n * breakpoint, so widths straddling that threshold would share a cache key\n * and serve a stale style).\n * @param windowWidth Live window width in px.\n * @returns Tier 0..N.\n */\nexport function breakpointTier(windowWidth: number): number {\n return tierFor(windowWidth)\n}\n\n/**\n * Build the style array for a (hoist, scheme, state, width) tuple.\n * Walks the atom list, applies the interact-state and breakpoint\n * filters, resolves each atom via scheme→common fallback, and\n * envelopes safe values via {@link resolveSafe}.\n * @param atoms Atom name list (build-time constant).\n * @param scheme Active scheme.\n * @param stateIndex Encoded active/focus state.\n * @param insets Live safe-area insets.\n * @param fontScale Font scale multiplier.\n * @param windowWidth Live window width — gates `md:*` / `lg:*` atoms.\n * @returns Fresh style array.\n */\nfunction buildStyleArray(\n atoms: readonly string[],\n scheme: string,\n stateIndex: StateIndex,\n insets: LookupInsets | undefined,\n fontScale: number,\n windowWidth: number,\n): readonly unknown[] {\n const out: unknown[] = []\n for (const atom of atoms) {\n if (!atomMatchesState(atom, stateIndex)) continue\n if (!atomMatchesBreakpoint(atom, windowWidth)) continue\n const value = lookupAtom(scheme, atom)\n if (value === undefined) {\n warnUnknownAtomOnce(atom)\n continue\n }\n const safe = readSafeSpecs(value)\n const resolved = safe === null ? value : resolveSafe(safe, insets)\n out.push(applyFontScale(resolved, fontScale))\n }\n return out\n}\n\n/**\n * Emit a one-shot dev warning when an atom name doesn't resolve in the\n * registry. The two real causes are a typo (`bg-red-501`) or a class\n * the build-time scanner never saw because it lives in a string the\n * oxide tokeniser can't see (e.g. computed at runtime). Either way, a\n * silent empty style is the worst possible UX — surface it.\n *\n * Filters cosmetic non-issues: empty strings, build-time `__safeStyle`\n * envelopes that wandered in, etc.\n * @param atom Class name that didn't resolve.\n */\nfunction warnUnknownAtomOnce(atom: string): void {\n if (atom.length === 0) return\n const isDevelopment = typeof __DEV__ === 'undefined' || __DEV__\n if (!isDevelopment) return\n if (WARNED_UNKNOWN_ATOMS.has(atom)) return\n WARNED_UNKNOWN_ATOMS.add(atom)\n // eslint-disable-next-line no-console\n console.warn(\n `rnwind: unknown class \"${atom}\" — typo, or the class is built dynamically and the build-time ` +\n `scanner never saw it. Static literals + ternaries are scanned automatically; runtime-built ` +\n `strings need to appear somewhere as a literal so oxide can pick them up.`,\n )\n}\n\n/**\n * Per-hoist cache entry. `version` stamps `atomVersion` at build time\n * so HMR reloads (which bump the counter) invalidate cleanly on next\n * read. `hasSafe` prevents caching results whose values depend on\n * per-render insets. `byKey` maps `\"${scheme}|${stateIndex}\"` to the\n * cached result.\n */\ninterface HoistCache {\n version: number\n hasSafe: boolean\n byKey: Partial<Record<string, readonly unknown[]>>\n}\n\n/**\n * Per-atom-list cache keyed on the hoist reference. WeakMap so\n * hoists GC with their host module on HMR.\n */\nconst resultCache = new WeakMap<readonly string[], HoistCache>()\n\n/**\n * Walk the atom list once to detect safe-area atoms — results that\n * vary per render with `insets`. When any atom envelopes safe specs\n * we skip the cache and rebuild every call.\n * @param atoms Hoist atom list.\n * @param scheme Active scheme.\n * @returns Whether the hoist resolves a safe atom under this scheme.\n */\nfunction detectHasSafe(atoms: readonly string[], scheme: string): boolean {\n for (const atom of atoms) {\n const value = lookupAtom(scheme, atom)\n if (readSafeSpecs(value) !== null) return true\n }\n return false\n}\n\n/**\n * Cache-keyed resolution for the common static-schema case. Returns a\n * stable array reference across renders until `atomVersion` bumps.\n * For hoists containing safe atoms — which depend on per-render\n * insets — rebuilds every call.\n *\n * The `tier` dimension keeps the cache bounded under responsive\n * variants: instead of keying on raw `windowWidth` (which would explode\n * the cache to one entry per pixel), we key on the count of registered\n * breakpoints whose threshold is reached. That gives at most\n * `breakpointCount + 1` cache rows per (scheme, state, fontScale).\n * @param atoms Hoist atom list.\n * @param scheme Active scheme.\n * @param stateIndex Encoded interact state.\n * @param insets Live safe-area insets.\n * @param fontScale Font scale multiplier.\n * @param windowWidth Live window width.\n * @returns Style array.\n */\nfunction lookupCached(\n atoms: readonly string[],\n scheme: string,\n stateIndex: StateIndex,\n insets: LookupInsets | undefined,\n fontScale: number,\n windowWidth: number,\n): readonly unknown[] {\n let entry = resultCache.get(atoms)\n if (entry?.version !== atomVersion) {\n entry = { version: atomVersion, hasSafe: detectHasSafe(atoms, scheme), byKey: Object.create(null) }\n resultCache.set(atoms, entry)\n }\n if (entry.hasSafe) return buildStyleArray(atoms, scheme, stateIndex, insets, fontScale, windowWidth)\n const tier = tierFor(windowWidth)\n const key = `${scheme}|${stateIndex}|${fontScale}|${tier}`\n const cached = entry.byKey[key]\n if (cached !== undefined) return cached\n const fresh = buildStyleArray(atoms, scheme, stateIndex, insets, fontScale, windowWidth)\n entry.byKey[key] = fresh\n return fresh\n}\n\n/**\n * Per-render snapshot of which interactive states (active, focus) are\n * currently engaged. Forwarded from the `useInteract()` hook the\n * transformer injects.\n */\nexport interface InteractState {\n active?: boolean\n focus?: boolean\n}\n\n/**\n * Safe-area insets bundle the transformer passes to `lookupCss` when a\n * file uses any `*-safe` utility.\n */\nexport interface LookupInsets {\n top: number\n right: number\n bottom: number\n left: number\n}\n\n\n/**\n * Precomputed safe-area marker spec emitted by the build-side\n * `envelopeSafeMarkers`. Tuple form: `[cssKey, sideTag, or, offset]`.\n */\nexport type SafeMarkerSpec = readonly [string, string, number | undefined, number | undefined]\n\n/** Type alias: the atom-list build output the transformer emits. */\nexport type HoistedClassName = readonly string[]\n\n/**\n * Register a window-height provider used by the `screen-minus-y`\n * safe-area variant. When not wired, `h-screen-safe` resolves to `0`.\n * @param provider Callback returning the current window height in px.\n */\nexport function setWindowHeightProvider(provider: WindowHeightProvider | null): void {\n windowHeightProvider = provider\n}\n\n/**\n * Register the scheme-loader function exported by the generated\n * manifest module. Called once at manifest-module evaluation time —\n * subsequent registrations override the previous loader (useful for\n * tests).\n * @param loader Manifest's `ensureSchemeLoaded` function, or null to\n * detach (tests).\n */\nexport function registerSchemeLoader(loader: SchemeLoader | null): void {\n schemeLoader = loader\n}\n\n/**\n * Ensure the given scheme's style module is loaded. Safe to call in\n * render — zero-cost after the first call per scheme thanks to\n * Metro's module cache, and a no-op when no loader is registered\n * (tests, or a bundle without rnwind-transformed sources).\n * @param scheme Active scheme name.\n */\nexport function loadScheme(scheme: string): void {\n if (schemeLoader) schemeLoader(scheme)\n}\n\n/**\n * Register (or re-register) one scheme's atoms in the global registry.\n * Pure property assignment — no iteration, no allocation. The version\n * counter bump invalidates every hoist-level result cache lazily on\n * next read.\n * @param scheme Registry key — `'common'` for the always-loaded\n * fallback, or a variant name (`'dark'`, `'light'`, `'brand'`, ...).\n * @param atoms Plain record keyed by atom name.\n */\nexport function registerAtoms(scheme: string, atoms: Record<string, unknown>): void {\n cache.atoms[scheme] = atoms\n atomVersion += 1\n}\n\n/**\n * Current registry version — bumps on every `registerAtoms` /\n * `registerBreakpoints`. The molecule resolver folds it into its cache\n * key so an HMR atom reload invalidates derived results.\n * @returns Monotonic version counter.\n */\nexport function getStyleVersion(): number {\n return atomVersion\n}\n\n/**\n * Register the responsive-breakpoint table the manifest module emits at\n * load time. Replaces the prior table — calling with `{}` clears it.\n * Bumps `atomVersion` so any cached lookup invalidates on next read,\n * which matters during a theme HMR cycle that adds/removes breakpoints.\n * @param breakpoints Breakpoint name → minimum-width threshold (px).\n */\nexport function registerBreakpoints(breakpoints: Record<string, number>): void {\n const fresh: Partial<Record<string, number>> = Object.create(null)\n const list: BreakpointEntry[] = []\n for (const name of Object.keys(breakpoints)) {\n const minWidth = breakpoints[name]\n if (!Number.isFinite(minWidth) || minWidth <= 0) continue\n fresh[name] = minWidth\n list.push({ name, minWidth })\n }\n list.sort((a, b) => a.minWidth - b.minWidth || a.name.localeCompare(b.name))\n cache.breakpoints = fresh\n cache.breakpointList = list\n atomVersion += 1\n}\n\n/**\n * Snapshot of the registered breakpoints, for callers that want to\n * compute their own derivations (e.g. the provider deriving the active\n * breakpoint name). Returns a fresh array — callers can iterate without\n * worrying about concurrent mutation from a manifest reload.\n * @returns Breakpoints sorted by ascending min-width threshold.\n */\nexport function getBreakpoints(): readonly BreakpointEntry[] {\n return cache.breakpointList\n}\n\n/**\n * Sentinel name returned by {@link activeBreakpointFor} ONLY when no\n * breakpoints are registered at all (bundle without rnwind-transformed\n * sources, fresh test setup). When at least one breakpoint is\n * registered, the function falls back to the smallest registered name\n * instead — so phone-width devices (402 dp on a stock iPhone, well\n * below `sm = 640`) report `activeBreakpoint === 'sm'` rather than the\n * abstract `'base'`. This matches the user expectation that the value\n * is always a real Tailwind breakpoint label they can branch on.\n *\n * Note: this is decoupled from the className filter. `sm:*` atoms\n * still only fire at `windowWidth >= 640` per Tailwind's mobile-first\n * spec — `activeBreakpoint === 'sm'` at 402 means \"I'm in the smallest\n * tier\", not \"`sm:` classes are firing\".\n */\nexport const BASE_BREAKPOINT = 'base'\n\n/**\n * Resolve the currently-active breakpoint name for a width:\n * - `windowWidth >= some threshold` → the highest matching breakpoint name.\n * - below every registered threshold → the smallest registered name.\n * - no breakpoints registered → {@link BASE_BREAKPOINT}.\n * Always returns a string so consumers can branch on it without\n * null-handling.\n * @param windowWidth Live window width in px.\n * @returns Active breakpoint name (never null).\n */\nexport function activeBreakpointFor(windowWidth: number): string {\n const list = cache.breakpointList\n if (list.length === 0) return BASE_BREAKPOINT\n let active: string = list[0]!.name\n for (const entry of list) {\n if (windowWidth >= entry.minWidth) active = entry.name\n else break\n }\n return active\n}\n\n/**\n * Resolve a className input against the active rnwind context. Hot\n * path:\n * - Array input (build hoist): ONE WeakMap.get + ONE record-access\n * + cached array return. No per-render allocation when there's no\n * userStyle and the hoist has no safe atoms.\n * - String input (dynamic `className={expr}`): tokenise + walk.\n * @param input Hoisted atom list or raw className string.\n * @param ctx Rnwind context — `{scheme, fontScale, insets}` (extra\n * fields ignored). Pass the result of `useRnwind()` directly.\n * @param userStyle Optional caller-supplied style appended last.\n * @param interactState Live active/focus flags from `useInteract()`.\n * @returns Style array for React Native's `style` prop.\n */\nexport function lookupCss(\n input: HoistedClassName | string | null | undefined,\n ctx: RnwindState,\n userStyle?: unknown,\n interactState?: InteractState,\n): readonly unknown[] {\n if (input === null || input === undefined) {\n return userStyle === undefined || userStyle === null ? EMPTY_STYLES : [userStyle]\n }\n const { scheme, insets, fontScale, windowWidth } = ctx\n if (typeof input === 'string') {\n const trimmed = input.trim()\n if (trimmed.length === 0) {\n return userStyle === undefined || userStyle === null ? EMPTY_STYLES : [userStyle]\n }\n const atoms = trimmed.split(/\\s+/)\n const out = buildStyleArray(atoms, scheme, stateIndexFor(interactState), insets, fontScale, windowWidth)\n if (userStyle === undefined || userStyle === null) return out\n return [...out, userStyle]\n }\n const base = lookupCached(input, scheme, stateIndexFor(interactState), insets, fontScale, windowWidth)\n if (userStyle === undefined || userStyle === null) return base\n return [...base, userStyle]\n}\n\n/** Test-only — clear the global registry between suites. */\nexport function __resetLookupCssState(): void {\n for (const key of Object.keys(cache.atoms)) delete cache.atoms[key]\n for (const key of Object.keys(cache.breakpoints)) delete cache.breakpoints[key]\n cache.breakpointList = []\n windowHeightProvider = null\n schemeLoader = null\n WARNED_MISSING_INSETS = false\n WARNED_UNKNOWN_ATOMS.clear()\n atomVersion += 1\n}\n\n/**\n * Test-only sugar: accept a single-scheme record and register it as the\n * `common` table.\n * @param record Atom name → value record (registered under `common`).\n */\nexport function __registerAtomsFromRecord(record: Record<string, unknown>): void {\n registerAtoms(COMMON_SCHEME, record)\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { lookupCss, getStyleVersion } from './lookup-css.mjs';
1
+ import { lookupCss, getStyleVersion, breakpointTier } from './lookup-css.mjs';
2
2
  import { normalizeClassName } from '../core/normalize-classname.mjs';
3
3
 
4
4
  /**
@@ -108,17 +108,19 @@ function registerHaptics(map) {
108
108
  const stateSignatureCache = new WeakMap();
109
109
  /**
110
110
  * Cache key dimension for the reactive context — everything that can
111
- * change a resolved style. Uses the breakpoint TIER (`activeBreakpoint`),
112
- * NOT the raw `windowWidth`: two widths in the same tier gate `md:*` atoms
113
- * identically, so they resolve the same. This collapses the window axis
114
- * from "every pixel" to ~6 values, bounding the cache on resizable
115
- * surfaces (web / desktop) without changing any result.
111
+ * change a resolved style. Uses the numeric breakpoint TIER (count of
112
+ * thresholds reached) from `breakpointTier(windowWidth)`, NOT the
113
+ * `activeBreakpoint` NAME: the name clamps tier-0 into the smallest
114
+ * breakpoint, so widths straddling that threshold (e.g. 320 vs 700 with
115
+ * `sm=640`) would collide on one cache key and serve a stale style. The
116
+ * tier is exact AND bounded — two widths in the same tier gate every
117
+ * `sm:`/`md:`/… atom identically, so they resolve the same.
116
118
  * @param state Rnwind context.
117
119
  * @returns Compact signature string.
118
120
  */
119
121
  function stateSignature(state) {
120
122
  const { insets } = state;
121
- return `${state.scheme}|${insets.top},${insets.right},${insets.bottom},${insets.left}|${state.fontScale}|${state.activeBreakpoint}`;
123
+ return `${state.scheme}|${insets.top},${insets.right},${insets.bottom},${insets.left}|${state.fontScale}|${breakpointTier(state.windowWidth)}`;
122
124
  }
123
125
  /**
124
126
  * Memoised {@link stateSignature} — one `WeakMap.get` on the hot path
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.mjs","sources":["../../../../src/runtime/resolve.ts"],"sourcesContent":["import { getStyleVersion, lookupCss, type InteractState } from './lookup-css'\nimport type { RnwindState } from './components/rnwind-provider'\nimport { normalizeClassName } from '../core/normalize-classname'\nimport type { GradientAtomInfo, GradientDirection } from '../core/parser/gradient'\nimport type { HapticRequest, HapticTrigger } from '../core/parser/haptics'\n\n/**\n * Rich className resolver — the runtime heart of the wrap / `useCss`.\n *\n * Resolution order, per className string:\n * 1. **Molecule** — a build-time PRE-MERGED single style object for the\n * whole literal className (per scheme). One map lookup returns it by\n * reference: no array, no merge, no per-atom loop. The common case.\n * 2. **Atom fallback** — for a className the scanner never saw (a\n * runtime-built string like `` `${className} px-2` ``) OR one that\n * carries context-dependent atoms (`pt-safe`, `text-base`, `md:*`),\n * fall back to per-atom resolution via `lookupCss`, which folds in\n * insets / fontScale / breakpoint / scheme.\n *\n * Results are cached by `(normalized className, scheme, insets, fontScale,\n * breakpoint)` so repeated renders return the SAME reference until the\n * reactive context changes. Atoms / molecules / features all live in\n * build-time registries the generated `.rnwind/*.js` modules populate.\n */\n\n/** Always-loaded fallback scheme key. */\nconst COMMON_SCHEME = 'common'\n\n/** Empty style sentinel. */\nconst EMPTY: readonly unknown[] = []\n\n/** scheme → normalized className → pre-merged style object. */\nlet molecules: Record<string, Record<string, unknown>> = Object.create(null)\n/** atom name → gradient role + resolved colour. */\nlet gradients: Record<string, GradientAtomInfo> = Object.create(null)\n/** atom name (incl. `active:`/`focus:` prefix) → haptic request. */\nlet haptics: Record<string, HapticRequest> = Object.create(null)\n/** Bumps on any molecule/gradient/haptic registration. */\nlet registryVersion = 0\n\n/** Per-(className·state) resolved cache — strong references between context changes. */\nconst resolvedCache = new Map<string, ResolvedCss>()\n/** Version the cache was last valid for (`getStyleVersion()` + {@link registryVersion}). */\nlet cachedFor = -1\n\n/**\n * Hard ceiling on the resolved cache. The cache is pure memoisation, so\n * eviction only costs a re-resolve (sub-µs) — never correctness. Build\n * molecules are NOT in here; they live permanently in `molecules`.\n */\nconst MAX_RESOLVED_CACHE = 2048\n\n/**\n * Store a resolved result, bulk-evicting the OLDEST half when the cache\n * hits {@link MAX_RESOLVED_CACHE}. `Map` preserves insertion order, so the\n * first keys are the oldest. Bulk eviction keeps the hot (cache-hit) path\n * free of per-access LRU bookkeeping at the cost of an occasional small\n * recompute burst under sustained pressure (web / long sessions).\n * @param key Cache key.\n * @param value Resolved result to store.\n */\nfunction cacheResolved(key: string, value: ResolvedCss): void {\n if (resolvedCache.size >= MAX_RESOLVED_CACHE) {\n let drop = resolvedCache.size >> 1\n for (const oldKey of resolvedCache.keys()) {\n resolvedCache.delete(oldKey)\n if (--drop <= 0) break\n }\n }\n resolvedCache.set(key, value)\n}\n\n/** A unit-square gradient endpoint. */\ninterface GradientPoint {\n readonly x: number\n readonly y: number\n}\n\n/** Rich resolution: the RN `style` plus any className-derived props. */\nexport interface ResolvedCss {\n /** RN `style` value — a single molecule object (by ref) or an atom array. */\n readonly style: unknown\n /** Gradient stop colours (when the className is a complete gradient). */\n readonly colors?: readonly string[]\n /** Gradient start point. */\n readonly start?: GradientPoint\n /** Gradient end point. */\n readonly end?: GradientPoint\n /** Text truncation line count. */\n readonly numberOfLines?: number\n /** Text ellipsize mode. */\n readonly ellipsizeMode?: 'tail' | 'clip'\n /** Haptic requests present on the className, for the wrap to dispatch. */\n readonly haptics?: readonly { readonly request: HapticRequest; readonly trigger: HapticTrigger }[]\n}\n\n/** `GradientDirection` → expo-linear-gradient start/end points. */\nconst DIRECTION_POINTS: Record<GradientDirection, { start: GradientPoint; end: GradientPoint }> = {\n 'to-t': { start: { x: 0.5, y: 1 }, end: { x: 0.5, y: 0 } },\n 'to-b': { start: { x: 0.5, y: 0 }, end: { x: 0.5, y: 1 } },\n 'to-l': { start: { x: 1, y: 0.5 }, end: { x: 0, y: 0.5 } },\n 'to-r': { start: { x: 0, y: 0.5 }, end: { x: 1, y: 0.5 } },\n 'to-tl': { start: { x: 1, y: 1 }, end: { x: 0, y: 0 } },\n 'to-tr': { start: { x: 0, y: 1 }, end: { x: 1, y: 0 } },\n 'to-bl': { start: { x: 1, y: 0 }, end: { x: 0, y: 1 } },\n 'to-br': { start: { x: 0, y: 0 }, end: { x: 1, y: 1 } },\n unknown: { start: { x: 0, y: 0.5 }, end: { x: 1, y: 0.5 } },\n}\n\n/**\n * Register one scheme's pre-merged molecules (atom-merged literal\n * classNames). Merges onto any existing entries for the scheme.\n * @param scheme Scheme name (or `'common'`).\n * @param entries Normalized className → merged style object.\n */\nexport function registerMolecules(scheme: string, entries: Record<string, unknown>): void {\n molecules[scheme] = { ...molecules[scheme], ...entries }\n registryVersion += 1\n}\n\n/**\n * Register the gradient atom map (atom name → role + resolved colour).\n * @param map Atom name → gradient info.\n */\nexport function registerGradients(map: Record<string, GradientAtomInfo>): void {\n gradients = map\n registryVersion += 1\n}\n\n/**\n * Register the haptic atom map (atom name → request).\n * @param map Atom name → haptic request.\n */\nexport function registerHaptics(map: Record<string, HapticRequest>): void {\n haptics = map\n registryVersion += 1\n}\n\n\n\n/**\n * Per-state-object signature memo. `RnwindState` is created fresh (via the\n * provider's `useMemo`) whenever any field changes, so its identity is a\n * sound key — a new object means a new signature. Keyed weakly so states\n * GC with their provider.\n */\nconst stateSignatureCache = new WeakMap<RnwindState, string>()\n\n/**\n * Cache key dimension for the reactive context — everything that can\n * change a resolved style. Uses the breakpoint TIER (`activeBreakpoint`),\n * NOT the raw `windowWidth`: two widths in the same tier gate `md:*` atoms\n * identically, so they resolve the same. This collapses the window axis\n * from \"every pixel\" to ~6 values, bounding the cache on resizable\n * surfaces (web / desktop) without changing any result.\n * @param state Rnwind context.\n * @returns Compact signature string.\n */\nfunction stateSignature(state: RnwindState): string {\n const { insets } = state\n return `${state.scheme}|${insets.top},${insets.right},${insets.bottom},${insets.left}|${state.fontScale}|${state.activeBreakpoint}`\n}\n\n/**\n * Memoised {@link stateSignature} — one `WeakMap.get` on the hot path\n * instead of rebuilding the template string every resolve.\n * @param state Rnwind context.\n * @returns Cached compact signature.\n */\nfunction stateSignatureCached(state: RnwindState): string {\n let signature = stateSignatureCache.get(state)\n if (signature === undefined) {\n signature = stateSignature(state)\n stateSignatureCache.set(state, signature)\n }\n return signature\n}\n\n/**\n * Compact signature of the live interactive state for the cache key.\n * @param interactState Active/focus flags, or undefined for the plain path.\n * @returns Two-bit signature (`''` when no interactive state).\n */\nfunction interactSignature(interactState?: InteractState): string {\n if (!interactState) return ''\n const active = interactState.active ? 1 : 0\n const focus = interactState.focus ? 1 : 0\n return `${active}${focus}`\n}\n\n/**\n * Whether a token is a feature-ONLY utility (gradient stop/direction,\n * haptic request, or text-truncate) that contributes NO RN `style`. These\n * are folded in via {@link attachFeatures}, so they must be kept OUT of\n * the `lookupCss` input — otherwise the atom resolver treats them as\n * unknown style atoms and emits a spurious \"unknown class\" dev warning\n * (e.g. for `active:haptic-rigid`).\n * @param token Atom name.\n * @returns True when the token carries no style.\n */\nfunction isFeatureOnlyToken(token: string): boolean {\n return Boolean(gradients[token]) || Boolean(haptics[token]) || truncateForToken(token) !== null\n}\n\n/**\n * Lifecycle trigger for a haptic atom from its variant prefix.\n * @param token Atom name (maybe `active:`/`focus:`/`hover:` prefixed).\n * @returns The trigger.\n */\nfunction hapticTriggerForToken(token: string): HapticTrigger {\n const colon = token.indexOf(':')\n if (colon === -1) return 'mount'\n const prefix = token.slice(0, colon)\n if (prefix === 'active') return 'pressIn'\n if (prefix === 'focus') return 'focus'\n if (prefix === 'hover') return 'hover'\n return 'mount'\n}\n\n/**\n * Syntactic text-truncate directive for one atom.\n * @param token Atom name.\n * @returns Partial truncate props, or null.\n */\nfunction truncateForToken(token: string): { numberOfLines?: number; ellipsizeMode?: 'tail' | 'clip' } | null {\n if (token === 'truncate') return { numberOfLines: 1, ellipsizeMode: 'tail' }\n if (token === 'text-ellipsis') return { ellipsizeMode: 'tail' }\n if (token === 'text-clip') return { ellipsizeMode: 'clip' }\n if (token === 'line-clamp-none') return { numberOfLines: 0 }\n if (token.startsWith('line-clamp-')) {\n const count = Number(token.slice('line-clamp-'.length))\n if (Number.isInteger(count) && count >= 0) return { numberOfLines: count }\n }\n return null\n}\n\n/**\n * Assemble gradient props from gradient roles present in the atom list.\n * @param tokens Atom names.\n * @returns `{colors, start, end}` or null when not a complete gradient.\n */\nfunction assembleGradient(tokens: readonly string[]): { colors: string[]; start: GradientPoint; end: GradientPoint } | null {\n let from: string | undefined\n let via: string | undefined\n let to: string | undefined\n let dir: GradientDirection | undefined\n for (const token of tokens) {\n const info = gradients[token]\n if (!info) continue\n switch (info.role) {\n case 'from': {\n from = info.color\n break\n }\n case 'via': {\n via = info.color\n break\n }\n case 'to': {\n to = info.color\n break\n }\n default: {\n ;({ dir } = info)\n }\n }\n }\n if (dir === undefined) return null\n const colors = [from, via, to].filter((color): color is string => color !== undefined)\n if (colors.length < 2) return null\n const points = DIRECTION_POINTS[dir]\n return { colors, start: points.start, end: points.end }\n}\n\n/**\n * Fold every truncate directive across the atom list into one result —\n * last token wins per prop (matches Tailwind last-wins).\n * @param tokens Atom names.\n * @returns Merged truncate props (empty when none apply).\n */\nfunction collectTruncate(tokens: readonly string[]): { numberOfLines?: number; ellipsizeMode?: 'tail' | 'clip' } {\n const out: { numberOfLines?: number; ellipsizeMode?: 'tail' | 'clip' } = {}\n for (const token of tokens) {\n const truncate = truncateForToken(token)\n if (!truncate) continue\n if (truncate.numberOfLines !== undefined) out.numberOfLines = truncate.numberOfLines\n if (truncate.ellipsizeMode !== undefined) out.ellipsizeMode = truncate.ellipsizeMode\n }\n return out\n}\n\n/**\n * Collect every haptic request present in the atom list, tagged with the\n * lifecycle trigger its variant prefix implies.\n * @param tokens Atom names.\n * @returns Haptic request list, or undefined when none apply.\n */\nfunction collectHaptics(tokens: readonly string[]): { request: HapticRequest; trigger: HapticTrigger }[] | undefined {\n let collected: { request: HapticRequest; trigger: HapticTrigger }[] | undefined\n for (const token of tokens) {\n const request = haptics[token]\n if (!request) continue\n collected ??= []\n collected.push({ request, trigger: hapticTriggerForToken(token) })\n }\n return collected\n}\n\n/**\n * Scan tokens for the className-derived feature props (gradient,\n * truncate, haptics) and fold them onto the base result.\n * @param base Result carrying the resolved `style`.\n * @param tokens Atom names.\n * @returns The result with any feature props attached.\n */\nfunction attachFeatures(base: ResolvedCss, tokens: readonly string[]): ResolvedCss {\n const { numberOfLines, ellipsizeMode } = collectTruncate(tokens)\n const collected = collectHaptics(tokens)\n const gradient = assembleGradient(tokens)\n const result: Mutable<ResolvedCss> = { style: base.style }\n if (gradient) {\n result.colors = gradient.colors\n result.start = gradient.start\n result.end = gradient.end\n }\n // `numberOfLines: 0` is kept (RN reads it as \"unlimited\"): `line-clamp-none`\n // must be able to explicitly reset an earlier `line-clamp-N` on the same\n // element — dropping the 0 would silently leave the prior limit in place.\n if (numberOfLines !== undefined) {\n result.numberOfLines = numberOfLines\n if (ellipsizeMode !== undefined) result.ellipsizeMode = ellipsizeMode\n }\n if (collected) result.haptics = collected\n return result\n}\n\n/**\n * Flatten the per-atom style array into ONE object — a *runtime molecule*.\n * RN flattens a style array left-to-right (later wins), which is exactly\n * `Object.assign` semantics, so the merged object renders identically\n * while giving dynamic (cva / clsx) classNames the same single-object\n * shape a build-time molecule has. The caller caches the result per\n * `(className · state)`, so the merge runs once per unique context.\n * @param array Per-atom style array from `lookupCss`.\n * @returns Single merged style object.\n */\nfunction mergeStyleArray(array: readonly unknown[]): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const entry of array) if (entry && typeof entry === 'object') Object.assign(out, entry)\n return out\n}\n\n/**\n * Compose a resolved style with a caller-supplied inline style (user wins).\n * @param style\n * @param userStyle\n */\nfunction withUserStyle(style: unknown, userStyle: unknown): unknown {\n return Array.isArray(style) ? [...style, userStyle] : [style, userStyle]\n}\n\n/**\n * Resolve a className against the reactive context into a style plus any\n * className-derived props. Molecule-first (one lookup, by reference),\n * atom-fallback for unseen / context-dependent strings, cached per\n * `(className, state)`.\n * @param className Raw className string.\n * @param state Rnwind context from `useRnwind()`.\n * @param userStyle Optional inline style appended last (wins).\n * @param interactState Live active/focus flags (for `active:`/`focus:` atoms).\n * @returns The resolved style + feature props.\n */\nexport function resolve(\n className: string | null | undefined,\n state: RnwindState,\n userStyle?: unknown,\n interactState?: InteractState,\n): ResolvedCss {\n const version = getStyleVersion() + registryVersion\n if (version !== cachedFor) {\n resolvedCache.clear()\n cachedFor = version\n }\n if (className == null) {\n return { style: userStyle === undefined || userStyle === null ? EMPTY : [userStyle] }\n }\n // Key on the RAW className so the hot (cache-hit) path skips normalize\n // entirely — normalization only runs on a miss. The state signature is\n // memoised per state object, so the hit path is one WeakMap.get + one\n // string concat + one Map.get.\n const key = `${className}@${stateSignatureCached(state)}@${interactSignature(interactState)}`\n const cached = resolvedCache.get(key)\n if (cached !== undefined) {\n return userStyle === undefined || userStyle === null ? cached : { ...cached, style: withUserStyle(cached.style, userStyle) }\n }\n const normalized = normalizeClassName(className)\n if (normalized.length === 0) {\n const empty: ResolvedCss = { style: EMPTY }\n cacheResolved(key, empty)\n return userStyle === undefined || userStyle === null ? empty : { style: [userStyle] }\n }\n // Molecules are static pre-merges; anything carrying `active:`/`focus:`\n // is never registered as one, so the atom path handles interactive state.\n const tokens = normalized.split(' ')\n const molecule = interactState ? undefined : molecules[state.scheme]?.[normalized] ?? molecules[COMMON_SCHEME]?.[normalized]\n // Feature-only tokens (gradient / haptic / truncate) carry no style — keep\n // them out of the atom lookup so they don't warn as \"unknown class\". The\n // atom array is merged into ONE object (a runtime molecule) so dynamic\n // (cva / clsx) classNames get the same single-object shape as a build\n // molecule; the cache below pins the context, so the merge is correct.\n const style =\n molecule === undefined\n ? mergeStyleArray(lookupCss(tokens.filter((token) => !isFeatureOnlyToken(token)).join(' '), state, undefined, interactState))\n : molecule\n const base = attachFeatures({ style }, tokens)\n cacheResolved(key, base)\n return userStyle === undefined || userStyle === null ? base : { ...base, style: withUserStyle(base.style, userStyle) }\n}\n\n/** Local mutable view for building the frozen-shaped result. */\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\n/** Test-only — clear the molecule / gradient / haptic registries + cache. */\nexport function __resetResolveState(): void {\n molecules = Object.create(null)\n gradients = Object.create(null)\n haptics = Object.create(null)\n resolvedCache.clear()\n registryVersion += 1\n cachedFor = -1\n}\n\n/** Test-only — current resolved-cache entry count + its hard ceiling. */\nexport function __resolveCacheStats(): { size: number; max: number } {\n return { size: resolvedCache.size, max: MAX_RESOLVED_CACHE }\n}\n\nexport {normalizeClassName} from '../core/normalize-classname'"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolve.mjs","sources":["../../../../src/runtime/resolve.ts"],"sourcesContent":["import { breakpointTier, getStyleVersion, lookupCss, type InteractState } from './lookup-css'\nimport type { RnwindState } from './components/rnwind-provider'\nimport { normalizeClassName } from '../core/normalize-classname'\nimport type { GradientAtomInfo, GradientDirection } from '../core/parser/gradient'\nimport type { HapticRequest, HapticTrigger } from '../core/parser/haptics'\n\n/**\n * Rich className resolver — the runtime heart of the wrap / `useCss`.\n *\n * Resolution order, per className string:\n * 1. **Molecule** — a build-time PRE-MERGED single style object for the\n * whole literal className (per scheme). One map lookup returns it by\n * reference: no array, no merge, no per-atom loop. The common case.\n * 2. **Atom fallback** — for a className the scanner never saw (a\n * runtime-built string like `` `${className} px-2` ``) OR one that\n * carries context-dependent atoms (`pt-safe`, `text-base`, `md:*`),\n * fall back to per-atom resolution via `lookupCss`, which folds in\n * insets / fontScale / breakpoint / scheme.\n *\n * Results are cached by `(normalized className, scheme, insets, fontScale,\n * breakpoint)` so repeated renders return the SAME reference until the\n * reactive context changes. Atoms / molecules / features all live in\n * build-time registries the generated `.rnwind/*.js` modules populate.\n */\n\n/** Always-loaded fallback scheme key. */\nconst COMMON_SCHEME = 'common'\n\n/** Empty style sentinel. */\nconst EMPTY: readonly unknown[] = []\n\n/** scheme → normalized className → pre-merged style object. */\nlet molecules: Record<string, Record<string, unknown>> = Object.create(null)\n/** atom name → gradient role + resolved colour. */\nlet gradients: Record<string, GradientAtomInfo> = Object.create(null)\n/** atom name (incl. `active:`/`focus:` prefix) → haptic request. */\nlet haptics: Record<string, HapticRequest> = Object.create(null)\n/** Bumps on any molecule/gradient/haptic registration. */\nlet registryVersion = 0\n\n/** Per-(className·state) resolved cache — strong references between context changes. */\nconst resolvedCache = new Map<string, ResolvedCss>()\n/** Version the cache was last valid for (`getStyleVersion()` + {@link registryVersion}). */\nlet cachedFor = -1\n\n/**\n * Hard ceiling on the resolved cache. The cache is pure memoisation, so\n * eviction only costs a re-resolve (sub-µs) — never correctness. Build\n * molecules are NOT in here; they live permanently in `molecules`.\n */\nconst MAX_RESOLVED_CACHE = 2048\n\n/**\n * Store a resolved result, bulk-evicting the OLDEST half when the cache\n * hits {@link MAX_RESOLVED_CACHE}. `Map` preserves insertion order, so the\n * first keys are the oldest. Bulk eviction keeps the hot (cache-hit) path\n * free of per-access LRU bookkeeping at the cost of an occasional small\n * recompute burst under sustained pressure (web / long sessions).\n * @param key Cache key.\n * @param value Resolved result to store.\n */\nfunction cacheResolved(key: string, value: ResolvedCss): void {\n if (resolvedCache.size >= MAX_RESOLVED_CACHE) {\n let drop = resolvedCache.size >> 1\n for (const oldKey of resolvedCache.keys()) {\n resolvedCache.delete(oldKey)\n if (--drop <= 0) break\n }\n }\n resolvedCache.set(key, value)\n}\n\n/** A unit-square gradient endpoint. */\ninterface GradientPoint {\n readonly x: number\n readonly y: number\n}\n\n/** Rich resolution: the RN `style` plus any className-derived props. */\nexport interface ResolvedCss {\n /** RN `style` value — a single molecule object (by ref) or an atom array. */\n readonly style: unknown\n /** Gradient stop colours (when the className is a complete gradient). */\n readonly colors?: readonly string[]\n /** Gradient start point. */\n readonly start?: GradientPoint\n /** Gradient end point. */\n readonly end?: GradientPoint\n /** Text truncation line count. */\n readonly numberOfLines?: number\n /** Text ellipsize mode. */\n readonly ellipsizeMode?: 'tail' | 'clip'\n /** Haptic requests present on the className, for the wrap to dispatch. */\n readonly haptics?: readonly { readonly request: HapticRequest; readonly trigger: HapticTrigger }[]\n}\n\n/** `GradientDirection` → expo-linear-gradient start/end points. */\nconst DIRECTION_POINTS: Record<GradientDirection, { start: GradientPoint; end: GradientPoint }> = {\n 'to-t': { start: { x: 0.5, y: 1 }, end: { x: 0.5, y: 0 } },\n 'to-b': { start: { x: 0.5, y: 0 }, end: { x: 0.5, y: 1 } },\n 'to-l': { start: { x: 1, y: 0.5 }, end: { x: 0, y: 0.5 } },\n 'to-r': { start: { x: 0, y: 0.5 }, end: { x: 1, y: 0.5 } },\n 'to-tl': { start: { x: 1, y: 1 }, end: { x: 0, y: 0 } },\n 'to-tr': { start: { x: 0, y: 1 }, end: { x: 1, y: 0 } },\n 'to-bl': { start: { x: 1, y: 0 }, end: { x: 0, y: 1 } },\n 'to-br': { start: { x: 0, y: 0 }, end: { x: 1, y: 1 } },\n unknown: { start: { x: 0, y: 0.5 }, end: { x: 1, y: 0.5 } },\n}\n\n/**\n * Register one scheme's pre-merged molecules (atom-merged literal\n * classNames). Merges onto any existing entries for the scheme.\n * @param scheme Scheme name (or `'common'`).\n * @param entries Normalized className → merged style object.\n */\nexport function registerMolecules(scheme: string, entries: Record<string, unknown>): void {\n molecules[scheme] = { ...molecules[scheme], ...entries }\n registryVersion += 1\n}\n\n/**\n * Register the gradient atom map (atom name → role + resolved colour).\n * @param map Atom name → gradient info.\n */\nexport function registerGradients(map: Record<string, GradientAtomInfo>): void {\n gradients = map\n registryVersion += 1\n}\n\n/**\n * Register the haptic atom map (atom name → request).\n * @param map Atom name → haptic request.\n */\nexport function registerHaptics(map: Record<string, HapticRequest>): void {\n haptics = map\n registryVersion += 1\n}\n\n\n\n/**\n * Per-state-object signature memo. `RnwindState` is created fresh (via the\n * provider's `useMemo`) whenever any field changes, so its identity is a\n * sound key — a new object means a new signature. Keyed weakly so states\n * GC with their provider.\n */\nconst stateSignatureCache = new WeakMap<RnwindState, string>()\n\n/**\n * Cache key dimension for the reactive context — everything that can\n * change a resolved style. Uses the numeric breakpoint TIER (count of\n * thresholds reached) from `breakpointTier(windowWidth)`, NOT the\n * `activeBreakpoint` NAME: the name clamps tier-0 into the smallest\n * breakpoint, so widths straddling that threshold (e.g. 320 vs 700 with\n * `sm=640`) would collide on one cache key and serve a stale style. The\n * tier is exact AND bounded — two widths in the same tier gate every\n * `sm:`/`md:`/… atom identically, so they resolve the same.\n * @param state Rnwind context.\n * @returns Compact signature string.\n */\nfunction stateSignature(state: RnwindState): string {\n const { insets } = state\n return `${state.scheme}|${insets.top},${insets.right},${insets.bottom},${insets.left}|${state.fontScale}|${breakpointTier(state.windowWidth)}`\n}\n\n/**\n * Memoised {@link stateSignature} — one `WeakMap.get` on the hot path\n * instead of rebuilding the template string every resolve.\n * @param state Rnwind context.\n * @returns Cached compact signature.\n */\nfunction stateSignatureCached(state: RnwindState): string {\n let signature = stateSignatureCache.get(state)\n if (signature === undefined) {\n signature = stateSignature(state)\n stateSignatureCache.set(state, signature)\n }\n return signature\n}\n\n/**\n * Compact signature of the live interactive state for the cache key.\n * @param interactState Active/focus flags, or undefined for the plain path.\n * @returns Two-bit signature (`''` when no interactive state).\n */\nfunction interactSignature(interactState?: InteractState): string {\n if (!interactState) return ''\n const active = interactState.active ? 1 : 0\n const focus = interactState.focus ? 1 : 0\n return `${active}${focus}`\n}\n\n/**\n * Whether a token is a feature-ONLY utility (gradient stop/direction,\n * haptic request, or text-truncate) that contributes NO RN `style`. These\n * are folded in via {@link attachFeatures}, so they must be kept OUT of\n * the `lookupCss` input — otherwise the atom resolver treats them as\n * unknown style atoms and emits a spurious \"unknown class\" dev warning\n * (e.g. for `active:haptic-rigid`).\n * @param token Atom name.\n * @returns True when the token carries no style.\n */\nfunction isFeatureOnlyToken(token: string): boolean {\n return Boolean(gradients[token]) || Boolean(haptics[token]) || truncateForToken(token) !== null\n}\n\n/**\n * Lifecycle trigger for a haptic atom from its variant prefix.\n * @param token Atom name (maybe `active:`/`focus:`/`hover:` prefixed).\n * @returns The trigger.\n */\nfunction hapticTriggerForToken(token: string): HapticTrigger {\n const colon = token.indexOf(':')\n if (colon === -1) return 'mount'\n const prefix = token.slice(0, colon)\n if (prefix === 'active') return 'pressIn'\n if (prefix === 'focus') return 'focus'\n if (prefix === 'hover') return 'hover'\n return 'mount'\n}\n\n/**\n * Syntactic text-truncate directive for one atom.\n * @param token Atom name.\n * @returns Partial truncate props, or null.\n */\nfunction truncateForToken(token: string): { numberOfLines?: number; ellipsizeMode?: 'tail' | 'clip' } | null {\n if (token === 'truncate') return { numberOfLines: 1, ellipsizeMode: 'tail' }\n if (token === 'text-ellipsis') return { ellipsizeMode: 'tail' }\n if (token === 'text-clip') return { ellipsizeMode: 'clip' }\n if (token === 'line-clamp-none') return { numberOfLines: 0 }\n if (token.startsWith('line-clamp-')) {\n const count = Number(token.slice('line-clamp-'.length))\n if (Number.isInteger(count) && count >= 0) return { numberOfLines: count }\n }\n return null\n}\n\n/**\n * Assemble gradient props from gradient roles present in the atom list.\n * @param tokens Atom names.\n * @returns `{colors, start, end}` or null when not a complete gradient.\n */\nfunction assembleGradient(tokens: readonly string[]): { colors: string[]; start: GradientPoint; end: GradientPoint } | null {\n let from: string | undefined\n let via: string | undefined\n let to: string | undefined\n let dir: GradientDirection | undefined\n for (const token of tokens) {\n const info = gradients[token]\n if (!info) continue\n switch (info.role) {\n case 'from': {\n from = info.color\n break\n }\n case 'via': {\n via = info.color\n break\n }\n case 'to': {\n to = info.color\n break\n }\n default: {\n ;({ dir } = info)\n }\n }\n }\n if (dir === undefined) return null\n const colors = [from, via, to].filter((color): color is string => color !== undefined)\n if (colors.length < 2) return null\n const points = DIRECTION_POINTS[dir]\n return { colors, start: points.start, end: points.end }\n}\n\n/**\n * Fold every truncate directive across the atom list into one result —\n * last token wins per prop (matches Tailwind last-wins).\n * @param tokens Atom names.\n * @returns Merged truncate props (empty when none apply).\n */\nfunction collectTruncate(tokens: readonly string[]): { numberOfLines?: number; ellipsizeMode?: 'tail' | 'clip' } {\n const out: { numberOfLines?: number; ellipsizeMode?: 'tail' | 'clip' } = {}\n for (const token of tokens) {\n const truncate = truncateForToken(token)\n if (!truncate) continue\n if (truncate.numberOfLines !== undefined) out.numberOfLines = truncate.numberOfLines\n if (truncate.ellipsizeMode !== undefined) out.ellipsizeMode = truncate.ellipsizeMode\n }\n return out\n}\n\n/**\n * Collect every haptic request present in the atom list, tagged with the\n * lifecycle trigger its variant prefix implies.\n * @param tokens Atom names.\n * @returns Haptic request list, or undefined when none apply.\n */\nfunction collectHaptics(tokens: readonly string[]): { request: HapticRequest; trigger: HapticTrigger }[] | undefined {\n let collected: { request: HapticRequest; trigger: HapticTrigger }[] | undefined\n for (const token of tokens) {\n const request = haptics[token]\n if (!request) continue\n collected ??= []\n collected.push({ request, trigger: hapticTriggerForToken(token) })\n }\n return collected\n}\n\n/**\n * Scan tokens for the className-derived feature props (gradient,\n * truncate, haptics) and fold them onto the base result.\n * @param base Result carrying the resolved `style`.\n * @param tokens Atom names.\n * @returns The result with any feature props attached.\n */\nfunction attachFeatures(base: ResolvedCss, tokens: readonly string[]): ResolvedCss {\n const { numberOfLines, ellipsizeMode } = collectTruncate(tokens)\n const collected = collectHaptics(tokens)\n const gradient = assembleGradient(tokens)\n const result: Mutable<ResolvedCss> = { style: base.style }\n if (gradient) {\n result.colors = gradient.colors\n result.start = gradient.start\n result.end = gradient.end\n }\n // `numberOfLines: 0` is kept (RN reads it as \"unlimited\"): `line-clamp-none`\n // must be able to explicitly reset an earlier `line-clamp-N` on the same\n // element — dropping the 0 would silently leave the prior limit in place.\n if (numberOfLines !== undefined) {\n result.numberOfLines = numberOfLines\n if (ellipsizeMode !== undefined) result.ellipsizeMode = ellipsizeMode\n }\n if (collected) result.haptics = collected\n return result\n}\n\n/**\n * Flatten the per-atom style array into ONE object — a *runtime molecule*.\n * RN flattens a style array left-to-right (later wins), which is exactly\n * `Object.assign` semantics, so the merged object renders identically\n * while giving dynamic (cva / clsx) classNames the same single-object\n * shape a build-time molecule has. The caller caches the result per\n * `(className · state)`, so the merge runs once per unique context.\n * @param array Per-atom style array from `lookupCss`.\n * @returns Single merged style object.\n */\nfunction mergeStyleArray(array: readonly unknown[]): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const entry of array) if (entry && typeof entry === 'object') Object.assign(out, entry)\n return out\n}\n\n/**\n * Compose a resolved style with a caller-supplied inline style (user wins).\n * @param style\n * @param userStyle\n */\nfunction withUserStyle(style: unknown, userStyle: unknown): unknown {\n return Array.isArray(style) ? [...style, userStyle] : [style, userStyle]\n}\n\n/**\n * Resolve a className against the reactive context into a style plus any\n * className-derived props. Molecule-first (one lookup, by reference),\n * atom-fallback for unseen / context-dependent strings, cached per\n * `(className, state)`.\n * @param className Raw className string.\n * @param state Rnwind context from `useRnwind()`.\n * @param userStyle Optional inline style appended last (wins).\n * @param interactState Live active/focus flags (for `active:`/`focus:` atoms).\n * @returns The resolved style + feature props.\n */\nexport function resolve(\n className: string | null | undefined,\n state: RnwindState,\n userStyle?: unknown,\n interactState?: InteractState,\n): ResolvedCss {\n const version = getStyleVersion() + registryVersion\n if (version !== cachedFor) {\n resolvedCache.clear()\n cachedFor = version\n }\n if (className == null) {\n return { style: userStyle === undefined || userStyle === null ? EMPTY : [userStyle] }\n }\n // Key on the RAW className so the hot (cache-hit) path skips normalize\n // entirely — normalization only runs on a miss. The state signature is\n // memoised per state object, so the hit path is one WeakMap.get + one\n // string concat + one Map.get.\n const key = `${className}@${stateSignatureCached(state)}@${interactSignature(interactState)}`\n const cached = resolvedCache.get(key)\n if (cached !== undefined) {\n return userStyle === undefined || userStyle === null ? cached : { ...cached, style: withUserStyle(cached.style, userStyle) }\n }\n const normalized = normalizeClassName(className)\n if (normalized.length === 0) {\n const empty: ResolvedCss = { style: EMPTY }\n cacheResolved(key, empty)\n return userStyle === undefined || userStyle === null ? empty : { style: [userStyle] }\n }\n // Molecules are static pre-merges; anything carrying `active:`/`focus:`\n // is never registered as one, so the atom path handles interactive state.\n const tokens = normalized.split(' ')\n const molecule = interactState ? undefined : molecules[state.scheme]?.[normalized] ?? molecules[COMMON_SCHEME]?.[normalized]\n // Feature-only tokens (gradient / haptic / truncate) carry no style — keep\n // them out of the atom lookup so they don't warn as \"unknown class\". The\n // atom array is merged into ONE object (a runtime molecule) so dynamic\n // (cva / clsx) classNames get the same single-object shape as a build\n // molecule; the cache below pins the context, so the merge is correct.\n const style =\n molecule === undefined\n ? mergeStyleArray(lookupCss(tokens.filter((token) => !isFeatureOnlyToken(token)).join(' '), state, undefined, interactState))\n : molecule\n const base = attachFeatures({ style }, tokens)\n cacheResolved(key, base)\n return userStyle === undefined || userStyle === null ? base : { ...base, style: withUserStyle(base.style, userStyle) }\n}\n\n/** Local mutable view for building the frozen-shaped result. */\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\n/** Test-only — clear the molecule / gradient / haptic registries + cache. */\nexport function __resetResolveState(): void {\n molecules = Object.create(null)\n gradients = Object.create(null)\n haptics = Object.create(null)\n resolvedCache.clear()\n registryVersion += 1\n cachedFor = -1\n}\n\n/** Test-only — current resolved-cache entry count + its hard ceiling. */\nexport function __resolveCacheStats(): { size: number; max: number } {\n return { size: resolvedCache.size, max: MAX_RESOLVED_CACHE }\n}\n\nexport {normalizeClassName} from '../core/normalize-classname'"],"names":[],"mappings":";;;AAMA;;;;;;;;;;;;;;;;;AAiBG;AAEH;AACA,MAAM,aAAa,GAAG,QAAQ;AAE9B;AACA,MAAM,KAAK,GAAuB,EAAE;AAEpC;AACA,IAAI,SAAS,GAA4C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;AAC5E;AACA,IAAI,SAAS,GAAqC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;AACrE;AACA,IAAI,OAAO,GAAkC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;AAChE;AACA,IAAI,eAAe,GAAG,CAAC;AAEvB;AACA,MAAM,aAAa,GAAG,IAAI,GAAG,EAAuB;AACpD;AACA,IAAI,SAAS,GAAG,EAAE;AAElB;;;;AAIG;AACH,MAAM,kBAAkB,GAAG,IAAI;AAE/B;;;;;;;;AAQG;AACH,SAAS,aAAa,CAAC,GAAW,EAAE,KAAkB,EAAA;AACpD,IAAA,IAAI,aAAa,CAAC,IAAI,IAAI,kBAAkB,EAAE;AAC5C,QAAA,IAAI,IAAI,GAAG,aAAa,CAAC,IAAI,IAAI,CAAC;QAClC,KAAK,MAAM,MAAM,IAAI,aAAa,CAAC,IAAI,EAAE,EAAE;AACzC,YAAA,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC;YAC5B,IAAI,EAAE,IAAI,IAAI,CAAC;gBAAE;QACnB;IACF;AACA,IAAA,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC;AAC/B;AA0BA;AACA,MAAM,gBAAgB,GAA4E;IAChG,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IAC1D,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IAC1D,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE;IAC1D,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE;IAC1D,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACvD,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACvD,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACvD,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACvD,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE;CAC5D;AAED;;;;;AAKG;AACG,SAAU,iBAAiB,CAAC,MAAc,EAAE,OAAgC,EAAA;AAChF,IAAA,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE;IACxD,eAAe,IAAI,CAAC;AACtB;AAEA;;;AAGG;AACG,SAAU,iBAAiB,CAAC,GAAqC,EAAA;IACrE,SAAS,GAAG,GAAG;IACf,eAAe,IAAI,CAAC;AACtB;AAEA;;;AAGG;AACG,SAAU,eAAe,CAAC,GAAkC,EAAA;IAChE,OAAO,GAAG,GAAG;IACb,eAAe,IAAI,CAAC;AACtB;AAIA;;;;;AAKG;AACH,MAAM,mBAAmB,GAAG,IAAI,OAAO,EAAuB;AAE9D;;;;;;;;;;;AAWG;AACH,SAAS,cAAc,CAAC,KAAkB,EAAA;AACxC,IAAA,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK;AACxB,IAAA,OAAO,CAAA,EAAG,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,GAAG,CAAA,CAAA,EAAI,MAAM,CAAC,KAAK,CAAA,CAAA,EAAI,MAAM,CAAC,MAAM,CAAA,CAAA,EAAI,MAAM,CAAC,IAAI,CAAA,CAAA,EAAI,KAAK,CAAC,SAAS,CAAA,CAAA,EAAI,cAAc,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE;AAChJ;AAEA;;;;;AAKG;AACH,SAAS,oBAAoB,CAAC,KAAkB,EAAA;IAC9C,IAAI,SAAS,GAAG,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC;AAC9C,IAAA,IAAI,SAAS,KAAK,SAAS,EAAE;AAC3B,QAAA,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC;AACjC,QAAA,mBAAmB,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC;IAC3C;AACA,IAAA,OAAO,SAAS;AAClB;AAEA;;;;AAIG;AACH,SAAS,iBAAiB,CAAC,aAA6B,EAAA;AACtD,IAAA,IAAI,CAAC,aAAa;AAAE,QAAA,OAAO,EAAE;AAC7B,IAAA,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC;AAC3C,IAAA,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC;AACzC,IAAA,OAAO,CAAA,EAAG,MAAM,CAAA,EAAG,KAAK,EAAE;AAC5B;AAEA;;;;;;;;;AASG;AACH,SAAS,kBAAkB,CAAC,KAAa,EAAA;IACvC,OAAO,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,gBAAgB,CAAC,KAAK,CAAC,KAAK,IAAI;AACjG;AAEA;;;;AAIG;AACH,SAAS,qBAAqB,CAAC,KAAa,EAAA;IAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;IAChC,IAAI,KAAK,KAAK,EAAE;AAAE,QAAA,OAAO,OAAO;IAChC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;IACpC,IAAI,MAAM,KAAK,QAAQ;AAAE,QAAA,OAAO,SAAS;IACzC,IAAI,MAAM,KAAK,OAAO;AAAE,QAAA,OAAO,OAAO;IACtC,IAAI,MAAM,KAAK,OAAO;AAAE,QAAA,OAAO,OAAO;AACtC,IAAA,OAAO,OAAO;AAChB;AAEA;;;;AAIG;AACH,SAAS,gBAAgB,CAAC,KAAa,EAAA;IACrC,IAAI,KAAK,KAAK,UAAU;QAAE,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE;IAC5E,IAAI,KAAK,KAAK,eAAe;AAAE,QAAA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE;IAC/D,IAAI,KAAK,KAAK,WAAW;AAAE,QAAA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE;IAC3D,IAAI,KAAK,KAAK,iBAAiB;AAAE,QAAA,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE;AAC5D,IAAA,IAAI,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE;AACnC,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACvD,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;AAAE,YAAA,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE;IAC5E;AACA,IAAA,OAAO,IAAI;AACb;AAEA;;;;AAIG;AACH,SAAS,gBAAgB,CAAC,MAAyB,EAAA;AACjD,IAAA,IAAI,IAAwB;AAC5B,IAAA,IAAI,GAAuB;AAC3B,IAAA,IAAI,EAAsB;AAC1B,IAAA,IAAI,GAAkC;AACtC,IAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;AAC1B,QAAA,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC;AAC7B,QAAA,IAAI,CAAC,IAAI;YAAE;AACX,QAAA,QAAQ,IAAI,CAAC,IAAI;YACf,KAAK,MAAM,EAAE;AACX,gBAAA,IAAI,GAAG,IAAI,CAAC,KAAK;gBACjB;YACF;YACA,KAAK,KAAK,EAAE;AACV,gBAAA,GAAG,GAAG,IAAI,CAAC,KAAK;gBAChB;YACF;YACA,KAAK,IAAI,EAAE;AACT,gBAAA,EAAE,GAAG,IAAI,CAAC,KAAK;gBACf;YACF;YACA,SAAS;AACN,gBAAA,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI;YAClB;;IAEJ;IACA,IAAI,GAAG,KAAK,SAAS;AAAE,QAAA,OAAO,IAAI;IAClC,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,KAAsB,KAAK,KAAK,SAAS,CAAC;AACtF,IAAA,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;AAAE,QAAA,OAAO,IAAI;AAClC,IAAA,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC;AACpC,IAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE;AACzD;AAEA;;;;;AAKG;AACH,SAAS,eAAe,CAAC,MAAyB,EAAA;IAChD,MAAM,GAAG,GAAgE,EAAE;AAC3E,IAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;AAC1B,QAAA,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC;AACxC,QAAA,IAAI,CAAC,QAAQ;YAAE;AACf,QAAA,IAAI,QAAQ,CAAC,aAAa,KAAK,SAAS;AAAE,YAAA,GAAG,CAAC,aAAa,GAAG,QAAQ,CAAC,aAAa;AACpF,QAAA,IAAI,QAAQ,CAAC,aAAa,KAAK,SAAS;AAAE,YAAA,GAAG,CAAC,aAAa,GAAG,QAAQ,CAAC,aAAa;IACtF;AACA,IAAA,OAAO,GAAG;AACZ;AAEA;;;;;AAKG;AACH,SAAS,cAAc,CAAC,MAAyB,EAAA;AAC/C,IAAA,IAAI,SAA2E;AAC/E,IAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;AAC1B,QAAA,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC;AAC9B,QAAA,IAAI,CAAC,OAAO;YAAE;QACd,SAAS,KAAK,EAAE;AAChB,QAAA,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;IACpE;AACA,IAAA,OAAO,SAAS;AAClB;AAEA;;;;;;AAMG;AACH,SAAS,cAAc,CAAC,IAAiB,EAAE,MAAyB,EAAA;IAClE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,eAAe,CAAC,MAAM,CAAC;AAChE,IAAA,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC;AACxC,IAAA,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,CAAC;IACzC,MAAM,MAAM,GAAyB,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;IAC1D,IAAI,QAAQ,EAAE;AACZ,QAAA,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM;AAC/B,QAAA,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK;AAC7B,QAAA,MAAM,CAAC,GAAG,GAAG,QAAQ,CAAC,GAAG;IAC3B;;;;AAIA,IAAA,IAAI,aAAa,KAAK,SAAS,EAAE;AAC/B,QAAA,MAAM,CAAC,aAAa,GAAG,aAAa;QACpC,IAAI,aAAa,KAAK,SAAS;AAAE,YAAA,MAAM,CAAC,aAAa,GAAG,aAAa;IACvE;AACA,IAAA,IAAI,SAAS;AAAE,QAAA,MAAM,CAAC,OAAO,GAAG,SAAS;AACzC,IAAA,OAAO,MAAM;AACf;AAEA;;;;;;;;;AASG;AACH,SAAS,eAAe,CAAC,KAAyB,EAAA;IAChD,MAAM,GAAG,GAA4B,EAAE;IACvC,KAAK,MAAM,KAAK,IAAI,KAAK;AAAE,QAAA,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;AAAE,YAAA,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC;AAC5F,IAAA,OAAO,GAAG;AACZ;AAEA;;;;AAIG;AACH,SAAS,aAAa,CAAC,KAAc,EAAE,SAAkB,EAAA;IACvD,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC;AAC1E;AAEA;;;;;;;;;;AAUG;AACG,SAAU,OAAO,CACrB,SAAoC,EACpC,KAAkB,EAClB,SAAmB,EACnB,aAA6B,EAAA;AAE7B,IAAA,MAAM,OAAO,GAAG,eAAe,EAAE,GAAG,eAAe;AACnD,IAAA,IAAI,OAAO,KAAK,SAAS,EAAE;QACzB,aAAa,CAAC,KAAK,EAAE;QACrB,SAAS,GAAG,OAAO;IACrB;AACA,IAAA,IAAI,SAAS,IAAI,IAAI,EAAE;QACrB,OAAO,EAAE,KAAK,EAAE,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,IAAI,GAAG,KAAK,GAAG,CAAC,SAAS,CAAC,EAAE;IACvF;;;;;AAKA,IAAA,MAAM,GAAG,GAAG,CAAA,EAAG,SAAS,IAAI,oBAAoB,CAAC,KAAK,CAAC,IAAI,iBAAiB,CAAC,aAAa,CAAC,EAAE;IAC7F,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC;AACrC,IAAA,IAAI,MAAM,KAAK,SAAS,EAAE;AACxB,QAAA,OAAO,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,IAAI,GAAG,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE;IAC9H;AACA,IAAA,MAAM,UAAU,GAAG,kBAAkB,CAAC,SAAS,CAAC;AAChD,IAAA,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE;AAC3B,QAAA,MAAM,KAAK,GAAgB,EAAE,KAAK,EAAE,KAAK,EAAE;AAC3C,QAAA,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC;QACzB,OAAO,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,IAAI,GAAG,KAAK,GAAG,EAAE,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE;IACvF;;;IAGA,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC;AACpC,IAAA,MAAM,QAAQ,GAAG,aAAa,GAAG,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,IAAI,SAAS,CAAC,aAAa,CAAC,GAAG,UAAU,CAAC;;;;;;AAM5H,IAAA,MAAM,KAAK,GACT,QAAQ,KAAK;AACX,UAAE,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,CAAC;UAC1H,QAAQ;IACd,MAAM,IAAI,GAAG,cAAc,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,CAAC;AAC9C,IAAA,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC;AACxB,IAAA,OAAO,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,IAAI,GAAG,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE;AACxH;AAKA;SACgB,mBAAmB,GAAA;AACjC,IAAA,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;AAC/B,IAAA,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;AAC/B,IAAA,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;IAC7B,aAAa,CAAC,KAAK,EAAE;IACrB,eAAe,IAAI,CAAC;IACpB,SAAS,GAAG,EAAE;AAChB;;;;"}
@@ -3,10 +3,16 @@ import { type ComponentType } from 'react';
3
3
  * Wrap a component so its `className` prop resolves to RN `style` (plus
4
4
  * gradient / truncate props and haptic dispatch) at render — no matter
5
5
  * how className arrived: written directly, spread through `{...rest}`, or
6
- * forwarded down custom wrappers. The returned component is hook-free; it
7
- * dispatches to a plain or interactive leaf so non-interactive elements
8
- * never pay for press/focus state. `ref` (a normal prop in React 19) and
9
- * all other props forward untouched.
6
+ * forwarded down custom wrappers. `ref` (a normal prop in React 19) and all
7
+ * other props forward untouched.
8
+ *
9
+ * A SINGLE stable component does the work and always calls `useInteract()`,
10
+ * so its identity never changes when `className` flips between interactive
11
+ * (`active:`/`focus:`) and not — swapping the rendered component type would
12
+ * unmount + remount the whole host subtree (lost state, effect re-runs,
13
+ * visual flash). `useInteract` is cheap and shares one idle-state ref, so the
14
+ * always-on cost is a couple of `useState` cells; the press/focus handlers
15
+ * and live state only wire in when the className actually needs them.
10
16
  * @example
11
17
  * ```tsx
12
18
  * const Pressable = wrap(RNPressable)
@@ -73,8 +73,10 @@ const CLASSNAME_SUFFIX = 'ClassName';
73
73
  * handled separately by the leaf and never reaches here.
74
74
  * @param props Mutable prop object being assembled for the host.
75
75
  * @param state Rnwind context for resolution.
76
+ * @param interactState Live press/focus state so `active:`/`focus:` variants
77
+ * on a secondary class prop resolve too (undefined for non-interactive).
76
78
  */
77
- function applyContainerClassNames(props, state) {
79
+ function applyContainerClassNames(props, state, interactState) {
78
80
  for (const key of Object.keys(props)) {
79
81
  if (!key.endsWith(CLASSNAME_SUFFIX))
80
82
  continue;
@@ -82,7 +84,7 @@ function applyContainerClassNames(props, state) {
82
84
  if (typeof value !== 'string')
83
85
  continue;
84
86
  const styleKey = `${key.slice(0, -CLASSNAME_SUFFIX.length)}Style`;
85
- props[styleKey] = resolve(value, state, props[styleKey]).style;
87
+ props[styleKey] = resolve(value, state, props[styleKey], interactState).style;
86
88
  delete props[key];
87
89
  }
88
90
  }
@@ -97,12 +99,13 @@ function applyContainerClassNames(props, state) {
97
99
  * @param state Rnwind context — used to resolve secondary class props.
98
100
  * @param onHaptics Dispatcher from context.
99
101
  * @param userOnPressIn Caller-supplied onPressIn to chain after the haptic.
102
+ * @param interactState Live press/focus state for secondary class props.
100
103
  * @returns The merged prop object for `createElement`.
101
104
  */
102
- function buildProps(rest, resolved, state, onHaptics, userOnPressIn) {
105
+ function buildProps(rest, resolved, state, onHaptics, userOnPressIn, interactState) {
103
106
  warnIfHapticsUnwired(onHaptics, resolved.haptics);
104
107
  const props = { ...rest, style: resolved.style };
105
- applyContainerClassNames(props, state);
108
+ applyContainerClassNames(props, state, interactState);
106
109
  if (resolved.colors) {
107
110
  props.colors = resolved.colors;
108
111
  props.start = resolved.start;
@@ -127,56 +130,20 @@ function buildProps(rest, resolved, state, onHaptics, userOnPressIn) {
127
130
  }
128
131
  return props;
129
132
  }
130
- /**
131
- * Non-interactive leaf: resolve className → style (+ features) and
132
- * forward. One context read, one molecule/atom resolve.
133
- * @param props Leaf props.
134
- * @param props.as
135
- * @param props.className
136
- * @param props.style
137
- * @param props.onPressIn
138
- * @returns The rendered `as` element.
139
- */
140
- function PlainLeaf({ as: As, className, style, onPressIn, ...rest }) {
141
- const state = useRnwind();
142
- const resolved = resolve(className, state, style);
143
- useMountHaptics(resolved, state.onHaptics);
144
- return createElement(As, buildProps(rest, resolved, state, state.onHaptics, onPressIn));
145
- }
146
- /**
147
- * Interactive leaf: tracks press/focus via `useInteract()`, feeds it into
148
- * `resolve` so `active:`/`focus:` atoms apply, and chains the
149
- * press/focus handlers.
150
- * @param props Leaf props.
151
- * @param props.as
152
- * @param props.className
153
- * @param props.style
154
- * @param props.onPressIn
155
- * @param props.onPressOut
156
- * @param props.onFocus
157
- * @param props.onBlur
158
- * @returns The rendered `as` element with interactive wiring.
159
- */
160
- function InteractiveLeaf({ as: As, className, style, onPressIn, onPressOut, onFocus, onBlur, ...rest }) {
161
- const state = useRnwind();
162
- const interact = useInteract();
163
- const resolved = resolve(className, state, style, interact.state);
164
- useMountHaptics(resolved, state.onHaptics);
165
- const props = buildProps(rest, resolved, state, state.onHaptics, onPressIn);
166
- props.onPressIn = chainPress(props.onPressIn, interact.onPressIn);
167
- props.onPressOut = chainPress(onPressOut, interact.onPressOut);
168
- props.onFocus = chainFocus(onFocus, interact.onFocus);
169
- props.onBlur = chainFocus(onBlur, interact.onBlur);
170
- return createElement(As, props);
171
- }
172
133
  /**
173
134
  * Wrap a component so its `className` prop resolves to RN `style` (plus
174
135
  * gradient / truncate props and haptic dispatch) at render — no matter
175
136
  * how className arrived: written directly, spread through `{...rest}`, or
176
- * forwarded down custom wrappers. The returned component is hook-free; it
177
- * dispatches to a plain or interactive leaf so non-interactive elements
178
- * never pay for press/focus state. `ref` (a normal prop in React 19) and
179
- * all other props forward untouched.
137
+ * forwarded down custom wrappers. `ref` (a normal prop in React 19) and all
138
+ * other props forward untouched.
139
+ *
140
+ * A SINGLE stable component does the work and always calls `useInteract()`,
141
+ * so its identity never changes when `className` flips between interactive
142
+ * (`active:`/`focus:`) and not — swapping the rendered component type would
143
+ * unmount + remount the whole host subtree (lost state, effect re-runs,
144
+ * visual flash). `useInteract` is cheap and shares one idle-state ref, so the
145
+ * always-on cost is a couple of `useState` cells; the press/focus handlers
146
+ * and live state only wire in when the className actually needs them.
180
147
  * @example
181
148
  * ```tsx
182
149
  * const Pressable = wrap(RNPressable)
@@ -188,16 +155,42 @@ function InteractiveLeaf({ as: As, className, style, onPressIn, onPressOut, onFo
188
155
  function wrap(Component) {
189
156
  const as = Component;
190
157
  /**
191
- * The wrapped component hook-free dispatcher to a leaf.
158
+ * The wrapped component. Stable identity + unconditional hooks; branches
159
+ * internally on whether the className carries an interactive variant.
192
160
  * @param props Forwarded props with `className` intercepted.
193
- * @param props.className
194
- * @returns The rendered leaf.
161
+ * @param props.className Raw className string.
162
+ * @param props.style Caller-supplied style, merged under the resolved style.
163
+ * @param props.onPressIn Caller onPressIn — chained after haptics / interact.
164
+ * @param props.onPressOut Caller onPressOut — chained with interact when active.
165
+ * @param props.onFocus Caller onFocus — chained with interact when active.
166
+ * @param props.onBlur Caller onBlur — chained with interact when active.
167
+ * @returns The rendered `as` element.
195
168
  */
196
- function RnwindWrapped({ className, ...rest }) {
197
- if (className !== undefined && hasInteractiveVariant(className)) {
198
- return createElement(InteractiveLeaf, { as, className, ...rest });
169
+ function RnwindWrapped({ className, style, onPressIn, onPressOut, onFocus, onBlur, ...rest }) {
170
+ const state = useRnwind();
171
+ const interact = useInteract();
172
+ const isInteractive = className !== undefined && hasInteractiveVariant(className);
173
+ const interactState = isInteractive ? interact.state : undefined;
174
+ const resolved = resolve(className, state, style, interactState);
175
+ useMountHaptics(resolved, state.onHaptics);
176
+ const props = buildProps(rest, resolved, state, state.onHaptics, onPressIn, interactState);
177
+ if (isInteractive) {
178
+ props.onPressIn = chainPress(props.onPressIn, interact.onPressIn);
179
+ props.onPressOut = chainPress(onPressOut, interact.onPressOut);
180
+ props.onFocus = chainFocus(onFocus, interact.onFocus);
181
+ props.onBlur = chainFocus(onBlur, interact.onBlur);
182
+ }
183
+ else {
184
+ // Forward the caller's press/focus handlers untouched (onPressIn is
185
+ // already set by buildProps, possibly haptic-chained).
186
+ if (onPressOut !== undefined)
187
+ props.onPressOut = onPressOut;
188
+ if (onFocus !== undefined)
189
+ props.onFocus = onFocus;
190
+ if (onBlur !== undefined)
191
+ props.onBlur = onBlur;
199
192
  }
200
- return createElement(PlainLeaf, { as, className, ...rest });
193
+ return createElement(as, props);
201
194
  }
202
195
  RnwindWrapped.displayName = `wrap(${displayNameOf(Component)})`;
203
196
  return RnwindWrapped;
@@ -1 +1 @@
1
- {"version":3,"file":"wrap.mjs","sources":["../../../../src/runtime/wrap.tsx"],"sourcesContent":["import { createElement, useEffect, useRef, type ComponentType, type ReactElement } from 'react'\nimport { chainFocus, chainPress } from './chain-handlers'\nimport { useInteract } from './hooks/use-interact'\nimport { useRnwind } from './components/rnwind-provider'\nimport type { RnwindState } from './components/rnwind-provider'\nimport { resolve, type ResolvedCss } from './resolve'\nimport type { OnHaptics } from '../core/parser/haptics'\n\n/** Matches a leading `active:` / `focus:` variant token (`\\b` excludes `inactive:`). */\nconst INTERACTIVE_VARIANT = /\\b(?:active|focus):/\n\n/** One-shot guard so the missing-`onHaptics` warning logs once per session. */\nlet warnedMissingOnHaptics = false\n\n/**\n * Dev-only warning when a className carries a haptic utility but no\n * `onHaptics` dispatcher is wired on the nearest `<RnwindProvider>` — the\n * haptic would silently drop otherwise. Fires once per session.\n * @param onHaptics The dispatcher from context (or undefined).\n * @param haptics The resolved haptic requests (or undefined).\n */\nfunction warnIfHapticsUnwired(onHaptics: OnHaptics | undefined, haptics: ResolvedCss['haptics']): void {\n if (onHaptics || !haptics || haptics.length === 0) return\n const isDevelopment = typeof __DEV__ === 'undefined' || __DEV__\n if (!isDevelopment || warnedMissingOnHaptics) return\n warnedMissingOnHaptics = true\n // eslint-disable-next-line no-console\n console.warn(\n 'rnwind: a `haptic-*` utility resolved but no `onHaptics` callback is wired on <RnwindProvider>. ' +\n 'Pass `onHaptics` on the provider to forward the request to expo-haptics (or any library).',\n )\n}\n\n/**\n * Whether a className needs press/focus state tracking.\n * @param className Raw className string.\n * @returns True when an `active:` / `focus:` variant is present.\n */\nfunction hasInteractiveVariant(className: string): boolean {\n return INTERACTIVE_VARIANT.test(className)\n}\n\n/**\n * Best-effort display name for the wrapped component.\n * @param component Component being wrapped.\n * @returns Its `displayName`, `name`, or `'Component'`.\n */\nfunction displayNameOf(component: unknown): string {\n const named = component as { displayName?: string; name?: string }\n return named.displayName ?? named.name ?? 'Component'\n}\n\n/**\n * Fire the `mount`-trigger haptics once, after the element mounts. Snaps\n * the resolved requests + dispatcher at mount via a `useRef` initializer\n * (evaluated only on the first render), so an unstable inline `onHaptics`\n * doesn't re-fire them and no ref is written during render.\n * @param resolved The resolved className (carries any haptic requests).\n * @param onHaptics The dispatcher from context (or undefined).\n */\nfunction useMountHaptics(resolved: ResolvedCss, onHaptics: OnHaptics | undefined): void {\n const mount = useRef({ resolved, onHaptics })\n useEffect(() => {\n const { resolved: current, onHaptics: dispatch } = mount.current\n if (!dispatch || !current.haptics) return\n for (const entry of current.haptics) if (entry.trigger === 'mount') dispatch(entry.request, 'mount')\n }, [])\n}\n\n/** Suffix marking a secondary class-prop (`contentContainerClassName`, …). */\nconst CLASSNAME_SUFFIX = 'ClassName'\n\n/**\n * Resolve every secondary `<prefix>ClassName` prop (e.g.\n * `contentContainerClassName` on a ScrollView / FlatList) into its\n * matching `<prefix>Style`, in place. Any existing `<prefix>Style` is\n * appended last (caller wins). The original `*ClassName` prop is deleted\n * so RN never sees an unknown attribute. The primary `className` is\n * handled separately by the leaf and never reaches here.\n * @param props Mutable prop object being assembled for the host.\n * @param state Rnwind context for resolution.\n */\nfunction applyContainerClassNames(props: Record<string, unknown>, state: RnwindState): void {\n for (const key of Object.keys(props)) {\n if (!key.endsWith(CLASSNAME_SUFFIX)) continue\n const value = props[key]\n if (typeof value !== 'string') continue\n const styleKey = `${key.slice(0, -CLASSNAME_SUFFIX.length)}Style`\n props[styleKey] = resolve(value, state, props[styleKey]).style\n delete props[key]\n }\n}\n\n/**\n * Build the props for the wrapped host: resolved `style`, gradient\n * (`colors`/`start`/`end`), truncate (`numberOfLines`/`ellipsizeMode`),\n * secondary `<prefix>ClassName` → `<prefix>Style`, and a chained\n * `onPressIn` that fires press-trigger haptics. Unknown props on a host\n * are simply ignored by RN, so this stays generic.\n * @param rest Forwarded props (incl. `ref`).\n * @param resolved Resolved className result.\n * @param state Rnwind context — used to resolve secondary class props.\n * @param onHaptics Dispatcher from context.\n * @param userOnPressIn Caller-supplied onPressIn to chain after the haptic.\n * @returns The merged prop object for `createElement`.\n */\nfunction buildProps(\n rest: Record<string, unknown>,\n resolved: ResolvedCss,\n state: RnwindState,\n onHaptics: OnHaptics | undefined,\n userOnPressIn?: unknown,\n): Record<string, unknown> {\n warnIfHapticsUnwired(onHaptics, resolved.haptics)\n const props: Record<string, unknown> = { ...rest, style: resolved.style }\n applyContainerClassNames(props, state)\n if (resolved.colors) {\n props.colors = resolved.colors\n props.start = resolved.start\n props.end = resolved.end\n }\n if (resolved.numberOfLines !== undefined) {\n props.numberOfLines = resolved.numberOfLines\n if (resolved.ellipsizeMode !== undefined) props.ellipsizeMode = resolved.ellipsizeMode\n }\n const pressHaptics = onHaptics && resolved.haptics?.filter((entry) => entry.trigger === 'pressIn')\n if (pressHaptics && pressHaptics.length > 0) {\n const previous = userOnPressIn as ((event: unknown) => void) | undefined\n props.onPressIn = (event: unknown): void => {\n for (const entry of pressHaptics) onHaptics(entry.request, 'pressIn')\n previous?.(event)\n }\n } else if (userOnPressIn !== undefined) {\n props.onPressIn = userOnPressIn\n }\n return props\n}\n\n/** Props a leaf receives — the wrapped `as` tag plus forwarded props. */\ninterface LeafProps {\n readonly as: ComponentType<Record<string, unknown>>\n readonly className?: string\n readonly style?: unknown\n readonly [key: string]: unknown\n}\n\n/**\n * Non-interactive leaf: resolve className → style (+ features) and\n * forward. One context read, one molecule/atom resolve.\n * @param props Leaf props.\n * @param props.as\n * @param props.className\n * @param props.style\n * @param props.onPressIn\n * @returns The rendered `as` element.\n */\nfunction PlainLeaf({ as: As, className, style, onPressIn, ...rest }: LeafProps): ReactElement {\n const state = useRnwind()\n const resolved = resolve(className, state, style)\n useMountHaptics(resolved, state.onHaptics)\n return createElement(As, buildProps(rest, resolved, state, state.onHaptics, onPressIn))\n}\n\n/**\n * Interactive leaf: tracks press/focus via `useInteract()`, feeds it into\n * `resolve` so `active:`/`focus:` atoms apply, and chains the\n * press/focus handlers.\n * @param props Leaf props.\n * @param props.as\n * @param props.className\n * @param props.style\n * @param props.onPressIn\n * @param props.onPressOut\n * @param props.onFocus\n * @param props.onBlur\n * @returns The rendered `as` element with interactive wiring.\n */\nfunction InteractiveLeaf({ as: As, className, style, onPressIn, onPressOut, onFocus, onBlur, ...rest }: LeafProps): ReactElement {\n const state = useRnwind()\n const interact = useInteract()\n const resolved = resolve(className, state, style, interact.state)\n useMountHaptics(resolved, state.onHaptics)\n const props = buildProps(rest, resolved, state, state.onHaptics, onPressIn)\n props.onPressIn = chainPress(props.onPressIn as Parameters<typeof chainPress>[0], interact.onPressIn)\n props.onPressOut = chainPress(onPressOut as Parameters<typeof chainPress>[0], interact.onPressOut)\n props.onFocus = chainFocus(onFocus as Parameters<typeof chainFocus>[0], interact.onFocus)\n props.onBlur = chainFocus(onBlur as Parameters<typeof chainFocus>[0], interact.onBlur)\n return createElement(As, props)\n}\n\n/**\n * Wrap a component so its `className` prop resolves to RN `style` (plus\n * gradient / truncate props and haptic dispatch) at render — no matter\n * how className arrived: written directly, spread through `{...rest}`, or\n * forwarded down custom wrappers. The returned component is hook-free; it\n * dispatches to a plain or interactive leaf so non-interactive elements\n * never pay for press/focus state. `ref` (a normal prop in React 19) and\n * all other props forward untouched.\n * @example\n * ```tsx\n * const Pressable = wrap(RNPressable)\n * <Pressable className=\"active:bg-sky-700 px-4 haptic-light\" onPress={fn} />\n * ```\n * @param Component Any component accepting a `style` prop.\n * @returns A component accepting `className`.\n */\nexport function wrap<P>(Component: ComponentType<P>): ComponentType<P & { className?: string }> {\n const as = Component as unknown as ComponentType<Record<string, unknown>>\n /**\n * The wrapped component — hook-free dispatcher to a leaf.\n * @param props Forwarded props with `className` intercepted.\n * @param props.className\n * @returns The rendered leaf.\n */\n function RnwindWrapped({ className, ...rest }: { className?: string; [key: string]: unknown }): ReactElement {\n if (className !== undefined && hasInteractiveVariant(className)) {\n return createElement(InteractiveLeaf, { as, className, ...rest })\n }\n return createElement(PlainLeaf, { as, className, ...rest })\n }\n RnwindWrapped.displayName = `wrap(${displayNameOf(Component)})`\n return RnwindWrapped as unknown as ComponentType<P & { className?: string }>\n}\n\n/**\n * Whether a namespace member name denotes a component to wrap —\n * PascalCase and not a React context (`*Context`). Lowercase utilities /\n * hooks (`createAnimatedComponent`, `spring`) pass through untouched.\n * @param name Member key.\n * @returns True when the member should be `wrap()`-ed.\n */\nfunction isComponentMember(name: string): boolean {\n return /^[A-Z]/.test(name) && !name.endsWith('Context')\n}\n\n/**\n * Wrap a component NAMESPACE (a default/namespace import like reanimated's\n * `Animated`) so member access — `Animated.View`, `Animated.ScrollView` —\n * returns a `wrap()`-ed component whose `className` resolves at render.\n * Returns a Proxy: component members are wrapped lazily and memoised so\n * each access yields the SAME wrapped component (stable identity — React\n * would remount otherwise). Non-component members (`createAnimatedComponent`,\n * config objects) pass straight through.\n * @example\n * ```tsx\n * const Animated = wrapNamespace(RNReanimated)\n * <Animated.View className=\"enter-fade\" />\n * ```\n * @param namespace The imported namespace object.\n * @returns A Proxy that wraps component members on access.\n */\nexport function wrapNamespace<T extends object>(namespace: T): T {\n const cache = new Map<string, unknown>()\n return new Proxy(namespace, {\n get(target, key, receiver): unknown {\n const value = Reflect.get(target, key, receiver)\n if (typeof key !== 'string' || !isComponentMember(key)) return value\n if (!value || (typeof value !== 'function' && typeof value !== 'object')) return value\n let wrapped = cache.get(key)\n if (wrapped === undefined) {\n wrapped = wrap(value as ComponentType<unknown>)\n cache.set(key, wrapped)\n }\n return wrapped\n },\n })\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wrap.mjs","sources":["../../../../src/runtime/wrap.tsx"],"sourcesContent":["import { createElement, useEffect, useRef, type ComponentType, type ReactElement } from 'react'\nimport { chainFocus, chainPress } from './chain-handlers'\nimport { useInteract } from './hooks/use-interact'\nimport { useRnwind } from './components/rnwind-provider'\nimport type { RnwindState } from './components/rnwind-provider'\nimport type { InteractState } from './lookup-css'\nimport { resolve, type ResolvedCss } from './resolve'\nimport type { OnHaptics } from '../core/parser/haptics'\n\n/** Matches a leading `active:` / `focus:` variant token (`\\b` excludes `inactive:`). */\nconst INTERACTIVE_VARIANT = /\\b(?:active|focus):/\n\n/** One-shot guard so the missing-`onHaptics` warning logs once per session. */\nlet warnedMissingOnHaptics = false\n\n/**\n * Dev-only warning when a className carries a haptic utility but no\n * `onHaptics` dispatcher is wired on the nearest `<RnwindProvider>` — the\n * haptic would silently drop otherwise. Fires once per session.\n * @param onHaptics The dispatcher from context (or undefined).\n * @param haptics The resolved haptic requests (or undefined).\n */\nfunction warnIfHapticsUnwired(onHaptics: OnHaptics | undefined, haptics: ResolvedCss['haptics']): void {\n if (onHaptics || !haptics || haptics.length === 0) return\n const isDevelopment = typeof __DEV__ === 'undefined' || __DEV__\n if (!isDevelopment || warnedMissingOnHaptics) return\n warnedMissingOnHaptics = true\n // eslint-disable-next-line no-console\n console.warn(\n 'rnwind: a `haptic-*` utility resolved but no `onHaptics` callback is wired on <RnwindProvider>. ' +\n 'Pass `onHaptics` on the provider to forward the request to expo-haptics (or any library).',\n )\n}\n\n/**\n * Whether a className needs press/focus state tracking.\n * @param className Raw className string.\n * @returns True when an `active:` / `focus:` variant is present.\n */\nfunction hasInteractiveVariant(className: string): boolean {\n return INTERACTIVE_VARIANT.test(className)\n}\n\n/**\n * Best-effort display name for the wrapped component.\n * @param component Component being wrapped.\n * @returns Its `displayName`, `name`, or `'Component'`.\n */\nfunction displayNameOf(component: unknown): string {\n const named = component as { displayName?: string; name?: string }\n return named.displayName ?? named.name ?? 'Component'\n}\n\n/**\n * Fire the `mount`-trigger haptics once, after the element mounts. Snaps\n * the resolved requests + dispatcher at mount via a `useRef` initializer\n * (evaluated only on the first render), so an unstable inline `onHaptics`\n * doesn't re-fire them and no ref is written during render.\n * @param resolved The resolved className (carries any haptic requests).\n * @param onHaptics The dispatcher from context (or undefined).\n */\nfunction useMountHaptics(resolved: ResolvedCss, onHaptics: OnHaptics | undefined): void {\n const mount = useRef({ resolved, onHaptics })\n useEffect(() => {\n const { resolved: current, onHaptics: dispatch } = mount.current\n if (!dispatch || !current.haptics) return\n for (const entry of current.haptics) if (entry.trigger === 'mount') dispatch(entry.request, 'mount')\n }, [])\n}\n\n/** Suffix marking a secondary class-prop (`contentContainerClassName`, …). */\nconst CLASSNAME_SUFFIX = 'ClassName'\n\n/**\n * Resolve every secondary `<prefix>ClassName` prop (e.g.\n * `contentContainerClassName` on a ScrollView / FlatList) into its\n * matching `<prefix>Style`, in place. Any existing `<prefix>Style` is\n * appended last (caller wins). The original `*ClassName` prop is deleted\n * so RN never sees an unknown attribute. The primary `className` is\n * handled separately by the leaf and never reaches here.\n * @param props Mutable prop object being assembled for the host.\n * @param state Rnwind context for resolution.\n * @param interactState Live press/focus state so `active:`/`focus:` variants\n * on a secondary class prop resolve too (undefined for non-interactive).\n */\nfunction applyContainerClassNames(\n props: Record<string, unknown>,\n state: RnwindState,\n interactState?: InteractState,\n): void {\n for (const key of Object.keys(props)) {\n if (!key.endsWith(CLASSNAME_SUFFIX)) continue\n const value = props[key]\n if (typeof value !== 'string') continue\n const styleKey = `${key.slice(0, -CLASSNAME_SUFFIX.length)}Style`\n props[styleKey] = resolve(value, state, props[styleKey], interactState).style\n delete props[key]\n }\n}\n\n/**\n * Build the props for the wrapped host: resolved `style`, gradient\n * (`colors`/`start`/`end`), truncate (`numberOfLines`/`ellipsizeMode`),\n * secondary `<prefix>ClassName` → `<prefix>Style`, and a chained\n * `onPressIn` that fires press-trigger haptics. Unknown props on a host\n * are simply ignored by RN, so this stays generic.\n * @param rest Forwarded props (incl. `ref`).\n * @param resolved Resolved className result.\n * @param state Rnwind context — used to resolve secondary class props.\n * @param onHaptics Dispatcher from context.\n * @param userOnPressIn Caller-supplied onPressIn to chain after the haptic.\n * @param interactState Live press/focus state for secondary class props.\n * @returns The merged prop object for `createElement`.\n */\nfunction buildProps(\n rest: Record<string, unknown>,\n resolved: ResolvedCss,\n state: RnwindState,\n onHaptics: OnHaptics | undefined,\n userOnPressIn?: unknown,\n interactState?: InteractState,\n): Record<string, unknown> {\n warnIfHapticsUnwired(onHaptics, resolved.haptics)\n const props: Record<string, unknown> = { ...rest, style: resolved.style }\n applyContainerClassNames(props, state, interactState)\n if (resolved.colors) {\n props.colors = resolved.colors\n props.start = resolved.start\n props.end = resolved.end\n }\n if (resolved.numberOfLines !== undefined) {\n props.numberOfLines = resolved.numberOfLines\n if (resolved.ellipsizeMode !== undefined) props.ellipsizeMode = resolved.ellipsizeMode\n }\n const pressHaptics = onHaptics && resolved.haptics?.filter((entry) => entry.trigger === 'pressIn')\n if (pressHaptics && pressHaptics.length > 0) {\n const previous = userOnPressIn as ((event: unknown) => void) | undefined\n props.onPressIn = (event: unknown): void => {\n for (const entry of pressHaptics) onHaptics(entry.request, 'pressIn')\n previous?.(event)\n }\n } else if (userOnPressIn !== undefined) {\n props.onPressIn = userOnPressIn\n }\n return props\n}\n\n/** Props the wrapped renderer accepts — `className` plus forwarded props. */\ninterface WrappedProps {\n readonly className?: string\n readonly style?: unknown\n readonly onPressIn?: unknown\n readonly onPressOut?: unknown\n readonly onFocus?: unknown\n readonly onBlur?: unknown\n readonly [key: string]: unknown\n}\n\n/**\n * Wrap a component so its `className` prop resolves to RN `style` (plus\n * gradient / truncate props and haptic dispatch) at render — no matter\n * how className arrived: written directly, spread through `{...rest}`, or\n * forwarded down custom wrappers. `ref` (a normal prop in React 19) and all\n * other props forward untouched.\n *\n * A SINGLE stable component does the work and always calls `useInteract()`,\n * so its identity never changes when `className` flips between interactive\n * (`active:`/`focus:`) and not — swapping the rendered component type would\n * unmount + remount the whole host subtree (lost state, effect re-runs,\n * visual flash). `useInteract` is cheap and shares one idle-state ref, so the\n * always-on cost is a couple of `useState` cells; the press/focus handlers\n * and live state only wire in when the className actually needs them.\n * @example\n * ```tsx\n * const Pressable = wrap(RNPressable)\n * <Pressable className=\"active:bg-sky-700 px-4 haptic-light\" onPress={fn} />\n * ```\n * @param Component Any component accepting a `style` prop.\n * @returns A component accepting `className`.\n */\nexport function wrap<P>(Component: ComponentType<P>): ComponentType<P & { className?: string }> {\n const as = Component as unknown as ComponentType<Record<string, unknown>>\n /**\n * The wrapped component. Stable identity + unconditional hooks; branches\n * internally on whether the className carries an interactive variant.\n * @param props Forwarded props with `className` intercepted.\n * @param props.className Raw className string.\n * @param props.style Caller-supplied style, merged under the resolved style.\n * @param props.onPressIn Caller onPressIn — chained after haptics / interact.\n * @param props.onPressOut Caller onPressOut — chained with interact when active.\n * @param props.onFocus Caller onFocus — chained with interact when active.\n * @param props.onBlur Caller onBlur — chained with interact when active.\n * @returns The rendered `as` element.\n */\n function RnwindWrapped({ className, style, onPressIn, onPressOut, onFocus, onBlur, ...rest }: WrappedProps): ReactElement {\n const state = useRnwind()\n const interact = useInteract()\n const isInteractive = className !== undefined && hasInteractiveVariant(className)\n const interactState = isInteractive ? interact.state : undefined\n const resolved = resolve(className, state, style, interactState)\n useMountHaptics(resolved, state.onHaptics)\n const props = buildProps(rest, resolved, state, state.onHaptics, onPressIn, interactState)\n if (isInteractive) {\n props.onPressIn = chainPress(props.onPressIn as Parameters<typeof chainPress>[0], interact.onPressIn)\n props.onPressOut = chainPress(onPressOut as Parameters<typeof chainPress>[0], interact.onPressOut)\n props.onFocus = chainFocus(onFocus as Parameters<typeof chainFocus>[0], interact.onFocus)\n props.onBlur = chainFocus(onBlur as Parameters<typeof chainFocus>[0], interact.onBlur)\n } else {\n // Forward the caller's press/focus handlers untouched (onPressIn is\n // already set by buildProps, possibly haptic-chained).\n if (onPressOut !== undefined) props.onPressOut = onPressOut\n if (onFocus !== undefined) props.onFocus = onFocus\n if (onBlur !== undefined) props.onBlur = onBlur\n }\n return createElement(as, props)\n }\n RnwindWrapped.displayName = `wrap(${displayNameOf(Component)})`\n return RnwindWrapped as unknown as ComponentType<P & { className?: string }>\n}\n\n/**\n * Whether a namespace member name denotes a component to wrap —\n * PascalCase and not a React context (`*Context`). Lowercase utilities /\n * hooks (`createAnimatedComponent`, `spring`) pass through untouched.\n * @param name Member key.\n * @returns True when the member should be `wrap()`-ed.\n */\nfunction isComponentMember(name: string): boolean {\n return /^[A-Z]/.test(name) && !name.endsWith('Context')\n}\n\n/**\n * Wrap a component NAMESPACE (a default/namespace import like reanimated's\n * `Animated`) so member access — `Animated.View`, `Animated.ScrollView` —\n * returns a `wrap()`-ed component whose `className` resolves at render.\n * Returns a Proxy: component members are wrapped lazily and memoised so\n * each access yields the SAME wrapped component (stable identity — React\n * would remount otherwise). Non-component members (`createAnimatedComponent`,\n * config objects) pass straight through.\n * @example\n * ```tsx\n * const Animated = wrapNamespace(RNReanimated)\n * <Animated.View className=\"enter-fade\" />\n * ```\n * @param namespace The imported namespace object.\n * @returns A Proxy that wraps component members on access.\n */\nexport function wrapNamespace<T extends object>(namespace: T): T {\n const cache = new Map<string, unknown>()\n return new Proxy(namespace, {\n get(target, key, receiver): unknown {\n const value = Reflect.get(target, key, receiver)\n if (typeof key !== 'string' || !isComponentMember(key)) return value\n if (!value || (typeof value !== 'function' && typeof value !== 'object')) return value\n let wrapped = cache.get(key)\n if (wrapped === undefined) {\n wrapped = wrap(value as ComponentType<unknown>)\n cache.set(key, wrapped)\n }\n return wrapped\n },\n })\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnwind",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "Tailwind for React Native",
5
5
  "author": "https://github.com/sagltd",
6
6
  "license": "MIT",