@momo-kits/foundation 0.92.21-beta.0 → 0.92.21-beta.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.
@@ -125,7 +125,7 @@ export default function BottomTabBar({
125
125
  );
126
126
  });
127
127
  },
128
- [JSON.stringify(routes), state, descriptors, focusedTab]
128
+ [JSON.stringify(routes), state, descriptors, focusedTab],
129
129
  );
130
130
 
131
131
  /**
@@ -153,7 +153,7 @@ export default function BottomTabBar({
153
153
  </View>
154
154
  <View
155
155
  style={{
156
- top: -4,
156
+ top: -6,
157
157
  backgroundColor: activeTintColor ?? theme.colors.primary,
158
158
  borderRadius: Radius.XL,
159
159
  paddingHorizontal: 6,
@@ -101,7 +101,7 @@ const BottomTab: React.FC<BottomTabProps> = ({
101
101
  name={item.name}
102
102
  component={TabScreen}
103
103
  initialParams={{...item, nested}}
104
- listeners={item.listeners ?? listeners}
104
+ listeners={listeners}
105
105
  options={{
106
106
  tabBarLabel: ({color, focused}) => {
107
107
  return (
@@ -1,8 +1,9 @@
1
1
  import React, {
2
- Fragment,
2
+ FC,
3
3
  useCallback,
4
4
  useContext,
5
5
  useEffect,
6
+ useRef,
6
7
  useState,
7
8
  } from 'react';
8
9
  import {
@@ -83,11 +84,6 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
83
84
 
84
85
  const HeaderTitle: React.FC<any> = props => {
85
86
  const {theme} = useContext(ApplicationContext);
86
- const opacity = props.animatedValue?.interpolate({
87
- inputRange: [0, 200],
88
- outputRange: [0, 1],
89
- extrapolate: 'clamp',
90
- });
91
87
 
92
88
  return (
93
89
  <Animated.Text
@@ -95,7 +91,11 @@ const HeaderTitle: React.FC<any> = props => {
95
91
  accessibilityLabel={'title_navigation_header'}
96
92
  style={[
97
93
  styles.title,
98
- {fontFamily: `${theme.font}-Bold`, opacity, color: props.tintColor},
94
+ {
95
+ fontFamily: `${theme.font}-Bold`,
96
+ color: props.tintColor,
97
+ opacity: props.titleOpacity,
98
+ },
99
99
  ]}
100
100
  />
101
101
  );
@@ -113,7 +113,7 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
113
113
  useEffect(() => {
114
114
  const backHandler = BackHandler.addEventListener(
115
115
  'hardwareBackPress',
116
- goBackSafe,
116
+ goBackSafe
117
117
  );
118
118
 
119
119
  return () => backHandler.remove();
@@ -263,35 +263,40 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
263
263
  return <View style={styles.headerTitleContainer}>{content ?? header}</View>;
264
264
  };
265
265
 
266
- const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
267
- const validateType = (child: React.ReactElement) => {
268
- const valid = child?.type === NavigationButton || child?.type === Fragment;
269
- if (__DEV__ && !valid) {
270
- console.warn(
271
- 'HeaderRightAction contains element type of NavigationButton, Please check again.',
272
- );
273
- }
274
- return child;
275
- };
266
+ const HeaderRight: FC<any> = ({type, ...props}) => {
267
+ let buttons = props?.buttons || [];
268
+ if (!type) {
269
+ return <View />;
270
+ }
276
271
 
277
- const renderAction = () => {
278
- if (Array.isArray(children)) {
279
- return children.map((child, index) => {
280
- return (
281
- <View key={`HeaderRightAction ${index}`} style={styles.headerButton}>
282
- {React.cloneElement(validateType(child), {...restProps})}
283
- </View>
284
- );
285
- });
272
+ if (type === 'iconButton') {
273
+ if (buttons?.length > 3) {
274
+ buttons = buttons.slice(0, 3);
286
275
  }
287
-
288
276
  return (
289
- <View style={styles.headerButton}>
290
- {React.cloneElement(validateType(children), {...restProps})}
277
+ <View style={styles.headerRightButton}>
278
+ {buttons?.map?.(
279
+ ({icon, onPress}: NavigationButtonProps, index: number) => {
280
+ return (
281
+ <View
282
+ key={`HeaderRightAction ${index}`}
283
+ style={{
284
+ marginLeft: index !== 0 ? Spacing.S : 0,
285
+ }}>
286
+ <NavigationButton
287
+ icon={icon}
288
+ onPress={onPress}
289
+ tintColor={props?.tintColor}
290
+ />
291
+ </View>
292
+ );
293
+ }
294
+ )}
291
295
  </View>
292
296
  );
293
- };
294
- return <View style={styles.headerRightButton}>{renderAction()}</View>;
297
+ }
298
+
299
+ return <HeaderToolkitAction {...props} />;
295
300
  };
296
301
 
297
302
  const HeaderToolkitAction: React.FC<any> = ({
@@ -327,7 +332,7 @@ const HeaderToolkitAction: React.FC<any> = ({
327
332
  (config: any) => {
328
333
  navigator.toolkitConfig = config;
329
334
  setToolConfig(navigator?.toolkitConfig);
330
- },
335
+ }
331
336
  );
332
337
  };
333
338
 
@@ -340,7 +345,7 @@ const HeaderToolkitAction: React.FC<any> = ({
340
345
  const {item} = res;
341
346
  navigator?.toolkitCallback?.(item);
342
347
  getToolkitConfig();
343
- },
348
+ }
344
349
  );
345
350
  };
346
351
 
@@ -357,7 +362,7 @@ const HeaderToolkitAction: React.FC<any> = ({
357
362
  navigator?.maxApi?.dispatchFunction?.(
358
363
  'dismiss',
359
364
  undefined,
360
- undefined,
365
+ undefined
361
366
  );
362
367
  },
363
368
  }}
@@ -388,7 +393,7 @@ const HeaderToolkitAction: React.FC<any> = ({
388
393
  [pinTool?.key],
389
394
  () => {
390
395
  getToolkitConfig();
391
- },
396
+ }
392
397
  );
393
398
  navigator?.toolkitCallback?.(pinTool.key);
394
399
  }}
@@ -405,6 +410,7 @@ const HeaderToolkitAction: React.FC<any> = ({
405
410
  {
406
411
  backgroundColor: backgroundColor ?? '#00000066',
407
412
  borderWidth: backgroundColor ? 0.5 : 0,
413
+ marginLeft: renderPinnedTool() ? Spacing.S : 0,
408
414
  },
409
415
  ]}>
410
416
  <TouchableOpacity
@@ -470,6 +476,42 @@ const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
470
476
  );
471
477
  };
472
478
 
479
+ const ExtendBackground: FC<{
480
+ headerBackground: string;
481
+ animatedValue: Animated.Value;
482
+ heightHeader: number;
483
+ }> = ({headerBackground, animatedValue, heightHeader}) => {
484
+ const heightAnimated = useRef(new Animated.Value(0));
485
+ useEffect(() => {
486
+ const listener = animatedValue.addListener(({value}) => {
487
+ heightAnimated.current.setValue(value);
488
+ });
489
+ return () => {
490
+ animatedValue?.removeListener(listener);
491
+ };
492
+ }, []);
493
+
494
+ return (
495
+ <>
496
+ <Image
497
+ source={{
498
+ uri: headerBackground,
499
+ }}
500
+ style={styles.extendedHeader}
501
+ />
502
+ <Animated.View
503
+ style={{
504
+ height: heightAnimated.current.interpolate({
505
+ inputRange: [0, 100],
506
+ outputRange: [heightHeader, heightHeader - 52],
507
+ extrapolate: 'clamp',
508
+ }),
509
+ }}
510
+ />
511
+ </>
512
+ );
513
+ };
514
+
473
515
  const styles = StyleSheet.create({
474
516
  navigationButton: {
475
517
  height: 28,
@@ -509,7 +551,6 @@ const styles = StyleSheet.create({
509
551
  paddingRight: Spacing.M,
510
552
  },
511
553
  toolkitContainer: {
512
- marginLeft: Spacing.S,
513
554
  padding: Spacing.XS,
514
555
  height: 28,
515
556
  borderRadius: 14,
@@ -541,6 +582,12 @@ const styles = StyleSheet.create({
541
582
  top: -Spacing.XS,
542
583
  right: -Spacing.XS,
543
584
  },
585
+ extendedHeader: {
586
+ aspectRatio: 1.75,
587
+ position: 'absolute',
588
+ width: '100%',
589
+ height: 210,
590
+ },
544
591
  });
545
592
 
546
593
  export {
@@ -548,8 +595,9 @@ export {
548
595
  HeaderTitle,
549
596
  HeaderLeft,
550
597
  HeaderBackground,
551
- HeaderRightAction,
552
598
  HeaderToolkitAction,
553
599
  HeaderCustom,
554
600
  HeaderAnimated,
601
+ HeaderRight,
602
+ ExtendBackground,
555
603
  };
@@ -1,9 +1,6 @@
1
- import React from 'react';
2
1
  import {NavigationProp} from '@react-navigation/native';
3
2
  import {NavigationOptions, Theme} from './types';
4
- import {HeaderRightAction} from './index';
5
3
  import {getOptions} from './utils';
6
- import {HeaderToolkitAction} from './Components';
7
4
 
8
5
  class Navigation {
9
6
  instance: NavigationProp<any>;
@@ -19,16 +16,6 @@ class Navigation {
19
16
  * @param params
20
17
  */
21
18
  private filterParams = (params: NavigationOptions) => {
22
- if (params.headerRight) {
23
- const headerRight = params.headerRight?.({}) as React.ReactElement;
24
- const type = headerRight?.type;
25
- if (type !== HeaderRightAction && type !== HeaderToolkitAction) {
26
- console.warn(
27
- 'headerRight contains element type of HeaderRightAction | HeaderToolkitAction, Please check again.',
28
- );
29
- }
30
- }
31
-
32
19
  if (params.headerLeft) {
33
20
  console.warn('headerLeft not allow override render by design system!');
34
21
  delete params.headerLeft;
@@ -1,5 +1,4 @@
1
1
  import {StackNavigationOptions} from '@react-navigation/stack';
2
- import {EventArg} from '@react-navigation/core';
3
2
  import React from 'react';
4
3
  import {Animated, ViewProps} from 'react-native';
5
4
  import {PopupNotifyProps} from '../Popup/types';
@@ -145,19 +144,29 @@ export type RuntimeToolType = {
145
144
  key: string;
146
145
  };
147
146
 
148
- export interface NavigationOptions extends StackNavigationOptions {
147
+ export interface NavigationOptions
148
+ extends Omit<StackNavigationOptions, 'headerRight'> {
149
149
  preventBack?: PopupNotifyProps;
150
150
  onPressLeftHeader?: () => void;
151
151
  surface?: boolean;
152
152
  hiddenBack?: boolean;
153
153
  customTitle?: TitleCustomProps;
154
- toolkitParams?: {
155
- pinnedTool?: PinnedToolType;
156
- runtimeTools?: RuntimeToolType[];
157
- preventClose?: PopupNotifyProps;
158
- };
154
+ headerRight?: HeaderRightToolkit | HeaderRightActions | Element;
159
155
  }
160
156
 
157
+ export type HeaderRightToolkit = {
158
+ type?: 'toolkit';
159
+ pinnedTool?: PinnedToolType;
160
+ runtimeTools?: RuntimeToolType[];
161
+ preventClose?: PopupNotifyProps;
162
+ useMore?: boolean;
163
+ };
164
+
165
+ export type HeaderRightActions = {
166
+ type?: 'iconButton';
167
+ buttons: NavigationButtonProps[];
168
+ };
169
+
161
170
  export interface HeaderBackProps extends NavigationButtonProps {
162
171
  preventBack?: PopupNotifyProps;
163
172
  onPressLeftHeader?: () => void;
@@ -199,11 +208,6 @@ export type BottomTabItemProps = {
199
208
  screen: Screen;
200
209
  options: NavigationOptions;
201
210
  initialParams?: any;
202
- listeners?: {
203
- tabPress?: (e: EventArg<'tabPress', true, undefined>) => void;
204
- focus?: (e: EventArg<'focus', false, unknown>) => void;
205
- blur?: (e: EventArg<'blur', false, unknown>) => void;
206
- };
207
211
  };
208
212
 
209
213
  export type BottomTabProps = {
@@ -212,9 +216,8 @@ export type BottomTabProps = {
212
216
  initialRouteName?: string;
213
217
  navigation: Navigation;
214
218
  listeners?: {
215
- tabPress?: (e: EventArg<'tabPress', true, undefined>) => void;
216
- focus?: (e: EventArg<'focus', false, unknown>) => void;
217
- blur?: (e: EventArg<'blur', false, unknown>) => void;
219
+ tabPress?: any;
220
+ focus?: any;
218
221
  };
219
222
  floatingButton?: FloatingButtonProps;
220
223
  };
@@ -122,15 +122,6 @@ const getOptions = (params: NavigationOptions, theme: Theme) => {
122
122
  };
123
123
  }
124
124
 
125
- if (params.toolkitParams) {
126
- options = {
127
- ...options,
128
- headerRight: (props: any) => {
129
- return <HeaderToolkitAction {...params.toolkitParams} {...props} />;
130
- },
131
- };
132
- }
133
-
134
125
  return {
135
126
  ...params,
136
127
  ...options,
package/Button/index.tsx CHANGED
@@ -297,7 +297,6 @@ const Button: FC<ButtonProps> = ({
297
297
  };
298
298
 
299
299
  const activeOpacity = type === 'disabled' ? 0.75 : 0.5;
300
-
301
300
  return (
302
301
  <ComponentContext.Provider
303
302
  value={{
package/Icon/types.ts CHANGED
@@ -16,6 +16,7 @@ export type IconProps = {
16
16
 
17
17
  /**
18
18
  * Optional. Represents the color of the icon.
19
+ * It can be any valid color in @momo-kits/foundation.
19
20
  */
20
21
  color?: string | null;
21
22
 
@@ -4,7 +4,7 @@ import {ApplicationContext, ComponentContext} from '../Application';
4
4
  import {Styles} from '../Consts';
5
5
  import {Icon} from '../Icon';
6
6
  import {Loader} from '../Loader';
7
- import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
7
+ import {ErrorView, FloatingView, getSizeStyle} from './common';
8
8
  import {InputDropDownProps} from './index';
9
9
  import styles from './styles';
10
10
 
@@ -61,7 +61,7 @@ const InputDropDown = ({
61
61
  styles.inputWrapper,
62
62
  {backgroundColor: theme.colors.background.surface},
63
63
  getSizeStyle(size),
64
- getBorderColor(theme, false, errorMessage, disabled),
64
+ // getBorderColor(theme, false, errorMessage, disabled),
65
65
  ]}>
66
66
  <FloatingView
67
67
  floatingValue={floatingValue}
@@ -44,7 +44,7 @@ const InputMoney = forwardRef(
44
44
  value: _value,
45
45
  ...props
46
46
  }: InputMoneyProps,
47
- ref,
47
+ ref
48
48
  ) => {
49
49
  const {theme} = useContext(ApplicationContext);
50
50
  const [focused, setFocused] = useState(false);
@@ -63,7 +63,7 @@ const InputMoney = forwardRef(
63
63
  };
64
64
 
65
65
  const [value, setValue] = useState(
66
- defaultValue ? validateText(defaultValue) : '',
66
+ defaultValue ? validateText(defaultValue) : ''
67
67
  );
68
68
 
69
69
  const onClearText = () => {
@@ -198,7 +198,7 @@ const InputMoney = forwardRef(
198
198
  </View>
199
199
  </ComponentContext.Provider>
200
200
  );
201
- },
201
+ }
202
202
  );
203
203
 
204
204
  export default InputMoney;
@@ -41,7 +41,7 @@ const OTPCaret: FC<CaretProps> = ({index, length}) => {
41
41
  duration: DURATION,
42
42
  useNativeDriver: true,
43
43
  }),
44
- ]),
44
+ ])
45
45
  ).start();
46
46
  }, []);
47
47
  const spacingStyle = !isNaN(Number(length)) &&
@@ -81,7 +81,7 @@ const InputOTP = forwardRef(
81
81
  hintText,
82
82
  ...props
83
83
  }: InputOTPProps,
84
- ref,
84
+ ref
85
85
  ) => {
86
86
  const MAX_LENGTH = 10;
87
87
  const [value, setValue] = useState('');
@@ -143,7 +143,7 @@ const InputOTP = forwardRef(
143
143
  {value[i] || '-'}
144
144
  </Text>
145
145
  )}
146
- </View>,
146
+ </View>
147
147
  );
148
148
  }
149
149
  return TextInputs;
@@ -248,7 +248,7 @@ const InputOTP = forwardRef(
248
248
  </TouchableOpacity>
249
249
  </ComponentContext.Provider>
250
250
  );
251
- },
251
+ }
252
252
  );
253
253
 
254
254
  export default InputOTP;