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.
@@ -6,8 +6,8 @@ import {
6
6
  type StyleProp,
7
7
  type ViewStyle,
8
8
  } from 'react-native'
9
- import Text from './Text'
10
9
  import {StyleSheet, UnistylesVariants} from 'react-native-unistyles'
10
+ import Text from './Text'
11
11
  import {PalettesWithNestedKeys, ThemeColors} from '../style/varia/types'
12
12
  import {DefaultTextVariants, TextStyles} from '../theme/Text.recipe'
13
13
  type TextVariants = UnistylesVariants<typeof TextStyles>
@@ -6,12 +6,12 @@ import {
6
6
  StyleSheet as RNStyleSheet,
7
7
  } from 'react-native'
8
8
  import Animated from 'react-native-reanimated'
9
+ import {Portal} from '@gorhom/portal'
10
+ import Svg, {Path} from 'react-native-svg'
9
11
  import {StyleSheet, UnistylesVariants} from 'react-native-unistyles'
10
12
  import Text from './Text'
11
- import Svg, {Path} from 'react-native-svg'
12
13
  import {ModalStyles, ModalTokens} from '../theme/Modal.recipe'
13
14
  import {PalettesWithNestedKeys} from '../style/varia/types'
14
- import {Portal} from '@gorhom/portal'
15
15
 
16
16
  type ModalVariants = UnistylesVariants<typeof ModalStyles>
17
17
  type AnimationKey = keyof typeof ModalTokens.animations.variants
@@ -176,8 +176,6 @@ const CloseButton = ({
176
176
  }: CloseButtonProps) => (
177
177
  <TouchableOpacity onPress={onClose}>
178
178
  <Svg
179
- // @ts-ignore
180
- xmlns="http://www.w3.org/2000/svg"
181
179
  width={scale * 24}
182
180
  height={scale * 24}
183
181
  viewBox={`0 0 ${24} ${24}`}
@@ -1,12 +1,11 @@
1
1
  import React, {createContext, useContext, useState} from 'react'
2
2
  import {View, TextInput, Pressable} from 'react-native'
3
+ import {UnistylesVariants, StyleSheet} from 'react-native-unistyles'
3
4
  import {
4
5
  NumberInputStyles,
5
6
  NumberInputDefaultVariants,
6
7
  } from '../theme/NumberInput.recipe'
7
8
  import {PalettesWithNestedKeys} from '../style/varia/types'
8
- import {UnistylesVariants, StyleSheet} from 'react-native-unistyles'
9
- import Arrow from '../icons/Arrow'
10
9
  import Plus from '../icons/Plus'
11
10
  import Minus from '../icons/Minus'
12
11
 
@@ -15,6 +14,12 @@ type NumberInputVariants = UnistylesVariants<typeof NumberInputStyles>
15
14
  type PublicInputProps = Omit<NumberInputVariants, 'variant' | 'size'> & {
16
15
  placeholder?: string
17
16
  }
17
+
18
+ interface IconProps {
19
+ color?: string
20
+ size?: number
21
+ }
22
+
18
23
  type PublicTriggerProps = {
19
24
  children?: React.ReactNode
20
25
  variant?: NumberInputVariants['variant']
@@ -154,10 +159,20 @@ const NumberInput = {
154
159
  distribution = NumberInputDefaultVariants.distribution,
155
160
  colorPalette = 'accent',
156
161
  children,
157
- min,
158
162
  max,
159
163
  } = {...useSimpleNumberInputContext(), ...props}
160
164
  NumberInputStyles.useVariants({variant, size, distribution})
165
+
166
+ const color = (NumberInputStyles.buttons(colorPalette) as {color: string})
167
+ .color
168
+
169
+ const iconElement = children || <IncreaseTriggerIcon />
170
+ const iconWithProps = React.isValidElement<IconProps>(iconElement)
171
+ ? React.cloneElement(iconElement, {
172
+ color,
173
+ })
174
+ : iconElement
175
+
161
176
  return (
162
177
  <Pressable
163
178
  onPress={() => setValue(value + 1)}
@@ -167,7 +182,7 @@ const NumberInput = {
167
182
  NumberInputStyles.buttons(colorPalette),
168
183
  NumberInputStyles.increaseTrigger(colorPalette),
169
184
  ]}>
170
- {children || <IncreaseTriggerIcon />}
185
+ {iconWithProps}
171
186
  </Pressable>
172
187
  )
173
188
  },
@@ -182,9 +197,19 @@ const NumberInput = {
182
197
  colorPalette = 'accent',
183
198
  children,
184
199
  min,
185
- max,
186
200
  } = {...useSimpleNumberInputContext(), ...props}
187
201
  NumberInputStyles.useVariants({variant, size, distribution})
202
+
203
+ const color = (NumberInputStyles.buttons(colorPalette) as {color: string})
204
+ .color
205
+
206
+ const iconElement = children || <DecreaseTriggerIcon />
207
+ const iconWithProps = React.isValidElement<IconProps>(iconElement)
208
+ ? React.cloneElement(iconElement, {
209
+ color,
210
+ })
211
+ : iconElement
212
+
188
213
  return (
189
214
  <Pressable
190
215
  onPress={() => setValue(value - 1)}
@@ -194,18 +219,18 @@ const NumberInput = {
194
219
  NumberInputStyles.buttons(colorPalette),
195
220
  NumberInputStyles.decreaseTrigger(colorPalette),
196
221
  ]}>
197
- {children || <DecreaseTriggerIcon />}
222
+ {iconWithProps}
198
223
  </Pressable>
199
224
  )
200
225
  },
201
226
  }
202
227
 
203
- const IncreaseTriggerIcon = () => {
204
- return <Plus scale={0.8} variant="solid" />
228
+ const IncreaseTriggerIcon = ({color}: {color?: string}) => {
229
+ return <Plus color={color} />
205
230
  }
206
231
 
207
- const DecreaseTriggerIcon = () => {
208
- return <Minus scale={0.8} variant="solid" />
232
+ const DecreaseTriggerIcon = ({color}: {color?: string}) => {
233
+ return <Minus color={color} />
209
234
  }
210
235
 
211
236
  export default NumberInput
@@ -1,3 +1,4 @@
1
+ import {useMemo} from 'react'
1
2
  import type {StyleProp, TextInputProps, TextStyle} from 'react-native'
2
3
  import {TextInput} from 'react-native'
3
4
  import Animated, {SharedValue, useAnimatedProps} from 'react-native-reanimated'
@@ -8,7 +9,6 @@ import {
8
9
  ThemeColors,
9
10
  } from '../style/varia/types'
10
11
  import {TextStyles, DefaultTextVariants} from '../theme/Text.recipe'
11
- import {useMemo} from 'react'
12
12
  import {extractThemeColor} from '../style/varia/utils'
13
13
 
14
14
  type ReTextVariants = UnistylesVariants<typeof TextStyles>
@@ -12,12 +12,12 @@ import {
12
12
  TouchableWithoutFeedback,
13
13
  StyleSheet,
14
14
  } from 'react-native'
15
+ import {UnistylesVariants} from 'react-native-unistyles'
15
16
  import {Portal} from '@gorhom/portal'
16
17
  import Text from './Text'
17
18
  import {StyleSheet as UniStyleSheet} from 'react-native-unistyles'
18
19
  import {SelectStyles, SelectDefaultVariants} from '../theme/Select.recipe'
19
20
  import {PalettesWithNestedKeys} from '../style/varia/types'
20
- import {UnistylesVariants} from 'react-native-unistyles'
21
21
 
22
22
  type SelectVariants = UnistylesVariants<typeof SelectStyles>
23
23
 
@@ -52,19 +52,17 @@ const Slider = ({
52
52
  size,
53
53
  variant,
54
54
  })
55
- // @ts-ignore
56
- const halfSize = (SliderStyles.thumb(colorPalette).width ?? 0) / 2
55
+ const thumbStyle = SliderStyles.thumb(colorPalette)
56
+ const maximumTrackStyle = SliderStyles.maximumTrack(colorPalette)
57
+ const minimumTrackStyle = SliderStyles.minimumTrack(colorPalette, false)
58
+
59
+ const halfSize = (thumbStyle.width ?? 0) / 2
57
60
  const thumbSize = {
58
- // @ts-ignore
59
- width: SliderStyles.thumb(colorPalette).width,
60
- // @ts-ignore
61
- height: SliderStyles.thumb(colorPalette).height,
61
+ width: thumbStyle.width,
62
+ height: thumbStyle.height,
62
63
  }
63
- // @ts-ignore
64
- const maximumTrackWidth = SliderStyles.maximumTrack(colorPalette).height ?? 0
65
- const minimumTrackWidth =
66
- // @ts-ignore
67
- SliderStyles.minimumTrack(colorPalette, false).height ?? 0
64
+ const maximumTrackWidth = maximumTrackStyle.height ?? 0
65
+ const minimumTrackWidth = minimumTrackStyle.height ?? 0
68
66
  const context = useSharedValue({x: 0})
69
67
  const translate = useSharedValue(value)
70
68
  const trackLength = useSharedValue(0)
@@ -7,7 +7,7 @@ import Animated, {
7
7
  withSpring,
8
8
  withTiming,
9
9
  } from 'react-native-reanimated'
10
- import {runOnJS} from 'react-native-worklets'
10
+ import {scheduleOnRN} from 'react-native-worklets'
11
11
  import {StyleSheet, UnistylesVariants} from 'react-native-unistyles'
12
12
  import {Gesture, GestureDetector} from 'react-native-gesture-handler'
13
13
  import {SlideshowStyles, SlideshowTokens} from '../theme/Slideshow.recipe'
@@ -28,7 +28,7 @@ type SlideshowProps = SlideshowVariants & {
28
28
  onSlideChange?: (index: number) => void
29
29
  slideContainerType?: any
30
30
  children: ReactNode
31
- ref?: React.RefObject<SlideshowRef>
31
+ ref?: React.RefObject<SlideshowRef | null>
32
32
  }
33
33
 
34
34
  /**
@@ -99,7 +99,7 @@ const Slideshow = ({
99
99
  )
100
100
 
101
101
  if (onSlideChange) {
102
- runOnJS(onSlideChange)((destination / 100) * NUM_PAGES * -1)
102
+ scheduleOnRN(onSlideChange, (destination / 100) * NUM_PAGES * -1)
103
103
  }
104
104
  }
105
105
  }
@@ -207,14 +207,11 @@ const styles = StyleSheet.create({
207
207
  flexDirection: 'row',
208
208
  }),
209
209
  container: () => ({
210
- zIndex: 1,
211
210
  width: '100%',
212
211
  height: '100%',
213
212
  overflow: 'hidden',
214
213
  justifyContent: 'flex-start',
215
214
  alignItems: 'flex-start',
216
- backgroundColor: 'white',
217
- borderRadius: 16,
218
215
  }),
219
216
  slidesContainer: width => ({
220
217
  flexDirection: 'row',
@@ -1,6 +1,6 @@
1
- import {Gesture, GestureDetector} from 'react-native-gesture-handler'
2
1
  import React, {useImperativeHandle} from 'react'
3
2
  import {StyleSheet, UnistylesVariants} from 'react-native-unistyles'
3
+ import {Gesture, GestureDetector} from 'react-native-gesture-handler'
4
4
  import Animated, {
5
5
  useAnimatedStyle,
6
6
  useSharedValue,
@@ -14,6 +14,7 @@ import {
14
14
  SlidingDrawerStyles,
15
15
  } from '../theme/SlidingDrawer.recipe'
16
16
  import {PalettesWithNestedKeys} from '../style/varia/types'
17
+ import {TouchableWithoutFeedback} from 'react-native'
17
18
 
18
19
  export type SlidingDrawerRef = {
19
20
  snapTo: (point: number) => void | null
@@ -26,6 +27,7 @@ type SlidingDrawerVariants = UnistylesVariants<typeof SlidingDrawerStyles>
26
27
  type SlidingDrawerProps = SlidingDrawerVariants & {
27
28
  colorPalette?: PalettesWithNestedKeys
28
29
  animation?: keyof typeof SlidingDrawerTokens.variants.animation
30
+ width?: string
29
31
  flex?: number
30
32
  direction?: 1 | -1
31
33
  onCollapse?: () => void
@@ -35,14 +37,20 @@ type SlidingDrawerProps = SlidingDrawerVariants & {
35
37
  axis: 'y' | 'x'
36
38
  allowGestures?: boolean
37
39
  overlay?: boolean
40
+ closeOnOverlayPress?: boolean
38
41
  children?: React.ReactNode
39
- ref?: React.RefObject<SlidingDrawerRef>
42
+ ref?: React.RefObject<SlidingDrawerRef | null>
40
43
  }
41
44
 
45
+ const AnimatedTouchableOpacity = Animated.createAnimatedComponent(
46
+ TouchableWithoutFeedback,
47
+ )
48
+
42
49
  const SlidingDrawer = ({
43
50
  colorPalette = 'accent',
44
51
  variant = SlidingDrawerTokens.defaultProps.variant,
45
52
  animation = SlidingDrawerTokens.defaultProps.animation,
53
+ width = '100%',
46
54
  flex = 0,
47
55
  direction = 1,
48
56
  onCollapse,
@@ -52,6 +60,7 @@ const SlidingDrawer = ({
52
60
  axis,
53
61
  allowGestures = true,
54
62
  overlay = false,
63
+ closeOnOverlayPress = true,
55
64
  children,
56
65
  ref,
57
66
  }: SlidingDrawerProps) => {
@@ -147,12 +156,44 @@ const SlidingDrawer = ({
147
156
  })
148
157
  .onUpdate(event => {
149
158
  const delta = axis === 'y' ? event.translationY : event.translationX
150
- translate.value = delta + (context.value.position ?? 0)
159
+
160
+ const proposed = delta + (context.value.position ?? 0)
161
+
162
+ const minPoint = Math.min(...points)
163
+ const maxPoint = Math.max(...points)
164
+
165
+ let clamped = proposed
166
+
167
+ // Si se pasa del rango, aplicamos resistencia
168
+ if (proposed < minPoint) {
169
+ const overdrag = minPoint - proposed
170
+ // Cuanto mayor sea el exceso, menos se mueve (efecto pesado)
171
+ clamped = minPoint - overdrag / (1 + overdrag / 60)
172
+ } else if (proposed > maxPoint) {
173
+ const overdrag = proposed - maxPoint
174
+ clamped = maxPoint + overdrag / (1 + overdrag / 60)
175
+ }
176
+
177
+ translate.value = clamped
178
+ // translate.value = delta + (context.value.position ?? 0)
151
179
  })
152
180
  .onEnd(({velocityX, velocityY, translationX, translationY}) => {
153
181
  const velocity = axis === 'y' ? velocityY : velocityX
154
182
  const translation = axis === 'y' ? translationY : translationX
155
183
 
184
+ const minPoint = Math.min(...points)
185
+ const maxPoint = Math.max(...points)
186
+
187
+ // 🧲 1. Si está fuera del rango, lo regresamos suavemente
188
+ if (translate.value < minPoint) {
189
+ translate.value = withSpring(minPoint, {velocity})
190
+ return
191
+ } else if (translate.value > maxPoint) {
192
+ translate.value = withSpring(maxPoint, {velocity})
193
+ return
194
+ }
195
+
196
+ // 🧭 2. Lógica original de snapping
156
197
  const forwardsThreshold =
157
198
  (points[context.value.snapPoint] +
158
199
  points[context.value.snapPoint + 1]) /
@@ -214,20 +255,21 @@ const SlidingDrawer = ({
214
255
  return (
215
256
  <>
216
257
  {overlay && (
217
- <Animated.View
218
- style={[
219
- {
220
- ...StyleSheet.absoluteFillObject,
221
- },
222
- displayOverlayStyle,
223
- SlidingDrawerStyles.backdrop(colorPalette),
224
- ]}
225
- />
258
+ <AnimatedTouchableOpacity
259
+ onPress={() => closeOnOverlayPress && collapse()}>
260
+ <Animated.View
261
+ style={[
262
+ StyleSheet.absoluteFillObject,
263
+ displayOverlayStyle,
264
+ SlidingDrawerStyles.backdrop(colorPalette),
265
+ ]}
266
+ />
267
+ </AnimatedTouchableOpacity>
226
268
  )}
227
269
  <GestureDetector gesture={slideGesture}>
228
270
  <Animated.View
229
271
  style={[
230
- styles.container(flex, direction, axis, SlidingDrawerTokens),
272
+ styles.container(flex, direction, axis, width),
231
273
  blockAnimatedStyle,
232
274
  SlidingDrawerStyles.container(colorPalette),
233
275
  ]}>
@@ -240,14 +282,16 @@ const SlidingDrawer = ({
240
282
  export default SlidingDrawer
241
283
 
242
284
  const styles = StyleSheet.create({
243
- container: (flex, direction, axis, slidingDrawerTokens): any => ({
285
+ container: (flex, direction, axis, width): any => ({
244
286
  position: flex === 0 ? 'absolute' : 'relative',
245
- bottom: axis === 'y' && direction === 1 ? 0 : 'auto',
246
- top: axis === 'y' && direction === -1 ? 0 : 'auto',
287
+ bottom: axis === 'y' && direction === -1 ? 0 : 'auto',
288
+ top: axis === 'y' && direction === 1 ? 0 : 'auto',
247
289
  left: axis === 'x' ? 0 : 'auto',
248
290
  flex: flex === 0 ? 1 : flex,
249
291
  height: '100%',
250
- width: '100%',
292
+ width,
293
+ flexDirection: 'column',
294
+ alignSelf: 'stretch',
251
295
  alignItems: 'center',
252
296
  justifyContent: 'flex-start',
253
297
  zIndex: 100,
@@ -4,15 +4,14 @@ import {
4
4
  type StyleProp,
5
5
  type ViewStyle,
6
6
  } from 'react-native'
7
- import {withUnistyles} from 'react-native-unistyles'
7
+ import {withUnistyles, UnistylesVariants} from 'react-native-unistyles'
8
8
  import {PalettesWithNestedKeys, ThemeColors} from '../style/varia/types'
9
9
  import {SpinnerTokens} from '../theme/Spinner.recipe'
10
10
  import {resolveColor} from '../style/varia/utils'
11
11
  import {SpinnerStyles} from '../theme/Spinner.recipe'
12
- import {UnistylesVariants} from 'react-native-unistyles'
13
12
 
14
13
  type SpinnerVariants = UnistylesVariants<typeof SpinnerStyles>
15
- type SpinnerProps = SpinnerVariants &
14
+ export type SpinnerProps = SpinnerVariants &
16
15
  Omit<ActivityIndicatorProps, 'size'> & {
17
16
  color?: ThemeColors
18
17
  style?: StyleProp<ViewStyle>
@@ -1,4 +1,4 @@
1
- import {TouchableWithoutFeedback} from 'react-native'
1
+ import {TouchableWithoutFeedback, View} from 'react-native'
2
2
  import Animated, {
3
3
  useAnimatedStyle,
4
4
  useSharedValue,
@@ -41,7 +41,7 @@ const Switch = ({
41
41
  size = SwitchTokens.defaultProps.size,
42
42
  flex = 1,
43
43
  }: SwitchProps) => {
44
- const animatedRef = useRef(null)
44
+ const animatedRef = useRef<View>(null)
45
45
 
46
46
  const isAnimating = useSharedValue(false)
47
47
 
@@ -76,15 +76,11 @@ const Switch = ({
76
76
  const containerWidth = useSharedValue(0)
77
77
 
78
78
  useLayoutEffect(() => {
79
- //@ts-ignore
80
79
  animatedRef.current?.measure((x, y, width) => {
81
80
  containerWidth.value = width
82
- //@ts-ignore
83
81
  const thumbWidth = SwitchStyles.thumb(colorPalette).width
84
- //@ts-ignore
85
82
  const padding = SwitchStyles.container(colorPalette).padding || 0
86
83
  const trackBorderWidth =
87
- //@ts-ignore
88
84
  SwitchStyles.container(colorPalette).borderWidth || 0
89
85
  thumbEnabledPosition.value =
90
86
  width - thumbWidth - trackBorderWidth * 2 - padding * 2
@@ -0,0 +1,24 @@
1
+ import * as React from 'react'
2
+ import {IconWrapperProps, ThemedIcon} from '../components/IconWrapper'
3
+ import {Path} from 'react-native-svg'
4
+ import {View} from 'react-native'
5
+
6
+ const Minus = ({
7
+ color,
8
+ ...props
9
+ }: Omit<IconWrapperProps, 'children' | 'colors'>) => {
10
+ return (
11
+ <ThemedIcon {...props} color={color}>
12
+ <>
13
+ <Path
14
+ stroke={color}
15
+ strokeLinecap="round"
16
+ strokeLinejoin="round"
17
+ strokeWidth="2.5"
18
+ d="M1.5 12h20"
19
+ />
20
+ </>
21
+ </ThemedIcon>
22
+ )
23
+ }
24
+ export default Minus
@@ -0,0 +1,23 @@
1
+ import * as React from 'react'
2
+ import {IconWrapperProps, ThemedIcon} from '../components/IconWrapper'
3
+ import {Path} from 'react-native-svg'
4
+
5
+ const Plus = ({
6
+ color,
7
+ ...props
8
+ }: Omit<IconWrapperProps, 'children' | 'colors'>) => {
9
+ return (
10
+ <ThemedIcon {...props} color={color}>
11
+ <>
12
+ <Path
13
+ stroke={color}
14
+ strokeLinecap="round"
15
+ strokeLinejoin="round"
16
+ strokeWidth="2.5"
17
+ d="M1.5 11.5h20m-10-10v20"
18
+ />
19
+ </>
20
+ </ThemedIcon>
21
+ )
22
+ }
23
+ export default Plus
@@ -269,12 +269,11 @@ export const FlexGrid = ({
269
269
  style?: any
270
270
  children: ReactNode
271
271
  }) => {
272
- const viewRef = useRef(null)
272
+ const viewRef = useRef<View>(null)
273
273
  const gridItems = Children.toArray(children)
274
274
  const [parentWidth, setParentWidth] = useState(0)
275
275
 
276
276
  useLayoutEffect(() => {
277
- // @ts-ignore
278
277
  viewRef.current?.measure((x, y, width, height, pageX, pageY) => {
279
278
  setParentWidth(width)
280
279
  })
@@ -38,7 +38,7 @@ export const NumberInputStyles = StyleSheet.create(theme => ({
38
38
  },
39
39
  variant: {
40
40
  solid: {
41
- color: theme.colors[colorPalette]['1'],
41
+ color: theme.colors[colorPalette].text,
42
42
  borderColor: theme.colors.border.default,
43
43
  borderWidth: 1,
44
44
  borderRadius: theme.radii.sm,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-varia",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "bin": {
5
5
  "varia": "bin/cli.js"
6
6
  },
@@ -13,6 +13,7 @@
13
13
  "description": "",
14
14
  "dependencies": {
15
15
  "commander": "^14.0.0",
16
- "fs-extra": "^11.3.1"
16
+ "fs-extra": "^11.3.1",
17
+ "inquirer": "^8.2.7"
17
18
  }
18
19
  }