@momo-kits/foundation 0.92.23 → 0.92.25
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/Application/BottomSheet.tsx +15 -6
- package/Application/BottomTab/BottomTabBar.tsx +2 -2
- package/Application/BottomTab/index.tsx +3 -2
- package/Application/Components.tsx +34 -107
- package/Application/ModalScreen.tsx +2 -2
- package/Application/Navigation.ts +18 -4
- package/Application/StackScreen.tsx +2 -2
- package/Application/index.ts +2 -0
- package/Application/types.ts +6 -16
- package/Application/utils.tsx +18 -64
- package/Button/index.tsx +1 -0
- package/Icon/types.ts +0 -1
- package/Input/InputDropDown.tsx +2 -2
- package/Input/InputMoney.tsx +3 -3
- package/Input/InputOTP.tsx +4 -4
- package/Input/InputSearch.tsx +144 -249
- package/Input/index.tsx +1 -19
- package/Input/styles.ts +3 -10
- package/Layout/FloatingButton.tsx +2 -2
- package/Layout/GridSystem.tsx +1 -1
- package/Layout/ItemList.tsx +3 -2
- package/Layout/Screen.tsx +87 -122
- package/Layout/styles.ts +6 -0
- package/Layout/types.ts +1 -20
- package/Title/index.tsx +6 -9
- package/package.json +1 -1
- package/Input/TextTyping.tsx +0 -113
- package/Layout/AnimatedInputSearch.tsx +0 -66
package/Layout/Screen.tsx
CHANGED
|
@@ -27,12 +27,10 @@ import Navigation from '../Application/Navigation';
|
|
|
27
27
|
import {AnimatedHeader, NavigationOptions} from '../Application/types';
|
|
28
28
|
import {Colors, Spacing, Styles} from '../Consts';
|
|
29
29
|
import {FloatingButton, FloatingButtonProps} from './FloatingButton';
|
|
30
|
+
import {Image} from '../Image';
|
|
30
31
|
import {Card, Section, validateChildren} from './index';
|
|
31
32
|
import styles from './styles';
|
|
32
33
|
import {HeaderType} from './types';
|
|
33
|
-
import AnimatedInputSearch from './AnimatedInputSearch';
|
|
34
|
-
import {InputSearchProps} from '../Input';
|
|
35
|
-
import {HeaderExtendBackground} from '../Application/Components';
|
|
36
34
|
|
|
37
35
|
export interface ScreenProps extends ViewProps {
|
|
38
36
|
/**
|
|
@@ -103,11 +101,6 @@ export interface ScreenProps extends ViewProps {
|
|
|
103
101
|
* Optional. If `true`, the screen content is using grid layout by span.
|
|
104
102
|
*/
|
|
105
103
|
useGridLayout?: boolean;
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Optional. specs for input search.
|
|
109
|
-
*/
|
|
110
|
-
inputSearchProps?: InputSearchProps;
|
|
111
104
|
}
|
|
112
105
|
|
|
113
106
|
const Screen = forwardRef(
|
|
@@ -127,79 +120,32 @@ const Screen = forwardRef(
|
|
|
127
120
|
floatingButtonProps,
|
|
128
121
|
useGridLayout = true,
|
|
129
122
|
keyboardVerticalOffset,
|
|
130
|
-
inputSearchProps,
|
|
131
123
|
}: ScreenProps,
|
|
132
|
-
ref
|
|
124
|
+
ref,
|
|
133
125
|
) => {
|
|
126
|
+
const animatedValue = useRef<Animated.Value>(new Animated.Value(0));
|
|
134
127
|
const {theme} = useContext(ApplicationContext);
|
|
135
128
|
const insets = useSafeAreaInsets();
|
|
136
129
|
const heightHeader = useHeaderHeight();
|
|
137
|
-
const animatedValue = useRef<Animated.Value>(new Animated.Value(0));
|
|
138
|
-
const scrollViewRef = useRef<any>(ref);
|
|
139
130
|
const currentTint = useRef(Colors.black_01);
|
|
140
|
-
const isTab = navigation?.instance?.getState?.()?.type
|
|
131
|
+
const isTab = navigation?.instance?.getState?.()?.type == 'tab';
|
|
141
132
|
|
|
133
|
+
let styleAnimatedHeader: NavigationOptions;
|
|
142
134
|
let handleScroll;
|
|
143
135
|
let headerBackground: string | undefined = undefined;
|
|
144
136
|
let Component: any = View;
|
|
145
137
|
let keyboardOffset = heightHeader - 20;
|
|
146
|
-
if (headerType
|
|
138
|
+
if (headerType == 'extended' || animatedHeader) {
|
|
147
139
|
keyboardOffset = -20;
|
|
148
140
|
}
|
|
149
|
-
|
|
141
|
+
|
|
142
|
+
if (headerType == 'extended') {
|
|
150
143
|
headerBackground = theme.assets?.headerBackground;
|
|
151
144
|
}
|
|
152
145
|
|
|
153
146
|
useEffect(() => {
|
|
154
|
-
let options: NavigationOptions;
|
|
155
|
-
/**
|
|
156
|
-
* handle for basic header type
|
|
157
|
-
*/
|
|
158
|
-
switch (headerType) {
|
|
159
|
-
case 'none':
|
|
160
|
-
options = {
|
|
161
|
-
headerTransparent: true,
|
|
162
|
-
headerBackground: () => null,
|
|
163
|
-
headerShown: false,
|
|
164
|
-
};
|
|
165
|
-
break;
|
|
166
|
-
|
|
167
|
-
case 'surface':
|
|
168
|
-
options = {
|
|
169
|
-
headerTransparent: false,
|
|
170
|
-
headerShown: true,
|
|
171
|
-
headerTintColor: theme.colors.text.default,
|
|
172
|
-
headerBackground: (props: any) => (
|
|
173
|
-
<HeaderBackground {...props} image={null} useSurface={true} />
|
|
174
|
-
),
|
|
175
|
-
headerTitle: (props: any) => <HeaderTitle {...props} />,
|
|
176
|
-
};
|
|
177
|
-
break;
|
|
178
|
-
|
|
179
|
-
case 'extended':
|
|
180
|
-
options = {
|
|
181
|
-
headerShown: true,
|
|
182
|
-
headerTransparent: true,
|
|
183
|
-
headerTintColor: Colors.black_01,
|
|
184
|
-
headerBackground: () => null,
|
|
185
|
-
headerTitle: (props: any) => <HeaderTitle {...props} />,
|
|
186
|
-
};
|
|
187
|
-
break;
|
|
188
|
-
|
|
189
|
-
default:
|
|
190
|
-
options = {
|
|
191
|
-
headerTransparent: false,
|
|
192
|
-
headerShown: true,
|
|
193
|
-
headerTintColor: Colors.black_01,
|
|
194
|
-
headerBackground: (props: any) => <HeaderBackground {...props} />,
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* override options for animated header
|
|
200
|
-
*/
|
|
201
147
|
if (animatedHeader) {
|
|
202
|
-
|
|
148
|
+
styleAnimatedHeader = {
|
|
203
149
|
headerTransparent: true,
|
|
204
150
|
headerBackground: (props: any) => (
|
|
205
151
|
<HeaderBackground
|
|
@@ -211,9 +157,9 @@ const Screen = forwardRef(
|
|
|
211
157
|
<HeaderTitle {...props} animatedValue={animatedValue.current} />
|
|
212
158
|
),
|
|
213
159
|
};
|
|
214
|
-
if (animatedHeader.type
|
|
215
|
-
|
|
216
|
-
...
|
|
160
|
+
if (animatedHeader.type == 'surface') {
|
|
161
|
+
styleAnimatedHeader = {
|
|
162
|
+
...styleAnimatedHeader,
|
|
217
163
|
headerBackground: (props: any) => (
|
|
218
164
|
<HeaderBackground
|
|
219
165
|
{...props}
|
|
@@ -225,8 +171,8 @@ const Screen = forwardRef(
|
|
|
225
171
|
};
|
|
226
172
|
}
|
|
227
173
|
if (animatedHeader.headerTitle) {
|
|
228
|
-
|
|
229
|
-
...
|
|
174
|
+
styleAnimatedHeader = {
|
|
175
|
+
...styleAnimatedHeader,
|
|
230
176
|
headerTitle: (props: any) =>
|
|
231
177
|
animatedHeader.headerTitle?.({
|
|
232
178
|
...props,
|
|
@@ -234,10 +180,55 @@ const Screen = forwardRef(
|
|
|
234
180
|
}),
|
|
235
181
|
};
|
|
236
182
|
}
|
|
183
|
+
navigation?.setOptions(styleAnimatedHeader);
|
|
237
184
|
}
|
|
185
|
+
}, [animatedHeader]);
|
|
238
186
|
|
|
239
|
-
|
|
240
|
-
|
|
187
|
+
useEffect(() => {
|
|
188
|
+
if (!animatedHeader) {
|
|
189
|
+
let headerOptions: NavigationOptions;
|
|
190
|
+
switch (headerType) {
|
|
191
|
+
case 'none':
|
|
192
|
+
headerOptions = {
|
|
193
|
+
headerTransparent: true,
|
|
194
|
+
headerBackground: () => null,
|
|
195
|
+
headerShown: false,
|
|
196
|
+
};
|
|
197
|
+
break;
|
|
198
|
+
|
|
199
|
+
case 'surface':
|
|
200
|
+
headerOptions = {
|
|
201
|
+
headerTransparent: false,
|
|
202
|
+
headerShown: true,
|
|
203
|
+
headerTintColor: theme.colors.text.default,
|
|
204
|
+
headerBackground: (props: any) => (
|
|
205
|
+
<HeaderBackground {...props} image={null} useSurface={true} />
|
|
206
|
+
),
|
|
207
|
+
headerTitle: (props: any) => <HeaderTitle {...props} />,
|
|
208
|
+
};
|
|
209
|
+
break;
|
|
210
|
+
|
|
211
|
+
case 'extended':
|
|
212
|
+
headerOptions = {
|
|
213
|
+
headerShown: true,
|
|
214
|
+
headerTransparent: true,
|
|
215
|
+
headerTintColor: Colors.black_01,
|
|
216
|
+
headerBackground: () => null,
|
|
217
|
+
headerTitle: (props: any) => <HeaderTitle {...props} />,
|
|
218
|
+
};
|
|
219
|
+
break;
|
|
220
|
+
|
|
221
|
+
default:
|
|
222
|
+
headerOptions = {
|
|
223
|
+
headerTransparent: false,
|
|
224
|
+
headerShown: true,
|
|
225
|
+
headerTintColor: Colors.black_01,
|
|
226
|
+
headerBackground: (props: any) => <HeaderBackground {...props} />,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
navigation?.setOptions(headerOptions);
|
|
230
|
+
}
|
|
231
|
+
}, [headerType]);
|
|
241
232
|
|
|
242
233
|
/**
|
|
243
234
|
* animated when use scroll && animated value
|
|
@@ -245,7 +236,7 @@ const Screen = forwardRef(
|
|
|
245
236
|
if (scrollable) {
|
|
246
237
|
Component = Animated.ScrollView;
|
|
247
238
|
handleScroll = scrollViewProps?.onScroll;
|
|
248
|
-
if (animatedHeader || floatingButtonProps?.icon
|
|
239
|
+
if (animatedHeader || floatingButtonProps?.icon) {
|
|
249
240
|
handleScroll = Animated.event(
|
|
250
241
|
[
|
|
251
242
|
{
|
|
@@ -258,13 +249,13 @@ const Screen = forwardRef(
|
|
|
258
249
|
useNativeDriver: true,
|
|
259
250
|
listener: (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
260
251
|
scrollViewProps?.onScroll?.(e);
|
|
261
|
-
if (animatedHeader?.type
|
|
252
|
+
if (animatedHeader?.type == 'surface') {
|
|
262
253
|
const offsetY = e.nativeEvent.contentOffset.y;
|
|
263
254
|
let color = Colors.black_01;
|
|
264
255
|
if (offsetY > 50) {
|
|
265
256
|
color = theme.colors.text.default;
|
|
266
257
|
}
|
|
267
|
-
if (color
|
|
258
|
+
if (color != currentTint.current) {
|
|
268
259
|
currentTint.current = color;
|
|
269
260
|
navigation?.setOptions({
|
|
270
261
|
headerTintColor: color,
|
|
@@ -272,52 +263,31 @@ const Screen = forwardRef(
|
|
|
272
263
|
}
|
|
273
264
|
}
|
|
274
265
|
},
|
|
275
|
-
}
|
|
266
|
+
},
|
|
276
267
|
);
|
|
277
268
|
}
|
|
278
269
|
}
|
|
279
270
|
|
|
280
|
-
/**
|
|
281
|
-
* handle scroll end
|
|
282
|
-
* @param e
|
|
283
|
-
*/
|
|
284
|
-
const handleScrollEnd = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
285
|
-
const offsetY = e.nativeEvent.contentOffset.y;
|
|
286
|
-
if (inputSearchProps && offsetY < 100 && offsetY > 0) {
|
|
287
|
-
Animated.timing(animatedValue.current, {
|
|
288
|
-
toValue: 0,
|
|
289
|
-
useNativeDriver: true,
|
|
290
|
-
duration: 300,
|
|
291
|
-
}).start();
|
|
292
|
-
scrollViewRef.current?.scrollTo({y: 0, animated: true});
|
|
293
|
-
}
|
|
294
|
-
scrollViewProps?.onScrollEndDrag?.(e);
|
|
295
|
-
};
|
|
296
|
-
|
|
297
271
|
/**
|
|
298
272
|
* render top navigation banner
|
|
299
273
|
*/
|
|
300
|
-
const
|
|
274
|
+
const renderHeader = () => {
|
|
301
275
|
if (typeof animatedHeader?.component === 'function') {
|
|
302
|
-
return (
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
animatedValue: animatedValue.current,
|
|
306
|
-
})}
|
|
307
|
-
</View>
|
|
308
|
-
);
|
|
276
|
+
return animatedHeader?.component({
|
|
277
|
+
animatedValue: animatedValue.current,
|
|
278
|
+
});
|
|
309
279
|
}
|
|
310
280
|
};
|
|
311
281
|
|
|
312
282
|
/**
|
|
313
|
-
* build content for screen
|
|
283
|
+
* build content for screen
|
|
314
284
|
*/
|
|
315
285
|
const renderContent = (children: any): any => {
|
|
316
286
|
const results = validateChildren(children, [Section, Card, undefined]);
|
|
317
287
|
if (Array.isArray(results)) {
|
|
318
288
|
return results.map((item, index) => {
|
|
319
289
|
const space = item?.props?.useMargin === false ? 0 : Spacing.M;
|
|
320
|
-
if (item?.type
|
|
290
|
+
if (item?.type == Fragment) {
|
|
321
291
|
return renderContent(item?.props?.children);
|
|
322
292
|
}
|
|
323
293
|
if (item) {
|
|
@@ -337,7 +307,7 @@ const Screen = forwardRef(
|
|
|
337
307
|
} else {
|
|
338
308
|
const item: any = children;
|
|
339
309
|
const space = item?.props?.useMargin === false ? 0 : Spacing.M;
|
|
340
|
-
if (item?.type
|
|
310
|
+
if (item?.type == Fragment) {
|
|
341
311
|
return renderContent(item?.props?.children);
|
|
342
312
|
}
|
|
343
313
|
return (
|
|
@@ -357,21 +327,16 @@ const Screen = forwardRef(
|
|
|
357
327
|
return (
|
|
358
328
|
<View style={[Styles.flex, {backgroundColor}]}>
|
|
359
329
|
{!!headerBackground && (
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
animatedValue={animatedValue.current}
|
|
370
|
-
navigation={navigation}
|
|
371
|
-
{...inputSearchProps}
|
|
372
|
-
/>
|
|
330
|
+
<>
|
|
331
|
+
<Image
|
|
332
|
+
source={{
|
|
333
|
+
uri: headerBackground,
|
|
334
|
+
}}
|
|
335
|
+
style={styles.extendedHeader}
|
|
336
|
+
/>
|
|
337
|
+
<View style={{height: heightHeader}} />
|
|
338
|
+
</>
|
|
373
339
|
)}
|
|
374
|
-
|
|
375
340
|
<KeyboardAvoidingView
|
|
376
341
|
style={Styles.flex}
|
|
377
342
|
enabled={enableKeyboardAvoidingView}
|
|
@@ -384,14 +349,14 @@ const Screen = forwardRef(
|
|
|
384
349
|
|
|
385
350
|
<Component
|
|
386
351
|
{...scrollViewProps}
|
|
387
|
-
ref={
|
|
352
|
+
ref={ref}
|
|
388
353
|
showsVerticalScrollIndicator={false}
|
|
389
354
|
onScroll={handleScroll}
|
|
390
|
-
onScrollEndDrag={handleScrollEnd}
|
|
391
|
-
scrollEventThrottle={16}
|
|
392
355
|
style={Styles.flex}>
|
|
393
|
-
|
|
394
|
-
|
|
356
|
+
<View
|
|
357
|
+
style={[styles.screenBanner, {maxHeight: 210 + layoutOffset}]}>
|
|
358
|
+
{renderHeader()}
|
|
359
|
+
</View>
|
|
395
360
|
{useGridLayout ? renderContent(children) : children}
|
|
396
361
|
</Component>
|
|
397
362
|
|
|
@@ -422,7 +387,7 @@ const Screen = forwardRef(
|
|
|
422
387
|
</KeyboardAvoidingView>
|
|
423
388
|
</View>
|
|
424
389
|
);
|
|
425
|
-
}
|
|
390
|
+
},
|
|
426
391
|
);
|
|
427
392
|
|
|
428
393
|
export default Screen;
|
package/Layout/styles.ts
CHANGED
|
@@ -2,6 +2,12 @@ import {Platform, StyleSheet} from 'react-native';
|
|
|
2
2
|
import {Colors, Radius, Spacing} from '../Consts';
|
|
3
3
|
|
|
4
4
|
export default StyleSheet.create({
|
|
5
|
+
extendedHeader: {
|
|
6
|
+
aspectRatio: 1.75,
|
|
7
|
+
position: 'absolute',
|
|
8
|
+
width: '100%',
|
|
9
|
+
height: 210,
|
|
10
|
+
},
|
|
5
11
|
screenBanner: {
|
|
6
12
|
width: '100%',
|
|
7
13
|
},
|
package/Layout/types.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import {InputSearchProps, InputSearchRef} from '../Input';
|
|
3
|
-
import {LegacyRef} from 'react';
|
|
4
|
-
|
|
5
|
-
export type HeaderType = 'default' | 'surface' | 'extended' | 'search' | 'none';
|
|
1
|
+
export type HeaderType = 'default' | 'surface' | 'extended' | 'none';
|
|
6
2
|
|
|
7
3
|
export type GridContextProps = {
|
|
8
4
|
/**
|
|
@@ -25,18 +21,3 @@ export type GridContextProps = {
|
|
|
25
21
|
*/
|
|
26
22
|
getSizeSpan: (span: number) => number;
|
|
27
23
|
};
|
|
28
|
-
|
|
29
|
-
export type AnimatedInputSearchProps = {
|
|
30
|
-
animatedValue: Animated.Value;
|
|
31
|
-
headerRightWidth: number;
|
|
32
|
-
heightHeader: number;
|
|
33
|
-
headerType: HeaderType;
|
|
34
|
-
inputSearchProps?: InputSearchProps;
|
|
35
|
-
inputRef?: LegacyRef<InputSearchRef>;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export type ExtendHeaderProps = {
|
|
39
|
-
headerBackground: string;
|
|
40
|
-
animatedValue: Animated.Value;
|
|
41
|
-
heightHeader: number;
|
|
42
|
-
};
|
package/Title/index.tsx
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import React, {FC, useContext, useState} from 'react';
|
|
2
2
|
import {Text as RNText, TouchableOpacity, View, ViewStyle} from 'react-native';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
ApplicationContext,
|
|
9
|
-
scaleSize,
|
|
10
|
-
Text,
|
|
11
|
-
} from '@momo-kits/foundation';
|
|
3
|
+
import {Icon} from '../Icon';
|
|
4
|
+
import {scaleSize, Text} from '../Text';
|
|
5
|
+
import {ApplicationContext} from '../Application';
|
|
6
|
+
import {Badge} from '../Badge';
|
|
7
|
+
import {Colors} from '../Consts';
|
|
12
8
|
import styles from './styles';
|
|
13
9
|
import {TitleProps} from './types';
|
|
10
|
+
import {Typography} from '../Text/types';
|
|
14
11
|
|
|
15
12
|
const Title: FC<TitleProps> = ({
|
|
16
13
|
title = 'Title',
|
package/package.json
CHANGED
package/Input/TextTyping.tsx
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import React, {FC, memo, useEffect, useRef} from 'react';
|
|
2
|
-
import {Platform, StyleSheet, TextInput, TextStyle} from 'react-native';
|
|
3
|
-
import {Colors} from '../Consts';
|
|
4
|
-
import {scaleSize} from '../Text';
|
|
5
|
-
|
|
6
|
-
export interface TextTypingProps {
|
|
7
|
-
data: string[];
|
|
8
|
-
timeDelayEnd?: number;
|
|
9
|
-
timeDelayNextChar?: number;
|
|
10
|
-
inputStyle?: TextStyle;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const TextTyping: FC<TextTypingProps> = ({
|
|
14
|
-
data = [],
|
|
15
|
-
timeDelayEnd = 2000,
|
|
16
|
-
timeDelayNextChar = 20,
|
|
17
|
-
inputStyle = {},
|
|
18
|
-
}) => {
|
|
19
|
-
const textRef = useRef<TextInput>(null);
|
|
20
|
-
|
|
21
|
-
const currentIndex = useRef<number>(0);
|
|
22
|
-
const currentCharIndex = useRef<number>(0);
|
|
23
|
-
const currentText = useRef('');
|
|
24
|
-
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
setTimeout(() => {
|
|
27
|
-
playAnimation();
|
|
28
|
-
}, 1000);
|
|
29
|
-
}, []);
|
|
30
|
-
|
|
31
|
-
const playAnimation = () => {
|
|
32
|
-
const handleResetList = () => {
|
|
33
|
-
currentIndex.current = 0;
|
|
34
|
-
handleAnimation();
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const handleAnimation = () => {
|
|
38
|
-
const listChar = data?.[currentIndex.current]?.split('') || [];
|
|
39
|
-
listChar.length !== 0 && showChar(listChar?.[currentCharIndex.current]);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
currentIndex.current >= data?.length
|
|
43
|
-
? handleResetList()
|
|
44
|
-
: handleAnimation();
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const showChar = (char?: string) => {
|
|
48
|
-
const handleResetString = () => {
|
|
49
|
-
setTimeout(() => {
|
|
50
|
-
reset();
|
|
51
|
-
}, timeDelayEnd);
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const handleShowChar = () => {
|
|
55
|
-
setTimeout(() => {
|
|
56
|
-
textRef.current?.setNativeProps?.({
|
|
57
|
-
text: currentText.current + char,
|
|
58
|
-
});
|
|
59
|
-
currentText.current += char;
|
|
60
|
-
currentCharIndex.current++;
|
|
61
|
-
playAnimation();
|
|
62
|
-
}, timeDelayNextChar);
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
currentCharIndex.current >= (data?.[currentIndex.current]?.length || 0)
|
|
66
|
-
? handleResetString()
|
|
67
|
-
: handleShowChar();
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const reset = () => {
|
|
71
|
-
const handleNextString = () => {
|
|
72
|
-
currentIndex.current++;
|
|
73
|
-
playAnimation();
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const handleReset = () => {
|
|
77
|
-
setTimeout(() => {
|
|
78
|
-
textRef.current?.setNativeProps?.({
|
|
79
|
-
text: currentText.current.slice(0, -1),
|
|
80
|
-
});
|
|
81
|
-
currentText.current = currentText.current.slice(0, -1);
|
|
82
|
-
currentCharIndex.current--;
|
|
83
|
-
reset();
|
|
84
|
-
}, timeDelayNextChar);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
currentCharIndex.current <= 0 ? handleNextString() : handleReset();
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
return (
|
|
91
|
-
<TextInput
|
|
92
|
-
style={[styles.inputStyle, inputStyle]}
|
|
93
|
-
ref={textRef}
|
|
94
|
-
editable={false}
|
|
95
|
-
autoCorrect={false}
|
|
96
|
-
pointerEvents={'none'}
|
|
97
|
-
numberOfLines={1}
|
|
98
|
-
/>
|
|
99
|
-
);
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
export default memo(TextTyping);
|
|
103
|
-
|
|
104
|
-
const styles = StyleSheet.create({
|
|
105
|
-
inputStyle: {
|
|
106
|
-
color: Colors.black_12,
|
|
107
|
-
fontSize: scaleSize(12),
|
|
108
|
-
height: Platform.select({
|
|
109
|
-
android: 60,
|
|
110
|
-
ios: 36,
|
|
111
|
-
}),
|
|
112
|
-
},
|
|
113
|
-
});
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import React, {FC, useEffect, useRef, useState} from 'react';
|
|
2
|
-
import {InputSearch, InputSearchProps} from '../Input';
|
|
3
|
-
import {Animated, Dimensions} from 'react-native';
|
|
4
|
-
import {Spacing} from '../Consts';
|
|
5
|
-
import {scaleSize} from '../Text';
|
|
6
|
-
import Navigation from '../Application/Navigation';
|
|
7
|
-
|
|
8
|
-
export interface AnimatedInputSearchProps extends InputSearchProps {
|
|
9
|
-
animatedValue: Animated.Value;
|
|
10
|
-
navigation?: Navigation;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const SCREEN_PADDING = 12;
|
|
14
|
-
const BACK_WIDTH = scaleSize(28);
|
|
15
|
-
|
|
16
|
-
const AnimatedInputSearch: FC<AnimatedInputSearchProps> = ({
|
|
17
|
-
animatedValue,
|
|
18
|
-
navigation,
|
|
19
|
-
...props
|
|
20
|
-
}) => {
|
|
21
|
-
const {width: screenWidth} = Dimensions.get('window');
|
|
22
|
-
const widthAnimated = useRef(new Animated.Value(0));
|
|
23
|
-
const [rightSpace, setRightSpace] = useState(
|
|
24
|
-
navigation?.rightHeaderWidth ?? 0
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
setTimeout(() => {
|
|
29
|
-
if (rightSpace != navigation?.rightHeaderWidth) {
|
|
30
|
-
setRightSpace(navigation?.rightHeaderWidth ?? 0);
|
|
31
|
-
}
|
|
32
|
-
}, 500);
|
|
33
|
-
const listener = animatedValue.addListener(({value}) => {
|
|
34
|
-
widthAnimated.current.setValue(value);
|
|
35
|
-
});
|
|
36
|
-
return () => {
|
|
37
|
-
animatedValue?.removeListener(listener);
|
|
38
|
-
};
|
|
39
|
-
}, []);
|
|
40
|
-
|
|
41
|
-
const translateX = widthAnimated.current.interpolate({
|
|
42
|
-
inputRange: [0, 100],
|
|
43
|
-
outputRange: [SCREEN_PADDING, BACK_WIDTH + SCREEN_PADDING * 2],
|
|
44
|
-
extrapolate: 'clamp',
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
return (
|
|
48
|
-
<Animated.View
|
|
49
|
-
style={{
|
|
50
|
-
transform: [{translateX}],
|
|
51
|
-
marginVertical: Spacing.S,
|
|
52
|
-
width: widthAnimated.current.interpolate({
|
|
53
|
-
inputRange: [0, 100],
|
|
54
|
-
outputRange: [
|
|
55
|
-
screenWidth - SCREEN_PADDING * 2,
|
|
56
|
-
screenWidth - SCREEN_PADDING * 3 - BACK_WIDTH - rightSpace,
|
|
57
|
-
],
|
|
58
|
-
extrapolate: 'clamp',
|
|
59
|
-
}),
|
|
60
|
-
}}>
|
|
61
|
-
<InputSearch {...props} showButtonText={false} />
|
|
62
|
-
</Animated.View>
|
|
63
|
-
);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export default AnimatedInputSearch;
|