@momo-kits/foundation 0.92.23 → 0.92.24
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 -4
- 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/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/Input/InputOTP.tsx
CHANGED
|
@@ -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;
|
package/Input/InputSearch.tsx
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import React, {
|
|
2
|
-
FC,
|
|
3
2
|
forwardRef,
|
|
4
|
-
ForwardRefRenderFunction,
|
|
5
3
|
useContext,
|
|
6
|
-
useEffect,
|
|
7
4
|
useImperativeHandle,
|
|
8
5
|
useRef,
|
|
9
6
|
useState,
|
|
@@ -18,279 +15,177 @@ import {
|
|
|
18
15
|
import {ApplicationContext, ComponentContext} from '../Application';
|
|
19
16
|
import {Icon} from '../Icon';
|
|
20
17
|
import {Text} from '../Text';
|
|
21
|
-
import {
|
|
18
|
+
import {InputSearchProps} from './index';
|
|
22
19
|
import styles from './styles';
|
|
23
20
|
import {checkTyping} from './utils';
|
|
24
21
|
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
: handleAnimation();
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const showChar = (char?: string) => {
|
|
59
|
-
const handleResetString = () => {
|
|
60
|
-
setTimeout(() => {
|
|
61
|
-
reset();
|
|
62
|
-
}, timeDelayEnd);
|
|
22
|
+
const InputSearch = forwardRef(
|
|
23
|
+
(
|
|
24
|
+
{
|
|
25
|
+
placeholder,
|
|
26
|
+
onFocus,
|
|
27
|
+
onBlur,
|
|
28
|
+
iconColor,
|
|
29
|
+
value,
|
|
30
|
+
onChangeText,
|
|
31
|
+
icon,
|
|
32
|
+
buttonText = 'Hủy',
|
|
33
|
+
showButtonText = true,
|
|
34
|
+
style,
|
|
35
|
+
defaultValue,
|
|
36
|
+
onPressButtonText,
|
|
37
|
+
params,
|
|
38
|
+
hasColorBG = false,
|
|
39
|
+
accessibilityLabel,
|
|
40
|
+
...props
|
|
41
|
+
}: InputSearchProps,
|
|
42
|
+
ref,
|
|
43
|
+
) => {
|
|
44
|
+
const {theme} = useContext(ApplicationContext);
|
|
45
|
+
const [focused, setFocused] = useState(false);
|
|
46
|
+
const [haveValue, setHaveValue] = useState(!!value || !!defaultValue);
|
|
47
|
+
const inputRef = useRef<TextInput | null>(null);
|
|
48
|
+
|
|
49
|
+
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
50
|
+
setFocused(true);
|
|
51
|
+
onFocus?.(e);
|
|
63
52
|
};
|
|
64
53
|
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
text: currentText.current + char,
|
|
69
|
-
});
|
|
70
|
-
currentText.current += char;
|
|
71
|
-
currentCharIndex.current++;
|
|
72
|
-
playAnimation();
|
|
73
|
-
}, timeDelayNextChar);
|
|
54
|
+
const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
55
|
+
setFocused(false);
|
|
56
|
+
onBlur?.(e);
|
|
74
57
|
};
|
|
75
58
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const reset = () => {
|
|
82
|
-
const handleNextString = () => {
|
|
83
|
-
currentIndex.current++;
|
|
84
|
-
playAnimation();
|
|
59
|
+
const onClearText = () => {
|
|
60
|
+
inputRef?.current?.clear();
|
|
61
|
+
_onChangeText('');
|
|
85
62
|
};
|
|
86
63
|
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
text: currentText.current.slice(0, -1),
|
|
91
|
-
});
|
|
92
|
-
currentText.current = currentText.current.slice(0, -1);
|
|
93
|
-
currentCharIndex.current--;
|
|
94
|
-
reset();
|
|
95
|
-
}, timeDelayNextChar);
|
|
64
|
+
const _onChangeText = (text: string) => {
|
|
65
|
+
checkTyping(text, haveValue, setHaveValue);
|
|
66
|
+
onChangeText?.(text);
|
|
96
67
|
};
|
|
97
68
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
autoCorrect={false}
|
|
107
|
-
pointerEvents={'none'}
|
|
108
|
-
numberOfLines={1}
|
|
109
|
-
/>
|
|
110
|
-
);
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
const InputSearch: ForwardRefRenderFunction<InputRef, InputSearchProps> = (
|
|
114
|
-
{
|
|
115
|
-
placeholder,
|
|
116
|
-
onFocus,
|
|
117
|
-
onBlur,
|
|
118
|
-
iconColor,
|
|
119
|
-
value,
|
|
120
|
-
onChangeText,
|
|
121
|
-
icon,
|
|
122
|
-
buttonText = 'Hủy',
|
|
123
|
-
showButtonText = true,
|
|
124
|
-
style,
|
|
125
|
-
defaultValue,
|
|
126
|
-
onPressButtonText,
|
|
127
|
-
params,
|
|
128
|
-
hasColorBG = false,
|
|
129
|
-
accessibilityLabel,
|
|
130
|
-
typingData = [],
|
|
131
|
-
onPress,
|
|
132
|
-
...props
|
|
133
|
-
},
|
|
134
|
-
ref
|
|
135
|
-
) => {
|
|
136
|
-
const {theme} = useContext(ApplicationContext);
|
|
137
|
-
const [focused, setFocused] = useState(false);
|
|
138
|
-
const [haveValue, setHaveValue] = useState(!!value || !!defaultValue);
|
|
139
|
-
const inputRef = useRef<TextInput | null>(null);
|
|
69
|
+
useImperativeHandle(ref, () => {
|
|
70
|
+
return {
|
|
71
|
+
clear: onClearText,
|
|
72
|
+
focus: () => inputRef.current?.focus(),
|
|
73
|
+
blur: () => inputRef.current?.blur(),
|
|
74
|
+
setText: (text: string) => _onChangeText(text),
|
|
75
|
+
};
|
|
76
|
+
});
|
|
140
77
|
|
|
141
|
-
|
|
142
|
-
setFocused(true);
|
|
143
|
-
onFocus?.(e);
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
147
|
-
setFocused(false);
|
|
148
|
-
onBlur?.(e);
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
const onClearText = () => {
|
|
152
|
-
inputRef?.current?.clear();
|
|
153
|
-
_onChangeText('');
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
const _onChangeText = (text: string) => {
|
|
157
|
-
checkTyping(text, haveValue, setHaveValue);
|
|
158
|
-
onChangeText?.(text);
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
useImperativeHandle(ref, () => {
|
|
162
|
-
return {
|
|
163
|
-
clear: onClearText,
|
|
164
|
-
focus: () => inputRef.current?.focus(),
|
|
165
|
-
blur: () => inputRef.current?.blur(),
|
|
166
|
-
setText: (text: string) => _onChangeText(text),
|
|
167
|
-
};
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
const renderInputView = () => {
|
|
171
|
-
if (typingData?.length > 0) {
|
|
78
|
+
const renderInputView = () => {
|
|
172
79
|
return (
|
|
173
|
-
<
|
|
80
|
+
<TextInput
|
|
81
|
+
{...props}
|
|
82
|
+
accessibilityLabel={accessibilityLabel}
|
|
83
|
+
textAlignVertical="center"
|
|
84
|
+
ref={inputRef}
|
|
174
85
|
style={[
|
|
175
86
|
styles.searchInput,
|
|
176
87
|
{
|
|
177
|
-
|
|
88
|
+
color: theme.colors.text.default,
|
|
178
89
|
},
|
|
179
90
|
]}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
91
|
+
value={value}
|
|
92
|
+
onChangeText={_onChangeText}
|
|
93
|
+
onFocus={_onFocus}
|
|
94
|
+
onBlur={_onBlur}
|
|
95
|
+
placeholder={placeholder}
|
|
96
|
+
selectionColor={theme.colors.primary}
|
|
97
|
+
placeholderTextColor={theme.colors.text.hint}
|
|
98
|
+
/>
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const renderIconView = () => {
|
|
103
|
+
return (
|
|
104
|
+
<View
|
|
105
|
+
style={{
|
|
106
|
+
flexDirection: 'row',
|
|
107
|
+
}}>
|
|
108
|
+
{focused && haveValue && (
|
|
109
|
+
<TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
|
|
110
|
+
<Icon
|
|
111
|
+
source="24_navigation_close_circle_full"
|
|
112
|
+
size={16}
|
|
113
|
+
color={theme.colors.text.hint}
|
|
114
|
+
/>
|
|
115
|
+
</TouchableOpacity>
|
|
116
|
+
)}
|
|
117
|
+
{!!icon && (
|
|
118
|
+
<View style={{flexDirection: 'row'}}>
|
|
119
|
+
<View
|
|
120
|
+
style={[
|
|
121
|
+
styles.divider,
|
|
122
|
+
{
|
|
123
|
+
backgroundColor: theme.colors.primary,
|
|
124
|
+
},
|
|
125
|
+
]}
|
|
126
|
+
/>
|
|
127
|
+
<Icon
|
|
128
|
+
color={iconColor}
|
|
129
|
+
source={icon}
|
|
130
|
+
style={styles.iconSearchInput}
|
|
131
|
+
/>
|
|
132
|
+
</View>
|
|
133
|
+
)}
|
|
134
|
+
</View>
|
|
184
135
|
);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
let inputState = 'empty';
|
|
139
|
+
|
|
140
|
+
if (focused) {
|
|
141
|
+
inputState = 'focus';
|
|
185
142
|
}
|
|
186
143
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
styles.searchInput,
|
|
195
|
-
{
|
|
196
|
-
color: theme.colors.text.default,
|
|
197
|
-
},
|
|
198
|
-
]}
|
|
199
|
-
value={value}
|
|
200
|
-
onChangeText={_onChangeText}
|
|
201
|
-
onFocus={_onFocus}
|
|
202
|
-
onBlur={_onBlur}
|
|
203
|
-
placeholder={placeholder}
|
|
204
|
-
selectionColor={theme.colors.primary}
|
|
205
|
-
placeholderTextColor={theme.colors.text.hint}
|
|
206
|
-
/>
|
|
207
|
-
);
|
|
208
|
-
};
|
|
144
|
+
if (value && value?.length > 0) {
|
|
145
|
+
inputState = 'filled';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const backgroundColor = hasColorBG
|
|
149
|
+
? theme.colors.background.default
|
|
150
|
+
: theme.colors.background.surface;
|
|
209
151
|
|
|
210
|
-
const renderIconView = () => {
|
|
211
152
|
return (
|
|
212
|
-
<
|
|
213
|
-
|
|
214
|
-
|
|
153
|
+
<ComponentContext.Provider
|
|
154
|
+
value={{
|
|
155
|
+
componentName: 'InputSearch',
|
|
156
|
+
params,
|
|
157
|
+
state: inputState,
|
|
158
|
+
componentId: accessibilityLabel,
|
|
215
159
|
}}>
|
|
216
|
-
{
|
|
217
|
-
<
|
|
160
|
+
<View style={[style, styles.searchInputContainer]}>
|
|
161
|
+
<View
|
|
162
|
+
style={[
|
|
163
|
+
styles.searchInputWrapper,
|
|
164
|
+
{
|
|
165
|
+
backgroundColor,
|
|
166
|
+
},
|
|
167
|
+
]}>
|
|
218
168
|
<Icon
|
|
219
|
-
source=
|
|
220
|
-
size={
|
|
169
|
+
source={'navigation_search'}
|
|
170
|
+
size={24}
|
|
221
171
|
color={theme.colors.text.hint}
|
|
222
172
|
/>
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
{!!icon && (
|
|
226
|
-
<View style={{flexDirection: 'row'}}>
|
|
227
|
-
<View
|
|
228
|
-
style={[
|
|
229
|
-
styles.divider,
|
|
230
|
-
{
|
|
231
|
-
backgroundColor: theme.colors.primary,
|
|
232
|
-
},
|
|
233
|
-
]}
|
|
234
|
-
/>
|
|
235
|
-
<Icon
|
|
236
|
-
color={iconColor}
|
|
237
|
-
source={icon}
|
|
238
|
-
style={styles.iconSearchInput}
|
|
239
|
-
/>
|
|
173
|
+
{renderInputView()}
|
|
174
|
+
{renderIconView()}
|
|
240
175
|
</View>
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (value && value?.length > 0) {
|
|
253
|
-
inputState = 'filled';
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const backgroundColor = hasColorBG
|
|
257
|
-
? theme.colors.background.default
|
|
258
|
-
: theme.colors.background.surface;
|
|
259
|
-
|
|
260
|
-
return (
|
|
261
|
-
<ComponentContext.Provider
|
|
262
|
-
value={{
|
|
263
|
-
componentName: 'InputSearch',
|
|
264
|
-
params,
|
|
265
|
-
state: inputState,
|
|
266
|
-
componentId: accessibilityLabel,
|
|
267
|
-
}}>
|
|
268
|
-
<View style={[style, styles.searchInputContainer]}>
|
|
269
|
-
<View
|
|
270
|
-
style={[
|
|
271
|
-
styles.searchInputWrapper,
|
|
272
|
-
{
|
|
273
|
-
backgroundColor,
|
|
274
|
-
},
|
|
275
|
-
]}>
|
|
276
|
-
<Icon
|
|
277
|
-
source={'navigation_search'}
|
|
278
|
-
size={24}
|
|
279
|
-
color={theme.colors.text.hint}
|
|
280
|
-
/>
|
|
281
|
-
{renderInputView()}
|
|
282
|
-
{renderIconView()}
|
|
176
|
+
{showButtonText && (
|
|
177
|
+
<TouchableOpacity onPress={onPressButtonText}>
|
|
178
|
+
<Text
|
|
179
|
+
typography={'action_default_bold'}
|
|
180
|
+
style={styles.textButton}>
|
|
181
|
+
{buttonText}
|
|
182
|
+
</Text>
|
|
183
|
+
</TouchableOpacity>
|
|
184
|
+
)}
|
|
283
185
|
</View>
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
</Text>
|
|
289
|
-
</TouchableOpacity>
|
|
290
|
-
)}
|
|
291
|
-
</View>
|
|
292
|
-
</ComponentContext.Provider>
|
|
293
|
-
);
|
|
294
|
-
};
|
|
186
|
+
</ComponentContext.Provider>
|
|
187
|
+
);
|
|
188
|
+
},
|
|
189
|
+
);
|
|
295
190
|
|
|
296
|
-
export default
|
|
191
|
+
export default InputSearch;
|
package/Input/index.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {TextInputProps, ViewStyle} from 'react-native';
|
|
2
2
|
import Input from './Input';
|
|
3
3
|
import InputDropDown from './InputDropDown';
|
|
4
4
|
import InputMoney from './InputMoney';
|
|
@@ -143,17 +143,6 @@ export interface InputSearchProps extends TextInputProps {
|
|
|
143
143
|
* Optional. Represents the style of the InputSearch component.
|
|
144
144
|
*/
|
|
145
145
|
params?: any;
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Optional. Represents the data for typing animation.
|
|
149
|
-
*/
|
|
150
|
-
typingData?: string[];
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Optional. Represents the callback function to be called when the search button is pressed.
|
|
154
|
-
* @param e
|
|
155
|
-
*/
|
|
156
|
-
onPress?: (e: GestureResponderEvent) => void;
|
|
157
146
|
}
|
|
158
147
|
|
|
159
148
|
export interface InputMoneyProps extends Omit<InputProps, 'placeholder'> {}
|
|
@@ -293,11 +282,4 @@ export interface InputDropDownProps extends InputProps {
|
|
|
293
282
|
style?: ViewStyle | ViewStyle[];
|
|
294
283
|
}
|
|
295
284
|
|
|
296
|
-
export type InputRef = {
|
|
297
|
-
clear: () => void;
|
|
298
|
-
focus: () => void | undefined;
|
|
299
|
-
blur: () => void | undefined;
|
|
300
|
-
setText: (text: string) => void;
|
|
301
|
-
};
|
|
302
|
-
|
|
303
285
|
export {Input, InputDropDown, InputMoney, InputOTP, InputSearch, InputTextArea};
|
package/Input/styles.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {StyleSheet} from 'react-native';
|
|
2
|
+
import {Radius, Spacing} from '../Consts';
|
|
3
3
|
import {scaleSize} from '../Text';
|
|
4
4
|
|
|
5
5
|
export default StyleSheet.create({
|
|
@@ -133,14 +133,7 @@ export default StyleSheet.create({
|
|
|
133
133
|
paddingVertical: Spacing.S,
|
|
134
134
|
fontWeight: 'bold',
|
|
135
135
|
},
|
|
136
|
-
|
|
137
|
-
color: Colors.black_12,
|
|
138
|
-
fontSize: scaleSize(12),
|
|
139
|
-
height: Platform.select({
|
|
140
|
-
android: 60,
|
|
141
|
-
ios: 36,
|
|
142
|
-
}),
|
|
143
|
-
},
|
|
136
|
+
|
|
144
137
|
//OTP
|
|
145
138
|
otpWrapper: {
|
|
146
139
|
width: '100%',
|
|
@@ -84,8 +84,8 @@ export const FloatingButton: React.FC<FloatingButtonProps> = ({
|
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
return () => {
|
|
87
|
-
if (listener
|
|
88
|
-
animatedValue?.removeListener(listener
|
|
87
|
+
if (listener) {
|
|
88
|
+
animatedValue?.removeListener(listener);
|
|
89
89
|
}
|
|
90
90
|
};
|
|
91
91
|
}, [label, widthAnimated]);
|
package/Layout/GridSystem.tsx
CHANGED
|
@@ -53,7 +53,7 @@ const GridSystem: React.FC<any> = ({
|
|
|
53
53
|
{list.map((_, index) => {
|
|
54
54
|
return (
|
|
55
55
|
<View style={{flexDirection: 'row'}} key={index.toString()}>
|
|
56
|
-
{index !==
|
|
56
|
+
{index !== 0 && <View style={{width: grid.gutterSize}} />}
|
|
57
57
|
<View
|
|
58
58
|
key={`Grid${index.toString()}`}
|
|
59
59
|
pointerEvents="none"
|