react-native-varia 0.4.0 → 0.4.2

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.
@@ -77,7 +77,13 @@ function AccordionGroupRoot({
77
77
  })
78
78
  })
79
79
 
80
- return <View style={styles.groupContainer(flex, alignSelf)}>{items}</View>
80
+ return (
81
+ <View
82
+ testID="varia-accordion-group-root"
83
+ style={styles.groupContainer(flex, alignSelf)}>
84
+ {items}
85
+ </View>
86
+ )
81
87
  }
82
88
 
83
89
  function AccordionGroupItem({
@@ -88,23 +94,28 @@ function AccordionGroupItem({
88
94
  children,
89
95
  isOpen = false,
90
96
  onToggle,
97
+ itemKey,
91
98
  }: AccordionItemProps) {
92
99
  AccordionStyles.useVariants({variant, size, active: isOpen})
93
100
  return (
94
101
  <AnimatedView
102
+ testID={`varia-accordion-group-item-${itemKey}`}
95
103
  layout={LinearTransition.duration(150)}
96
104
  style={[
97
105
  styles.itemContainer,
98
106
  AccordionStyles.itemContainer(colorPalette),
99
107
  ]}>
100
108
  <Pressable
109
+ testID={`varia-accordion-group-header-${itemKey}`}
101
110
  onPress={onToggle}
102
111
  style={[styles.header, AccordionStyles.header(colorPalette)]}>
103
112
  <Text style={AccordionStyles.headerTitle(colorPalette)}>{title}</Text>
104
113
  </Pressable>
105
114
 
106
115
  {isOpen && (
107
- <View style={styles.contentContainer}>
116
+ <View
117
+ style={styles.contentContainer}
118
+ testID={`varia-accordion-group-content-${itemKey}`}>
108
119
  <View style={styles.innerContent}>{children}</View>
109
120
  </View>
110
121
  )}
@@ -48,16 +48,24 @@ function Checkbox({
48
48
 
49
49
  return (
50
50
  <Pressable
51
+ testID="varia-checkbox-container"
51
52
  style={[styles.container, CheckboxStyles.container(colorPalette)]}
52
53
  onPress={handlePress}>
53
54
  <View
55
+ testID="varia-check-container"
54
56
  style={[
55
57
  styles.checkContainer,
56
58
  CheckboxStyles.checkContainer(colorPalette),
57
59
  ]}>
58
- {isChecked && <Check size={checkSize} color={checkColor} />}
60
+ {isChecked && (
61
+ <Check testID="varia-check" size={checkSize} color={checkColor} />
62
+ )}
59
63
  </View>
60
- <Text style={CheckboxStyles.label(colorPalette)}>{children}</Text>
64
+ <Text
65
+ testID="varia-checkbox-label"
66
+ style={CheckboxStyles.label(colorPalette)}>
67
+ {children}
68
+ </Text>
61
69
  </Pressable>
62
70
  )
63
71
  }
@@ -81,9 +89,22 @@ const styles = StyleSheet.create({
81
89
 
82
90
  export default Checkbox
83
91
 
84
- const Check = ({size, color}: {size: string; color: string}) => {
92
+ const Check = ({
93
+ size,
94
+ color,
95
+ testID,
96
+ }: {
97
+ size: string
98
+ color: string
99
+ testID?: string
100
+ }) => {
85
101
  return (
86
- <Svg width={size} height={size} viewBox="0 0 16 13" fill="none">
102
+ <Svg
103
+ testID={testID}
104
+ width={size}
105
+ height={size}
106
+ viewBox="0 0 16 13"
107
+ fill="none">
87
108
  <Line
88
109
  x1="1.64402"
89
110
  y1="6.05591"
@@ -17,8 +17,13 @@ const Divider = ({
17
17
  colorPalette?: PalettesWithNestedKeys
18
18
  }) => {
19
19
  return (
20
- <View style={styles.container(size, axis, margin)}>
21
- <View style={[styles.divider(color, colorPalette, size, axis)]} />
20
+ <View
21
+ testID="varia-divider-container"
22
+ style={styles.container(size, axis, margin)}>
23
+ <View
24
+ testID="varia-divider"
25
+ style={[styles.divider(color, colorPalette, size, axis)]}
26
+ />
22
27
  </View>
23
28
  )
24
29
  }
@@ -1,10 +1,18 @@
1
1
  import React, {
2
2
  createContext,
3
3
  useContext,
4
+ useEffect,
4
5
  useImperativeHandle,
5
6
  useMemo,
7
+ useState,
6
8
  } from 'react'
7
- import {Platform, TouchableWithoutFeedback, View} from 'react-native'
9
+ import {
10
+ Dimensions,
11
+ Keyboard,
12
+ Platform,
13
+ TouchableWithoutFeedback,
14
+ View,
15
+ } from 'react-native'
8
16
  import {Gesture, GestureDetector} from 'react-native-gesture-handler'
9
17
  import Animated, {
10
18
  measure,
@@ -228,8 +236,29 @@ const DrawerSliderInternal = ({
228
236
 
229
237
  DrawerStyles.useVariants({variant})
230
238
 
239
+ const [keyboardHeight, setKeyboardHeight] = useState<number>(0)
240
+
241
+ useEffect(() => {
242
+ const showSub = Keyboard.addListener('keyboardDidShow', e => {
243
+ if (e.endCoordinates.height < 50) return // ignoramos eventos “prematuros”
244
+
245
+ console.log(e.endCoordinates.height)
246
+ setKeyboardHeight(e.endCoordinates.height)
247
+ })
248
+ const hideSub = Keyboard.addListener('keyboardDidHide', () => {
249
+ setKeyboardHeight(0)
250
+ })
251
+ return () => {
252
+ showSub.remove()
253
+ hideSub.remove()
254
+ }
255
+ }, [])
256
+
231
257
  const screenHeight =
232
- UnistylesRuntime.screen.height - UnistylesRuntime.insets.top
258
+ Dimensions.get('window').height - UnistylesRuntime.insets.top
259
+
260
+ // const screenHeight =
261
+ // UnistylesRuntime.screen.height - UnistylesRuntime.insets.top
233
262
  const screenWidth = UnistylesRuntime.screen.width
234
263
 
235
264
  const animations = {withSpring, withTiming}
@@ -251,7 +280,10 @@ const DrawerSliderInternal = ({
251
280
  )
252
281
  }
253
282
 
283
+ const initialized = useSharedValue(false)
284
+
254
285
  const onLayout = () => {
286
+ if (initialized.value) return
255
287
  const _screenHeight = screenHeight
256
288
  const _screenWidth = screenWidth
257
289
  const _axis = axis
@@ -275,6 +307,7 @@ const DrawerSliderInternal = ({
275
307
  resolvedSnapPoints.value = resolved
276
308
  translate.value = resolved[0]
277
309
  context.value = {position: resolved[0], snapPoint: 0}
310
+ initialized.value = true
278
311
  }
279
312
  })
280
313
  }
@@ -446,7 +479,7 @@ const DrawerSliderInternal = ({
446
479
  return {
447
480
  transform: [
448
481
  axis === 'y'
449
- ? {translateY: translate.value}
482
+ ? {translateY: translate.value - keyboardHeight}
450
483
  : {translateX: translate.value},
451
484
  ],
452
485
  }
@@ -40,6 +40,7 @@ const FieldRoot = ({
40
40
 
41
41
  return (
42
42
  <View
43
+ testID="varia-field-root"
43
44
  style={[
44
45
  styles.root(flex),
45
46
  FieldStyles.root(colorPalette),
@@ -71,7 +72,11 @@ const FieldLabel = ({children, ...props}: FieldLabelProps) => {
71
72
 
72
73
  FieldStyles.useVariants({variant, size})
73
74
 
74
- return <Text style={FieldStyles.label(colorPalette)}>{children}</Text>
75
+ return (
76
+ <Text testID="varia-field-label" style={FieldStyles.label(colorPalette)}>
77
+ {children}
78
+ </Text>
79
+ )
75
80
  }
76
81
 
77
82
  type FieldErrorProps = {
@@ -96,7 +101,10 @@ const FieldError = ({...props}: FieldErrorProps) => {
96
101
  FieldStyles.useVariants({size, variant})
97
102
 
98
103
  return (
99
- <Text size={size} color={FieldStyles.error(colorPalette).color}>
104
+ <Text
105
+ testID="varia-field-error"
106
+ size={size}
107
+ color={FieldStyles.error(colorPalette).color}>
100
108
  {error}
101
109
  </Text>
102
110
  )
@@ -0,0 +1,216 @@
1
+ import React, {createContext, useContext} from 'react'
2
+ import {View, Pressable} from 'react-native'
3
+ import Animated, {
4
+ withDelay,
5
+ useAnimatedStyle,
6
+ useSharedValue,
7
+ withSpring,
8
+ withTiming,
9
+ } from 'react-native-reanimated'
10
+ import {StyleSheet, UnistylesVariants} from 'react-native-unistyles'
11
+ import Plus from '../icons/Plus'
12
+ import {
13
+ FloatingActionDefaultVariants,
14
+ FloatingActionStyles,
15
+ } from '../theme/FloatingAction'
16
+ import {ViewStyle} from 'react-native'
17
+ import {PalettesWithNestedKeys} from '../style/varia/types'
18
+ import {getVariantValue} from '../style/varia/utils'
19
+
20
+ const AnimatedPressable = Animated.createAnimatedComponent(Pressable)
21
+
22
+ const SPRING_CONFIG = {
23
+ duration: 800,
24
+ overshootClamping: true,
25
+ dampingRatio: 0.8,
26
+ }
27
+
28
+ const FloatingActionContext = createContext<any>(null)
29
+
30
+ const useFloatingContext = () => {
31
+ const ctx = useContext(FloatingActionContext)
32
+ if (!ctx)
33
+ throw new Error('FloatingAction.Item must be inside FloatingAction.Root')
34
+ return ctx
35
+ }
36
+
37
+ type ItemProps = FloatingActionVariants & {
38
+ children: React.ReactNode
39
+ onPress: () => void
40
+ }
41
+
42
+ function Item({children, onPress, ...props}: ItemProps) {
43
+ const {
44
+ direction,
45
+ gap,
46
+ isExpanded,
47
+ index,
48
+ variant,
49
+ size,
50
+ colorPalette = 'accent',
51
+ } = {...useFloatingContext(), ...props}
52
+ FloatingActionStyles.useVariants({
53
+ variant,
54
+ size,
55
+ })
56
+
57
+ const iconHeight = getVariantValue(
58
+ FloatingActionStyles.button(colorPalette),
59
+ 'size',
60
+ size,
61
+ 'height',
62
+ )
63
+ const animatedStyles = useAnimatedStyle(() => {
64
+ const multiplier = direction === 'toTop' ? -1 : 1
65
+ const OFFSET_FROM_MAIN = iconHeight + gap
66
+
67
+ const moveValue = isExpanded.value
68
+ ? (OFFSET_FROM_MAIN + (gap + iconHeight) * (index - 1)) * multiplier
69
+ : 0
70
+
71
+ const delay = index * 30
72
+
73
+ return {
74
+ opacity: withDelay(
75
+ delay,
76
+ withTiming(isExpanded.value ? 1 : 0, {duration: 150}),
77
+ ),
78
+ transform: [
79
+ {translateY: withDelay(delay, withSpring(moveValue, SPRING_CONFIG))},
80
+ {
81
+ scale: withDelay(
82
+ delay,
83
+ withTiming(isExpanded.value ? 1 : 0.95, {duration: 200}),
84
+ ),
85
+ },
86
+ ],
87
+ }
88
+ })
89
+
90
+ return (
91
+ <AnimatedPressable
92
+ testID="varia-floating-action-item"
93
+ style={[
94
+ animatedStyles,
95
+ styles.itemButton,
96
+ FloatingActionStyles.item(colorPalette),
97
+ ]}
98
+ onPress={onPress}>
99
+ {children}
100
+ </AnimatedPressable>
101
+ )
102
+ }
103
+
104
+ type directions = 'toTop' | 'toBottom'
105
+ type FloatingActionVariants = UnistylesVariants<typeof FloatingActionStyles>
106
+ type FloatingActionProps = FloatingActionVariants & {
107
+ colorPalette?: PalettesWithNestedKeys
108
+ gap?: ViewStyle['gap']
109
+ direction?: directions
110
+ top?: ViewStyle['top']
111
+ bottom?: ViewStyle['bottom']
112
+ right?: ViewStyle['right']
113
+ left?: ViewStyle['left']
114
+ children: React.ReactNode
115
+ }
116
+
117
+ function Root({
118
+ variant = FloatingActionDefaultVariants.variant,
119
+ size = FloatingActionDefaultVariants.size,
120
+ colorPalette = 'accent',
121
+ children,
122
+ gap = 10,
123
+ direction = 'toTop',
124
+ top = null,
125
+ bottom = null,
126
+ right = null,
127
+ left = null,
128
+ }: FloatingActionProps) {
129
+ FloatingActionStyles.useVariants({
130
+ variant,
131
+ size,
132
+ })
133
+
134
+ const isExpanded = useSharedValue(false)
135
+
136
+ const plusIconStyle = useAnimatedStyle(() => ({
137
+ transform: [{rotate: withTiming(isExpanded.value ? '45deg' : '0deg')}],
138
+ }))
139
+
140
+ const arrayChildren = React.Children.toArray(children)
141
+
142
+ const iconHeight = getVariantValue(
143
+ FloatingActionStyles.button(colorPalette),
144
+ 'size',
145
+ size,
146
+ 'height',
147
+ )
148
+ const iconColor = getVariantValue(
149
+ FloatingActionStyles.buttonIcon(colorPalette),
150
+ 'variant',
151
+ variant,
152
+ 'color',
153
+ )
154
+ return (
155
+ <View
156
+ testID="varia-floating-action-container"
157
+ style={[
158
+ styles.buttonContainer(top, bottom, left, right),
159
+ FloatingActionStyles.buttonContainer(colorPalette),
160
+ ]}>
161
+ <AnimatedPressable
162
+ testID="varia-floating-action-button"
163
+ onPress={() => (isExpanded.value = !isExpanded.value)}
164
+ style={[
165
+ plusIconStyle,
166
+ styles.button,
167
+ FloatingActionStyles.button(colorPalette),
168
+ ]}>
169
+ <Plus size={iconHeight - 20} color={iconColor} />
170
+ </AnimatedPressable>
171
+ {arrayChildren.map((child: any, i) => (
172
+ <FloatingActionContext.Provider
173
+ key={i}
174
+ value={{
175
+ direction,
176
+ gap,
177
+ isExpanded,
178
+ index: i + 1,
179
+ variant,
180
+ size,
181
+ colorPalette,
182
+ }}>
183
+ {child}
184
+ </FloatingActionContext.Provider>
185
+ ))}
186
+ </View>
187
+ )
188
+ }
189
+
190
+ const FloatingAction = {
191
+ Root,
192
+ Item,
193
+ }
194
+ export default FloatingAction
195
+
196
+ const styles = StyleSheet.create({
197
+ buttonContainer: (top, bottom, left, right) => ({
198
+ position: 'absolute',
199
+ ...(top !== null && top !== undefined ? {top} : {}),
200
+ ...(bottom !== null && bottom !== undefined ? {bottom} : {}),
201
+ ...(left !== null && left !== undefined ? {left} : {}),
202
+ ...(right !== null && right !== undefined ? {right} : {}),
203
+ zIndex: 99,
204
+ alignItems: 'center',
205
+ }),
206
+ button: {
207
+ zIndex: 1,
208
+ justifyContent: 'center',
209
+ alignItems: 'center',
210
+ },
211
+ itemButton: {
212
+ position: 'absolute',
213
+ justifyContent: 'center',
214
+ alignItems: 'center',
215
+ },
216
+ })
@@ -68,7 +68,7 @@ const Icon = ({
68
68
  <Svg
69
69
  width={size || width}
70
70
  height={size || height}
71
- viewBox="0 0 24 24"
71
+ viewBox="0 0 23 23"
72
72
  // viewBox={`0 0 ${viewBoxWidth} ${viewBoxHeight}`}
73
73
  fill="none"
74
74
  {...rest}>
@@ -129,9 +129,11 @@ const Input = ({
129
129
 
130
130
  return (
131
131
  <View
132
+ testID="varia-input-container"
132
133
  style={styles.container(flex, direction, alignSelf, textAlignVertical)}>
133
134
  {IconRendered}
134
135
  <TextInput
136
+ testID="varia-input"
135
137
  editable={!disabled}
136
138
  style={[
137
139
  styles.input(
@@ -65,23 +65,11 @@ export const DrawerStyles = StyleSheet.create((theme, rt) => ({
65
65
  card: {
66
66
  boxShadow: 'none',
67
67
  borderRadius: theme.radii.lg,
68
- // marginHorizontal: theme.spacing[3],
69
68
  borderWidth: 2,
70
69
  borderColor: theme.colors.border.default,
71
- // height: rt.screen.height,
72
- // height: 'auto',
73
70
  alignSelf: 'auto',
74
71
  maxWidth: '90%',
75
72
  },
76
- new: {
77
- maxWidth: '80%',
78
- },
79
- iglooroom: {
80
- padding: 0,
81
- boxShadow: 'none',
82
- borderRadius: theme.radii.none,
83
- backgroundColor: 'transparent',
84
- },
85
73
  },
86
74
  },
87
75
  }),
@@ -0,0 +1,117 @@
1
+ import {StyleSheet} from 'react-native-unistyles'
2
+ import {PalettesWithNestedKeys} from '../style/varia/types'
3
+ import {textStyle} from '../style/varia/textStyles'
4
+
5
+ export const FloatingActionDefaultVariants = {
6
+ variant: 'solid',
7
+ size: 'md',
8
+ } as const
9
+
10
+ export const FloatingActionStyles = StyleSheet.create(theme => ({
11
+ buttonContainer: (colorPalette: PalettesWithNestedKeys) => ({
12
+ variants: {
13
+ variant: {
14
+ solid: {},
15
+ subtle: {},
16
+ outline: {},
17
+ ghost: {},
18
+ },
19
+ size: {
20
+ sm: {},
21
+ md: {},
22
+ lg: {},
23
+ },
24
+ },
25
+ }),
26
+ button: (colorPalette: PalettesWithNestedKeys) => ({
27
+ borderRadius: theme.radii.full,
28
+ variants: {
29
+ variant: {
30
+ solid: {
31
+ backgroundColor: theme.colors[colorPalette].default,
32
+ },
33
+ outline: {
34
+ borderWidth: 1,
35
+ borderColor: theme.colors[colorPalette].a7,
36
+ },
37
+ subtle: {
38
+ backgroundColor: theme.colors[colorPalette]['a3'],
39
+ },
40
+ ghost: {
41
+ backgroundColor: 'transparent',
42
+ },
43
+ },
44
+ size: {
45
+ sm: {
46
+ height: theme.sizes['8'],
47
+ width: theme.sizes['8'],
48
+ },
49
+ md: {
50
+ height: theme.sizes['10'],
51
+ width: theme.sizes['10'],
52
+ },
53
+ lg: {
54
+ height: theme.sizes['16'],
55
+ width: theme.sizes['16'],
56
+ },
57
+ },
58
+ },
59
+ }),
60
+ buttonIcon: (colorPalette: PalettesWithNestedKeys) => ({
61
+ variants: {
62
+ variant: {
63
+ solid: {
64
+ color: theme.colors.fg.default,
65
+ },
66
+ outline: {
67
+ color: theme.colors[colorPalette].text,
68
+ },
69
+ ghost: {
70
+ color: theme.colors.gray.text,
71
+ },
72
+ subtle: {
73
+ color: theme.colors[colorPalette].text,
74
+ },
75
+ },
76
+ size: {
77
+ sm: {},
78
+ md: {},
79
+ lg: {},
80
+ },
81
+ },
82
+ }),
83
+ item: (colorPalette: PalettesWithNestedKeys) => ({
84
+ borderRadius: theme.radii.full,
85
+ variants: {
86
+ variant: {
87
+ solid: {
88
+ backgroundColor: theme.colors[colorPalette].default,
89
+ },
90
+ outline: {
91
+ borderWidth: 1,
92
+ borderColor: theme.colors[colorPalette].a7,
93
+ },
94
+ subtle: {
95
+ backgroundColor: theme.colors[colorPalette]['a3'],
96
+ },
97
+ ghost: {
98
+ backgroundColor: 'transparent',
99
+ },
100
+ },
101
+ size: {
102
+ sm: {
103
+ height: theme.sizes['8'],
104
+ width: theme.sizes['8'],
105
+ },
106
+ md: {
107
+ height: theme.sizes['10'],
108
+ width: theme.sizes['10'],
109
+ },
110
+ lg: {
111
+ height: theme.sizes['16'],
112
+ width: theme.sizes['16'],
113
+ },
114
+ },
115
+ },
116
+ }),
117
+ }))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-varia",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "bin": {
5
5
  "varia": "bin/cli.js"
6
6
  },