aport-tools 4.5.2 → 4.6.0
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/package.json +13 -28
- package/src/cards/Card.tsx +129 -0
- package/src/cards/index.ts +1 -0
- package/src/components/Button.tsx +180 -0
- package/src/fonts/Text.tsx +137 -0
- package/{dist/fonts/index.d.ts → src/fonts/index.ts} +1 -0
- package/src/forms/ErrorList.tsx +47 -0
- package/src/forms/FORMDOC.md +87 -0
- package/{dist/forms/Form.d.ts → src/forms/Form.tsx} +2 -0
- package/src/forms/FormContext.tsx +248 -0
- package/src/forms/Input.tsx +174 -0
- package/src/forms/InputAttach.tsx +184 -0
- package/src/forms/InputCheck.tsx +169 -0
- package/src/forms/InputList.tsx +304 -0
- package/src/forms/Label.tsx +26 -0
- package/src/forms/Stepper.tsx +289 -0
- package/src/forms/TextArea.tsx +91 -0
- package/{dist/forms/index.d.ts → src/forms/index.ts} +4 -2
- package/src/index.ts +6 -0
- package/dist/cards/Card.d.ts +0 -57
- package/dist/cards/index.d.ts +0 -1
- package/dist/components/Button.d.ts +0 -52
- package/dist/fonts/Text.d.ts +0 -64
- package/dist/forms/ErrorList.d.ts +0 -6
- package/dist/forms/FormContext.d.ts +0 -132
- package/dist/forms/Input.d.ts +0 -43
- package/dist/forms/InputAttach.d.ts +0 -16
- package/dist/forms/InputCheck.d.ts +0 -19
- package/dist/forms/InputList.d.ts +0 -93
- package/dist/forms/Label.d.ts +0 -7
- package/dist/forms/Stepper.d.ts +0 -54
- package/dist/forms/TextArea.d.ts +0 -13
- package/dist/index.d.ts +0 -4
- package/dist/index.esm.js +0 -1493
- package/dist/index.esm.js.map +0 -1
- package/dist/index.js +0 -1526
- package/dist/index.js.map +0 -1
- /package/{dist/buttons/index.d.ts → src/buttons/index.ts} +0 -0
@@ -0,0 +1,169 @@
|
|
1
|
+
import React, { useContext, useEffect, useRef, useState } from "react";
|
2
|
+
import { useFormContext } from "../forms/FormContext";
|
3
|
+
import { Image, StyleSheet, FlatList } from "react-native";
|
4
|
+
import { ThemeContext } from "aport-themes";
|
5
|
+
import { Text } from "../fonts";
|
6
|
+
import { Card } from "../cards";
|
7
|
+
import ErrorList from "./ErrorList";
|
8
|
+
|
9
|
+
interface InputOption {
|
10
|
+
id: string;
|
11
|
+
label?: string;
|
12
|
+
icon?: string;
|
13
|
+
value: string;
|
14
|
+
}
|
15
|
+
|
16
|
+
interface InputCheckProps {
|
17
|
+
name: string;
|
18
|
+
options: InputOption[]; // Use the shared interface
|
19
|
+
multi?: boolean; // Allows multiple selection (checkbox behavior)
|
20
|
+
max?: number; // Maximum number of selections
|
21
|
+
rowAmount?: number; // Number of items per row
|
22
|
+
iconPosition?: "row" | "column"; // Icon and label layout
|
23
|
+
disabled?: boolean; // Disable the input
|
24
|
+
firstValue?: InputOption[]; // Use the shared interface
|
25
|
+
}
|
26
|
+
|
27
|
+
const InputCheck: React.FC<InputCheckProps> = ({
|
28
|
+
name,
|
29
|
+
options,
|
30
|
+
multi = false,
|
31
|
+
max,
|
32
|
+
rowAmount = 3,
|
33
|
+
firstValue,
|
34
|
+
iconPosition = "row",
|
35
|
+
disabled = false,
|
36
|
+
}) => {
|
37
|
+
const { formValues, setFormValue, errors: formErrors } = useFormContext();
|
38
|
+
const [selectedValues, setSelectedValues] = useState<InputOption[]>([]);
|
39
|
+
const { theme } = useContext(ThemeContext);
|
40
|
+
const { colors } = theme;
|
41
|
+
const isFirstRender = useRef(true);
|
42
|
+
|
43
|
+
// Initialize selectedValues on first render if firstValue is provided
|
44
|
+
useEffect(() => {
|
45
|
+
if (isFirstRender.current && firstValue) {
|
46
|
+
const initialSelectedValues = options.filter((option) =>
|
47
|
+
firstValue.some((fv) => fv.value === option.value)
|
48
|
+
);
|
49
|
+
|
50
|
+
setSelectedValues(initialSelectedValues);
|
51
|
+
setFormValue(name, initialSelectedValues, initialSelectedValues); // Update form context
|
52
|
+
isFirstRender.current = false; // Prevent subsequent updates
|
53
|
+
}
|
54
|
+
}, [firstValue, name, options, setFormValue]);
|
55
|
+
|
56
|
+
const handleSelect = (id: string, value: string) => {
|
57
|
+
if (disabled) return;
|
58
|
+
|
59
|
+
let updatedSelection;
|
60
|
+
if (multi) {
|
61
|
+
const alreadySelected = selectedValues.find((item) => item.id === id);
|
62
|
+
if (alreadySelected) {
|
63
|
+
updatedSelection = selectedValues.filter((item) => item.id !== id);
|
64
|
+
} else {
|
65
|
+
if (max && selectedValues.length >= max) return; // Prevent selection beyond max
|
66
|
+
updatedSelection = [...selectedValues, { id, value }];
|
67
|
+
}
|
68
|
+
} else {
|
69
|
+
updatedSelection = [{ id, value }];
|
70
|
+
}
|
71
|
+
|
72
|
+
setSelectedValues(updatedSelection);
|
73
|
+
setFormValue(name, updatedSelection);
|
74
|
+
};
|
75
|
+
|
76
|
+
const renderItem = ({ item }: { item: InputOption }) => {
|
77
|
+
const isSelected = selectedValues.some(
|
78
|
+
(selected) => selected.id === item.id.toString()
|
79
|
+
);
|
80
|
+
|
81
|
+
return (
|
82
|
+
<Card
|
83
|
+
pressable
|
84
|
+
onPress={() => handleSelect(item.id.toString(), item.value)}
|
85
|
+
style={[
|
86
|
+
styles.card,
|
87
|
+
isSelected && { backgroundColor: colors.primary.hex }, // Replace with colors.primary.hex if available
|
88
|
+
disabled && styles.cardDisabled,
|
89
|
+
]}
|
90
|
+
>
|
91
|
+
{item.icon && (
|
92
|
+
<Image
|
93
|
+
source={{ uri: item.icon }}
|
94
|
+
style={[
|
95
|
+
styles.icon,
|
96
|
+
iconPosition === "column" && styles.iconColumn,
|
97
|
+
]}
|
98
|
+
/>
|
99
|
+
)}
|
100
|
+
{item.label && (
|
101
|
+
<Text
|
102
|
+
style={[
|
103
|
+
styles.label,
|
104
|
+
{ color: isSelected ? colors.textButton.hex : colors.text.hex },
|
105
|
+
]}
|
106
|
+
>
|
107
|
+
{item.label}
|
108
|
+
</Text>
|
109
|
+
)}
|
110
|
+
</Card>
|
111
|
+
);
|
112
|
+
};
|
113
|
+
|
114
|
+
return (
|
115
|
+
<>
|
116
|
+
{/* Display the name as a title */}
|
117
|
+
<Text style={styles.title}>{name}</Text>
|
118
|
+
|
119
|
+
<FlatList
|
120
|
+
data={options}
|
121
|
+
renderItem={renderItem}
|
122
|
+
keyExtractor={(item) => item.id}
|
123
|
+
numColumns={rowAmount}
|
124
|
+
columnWrapperStyle={rowAmount > 1 ? styles.row : undefined}
|
125
|
+
scrollEnabled={false}
|
126
|
+
/>
|
127
|
+
{formErrors[name] && formErrors[name].length > 0 && (
|
128
|
+
<ErrorList errors={formErrors[name]} />
|
129
|
+
)}
|
130
|
+
</>
|
131
|
+
);
|
132
|
+
};
|
133
|
+
|
134
|
+
export default InputCheck;
|
135
|
+
|
136
|
+
const styles = StyleSheet.create({
|
137
|
+
card: {
|
138
|
+
flex: 1,
|
139
|
+
margin: 5,
|
140
|
+
padding: 10,
|
141
|
+
borderWidth: 1,
|
142
|
+
borderColor: "#ccc",
|
143
|
+
borderRadius: 8,
|
144
|
+
alignItems: "center",
|
145
|
+
justifyContent: "center",
|
146
|
+
},
|
147
|
+
title: {
|
148
|
+
marginBottom: 4,
|
149
|
+
fontSize: 14,
|
150
|
+
},
|
151
|
+
cardDisabled: {
|
152
|
+
opacity: 0.5,
|
153
|
+
},
|
154
|
+
icon: {
|
155
|
+
width: 40,
|
156
|
+
height: 40,
|
157
|
+
marginBottom: 5,
|
158
|
+
},
|
159
|
+
iconColumn: {
|
160
|
+
marginBottom: 10,
|
161
|
+
},
|
162
|
+
label: {
|
163
|
+
fontSize: 14,
|
164
|
+
textAlign: "center",
|
165
|
+
},
|
166
|
+
row: {
|
167
|
+
justifyContent: "space-between",
|
168
|
+
},
|
169
|
+
});
|
@@ -0,0 +1,304 @@
|
|
1
|
+
import React, { useState, useCallback, useContext, useEffect, useMemo } from 'react';
|
2
|
+
import { View, Text, TouchableOpacity, FlatList, StyleSheet, Modal, Pressable, Keyboard } from 'react-native';
|
3
|
+
import { ThemeContext } from "aport-themes";
|
4
|
+
import { useFormContext } from '../forms/FormContext';
|
5
|
+
import ErrorList from "./ErrorList";
|
6
|
+
|
7
|
+
interface Option {
|
8
|
+
id: number | string;
|
9
|
+
label: string;
|
10
|
+
value: any;
|
11
|
+
}
|
12
|
+
|
13
|
+
interface InputListProps {
|
14
|
+
name: string;
|
15
|
+
/**
|
16
|
+
* Placeholder text displayed in the input box when no selection is made.
|
17
|
+
* @type {string}
|
18
|
+
* @default "Choose value/s"
|
19
|
+
*/
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Optional first value if you want to set values with fetch or dont have empty inputs.
|
23
|
+
*/
|
24
|
+
firstValue?: any[]; // Optional prop for the initial value
|
25
|
+
|
26
|
+
placeholder?: string;
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Custom styles for the component.
|
30
|
+
* @type {object}
|
31
|
+
*/
|
32
|
+
style?: object;
|
33
|
+
|
34
|
+
/**
|
35
|
+
* Array of options to display in the dropdown. Each option should have an id, label, and value.
|
36
|
+
* @type {Option[]}
|
37
|
+
*/
|
38
|
+
options: Option[];
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Enables multi-selection mode when true. If enabled, users can select multiple values.
|
42
|
+
* @type {boolean}
|
43
|
+
* @default false
|
44
|
+
*/
|
45
|
+
multi?: boolean;
|
46
|
+
|
47
|
+
/**
|
48
|
+
* Disables the dropdown input when true.
|
49
|
+
* @type {boolean}
|
50
|
+
* @default false
|
51
|
+
*/
|
52
|
+
disabled?: boolean;
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Key used to sort options in the dropdown (e.g., by 'id', 'label').
|
56
|
+
* @type {keyof Option}
|
57
|
+
*/
|
58
|
+
sortBy?: keyof Option;
|
59
|
+
|
60
|
+
/**
|
61
|
+
* If true, displays a separator line between each option.
|
62
|
+
* @type {boolean}
|
63
|
+
* @default false
|
64
|
+
*/
|
65
|
+
separator?: boolean;
|
66
|
+
|
67
|
+
/**
|
68
|
+
* Closes the dropdown if the user scrolls the list.
|
69
|
+
* @type {boolean}
|
70
|
+
* @default false
|
71
|
+
*/
|
72
|
+
closeOnScroll?: boolean;
|
73
|
+
|
74
|
+
/**
|
75
|
+
* Closes the dropdown after selecting an item if true (only relevant when multi is false).
|
76
|
+
* @type {boolean}
|
77
|
+
* @default true
|
78
|
+
*/
|
79
|
+
closeOnSelect?: boolean;
|
80
|
+
|
81
|
+
/**
|
82
|
+
* Limits the maximum number of items that can be selected when multi is true.
|
83
|
+
* Once the limit is reached, the dropdown closes, and no further selections can be made until
|
84
|
+
* an item is deselected.
|
85
|
+
* @type {number}
|
86
|
+
*/
|
87
|
+
maxSelection?: number;
|
88
|
+
|
89
|
+
/**
|
90
|
+
* Callback function called when the selection changes. Useful for conditional field enabling.
|
91
|
+
* @param {Option | Option[] | null} selection - The updated selection.
|
92
|
+
*/
|
93
|
+
onChange?: (selection: Option | Option[] | null) => void;
|
94
|
+
}
|
95
|
+
|
96
|
+
/**
|
97
|
+
* InputList component - A custom dropdown list component for React Native with multi-selection support,
|
98
|
+
* customizable styling, sorting, and configurable close behavior on selection or scrolling.
|
99
|
+
*
|
100
|
+
* @param {string} placeholder - Placeholder text for the input.
|
101
|
+
* @param {object} style - Custom styles for the component.
|
102
|
+
* @param {Option[]} options - Array of options to display in the dropdown.
|
103
|
+
* @param {boolean} multi - Enables multi-selection mode.
|
104
|
+
* @param {boolean} disabled - Disables the dropdown input.
|
105
|
+
* @param {keyof Option} sortBy - Key to sort options by (e.g., 'id').
|
106
|
+
* @param {boolean} separator - If true, adds a separator line between options.
|
107
|
+
* @param {boolean} closeOnScroll - Closes the dropdown if the user scrolls the list.
|
108
|
+
* @param {boolean} closeOnSelect - Closes the dropdown on selection in single-select mode.
|
109
|
+
* @param {number} maxSelection - Maximum number of items selectable in multi-select mode.
|
110
|
+
*/
|
111
|
+
export const InputList: React.FC<InputListProps> = ({
|
112
|
+
name,
|
113
|
+
placeholder = "Choose value/s",
|
114
|
+
style,
|
115
|
+
options,
|
116
|
+
multi = false,
|
117
|
+
disabled = false,
|
118
|
+
sortBy,
|
119
|
+
firstValue = [],
|
120
|
+
separator = false,
|
121
|
+
closeOnScroll = false,
|
122
|
+
closeOnSelect = true,
|
123
|
+
maxSelection,
|
124
|
+
onChange,
|
125
|
+
}) => {
|
126
|
+
const { formValues, setFormValue, errors: formErrors } = useFormContext();
|
127
|
+
const [isDropdownVisible, setIsDropdownVisible] = useState(false);
|
128
|
+
|
129
|
+
// Memoize sorted options for performance
|
130
|
+
const sortedOptions = useMemo(() => {
|
131
|
+
return sortBy
|
132
|
+
? [...options].sort((a, b) => (a[sortBy] > b[sortBy] ? 1 : -1))
|
133
|
+
: options;
|
134
|
+
}, [options, sortBy]);
|
135
|
+
const { theme } = useContext(ThemeContext);
|
136
|
+
const { colors } = theme;
|
137
|
+
|
138
|
+
// Initialize selected options based on firstValue
|
139
|
+
// Filter initial selections from options based on `firstValue`
|
140
|
+
const initialSelections = useMemo(
|
141
|
+
() => options.filter((opt) => firstValue.includes(opt.value)),
|
142
|
+
[options, firstValue]
|
143
|
+
);
|
144
|
+
// State for selected options
|
145
|
+
const [selectedOptions, setSelectedOptions] = useState(
|
146
|
+
multi ? initialSelections : initialSelections[0] || null
|
147
|
+
);
|
148
|
+
// Update form value when firstValue changes
|
149
|
+
useEffect(() => {
|
150
|
+
if (!firstValue || firstValue.length === 0) return;
|
151
|
+
|
152
|
+
const matchedSelections = options.filter((opt) => firstValue.includes(opt.value));
|
153
|
+
|
154
|
+
if (multi) {
|
155
|
+
setSelectedOptions(matchedSelections);
|
156
|
+
setFormValue(name, matchedSelections, matchedSelections);
|
157
|
+
} else {
|
158
|
+
const singleValue = matchedSelections[0] || null;
|
159
|
+
setSelectedOptions(singleValue);
|
160
|
+
setFormValue(name, singleValue, singleValue);
|
161
|
+
}
|
162
|
+
}, [firstValue, multi]);
|
163
|
+
|
164
|
+
|
165
|
+
// Handle option selection
|
166
|
+
const handleSelectOption = (option: Option) => {
|
167
|
+
|
168
|
+
let updatedSelections;
|
169
|
+
|
170
|
+
if (multi) {
|
171
|
+
const selectedArray = Array.isArray(selectedOptions) ? selectedOptions : [];
|
172
|
+
const alreadySelected = selectedArray.some((opt) => opt.id === option.id);
|
173
|
+
|
174
|
+
updatedSelections = alreadySelected
|
175
|
+
? selectedArray.filter((opt) => opt.id !== option.id)
|
176
|
+
: [...selectedArray, option];
|
177
|
+
|
178
|
+
if (!alreadySelected && maxSelection && updatedSelections.length >= maxSelection) {
|
179
|
+
setIsDropdownVisible(false);
|
180
|
+
}
|
181
|
+
|
182
|
+
setFormValue(name, updatedSelections);
|
183
|
+
} else {
|
184
|
+
updatedSelections = option;
|
185
|
+
setFormValue(name, option);
|
186
|
+
if (closeOnSelect) setIsDropdownVisible(false);
|
187
|
+
}
|
188
|
+
|
189
|
+
setSelectedOptions(updatedSelections);
|
190
|
+
if (onChange) onChange(updatedSelections);
|
191
|
+
};
|
192
|
+
|
193
|
+
const isItemDisabled = (option: Option) => {
|
194
|
+
if (!multi) return false; // Disable check only applies for multi-select
|
195
|
+
|
196
|
+
// Ensure selectedOptions is treated as an array
|
197
|
+
const selectedArray = Array.isArray(selectedOptions) ? selectedOptions : [];
|
198
|
+
return (
|
199
|
+
maxSelection &&
|
200
|
+
selectedArray.length >= maxSelection &&
|
201
|
+
!selectedArray.some((opt) => opt.id === option.id)
|
202
|
+
);
|
203
|
+
};
|
204
|
+
|
205
|
+
const renderSelectedText = () => {
|
206
|
+
if (multi) {
|
207
|
+
// Ensure selectedOptions is treated as an array
|
208
|
+
const selectedArray = Array.isArray(selectedOptions) ? selectedOptions : [];
|
209
|
+
return selectedArray.map((opt) => opt.label).join(', ') || placeholder;
|
210
|
+
}
|
211
|
+
return (selectedOptions as Option)?.label || placeholder;
|
212
|
+
};
|
213
|
+
|
214
|
+
|
215
|
+
const toggleDropdown = () => {
|
216
|
+
if (!disabled) {
|
217
|
+
setIsDropdownVisible(!isDropdownVisible);
|
218
|
+
if (!isDropdownVisible) Keyboard.dismiss();
|
219
|
+
}
|
220
|
+
};
|
221
|
+
|
222
|
+
const handleCloseDropdown = useCallback(() => {
|
223
|
+
if (isDropdownVisible) setIsDropdownVisible(false);
|
224
|
+
}, [isDropdownVisible]);
|
225
|
+
|
226
|
+
/**
|
227
|
+
* Renders selected options as a comma-separated string or the placeholder if none selected.
|
228
|
+
* @returns {string} - The display text for selected options or placeholder.
|
229
|
+
*/
|
230
|
+
|
231
|
+
|
232
|
+
// Conditionally render item as disabled if max selection reached and item is unselected
|
233
|
+
|
234
|
+
|
235
|
+
return (
|
236
|
+
<View style={[styles.container, style]}>
|
237
|
+
<Text style={{color: colors.text.hex,marginBottom: 4,
|
238
|
+
}}>{name}</Text>
|
239
|
+
|
240
|
+
<TouchableOpacity style={[styles.inputContainer,{borderColor: formErrors[name] ? colors.error.hex : "#CCC",}]} onPress={toggleDropdown} disabled={disabled}>
|
241
|
+
<Text style={{color: colors.text.hex}}>{renderSelectedText()}</Text>
|
242
|
+
</TouchableOpacity>
|
243
|
+
|
244
|
+
{/* Display errors only if form has been submitted and there are errors */}
|
245
|
+
{formErrors[name] && formErrors[name].length > 0 && (
|
246
|
+
<ErrorList errors={formErrors[name]} />
|
247
|
+
)}
|
248
|
+
<Modal visible={isDropdownVisible} transparent animationType="fade">
|
249
|
+
<Pressable style={styles.overlay} onPress={handleCloseDropdown} />
|
250
|
+
<View style={[styles.dropdownContainer,{backgroundColor: colors.body.hex,
|
251
|
+
}]}>
|
252
|
+
<FlatList
|
253
|
+
data={sortedOptions}
|
254
|
+
keyExtractor={(item) => item.id.toString()}
|
255
|
+
renderItem={({ item }) => {
|
256
|
+
const isSelected = multi
|
257
|
+
? Array.isArray(selectedOptions) && selectedOptions.some((opt: Option) => opt.id === item.id)
|
258
|
+
: selectedOptions && 'id' in selectedOptions && selectedOptions.id === item.id;
|
259
|
+
|
260
|
+
const isDisabled = isItemDisabled(item);
|
261
|
+
|
262
|
+
return (
|
263
|
+
<TouchableOpacity
|
264
|
+
onPress={() => handleSelectOption(item)}
|
265
|
+
style={[
|
266
|
+
styles.optionItem,
|
267
|
+
isSelected ? {backgroundColor: colors.primary.hex} : {},
|
268
|
+
isDisabled ? {backgroundColor: colors.placeHolder.hex} : {},
|
269
|
+
]}
|
270
|
+
disabled={!!isDisabled} // Ensure disabled prop is a boolean
|
271
|
+
>
|
272
|
+
<Text style={[isSelected ? {color: colors.body.hex}: {color: colors.text.hex}, isDisabled ? styles.disabledText : {}]}>
|
273
|
+
{item.label}
|
274
|
+
</Text>
|
275
|
+
</TouchableOpacity>
|
276
|
+
);
|
277
|
+
}}
|
278
|
+
ItemSeparatorComponent={() => (separator ? <View style={styles.separator} /> : null)}
|
279
|
+
scrollEnabled={!closeOnScroll}
|
280
|
+
/>
|
281
|
+
</View>
|
282
|
+
</Modal>
|
283
|
+
</View>
|
284
|
+
);
|
285
|
+
};
|
286
|
+
|
287
|
+
const styles = StyleSheet.create({
|
288
|
+
container: {marginVertical: 10 },
|
289
|
+
inputContainer: { padding: 12, borderWidth: 1, borderRadius: 5 },
|
290
|
+
dropdownContainer: {
|
291
|
+
position: 'absolute',
|
292
|
+
top: '30%', // Center the dropdown vertically
|
293
|
+
alignSelf: 'center',
|
294
|
+
width: '90%',
|
295
|
+
backgroundColor: '#fff',
|
296
|
+
borderRadius: 8,
|
297
|
+
elevation: 5,
|
298
|
+
paddingVertical: 10,
|
299
|
+
},
|
300
|
+
optionItem: { padding: 12 },
|
301
|
+
disabledText: { color: '#999' },
|
302
|
+
separator: { height: 1, backgroundColor: '#ddd', marginHorizontal: 8 },
|
303
|
+
overlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.3)' },
|
304
|
+
});
|
@@ -0,0 +1,26 @@
|
|
1
|
+
// src/forms/Label.tsx
|
2
|
+
|
3
|
+
import React, { useContext } from 'react';
|
4
|
+
import { StyleSheet } from 'react-native';
|
5
|
+
import { Text } from '../fonts/Text';
|
6
|
+
import { ThemeContext } from 'aport-themes';
|
7
|
+
|
8
|
+
interface LabelProps {
|
9
|
+
text: string;
|
10
|
+
style?: any;
|
11
|
+
}
|
12
|
+
|
13
|
+
const Label: React.FC<LabelProps> = ({ text, style }) => {
|
14
|
+
const { theme } = useContext(ThemeContext);
|
15
|
+
const { colors } = theme;
|
16
|
+
return <Text style={[styles.label, style, { color: colors.text.hex }]}>{text}</Text>;
|
17
|
+
};
|
18
|
+
|
19
|
+
const styles = StyleSheet.create({
|
20
|
+
label: {
|
21
|
+
marginBottom: 4,
|
22
|
+
fontWeight: '500',
|
23
|
+
},
|
24
|
+
});
|
25
|
+
|
26
|
+
export default Label;
|