@momo-kits/foundation 0.92.21 → 0.92.23
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 +6 -5
- package/Application/BottomTab/BottomTabBar.tsx +2 -2
- package/Application/BottomTab/index.tsx +1 -2
- package/Application/Components.tsx +107 -34
- package/Application/ModalScreen.tsx +2 -2
- package/Application/Navigation.ts +4 -18
- package/Application/StackScreen.tsx +2 -2
- package/Application/index.ts +0 -2
- package/Application/types.ts +25 -8
- package/Application/utils.tsx +64 -18
- package/Button/index.tsx +0 -1
- package/Icon/types.ts +1 -0
- package/Input/InputDropDown.tsx +2 -2
- package/Input/InputMoney.tsx +3 -3
- package/Input/InputOTP.tsx +4 -4
- package/Input/InputSearch.tsx +249 -144
- package/Input/TextTyping.tsx +113 -0
- package/Input/index.tsx +19 -1
- package/Input/styles.ts +10 -3
- package/Layout/AnimatedInputSearch.tsx +66 -0
- package/Layout/FloatingButton.tsx +1 -1
- package/Layout/Screen.tsx +122 -87
- package/Layout/styles.ts +0 -6
- package/Layout/types.ts +20 -1
- package/Title/index.tsx +9 -6
- package/package.json +1 -1
|
@@ -0,0 +1,66 @@
|
|
|
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;
|
package/Layout/Screen.tsx
CHANGED
|
@@ -27,10 +27,12 @@ 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';
|
|
31
30
|
import {Card, Section, validateChildren} from './index';
|
|
32
31
|
import styles from './styles';
|
|
33
32
|
import {HeaderType} from './types';
|
|
33
|
+
import AnimatedInputSearch from './AnimatedInputSearch';
|
|
34
|
+
import {InputSearchProps} from '../Input';
|
|
35
|
+
import {HeaderExtendBackground} from '../Application/Components';
|
|
34
36
|
|
|
35
37
|
export interface ScreenProps extends ViewProps {
|
|
36
38
|
/**
|
|
@@ -101,6 +103,11 @@ export interface ScreenProps extends ViewProps {
|
|
|
101
103
|
* Optional. If `true`, the screen content is using grid layout by span.
|
|
102
104
|
*/
|
|
103
105
|
useGridLayout?: boolean;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Optional. specs for input search.
|
|
109
|
+
*/
|
|
110
|
+
inputSearchProps?: InputSearchProps;
|
|
104
111
|
}
|
|
105
112
|
|
|
106
113
|
const Screen = forwardRef(
|
|
@@ -120,32 +127,79 @@ const Screen = forwardRef(
|
|
|
120
127
|
floatingButtonProps,
|
|
121
128
|
useGridLayout = true,
|
|
122
129
|
keyboardVerticalOffset,
|
|
130
|
+
inputSearchProps,
|
|
123
131
|
}: ScreenProps,
|
|
124
|
-
ref
|
|
132
|
+
ref
|
|
125
133
|
) => {
|
|
126
|
-
const animatedValue = useRef<Animated.Value>(new Animated.Value(0));
|
|
127
134
|
const {theme} = useContext(ApplicationContext);
|
|
128
135
|
const insets = useSafeAreaInsets();
|
|
129
136
|
const heightHeader = useHeaderHeight();
|
|
137
|
+
const animatedValue = useRef<Animated.Value>(new Animated.Value(0));
|
|
138
|
+
const scrollViewRef = useRef<any>(ref);
|
|
130
139
|
const currentTint = useRef(Colors.black_01);
|
|
131
|
-
const isTab = navigation?.instance?.getState?.()?.type
|
|
140
|
+
const isTab = navigation?.instance?.getState?.()?.type === 'tab';
|
|
132
141
|
|
|
133
|
-
let styleAnimatedHeader: NavigationOptions;
|
|
134
142
|
let handleScroll;
|
|
135
143
|
let headerBackground: string | undefined = undefined;
|
|
136
144
|
let Component: any = View;
|
|
137
145
|
let keyboardOffset = heightHeader - 20;
|
|
138
|
-
if (headerType
|
|
146
|
+
if (headerType === 'extended' || animatedHeader) {
|
|
139
147
|
keyboardOffset = -20;
|
|
140
148
|
}
|
|
141
|
-
|
|
142
|
-
if (headerType == 'extended') {
|
|
149
|
+
if (headerType === 'extended') {
|
|
143
150
|
headerBackground = theme.assets?.headerBackground;
|
|
144
151
|
}
|
|
145
152
|
|
|
146
153
|
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
|
+
*/
|
|
147
201
|
if (animatedHeader) {
|
|
148
|
-
|
|
202
|
+
options = {
|
|
149
203
|
headerTransparent: true,
|
|
150
204
|
headerBackground: (props: any) => (
|
|
151
205
|
<HeaderBackground
|
|
@@ -157,9 +211,9 @@ const Screen = forwardRef(
|
|
|
157
211
|
<HeaderTitle {...props} animatedValue={animatedValue.current} />
|
|
158
212
|
),
|
|
159
213
|
};
|
|
160
|
-
if (animatedHeader.type
|
|
161
|
-
|
|
162
|
-
...
|
|
214
|
+
if (animatedHeader.type === 'surface') {
|
|
215
|
+
options = {
|
|
216
|
+
...options,
|
|
163
217
|
headerBackground: (props: any) => (
|
|
164
218
|
<HeaderBackground
|
|
165
219
|
{...props}
|
|
@@ -171,8 +225,8 @@ const Screen = forwardRef(
|
|
|
171
225
|
};
|
|
172
226
|
}
|
|
173
227
|
if (animatedHeader.headerTitle) {
|
|
174
|
-
|
|
175
|
-
...
|
|
228
|
+
options = {
|
|
229
|
+
...options,
|
|
176
230
|
headerTitle: (props: any) =>
|
|
177
231
|
animatedHeader.headerTitle?.({
|
|
178
232
|
...props,
|
|
@@ -180,55 +234,10 @@ const Screen = forwardRef(
|
|
|
180
234
|
}),
|
|
181
235
|
};
|
|
182
236
|
}
|
|
183
|
-
navigation?.setOptions(styleAnimatedHeader);
|
|
184
237
|
}
|
|
185
|
-
}, [animatedHeader]);
|
|
186
238
|
|
|
187
|
-
|
|
188
|
-
|
|
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]);
|
|
239
|
+
navigation?.setOptions(options);
|
|
240
|
+
}, [headerType, animatedHeader]);
|
|
232
241
|
|
|
233
242
|
/**
|
|
234
243
|
* animated when use scroll && animated value
|
|
@@ -236,7 +245,7 @@ const Screen = forwardRef(
|
|
|
236
245
|
if (scrollable) {
|
|
237
246
|
Component = Animated.ScrollView;
|
|
238
247
|
handleScroll = scrollViewProps?.onScroll;
|
|
239
|
-
if (animatedHeader || floatingButtonProps?.icon) {
|
|
248
|
+
if (animatedHeader || floatingButtonProps?.icon || inputSearchProps) {
|
|
240
249
|
handleScroll = Animated.event(
|
|
241
250
|
[
|
|
242
251
|
{
|
|
@@ -249,13 +258,13 @@ const Screen = forwardRef(
|
|
|
249
258
|
useNativeDriver: true,
|
|
250
259
|
listener: (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
251
260
|
scrollViewProps?.onScroll?.(e);
|
|
252
|
-
if (animatedHeader?.type
|
|
261
|
+
if (animatedHeader?.type === 'surface') {
|
|
253
262
|
const offsetY = e.nativeEvent.contentOffset.y;
|
|
254
263
|
let color = Colors.black_01;
|
|
255
264
|
if (offsetY > 50) {
|
|
256
265
|
color = theme.colors.text.default;
|
|
257
266
|
}
|
|
258
|
-
if (color
|
|
267
|
+
if (color !== currentTint.current) {
|
|
259
268
|
currentTint.current = color;
|
|
260
269
|
navigation?.setOptions({
|
|
261
270
|
headerTintColor: color,
|
|
@@ -263,31 +272,52 @@ const Screen = forwardRef(
|
|
|
263
272
|
}
|
|
264
273
|
}
|
|
265
274
|
},
|
|
266
|
-
}
|
|
275
|
+
}
|
|
267
276
|
);
|
|
268
277
|
}
|
|
269
278
|
}
|
|
270
279
|
|
|
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
|
+
|
|
271
297
|
/**
|
|
272
298
|
* render top navigation banner
|
|
273
299
|
*/
|
|
274
|
-
const
|
|
300
|
+
const renderAnimatedHeader = () => {
|
|
275
301
|
if (typeof animatedHeader?.component === 'function') {
|
|
276
|
-
return
|
|
277
|
-
|
|
278
|
-
|
|
302
|
+
return (
|
|
303
|
+
<View style={[styles.screenBanner, {maxHeight: 210 + layoutOffset}]}>
|
|
304
|
+
{animatedHeader?.component({
|
|
305
|
+
animatedValue: animatedValue.current,
|
|
306
|
+
})}
|
|
307
|
+
</View>
|
|
308
|
+
);
|
|
279
309
|
}
|
|
280
310
|
};
|
|
281
311
|
|
|
282
312
|
/**
|
|
283
|
-
* build content for screen
|
|
313
|
+
* build content for screen for grid rule
|
|
284
314
|
*/
|
|
285
315
|
const renderContent = (children: any): any => {
|
|
286
316
|
const results = validateChildren(children, [Section, Card, undefined]);
|
|
287
317
|
if (Array.isArray(results)) {
|
|
288
318
|
return results.map((item, index) => {
|
|
289
319
|
const space = item?.props?.useMargin === false ? 0 : Spacing.M;
|
|
290
|
-
if (item?.type
|
|
320
|
+
if (item?.type === Fragment) {
|
|
291
321
|
return renderContent(item?.props?.children);
|
|
292
322
|
}
|
|
293
323
|
if (item) {
|
|
@@ -307,7 +337,7 @@ const Screen = forwardRef(
|
|
|
307
337
|
} else {
|
|
308
338
|
const item: any = children;
|
|
309
339
|
const space = item?.props?.useMargin === false ? 0 : Spacing.M;
|
|
310
|
-
if (item?.type
|
|
340
|
+
if (item?.type === Fragment) {
|
|
311
341
|
return renderContent(item?.props?.children);
|
|
312
342
|
}
|
|
313
343
|
return (
|
|
@@ -327,16 +357,21 @@ const Screen = forwardRef(
|
|
|
327
357
|
return (
|
|
328
358
|
<View style={[Styles.flex, {backgroundColor}]}>
|
|
329
359
|
{!!headerBackground && (
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
360
|
+
<HeaderExtendBackground
|
|
361
|
+
headerBackground={headerBackground}
|
|
362
|
+
heightHeader={heightHeader}
|
|
363
|
+
animatedValue={animatedValue.current}
|
|
364
|
+
/>
|
|
365
|
+
)}
|
|
366
|
+
|
|
367
|
+
{inputSearchProps && (
|
|
368
|
+
<AnimatedInputSearch
|
|
369
|
+
animatedValue={animatedValue.current}
|
|
370
|
+
navigation={navigation}
|
|
371
|
+
{...inputSearchProps}
|
|
372
|
+
/>
|
|
339
373
|
)}
|
|
374
|
+
|
|
340
375
|
<KeyboardAvoidingView
|
|
341
376
|
style={Styles.flex}
|
|
342
377
|
enabled={enableKeyboardAvoidingView}
|
|
@@ -349,14 +384,14 @@ const Screen = forwardRef(
|
|
|
349
384
|
|
|
350
385
|
<Component
|
|
351
386
|
{...scrollViewProps}
|
|
352
|
-
ref={
|
|
387
|
+
ref={scrollViewRef}
|
|
353
388
|
showsVerticalScrollIndicator={false}
|
|
354
389
|
onScroll={handleScroll}
|
|
390
|
+
onScrollEndDrag={handleScrollEnd}
|
|
391
|
+
scrollEventThrottle={16}
|
|
355
392
|
style={Styles.flex}>
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
{renderHeader()}
|
|
359
|
-
</View>
|
|
393
|
+
{renderAnimatedHeader()}
|
|
394
|
+
|
|
360
395
|
{useGridLayout ? renderContent(children) : children}
|
|
361
396
|
</Component>
|
|
362
397
|
|
|
@@ -387,7 +422,7 @@ const Screen = forwardRef(
|
|
|
387
422
|
</KeyboardAvoidingView>
|
|
388
423
|
</View>
|
|
389
424
|
);
|
|
390
|
-
}
|
|
425
|
+
}
|
|
391
426
|
);
|
|
392
427
|
|
|
393
428
|
export default Screen;
|
package/Layout/styles.ts
CHANGED
|
@@ -2,12 +2,6 @@ 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
|
-
},
|
|
11
5
|
screenBanner: {
|
|
12
6
|
width: '100%',
|
|
13
7
|
},
|
package/Layout/types.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import {Animated} from 'react-native';
|
|
2
|
+
import {InputSearchProps, InputSearchRef} from '../Input';
|
|
3
|
+
import {LegacyRef} from 'react';
|
|
4
|
+
|
|
5
|
+
export type HeaderType = 'default' | 'surface' | 'extended' | 'search' | 'none';
|
|
2
6
|
|
|
3
7
|
export type GridContextProps = {
|
|
4
8
|
/**
|
|
@@ -21,3 +25,18 @@ export type GridContextProps = {
|
|
|
21
25
|
*/
|
|
22
26
|
getSizeSpan: (span: number) => number;
|
|
23
27
|
};
|
|
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,13 +1,16 @@
|
|
|
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
|
-
|
|
3
|
+
import {
|
|
4
|
+
Typography,
|
|
5
|
+
Colors,
|
|
6
|
+
Icon,
|
|
7
|
+
Badge,
|
|
8
|
+
ApplicationContext,
|
|
9
|
+
scaleSize,
|
|
10
|
+
Text,
|
|
11
|
+
} from '@momo-kits/foundation';
|
|
8
12
|
import styles from './styles';
|
|
9
13
|
import {TitleProps} from './types';
|
|
10
|
-
import {Typography} from '../Text/types';
|
|
11
14
|
|
|
12
15
|
const Title: FC<TitleProps> = ({
|
|
13
16
|
title = 'Title',
|