rnwind 0.0.9 → 0.0.11

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 (47) hide show
  1. package/lib/cjs/core/parser/tw-parser.cjs +126 -3
  2. package/lib/cjs/core/parser/tw-parser.cjs.map +1 -1
  3. package/lib/cjs/core/parser/tw-parser.d.ts +22 -0
  4. package/lib/cjs/core/style-builder/build-style.cjs +12 -3
  5. package/lib/cjs/core/style-builder/build-style.cjs.map +1 -1
  6. package/lib/cjs/core/style-builder/build-style.d.ts +3 -1
  7. package/lib/cjs/core/style-builder/union-builder.cjs +9 -1
  8. package/lib/cjs/core/style-builder/union-builder.cjs.map +1 -1
  9. package/lib/cjs/core/style-builder/union-builder.d.ts +7 -0
  10. package/lib/cjs/runtime/hooks/use-scheme.cjs +8 -5
  11. package/lib/cjs/runtime/hooks/use-scheme.cjs.map +1 -1
  12. package/lib/cjs/runtime/index.cjs +1 -0
  13. package/lib/cjs/runtime/index.cjs.map +1 -1
  14. package/lib/cjs/runtime/index.d.ts +1 -1
  15. package/lib/cjs/runtime/lookup-css.cjs +27 -0
  16. package/lib/cjs/runtime/lookup-css.cjs.map +1 -1
  17. package/lib/cjs/runtime/lookup-css.d.ts +18 -0
  18. package/lib/cjs/testing/index.cjs +1 -1
  19. package/lib/cjs/testing/index.cjs.map +1 -1
  20. package/lib/esm/core/parser/color.mjs +1 -1
  21. package/lib/esm/core/parser/tw-parser.d.ts +22 -0
  22. package/lib/esm/core/parser/tw-parser.mjs +107 -2
  23. package/lib/esm/core/parser/tw-parser.mjs.map +1 -1
  24. package/lib/esm/core/style-builder/build-style.d.ts +3 -1
  25. package/lib/esm/core/style-builder/build-style.mjs +12 -3
  26. package/lib/esm/core/style-builder/build-style.mjs.map +1 -1
  27. package/lib/esm/core/style-builder/union-builder.d.ts +7 -0
  28. package/lib/esm/core/style-builder/union-builder.mjs +9 -1
  29. package/lib/esm/core/style-builder/union-builder.mjs.map +1 -1
  30. package/lib/esm/runtime/hooks/use-scheme.mjs +8 -5
  31. package/lib/esm/runtime/hooks/use-scheme.mjs.map +1 -1
  32. package/lib/esm/runtime/index.d.ts +1 -1
  33. package/lib/esm/runtime/index.mjs +1 -1
  34. package/lib/esm/runtime/index.mjs.map +1 -1
  35. package/lib/esm/runtime/lookup-css.d.ts +18 -0
  36. package/lib/esm/runtime/lookup-css.mjs +26 -1
  37. package/lib/esm/runtime/lookup-css.mjs.map +1 -1
  38. package/lib/esm/testing/index.mjs +2 -2
  39. package/lib/esm/testing/index.mjs.map +1 -1
  40. package/package.json +1 -1
  41. package/src/core/parser/tw-parser.ts +118 -1
  42. package/src/core/style-builder/build-style.ts +12 -1
  43. package/src/core/style-builder/union-builder.ts +10 -1
  44. package/src/runtime/hooks/use-scheme.ts +8 -4
  45. package/src/runtime/index.ts +1 -0
  46. package/src/runtime/lookup-css.ts +28 -0
  47. package/src/testing/index.ts +3 -0
@@ -1,4 +1,5 @@
1
1
  import type { KeyframeBlock, RNStyle, SchemedStyle } from '../parser'
2
+ import type { ThemeTables } from '../types'
2
3
  import { normalizeClassName } from '../normalize-classname'
3
4
 
4
5
  /** Match atom names like `border-hairline`, `h-hairline`, `border-t-hairline`, etc. */
@@ -300,6 +301,7 @@ function serializeBreakpoints(breakpoints: ReadonlyMap<string, number>): string
300
301
  * @param breakpoints Responsive breakpoint name → px-threshold map.
301
302
  * @param gradients Atom → gradient info for `registerGradients`.
302
303
  * @param haptics Atom → haptic request for `registerHaptics`.
304
+ * @param themeTokens
303
305
  * @returns JS source text.
304
306
  */
305
307
  function renderManifest(
@@ -307,15 +309,19 @@ function renderManifest(
307
309
  breakpoints: ReadonlyMap<string, number>,
308
310
  gradients: ReadonlyMap<string, unknown>,
309
311
  haptics: ReadonlyMap<string, unknown>,
312
+ themeTokens: ThemeTables,
310
313
  ): string {
314
+ const hasTokens = Object.keys(themeTokens).length > 0
311
315
  const imports = ['registerSchemeLoader', 'registerBreakpoints']
312
316
  if (gradients.size > 0) imports.push('registerGradients')
313
317
  if (haptics.size > 0) imports.push('registerHaptics')
318
+ if (hasTokens) imports.push('registerThemeTokens')
314
319
  const lines: string[] = [`import { ${imports.join(', ')} } from 'rnwind'`, `import './common.style'`]
315
320
  for (const variant of variants) lines.push(`import ${JSON.stringify(`./${variant}.style`)}`)
316
321
  lines.push(``, `registerBreakpoints(${serializeBreakpoints(breakpoints)})`)
317
322
  if (gradients.size > 0) lines.push(`registerGradients(${serializeFeatureMap(gradients)})`)
318
323
  if (haptics.size > 0) lines.push(`registerHaptics(${serializeFeatureMap(haptics)})`)
324
+ if (hasTokens) lines.push(`registerThemeTokens(${JSON.stringify(themeTokens)})`)
319
325
  lines.push(
320
326
  ``,
321
327
  `function ensureSchemeLoaded(_name) {}`,
@@ -679,6 +685,7 @@ const EMPTY_BREAKPOINTS: ReadonlyMap<string, number> = new Map()
679
685
  * @param literals Distinct literal className strings — pre-merged into
680
686
  * per-scheme molecules so the runtime resolver's O(1) molecule-first
681
687
  * path is populated. Empty for legacy/test callers (atom path only).
688
+ * @param themeTokens
682
689
  * @returns Per-scheme sources, manifest source, variant list.
683
690
  */
684
691
  export function buildSchemeSources(
@@ -690,6 +697,7 @@ export function buildSchemeSources(
690
697
  gradients: ReadonlyMap<string, unknown> = EMPTY_FEATURE_MAP,
691
698
  haptics: ReadonlyMap<string, unknown> = EMPTY_FEATURE_MAP,
692
699
  literals: readonly string[] = EMPTY_LITERALS,
700
+ themeTokens: ThemeTables = EMPTY_THEME_TOKENS,
693
701
  ): BuildSchemeSourcesOutput {
694
702
  const variants = collectVariantSchemes(resolved)
695
703
  const commonEntries: (readonly [string, string])[] = []
@@ -715,7 +723,7 @@ export function buildSchemeSources(
715
723
 
716
724
  return {
717
725
  schemeSources,
718
- manifestSource: renderManifest(variants, breakpoints, gradients, haptics),
726
+ manifestSource: renderManifest(variants, breakpoints, gradients, haptics, themeTokens),
719
727
  variants,
720
728
  serializedMisses: misses,
721
729
  }
@@ -727,5 +735,8 @@ const EMPTY_FEATURE_MAP: ReadonlyMap<string, unknown> = new Map()
727
735
  /** Shared empty literal-list default (atom-only callers). */
728
736
  const EMPTY_LITERALS: readonly string[] = []
729
737
 
738
+ /** Shared empty theme-token default (callers without theme tokens). */
739
+ const EMPTY_THEME_TOKENS: ThemeTables = {}
740
+
730
741
  /** Registry key the runtime uses for the always-loaded fallback. */
731
742
  export const COMMON_SCHEME_NAME: string = COMMON_SCHEME
@@ -2,6 +2,7 @@ import { createHash, randomBytes } from 'node:crypto'
2
2
  import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'
3
3
  import path from 'node:path'
4
4
  import type { GradientAtomInfo, HapticRequest, KeyframeBlock, SchemedStyle, TailwindParser } from '../parser'
5
+ import type { ThemeTables } from '../types'
5
6
  import { buildSchemeSources, type AtomSerializedCache } from './build-style'
6
7
 
7
8
  /** Manifest module basename — the file SchemeProvider imports via the resolver. */
@@ -110,6 +111,13 @@ class UnionBuilder {
110
111
  * snapshot is sufficient.
111
112
  */
112
113
  private breakpoints: ReadonlyMap<string, number> = new Map()
114
+ /**
115
+ * Per-scheme theme token tables captured from the parser. Refreshed on
116
+ * every `recordFile` / `ensureProjectScanned` so theme-token edits land in
117
+ * the manifest's `registerThemeTokens({...})` — the data source for
118
+ * `useColor` / `useToken` / `useSize`.
119
+ */
120
+ private themeTokens: ThemeTables = {}
113
121
  /** file → set of atom names this file currently contributes. */
114
122
  private readonly fileAtomSets = new Map<string, Set<string>>()
115
123
  /** atom name → how many files currently contribute it (refcount). */
@@ -172,6 +180,7 @@ class UnionBuilder {
172
180
  for (const [name, gradient] of parsed.gradientAtoms) this.unionGradients.set(name, gradient)
173
181
  for (const [name, haptic] of parsed.hapticAtoms) this.unionHaptics.set(name, haptic)
174
182
  this.breakpoints = parsed.breakpoints
183
+ this.themeTokens = parsed.themeTokens
175
184
  this.projectScanned = true
176
185
  })()
177
186
  try {
@@ -268,7 +277,7 @@ class UnionBuilder {
268
277
  public async writeSchemes(): Promise<{ changedSchemes: readonly string[] }> {
269
278
  await this.ensureProjectScanned()
270
279
  const sortedAtomNames = [...this.unionAtoms.keys()].toSorted((a, b) => a.localeCompare(b))
271
- const result = buildSchemeSources(sortedAtomNames, this.unionAtoms, this.unionKeyframes, this.serializedCache, this.breakpoints, this.unionGradients, this.unionHaptics, [...this.unionLiterals])
280
+ const result = buildSchemeSources(sortedAtomNames, this.unionAtoms, this.unionKeyframes, this.serializedCache, this.breakpoints, this.unionGradients, this.unionHaptics, [...this.unionLiterals], this.themeTokens)
272
281
  this.serializedMissesCount += result.serializedMisses
273
282
  const { schemeSources, manifestSource } = result
274
283
 
@@ -1,5 +1,6 @@
1
1
  import type { ThemeTable } from '../../core/types'
2
2
  import { useRnwind } from '../components/rnwind-provider'
3
+ import { getThemeTokens } from '../lookup-css'
3
4
 
4
5
  /**
5
6
  * Synthetic scheme name applied when tokens aren't declared under any
@@ -20,10 +21,13 @@ const BASE_SCHEME = 'base'
20
21
  */
21
22
  export function useTheme(): ThemeTable {
22
23
  const { scheme, tables } = useRnwind()
23
- const base = tables[BASE_SCHEME] ?? {}
24
- const schemeTable = tables[scheme]
25
- if (!schemeTable) return base
26
- // Fast path: nothing to merge when the scheme table is empty.
24
+ // The build registers token tables on the manifest so `useColor` works out
25
+ // of the box; an explicit `tables` prop layers on top (the prop wins).
26
+ const registered = getThemeTokens()
27
+ const base = { ...registered[BASE_SCHEME], ...tables[BASE_SCHEME] }
28
+ const schemeTable = { ...registered[scheme], ...tables[scheme] }
29
+ // Base tokens apply everywhere (CSS `:root` cascade); the active scheme's
30
+ // own entries override on overlap.
27
31
  if (Object.keys(schemeTable).length === 0) return base
28
32
  return { ...base, ...schemeTable }
29
33
  }
@@ -2,6 +2,7 @@ export {
2
2
  lookupCss,
3
3
  registerAtoms,
4
4
  registerBreakpoints,
5
+ registerThemeTokens,
5
6
  registerSchemeLoader,
6
7
  setWindowHeightProvider,
7
8
  getBreakpoints,
@@ -16,6 +16,7 @@
16
16
  */
17
17
 
18
18
  import type { RnwindState } from './components/rnwind-provider'
19
+ import type { ThemeTables } from '../core/types'
19
20
 
20
21
  /** Empty sentinel returned when the input is null / undefined / empty. */
21
22
  const EMPTY_STYLES: readonly unknown[] = []
@@ -62,6 +63,8 @@ const cache = {
62
63
  atoms: Object.create(null) as Partial<Record<string, SchemeAtomsRecord>>,
63
64
  breakpoints: Object.create(null) as Partial<Record<string, number>>,
64
65
  breakpointList: [] as readonly BreakpointEntry[],
66
+ /** Per-scheme theme token tables (`--color-*`, `--spacing-*`, …) the manifest registers for `useColor` / `useToken` / `useSize`. */
67
+ themeTokens: {} as ThemeTables,
65
68
  }
66
69
 
67
70
  /**
@@ -553,6 +556,30 @@ export function getBreakpoints(): readonly BreakpointEntry[] {
553
556
  return cache.breakpointList
554
557
  }
555
558
 
559
+ /**
560
+ * Register the per-scheme theme token tables the manifest module emits at
561
+ * load time — the data source for `useColor` / `useToken` / `useSize`. The
562
+ * build lowers `--color-*` tokens to sRGB before registering them, so these
563
+ * are RN-safe. Replaces the prior tables; bumps `atomVersion` so a theme HMR
564
+ * cycle re-resolves. The build registers tokens here so the hooks work out of
565
+ * the box, without the user manually threading a `tables` prop on the provider.
566
+ * @param tables Scheme name → (token name → value) map.
567
+ */
568
+ export function registerThemeTokens(tables: ThemeTables): void {
569
+ cache.themeTokens = tables
570
+ atomVersion += 1
571
+ }
572
+
573
+ /**
574
+ * The manifest-registered theme token tables. The provider merges these under
575
+ * any explicit `tables` prop (the prop wins), so `useColor` resolves from the
576
+ * build by default.
577
+ * @returns Registered per-scheme token tables.
578
+ */
579
+ export function getThemeTokens(): ThemeTables {
580
+ return cache.themeTokens
581
+ }
582
+
556
583
  /**
557
584
  * Sentinel name returned by {@link activeBreakpointFor} ONLY when no
558
585
  * breakpoints are registered at all (bundle without rnwind-transformed
@@ -635,6 +662,7 @@ export function __resetLookupCssState(): void {
635
662
  for (const key of Object.keys(cache.atoms)) delete cache.atoms[key]
636
663
  for (const key of Object.keys(cache.breakpoints)) delete cache.breakpoints[key]
637
664
  cache.breakpointList = []
665
+ cache.themeTokens = {}
638
666
  windowHeightProvider = null
639
667
  schemeLoader = null
640
668
  WARNED_MISSING_INSETS = false
@@ -17,6 +17,7 @@ import {
17
17
  __resetLookupCssState,
18
18
  registerAtoms,
19
19
  registerBreakpoints,
20
+ registerThemeTokens,
20
21
  registerSchemeLoader,
21
22
  } from '../runtime/lookup-css'
22
23
  import { __resetResolveState, registerGradients, registerHaptics, registerMolecules } from '../runtime/resolve'
@@ -159,6 +160,7 @@ function evaluateGeneratedFile(filePath: string): void {
159
160
  'registerBreakpoints',
160
161
  'registerGradients',
161
162
  'registerHaptics',
163
+ 'registerThemeTokens',
162
164
  'registerSchemeLoader',
163
165
  'require',
164
166
  body,
@@ -169,6 +171,7 @@ function evaluateGeneratedFile(filePath: string): void {
169
171
  registerBreakpoints,
170
172
  registerGradients,
171
173
  registerHaptics,
174
+ registerThemeTokens,
172
175
  registerSchemeLoader,
173
176
  () => {},
174
177
  )