@core_super_app/ui 0.0.1

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.
Files changed (64) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +37 -0
  3. package/Ui.podspec +20 -0
  4. package/android/build.gradle +67 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/java/com/core/ui/UiModule.kt +15 -0
  7. package/android/src/main/java/com/core/ui/UiPackage.kt +31 -0
  8. package/ios/Ui.h +5 -0
  9. package/ios/Ui.mm +21 -0
  10. package/lib/module/assets/images/icons/remove.png +0 -0
  11. package/lib/module/components/BaseView.js +45 -0
  12. package/lib/module/components/BaseView.js.map +1 -0
  13. package/lib/module/components/BasicButton.js +57 -0
  14. package/lib/module/components/BasicButton.js.map +1 -0
  15. package/lib/module/components/Header.js +140 -0
  16. package/lib/module/components/Header.js.map +1 -0
  17. package/lib/module/components/LoadingOverlay.js +32 -0
  18. package/lib/module/components/LoadingOverlay.js.map +1 -0
  19. package/lib/module/components/TextWrapper.js +34 -0
  20. package/lib/module/components/TextWrapper.js.map +1 -0
  21. package/lib/module/components/index.js +9 -0
  22. package/lib/module/components/index.js.map +1 -0
  23. package/lib/module/components/input/BasicInput.js +237 -0
  24. package/lib/module/components/input/BasicInput.js.map +1 -0
  25. package/lib/module/components/input/index.js +4 -0
  26. package/lib/module/components/input/index.js.map +1 -0
  27. package/lib/module/constants/image.js +6 -0
  28. package/lib/module/constants/image.js.map +1 -0
  29. package/lib/module/index.js +5 -0
  30. package/lib/module/index.js.map +1 -0
  31. package/lib/module/package.json +1 -0
  32. package/lib/typescript/package.json +1 -0
  33. package/lib/typescript/src/components/BaseView.d.ts +11 -0
  34. package/lib/typescript/src/components/BaseView.d.ts.map +1 -0
  35. package/lib/typescript/src/components/BasicButton.d.ts +16 -0
  36. package/lib/typescript/src/components/BasicButton.d.ts.map +1 -0
  37. package/lib/typescript/src/components/Header.d.ts +18 -0
  38. package/lib/typescript/src/components/Header.d.ts.map +1 -0
  39. package/lib/typescript/src/components/LoadingOverlay.d.ts +7 -0
  40. package/lib/typescript/src/components/LoadingOverlay.d.ts.map +1 -0
  41. package/lib/typescript/src/components/TextWrapper.d.ts +14 -0
  42. package/lib/typescript/src/components/TextWrapper.d.ts.map +1 -0
  43. package/lib/typescript/src/components/index.d.ts +7 -0
  44. package/lib/typescript/src/components/index.d.ts.map +1 -0
  45. package/lib/typescript/src/components/input/BasicInput.d.ts +49 -0
  46. package/lib/typescript/src/components/input/BasicInput.d.ts.map +1 -0
  47. package/lib/typescript/src/components/input/index.d.ts +2 -0
  48. package/lib/typescript/src/components/input/index.d.ts.map +1 -0
  49. package/lib/typescript/src/constants/image.d.ts +3 -0
  50. package/lib/typescript/src/constants/image.d.ts.map +1 -0
  51. package/lib/typescript/src/index.d.ts +3 -0
  52. package/lib/typescript/src/index.d.ts.map +1 -0
  53. package/package.json +170 -0
  54. package/src/assets/images/icons/remove.png +0 -0
  55. package/src/components/BaseView.tsx +56 -0
  56. package/src/components/BasicButton.tsx +70 -0
  57. package/src/components/Header.tsx +171 -0
  58. package/src/components/LoadingOverlay.tsx +32 -0
  59. package/src/components/TextWrapper.tsx +49 -0
  60. package/src/components/index.ts +6 -0
  61. package/src/components/input/BasicInput.tsx +360 -0
  62. package/src/components/input/index.ts +1 -0
  63. package/src/constants/image.ts +5 -0
  64. package/src/index.tsx +2 -0
@@ -0,0 +1,360 @@
1
+ import {
2
+ useState,
3
+ useRef,
4
+ useEffect,
5
+ forwardRef,
6
+ useImperativeHandle,
7
+ type JSX,
8
+ type ComponentRef,
9
+ } from 'react';
10
+ import {
11
+ View,
12
+ StyleSheet,
13
+ TouchableOpacity,
14
+ TextInput,
15
+ Pressable,
16
+ Image,
17
+ } from 'react-native';
18
+ import Animated, {
19
+ useAnimatedStyle,
20
+ withTiming,
21
+ Easing,
22
+ useSharedValue,
23
+ } from 'react-native-reanimated';
24
+ import TextWrapper from '../TextWrapper';
25
+ import type {
26
+ BlurEvent,
27
+ FocusEvent,
28
+ TextInputEndEditingEvent,
29
+ KeyboardTypeOptions,
30
+ DimensionValue,
31
+ SubmitBehavior,
32
+ TextInputProps,
33
+ ColorValue,
34
+ StyleProp,
35
+ ViewStyle,
36
+ TextStyle,
37
+ } from 'react-native';
38
+ import { Icon } from '../../constants/image';
39
+ import { scaleFont, scaleHeight, scaleWidth } from '@core_super_app/utils/dimension';
40
+
41
+ type dynamicLabelInputProps = {
42
+ containerStyle?: StyleProp<ViewStyle>;
43
+ renderLeftIcon?: JSX.Element;
44
+ label?: string;
45
+ value: string;
46
+ uniqueIdForBasicInput?: string;
47
+ isFocus?: boolean;
48
+ onChange?: (text: string) => void;
49
+ onSubmitEditing?: ((e: TextInputEndEditingEvent) => void) | undefined;
50
+ onBlur?: ((e: BlurEvent) => void) | undefined;
51
+ onFocus?: ((e: FocusEvent) => void) | undefined;
52
+ showClearButton?: boolean;
53
+ placeholder?: string;
54
+ contextMenuHidden?: boolean;
55
+ readOnly?: boolean;
56
+ renderRightIcon?: JSX.Element;
57
+ onPressRightIcon?: () => void;
58
+ onInputPress?: () => void;
59
+ labelStyle?: StyleProp<TextStyle>;
60
+ onEndEditing?: (e: TextInputEndEditingEvent) => void;
61
+ placeholderTextColor?: ColorValue;
62
+ isError?: boolean;
63
+ maxLength?: number;
64
+ submitBehavior?: SubmitBehavior;
65
+ required?: boolean;
66
+ disabled?: boolean;
67
+ showLimitCount?: boolean;
68
+ inputStyle?: StyleProp<TextStyle>;
69
+ width?: DimensionValue;
70
+ autoComplete?: 'off';
71
+ autoCorrect?: boolean;
72
+ importantForAutofill?: 'no';
73
+ keyboardType?: KeyboardTypeOptions;
74
+ height?: number;
75
+ labelTopPosition?: number;
76
+ labelFocusColor?: string;
77
+ replaceRegex?: RegExp;
78
+ accessibilityLabel?: string;
79
+ inputProps?: TextInputProps;
80
+ };
81
+
82
+ type labellPositionDef = {
83
+ topBlur: number;
84
+ };
85
+
86
+ type inputRefDef = {
87
+ focus: () => void;
88
+ blur: () => void;
89
+ };
90
+
91
+ const labelAniConfig = {
92
+ duration: 100,
93
+ easing: Easing.linear,
94
+ };
95
+
96
+ const BasicInput = forwardRef<inputRefDef, dynamicLabelInputProps>(
97
+ (props, ref) => {
98
+ const {
99
+ width = '100%',
100
+ containerStyle,
101
+ renderLeftIcon,
102
+ label,
103
+ inputProps,
104
+ value,
105
+ isFocus,
106
+ onChange,
107
+ onSubmitEditing,
108
+ onBlur,
109
+ onFocus,
110
+ showClearButton,
111
+ placeholder,
112
+ readOnly = false,
113
+ renderRightIcon,
114
+ onPressRightIcon,
115
+ onInputPress,
116
+ labelStyle,
117
+ onEndEditing,
118
+ placeholderTextColor = '#868F97',
119
+ isError = false,
120
+ maxLength,
121
+ required,
122
+ disabled,
123
+ showLimitCount = false,
124
+ inputStyle,
125
+ autoComplete = 'off',
126
+ autoCorrect = false,
127
+ importantForAutofill = 'no',
128
+ height = scaleHeight(6.5),
129
+ labelTopPosition = 0,
130
+ labelFocusColor,
131
+ replaceRegex,
132
+ accessibilityLabel = "input",
133
+ uniqueIdForBasicInput
134
+ } = props;
135
+
136
+ const [currChar, setCurrChar] = useState<number>(0);
137
+ const [focus, setFocus] = useState<boolean>(isFocus || false);
138
+ const calculatedValues = useSharedValue<labellPositionDef>({
139
+ topBlur: (height - scaleHeight(1.8)) / 2 - scaleFont(16) / 2,
140
+ });
141
+
142
+ useEffect(() => {
143
+ if (showLimitCount) {
144
+ setCurrChar(value?.length || 0);
145
+ }
146
+ }, [value, showLimitCount]);
147
+
148
+ useImperativeHandle(
149
+ ref,
150
+ () => ({
151
+ focus: () => {
152
+ setFocus(true);
153
+ inputRef.current?.focus();
154
+ },
155
+ blur: () => {
156
+ setFocus(false);
157
+ inputRef.current?.blur();
158
+ },
159
+ }),
160
+ [],
161
+ );
162
+
163
+ const inputRef = useRef<ComponentRef<typeof TextInput>>(null);
164
+
165
+ const labelAni = useAnimatedStyle(() => {
166
+ return {
167
+ top: withTiming(
168
+ focus || value || (label && placeholder)
169
+ ? labelTopPosition
170
+ : calculatedValues!.value.topBlur,
171
+ labelAniConfig,
172
+ ),
173
+ color:
174
+ focus || value || (label && placeholder)
175
+ ? labelFocusColor || '#212B36'
176
+ : '#868F97',
177
+ };
178
+ }, [value, focus, label, placeholder, labelFocusColor]);
179
+
180
+ const handleBlur = (e: BlurEvent) => {
181
+ setFocus(false);
182
+ if (onBlur) {
183
+ onBlur(e);
184
+ }
185
+ };
186
+
187
+ const handleFocus = (e: FocusEvent) => {
188
+ setFocus(true);
189
+ if (onFocus) {
190
+ onFocus(e);
191
+ }
192
+ };
193
+
194
+ const handleChangeText = (text: string) => {
195
+ let newText = text;
196
+ if (newText && replaceRegex) {
197
+ newText = newText.replace(replaceRegex, '');
198
+ }
199
+ if (onChange) {
200
+ onChange(newText);
201
+ }
202
+ if (showLimitCount) {
203
+ setCurrChar(newText?.length);
204
+ }
205
+ };
206
+
207
+ return (
208
+ <Pressable
209
+ style={[
210
+ styles.inputContainer,
211
+ containerStyle,
212
+ isError && styles.borderError,
213
+ disabled && styles.containerDisabled,
214
+ { height: height, width },
215
+ ]}
216
+ disabled={!onInputPress || disabled}
217
+ onPress={onInputPress}
218
+ >
219
+ {renderLeftIcon && (
220
+ <View style={styles.iconContainerLeft}>{renderLeftIcon}</View>
221
+ )}
222
+ <Pressable
223
+ style={styles.innerInputContainer}
224
+ onPress={() => inputRef.current?.focus()}
225
+ disabled={(!label || readOnly) && !!onInputPress}
226
+ >
227
+ <TextInput
228
+ accessible
229
+ accessibilityLabel={accessibilityLabel}
230
+ testID={uniqueIdForBasicInput}
231
+ autoComplete={autoComplete}
232
+ autoCorrect={autoCorrect}
233
+ importantForAutofill={importantForAutofill}
234
+ allowFontScaling={false}
235
+ editable={!readOnly}
236
+ ref={inputRef}
237
+ value={value}
238
+ style={[
239
+ styles.inputStyleCommon,
240
+ inputStyle,
241
+ label && styles.inputShrink,
242
+ ]}
243
+ onChangeText={handleChangeText}
244
+ onFocus={handleFocus}
245
+ onBlur={handleBlur}
246
+ onSubmitEditing={onSubmitEditing}
247
+ readOnly={readOnly}
248
+ onEndEditing={onEndEditing}
249
+ onPress={() => {
250
+ if (readOnly && onInputPress) {
251
+ onInputPress();
252
+ }
253
+ }}
254
+ placeholderTextColor={placeholderTextColor}
255
+ {...inputProps}
256
+ />
257
+ {label && (
258
+ <Animated.Text
259
+ numberOfLines={1}
260
+ ellipsizeMode="tail"
261
+ allowFontScaling={false}
262
+ style={[styles.label, labelAni, labelStyle]}
263
+ >
264
+ {label}
265
+ {required && (
266
+ <TextWrapper style={styles.requireMark}>{' *'}</TextWrapper>
267
+ )}
268
+ {showLimitCount && value && (
269
+ <TextWrapper>{` (${currChar}/${maxLength})`}</TextWrapper>
270
+ )}
271
+ </Animated.Text>
272
+ )}
273
+ </Pressable>
274
+ {showClearButton && value && (
275
+ <TouchableOpacity
276
+ style={styles.iconContainerRight}
277
+ onPress={() => handleChangeText('')}
278
+ disabled={!value}
279
+ >
280
+ <Image
281
+ style={styles.iconRemove}
282
+ source={Icon.remove}
283
+ resizeMode="contain"
284
+ tintColor="#A1AAB2"
285
+ />
286
+ </TouchableOpacity>
287
+ )}
288
+ {renderRightIcon && (
289
+ <TouchableOpacity
290
+ style={styles.iconContainerRight}
291
+ onPress={onPressRightIcon}
292
+ disabled={!!onInputPress}
293
+ >
294
+ {renderRightIcon}
295
+ </TouchableOpacity>
296
+ )}
297
+ </Pressable>
298
+ );
299
+ },
300
+ );
301
+
302
+ const styles = StyleSheet.create({
303
+ inputContainer: {
304
+ borderRadius: 12,
305
+ backgroundColor: 'white',
306
+ paddingHorizontal: scaleWidth(4.3),
307
+ paddingVertical: scaleHeight(0.9),
308
+ flexDirection: 'row',
309
+ alignItems: 'center',
310
+ marginVertical: scaleHeight(1),
311
+ borderWidth: 1,
312
+ borderColor: '#DDE4EE',
313
+ },
314
+ iconContainerLeft: {
315
+ height: scaleHeight(6),
316
+ justifyContent: 'center',
317
+ alignItems: 'center',
318
+ marginLeft: scaleWidth(12),
319
+ },
320
+ iconContainerRight: {
321
+ height: scaleHeight(6),
322
+ justifyContent: 'center',
323
+ alignItems: 'center',
324
+ marginLeft: scaleWidth(12),
325
+ },
326
+ innerInputContainer: {
327
+ flex: 1,
328
+ height: '100%',
329
+ justifyContent: 'flex-end',
330
+ position: 'relative',
331
+ },
332
+ inputStyleCommon: {
333
+ width: '100%',
334
+ height: '100%',
335
+ color: '#ffffff',
336
+ padding: 0,
337
+ fontSize: scaleFont(14),
338
+ },
339
+ label: {
340
+ color: '#9DA4AE',
341
+ position: 'absolute',
342
+ left: 0,
343
+ fontSize: scaleFont(12),
344
+ lineHeight: scaleFont(16),
345
+ },
346
+ containerDisabled: {
347
+ borderColor: '#DAE0E7',
348
+ borderWidth: 0,
349
+ backgroundColor: '#DAE0E7',
350
+ opacity: 0.9,
351
+ },
352
+ iconRemove: { width: scaleFont(16), height: scaleFont(16) },
353
+ borderError: { borderColor: '#DA2128' },
354
+ requireMark: {
355
+ color: '#DA2128',
356
+ },
357
+ inputShrink: { height: '54%' }
358
+ });
359
+
360
+ export default BasicInput;
@@ -0,0 +1 @@
1
+ export * from "./BasicInput";
@@ -0,0 +1,5 @@
1
+ import type { ImageSource } from "react-native";
2
+
3
+ export const Icon: Record<string, ImageSource> = {
4
+ remove: require('../assets/images/icons/remove.png')
5
+ }
package/src/index.tsx ADDED
@@ -0,0 +1,2 @@
1
+ export * from './components'
2
+ export * as ImageSrc from './constants/image'