@momo-kits/foundation 0.167.1-beta.5 → 0.167.1-duo-test.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.
Files changed (47) hide show
  1. package/Application/BottomSheet.tsx +115 -14
  2. package/Application/BottomTab/BottomTabBar.tsx +6 -3
  3. package/Application/BottomTab/DuoBarCompression.tsx +135 -0
  4. package/Application/BottomTab/DuoTabBar.tsx +462 -0
  5. package/Application/BottomTab/index.tsx +150 -134
  6. package/Application/Components/DuoGlassBackground.tsx +179 -0
  7. package/Application/Components/DuoQuickReturnHeader.tsx +42 -0
  8. package/Application/Components/HeaderExtendHeader.tsx +75 -28
  9. package/Application/Components/HeaderLeft.tsx +38 -0
  10. package/Application/Components/HeaderRight.tsx +142 -9
  11. package/Application/Components/HeaderTitle.tsx +67 -17
  12. package/Application/Components/OptionalGlassView.ts +11 -0
  13. package/Application/Components/OptionalScrollObserver.ts +12 -0
  14. package/Application/Components/SearchHeader.tsx +22 -15
  15. package/Application/Components/SideBarButton.tsx +139 -0
  16. package/Application/ModalScreen.tsx +16 -2
  17. package/Application/NavigationContainer.tsx +36 -45
  18. package/Application/Navigator.ts +1 -3
  19. package/Application/StackScreen.tsx +63 -9
  20. package/Application/WidgetContainer.tsx +9 -7
  21. package/Application/device.ts +29 -0
  22. package/Application/types.ts +27 -1
  23. package/Application/utils.tsx +255 -7
  24. package/Consts/index.ts +0 -1
  25. package/Consts/theme.ts +5 -6
  26. package/Input/Input.tsx +3 -4
  27. package/Input/InputMoney.tsx +31 -51
  28. package/Input/InputPhoneNumber.tsx +3 -4
  29. package/Input/InputSearch.tsx +3 -4
  30. package/Input/InputTextArea.tsx +3 -4
  31. package/Layout/Card.tsx +8 -26
  32. package/Layout/FloatingButton.tsx +3 -3
  33. package/Layout/Item.tsx +1 -10
  34. package/Layout/ReservedRegions.tsx +47 -0
  35. package/Layout/Screen.tsx +199 -52
  36. package/Layout/Section.tsx +5 -18
  37. package/Layout/index.ts +4 -4
  38. package/Layout/styles.ts +5 -0
  39. package/Layout/utils.ts +465 -5
  40. package/Popup/PopupNotify.tsx +33 -22
  41. package/Popup/PopupPromotion.tsx +20 -8
  42. package/Popup/utils.ts +32 -0
  43. package/Text/index.tsx +2 -11
  44. package/Text/utils.ts +1 -2
  45. package/package.json +3 -2
  46. package/Consts/designSystemFont.ts +0 -38
  47. package/Layout/GridSystem.tsx +0 -137
@@ -117,7 +117,6 @@ export type Context = {
117
117
  [key: string]: any;
118
118
  theme: Theme;
119
119
  navigator?: NavigatorProps;
120
- showGrid?: boolean;
121
120
  translate?: (data: string | { vi: string; en: string }) => string;
122
121
  };
123
122
 
@@ -258,6 +257,11 @@ export interface HeaderBackProps extends NavigationButtonProps {
258
257
  preventBack?: PopupNotifyProps;
259
258
  onPressLeftHeader?: () => void;
260
259
  onBackHandler?: (goBack: () => void) => void;
260
+ /**
261
+ * Optional. If `true`, the button floats into the iPhone Duo side bar while the
262
+ * device shows one. Set when the button is rendered by the navigation header.
263
+ */
264
+ floating?: boolean;
261
265
  }
262
266
 
263
267
  export type HeaderBackgroundProps = {
@@ -329,6 +333,11 @@ export type BottomTabProps = {
329
333
  blur?: (e: EventArg<'blur', false, unknown>) => void;
330
334
  };
331
335
  floatingButton?: FloatingButtonProps;
336
+ /**
337
+ * iPhone Duo: when the side bar can't hold both bars, which one starts compressed;
338
+ * tapping the compressed one swaps them. Defaults to 'toolbar'
339
+ */
340
+ compressionBehavior?: 'toolbar' | 'tabBar';
332
341
  };
333
342
 
334
343
  export type FloatingButtonProps = {
@@ -352,3 +361,20 @@ export interface SearchHeaderProps extends InputSearchProps {
352
361
  renderButtons?: () => ReactNode;
353
362
  hiddenBack?: boolean;
354
363
  }
364
+
365
+ export type HeaderScrollOptions = {
366
+ /**
367
+ * Navigation of the screen whose header follows the scroll.
368
+ */
369
+ navigation?: Navigation;
370
+ useShadowHeader?: boolean;
371
+ gradientColor?: string;
372
+ headerBackground?: string;
373
+ };
374
+
375
+ export type ScrollChange = {
376
+ y: number;
377
+ contentHeight: number;
378
+ viewportHeight: number;
379
+ phase: 'scroll' | 'dragEnd' | 'momentumEnd' | 'takeOver';
380
+ };
@@ -16,12 +16,28 @@ import type {
16
16
  StackCardInterpolationProps,
17
17
  } from '@react-navigation/stack';
18
18
  import type { NavigationState, PartialState } from '@react-navigation/native';
19
- import type { HeaderTitleProps, NavigationOptions } from './types';
19
+ import type {
20
+ HeaderScrollOptions,
21
+ ScrollChange,
22
+ HeaderTitleProps,
23
+ NavigationOptions,
24
+ } from './types';
20
25
  import { ApplicationContext } from '../Context';
21
26
  import { Colors, Spacing } from '../Consts';
22
- import { Animated, AppState, NativeModules, Platform } from 'react-native';
27
+ import {
28
+ Animated,
29
+ AppState,
30
+ NativeModules,
31
+ Platform,
32
+ } from 'react-native';
33
+ import { useHeaderHeight } from '@react-navigation/elements';
23
34
  import type { SharedValue } from 'react-native-reanimated';
24
- import { useSharedValue } from 'react-native-reanimated';
35
+ import {
36
+ useAnimatedReaction,
37
+ useAnimatedStyle,
38
+ useSharedValue,
39
+ withTiming,
40
+ } from 'react-native-reanimated';
25
41
  import {
26
42
  MiniAppContext,
27
43
  ScreenContext,
@@ -31,6 +47,12 @@ import { HeaderTitle, TitleCustom } from './Components/HeaderTitle';
31
47
  import { HeaderBackground } from './Components/HeaderBackground';
32
48
  import { HeaderLeft } from './Components/HeaderLeft';
33
49
  import { HeaderRight } from './Components/HeaderRight';
50
+ import {
51
+ DuoGlassBackground,
52
+ DuoScrollGradient,
53
+ } from './Components/DuoGlassBackground';
54
+ import { DuoQuickReturnHeader } from './Components/DuoQuickReturnHeader';
55
+ import { useScreenLayout } from '../Layout/utils';
34
56
 
35
57
  const forStackTransitionWithOverlay = (
36
58
  props: StackCardInterpolationProps,
@@ -73,8 +95,8 @@ const getStackOptions = (): StackNavigationOptions => {
73
95
  left: Spacing.S,
74
96
  },
75
97
  headerBackground: (props: any) => <HeaderBackground {...props} />,
76
- headerLeft: (props: any) => <HeaderLeft {...props} />,
77
- headerRight: (props: any) => <HeaderRight {...props} />,
98
+ headerLeft: (props: any) => <HeaderLeft {...props} floating />,
99
+ headerRight: (props: any) => <HeaderRight {...props} floating />,
78
100
  headerTintColor: Colors.black_17,
79
101
  gestureEnabled: Platform.OS === 'ios',
80
102
  ...TransitionPresets.SlideFromRightIOS,
@@ -129,6 +151,7 @@ const getOptions = (
129
151
  preventBack={params.preventBack}
130
152
  onPressLeftHeader={params.onPressLeftHeader}
131
153
  onBackHandler={params.onBackHandler}
154
+ floating
132
155
  />
133
156
  );
134
157
  if (params.hiddenBack) {
@@ -167,7 +190,9 @@ const getOptions = (
167
190
  ...options,
168
191
  ...{
169
192
  headerRight: (props: any) => {
170
- return <HeaderRight {...props} headerRight={params.headerRight} />;
193
+ return (
194
+ <HeaderRight {...props} headerRight={params.headerRight} floating />
195
+ );
171
196
  },
172
197
  },
173
198
  };
@@ -401,7 +426,9 @@ const getSwipeGestureValue = (
401
426
  };
402
427
 
403
428
  const readAnimatedValue = (node: unknown, fallback: number): number => {
404
- const value = (node as { __getValue?: () => unknown } | undefined)?.__getValue?.();
429
+ const value = (
430
+ node as { __getValue?: () => unknown } | undefined
431
+ )?.__getValue?.();
405
432
  return typeof value === 'number' ? value : fallback;
406
433
  };
407
434
 
@@ -475,6 +502,224 @@ const SwipeBackHaptic = () => {
475
502
  return null;
476
503
  };
477
504
 
505
+ const isWhiteListDesignSystem = (context: any): boolean =>
506
+ context?.designSystemConfig?.isWhiteListDesignSystem === true;
507
+
508
+ /**
509
+ * iPhone Duo: the header leaves with the content and returns on a reverse scroll
510
+ */
511
+ const useDuoQuickReturn = (
512
+ scrollY: SharedValue<number>,
513
+ enabled: boolean,
514
+ heightHeader: number,
515
+ ) => {
516
+ const headerHide = useSharedValue(0);
517
+ const lastScrollY = useSharedValue(0);
518
+
519
+ useAnimatedReaction(
520
+ () => scrollY.value,
521
+ y => {
522
+ const delta = y - lastScrollY.value;
523
+ lastScrollY.value = y;
524
+ if (!enabled || y <= 0) {
525
+ headerHide.value = 0;
526
+ return;
527
+ }
528
+ headerHide.value = Math.min(
529
+ Math.max(headerHide.value + delta, 0),
530
+ heightHeader,
531
+ );
532
+ },
533
+ [enabled, heightHeader],
534
+ );
535
+
536
+ const quickReturnOptions: StackNavigationOptions = useMemo(
537
+ () =>
538
+ enabled
539
+ ? {
540
+ header: (props: any) => (
541
+ <DuoQuickReturnHeader {...props} offset={headerHide} />
542
+ ),
543
+ }
544
+ : { header: undefined },
545
+ [enabled, headerHide],
546
+ );
547
+
548
+ /**
549
+ * a half-shown quick return header settles fully in or out
550
+ */
551
+ const snap = useCallback(
552
+ (offsetY: number) => {
553
+ const hide = headerHide.value;
554
+ // above heightHeader the header still sits on the content
555
+ if (
556
+ !enabled ||
557
+ offsetY < heightHeader ||
558
+ hide <= 0 ||
559
+ hide >= heightHeader
560
+ ) {
561
+ return;
562
+ }
563
+ headerHide.value = withTiming(
564
+ hide > heightHeader / 2 ? heightHeader : 0,
565
+ { duration: 200 },
566
+ );
567
+ },
568
+ [enabled, heightHeader, headerHide],
569
+ );
570
+
571
+ /**
572
+ * moves the reference point without counting it as a scroll
573
+ */
574
+ const resync = useCallback(
575
+ (y: number) => {
576
+ lastScrollY.value = y;
577
+ },
578
+ [lastScrollY],
579
+ );
580
+
581
+ return { headerHide, quickReturnOptions, snap, resync };
582
+ };
583
+
584
+ /**
585
+ * Header scroll state for screens that render their own scroll views instead of
586
+ * `<Screen scrollable>`, such as one ScrollView per TabView page.
587
+ */
588
+ /**
589
+ * header scroll state fed by any scroll source; off, it leaves the header and content alone
590
+ */
591
+ const useHeaderScrollState = (
592
+ {
593
+ navigation,
594
+ useShadowHeader = true,
595
+ gradientColor,
596
+ headerBackground,
597
+ }: HeaderScrollOptions,
598
+ enabled: boolean,
599
+ ) => {
600
+ const layout = useScreenLayout();
601
+ const heightHeader = useHeaderHeight();
602
+ const scrollY = useSharedValue(0);
603
+ const hasSideBar = !!layout.sideBar;
604
+ const duo = enabled && hasSideBar;
605
+
606
+ const viewportHeight = useRef<number | undefined>(undefined);
607
+ const { headerHide, quickReturnOptions, snap, resync } = useDuoQuickReturn(
608
+ scrollY,
609
+ duo,
610
+ heightHeader,
611
+ );
612
+
613
+ useEffect(() => {
614
+ if (!enabled) {
615
+ return;
616
+ }
617
+ const options: StackNavigationOptions = hasSideBar
618
+ ? {
619
+ ...quickReturnOptions,
620
+ headerTransparent: true,
621
+ headerTintColor: Colors.black_17,
622
+ headerShown: true,
623
+ headerBackground: () => (
624
+ <DuoGlassBackground animatedValue={scrollY} />
625
+ ),
626
+ headerTitle: (props: any) => <HeaderTitle {...props} />,
627
+ }
628
+ : {
629
+ header: undefined,
630
+ headerTransparent: false,
631
+ headerTintColor: Colors.black_17,
632
+ headerShown: true,
633
+ headerBackground: (props: any) => (
634
+ <HeaderBackground
635
+ {...props}
636
+ animatedValue={scrollY}
637
+ useShadowHeader={useShadowHeader}
638
+ headerBackground={headerBackground}
639
+ gradientColor={gradientColor}
640
+ />
641
+ ),
642
+ headerTitle: (props: any) => <HeaderTitle {...props} />,
643
+ };
644
+
645
+ navigation?.instance?.setOptions(options);
646
+ }, [
647
+ enabled,
648
+ navigation?.instance,
649
+ hasSideBar,
650
+ quickReturnOptions,
651
+ scrollY,
652
+ useShadowHeader,
653
+ headerBackground,
654
+ gradientColor,
655
+ ]);
656
+
657
+ const setScrollOffset = useCallback(
658
+ (y: number) => {
659
+ resync(y);
660
+ scrollY.value = y;
661
+ },
662
+ [scrollY, resync],
663
+ );
664
+
665
+ const onScrollChange = useCallback(
666
+ ({
667
+ y: offsetY,
668
+ contentHeight,
669
+ viewportHeight: height,
670
+ phase,
671
+ }: ScrollChange) => {
672
+ // the bottom bounce is not a reverse scroll
673
+ const maxY = Math.max(contentHeight - height, 0);
674
+ const y = Math.min(offsetY, maxY);
675
+ if (phase === 'takeOver') {
676
+ viewportHeight.current = height;
677
+ setScrollOffset(y);
678
+ return;
679
+ }
680
+ if (phase !== 'scroll') {
681
+ snap(offsetY);
682
+ return;
683
+ }
684
+ // the quick return resizes the viewport; pinned at the bottom, the offset
685
+ // iOS clamps to the new size is not a scroll
686
+ const resized = height !== viewportHeight.current;
687
+ viewportHeight.current = height;
688
+ if (resized && offsetY >= maxY - 1) {
689
+ resync(y);
690
+ }
691
+ scrollY.value = y;
692
+ },
693
+ [scrollY, snap, resync, setScrollOffset],
694
+ );
695
+
696
+ const { insetLeft, insetRight } = layout;
697
+ const contentStyle = useAnimatedStyle(
698
+ () =>
699
+ enabled
700
+ ? {
701
+ paddingLeft: insetLeft,
702
+ paddingRight: insetRight,
703
+ paddingTop: hasSideBar ? heightHeader - headerHide.value : 0,
704
+ }
705
+ : { paddingLeft: 0, paddingRight: 0, paddingTop: 0 },
706
+ [enabled, hasSideBar, heightHeader, insetLeft, insetRight],
707
+ );
708
+
709
+ const background = duo ? (
710
+ <DuoScrollGradient
711
+ animatedValue={scrollY}
712
+ gradientColor={gradientColor}
713
+ headerBackground={headerBackground}
714
+ heightHeader={heightHeader}
715
+ followScroll
716
+ />
717
+ ) : null;
718
+
719
+ return { scrollY, onScrollChange, setScrollOffset, background, contentStyle };
720
+ };
721
+
722
+
478
723
  export {
479
724
  getStackOptions,
480
725
  getModalOptions,
@@ -486,5 +731,8 @@ export {
486
731
  useAppState,
487
732
  useNativeCanGoBack,
488
733
  useNormalizedSharedValue,
734
+ useDuoQuickReturn,
735
+ useHeaderScrollState,
489
736
  SwipeBackHaptic,
737
+ isWhiteListDesignSystem,
490
738
  };
package/Consts/index.ts CHANGED
@@ -2,4 +2,3 @@ export * from './colors+spacing+radius';
2
2
  export * from './theme';
3
3
  export * from './styles';
4
4
  export const GRIDVIEW = false;
5
- export * from './designSystemFont';
package/Consts/theme.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type {Context, Theme} from '../Application/types';
2
- import {Colors} from './colors+spacing+radius';
1
+ import type { Context, Theme } from '../Application/types';
2
+ import { Colors } from './colors+spacing+radius';
3
3
 
4
4
  const defaultTheme: Theme = {
5
5
  dark: false,
@@ -51,7 +51,7 @@ const defaultTheme: Theme = {
51
51
  container: Colors.blue_08,
52
52
  },
53
53
  },
54
- font: 'MomoTrustSans',
54
+ font: 'SFProText',
55
55
  assets: {},
56
56
  };
57
57
 
@@ -105,17 +105,16 @@ const defaultDarkTheme: Theme = {
105
105
  container: Colors.blue_08,
106
106
  },
107
107
  },
108
- font: 'MomoTrustSans',
108
+ font: 'SFProText',
109
109
  assets: {},
110
110
  };
111
111
 
112
112
  const defaultContext: Context = {
113
113
  theme: defaultTheme,
114
114
  navigator: undefined,
115
- showGrid: false,
116
115
  translate: () => {
117
116
  return '';
118
117
  },
119
118
  };
120
119
 
121
- export {defaultContext, defaultTheme, defaultDarkTheme};
120
+ export { defaultContext, defaultTheme, defaultDarkTheme };
package/Input/Input.tsx CHANGED
@@ -6,9 +6,8 @@ import React, {
6
6
  useState,
7
7
  } from 'react';
8
8
  import {
9
- NativeSyntheticEvent,
10
9
  TextInput,
11
- TextInputFocusEventData,
10
+ TextInputFocusEvent,
12
11
  TouchableOpacity,
13
12
  View,
14
13
  } from 'react-native';
@@ -102,12 +101,12 @@ const Input = forwardRef(
102
101
  onChangeText?.(text);
103
102
  };
104
103
 
105
- const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
104
+ const _onFocus = (e: TextInputFocusEvent) => {
106
105
  setFocused(true);
107
106
  onFocus?.(e);
108
107
  };
109
108
 
110
- const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
109
+ const _onBlur = (e: TextInputFocusEvent) => {
111
110
  setFocused(false);
112
111
  onBlur?.(e);
113
112
  };
@@ -9,11 +9,9 @@ import React, {
9
9
  useState,
10
10
  } from 'react';
11
11
  import {
12
- NativeSyntheticEvent,
13
- Platform,
14
12
  TextInput,
15
- TextInputFocusEventData,
16
- TextInputSelectionChangeEventData,
13
+ TextInputFocusEvent,
14
+ TextInputSelectionChangeEvent,
17
15
  TouchableOpacity,
18
16
  View,
19
17
  } from 'react-native';
@@ -57,13 +55,10 @@ const caretFromDigitIndex = (display: string, digitIndex: number) => {
57
55
  return 0;
58
56
  };
59
57
 
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
58
  const detectEdit = (old: string, next: string, selection: Selection): Edit => {
64
59
  const { start, end } = selection;
65
60
  const removed = old.length - next.length;
66
- const preEdit: Edit[] = [
61
+ const candidates: Edit[] = [
67
62
  {
68
63
  start,
69
64
  end,
@@ -72,26 +67,6 @@ const detectEdit = (old: string, next: string, selection: Selection): Edit => {
72
67
  { start: start - removed, end: start, inserted: '' },
73
68
  { start, end: start + removed, inserted: '' },
74
69
  ];
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
70
  const match = candidates.find(
96
71
  e =>
97
72
  e.start >= 0 &&
@@ -196,9 +171,8 @@ const InputMoney = forwardRef(
196
171
  const selectionRef = useRef<Selection>({ start: 0, end: 0 });
197
172
  // Caret to push to native once the committed text is rendered.
198
173
  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);
174
+ const pendingSelectionRef = useRef<Selection | null>(null);
175
+ const editingRef = useRef(false);
202
176
  const inputRef = useRef<TextInput>(null);
203
177
  const componentName = 'InputMoney';
204
178
 
@@ -265,10 +239,13 @@ const InputMoney = forwardRef(
265
239
  const _onChangeText = (text: string) => {
266
240
  let digits = '';
267
241
  let caretDigit = 0;
268
- rawCaretRef.current = 0;
242
+ pendingSelectionRef.current = null;
243
+ editingRef.current = true;
244
+ setTimeout(() => {
245
+ editingRef.current = false;
246
+ });
269
247
  if (text) {
270
248
  const edit = detectEdit(displayRef.current, text, selectionRef.current);
271
- rawCaretRef.current = edit.start + edit.inserted.length;
272
249
  ({ digits, caretDigit } = applyEdit(
273
250
  displayRef.current,
274
251
  edit,
@@ -281,31 +258,34 @@ const InputMoney = forwardRef(
281
258
  };
282
259
 
283
260
  // Keeps the caret out of the currency suffix.
284
- const _onSelectionChange = (
285
- e: NativeSyntheticEvent<TextInputSelectionChangeEventData>,
286
- ) => {
261
+ const _onSelectionChange = (e: TextInputSelectionChangeEvent) => {
287
262
  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) {
292
- return;
293
- }
294
- const display = displayRef.current;
295
- const max = display ? display.length - currency.length : 0;
296
- const clamped = { start: Math.min(start, max), end: Math.min(end, max) };
297
- selectionRef.current = clamped;
298
- if (clamped.start !== start || clamped.end !== end) {
299
- inputRef.current?.setSelection(clamped.start, clamped.end);
300
- }
263
+ if (editingRef.current) return;
264
+ const selection = e.nativeEvent.selection;
265
+ pendingSelectionRef.current = selection;
266
+ setTimeout(() => {
267
+ if (pendingSelectionRef.current !== selection) return;
268
+ pendingSelectionRef.current = null;
269
+ const { start, end } = selection;
270
+ const display = displayRef.current;
271
+ const max = display ? display.length - currency.length : 0;
272
+ const clamped = {
273
+ start: Math.min(start, max),
274
+ end: Math.min(end, max),
275
+ };
276
+ selectionRef.current = clamped;
277
+ if (clamped.start !== start || clamped.end !== end) {
278
+ inputRef.current?.setSelection(clamped.start, clamped.end);
279
+ }
280
+ });
301
281
  };
302
282
 
303
- const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
283
+ const _onFocus = (e: TextInputFocusEvent) => {
304
284
  setFocused(true);
305
285
  onFocus?.(e);
306
286
  };
307
287
 
308
- const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
288
+ const _onBlur = (e: TextInputFocusEvent) => {
309
289
  setFocused(false);
310
290
  onBlur?.(e);
311
291
  };
@@ -6,10 +6,9 @@ import React, {
6
6
  useState,
7
7
  } from 'react';
8
8
  import {
9
- NativeSyntheticEvent,
10
9
  StyleSheet,
11
10
  TextInput,
12
- TextInputFocusEventData,
11
+ TextInputFocusEvent,
13
12
  TouchableOpacity,
14
13
  View,
15
14
  } from 'react-native';
@@ -93,12 +92,12 @@ const InputPhoneNumber = forwardRef(
93
92
  onChangeText?.(text);
94
93
  };
95
94
 
96
- const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
95
+ const _onFocus = (e: TextInputFocusEvent) => {
97
96
  setFocused(true);
98
97
  onFocus?.(e);
99
98
  };
100
99
 
101
- const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
100
+ const _onBlur = (e: TextInputFocusEvent) => {
102
101
  setFocused(false);
103
102
  onBlur?.(e);
104
103
  };
@@ -10,9 +10,8 @@ import React, {
10
10
  useState,
11
11
  } from 'react';
12
12
  import {
13
- NativeSyntheticEvent,
14
13
  TextInput,
15
- TextInputFocusEventData,
14
+ TextInputFocusEvent,
16
15
  TouchableOpacity,
17
16
  View,
18
17
  } from 'react-native';
@@ -166,12 +165,12 @@ const InputSearch: ForwardRefRenderFunction<InputRef, InputSearchProps> = (
166
165
  props.accessibilityLabel,
167
166
  );
168
167
 
169
- const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
168
+ const _onFocus = (e: TextInputFocusEvent) => {
170
169
  setFocused(true);
171
170
  onFocus?.(e);
172
171
  };
173
172
 
174
- const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
173
+ const _onBlur = (e: TextInputFocusEvent) => {
175
174
  setFocused(false);
176
175
  onBlur?.(e);
177
176
  };
@@ -7,9 +7,8 @@ import React, {
7
7
  useState,
8
8
  } from 'react';
9
9
  import {
10
- NativeSyntheticEvent,
11
10
  TextInput,
12
- TextInputFocusEventData,
11
+ TextInputFocusEvent,
13
12
  TouchableOpacity,
14
13
  View,
15
14
  } from 'react-native';
@@ -79,12 +78,12 @@ const InputTextArea = forwardRef(
79
78
  setInputValue(text);
80
79
  };
81
80
 
82
- const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
81
+ const _onFocus = (e: TextInputFocusEvent) => {
83
82
  setFocused(true);
84
83
  onFocus?.(e);
85
84
  };
86
85
 
87
- const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
86
+ const _onBlur = (e: TextInputFocusEvent) => {
88
87
  setFocused(false);
89
88
  onBlur?.(e);
90
89
  };