@momo-kits/foundation 0.169.9-beta.1 → 0.169.9

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 (63) hide show
  1. package/Application/BottomSheet.hooks.ts +27 -17
  2. package/Application/BottomSheet.tsx +35 -27
  3. package/Application/BottomTab/ActiveIndicator.tsx +5 -1
  4. package/Application/BottomTab/BottomTabBar.styles.ts +18 -1
  5. package/Application/BottomTab/BottomTabBar.tsx +14 -16
  6. package/Application/BottomTab/CurvedContainer.tsx +8 -2
  7. package/Application/BottomTab/CustomBottomTabItem.tsx +2 -2
  8. package/Application/BottomTab/DuoRailTabBar.tsx +5 -5
  9. package/Application/BottomTab/DuoTabBar.tsx +15 -3
  10. package/Application/BottomTab/TabScreen.tsx +11 -10
  11. package/Application/BottomTab/index.tsx +5 -5
  12. package/Application/BottomTab/metrics.ts +23 -3
  13. package/Application/BottomTab/usePressLift.ts +3 -3
  14. package/Application/Components/HeaderAnimated.tsx +13 -38
  15. package/Application/Components/HeaderBackground.tsx +3 -16
  16. package/Application/Components/HeaderExtendHeader.tsx +28 -41
  17. package/Application/Components/HeaderLeft.tsx +18 -4
  18. package/Application/Components/HeaderRight.styles.ts +13 -15
  19. package/Application/Components/HeaderTitle.shared.ts +11 -10
  20. package/Application/Components/HeaderToolkitAction.tsx +54 -21
  21. package/Application/Components/NavigationButton.tsx +6 -9
  22. package/Application/Components/SearchHeader.tsx +7 -20
  23. package/Application/Components/useToolkitActions.tsx +22 -21
  24. package/Application/ModalScreen.tsx +19 -15
  25. package/Application/StackScreen.tsx +13 -18
  26. package/Application/index.ts +1 -11
  27. package/Application/modalLayout.ts +1 -0
  28. package/Application/navigationOptions.tsx +15 -6
  29. package/Application/types.header.ts +2 -7
  30. package/Application/types.tabs.ts +0 -1
  31. package/Application/types.ts +0 -7
  32. package/Context/index.ts +3 -1
  33. package/Image/index.tsx +6 -6
  34. package/Input/ErrorView.tsx +59 -0
  35. package/Input/FloatingView.tsx +101 -0
  36. package/Input/Input.tsx +40 -37
  37. package/Input/InputDropDown.tsx +13 -10
  38. package/Input/InputMoney.tsx +17 -17
  39. package/Input/InputMoneyView.tsx +12 -12
  40. package/Input/InputOTP.tsx +46 -34
  41. package/Input/InputPhoneNumber.tsx +48 -43
  42. package/Input/InputSearch.tsx +26 -39
  43. package/Input/InputTextArea.tsx +29 -23
  44. package/Input/RenderTrailing.tsx +79 -0
  45. package/Input/constants.ts +8 -0
  46. package/Input/index.tsx +1 -7
  47. package/Input/utils.ts +126 -7
  48. package/Layout/FloatingButton.tsx +38 -24
  49. package/Layout/Screen.tsx +0 -3
  50. package/Layout/layoutMetrics.ts +43 -34
  51. package/Layout/screenHeader.tsx +52 -55
  52. package/Layout/screenTypes.ts +4 -13
  53. package/Pagination/PaginationScroll.tsx +5 -3
  54. package/Pagination/types.ts +3 -5
  55. package/Popup/PopupNotify.tsx +17 -14
  56. package/Popup/PopupPromotion.tsx +5 -4
  57. package/Popup/types.ts +2 -4
  58. package/Popup/utils.ts +7 -4
  59. package/Skeleton/index.tsx +15 -12
  60. package/package.json +1 -1
  61. package/Application/headerLayout.ts +0 -165
  62. package/Input/common.tsx +0 -257
  63. package/Input/moneyUtils.ts +0 -23
package/Input/common.tsx DELETED
@@ -1,257 +0,0 @@
1
- import React, { FC, ReactNode, useContext } from 'react';
2
- import {
3
- GestureResponderEvent,
4
- TouchableOpacity,
5
- View,
6
- ViewStyle,
7
- } from 'react-native';
8
- import { ApplicationContext } from '../Context';
9
- import { Theme } from '../Application/types';
10
- import { Styles } from '../Consts';
11
- import { Icon } from '../Icon';
12
- import { useScaleSize, Text } from '../Text';
13
- import styles from './styles';
14
- import { Loader } from '../Loader';
15
- import IconSources from '../Assets/icon.json';
16
-
17
- type FloatingViewProps = {
18
- floatingValue?: string;
19
- floatingIconColor?: string;
20
- componentId?: string;
21
- disabled?: boolean;
22
- floatingIcon?: string;
23
- required?: boolean;
24
- style?: ViewStyle;
25
- onPress?: (e: GestureResponderEvent) => void;
26
- };
27
-
28
- type TrailingProps = {
29
- loading?: boolean;
30
- color?: string;
31
- icon?: string;
32
- componentId?: string;
33
- onPressIcon?: () => void;
34
- };
35
-
36
- export const MAX_LENGTH = 300;
37
-
38
- /** Border color by state; priority is disabled > error > focused > default. */
39
- export const getBorderColor = (
40
- theme: Theme,
41
- focused: boolean,
42
- errorMessage?: string,
43
- disabled?: boolean,
44
- ) => {
45
- let borderColor = theme.colors.border.default;
46
-
47
- if (focused) {
48
- borderColor = theme.colors.primary;
49
- }
50
-
51
- if (errorMessage) {
52
- borderColor = theme.colors.error.primary;
53
- }
54
-
55
- if (disabled) {
56
- borderColor = theme.colors.border.disable;
57
- }
58
-
59
- return { borderColor };
60
- };
61
-
62
- /**
63
- * Container style for `size`; multiline uses `height` as minHeight so the
64
- * field can grow with its content.
65
- */
66
- export const getSizeStyle = (
67
- size?: 'small' | 'large',
68
- multiline: boolean = false,
69
- height?: number,
70
- ) => {
71
- let scaleStyle: ViewStyle = {};
72
- if (height) {
73
- scaleStyle = { height };
74
- }
75
-
76
- if (multiline) {
77
- return [
78
- styles.multilineContainer,
79
- {
80
- minHeight: height,
81
- },
82
- ];
83
- }
84
-
85
- if (size === 'small') {
86
- return [styles.smallContainer, scaleStyle];
87
- }
88
- return [styles.container, scaleStyle];
89
- };
90
-
91
- /**
92
- * Error or hint row under an input (error wins); with neither, `errorSpacing`
93
- * keeps an empty row so the layout doesn't jump when an error appears.
94
- */
95
- export const ErrorView: FC<{
96
- errorMessage?: string;
97
- errorSpacing?: boolean;
98
- hintText?: string;
99
- componentId?: string;
100
- }> = ({ errorMessage, errorSpacing, hintText, componentId }) => {
101
- const { theme } = useContext(ApplicationContext);
102
- const errorColor = theme.colors.error.primary;
103
- const hintColor = theme.colors.text.hint;
104
- const hintTextDefault = hintText ?? 'Không thể chỉnh sửa';
105
- const scaledIconSize = useScaleSize(16);
106
-
107
- if (errorMessage || hintText) {
108
- const messageColor = errorMessage ? errorColor : hintColor;
109
- const messageType = errorMessage ? 'error' : 'hint';
110
- return (
111
- <View style={styles.errorView}>
112
- <View style={styles.errorIcon}>
113
- <Icon color={messageColor} source="ic_error" size={scaledIconSize} />
114
- </View>
115
- <Text
116
- accessibilityLabel={`${componentId}|${messageType}-text`}
117
- style={Styles.flex}
118
- color={messageColor}
119
- typography={'description_default_regular'}
120
- >
121
- {errorMessage ?? hintTextDefault}
122
- </Text>
123
- </View>
124
- );
125
- }
126
- if (errorSpacing) {
127
- return <View style={[styles.errorView, styles.errorSpacing]} />;
128
- }
129
- return <View />;
130
- };
131
-
132
- /**
133
- * Floating label on the input's top border with a required `*` and an
134
- * optional pressable icon; renders nothing without `floatingValue`.
135
- */
136
- export const FloatingView: FC<FloatingViewProps> = ({
137
- floatingValue,
138
- floatingIconColor,
139
- disabled,
140
- floatingIcon,
141
- required,
142
- style,
143
- onPress,
144
- componentId,
145
- }) => {
146
- const { theme } = useContext(ApplicationContext);
147
- const scaledTop = useScaleSize(10);
148
- if (floatingValue) {
149
- let floatingTextColor = theme.colors.text.hint;
150
- let floatingIconTintColor = floatingIconColor;
151
- if (disabled) {
152
- floatingTextColor = theme.colors.text.disable;
153
- floatingIconTintColor = theme.colors.text.disable;
154
- }
155
-
156
- return (
157
- <View
158
- style={[
159
- styles.floatingView,
160
- styles.floatingViewLayer,
161
- {
162
- backgroundColor: theme.colors.background.surface,
163
- top: -scaledTop,
164
- },
165
- style,
166
- ]}
167
- >
168
- <Text
169
- color={floatingTextColor}
170
- typography={'label_s_medium'}
171
- accessibilityLabel={`${componentId}|floating-text`}
172
- >
173
- {floatingValue}
174
- {required && (
175
- <Text
176
- typography={'label_s_medium'}
177
- color={theme.colors.error.primary}
178
- >
179
- *
180
- </Text>
181
- )}
182
- </Text>
183
- {!!floatingIcon && (
184
- <TouchableOpacity
185
- activeOpacity={onPress ? 0.6 : 1}
186
- onPress={onPress}
187
- accessibilityLabel={`${componentId}|floating-icon-touch`}
188
- >
189
- <Icon
190
- color={floatingIconTintColor}
191
- source={floatingIcon}
192
- size={16}
193
- style={styles.floatingIcon}
194
- accessibilityLabel={`${componentId}|floating-icon`}
195
- />
196
- </TouchableOpacity>
197
- )}
198
- </View>
199
- );
200
- }
201
- return null;
202
- };
203
-
204
- /**
205
- * Trailing slot: spinner while `loading`, an icon when `icon` is a known icon
206
- * name or URL, otherwise `icon` as a text action (first 15 chars).
207
- */
208
- export const RenderTrailing: FC<TrailingProps> = ({
209
- loading,
210
- color,
211
- icon,
212
- onPressIcon,
213
- componentId,
214
- }) => {
215
- const { theme } = useContext(ApplicationContext);
216
- if (loading) {
217
- return <Loader type={'spinner'} color={color} style={styles.icon} />;
218
- }
219
-
220
- if (icon) {
221
- const isIconName = !!(IconSources as any)?.[icon]?.uri;
222
- const isIcon = isIconName || icon.includes('http');
223
- const renderIconTouchable = (content: ReactNode) => {
224
- return (
225
- <TouchableOpacity
226
- accessibilityLabel={`${componentId}|trailing-touch`}
227
- onPress={onPressIcon}
228
- style={styles.icon}
229
- >
230
- {content}
231
- </TouchableOpacity>
232
- );
233
- };
234
-
235
- if (isIcon) {
236
- return renderIconTouchable(
237
- <Icon
238
- color={color}
239
- source={icon as string}
240
- size={24}
241
- accessibilityLabel={`${componentId}|trailing-icon`}
242
- />,
243
- );
244
- }
245
- return renderIconTouchable(
246
- <Text
247
- typography="action_xs_bold"
248
- color={color ?? theme.colors.primary}
249
- numberOfLines={1}
250
- accessibilityLabel={`${componentId}|trailing-text`}
251
- >
252
- {icon!.substring(0, 15)}
253
- </Text>,
254
- );
255
- }
256
- return null;
257
- };
@@ -1,23 +0,0 @@
1
- export const moneyFormatter = new Intl.NumberFormat('vi-VN');
2
-
3
- /**
4
- * Locates the single edited span between `old` and `text`: common prefix
5
- * length (`start`), common suffix length (`suffix`) and removed + inserted
6
- * char count (`size`).
7
- */
8
- export const findEdit = (old: string, text: string) => {
9
- let start = 0;
10
- while (start < text.length && old[start] === text[start]) {
11
- start += 1;
12
- }
13
- const maxSuffix = Math.min(text.length, old.length) - start;
14
- let suffix = 0;
15
- while (suffix < maxSuffix) {
16
- if (old[old.length - 1 - suffix] !== text[text.length - 1 - suffix]) {
17
- break;
18
- }
19
- suffix += 1;
20
- }
21
- const size = old.length + text.length - 2 * (start + suffix);
22
- return { old, start, suffix, size };
23
- };