react-native-varia 0.2.1 → 0.2.3

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.
@@ -31,10 +31,12 @@ function Checkbox({
31
31
 
32
32
  const isChecked = checked
33
33
 
34
- // @ts-ignore
35
- const checkSize = CheckboxStyles.check(colorPalette).width
36
- // @ts-ignore
37
- const checkColor = CheckboxStyles.check(colorPalette).color
34
+ const checkStyle = CheckboxStyles.check(colorPalette) as {
35
+ width: string
36
+ color: string
37
+ }
38
+ const checkSize = checkStyle.width
39
+ const checkColor = checkStyle.color
38
40
 
39
41
  return (
40
42
  <Pressable
@@ -67,13 +69,7 @@ export {Checkbox}
67
69
 
68
70
  const Check = ({size, color}: {size: string; color: string}) => {
69
71
  return (
70
- <Svg
71
- width={size}
72
- height={size}
73
- viewBox="0 0 16 13"
74
- fill="none"
75
- // @ts-ignore: svg props
76
- xmlns="http://www.w3.org/2000/svg">
72
+ <Svg width={size} height={size} viewBox="0 0 16 13" fill="none">
77
73
  <Line
78
74
  x1="1.64402"
79
75
  y1="6.05591"
@@ -1,4 +1,4 @@
1
- import {useEffect, useLayoutEffect, useRef} from 'react'
1
+ import {useEffect} from 'react'
2
2
  import {View, StyleSheet} from 'react-native'
3
3
  import Animated, {
4
4
  Easing,
@@ -13,6 +13,7 @@ import {circleProgressTokens} from '../theme/CircleProgress.recipe'
13
13
  import {withUnistyles} from 'react-native-unistyles'
14
14
  import {resolveColor} from '../style/varia/utils'
15
15
  import {PalettesWithNestedKeys} from '../style/varia/types'
16
+ import {SharedValue} from 'react-native-reanimated'
16
17
 
17
18
  const AnimatedCircle = Animated.createAnimatedComponent(Circle)
18
19
  const svgSize = 160
@@ -21,6 +22,8 @@ interface CircleProgressProps {
21
22
  variant?: keyof typeof circleProgressTokens.variants.variant
22
23
  size?: keyof typeof circleProgressTokens.variants.size
23
24
  trackStrokeWidth?: number
25
+ progress: SharedValue<number> // ✅ Nuevo
26
+
24
27
  progressStrokeWidth?: number
25
28
  duration: number
26
29
  trackColor?: string
@@ -37,6 +40,7 @@ const BaseCircleProgress = ({
37
40
  variant = circleProgressTokens.defaultProps.variant,
38
41
  size = circleProgressTokens.defaultProps.size,
39
42
  trackStrokeWidth,
43
+ progress,
40
44
  progressStrokeWidth,
41
45
  duration,
42
46
  trackColor,
@@ -46,17 +50,6 @@ const BaseCircleProgress = ({
46
50
  children,
47
51
  colors,
48
52
  }: CircleProgressProps) => {
49
- const container = useRef<View>(null)
50
-
51
- // useLayoutEffect(() => {
52
- // //@ts-ignore
53
- // container.current?.measure((x, y, width, height) => {
54
- // const pxPerUnit = width / svgSize
55
- // const strokeWidthSVG =
56
- // circleProgressTokens.variants.size[size]?.trackStrokeWidth * pxPerUnit
57
- // })
58
- // }, [])
59
-
60
53
  const resolvedSize = circleProgressTokens.variants.size[size]
61
54
 
62
55
  const colorValue = circleProgressTokens.variants.variant[variant]
@@ -80,21 +73,26 @@ const BaseCircleProgress = ({
80
73
 
81
74
  const center = svgSize! / 2
82
75
 
83
- const progress = useSharedValue(duration)
76
+ const internalProgress = useSharedValue(0)
84
77
 
85
78
  useEffect(() => {
86
- progress.value = withTiming(0, {
87
- duration: duration,
88
- easing: Easing.linear,
89
- })
90
- }, [])
79
+ if (!progress) {
80
+ internalProgress.value = 0
81
+ internalProgress.value = withTiming(1, {
82
+ duration: duration,
83
+ easing: Easing.linear,
84
+ })
85
+ }
86
+ }, [progress, duration])
87
+
88
+ const progressValue = progress || internalProgress
91
89
 
92
90
  const animatedProps = useAnimatedProps(() => {
93
91
  const rStrokeDashOffset = interpolate(
94
- progress.value,
92
+ progressValue.value,
95
93
  [
96
- progressDirection === 'forward' ? duration : 0,
97
- progressDirection === 'forward' ? 0 : duration,
94
+ progressDirection === 'forward' ? 0 : 1,
95
+ progressDirection === 'forward' ? 1 : 0,
98
96
  ],
99
97
  [circumference, 0],
100
98
  Extrapolation.CLAMP,
@@ -108,7 +106,7 @@ const BaseCircleProgress = ({
108
106
  })
109
107
 
110
108
  return (
111
- <View style={styles.container} ref={container}>
109
+ <View style={styles.container}>
112
110
  <Svg
113
111
  width="100%"
114
112
  height="100%"
@@ -0,0 +1,539 @@
1
+ import React, {
2
+ createContext,
3
+ useContext,
4
+ useImperativeHandle,
5
+ useMemo,
6
+ } from 'react'
7
+ import {TouchableWithoutFeedback} from 'react-native'
8
+ import {Gesture, GestureDetector} from 'react-native-gesture-handler'
9
+ import Animated, {
10
+ measure,
11
+ SharedValue,
12
+ useAnimatedReaction,
13
+ useAnimatedRef,
14
+ useAnimatedStyle,
15
+ useSharedValue,
16
+ withSpring,
17
+ withTiming,
18
+ } from 'react-native-reanimated'
19
+ import {runOnUI, scheduleOnRN, scheduleOnUI} from 'react-native-worklets'
20
+ import {
21
+ SlidingDrawerTokens,
22
+ SlidingDrawerStyles,
23
+ } from '../theme/SlidingDrawer.recipe'
24
+ import {PalettesWithNestedKeys} from '../style/varia/types'
25
+ import {
26
+ StyleSheet,
27
+ UnistylesRuntime,
28
+ UnistylesVariants,
29
+ } from 'react-native-unistyles'
30
+ import {HStack} from '../patterns'
31
+
32
+ /* -----------------------------
33
+ * Types
34
+ * ----------------------------*/
35
+
36
+ export type SlidingDrawerRef = {
37
+ expand: () => void | null
38
+ collapse: () => void | null
39
+ snapTo: (point: number) => void | null
40
+ isCollapsed: () => boolean
41
+ }
42
+
43
+ type SlidingDrawerVariants = UnistylesVariants<typeof SlidingDrawerStyles>
44
+
45
+ type DrawerContextType = SlidingDrawerVariants & {
46
+ colorPalette: PalettesWithNestedKeys
47
+ overlayOpacity: SharedValue<number>
48
+ }
49
+
50
+ type DrawerRootProps = SlidingDrawerVariants & {
51
+ colorPalette?: PalettesWithNestedKeys
52
+ children?: React.ReactNode
53
+ }
54
+
55
+ /* -----------------------------
56
+ * Context
57
+ * ----------------------------*/
58
+
59
+ const DrawerContext = createContext<DrawerContextType | null>(null)
60
+ const useDrawer = () => {
61
+ const ctx = useContext(DrawerContext)
62
+ if (!ctx)
63
+ throw new Error('Drawer subcomponents must be used within Drawer.Root')
64
+ return ctx
65
+ }
66
+
67
+ /* -----------------------------
68
+ * Root
69
+ * ----------------------------*/
70
+
71
+ const DrawerRoot = ({
72
+ colorPalette = 'accent',
73
+ variant = SlidingDrawerTokens.defaultProps.variant,
74
+ children,
75
+ }: DrawerRootProps) => {
76
+ SlidingDrawerStyles.useVariants({variant})
77
+
78
+ const overlayOpacity = useSharedValue(0)
79
+ const value = useMemo(
80
+ () => ({
81
+ colorPalette,
82
+ variant,
83
+ overlayOpacity,
84
+ }),
85
+ [colorPalette, variant],
86
+ )
87
+
88
+ return (
89
+ <DrawerContext.Provider value={value}>{children}</DrawerContext.Provider>
90
+ )
91
+ }
92
+
93
+ /* -----------------------------
94
+ * Positioner
95
+ * ----------------------------*/
96
+ const DrawerPositioner = ({
97
+ children,
98
+ direction,
99
+ axis,
100
+ }: {
101
+ children?: React.ReactNode
102
+ direction: 1 | -1
103
+ axis: 'x' | 'y'
104
+ }) => {
105
+ const {variant} = useDrawer()
106
+ SlidingDrawerStyles.useVariants({variant})
107
+
108
+ type WithDirection = {direction?: 1 | -1; axis?: 'x' | 'y'}
109
+
110
+ const enhancedChildren = React.Children.map(children, child => {
111
+ if (React.isValidElement(child)) {
112
+ return React.cloneElement(child as React.ReactElement<WithDirection>, {
113
+ direction,
114
+ axis,
115
+ })
116
+ }
117
+ return child
118
+ })
119
+
120
+ return (
121
+ <HStack
122
+ style={[
123
+ styles.positioner,
124
+ SlidingDrawerStyles.positioner,
125
+ {
126
+ justifyContent:
127
+ axis === 'y'
128
+ ? 'center'
129
+ : direction === 1
130
+ ? 'flex-start'
131
+ : 'flex-end',
132
+ alignItems:
133
+ axis === 'x'
134
+ ? 'center'
135
+ : direction === 1
136
+ ? 'flex-start'
137
+ : 'flex-end',
138
+ },
139
+ ]}>
140
+ {enhancedChildren}
141
+ </HStack>
142
+ )
143
+ }
144
+
145
+ /* -----------------------------
146
+ * Overlay
147
+ * ----------------------------*/
148
+ const AnimatedTouchable = Animated.createAnimatedComponent(
149
+ TouchableWithoutFeedback,
150
+ )
151
+
152
+ const DrawerOverlay = ({onPress}: {onPress?: () => void}) => {
153
+ const {colorPalette, overlayOpacity, variant} = useDrawer()
154
+ SlidingDrawerStyles.useVariants({variant})
155
+ const visible = useSharedValue(0)
156
+
157
+ useAnimatedReaction(
158
+ () => overlayOpacity.value,
159
+ value => {
160
+ if (value === 0) {
161
+ visible.value = 0
162
+ } else {
163
+ visible.value = 1
164
+ }
165
+ },
166
+ )
167
+
168
+ const displayOverlayStyle = useAnimatedStyle(() => ({
169
+ opacity: withTiming(overlayOpacity.value, {duration: 50}),
170
+ display: visible.value === 0 ? 'none' : 'flex',
171
+ }))
172
+
173
+ return (
174
+ <AnimatedTouchable onPress={onPress}>
175
+ <Animated.View
176
+ style={[
177
+ StyleSheet.absoluteFillObject,
178
+ displayOverlayStyle,
179
+ SlidingDrawerStyles.overlay(colorPalette),
180
+ ]}
181
+ />
182
+ </AnimatedTouchable>
183
+ )
184
+ }
185
+
186
+ /* -----------------------------
187
+ * Slider (gestión independiente)
188
+ * ----------------------------*/
189
+
190
+ type InternalDrawerSliderProps = {
191
+ axis: 'x' | 'y'
192
+ direction: 1 | -1
193
+ lockAtEdges?: boolean
194
+ snapPoints?: number[] | ('hidden' | 'content')[]
195
+ animation?: keyof typeof SlidingDrawerTokens.variants.animation
196
+ onExpand?: () => void
197
+ onCollapse?: () => void
198
+ onSnap?: (point: number) => void
199
+ allowGestures?: boolean
200
+ children?: React.ReactNode
201
+ ref?: React.RefObject<SlidingDrawerRef | null>
202
+ externalTranslate?: SharedValue<number>
203
+ }
204
+
205
+ // Tipo público — el que exportas (sin direction)
206
+ export type DrawerSliderProps = Omit<
207
+ InternalDrawerSliderProps,
208
+ 'direction' | 'axis'
209
+ >
210
+
211
+ export const DrawerSlider = (props: DrawerSliderProps) => {
212
+ return <DrawerSliderInternal {...(props as InternalDrawerSliderProps)} />
213
+ }
214
+
215
+ const DrawerSliderInternal = ({
216
+ axis,
217
+ direction,
218
+ lockAtEdges = false,
219
+ snapPoints = ['hidden', 'content'],
220
+ animation = SlidingDrawerTokens.defaultProps.animation,
221
+ onExpand,
222
+ onCollapse,
223
+ onSnap,
224
+ allowGestures = true,
225
+ children,
226
+ externalTranslate,
227
+ ref,
228
+ }: InternalDrawerSliderProps) => {
229
+ const {variant, colorPalette, overlayOpacity} = useDrawer()
230
+
231
+ SlidingDrawerStyles.useVariants({variant})
232
+
233
+ const screenHeight =
234
+ UnistylesRuntime.screen.height - UnistylesRuntime.insets.top
235
+ const screenWidth = UnistylesRuntime.screen.width
236
+
237
+ const animations = {withSpring, withTiming}
238
+ const animationVariant = SlidingDrawerTokens.variants.animation[animation]
239
+ const VELOCITY_THRESHOLD = 2000
240
+
241
+ // --- shared values base ---
242
+ const viewRef = useAnimatedRef<Animated.View>()
243
+ const translate = useSharedValue(screenHeight)
244
+ const context = useSharedValue({position: screenHeight, snapPoint: 0})
245
+ const contentHeight = useSharedValue(0)
246
+ const resolvedSnapPoints = useSharedValue<number[]>([])
247
+
248
+ if (externalTranslate) {
249
+ useAnimatedReaction(
250
+ () => translate.value,
251
+ value => {
252
+ externalTranslate.value = value
253
+ },
254
+ )
255
+ }
256
+
257
+ // --- medir el contenido dinámicamente ---
258
+ // const onLayout = () => {
259
+ // scheduleOnUI(() => {
260
+ // 'worklet'
261
+ // const measured = measure(viewRef)
262
+ // if (measured) {
263
+ // const {height} = measured
264
+ // contentHeight.value = height
265
+
266
+ // // resuelve snapPoints declarativos
267
+ // const resolved = snapPoints.map(p => {
268
+ // if (p === 'hidden') return screenHeight * direction
269
+ // if (p === 'content') return (screenHeight - height) * direction
270
+ // // if (typeof p === 'string' && p.endsWith('%')) {
271
+ // // const percentage = parseFloat(p) / 100
272
+ // // return screenHeight * (1 - percentage) * direction
273
+ // // }
274
+ // return p * direction
275
+ // })
276
+
277
+ // resolvedSnapPoints.value = resolved
278
+
279
+ // // inicializa la posición (oculto)
280
+ // translate.value = resolved[0]
281
+ // context.value = {position: resolved[0], snapPoint: 0}
282
+ // }
283
+ // })
284
+ // }
285
+
286
+ const onLayout = () => {
287
+ // captura valores aquí (en JS)
288
+ const _screenHeight = screenHeight
289
+ const _screenWidth = screenWidth
290
+ const _axis = axis
291
+ const _direction = direction
292
+ const _snapPoints = snapPoints
293
+
294
+ scheduleOnUI(() => {
295
+ 'worklet'
296
+ const measured = measure(viewRef)
297
+ if (measured) {
298
+ const {height, width} = measured
299
+ const size = _axis === 'y' ? height : width
300
+ const screenSize = _axis === 'y' ? _screenHeight : _screenWidth
301
+
302
+ const resolved = _snapPoints.map(p => {
303
+ if (p === 'hidden') return screenSize * _direction
304
+ if (p === 'content') return (screenSize - size) * _direction
305
+ return (p as number) * _direction
306
+ })
307
+
308
+ resolvedSnapPoints.value = resolved
309
+ translate.value = resolved[0]
310
+ context.value = {position: resolved[0], snapPoint: 0}
311
+ }
312
+ })
313
+ }
314
+
315
+ const getPoints = () => {
316
+ 'worklet'
317
+ return resolvedSnapPoints.value.length > 0
318
+ ? resolvedSnapPoints.value
319
+ : snapPoints.map(p => (p as any) * direction)
320
+ }
321
+
322
+ // --- lógica de snapping ---
323
+ const updateCurrentSnapPoint = (snapPoint: number) => {
324
+ 'worklet'
325
+ context.value = {position: context.value.position, snapPoint}
326
+ }
327
+
328
+ const snapTo = (destination: number) => {
329
+ 'worklet'
330
+ const points = getPoints()
331
+ const point = points[destination]
332
+ if (animationVariant?.type && point != null) {
333
+ translate.value = animations[animationVariant.type](
334
+ point,
335
+ animationVariant.props,
336
+ )
337
+ updateCurrentSnapPoint(destination)
338
+ onSnap && scheduleOnRN(onSnap, destination)
339
+ }
340
+ }
341
+
342
+ const isCollapsed = () => {
343
+ 'worklet'
344
+ return context.value.snapPoint === 0
345
+ }
346
+
347
+ const showOverlay = () => {
348
+ 'worklet'
349
+ overlayOpacity.value = withTiming(1, {duration: 200})
350
+ }
351
+
352
+ const hideOverlay = () => {
353
+ 'worklet'
354
+ overlayOpacity.value = withTiming(0, {duration: 200})
355
+ }
356
+
357
+ const expand = () => {
358
+ const points = getPoints()
359
+ snapTo(points.length - 1)
360
+ showOverlay()
361
+ onExpand && scheduleOnRN(onExpand)
362
+ }
363
+
364
+ const collapse = () => {
365
+ snapTo(0)
366
+ hideOverlay()
367
+ onCollapse && scheduleOnRN(onCollapse)
368
+ }
369
+
370
+ useImperativeHandle(ref, () => ({
371
+ expand,
372
+ collapse,
373
+ snapTo,
374
+ isCollapsed,
375
+ }))
376
+
377
+ // --- sincronizar overlay con movimiento ---
378
+ useAnimatedReaction(
379
+ () => translate.value,
380
+ value => {
381
+ const points = getPoints()
382
+ if (points.length < 2) return
383
+
384
+ const collapsed = points[0]
385
+ const next = points[1] ?? collapsed
386
+ const threshold = 20
387
+ const opensUpward = next < collapsed
388
+ const delta = value - collapsed
389
+ const isExpanded = opensUpward ? delta < -threshold : delta > threshold
390
+
391
+ overlayOpacity.value = withTiming(isExpanded ? 1 : 0, {duration: 150})
392
+ },
393
+ )
394
+
395
+ // --- Gestures ---
396
+ const slideGesture = Gesture.Pan()
397
+ .enabled(allowGestures)
398
+ .onBegin(() => {
399
+ context.value.position = translate.value
400
+ })
401
+ .onUpdate(event => {
402
+ const delta = axis === 'y' ? event.translationY : event.translationX
403
+ const proposed = delta + (context.value.position ?? 0)
404
+ const points = getPoints()
405
+ const minPoint = Math.min(...points)
406
+ const maxPoint = Math.max(...points)
407
+ let clamped = proposed
408
+
409
+ if (proposed < minPoint) {
410
+ if (lockAtEdges) {
411
+ // Bloquea overscroll superior (cuando ya estás en el extremo)
412
+ clamped = minPoint
413
+ } else {
414
+ // Aplica resistencia
415
+ const overdrag = minPoint - proposed
416
+ clamped = minPoint - overdrag / (1 + overdrag / 60)
417
+ }
418
+ } else if (proposed > maxPoint) {
419
+ if (lockAtEdges) {
420
+ // Bloquea overscroll inferior
421
+ clamped = maxPoint
422
+ } else {
423
+ const overdrag = proposed - maxPoint
424
+ clamped = maxPoint + overdrag / (1 + overdrag / 60)
425
+ }
426
+ }
427
+
428
+ translate.value = clamped
429
+ })
430
+ .onEnd(({velocityX, velocityY, translationX, translationY}) => {
431
+ const velocity = axis === 'y' ? velocityY : velocityX
432
+ const translation = axis === 'y' ? translationY : translationX
433
+ const points = getPoints()
434
+
435
+ const minPoint = Math.min(...points)
436
+ const maxPoint = Math.max(...points)
437
+
438
+ if (translate.value < minPoint) {
439
+ translate.value = withSpring(minPoint, {velocity})
440
+ return
441
+ } else if (translate.value > maxPoint) {
442
+ translate.value = withSpring(maxPoint, {velocity})
443
+ return
444
+ }
445
+
446
+ const forwardsThreshold =
447
+ (points[context.value.snapPoint] +
448
+ points[context.value.snapPoint + 1]) /
449
+ 2
450
+ const backwardsThreshold =
451
+ (points[context.value.snapPoint] +
452
+ points[context.value.snapPoint - 1]) /
453
+ 2
454
+
455
+ if (translation * direction < 0) {
456
+ if (
457
+ ((direction === 1 && translate.value < forwardsThreshold) ||
458
+ (direction === -1 && translate.value > forwardsThreshold) ||
459
+ velocity * direction < -VELOCITY_THRESHOLD) &&
460
+ context.value.snapPoint < points.length - 1
461
+ ) {
462
+ snapTo(context.value.snapPoint + 1)
463
+ } else {
464
+ snapTo(context.value.snapPoint)
465
+ }
466
+ } else {
467
+ if (
468
+ ((direction === 1 && translate.value > backwardsThreshold) ||
469
+ (direction === -1 && translate.value < backwardsThreshold) ||
470
+ velocity * direction > VELOCITY_THRESHOLD) &&
471
+ context.value.snapPoint > 0
472
+ ) {
473
+ snapTo(context.value.snapPoint - 1)
474
+ } else {
475
+ snapTo(context.value.snapPoint)
476
+ }
477
+ }
478
+ })
479
+
480
+ // --- estilos animados ---
481
+ const blockAnimatedStyle = useAnimatedStyle(() => {
482
+ return {
483
+ transform: [
484
+ axis === 'y'
485
+ ? {translateY: translate.value}
486
+ : {translateX: translate.value},
487
+ ],
488
+ }
489
+ })
490
+
491
+ return (
492
+ <GestureDetector gesture={slideGesture}>
493
+ <Animated.View
494
+ ref={viewRef}
495
+ onLayout={onLayout}
496
+ style={[
497
+ styles.slider,
498
+ blockAnimatedStyle,
499
+ SlidingDrawerStyles.slider(colorPalette),
500
+ ]}>
501
+ {children}
502
+ </Animated.View>
503
+ </GestureDetector>
504
+ )
505
+ }
506
+
507
+ /* -----------------------------
508
+ * Export grouped
509
+ * ----------------------------*/
510
+
511
+ export const Drawer = {
512
+ Root: DrawerRoot,
513
+ Positioner: DrawerPositioner,
514
+ Overlay: DrawerOverlay,
515
+ Slider: DrawerSlider,
516
+ }
517
+
518
+ /* -----------------------------
519
+ * Styles
520
+ * ----------------------------*/
521
+
522
+ const styles = StyleSheet.create((theme, rt) => ({
523
+ positioner: {
524
+ flex: 1,
525
+ alignSelf: 'stretch',
526
+ position: 'absolute',
527
+ top: 0,
528
+ left: 0,
529
+ right: 0,
530
+ bottom: 0,
531
+ },
532
+ slider: {
533
+ flex: 1,
534
+ alignSelf: 'stretch',
535
+ alignItems: 'center',
536
+ justifyContent: 'flex-start',
537
+ zIndex: 100,
538
+ },
539
+ }))
@@ -1,8 +1,8 @@
1
1
  import React, {createContext, useContext} from 'react'
2
+ import {UnistylesVariants} from 'react-native-unistyles'
2
3
  import Text from './Text'
3
4
  import {VStack} from '../patterns'
4
5
  import {DefaultFieldVariants, FieldStyles} from '../theme/Field.recipe'
5
- import {UnistylesVariants} from 'react-native-unistyles'
6
6
  import {PalettesWithNestedKeys} from '../style/varia/types'
7
7
 
8
8
  type FieldVariants = UnistylesVariants<typeof FieldStyles>
@@ -90,10 +90,7 @@ const FieldLabel = ({children, ...props}: FieldLabelProps) => {
90
90
  FieldStyles.useVariants({variant, size})
91
91
 
92
92
  return (
93
- <Text
94
- size={size}
95
- // @ts-ignore
96
- color={FieldStyles.label(colorPalette).color}>
93
+ <Text size={size} color={FieldStyles.label(colorPalette).color}>
97
94
  {children}
98
95
  </Text>
99
96
  )
@@ -121,7 +118,6 @@ const FieldError = ({...props}: FieldErrorProps) => {
121
118
  FieldStyles.useVariants({size, variant})
122
119
 
123
120
  return (
124
- // @ts-ignore
125
121
  <Text size={size} color={FieldStyles.error(colorPalette).color}>
126
122
  {error}
127
123
  </Text>
@@ -66,6 +66,11 @@ const Input = ({
66
66
  invalid,
67
67
  })
68
68
 
69
+ const placeholderStyle = InputStyles.placeholder(colorPalette) as {
70
+ color: string
71
+ }
72
+ const placeholderColor = placeholderStyle.color
73
+
69
74
  return (
70
75
  <HStack
71
76
  style={{
@@ -82,8 +87,7 @@ const Input = ({
82
87
  ]}
83
88
  value={value}
84
89
  placeholder={placeholder}
85
- // @ts-ignore
86
- placeholderTextColor={InputStyles.placeholder(colorPalette).color}
90
+ placeholderTextColor={placeholderColor}
87
91
  inputMode={inputMode}
88
92
  keyboardType={keyboardType}
89
93
  secureTextEntry={password}