rnwind 0.0.8 → 0.0.10

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 (145) 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 +136 -34
  26. package/lib/cjs/core/parser/tw-parser.cjs.map +1 -1
  27. package/lib/cjs/core/parser/tw-parser.d.ts +20 -0
  28. package/lib/cjs/core/parser/typography-dispatcher.cjs +19 -1
  29. package/lib/cjs/core/parser/typography-dispatcher.cjs.map +1 -1
  30. package/lib/cjs/core/parser/typography.cjs +15 -18
  31. package/lib/cjs/core/parser/typography.cjs.map +1 -1
  32. package/lib/cjs/core/parser/typography.d.ts +5 -5
  33. package/lib/cjs/core/style-builder/build-style.cjs +12 -3
  34. package/lib/cjs/core/style-builder/build-style.cjs.map +1 -1
  35. package/lib/cjs/core/style-builder/build-style.d.ts +3 -1
  36. package/lib/cjs/core/style-builder/union-builder.cjs +9 -11
  37. package/lib/cjs/core/style-builder/union-builder.cjs.map +1 -1
  38. package/lib/cjs/core/style-builder/union-builder.d.ts +7 -8
  39. package/lib/cjs/metro/dts.cjs +6 -1
  40. package/lib/cjs/metro/dts.cjs.map +1 -1
  41. package/lib/cjs/metro/transformer.cjs +42 -77
  42. package/lib/cjs/metro/transformer.cjs.map +1 -1
  43. package/lib/cjs/metro/with-config.cjs +9 -29
  44. package/lib/cjs/metro/with-config.cjs.map +1 -1
  45. package/lib/cjs/runtime/hooks/use-scheme.cjs +17 -11
  46. package/lib/cjs/runtime/hooks/use-scheme.cjs.map +1 -1
  47. package/lib/cjs/runtime/hooks/use-scheme.d.ts +7 -4
  48. package/lib/cjs/runtime/index.cjs +2 -1
  49. package/lib/cjs/runtime/index.cjs.map +1 -1
  50. package/lib/cjs/runtime/index.d.ts +2 -2
  51. package/lib/cjs/runtime/lookup-css.cjs +41 -0
  52. package/lib/cjs/runtime/lookup-css.cjs.map +1 -1
  53. package/lib/cjs/runtime/lookup-css.d.ts +29 -0
  54. package/lib/cjs/runtime/resolve.cjs +8 -6
  55. package/lib/cjs/runtime/resolve.cjs.map +1 -1
  56. package/lib/cjs/runtime/wrap.cjs +50 -57
  57. package/lib/cjs/runtime/wrap.cjs.map +1 -1
  58. package/lib/cjs/runtime/wrap.d.ts +10 -4
  59. package/lib/cjs/testing/index.cjs +1 -1
  60. package/lib/cjs/testing/index.cjs.map +1 -1
  61. package/lib/esm/core/parser/color.d.ts +10 -0
  62. package/lib/esm/core/parser/color.mjs +34 -3
  63. package/lib/esm/core/parser/color.mjs.map +1 -1
  64. package/lib/esm/core/parser/declaration.mjs +122 -10
  65. package/lib/esm/core/parser/declaration.mjs.map +1 -1
  66. package/lib/esm/core/parser/gradient.d.ts +2 -1
  67. package/lib/esm/core/parser/gradient.mjs +45 -11
  68. package/lib/esm/core/parser/gradient.mjs.map +1 -1
  69. package/lib/esm/core/parser/keyframes.d.ts +11 -0
  70. package/lib/esm/core/parser/keyframes.mjs +27 -12
  71. package/lib/esm/core/parser/keyframes.mjs.map +1 -1
  72. package/lib/esm/core/parser/layout-dispatcher.mjs +33 -10
  73. package/lib/esm/core/parser/layout-dispatcher.mjs.map +1 -1
  74. package/lib/esm/core/parser/length.mjs +17 -1
  75. package/lib/esm/core/parser/length.mjs.map +1 -1
  76. package/lib/esm/core/parser/safe-area.mjs +24 -3
  77. package/lib/esm/core/parser/safe-area.mjs.map +1 -1
  78. package/lib/esm/core/parser/theme-vars.mjs +58 -8
  79. package/lib/esm/core/parser/theme-vars.mjs.map +1 -1
  80. package/lib/esm/core/parser/tokens.d.ts +9 -0
  81. package/lib/esm/core/parser/tokens.mjs +77 -10
  82. package/lib/esm/core/parser/tokens.mjs.map +1 -1
  83. package/lib/esm/core/parser/transform.mjs +18 -9
  84. package/lib/esm/core/parser/transform.mjs.map +1 -1
  85. package/lib/esm/core/parser/tw-parser.d.ts +20 -0
  86. package/lib/esm/core/parser/tw-parser.mjs +138 -36
  87. package/lib/esm/core/parser/tw-parser.mjs.map +1 -1
  88. package/lib/esm/core/parser/typography-dispatcher.mjs +19 -1
  89. package/lib/esm/core/parser/typography-dispatcher.mjs.map +1 -1
  90. package/lib/esm/core/parser/typography.d.ts +5 -5
  91. package/lib/esm/core/parser/typography.mjs +15 -18
  92. package/lib/esm/core/parser/typography.mjs.map +1 -1
  93. package/lib/esm/core/style-builder/build-style.d.ts +3 -1
  94. package/lib/esm/core/style-builder/build-style.mjs +12 -3
  95. package/lib/esm/core/style-builder/build-style.mjs.map +1 -1
  96. package/lib/esm/core/style-builder/union-builder.d.ts +7 -8
  97. package/lib/esm/core/style-builder/union-builder.mjs +9 -11
  98. package/lib/esm/core/style-builder/union-builder.mjs.map +1 -1
  99. package/lib/esm/metro/dts.mjs +6 -1
  100. package/lib/esm/metro/dts.mjs.map +1 -1
  101. package/lib/esm/metro/transformer.mjs +42 -77
  102. package/lib/esm/metro/transformer.mjs.map +1 -1
  103. package/lib/esm/metro/with-config.mjs +10 -30
  104. package/lib/esm/metro/with-config.mjs.map +1 -1
  105. package/lib/esm/runtime/hooks/use-scheme.d.ts +7 -4
  106. package/lib/esm/runtime/hooks/use-scheme.mjs +17 -11
  107. package/lib/esm/runtime/hooks/use-scheme.mjs.map +1 -1
  108. package/lib/esm/runtime/index.d.ts +2 -2
  109. package/lib/esm/runtime/index.mjs +2 -2
  110. package/lib/esm/runtime/index.mjs.map +1 -1
  111. package/lib/esm/runtime/lookup-css.d.ts +29 -0
  112. package/lib/esm/runtime/lookup-css.mjs +39 -1
  113. package/lib/esm/runtime/lookup-css.mjs.map +1 -1
  114. package/lib/esm/runtime/resolve.mjs +9 -7
  115. package/lib/esm/runtime/resolve.mjs.map +1 -1
  116. package/lib/esm/runtime/wrap.d.ts +10 -4
  117. package/lib/esm/runtime/wrap.mjs +50 -57
  118. package/lib/esm/runtime/wrap.mjs.map +1 -1
  119. package/lib/esm/testing/index.mjs +2 -2
  120. package/lib/esm/testing/index.mjs.map +1 -1
  121. package/package.json +1 -1
  122. package/src/core/parser/color.ts +32 -1
  123. package/src/core/parser/declaration.ts +119 -10
  124. package/src/core/parser/gradient.ts +48 -11
  125. package/src/core/parser/keyframes.ts +31 -3
  126. package/src/core/parser/layout-dispatcher.ts +32 -9
  127. package/src/core/parser/length.ts +18 -1
  128. package/src/core/parser/safe-area.ts +23 -2
  129. package/src/core/parser/theme-vars.ts +75 -8
  130. package/src/core/parser/tokens.ts +76 -9
  131. package/src/core/parser/transform.ts +19 -8
  132. package/src/core/parser/tw-parser.ts +148 -31
  133. package/src/core/parser/typography-dispatcher.ts +20 -1
  134. package/src/core/parser/typography.ts +15 -15
  135. package/src/core/style-builder/build-style.ts +12 -1
  136. package/src/core/style-builder/union-builder.ts +10 -12
  137. package/src/metro/dts.ts +6 -1
  138. package/src/metro/transformer.ts +42 -78
  139. package/src/metro/with-config.ts +10 -29
  140. package/src/runtime/hooks/use-scheme.ts +17 -10
  141. package/src/runtime/index.ts +2 -1
  142. package/src/runtime/lookup-css.ts +42 -0
  143. package/src/runtime/resolve.ts +9 -7
  144. package/src/runtime/wrap.tsx +57 -61
  145. package/src/testing/index.ts +3 -0
@@ -3,6 +3,7 @@ import { chainFocus, chainPress } from './chain-handlers'
3
3
  import { useInteract } from './hooks/use-interact'
4
4
  import { useRnwind } from './components/rnwind-provider'
5
5
  import type { RnwindState } from './components/rnwind-provider'
6
+ import type { InteractState } from './lookup-css'
6
7
  import { resolve, type ResolvedCss } from './resolve'
7
8
  import type { OnHaptics } from '../core/parser/haptics'
8
9
 
@@ -79,14 +80,20 @@ const CLASSNAME_SUFFIX = 'ClassName'
79
80
  * handled separately by the leaf and never reaches here.
80
81
  * @param props Mutable prop object being assembled for the host.
81
82
  * @param state Rnwind context for resolution.
83
+ * @param interactState Live press/focus state so `active:`/`focus:` variants
84
+ * on a secondary class prop resolve too (undefined for non-interactive).
82
85
  */
83
- function applyContainerClassNames(props: Record<string, unknown>, state: RnwindState): void {
86
+ function applyContainerClassNames(
87
+ props: Record<string, unknown>,
88
+ state: RnwindState,
89
+ interactState?: InteractState,
90
+ ): void {
84
91
  for (const key of Object.keys(props)) {
85
92
  if (!key.endsWith(CLASSNAME_SUFFIX)) continue
86
93
  const value = props[key]
87
94
  if (typeof value !== 'string') continue
88
95
  const styleKey = `${key.slice(0, -CLASSNAME_SUFFIX.length)}Style`
89
- props[styleKey] = resolve(value, state, props[styleKey]).style
96
+ props[styleKey] = resolve(value, state, props[styleKey], interactState).style
90
97
  delete props[key]
91
98
  }
92
99
  }
@@ -102,6 +109,7 @@ function applyContainerClassNames(props: Record<string, unknown>, state: RnwindS
102
109
  * @param state Rnwind context — used to resolve secondary class props.
103
110
  * @param onHaptics Dispatcher from context.
104
111
  * @param userOnPressIn Caller-supplied onPressIn to chain after the haptic.
112
+ * @param interactState Live press/focus state for secondary class props.
105
113
  * @returns The merged prop object for `createElement`.
106
114
  */
107
115
  function buildProps(
@@ -110,10 +118,11 @@ function buildProps(
110
118
  state: RnwindState,
111
119
  onHaptics: OnHaptics | undefined,
112
120
  userOnPressIn?: unknown,
121
+ interactState?: InteractState,
113
122
  ): Record<string, unknown> {
114
123
  warnIfHapticsUnwired(onHaptics, resolved.haptics)
115
124
  const props: Record<string, unknown> = { ...rest, style: resolved.style }
116
- applyContainerClassNames(props, state)
125
+ applyContainerClassNames(props, state, interactState)
117
126
  if (resolved.colors) {
118
127
  props.colors = resolved.colors
119
128
  props.start = resolved.start
@@ -136,66 +145,31 @@ function buildProps(
136
145
  return props
137
146
  }
138
147
 
139
- /** Props a leaf receivesthe wrapped `as` tag plus forwarded props. */
140
- interface LeafProps {
141
- readonly as: ComponentType<Record<string, unknown>>
148
+ /** Props the wrapped renderer accepts — `className` plus forwarded props. */
149
+ interface WrappedProps {
142
150
  readonly className?: string
143
151
  readonly style?: unknown
152
+ readonly onPressIn?: unknown
153
+ readonly onPressOut?: unknown
154
+ readonly onFocus?: unknown
155
+ readonly onBlur?: unknown
144
156
  readonly [key: string]: unknown
145
157
  }
146
158
 
147
- /**
148
- * Non-interactive leaf: resolve className → style (+ features) and
149
- * forward. One context read, one molecule/atom resolve.
150
- * @param props Leaf props.
151
- * @param props.as
152
- * @param props.className
153
- * @param props.style
154
- * @param props.onPressIn
155
- * @returns The rendered `as` element.
156
- */
157
- function PlainLeaf({ as: As, className, style, onPressIn, ...rest }: LeafProps): ReactElement {
158
- const state = useRnwind()
159
- const resolved = resolve(className, state, style)
160
- useMountHaptics(resolved, state.onHaptics)
161
- return createElement(As, buildProps(rest, resolved, state, state.onHaptics, onPressIn))
162
- }
163
-
164
- /**
165
- * Interactive leaf: tracks press/focus via `useInteract()`, feeds it into
166
- * `resolve` so `active:`/`focus:` atoms apply, and chains the
167
- * press/focus handlers.
168
- * @param props Leaf props.
169
- * @param props.as
170
- * @param props.className
171
- * @param props.style
172
- * @param props.onPressIn
173
- * @param props.onPressOut
174
- * @param props.onFocus
175
- * @param props.onBlur
176
- * @returns The rendered `as` element with interactive wiring.
177
- */
178
- function InteractiveLeaf({ as: As, className, style, onPressIn, onPressOut, onFocus, onBlur, ...rest }: LeafProps): ReactElement {
179
- const state = useRnwind()
180
- const interact = useInteract()
181
- const resolved = resolve(className, state, style, interact.state)
182
- useMountHaptics(resolved, state.onHaptics)
183
- const props = buildProps(rest, resolved, state, state.onHaptics, onPressIn)
184
- props.onPressIn = chainPress(props.onPressIn as Parameters<typeof chainPress>[0], interact.onPressIn)
185
- props.onPressOut = chainPress(onPressOut as Parameters<typeof chainPress>[0], interact.onPressOut)
186
- props.onFocus = chainFocus(onFocus as Parameters<typeof chainFocus>[0], interact.onFocus)
187
- props.onBlur = chainFocus(onBlur as Parameters<typeof chainFocus>[0], interact.onBlur)
188
- return createElement(As, props)
189
- }
190
-
191
159
  /**
192
160
  * Wrap a component so its `className` prop resolves to RN `style` (plus
193
161
  * gradient / truncate props and haptic dispatch) at render — no matter
194
162
  * how className arrived: written directly, spread through `{...rest}`, or
195
- * forwarded down custom wrappers. The returned component is hook-free; it
196
- * dispatches to a plain or interactive leaf so non-interactive elements
197
- * never pay for press/focus state. `ref` (a normal prop in React 19) and
198
- * all other props forward untouched.
163
+ * forwarded down custom wrappers. `ref` (a normal prop in React 19) and all
164
+ * other props forward untouched.
165
+ *
166
+ * A SINGLE stable component does the work and always calls `useInteract()`,
167
+ * so its identity never changes when `className` flips between interactive
168
+ * (`active:`/`focus:`) and not — swapping the rendered component type would
169
+ * unmount + remount the whole host subtree (lost state, effect re-runs,
170
+ * visual flash). `useInteract` is cheap and shares one idle-state ref, so the
171
+ * always-on cost is a couple of `useState` cells; the press/focus handlers
172
+ * and live state only wire in when the className actually needs them.
199
173
  * @example
200
174
  * ```tsx
201
175
  * const Pressable = wrap(RNPressable)
@@ -207,16 +181,38 @@ function InteractiveLeaf({ as: As, className, style, onPressIn, onPressOut, onFo
207
181
  export function wrap<P>(Component: ComponentType<P>): ComponentType<P & { className?: string }> {
208
182
  const as = Component as unknown as ComponentType<Record<string, unknown>>
209
183
  /**
210
- * The wrapped component hook-free dispatcher to a leaf.
184
+ * The wrapped component. Stable identity + unconditional hooks; branches
185
+ * internally on whether the className carries an interactive variant.
211
186
  * @param props Forwarded props with `className` intercepted.
212
- * @param props.className
213
- * @returns The rendered leaf.
187
+ * @param props.className Raw className string.
188
+ * @param props.style Caller-supplied style, merged under the resolved style.
189
+ * @param props.onPressIn Caller onPressIn — chained after haptics / interact.
190
+ * @param props.onPressOut Caller onPressOut — chained with interact when active.
191
+ * @param props.onFocus Caller onFocus — chained with interact when active.
192
+ * @param props.onBlur Caller onBlur — chained with interact when active.
193
+ * @returns The rendered `as` element.
214
194
  */
215
- function RnwindWrapped({ className, ...rest }: { className?: string; [key: string]: unknown }): ReactElement {
216
- if (className !== undefined && hasInteractiveVariant(className)) {
217
- return createElement(InteractiveLeaf, { as, className, ...rest })
195
+ function RnwindWrapped({ className, style, onPressIn, onPressOut, onFocus, onBlur, ...rest }: WrappedProps): ReactElement {
196
+ const state = useRnwind()
197
+ const interact = useInteract()
198
+ const isInteractive = className !== undefined && hasInteractiveVariant(className)
199
+ const interactState = isInteractive ? interact.state : undefined
200
+ const resolved = resolve(className, state, style, interactState)
201
+ useMountHaptics(resolved, state.onHaptics)
202
+ const props = buildProps(rest, resolved, state, state.onHaptics, onPressIn, interactState)
203
+ if (isInteractive) {
204
+ props.onPressIn = chainPress(props.onPressIn as Parameters<typeof chainPress>[0], interact.onPressIn)
205
+ props.onPressOut = chainPress(onPressOut as Parameters<typeof chainPress>[0], interact.onPressOut)
206
+ props.onFocus = chainFocus(onFocus as Parameters<typeof chainFocus>[0], interact.onFocus)
207
+ props.onBlur = chainFocus(onBlur as Parameters<typeof chainFocus>[0], interact.onBlur)
208
+ } else {
209
+ // Forward the caller's press/focus handlers untouched (onPressIn is
210
+ // already set by buildProps, possibly haptic-chained).
211
+ if (onPressOut !== undefined) props.onPressOut = onPressOut
212
+ if (onFocus !== undefined) props.onFocus = onFocus
213
+ if (onBlur !== undefined) props.onBlur = onBlur
218
214
  }
219
- return createElement(PlainLeaf, { as, className, ...rest })
215
+ return createElement(as, props)
220
216
  }
221
217
  RnwindWrapped.displayName = `wrap(${displayNameOf(Component)})`
222
218
  return RnwindWrapped as unknown as ComponentType<P & { className?: string }>
@@ -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
  )