react-native-yastools 1.0.1 → 1.0.2

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 (46) hide show
  1. package/README.md +55 -140
  2. package/dist/assets/imgs/close.png +0 -0
  3. package/dist/components/BottomTabs/__tests__/BottomTabs.test.js +69 -0
  4. package/dist/components/BottomTabs/index.d.ts +5 -0
  5. package/dist/components/BottomTabs/index.js +82 -0
  6. package/dist/components/BottomTabs/styles.d.ts +43 -0
  7. package/dist/components/BottomTabs/styles.js +44 -0
  8. package/dist/components/BottomTabs/type.d.ts +53 -0
  9. package/dist/components/BottomTabs/type.js +1 -0
  10. package/dist/components/Button/__tests__/Button.test.d.ts +1 -0
  11. package/dist/components/Button/__tests__/{YasButton.test.js → Button.test.js} +9 -9
  12. package/dist/components/Button/index.d.ts +3 -3
  13. package/dist/components/Button/index.js +30 -20
  14. package/dist/components/Button/styles.d.ts +1 -1
  15. package/dist/components/Button/styles.js +1 -1
  16. package/dist/components/Button/type.d.ts +7 -3
  17. package/dist/components/ConfirmationPopUp/__tests__/ConfirmationPopUp.test.d.ts +1 -0
  18. package/dist/components/ConfirmationPopUp/__tests__/ConfirmationPopUp.test.js +62 -0
  19. package/dist/components/ConfirmationPopUp/index.d.ts +15 -0
  20. package/dist/components/ConfirmationPopUp/index.js +41 -0
  21. package/dist/components/ConfirmationPopUp/styles.d.ts +79 -0
  22. package/dist/components/ConfirmationPopUp/styles.js +81 -0
  23. package/dist/index.d.ts +7 -3
  24. package/dist/index.js +5 -3
  25. package/dist/interactions.d.ts +8 -0
  26. package/dist/interactions.js +47 -0
  27. package/dist/theme/index.d.ts +3 -1
  28. package/dist/theme/index.js +3 -1
  29. package/package.json +6 -4
  30. package/src/assets/imgs/close.png +0 -0
  31. package/src/components/BottomTabs/__tests__/BottomTabs.test.tsx +142 -0
  32. package/src/components/BottomTabs/index.tsx +134 -0
  33. package/src/components/BottomTabs/styles.ts +45 -0
  34. package/src/components/BottomTabs/type.ts +61 -0
  35. package/src/components/Button/__tests__/{YasButton.test.tsx → Button.test.tsx} +9 -9
  36. package/src/components/Button/index.tsx +39 -21
  37. package/src/components/Button/styles.ts +1 -1
  38. package/src/components/Button/type.ts +7 -3
  39. package/src/components/ConfirmationPopUp/__tests__/ConfirmationPopUp.test.tsx +125 -0
  40. package/src/components/ConfirmationPopUp/index.tsx +103 -0
  41. package/src/components/ConfirmationPopUp/styles.ts +83 -0
  42. package/src/declarations.d.ts +5 -0
  43. package/src/index.ts +11 -4
  44. package/src/interactions.ts +58 -0
  45. package/src/theme/index.ts +3 -1
  46. /package/dist/components/{Button/__tests__/YasButton.test.d.ts → BottomTabs/__tests__/BottomTabs.test.d.ts} +0 -0
@@ -0,0 +1,142 @@
1
+ import React from 'react';
2
+ import { render, fireEvent } from '@testing-library/react-native';
3
+ import BottomTabs from '../index';
4
+ import { TabItem } from '../type';
5
+
6
+ // Mock navigation
7
+ const mockNavigate = jest.fn();
8
+ const mockNavigation = {
9
+ navigate: mockNavigate,
10
+ };
11
+
12
+ // Sample tabs for testing
13
+ const sampleTabs: TabItem[] = [
14
+ { name: 'Home', route: 'Home', icon: { uri: 'https://example.com/home.png' } },
15
+ { name: 'Search', route: 'Search', icon: { uri: 'https://example.com/search.png' } },
16
+ { name: 'Profile', route: 'Profile', icon: { uri: 'https://example.com/profile.png' } },
17
+ ];
18
+
19
+ describe('BottomTabs', () => {
20
+ beforeEach(() => {
21
+ jest.clearAllMocks();
22
+ });
23
+
24
+ it('renders all tabs correctly', () => {
25
+ const { getByText } = render(
26
+ <BottomTabs
27
+ navigation={mockNavigation}
28
+ currentRoute="Home"
29
+ tabs={sampleTabs}
30
+ />
31
+ );
32
+
33
+ expect(getByText('Home')).toBeTruthy();
34
+ expect(getByText('Search')).toBeTruthy();
35
+ expect(getByText('Profile')).toBeTruthy();
36
+ });
37
+
38
+ it('navigates to correct route when tab is pressed', () => {
39
+ const { getByText } = render(
40
+ <BottomTabs
41
+ navigation={mockNavigation}
42
+ currentRoute="Home"
43
+ tabs={sampleTabs}
44
+ />
45
+ );
46
+
47
+ fireEvent.press(getByText('Search'));
48
+ expect(mockNavigate).toHaveBeenCalledWith('Search');
49
+ });
50
+
51
+ it('calls onTabPress callback when provided', () => {
52
+ const onTabPressMock = jest.fn();
53
+ const { getByText } = render(
54
+ <BottomTabs
55
+ navigation={mockNavigation}
56
+ currentRoute="Home"
57
+ tabs={sampleTabs}
58
+ onTabPress={onTabPressMock}
59
+ />
60
+ );
61
+
62
+ fireEvent.press(getByText('Profile'));
63
+ expect(onTabPressMock).toHaveBeenCalledWith('Profile');
64
+ expect(mockNavigate).toHaveBeenCalledWith('Profile');
65
+ });
66
+
67
+ it('does not navigate when tab is disabled', () => {
68
+ const disabledTabs: TabItem[] = [
69
+ { name: 'Home', route: 'Home', icon: { uri: 'https://example.com/home.png' } },
70
+ { name: 'Search', route: 'Search', icon: { uri: 'https://example.com/search.png' }, disabled: true },
71
+ ];
72
+
73
+ const { getByText } = render(
74
+ <BottomTabs
75
+ navigation={mockNavigation}
76
+ currentRoute="Home"
77
+ tabs={disabledTabs}
78
+ />
79
+ );
80
+
81
+ fireEvent.press(getByText('Search'));
82
+ expect(mockNavigate).not.toHaveBeenCalled();
83
+ });
84
+
85
+ it('applies custom testID to tabs', () => {
86
+ const tabsWithTestId: TabItem[] = [
87
+ { name: 'Home', route: 'Home', icon: { uri: 'https://example.com/home.png' }, testID: 'home-tab' },
88
+ ];
89
+
90
+ const { getByTestId } = render(
91
+ <BottomTabs
92
+ navigation={mockNavigation}
93
+ currentRoute="Home"
94
+ tabs={tabsWithTestId}
95
+ />
96
+ );
97
+
98
+ expect(getByTestId('home-tab')).toBeTruthy();
99
+ });
100
+
101
+ it('renders with container testID', () => {
102
+ const { getByTestId } = render(
103
+ <BottomTabs
104
+ navigation={mockNavigation}
105
+ currentRoute="Home"
106
+ tabs={sampleTabs}
107
+ testID="bottom-tabs"
108
+ />
109
+ );
110
+
111
+ expect(getByTestId('bottom-tabs')).toBeTruthy();
112
+ });
113
+
114
+ it('renders empty when no tabs are provided', () => {
115
+ const { queryByText } = render(
116
+ <BottomTabs
117
+ navigation={mockNavigation}
118
+ currentRoute="Home"
119
+ tabs={[]}
120
+ />
121
+ );
122
+
123
+ expect(queryByText('Home')).toBeNull();
124
+ });
125
+
126
+ it('handles single tab correctly', () => {
127
+ const singleTab: TabItem[] = [
128
+ { name: 'Home', route: 'Home', icon: { uri: 'https://example.com/home.png' } },
129
+ ];
130
+
131
+ const { getByText, queryByText } = render(
132
+ <BottomTabs
133
+ navigation={mockNavigation}
134
+ currentRoute="Home"
135
+ tabs={singleTab}
136
+ />
137
+ );
138
+
139
+ expect(getByText('Home')).toBeTruthy();
140
+ expect(queryByText('Search')).toBeNull();
141
+ });
142
+ });
@@ -0,0 +1,134 @@
1
+ import React, { memo, useCallback } from 'react';
2
+ import { TouchableOpacity, Image, View, Text } from 'react-native';
3
+ import styles from './styles';
4
+ import { COLORS } from '../../theme';
5
+ import { BottomTabsProps, TabItem } from './type';
6
+
7
+ export type { BottomTabsProps, TabItem };
8
+
9
+ /**
10
+ * BottomTabs - A customizable bottom navigation component for React Native
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * import { BottomTabs } from 'react-native-yastools';
15
+ *
16
+ * const tabs = [
17
+ * { name: 'Home', route: 'Home', icon: require('./icons/home.png') },
18
+ * { name: 'Search', route: 'Search', icon: require('./icons/search.png') },
19
+ * { name: 'Profile', route: 'Profile', icon: require('./icons/profile.png') },
20
+ * ];
21
+ *
22
+ * <BottomTabs
23
+ * navigation={navigation}
24
+ * currentRoute="Home"
25
+ * tabs={tabs}
26
+ * activeColor="#007AFF"
27
+ * />
28
+ * ```
29
+ */
30
+ const BottomTabs: React.FC<BottomTabsProps> = ({
31
+ navigation,
32
+ currentRoute,
33
+ tabs,
34
+ containerStyle,
35
+ tabItemStyle,
36
+ activeTabItemStyle,
37
+ textStyle,
38
+ activeTextStyle,
39
+ iconStyle,
40
+ activeIconStyle,
41
+ activeColor,
42
+ inactiveColor,
43
+ onTabPress,
44
+ activeOpacity = 0.8,
45
+ testID,
46
+ }) => {
47
+ const handleTabPress = useCallback(
48
+ (tab: TabItem) => {
49
+ if (tab.disabled) return;
50
+
51
+ // Call custom callback if provided
52
+ if (onTabPress) {
53
+ onTabPress(tab.route);
54
+ }
55
+
56
+ // Navigate to the route
57
+ navigation.navigate(tab.route);
58
+ },
59
+ [navigation, onTabPress]
60
+ );
61
+
62
+ const renderTab = useCallback(
63
+ (tab: TabItem, index: number) => {
64
+ const isActive = currentRoute === tab.route;
65
+
66
+ // Determine icon tint color
67
+ const iconTintColor = isActive
68
+ ? activeColor || COLORS.primary
69
+ : inactiveColor || COLORS.black;
70
+
71
+ // Determine text color
72
+ const textColor = isActive
73
+ ? activeColor || COLORS.primary
74
+ : inactiveColor || COLORS.black;
75
+
76
+ // Determine which icon to use
77
+ const iconSource = isActive && tab.activeIcon ? tab.activeIcon : tab.icon;
78
+
79
+ // Merge styles based on active state
80
+ const tabStyle = isActive
81
+ ? [styles.navItemActive, tabItemStyle, activeTabItemStyle]
82
+ : [styles.navItem, tabItemStyle];
83
+
84
+ const tabTextStyle = isActive
85
+ ? [styles.navTextActive, { color: textColor }, textStyle, activeTextStyle]
86
+ : [styles.navText, { color: textColor }, textStyle];
87
+
88
+ const tabIconStyle = isActive
89
+ ? [styles.navIconActive, { tintColor: iconTintColor }, iconStyle, activeIconStyle]
90
+ : [styles.navIcon, { tintColor: iconTintColor }, iconStyle];
91
+
92
+ return (
93
+ <TouchableOpacity
94
+ key={`tab-${tab.route}-${index}`}
95
+ style={tabStyle}
96
+ activeOpacity={activeOpacity}
97
+ onPress={() => handleTabPress(tab)}
98
+ disabled={tab.disabled}
99
+ testID={tab.testID || `tab-${tab.route}`}
100
+ >
101
+ <Image
102
+ resizeMode="contain"
103
+ source={iconSource}
104
+ style={tabIconStyle}
105
+ />
106
+ <Text style={tabTextStyle} numberOfLines={1}>
107
+ {tab.name}
108
+ </Text>
109
+ </TouchableOpacity>
110
+ );
111
+ },
112
+ [
113
+ currentRoute,
114
+ activeColor,
115
+ inactiveColor,
116
+ tabItemStyle,
117
+ activeTabItemStyle,
118
+ textStyle,
119
+ activeTextStyle,
120
+ iconStyle,
121
+ activeIconStyle,
122
+ activeOpacity,
123
+ handleTabPress,
124
+ ]
125
+ );
126
+
127
+ return (
128
+ <View style={[styles.BottomTabsContainer, containerStyle]} testID={testID}>
129
+ {tabs.map(renderTab)}
130
+ </View>
131
+ );
132
+ };
133
+
134
+ export default memo(BottomTabs);
@@ -0,0 +1,45 @@
1
+ import { StyleSheet, Platform } from 'react-native';
2
+ import COLORS, { FONT_SIZES, FONT_FAMILY } from '../../theme';
3
+
4
+ /**
5
+ * Default styles for the BottomTabs component
6
+ * Uses standard React Native StyleSheet for maximum compatibility
7
+ */
8
+ export default StyleSheet.create({
9
+ BottomTabsContainer: {
10
+ width: '100%',
11
+ flexDirection: 'row',
12
+ backgroundColor: COLORS.white,
13
+ paddingBottom: Platform.OS === 'ios' ? 10 : 0,
14
+ },
15
+ navItem: {
16
+ flex: 1,
17
+ justifyContent: 'flex-end',
18
+ alignItems: 'center',
19
+ paddingVertical: 8,
20
+ },
21
+ navItemActive: {
22
+ flex: 1,
23
+ justifyContent: 'flex-end',
24
+ alignItems: 'center',
25
+ paddingVertical: 8,
26
+ },
27
+ navText: {
28
+ fontFamily: FONT_FAMILY.InterRegular,
29
+ fontSize: FONT_SIZES.f11,
30
+ marginTop: 5,
31
+ },
32
+ navTextActive: {
33
+ fontFamily: FONT_FAMILY.InterRegular,
34
+ fontSize: FONT_SIZES.f11,
35
+ marginTop: 5,
36
+ },
37
+ navIcon: {
38
+ width: 20,
39
+ height: 20,
40
+ },
41
+ navIconActive: {
42
+ width: 20,
43
+ height: 20,
44
+ },
45
+ });
@@ -0,0 +1,61 @@
1
+ import {
2
+ StyleProp,
3
+ ViewStyle,
4
+ TextStyle,
5
+ ImageSourcePropType,
6
+ ImageStyle,
7
+ } from 'react-native';
8
+
9
+ /**
10
+ * Represents a single tab item in the BottomTabs component
11
+ */
12
+ export interface TabItem {
13
+ /** Display name shown below the icon */
14
+ name: string;
15
+ /** Route name to navigate to when tab is pressed */
16
+ route: string;
17
+ /** Icon to display for the tab (required) */
18
+ icon: ImageSourcePropType;
19
+ /** Optional: Active state icon (if different from default) */
20
+ activeIcon?: ImageSourcePropType;
21
+ /** Optional: Whether this tab is disabled */
22
+ disabled?: boolean;
23
+ /** Optional: Test ID for testing purposes */
24
+ testID?: string;
25
+ }
26
+
27
+ /**
28
+ * Props for the BottomTabs component
29
+ */
30
+ export interface BottomTabsProps {
31
+ /** Navigation object from React Navigation */
32
+ navigation: any;
33
+ /** Currently active route name */
34
+ currentRoute: string;
35
+ /** Array of tab items to render */
36
+ tabs: TabItem[];
37
+ /** Optional: Custom styles for the container */
38
+ containerStyle?: StyleProp<ViewStyle>;
39
+ /** Optional: Custom styles for tab items */
40
+ tabItemStyle?: StyleProp<ViewStyle>;
41
+ /** Optional: Custom styles for active tab items */
42
+ activeTabItemStyle?: StyleProp<ViewStyle>;
43
+ /** Optional: Custom styles for tab text */
44
+ textStyle?: StyleProp<TextStyle>;
45
+ /** Optional: Custom styles for active tab text */
46
+ activeTextStyle?: StyleProp<TextStyle>;
47
+ /** Optional: Custom styles for tab icons */
48
+ iconStyle?: StyleProp<ImageStyle>;
49
+ /** Optional: Custom styles for active tab icons */
50
+ activeIconStyle?: StyleProp<ImageStyle>;
51
+ /** Optional: Active color for icons and text (overrides theme) */
52
+ activeColor?: string;
53
+ /** Optional: Inactive color for icons and text (overrides theme) */
54
+ inactiveColor?: string;
55
+ /** Optional: Callback when a tab is pressed (receives route name) */
56
+ onTabPress?: (route: string) => void;
57
+ /** Optional: Active opacity when pressing tabs (default: 0.8) */
58
+ activeOpacity?: number;
59
+ /** Test ID for testing purposes */
60
+ testID?: string;
61
+ }
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
2
  import { render, fireEvent } from '@testing-library/react-native';
3
- import YasButton from '../index';
3
+ import Button from '../index';
4
4
 
5
- describe('YasButton', () => {
5
+ describe('Button', () => {
6
6
  it('renders correctly with text', () => {
7
7
  const { getByText } = render(
8
- <YasButton text="Press Me" onPress={() => {}} />
8
+ <Button text="Press Me" onPress={() => {}} />
9
9
  );
10
10
  expect(getByText('Press Me')).toBeTruthy();
11
11
  });
@@ -13,7 +13,7 @@ describe('YasButton', () => {
13
13
  it('calls onPress when pressed', () => {
14
14
  const onPressMock = jest.fn();
15
15
  const { getByText } = render(
16
- <YasButton text="Press Me" onPress={onPressMock} />
16
+ <Button text="Press Me" onPress={onPressMock} />
17
17
  );
18
18
 
19
19
  fireEvent.press(getByText('Press Me'));
@@ -23,7 +23,7 @@ describe('YasButton', () => {
23
23
  it('does not call onPress when disabled', () => {
24
24
  const onPressMock = jest.fn();
25
25
  const { getByText } = render(
26
- <YasButton text="Press Me" onPress={onPressMock} disabled />
26
+ <Button text="Press Me" onPress={onPressMock} disabled />
27
27
  );
28
28
 
29
29
  fireEvent.press(getByText('Press Me'));
@@ -32,7 +32,7 @@ describe('YasButton', () => {
32
32
 
33
33
  it('shows loading indicator when fetching', () => {
34
34
  const { queryByText, getByTestId } = render(
35
- <YasButton text="Press Me" onPress={() => {}} fetching testID="button" />
35
+ <Button text="Press Me" onPress={() => {}} fetching testID="button" />
36
36
  );
37
37
 
38
38
  expect(queryByText('Press Me')).toBeNull();
@@ -42,7 +42,7 @@ describe('YasButton', () => {
42
42
  jest.useFakeTimers();
43
43
  const onPressMock = jest.fn();
44
44
  const { getByText } = render(
45
- <YasButton text="Press Me" onPress={onPressMock} debounceTime={1000} />
45
+ <Button text="Press Me" onPress={onPressMock} debounceTime={1000} />
46
46
  );
47
47
 
48
48
  const button = getByText('Press Me');
@@ -62,7 +62,7 @@ describe('YasButton', () => {
62
62
 
63
63
  it('applies custom primary color', () => {
64
64
  const { getByTestId } = render(
65
- <YasButton
65
+ <Button
66
66
  text="Press Me"
67
67
  onPress={() => {}}
68
68
  primaryColor="#FF0000"
@@ -80,7 +80,7 @@ describe('YasButton', () => {
80
80
  it('renders without text when only icon is provided', () => {
81
81
  const mockIcon = { uri: 'https://example.com/icon.png' };
82
82
  const { queryByText } = render(
83
- <YasButton onPress={() => {}} icon={mockIcon} />
83
+ <Button onPress={() => {}} icon={mockIcon} />
84
84
  );
85
85
 
86
86
  expect(queryByText('Press Me')).toBeNull();
@@ -1,4 +1,4 @@
1
- import React, { memo, useRef } from 'react';
1
+ import React, { memo, useMemo, useRef } from 'react';
2
2
  import {
3
3
  TouchableOpacity,
4
4
  Text,
@@ -7,34 +7,36 @@ import {
7
7
  ViewStyle,
8
8
  View,
9
9
  Image,
10
+ Animated,
10
11
  } from 'react-native';
11
12
 
12
13
  // Internal styles and theme
13
14
  import styles from './styles';
14
15
  import COLORS from '../../theme';
15
- import { YasButtonProps } from './type';
16
+ import { ButtonProps } from './type';
17
+ import { preventMultiPress, usePressScale } from '../../interactions';
16
18
 
17
- export type { YasButtonProps };
19
+ export type { ButtonProps };
18
20
 
21
+ const AnimatedTouchableOpacity = Animated.createAnimatedComponent(TouchableOpacity);
19
22
 
20
23
  /**
21
- * YasButton - A customizable button component for React Native
24
+ * Button - A customizable button component for React Native
22
25
  *
23
26
  * @example
24
27
  * ```tsx
25
- * import { YasButton } from 'react-native-yastools';
28
+ * import { Button } from 'react-native-yastools';
26
29
  *
27
- * <YasButton
30
+ * <Button
28
31
  * text="Click Me"
29
32
  * onPress={() => console.log('Pressed!')}
30
33
  * primaryColor="#FF6B6B"
31
34
  * />
32
35
  * ```
33
36
  */
34
- const YasButton: React.FC<YasButtonProps> = ({
37
+ const Button: React.FC<ButtonProps> = ({
35
38
  onPress,
36
39
  additionalStyle,
37
- additonalStyle, // Support legacy prop name
38
40
  disabled,
39
41
  fetching,
40
42
  text,
@@ -47,18 +49,28 @@ const YasButton: React.FC<YasButtonProps> = ({
47
49
  debounceTime = 1000,
48
50
  activeOpacity = 0.8,
49
51
  testID,
52
+ animateScale,
50
53
  }) => {
51
- const lastPressTime = useRef(0);
54
+ // Keep latest onPress in a ref to avoid resetting the debouncer closure when onPress changes
55
+ const onPressRef = useRef(onPress);
56
+ onPressRef.current = onPress;
52
57
 
53
- const handlePress = () => {
54
- // Prevent multiple clicks with configurable debounce
55
- const now = Date.now();
56
- if (now - lastPressTime.current < debounceTime) {
57
- return;
58
+ // Setup interactions
59
+ // Default to 1 (no scaling) if not provided.
60
+ const { scaleAnim, handlePressIn, handlePressOut } = usePressScale(animateScale ?? 1);
61
+
62
+ // Check if animation is requested
63
+ const isAnimated = animateScale !== undefined;
64
+
65
+ // Memoize the handler so existing debounce timer isn't lost on re-renders
66
+ const handlePress = useMemo(() => {
67
+ // If debounceTime is 0 or less, just call directly (or use logic if user wants default protection)
68
+ // Assuming if user passes 0 they want NO debounce. But existing code defaulted to 1000.
69
+ if (debounceTime > 0) {
70
+ return preventMultiPress(() => onPressRef.current && onPressRef.current(), debounceTime);
58
71
  }
59
- lastPressTime.current = now;
60
- onPress();
61
- };
72
+ return () => onPressRef.current && onPressRef.current();
73
+ }, [debounceTime]);
62
74
 
63
75
  // Determine container style based on state
64
76
  const containerStyle: StyleProp<ViewStyle> = [
@@ -67,14 +79,20 @@ const YasButton: React.FC<YasButtonProps> = ({
67
79
  !disabled && primaryColor && { backgroundColor: primaryColor },
68
80
  disabled && disabledColor && { backgroundColor: disabledColor },
69
81
  // Support both prop names for backwards compatibility
70
- additionalStyle || additonalStyle,
82
+ additionalStyle
71
83
  ];
72
84
 
85
+ // Combine animated style
86
+ const animatedStyle = isAnimated ? { transform: [{ scale: scaleAnim }] } : undefined;
87
+
73
88
  return (
74
- <TouchableOpacity
89
+ <AnimatedTouchableOpacity
75
90
  onPress={handlePress}
91
+ onPressIn={isAnimated ? handlePressIn : undefined}
92
+ onPressOut={isAnimated ? handlePressOut : undefined}
76
93
  activeOpacity={activeOpacity}
77
94
  disabled={disabled || fetching}
95
+ style={[animatedStyle]}
78
96
  >
79
97
  <View style={containerStyle} testID={testID}>
80
98
  {fetching ? (
@@ -89,8 +107,8 @@ const YasButton: React.FC<YasButtonProps> = ({
89
107
  </>
90
108
  )}
91
109
  </View>
92
- </TouchableOpacity>
110
+ </AnimatedTouchableOpacity>
93
111
  );
94
112
  };
95
113
 
96
- export default memo(YasButton);
114
+ export default memo(Button);
@@ -2,7 +2,7 @@ import { StyleSheet } from 'react-native';
2
2
  import COLORS, { FONT_SIZES } from '../../theme';
3
3
 
4
4
  /**
5
- * Default styles for the YasButton component
5
+ * Default styles for the Button component
6
6
  * Uses standard React Native StyleSheet for maximum compatibility
7
7
  */
8
8
  export default StyleSheet.create({
@@ -6,13 +6,11 @@ import {
6
6
  ImageStyle,
7
7
  } from "react-native";
8
8
 
9
- export interface YasButtonProps {
9
+ export interface ButtonProps {
10
10
  /** Callback function when button is pressed */
11
11
  onPress: () => void;
12
12
  /** Additional styles to apply to the button container */
13
13
  additionalStyle?: StyleProp<ViewStyle>;
14
- /** @deprecated Use additionalStyle instead */
15
- additonalStyle?: StyleProp<ViewStyle>;
16
14
  /** Whether the button is disabled */
17
15
  disabled?: boolean;
18
16
  /** Whether to show loading indicator */
@@ -37,4 +35,10 @@ export interface YasButtonProps {
37
35
  activeOpacity?: number;
38
36
  /** Test ID for testing purposes */
39
37
  testID?: string;
38
+ /**
39
+ * Scale value to animate to when pressed (0 to 1).
40
+ * If undefined, no scaling animation occurs.
41
+ * @example 0.95
42
+ */
43
+ animateScale?: number;
40
44
  }