react-native-molecules 0.5.0-beta.10 → 0.5.0-beta.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.
- package/components/Checkbox/CheckboxBase.tsx +23 -128
- package/components/Checkbox/utils.ts +0 -25
- package/components/DatePickerInput/DatePickerInput.tsx +4 -2
- package/components/DatePickerInput/DatePickerInputWithoutModal.tsx +0 -4
- package/components/DatePickerInput/types.ts +1 -3
- package/components/DatePickerModal/CalendarEdit.tsx +10 -9
- package/components/FilePicker/FilePicker.tsx +47 -76
- package/components/HelperText/HelperText.tsx +0 -35
- package/components/IconButton/utils.ts +140 -25
- package/components/Select/Select.tsx +12 -9
- package/components/Tabs/TabItem.tsx +35 -58
- package/components/Tabs/TabLabel.tsx +5 -9
- package/components/Tabs/Tabs.tsx +154 -149
- package/components/Tabs/utils.ts +15 -2
- package/components/TextInput/TextInput.tsx +657 -574
- package/components/TextInput/index.tsx +19 -3
- package/components/TextInput/types.ts +76 -27
- package/components/TextInput/utils.ts +225 -145
- package/components/TimePickerField/TimePickerField.tsx +7 -5
- package/components/TouchableRipple/TouchableRipple.native.tsx +1 -1
- package/components/TouchableRipple/TouchableRipple.tsx +1 -1
- package/hooks/index.tsx +0 -5
- package/hooks/useSubcomponents.tsx +31 -33
- package/package.json +3 -3
- package/hooks/useSearchable.tsx +0 -74
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import setColor from 'color';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
memo,
|
|
5
|
-
type PropsWithoutRef,
|
|
6
|
-
useCallback,
|
|
7
|
-
useEffect,
|
|
8
|
-
useMemo,
|
|
9
|
-
useRef,
|
|
10
|
-
} from 'react';
|
|
11
|
-
import { Animated, Platform, View, type ViewProps } from 'react-native';
|
|
12
|
-
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
+
import { forwardRef, memo, type PropsWithoutRef, useCallback, useMemo } from 'react';
|
|
3
|
+
import { Platform, type ViewProps } from 'react-native';
|
|
13
4
|
|
|
14
5
|
import { useActionState } from '../../hooks';
|
|
15
6
|
import { resolveStateVariant } from '../../utils';
|
|
@@ -44,9 +35,6 @@ const CheckboxAndroid = (
|
|
|
44
35
|
}: Props,
|
|
45
36
|
ref: any,
|
|
46
37
|
) => {
|
|
47
|
-
const { current: scaleAnim } = useRef<Animated.Value>(new Animated.Value(1));
|
|
48
|
-
const isFirstRendering = useRef<boolean>(true);
|
|
49
|
-
|
|
50
38
|
const { actionsRef, hovered } = useActionState({ ref, actionsToListen: ['hover'] });
|
|
51
39
|
|
|
52
40
|
const state = resolveStateVariant({
|
|
@@ -63,101 +51,20 @@ const CheckboxAndroid = (
|
|
|
63
51
|
size,
|
|
64
52
|
});
|
|
65
53
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const {
|
|
83
|
-
iconSize,
|
|
84
|
-
rippleColor,
|
|
85
|
-
scale,
|
|
86
|
-
animationDuration,
|
|
87
|
-
rippleContainerStyles,
|
|
88
|
-
filledContainerStyles,
|
|
89
|
-
animatedContainerStyles,
|
|
90
|
-
animatedFillStyles,
|
|
91
|
-
stateLayerStyle,
|
|
92
|
-
iconStyle,
|
|
93
|
-
} = useMemo(() => {
|
|
94
|
-
// const {
|
|
95
|
-
// color: checkedColor,
|
|
96
|
-
// uncheckedColor,
|
|
97
|
-
// animationScale: _scale,
|
|
98
|
-
// animationDuration: _animationDuration,
|
|
99
|
-
// iconSize: _iconSize,
|
|
100
|
-
// padding,
|
|
101
|
-
// width,
|
|
102
|
-
// height,
|
|
103
|
-
// borderRadius,
|
|
104
|
-
// ...checkboxStyles
|
|
105
|
-
// // @ts-ignore
|
|
106
|
-
// } = styles.root;
|
|
107
|
-
|
|
108
|
-
const _color = tokenStylesParser.getColor(checked ? colorProp : uncheckedColorProp);
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
iconStyle: [styles.icon, _color],
|
|
112
|
-
iconSize: iconSizeMap[size],
|
|
113
|
-
// TODO - fix this on web
|
|
114
|
-
rippleColor:
|
|
115
|
-
Platform.OS === 'web' ? undefined : setColor(_color).fade(0.32).rgb().string(),
|
|
116
|
-
checkboxStyle: [styles.root, style],
|
|
117
|
-
scale: 1,
|
|
118
|
-
animationDuration: 100,
|
|
119
|
-
rippleContainerStyles: [styles.root],
|
|
120
|
-
animatedContainerStyles: { transform: [{ scale: scaleAnim }] },
|
|
121
|
-
filledContainerStyles: [StyleSheet.absoluteFill, styles.fillContainer],
|
|
122
|
-
// for toggle animation // This needs to be computed because it's opinionated animation
|
|
123
|
-
animatedFillStyles: [
|
|
124
|
-
styles.animatedFill, // 4 because padding - border(which is 1px each side)
|
|
125
|
-
tokenStylesParser.getColor(checked ? colorProp : uncheckedColorProp, 'borderColor'),
|
|
126
|
-
{ borderWidth },
|
|
127
|
-
],
|
|
128
|
-
stateLayerStyle: [styles.stateLayer, stateLayerProps?.style],
|
|
129
|
-
};
|
|
130
|
-
}, [
|
|
131
|
-
borderWidth,
|
|
132
|
-
checked,
|
|
133
|
-
colorProp,
|
|
134
|
-
scaleAnim,
|
|
135
|
-
stateLayerProps?.style,
|
|
136
|
-
style,
|
|
137
|
-
uncheckedColorProp,
|
|
138
|
-
size,
|
|
139
|
-
]);
|
|
140
|
-
|
|
141
|
-
useEffect(() => {
|
|
142
|
-
// Do not run animation on very first rendering
|
|
143
|
-
if (isFirstRendering.current) {
|
|
144
|
-
isFirstRendering.current = false;
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
Animated.sequence([
|
|
149
|
-
Animated.timing(scaleAnim, {
|
|
150
|
-
toValue: 0.85,
|
|
151
|
-
duration: checked ? animationDuration * scale : 0,
|
|
152
|
-
useNativeDriver: false,
|
|
153
|
-
}),
|
|
154
|
-
Animated.timing(scaleAnim, {
|
|
155
|
-
toValue: 1,
|
|
156
|
-
duration: checked ? animationDuration * scale : animationDuration * scale * 1.75,
|
|
157
|
-
useNativeDriver: false,
|
|
158
|
-
}),
|
|
159
|
-
]).start();
|
|
160
|
-
}, [checked, scaleAnim, scale, animationDuration]);
|
|
54
|
+
const { iconSize, rippleColor, rippleContainerStyles, stateLayerStyle, iconStyle } =
|
|
55
|
+
useMemo(() => {
|
|
56
|
+
const _color = tokenStylesParser.getColor(checked ? colorProp : uncheckedColorProp);
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
iconStyle: [styles.icon, _color],
|
|
60
|
+
iconSize: iconSizeMap[size],
|
|
61
|
+
// TODO - fix this on web
|
|
62
|
+
rippleColor:
|
|
63
|
+
Platform.OS === 'web' ? undefined : setColor(_color).fade(0.32).rgb().string(),
|
|
64
|
+
rippleContainerStyles: [styles.root, style],
|
|
65
|
+
stateLayerStyle: [styles.stateLayer, stateLayerProps?.style],
|
|
66
|
+
};
|
|
67
|
+
}, [checked, colorProp, uncheckedColorProp, size, style, stateLayerProps?.style]);
|
|
161
68
|
|
|
162
69
|
const onChange = useCallback(() => {
|
|
163
70
|
onChangeProp?.(!checked);
|
|
@@ -185,18 +92,13 @@ const CheckboxAndroid = (
|
|
|
185
92
|
testID={testID}
|
|
186
93
|
ref={actionsRef}>
|
|
187
94
|
<>
|
|
188
|
-
<
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
/>
|
|
196
|
-
<View style={filledContainerStyles}>
|
|
197
|
-
<Animated.View style={animatedFillStyles} />
|
|
198
|
-
</View>
|
|
199
|
-
</Animated.View>
|
|
95
|
+
<Icon
|
|
96
|
+
allowFontScaling={false}
|
|
97
|
+
type="material-community"
|
|
98
|
+
name={icon}
|
|
99
|
+
size={iconSize}
|
|
100
|
+
style={iconStyle}
|
|
101
|
+
/>
|
|
200
102
|
<StateLayer
|
|
201
103
|
testID={testID ? `${testID}-stateLayer` : ''}
|
|
202
104
|
{...stateLayerProps}
|
|
@@ -207,11 +109,4 @@ const CheckboxAndroid = (
|
|
|
207
109
|
);
|
|
208
110
|
};
|
|
209
111
|
|
|
210
|
-
// const styles = StyleSheet.create({
|
|
211
|
-
// fillContainer: {
|
|
212
|
-
// alignItems: 'center',
|
|
213
|
-
// justifyContent: 'center',
|
|
214
|
-
// },
|
|
215
|
-
// });
|
|
216
|
-
|
|
217
112
|
export default memo(forwardRef(CheckboxAndroid));
|
|
@@ -132,31 +132,6 @@ const checkboxStylesDefault = StyleSheet.create(theme => ({
|
|
|
132
132
|
},
|
|
133
133
|
],
|
|
134
134
|
},
|
|
135
|
-
fillContainer: {
|
|
136
|
-
alignItems: 'center',
|
|
137
|
-
justifyContent: 'center',
|
|
138
|
-
},
|
|
139
|
-
animatedFill: {
|
|
140
|
-
width: 24 / 2 + (PADDING - 2),
|
|
141
|
-
height: 24 / 2 + (PADDING - 2),
|
|
142
|
-
|
|
143
|
-
variants: {
|
|
144
|
-
size: {
|
|
145
|
-
sm: {
|
|
146
|
-
width: iconSizeMap.sm / 2 + (PADDING - 2),
|
|
147
|
-
height: iconSizeMap.sm / 2 + (PADDING - 2),
|
|
148
|
-
},
|
|
149
|
-
md: {
|
|
150
|
-
width: iconSizeMap.md / 2 + (PADDING - 2),
|
|
151
|
-
height: iconSizeMap.md / 2 + (PADDING - 2),
|
|
152
|
-
},
|
|
153
|
-
lg: {
|
|
154
|
-
width: iconSizeMap.lg / 2 + (PADDING - 2),
|
|
155
|
-
height: iconSizeMap.lg / 2 + (PADDING - 2),
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
135
|
icon: {
|
|
161
136
|
color: theme.colors.onSurfaceVariant,
|
|
162
137
|
|
|
@@ -5,6 +5,7 @@ import { useLatest, useToggle } from '../../hooks';
|
|
|
5
5
|
import { noop } from '../../utils/lodash';
|
|
6
6
|
import { DatePickerDocked } from '../DatePickerDocked';
|
|
7
7
|
import { IconButton } from '../IconButton';
|
|
8
|
+
import { TextInput } from '../TextInput';
|
|
8
9
|
import DatePickerInputModal from './DatePickerInputModal';
|
|
9
10
|
import DatePickerInputWithoutModal from './DatePickerInputWithoutModal';
|
|
10
11
|
import type { DatePickerInputProps } from './types';
|
|
@@ -125,8 +126,9 @@ function DatePickerInput(
|
|
|
125
126
|
validRange={validRange}
|
|
126
127
|
onChange={onChange}
|
|
127
128
|
// locale={locale}
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
>
|
|
130
|
+
<TextInput.Right>{rightElement}</TextInput.Right>
|
|
131
|
+
</DatePickerInputWithoutModal>
|
|
130
132
|
);
|
|
131
133
|
}
|
|
132
134
|
|
|
@@ -7,13 +7,11 @@ import { datePickerInputStyles } from './utils';
|
|
|
7
7
|
|
|
8
8
|
function DatePickerInputWithoutModal(
|
|
9
9
|
{
|
|
10
|
-
label,
|
|
11
10
|
value,
|
|
12
11
|
onChange: onChangeProp,
|
|
13
12
|
// locale = 'en',
|
|
14
13
|
validRange,
|
|
15
14
|
inputMode,
|
|
16
|
-
inputButtons,
|
|
17
15
|
dateFormat = 'dd/MM/yyyy',
|
|
18
16
|
style,
|
|
19
17
|
onBlur: onBlurProp,
|
|
@@ -61,14 +59,12 @@ function DatePickerInputWithoutModal(
|
|
|
61
59
|
onBlur={onBlur}
|
|
62
60
|
onFocus={onFocus}
|
|
63
61
|
ref={inputRef}
|
|
64
|
-
label={label}
|
|
65
62
|
value={formattedValue}
|
|
66
63
|
keyboardType={'number-pad'}
|
|
67
64
|
mask={dateFormat}
|
|
68
65
|
onChangeText={onChangeText}
|
|
69
66
|
// keyboardAppearance={theme.dark ? 'dark' : 'default'}
|
|
70
67
|
// error={formattedValue ? !!error : false}
|
|
71
|
-
right={inputButtons}
|
|
72
68
|
// supportingText={formattedValue ? error || undefined : undefined}
|
|
73
69
|
/>
|
|
74
70
|
);
|
|
@@ -23,6 +23,4 @@ export interface DatePickerInputProps
|
|
|
23
23
|
endYear?: number;
|
|
24
24
|
dockedPopoverContentProps?: ViewProps;
|
|
25
25
|
}
|
|
26
|
-
export interface DatePickerInputWithoutModalProps extends Omit<DatePickerInputProps, 'withModal'> {
|
|
27
|
-
inputButtons?: any;
|
|
28
|
-
}
|
|
26
|
+
export interface DatePickerInputWithoutModalProps extends Omit<DatePickerInputProps, 'withModal'> {}
|
|
@@ -3,6 +3,7 @@ import { Keyboard, TextInput as TextInputNative, View } from 'react-native';
|
|
|
3
3
|
|
|
4
4
|
import type { ModeType, ValidRangeType } from '../DatePickerInline';
|
|
5
5
|
import DatePickerInputWithoutModal from '../DatePickerInput/DatePickerInputWithoutModal';
|
|
6
|
+
import { TextInput } from '../TextInput';
|
|
6
7
|
import type { LocalState, LocalStateRange, LocalStateSingle } from './types';
|
|
7
8
|
import { datePickerModalEditStyles } from './utils';
|
|
8
9
|
|
|
@@ -91,14 +92,14 @@ Props) {
|
|
|
91
92
|
<DatePickerInputWithoutModal
|
|
92
93
|
inputMode="start"
|
|
93
94
|
ref={dateInput}
|
|
94
|
-
label={label}
|
|
95
95
|
value={(state as LocalStateSingle).date}
|
|
96
96
|
onChange={onSingleInputChange}
|
|
97
97
|
onSubmitEditing={onSubmitInput}
|
|
98
98
|
validRange={validRange}
|
|
99
99
|
// locale={locale}
|
|
100
|
-
autoComplete={'off'}
|
|
101
|
-
|
|
100
|
+
autoComplete={'off'}>
|
|
101
|
+
<TextInput.Label>{label}</TextInput.Label>
|
|
102
|
+
</DatePickerInputWithoutModal>
|
|
102
103
|
) : null}
|
|
103
104
|
</>
|
|
104
105
|
|
|
@@ -108,27 +109,27 @@ Props) {
|
|
|
108
109
|
<DatePickerInputWithoutModal
|
|
109
110
|
inputMode="start"
|
|
110
111
|
ref={startInput}
|
|
111
|
-
label={startLabel}
|
|
112
112
|
value={(state as LocalStateRange).startDate}
|
|
113
113
|
onChange={onStartDateChange}
|
|
114
114
|
returnKeyType={'next'}
|
|
115
115
|
onSubmitEditing={onSubmitStartInput}
|
|
116
116
|
validRange={validRange}
|
|
117
117
|
// locale={locale}
|
|
118
|
-
autoComplete={'off'}
|
|
119
|
-
|
|
118
|
+
autoComplete={'off'}>
|
|
119
|
+
<TextInput.Label>{startLabel}</TextInput.Label>
|
|
120
|
+
</DatePickerInputWithoutModal>
|
|
120
121
|
<View style={datePickerModalEditStyles.separator} />
|
|
121
122
|
<DatePickerInputWithoutModal
|
|
122
123
|
inputMode="end"
|
|
123
124
|
ref={endInput}
|
|
124
|
-
label={endLabel}
|
|
125
125
|
value={(state as LocalStateRange).endDate}
|
|
126
126
|
onChange={onEndDateChange}
|
|
127
127
|
onSubmitEditing={onSubmitEndInput}
|
|
128
128
|
validRange={validRange}
|
|
129
129
|
// locale={locale}
|
|
130
|
-
autoComplete="off"
|
|
131
|
-
|
|
130
|
+
autoComplete="off">
|
|
131
|
+
<TextInput.Label>{endLabel}</TextInput.Label>
|
|
132
|
+
</DatePickerInputWithoutModal>
|
|
132
133
|
</View>
|
|
133
134
|
) : null}
|
|
134
135
|
</>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { memo, useCallback, useMemo } from 'react';
|
|
2
2
|
|
|
3
|
+
import useControlledValue from '../../hooks/useControlledValue';
|
|
3
4
|
import useFilePicker from '../../hooks/useFilePicker';
|
|
4
5
|
import type { DocumentPickerOptions, DocumentResult } from '../../utils/DocumentPicker';
|
|
5
|
-
import { ActivityIndicator } from '../ActivityIndicator';
|
|
6
6
|
import { IconButton } from '../IconButton';
|
|
7
7
|
import { TextInput, type TextInputProps } from '../TextInput';
|
|
8
8
|
|
|
@@ -10,6 +10,7 @@ export type OmitProp =
|
|
|
10
10
|
| 'editable'
|
|
11
11
|
| 'multiline'
|
|
12
12
|
| 'onChangeText'
|
|
13
|
+
| 'onChange'
|
|
13
14
|
| 'keyboardType'
|
|
14
15
|
| 'defaultValue'
|
|
15
16
|
| 'value'
|
|
@@ -24,12 +25,9 @@ export type Props = Omit<TextInputProps, OmitProp> &
|
|
|
24
25
|
*/
|
|
25
26
|
multiple?: boolean;
|
|
26
27
|
/**
|
|
27
|
-
*
|
|
28
|
-
* @default false
|
|
28
|
+
* Default value for uncontrolled usage
|
|
29
29
|
*/
|
|
30
|
-
|
|
31
|
-
left?: ReactNode;
|
|
32
|
-
right?: ReactNode;
|
|
30
|
+
defaultValue?: DocumentResult | DocumentResult[];
|
|
33
31
|
/**
|
|
34
32
|
* To Control the value
|
|
35
33
|
*/
|
|
@@ -37,32 +35,31 @@ export type Props = Omit<TextInputProps, OmitProp> &
|
|
|
37
35
|
/**
|
|
38
36
|
* The Callback function to return the selected files as an array or object
|
|
39
37
|
*/
|
|
40
|
-
onChange?: (result: DocumentResult | DocumentResult[]) => any;
|
|
41
|
-
/**
|
|
42
|
-
* To replace the default progress indicator
|
|
43
|
-
*/
|
|
44
|
-
progressIndicator?: ReactNode;
|
|
38
|
+
onChange?: (result: DocumentResult | DocumentResult[] | undefined) => any;
|
|
45
39
|
};
|
|
46
40
|
|
|
47
|
-
const FilePicker = (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
41
|
+
const FilePicker = ({
|
|
42
|
+
ref,
|
|
43
|
+
type,
|
|
44
|
+
multiple,
|
|
45
|
+
transitionStyle,
|
|
46
|
+
mode,
|
|
47
|
+
presentationStyle,
|
|
48
|
+
value: valueProp,
|
|
49
|
+
defaultValue,
|
|
50
|
+
onChange,
|
|
51
|
+
onCancel,
|
|
52
|
+
onError,
|
|
53
|
+
children,
|
|
54
|
+
...rest
|
|
55
|
+
}: Props) => {
|
|
56
|
+
const [value, onValueChange] = useControlledValue<
|
|
57
|
+
DocumentResult | DocumentResult[] | undefined
|
|
58
|
+
>({
|
|
59
|
+
value: valueProp,
|
|
60
|
+
defaultValue,
|
|
61
|
+
onChange,
|
|
62
|
+
});
|
|
66
63
|
|
|
67
64
|
const { openFilePicker } = useFilePicker({
|
|
68
65
|
type,
|
|
@@ -74,60 +71,34 @@ const FilePicker = (
|
|
|
74
71
|
onError,
|
|
75
72
|
});
|
|
76
73
|
|
|
77
|
-
const
|
|
78
|
-
(
|
|
79
|
-
if (Array.isArray(response)) {
|
|
80
|
-
if (response.length > 1) {
|
|
81
|
-
setDisplayText(`${response.length} file${response.length > 1 ? 's' : ''}`);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
74
|
+
const displayText = useMemo(() => {
|
|
75
|
+
if (!value) return '';
|
|
84
76
|
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
if (Array.isArray(value)) {
|
|
78
|
+
if (value.length > 1) {
|
|
79
|
+
return `${value.length} files`;
|
|
87
80
|
}
|
|
81
|
+
return value[0]?.name || '';
|
|
82
|
+
}
|
|
88
83
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
[],
|
|
92
|
-
);
|
|
84
|
+
return value.name || '';
|
|
85
|
+
}, [value]);
|
|
93
86
|
|
|
94
87
|
const onPress = useCallback(() => {
|
|
95
88
|
openFilePicker(response => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
onChange?.(response);
|
|
89
|
+
onValueChange(response);
|
|
99
90
|
});
|
|
100
|
-
}, [
|
|
101
|
-
|
|
102
|
-
const rightElement = useMemo(() => {
|
|
103
|
-
if (!loading) {
|
|
104
|
-
return (
|
|
105
|
-
<>
|
|
106
|
-
{rightProp || (
|
|
107
|
-
<IconButton type="material-community" name="upload" onPress={onPress} />
|
|
108
|
-
)}
|
|
109
|
-
</>
|
|
110
|
-
);
|
|
111
|
-
} else {
|
|
112
|
-
return <>{progressIndicator || <ActivityIndicator />}</>;
|
|
113
|
-
}
|
|
114
|
-
}, [loading, onPress, progressIndicator, rightProp]);
|
|
115
|
-
|
|
116
|
-
// if the value changes, we only want file name or the length of the array to display the text
|
|
117
|
-
useEffect(() => {
|
|
118
|
-
onSetInputValue(value);
|
|
119
|
-
}, [onSetInputValue, value]);
|
|
91
|
+
}, [onValueChange, openFilePicker]);
|
|
120
92
|
|
|
121
93
|
return (
|
|
122
|
-
<TextInput
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
/>
|
|
94
|
+
<TextInput value={displayText} {...rest} editable={false} ref={ref}>
|
|
95
|
+
<TextInput.Label>Choose file</TextInput.Label>
|
|
96
|
+
<TextInput.Right>
|
|
97
|
+
<IconButton type="material-community" name="upload" onPress={onPress} />
|
|
98
|
+
</TextInput.Right>
|
|
99
|
+
{children}
|
|
100
|
+
</TextInput>
|
|
130
101
|
);
|
|
131
102
|
};
|
|
132
103
|
|
|
133
|
-
export default memo(
|
|
104
|
+
export default memo(FilePicker);
|
|
@@ -24,41 +24,6 @@ export type Props = TextProps & {
|
|
|
24
24
|
testID?: string;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
/**
|
|
28
|
-
* Helper text is used in conjuction with input elements to provide additional hints for the user.
|
|
29
|
-
*
|
|
30
|
-
* <div class="screenshots">
|
|
31
|
-
* <img class="small" src="screenshots/helper-text.gif" />
|
|
32
|
-
* </div>
|
|
33
|
-
*
|
|
34
|
-
* ## Usage
|
|
35
|
-
* ```js
|
|
36
|
-
* import * as React from 'react';
|
|
37
|
-
* import { View } from 'react-native';
|
|
38
|
-
* import { HelperText, TextInput } from 'react-native-paper';
|
|
39
|
-
*
|
|
40
|
-
* const MyComponent = () => {
|
|
41
|
-
* const [text, setText] = React.useState('');
|
|
42
|
-
*
|
|
43
|
-
* const onChangeText = text => setText(text);
|
|
44
|
-
*
|
|
45
|
-
* const hasErrors = () => {
|
|
46
|
-
* return !text.includes('@');
|
|
47
|
-
* };
|
|
48
|
-
*
|
|
49
|
-
* return (
|
|
50
|
-
* <View>
|
|
51
|
-
* <TextInput label="Email" value={text} onChangeText={onChangeText} />
|
|
52
|
-
* <HelperText variant="error" visible={hasErrors()}>
|
|
53
|
-
* Email address is invalid!
|
|
54
|
-
* </HelperText>
|
|
55
|
-
* </View>
|
|
56
|
-
* );
|
|
57
|
-
* };
|
|
58
|
-
*
|
|
59
|
-
* export default MyComponent;
|
|
60
|
-
* ```
|
|
61
|
-
*/
|
|
62
27
|
const HelperText = ({
|
|
63
28
|
style: styleProp,
|
|
64
29
|
variant = 'info',
|