@momo-kits/foundation 0.167.1-beta.2 → 0.167.1-beta.3
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/BottomTab/BottomTabBar.tsx +3 -6
- package/Application/Components/HeaderExtendHeader.tsx +6 -7
- package/Application/Components/SearchHeader.tsx +8 -4
- package/Input/InputMoney.tsx +50 -192
- package/Layout/Card.tsx +4 -6
- package/Layout/FloatingButton.tsx +2 -4
- package/Layout/Section.tsx +11 -7
- package/Layout/utils.ts +1 -16
- package/package.json +1 -1
|
@@ -58,13 +58,11 @@ export default function BottomTabBar({
|
|
|
58
58
|
const { theme } = useContext(ApplicationContext);
|
|
59
59
|
const { routes } = state;
|
|
60
60
|
const widthDevice = useWindowDimensions()?.width;
|
|
61
|
-
const insets = useSafeAreaInsets();
|
|
62
61
|
const useFloating = floatingButton && state.routes.length % 2 === 0;
|
|
63
|
-
const itemWidth =
|
|
64
|
-
(widthDevice - insets.left - insets.right) /
|
|
65
|
-
(state.routes.length + (useFloating ? 1 : 0));
|
|
62
|
+
const itemWidth = widthDevice / (state.routes.length + (useFloating ? 1 : 0));
|
|
66
63
|
// const buildLink = useLinkBuilder();
|
|
67
64
|
const indicatorAnimated = useSharedValue(0);
|
|
65
|
+
const insets = useSafeAreaInsets();
|
|
68
66
|
|
|
69
67
|
const indicatorStyle = useAnimatedStyle(() => ({
|
|
70
68
|
width: itemWidth,
|
|
@@ -248,8 +246,7 @@ export default function BottomTabBar({
|
|
|
248
246
|
},
|
|
249
247
|
{
|
|
250
248
|
paddingBottom: paddingBottom,
|
|
251
|
-
|
|
252
|
-
paddingRight: insets.right,
|
|
249
|
+
paddingHorizontal: Math.max(insets.left, insets.right),
|
|
253
250
|
},
|
|
254
251
|
style,
|
|
255
252
|
]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { Ref, useContext } from 'react';
|
|
2
2
|
import LinearGradient from 'react-native-linear-gradient';
|
|
3
|
-
import { Platform, StyleSheet, View } from 'react-native';
|
|
3
|
+
import { Dimensions, Platform, StyleSheet, View } from 'react-native';
|
|
4
4
|
import Animated, {
|
|
5
5
|
Extrapolation,
|
|
6
6
|
interpolate,
|
|
@@ -18,11 +18,12 @@ import {
|
|
|
18
18
|
AnimatedCompatValue,
|
|
19
19
|
useNormalizedSharedValue,
|
|
20
20
|
} from '../utils';
|
|
21
|
-
import { useHorizontalLayout } from '../../Layout/utils';
|
|
22
21
|
|
|
23
22
|
const SCREEN_PADDING = 12;
|
|
24
23
|
const BACK_WIDTH = 28;
|
|
25
24
|
|
|
25
|
+
const { width: screenWidth } = Dimensions.get('window');
|
|
26
|
+
|
|
26
27
|
const HeaderExtendHeader: React.FC<{
|
|
27
28
|
headerType?: HeaderType;
|
|
28
29
|
animatedValue: AnimatedCompatValue;
|
|
@@ -51,8 +52,6 @@ const HeaderExtendHeader: React.FC<{
|
|
|
51
52
|
const gradientColor = customGradientColor ?? theme.colors.gradient;
|
|
52
53
|
const headerBackground = customBackground ?? theme.assets?.headerBackground;
|
|
53
54
|
const leftPosition = inputSearchProps?.leftPosition || BACK_WIDTH + 20;
|
|
54
|
-
const layout = useHorizontalLayout(SCREEN_PADDING);
|
|
55
|
-
const { insets } = layout;
|
|
56
55
|
|
|
57
56
|
let useShadowHeader = useShadowHeaderProp;
|
|
58
57
|
if (inputSearchProps && Platform.OS === 'android') {
|
|
@@ -80,7 +79,7 @@ const HeaderExtendHeader: React.FC<{
|
|
|
80
79
|
translateX: interpolate(
|
|
81
80
|
sharedValue.value,
|
|
82
81
|
[0, 100],
|
|
83
|
-
[
|
|
82
|
+
[SCREEN_PADDING, leftPosition],
|
|
84
83
|
Extrapolation.CLAMP,
|
|
85
84
|
),
|
|
86
85
|
},
|
|
@@ -89,8 +88,8 @@ const HeaderExtendHeader: React.FC<{
|
|
|
89
88
|
sharedValue.value,
|
|
90
89
|
[0, 100],
|
|
91
90
|
[
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
screenWidth - SCREEN_PADDING * 2,
|
|
92
|
+
screenWidth - leftPosition - 12 - headerRightWidth,
|
|
94
93
|
],
|
|
95
94
|
Extrapolation.CLAMP,
|
|
96
95
|
),
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { Colors, Radius, Spacing, Styles } from '../../Consts';
|
|
2
2
|
import { InputRef, InputSearch } from '../../Input';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
Dimensions,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
View,
|
|
8
|
+
} from 'react-native';
|
|
4
9
|
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
|
|
5
10
|
import React, { useContext } from 'react';
|
|
6
11
|
import { SearchHeaderProps } from '../types';
|
|
7
12
|
import { ApplicationContext, MiniAppContext } from '../../Context';
|
|
8
13
|
import { Text } from '../../Text';
|
|
9
14
|
import { useNormalizedSharedValue } from '../utils';
|
|
10
|
-
import { useHorizontalLayout } from '../../Layout/utils';
|
|
11
15
|
|
|
12
16
|
const SearchHeader = React.forwardRef<InputRef, SearchHeaderProps>(
|
|
13
17
|
(
|
|
@@ -23,7 +27,7 @@ const SearchHeader = React.forwardRef<InputRef, SearchHeaderProps>(
|
|
|
23
27
|
const { theme, navigator } = useContext(ApplicationContext);
|
|
24
28
|
const context = useContext<any>(MiniAppContext);
|
|
25
29
|
const BACK_WIDTH = 28;
|
|
26
|
-
const { width:
|
|
30
|
+
const { width: screenWidth } = Dimensions.get('window');
|
|
27
31
|
|
|
28
32
|
const sharedValue = useNormalizedSharedValue(animatedValue);
|
|
29
33
|
const leftPosition = props?.leftPosition ?? BACK_WIDTH + 20;
|
|
@@ -73,7 +77,7 @@ const SearchHeader = React.forwardRef<InputRef, SearchHeaderProps>(
|
|
|
73
77
|
style={[
|
|
74
78
|
Styles.flex,
|
|
75
79
|
renderButtons && {
|
|
76
|
-
maxWidth:
|
|
80
|
+
maxWidth: screenWidth - leftPosition - 12 - headerRightWidth,
|
|
77
81
|
},
|
|
78
82
|
]}
|
|
79
83
|
>
|
package/Input/InputMoney.tsx
CHANGED
|
@@ -4,16 +4,13 @@ import React, {
|
|
|
4
4
|
useContext,
|
|
5
5
|
useEffect,
|
|
6
6
|
useImperativeHandle,
|
|
7
|
-
useLayoutEffect,
|
|
8
7
|
useRef,
|
|
9
8
|
useState,
|
|
10
9
|
} from 'react';
|
|
11
10
|
import {
|
|
12
11
|
NativeSyntheticEvent,
|
|
13
|
-
Platform,
|
|
14
12
|
TextInput,
|
|
15
13
|
TextInputFocusEventData,
|
|
16
|
-
TextInputSelectionChangeEventData,
|
|
17
14
|
TouchableOpacity,
|
|
18
15
|
View,
|
|
19
16
|
} from 'react-native';
|
|
@@ -35,124 +32,9 @@ import {
|
|
|
35
32
|
} from './common';
|
|
36
33
|
import { InputMoneyProps } from './index';
|
|
37
34
|
import styles from './styles';
|
|
35
|
+
import { formatNumberToMoney } from './utils';
|
|
38
36
|
import SystemTextInput from './SystemTextInput';
|
|
39
37
|
|
|
40
|
-
type Selection = { start: number; end: number };
|
|
41
|
-
type Edit = { start: number; end: number; inserted: string };
|
|
42
|
-
|
|
43
|
-
const countDigits = (text: string) => text.replace(/\D/g, '').length;
|
|
44
|
-
|
|
45
|
-
const groupDigits = (digits: string) =>
|
|
46
|
-
digits.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
|
|
47
|
-
|
|
48
|
-
// Caret position right after the `digitIndex`-th digit of `display`.
|
|
49
|
-
const caretFromDigitIndex = (display: string, digitIndex: number) => {
|
|
50
|
-
let count = 0;
|
|
51
|
-
for (let i = 0; i < display.length && count < digitIndex; i++) {
|
|
52
|
-
if (/\d/.test(display[i])) {
|
|
53
|
-
count += 1;
|
|
54
|
-
if (count === digitIndex) return i + 1;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return 0;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
// Finds which range of `old` was replaced to produce `next`. `selection` is
|
|
61
|
-
// the pre-edit selection on iOS and already the post-edit caret on Android,
|
|
62
|
-
// where onSelectionChange fires before onChangeText.
|
|
63
|
-
const detectEdit = (old: string, next: string, selection: Selection): Edit => {
|
|
64
|
-
const { start, end } = selection;
|
|
65
|
-
const removed = old.length - next.length;
|
|
66
|
-
const preEdit: Edit[] = [
|
|
67
|
-
{
|
|
68
|
-
start,
|
|
69
|
-
end,
|
|
70
|
-
inserted: next.slice(start, next.length - (old.length - end)),
|
|
71
|
-
},
|
|
72
|
-
{ start: start - removed, end: start, inserted: '' },
|
|
73
|
-
{ start, end: start + removed, inserted: '' },
|
|
74
|
-
];
|
|
75
|
-
const postEdit: Edit[] = [];
|
|
76
|
-
const tail = next.length - start;
|
|
77
|
-
if (start === end && tail <= old.length) {
|
|
78
|
-
let prefix = 0;
|
|
79
|
-
while (
|
|
80
|
-
prefix < Math.min(start, old.length - tail) &&
|
|
81
|
-
old[prefix] === next[prefix]
|
|
82
|
-
) {
|
|
83
|
-
prefix += 1;
|
|
84
|
-
}
|
|
85
|
-
postEdit.push({
|
|
86
|
-
start: prefix,
|
|
87
|
-
end: old.length - tail,
|
|
88
|
-
inserted: next.slice(prefix, start),
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
const candidates =
|
|
92
|
-
Platform.OS === 'android'
|
|
93
|
-
? [...postEdit, ...preEdit]
|
|
94
|
-
: [...preEdit, ...postEdit];
|
|
95
|
-
const match = candidates.find(
|
|
96
|
-
e =>
|
|
97
|
-
e.start >= 0 &&
|
|
98
|
-
e.end >= e.start &&
|
|
99
|
-
e.end <= old.length &&
|
|
100
|
-
old.slice(0, e.start) + e.inserted + old.slice(e.end) === next,
|
|
101
|
-
);
|
|
102
|
-
if (match) return match;
|
|
103
|
-
|
|
104
|
-
let prefix = 0;
|
|
105
|
-
while (
|
|
106
|
-
prefix < Math.min(old.length, next.length) &&
|
|
107
|
-
old[prefix] === next[prefix]
|
|
108
|
-
) {
|
|
109
|
-
prefix += 1;
|
|
110
|
-
}
|
|
111
|
-
let suffix = 0;
|
|
112
|
-
while (
|
|
113
|
-
suffix < Math.min(old.length, next.length) - prefix &&
|
|
114
|
-
old[old.length - 1 - suffix] === next[next.length - 1 - suffix]
|
|
115
|
-
) {
|
|
116
|
-
suffix += 1;
|
|
117
|
-
}
|
|
118
|
-
return {
|
|
119
|
-
start: prefix,
|
|
120
|
-
end: old.length - suffix,
|
|
121
|
-
inserted: next.slice(prefix, next.length - suffix),
|
|
122
|
-
};
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
// Applies `edit` to the digits of `display`. Separators and currency are never
|
|
126
|
-
// deleted: removing a separator deletes the digit before it instead, removing
|
|
127
|
-
// only the currency leaves the digits untouched.
|
|
128
|
-
const applyEdit = (display: string, edit: Edit, digitLimit: number) => {
|
|
129
|
-
const digits = display.replace(/\D/g, '');
|
|
130
|
-
let left = countDigits(display.slice(0, edit.start));
|
|
131
|
-
let removed = countDigits(display.slice(edit.start, edit.end));
|
|
132
|
-
const inserted = edit.inserted.replace(/\D/g, '');
|
|
133
|
-
if (
|
|
134
|
-
!removed &&
|
|
135
|
-
!inserted &&
|
|
136
|
-
left > 0 &&
|
|
137
|
-
display.slice(edit.start, edit.end).includes('.')
|
|
138
|
-
) {
|
|
139
|
-
left -= 1;
|
|
140
|
-
removed = 1;
|
|
141
|
-
}
|
|
142
|
-
const next = digits.slice(0, left) + inserted + digits.slice(left + removed);
|
|
143
|
-
const trimmed = next.replace(/^0+(?=\d)/, '');
|
|
144
|
-
if ((!removed && !inserted) || trimmed.length > digitLimit) {
|
|
145
|
-
return { digits, caretDigit: left };
|
|
146
|
-
}
|
|
147
|
-
return {
|
|
148
|
-
digits: trimmed,
|
|
149
|
-
caretDigit: Math.max(
|
|
150
|
-
0,
|
|
151
|
-
left + inserted.length - (next.length - trimmed.length),
|
|
152
|
-
),
|
|
153
|
-
};
|
|
154
|
-
};
|
|
155
|
-
|
|
156
38
|
const InputMoney = forwardRef(
|
|
157
39
|
(
|
|
158
40
|
{
|
|
@@ -191,14 +73,7 @@ const InputMoney = forwardRef(
|
|
|
191
73
|
const [focused, setFocused] = useState(false);
|
|
192
74
|
const [displayValue, setDisplayValue] = useState('');
|
|
193
75
|
const [numericValue, setNumericValue] = useState('');
|
|
194
|
-
const [
|
|
195
|
-
const displayRef = useRef('');
|
|
196
|
-
const selectionRef = useRef<Selection>({ start: 0, end: 0 });
|
|
197
|
-
// Caret to push to native once the committed text is rendered.
|
|
198
|
-
const pendingCaretRef = useRef<number | null>(null);
|
|
199
|
-
// Caret the native input reports for the raw, unformatted text. On iOS that
|
|
200
|
-
// event lands after onChangeText and must not override the formatted caret.
|
|
201
|
-
const rawCaretRef = useRef<number | null>(null);
|
|
76
|
+
const [lastDisplayValue, setLastDisplayValue] = useState('');
|
|
202
77
|
const inputRef = useRef<TextInput>(null);
|
|
203
78
|
const componentName = 'InputMoney';
|
|
204
79
|
|
|
@@ -216,36 +91,25 @@ const InputMoney = forwardRef(
|
|
|
216
91
|
|
|
217
92
|
useEffect(() => {
|
|
218
93
|
if (value !== undefined && typeof value === 'string') {
|
|
219
|
-
const cleanValue = value.replace(/\D/g, '')
|
|
94
|
+
const cleanValue = value.replace(/\D/g, '');
|
|
220
95
|
if (cleanValue !== numericValue) {
|
|
221
|
-
|
|
96
|
+
setNumericValue(cleanValue);
|
|
97
|
+
updateDisplayValue(cleanValue);
|
|
222
98
|
}
|
|
223
99
|
}
|
|
224
100
|
}, [value]);
|
|
225
101
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
useLayoutEffect(() => {
|
|
230
|
-
const caret = pendingCaretRef.current;
|
|
231
|
-
if (caret === null) return;
|
|
232
|
-
pendingCaretRef.current = null;
|
|
233
|
-
if (inputRef.current?.isFocused()) {
|
|
234
|
-
inputRef.current.setSelection(caret, caret);
|
|
235
|
-
}
|
|
236
|
-
}, [commitCount]);
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
setLastDisplayValue(displayValue);
|
|
104
|
+
}, [displayValue]);
|
|
237
105
|
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
setCommitCount(count => count + 1);
|
|
246
|
-
setDisplayValue(display);
|
|
247
|
-
setNumericValue(digits);
|
|
248
|
-
return changed;
|
|
106
|
+
const updateDisplayValue = (numeric: string) => {
|
|
107
|
+
if (!numeric) {
|
|
108
|
+
setDisplayValue('');
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const formatted = formatNumberToMoney(Number(numeric));
|
|
112
|
+
setDisplayValue(formatted ? `${formatted}${currency}` : '');
|
|
249
113
|
};
|
|
250
114
|
|
|
251
115
|
const parseInputText = (text: string): string => {
|
|
@@ -255,49 +119,47 @@ const InputMoney = forwardRef(
|
|
|
255
119
|
return textWithoutCurrency.replace(/[^\d]/g, '');
|
|
256
120
|
};
|
|
257
121
|
|
|
122
|
+
const updateNumericValue = (val: string) => {
|
|
123
|
+
let next = val.replace(/[^\d]/g, '');
|
|
124
|
+
if (next.length > digitLimit) next = next.slice(0, digitLimit);
|
|
125
|
+
if (/^\d*$/.test(next)) {
|
|
126
|
+
setNumericValue(next);
|
|
127
|
+
updateDisplayValue(next);
|
|
128
|
+
onChangeText?.(next);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
258
132
|
const onClearText = () => {
|
|
259
133
|
inputRef?.current?.clear();
|
|
260
134
|
inputRef.current?.setNativeProps({ text: '' });
|
|
261
|
-
|
|
135
|
+
setDisplayValue('');
|
|
136
|
+
setNumericValue('');
|
|
262
137
|
onChangeText?.('');
|
|
263
138
|
};
|
|
264
139
|
|
|
265
140
|
const _onChangeText = (text: string) => {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const edit = detectEdit(displayRef.current, text, selectionRef.current);
|
|
271
|
-
rawCaretRef.current = edit.start + edit.inserted.length;
|
|
272
|
-
({ digits, caretDigit } = applyEdit(
|
|
273
|
-
displayRef.current,
|
|
274
|
-
edit,
|
|
275
|
-
digitLimit,
|
|
276
|
-
));
|
|
277
|
-
}
|
|
278
|
-
if (commit(digits, caretDigit)) {
|
|
279
|
-
onChangeText?.(digits);
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
// Keeps the caret out of the currency suffix.
|
|
284
|
-
const _onSelectionChange = (
|
|
285
|
-
e: NativeSyntheticEvent<TextInputSelectionChangeEventData>,
|
|
286
|
-
) => {
|
|
287
|
-
props.onSelectionChange?.(e);
|
|
288
|
-
const { start, end } = e.nativeEvent.selection;
|
|
289
|
-
const rawCaret = rawCaretRef.current;
|
|
290
|
-
rawCaretRef.current = null;
|
|
291
|
-
if (start === end && start === rawCaret) {
|
|
141
|
+
if (!text) {
|
|
142
|
+
setDisplayValue('');
|
|
143
|
+
setNumericValue('');
|
|
144
|
+
onChangeText?.('');
|
|
292
145
|
return;
|
|
293
146
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
147
|
+
if (text.length < lastDisplayValue.length) {
|
|
148
|
+
const lastChar = lastDisplayValue.charAt(lastDisplayValue.length - 1);
|
|
149
|
+
const isRemovingCurrency =
|
|
150
|
+
lastDisplayValue.endsWith(currency) || lastChar === ' ';
|
|
151
|
+
const isRemovingDot = lastChar === '.';
|
|
152
|
+
if (isRemovingCurrency || isRemovingDot) {
|
|
153
|
+
const currentNumericValue = numericValue;
|
|
154
|
+
if (currentNumericValue.length > 0) {
|
|
155
|
+
const newNumericValue = currentNumericValue.slice(0, -1);
|
|
156
|
+
updateNumericValue(newNumericValue);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
300
160
|
}
|
|
161
|
+
const newNumericValue = parseInputText(text);
|
|
162
|
+
updateNumericValue(newNumericValue);
|
|
301
163
|
};
|
|
302
164
|
|
|
303
165
|
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
@@ -312,16 +174,13 @@ const InputMoney = forwardRef(
|
|
|
312
174
|
|
|
313
175
|
const _setText = (text: string) => {
|
|
314
176
|
if (!text) {
|
|
315
|
-
|
|
177
|
+
setDisplayValue('');
|
|
178
|
+
setNumericValue('');
|
|
316
179
|
onChangeText?.('');
|
|
317
180
|
return;
|
|
318
181
|
}
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
.slice(0, digitLimit);
|
|
322
|
-
if (commit(digits, digits.length)) {
|
|
323
|
-
onChangeText?.(digits);
|
|
324
|
-
}
|
|
182
|
+
const newNumericValue = parseInputText(text);
|
|
183
|
+
updateNumericValue(newNumericValue);
|
|
325
184
|
};
|
|
326
185
|
|
|
327
186
|
useImperativeHandle(ref, () => {
|
|
@@ -388,7 +247,6 @@ const InputMoney = forwardRef(
|
|
|
388
247
|
textBreakStrategy="highQuality"
|
|
389
248
|
value={displayValue}
|
|
390
249
|
onChangeText={_onChangeText}
|
|
391
|
-
onSelectionChange={_onSelectionChange}
|
|
392
250
|
onFocus={_onFocus}
|
|
393
251
|
onBlur={_onBlur}
|
|
394
252
|
placeholder={placeholder}
|
package/Layout/Card.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
|
-
import { View, ViewProps } from 'react-native';
|
|
3
|
-
import { useGridSystem
|
|
2
|
+
import { Dimensions, View, ViewProps } from 'react-native';
|
|
3
|
+
import { useGridSystem } from './utils';
|
|
4
4
|
import { GridContextProps } from './types';
|
|
5
5
|
import { GridContext, GridSystem } from './index';
|
|
6
6
|
import { Image } from '../Image';
|
|
@@ -32,8 +32,7 @@ const Card: React.FC<CardProps> = ({
|
|
|
32
32
|
|
|
33
33
|
const gutterSize = 8;
|
|
34
34
|
const margin = 12;
|
|
35
|
-
const
|
|
36
|
-
const widthSection = layout.width;
|
|
35
|
+
const widthSection = Dimensions.get('window').width - margin * 2;
|
|
37
36
|
let sizePerSpan =
|
|
38
37
|
(widthSection - margin * 2 - gutterSize * (numberOfColumns - 1)) /
|
|
39
38
|
numberOfColumns -
|
|
@@ -77,8 +76,7 @@ const Card: React.FC<CardProps> = ({
|
|
|
77
76
|
styles.card,
|
|
78
77
|
{
|
|
79
78
|
width: widthSection,
|
|
80
|
-
|
|
81
|
-
marginRight: layout.marginRight,
|
|
79
|
+
marginHorizontal: margin,
|
|
82
80
|
gap: gutterSize,
|
|
83
81
|
},
|
|
84
82
|
!!backgroundImage && { backgroundColor: undefined },
|
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
AnimatedCompatValue,
|
|
20
20
|
useNormalizedSharedValue,
|
|
21
21
|
} from '../Application/utils';
|
|
22
|
-
import { useHorizontalLayout } from './utils';
|
|
23
22
|
|
|
24
23
|
export interface FloatingButtonProps {
|
|
25
24
|
label?: string;
|
|
@@ -57,7 +56,6 @@ export const FloatingButton: React.FC<FloatingButtonProps> = ({
|
|
|
57
56
|
const lastOffset = useSharedValue(0);
|
|
58
57
|
const lastDirection = useSharedValue<string | null>(null);
|
|
59
58
|
const [showText, setShowText] = useState(true);
|
|
60
|
-
const { marginRight } = useHorizontalLayout(12);
|
|
61
59
|
|
|
62
60
|
useEffect(() => {
|
|
63
61
|
if (!label) return;
|
|
@@ -121,7 +119,7 @@ export const FloatingButton: React.FC<FloatingButtonProps> = ({
|
|
|
121
119
|
style={[
|
|
122
120
|
styles.container,
|
|
123
121
|
{
|
|
124
|
-
right: position === 'right' ?
|
|
122
|
+
right: position === 'right' ? 12 : undefined,
|
|
125
123
|
alignSelf: position === 'center' ? 'center' : 'flex-end',
|
|
126
124
|
bottom,
|
|
127
125
|
},
|
|
@@ -138,7 +136,7 @@ export const FloatingButton: React.FC<FloatingButtonProps> = ({
|
|
|
138
136
|
style={[
|
|
139
137
|
styles.container,
|
|
140
138
|
{
|
|
141
|
-
right: position === 'right' ?
|
|
139
|
+
right: position === 'right' ? 12 : undefined,
|
|
142
140
|
alignSelf: position === 'center' ? 'center' : 'flex-end',
|
|
143
141
|
height: size === 'small' ? 36 : 48,
|
|
144
142
|
backgroundColor: theme.colors.primary,
|
package/Layout/Section.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { useGridSystem
|
|
2
|
+
import { Dimensions, View, ViewProps } from 'react-native';
|
|
3
|
+
import { useGridSystem } from './utils';
|
|
4
4
|
import { GridContextProps } from './types';
|
|
5
5
|
import { GridContext } from './index';
|
|
6
6
|
import { ApplicationContext, MiniAppContext } from '../Context';
|
|
@@ -38,9 +38,14 @@ const Section: React.FC<SectionProps> = ({
|
|
|
38
38
|
const { numberOfColumns } = useGridSystem();
|
|
39
39
|
|
|
40
40
|
const gutterSize = 12;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
let margin = 0;
|
|
42
|
+
if (useMargin) {
|
|
43
|
+
margin = 12;
|
|
44
|
+
}
|
|
45
|
+
let widthSection = Dimensions.get('window').width;
|
|
46
|
+
if (useMargin) {
|
|
47
|
+
widthSection = widthSection - margin * 2;
|
|
48
|
+
}
|
|
44
49
|
|
|
45
50
|
const sizePerSpan =
|
|
46
51
|
(widthSection - gutterSize * (numberOfColumns - 1)) / numberOfColumns -
|
|
@@ -72,8 +77,7 @@ const Section: React.FC<SectionProps> = ({
|
|
|
72
77
|
styles.protectedStyle,
|
|
73
78
|
{
|
|
74
79
|
width: widthSection,
|
|
75
|
-
|
|
76
|
-
marginRight: useMargin ? layout.marginRight : 0,
|
|
80
|
+
marginHorizontal: margin,
|
|
77
81
|
flexDirection: 'row',
|
|
78
82
|
flexWrap: 'wrap',
|
|
79
83
|
gap: gutterSize,
|
package/Layout/utils.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { Fragment, ReactElement } from 'react';
|
|
2
2
|
import { useWindowDimensions } from 'react-native';
|
|
3
|
-
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* validate children type
|
|
@@ -45,18 +44,4 @@ const useGridSystem = () => {
|
|
|
45
44
|
return { numberOfColumns };
|
|
46
45
|
};
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
const useHorizontalLayout = (margin: number) => {
|
|
50
|
-
const { width } = useWindowDimensions();
|
|
51
|
-
const insets = useSafeAreaInsets();
|
|
52
|
-
const marginLeft = margin + insets.left;
|
|
53
|
-
const marginRight = margin + insets.right;
|
|
54
|
-
return {
|
|
55
|
-
marginLeft,
|
|
56
|
-
marginRight,
|
|
57
|
-
width: width - marginLeft - marginRight,
|
|
58
|
-
insets,
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export { useGridSystem, useHorizontalLayout, validateChildren };
|
|
47
|
+
export { useGridSystem, validateChildren };
|