react-native-yastools 1.0.2 → 1.0.4
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/README.md +51 -18
- package/dist/assets/imgs/whiteCheck.png +0 -0
- package/dist/components/Button/index.js +1 -1
- package/dist/components/CheckBox/__tests__/CheckBox.test.d.ts +1 -0
- package/dist/components/CheckBox/__tests__/CheckBox.test.js +40 -0
- package/dist/components/CheckBox/index.d.ts +4 -0
- package/dist/components/CheckBox/index.js +32 -0
- package/dist/components/CheckBox/styles.d.ts +48 -0
- package/dist/components/CheckBox/styles.js +50 -0
- package/dist/components/CheckBox/type.d.ts +47 -0
- package/dist/components/CheckBox/type.js +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/package.json +6 -2
- package/src/assets/imgs/whiteCheck.png +0 -0
- package/src/components/Button/index.tsx +3 -3
- package/src/components/CheckBox/__tests__/CheckBox.test.tsx +61 -0
- package/src/components/CheckBox/index.tsx +64 -0
- package/src/components/CheckBox/styles.ts +54 -0
- package/src/components/CheckBox/type.ts +58 -0
- package/src/index.ts +5 -2
- /package/dist/{interactions.d.ts → utils/interactions.d.ts} +0 -0
- /package/dist/{interactions.js → utils/interactions.js} +0 -0
- /package/src/{interactions.ts → utils/interactions.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# React Native Yastools
|
|
2
2
|
|
|
3
3
|
A collection of **premium, high-performance** UI components and utilities for React Native. Built for speed, aesthetics, and developer experience.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* **Themable:** Fully customizable design system.
|
|
8
|
+
* **Performant:** Optimized for high frame rates and smooth interactions.
|
|
9
|
+
* **Native Feel:** Haptic feedback and native animations baked in.
|
|
10
|
+
* **Plug & Play:** Zero-config components ready to drop into your app.
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Installation
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
17
|
npm install react-native-yastools
|
|
@@ -23,9 +23,9 @@ yarn add react-native-yastools
|
|
|
23
23
|
|
|
24
24
|
---
|
|
25
25
|
|
|
26
|
-
##
|
|
26
|
+
## Components
|
|
27
27
|
|
|
28
|
-
###
|
|
28
|
+
### Button
|
|
29
29
|
A highly versatile button with built-in loading states, scaling animations, and debounce protection.
|
|
30
30
|
|
|
31
31
|
```tsx
|
|
@@ -35,13 +35,13 @@ import { Button } from 'react-native-yastools';
|
|
|
35
35
|
text="Confirm Order"
|
|
36
36
|
onPress={handleCheckout}
|
|
37
37
|
primaryColor="#007AFF"
|
|
38
|
-
animateScale={0.95} //
|
|
39
|
-
debounceTime={500} //
|
|
38
|
+
animateScale={0.95} // Smooth press animation
|
|
39
|
+
debounceTime={500} // Prevents double-taps
|
|
40
40
|
fetching={isLoading}
|
|
41
41
|
/>
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
###
|
|
44
|
+
### ConfirmationPopUp
|
|
45
45
|
A beautiful, promise-based confirmation dialog.
|
|
46
46
|
|
|
47
47
|
```tsx
|
|
@@ -59,9 +59,43 @@ import { ConfirmationPopUp } from 'react-native-yastools';
|
|
|
59
59
|
/>
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
### CheckBox
|
|
63
|
+
A customizable checkbox with label support and flexible styling.
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import { CheckBox } from 'react-native-yastools';
|
|
67
|
+
|
|
68
|
+
<CheckBox
|
|
69
|
+
checked={isChecked}
|
|
70
|
+
onToggle={(val) => setIsChecked(val)}
|
|
71
|
+
label="I agree to the Terms"
|
|
72
|
+
activeColor="#00E676"
|
|
73
|
+
disabled={false}
|
|
74
|
+
/>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### BottomTabs
|
|
78
|
+
A customizable bottom navigation bar to easily manage app routing.
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { BottomTabs } from 'react-native-yastools';
|
|
82
|
+
|
|
83
|
+
const tabs = [
|
|
84
|
+
{ name: 'Home', route: 'Home', icon: require('./assets/home.png') },
|
|
85
|
+
{ name: 'Profile', route: 'Profile', icon: require('./assets/profile.png') },
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
<BottomTabs
|
|
89
|
+
navigation={navigation} // React Navigation prop
|
|
90
|
+
currentRoute="Home"
|
|
91
|
+
tabs={tabs}
|
|
92
|
+
activeColor="#007AFF"
|
|
93
|
+
/>
|
|
94
|
+
```
|
|
95
|
+
|
|
62
96
|
---
|
|
63
97
|
|
|
64
|
-
##
|
|
98
|
+
## Theme & Utils
|
|
65
99
|
|
|
66
100
|
The library exposes its core theme and interaction helpers:
|
|
67
101
|
|
|
@@ -77,12 +111,11 @@ const safeHandler = preventMultiPress(() => console.log('Safe!'), 1000);
|
|
|
77
111
|
|
|
78
112
|
---
|
|
79
113
|
|
|
80
|
-
|
|
114
|
+
Built by [**Yassine Ben Zriouil**](https://ybz.vercel.app/).
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
## Contributing
|
|
81
118
|
|
|
82
119
|
1. Clone the repo
|
|
83
120
|
2. Run `npm install`
|
|
84
121
|
3. Test changes with `npm run local-publish`
|
|
85
|
-
|
|
86
|
-
---
|
|
87
|
-
|
|
88
|
-
Built with ❤️ by **Yassine Ben Zriouil**.
|
|
Binary file
|
|
@@ -3,7 +3,7 @@ import { TouchableOpacity, Text, ActivityIndicator, View, Image, Animated, } fro
|
|
|
3
3
|
// Internal styles and theme
|
|
4
4
|
import styles from './styles';
|
|
5
5
|
import COLORS from '../../theme';
|
|
6
|
-
import { preventMultiPress, usePressScale } from '../../interactions';
|
|
6
|
+
import { preventMultiPress, usePressScale } from '../../utils/interactions';
|
|
7
7
|
const AnimatedTouchableOpacity = Animated.createAnimatedComponent(TouchableOpacity);
|
|
8
8
|
/**
|
|
9
9
|
* Button - A customizable button component for React Native
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, fireEvent } from '@testing-library/react-native';
|
|
3
|
+
import CheckBox from '../index';
|
|
4
|
+
describe('CheckBox', () => {
|
|
5
|
+
it('renders correctly', () => {
|
|
6
|
+
const { getByTestId } = render(<CheckBox checked={false} onToggle={() => { }} testID="checkbox"/>);
|
|
7
|
+
expect(getByTestId('checkbox')).toBeTruthy();
|
|
8
|
+
});
|
|
9
|
+
it('displays label when provided', () => {
|
|
10
|
+
const { getByText } = render(<CheckBox checked={false} onToggle={() => { }} label="Accept Terms"/>);
|
|
11
|
+
expect(getByText('Accept Terms')).toBeTruthy();
|
|
12
|
+
});
|
|
13
|
+
it('calls onToggle when pressed', () => {
|
|
14
|
+
const onToggleMock = jest.fn();
|
|
15
|
+
const { getByTestId } = render(<CheckBox checked={false} onToggle={onToggleMock} testID="checkbox"/>);
|
|
16
|
+
fireEvent.press(getByTestId('checkbox'));
|
|
17
|
+
expect(onToggleMock).toHaveBeenCalledWith(true);
|
|
18
|
+
expect(onToggleMock).toHaveBeenCalledTimes(1);
|
|
19
|
+
});
|
|
20
|
+
it('calls onToggle with false when checked is true', () => {
|
|
21
|
+
const onToggleMock = jest.fn();
|
|
22
|
+
const { getByTestId } = render(<CheckBox checked={true} onToggle={onToggleMock} testID="checkbox"/>);
|
|
23
|
+
fireEvent.press(getByTestId('checkbox'));
|
|
24
|
+
expect(onToggleMock).toHaveBeenCalledWith(false);
|
|
25
|
+
});
|
|
26
|
+
it('does not call onToggle when disabled', () => {
|
|
27
|
+
const onToggleMock = jest.fn();
|
|
28
|
+
const { getByTestId } = render(<CheckBox checked={false} onToggle={onToggleMock} disabled testID="checkbox"/>);
|
|
29
|
+
fireEvent.press(getByTestId('checkbox'));
|
|
30
|
+
expect(onToggleMock).not.toHaveBeenCalled();
|
|
31
|
+
});
|
|
32
|
+
it('renders checked state correctly', () => {
|
|
33
|
+
// This is a visual test, but we can verify props/styles if needed,
|
|
34
|
+
// or just rely on the component integration.
|
|
35
|
+
// In React Native testing library, verifying styles is possible but often brittle.
|
|
36
|
+
// We'll trust the logic verification above.
|
|
37
|
+
const { getByTestId } = render(<CheckBox checked={true} onToggle={() => { }} testID="checkbox"/>);
|
|
38
|
+
expect(getByTestId('checkbox')).toBeTruthy();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, { memo } from 'react';
|
|
2
|
+
import { TouchableOpacity, Image, View, Text } from 'react-native';
|
|
3
|
+
import styles from './styles';
|
|
4
|
+
import CheckIcon from '../../assets/imgs/whiteCheck.png';
|
|
5
|
+
import COLORS from '../../theme';
|
|
6
|
+
/**
|
|
7
|
+
* CheckBox - A customizable checkbox component
|
|
8
|
+
*/
|
|
9
|
+
const CheckBox = ({ checked = false, onToggle, label, disabled = false, activeColor = COLORS.primary, inactiveColor = COLORS.gray, checkColor, containerStyle, labelStyle, boxStyle, testID, }) => {
|
|
10
|
+
const handlePress = () => {
|
|
11
|
+
if (!disabled && onToggle) {
|
|
12
|
+
onToggle(!checked);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const boxStyles = [
|
|
16
|
+
styles.box,
|
|
17
|
+
!checked && { borderColor: inactiveColor },
|
|
18
|
+
checked && styles.checkedBox,
|
|
19
|
+
checked && { backgroundColor: activeColor, borderColor: activeColor },
|
|
20
|
+
disabled && styles.disabledBox,
|
|
21
|
+
boxStyle,
|
|
22
|
+
];
|
|
23
|
+
return (<TouchableOpacity style={[styles.container, containerStyle]} onPress={handlePress} activeOpacity={0.8} disabled={disabled} testID={testID}>
|
|
24
|
+
<View style={boxStyles}>
|
|
25
|
+
{checked && (<Image source={CheckIcon} style={[styles.icon, checkColor ? { tintColor: checkColor } : undefined]}/>)}
|
|
26
|
+
</View>
|
|
27
|
+
{label && (<Text style={[styles.label, disabled && styles.disabledLabel, labelStyle]}>
|
|
28
|
+
{label}
|
|
29
|
+
</Text>)}
|
|
30
|
+
</TouchableOpacity>);
|
|
31
|
+
};
|
|
32
|
+
export default memo(CheckBox);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
declare const styles: {
|
|
2
|
+
container: {
|
|
3
|
+
flexDirection: "row";
|
|
4
|
+
alignItems: "center";
|
|
5
|
+
};
|
|
6
|
+
touchable: {
|
|
7
|
+
flexDirection: "row";
|
|
8
|
+
alignItems: "center";
|
|
9
|
+
};
|
|
10
|
+
box: {
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
borderWidth: number;
|
|
14
|
+
borderColor: string;
|
|
15
|
+
borderRadius: number;
|
|
16
|
+
justifyContent: "center";
|
|
17
|
+
alignItems: "center";
|
|
18
|
+
backgroundColor: string;
|
|
19
|
+
};
|
|
20
|
+
checkedBox: {
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
borderWidth: number;
|
|
24
|
+
borderColor: string;
|
|
25
|
+
borderRadius: number;
|
|
26
|
+
justifyContent: "center";
|
|
27
|
+
alignItems: "center";
|
|
28
|
+
backgroundColor: string;
|
|
29
|
+
};
|
|
30
|
+
disabledBox: {
|
|
31
|
+
backgroundColor: string;
|
|
32
|
+
borderColor: string;
|
|
33
|
+
};
|
|
34
|
+
icon: {
|
|
35
|
+
width: number;
|
|
36
|
+
height: number;
|
|
37
|
+
resizeMode: "contain";
|
|
38
|
+
};
|
|
39
|
+
label: {
|
|
40
|
+
marginLeft: number;
|
|
41
|
+
fontSize: number;
|
|
42
|
+
color: string;
|
|
43
|
+
};
|
|
44
|
+
disabledLabel: {
|
|
45
|
+
color: string;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export default styles;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import COLORS, { FONT_SIZES } from '../../theme';
|
|
3
|
+
const styles = StyleSheet.create({
|
|
4
|
+
container: {
|
|
5
|
+
flexDirection: 'row',
|
|
6
|
+
alignItems: 'center',
|
|
7
|
+
},
|
|
8
|
+
touchable: {
|
|
9
|
+
flexDirection: 'row',
|
|
10
|
+
alignItems: 'center',
|
|
11
|
+
},
|
|
12
|
+
box: {
|
|
13
|
+
width: 24,
|
|
14
|
+
height: 24,
|
|
15
|
+
borderWidth: 1,
|
|
16
|
+
borderColor: COLORS.gray,
|
|
17
|
+
borderRadius: 5,
|
|
18
|
+
justifyContent: 'center',
|
|
19
|
+
alignItems: 'center',
|
|
20
|
+
backgroundColor: COLORS.white,
|
|
21
|
+
},
|
|
22
|
+
checkedBox: {
|
|
23
|
+
width: 24,
|
|
24
|
+
height: 24,
|
|
25
|
+
borderWidth: 1,
|
|
26
|
+
borderColor: COLORS.primary,
|
|
27
|
+
borderRadius: 5,
|
|
28
|
+
justifyContent: 'center',
|
|
29
|
+
alignItems: 'center',
|
|
30
|
+
backgroundColor: COLORS.primary,
|
|
31
|
+
},
|
|
32
|
+
disabledBox: {
|
|
33
|
+
backgroundColor: COLORS.grayBg,
|
|
34
|
+
borderColor: COLORS.gray,
|
|
35
|
+
},
|
|
36
|
+
icon: {
|
|
37
|
+
width: 16,
|
|
38
|
+
height: 16,
|
|
39
|
+
resizeMode: 'contain',
|
|
40
|
+
},
|
|
41
|
+
label: {
|
|
42
|
+
marginLeft: 10,
|
|
43
|
+
fontSize: FONT_SIZES.f16 || 16,
|
|
44
|
+
color: COLORS.black,
|
|
45
|
+
},
|
|
46
|
+
disabledLabel: {
|
|
47
|
+
color: COLORS.gray,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
export default styles;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { StyleProp, ViewStyle, TextStyle } from 'react-native';
|
|
2
|
+
export interface CheckBoxProps {
|
|
3
|
+
/**
|
|
4
|
+
* Whether the checkbox is checked
|
|
5
|
+
*/
|
|
6
|
+
checked: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Callback function called when the checkbox is toggled
|
|
9
|
+
*/
|
|
10
|
+
onToggle: (checked: boolean) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Optional label text to display next to the checkbox
|
|
13
|
+
*/
|
|
14
|
+
label?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Whether the checkbox is disabled
|
|
17
|
+
*/
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Color of the box when checked (defaults to theme primary)
|
|
21
|
+
*/
|
|
22
|
+
activeColor?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Color of the box when unchecked (defaults to theme lightGray or border color)
|
|
25
|
+
*/
|
|
26
|
+
inactiveColor?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Color of the checkmark icon (defaults to white)
|
|
29
|
+
*/
|
|
30
|
+
checkColor?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Additional style for the container
|
|
33
|
+
*/
|
|
34
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
35
|
+
/**
|
|
36
|
+
* Additional style for the label text
|
|
37
|
+
*/
|
|
38
|
+
labelStyle?: StyleProp<TextStyle>;
|
|
39
|
+
/**
|
|
40
|
+
* Additional style for the checkbox square
|
|
41
|
+
*/
|
|
42
|
+
boxStyle?: StyleProp<ViewStyle>;
|
|
43
|
+
/**
|
|
44
|
+
* Test ID for testing
|
|
45
|
+
*/
|
|
46
|
+
testID?: string;
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -4,5 +4,7 @@ export { default as BottomTabs } from './components/BottomTabs';
|
|
|
4
4
|
export type { BottomTabsProps, TabItem } from './components/BottomTabs';
|
|
5
5
|
export { default as ConfirmationPopUp } from './components/ConfirmationPopUp';
|
|
6
6
|
export type { ConfirmationPopUpProps } from './components/ConfirmationPopUp';
|
|
7
|
+
export { default as CheckBox } from './components/CheckBox';
|
|
8
|
+
export type { CheckBoxProps } from './components/CheckBox/type';
|
|
7
9
|
export { default as COLORS, FONT_FAMILY, FONT_SIZES } from './theme';
|
|
8
|
-
export * from './interactions';
|
|
10
|
+
export * from './utils/interactions';
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
export { default as Button } from './components/Button/index';
|
|
3
3
|
export { default as BottomTabs } from './components/BottomTabs';
|
|
4
4
|
export { default as ConfirmationPopUp } from './components/ConfirmationPopUp';
|
|
5
|
+
export { default as CheckBox } from './components/CheckBox';
|
|
5
6
|
// Theme utilities (for customization)
|
|
6
7
|
export { default as COLORS, FONT_FAMILY, FONT_SIZES } from './theme';
|
|
7
8
|
// Utils
|
|
8
|
-
export * from './interactions';
|
|
9
|
+
export * from './utils/interactions';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-yastools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
"author": "",
|
|
26
26
|
"license": "ISC",
|
|
27
27
|
"description": "React Native Utility Files and Utility Components ",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/YassineBenZriouil/react-native-yastools"
|
|
31
|
+
},
|
|
28
32
|
"peerDependencies": {
|
|
29
33
|
"react": ">=17.0.0",
|
|
30
34
|
"react-native": ">=0.64.0"
|
|
@@ -82,4 +86,4 @@
|
|
|
82
86
|
"!src/**/*.d.ts"
|
|
83
87
|
]
|
|
84
88
|
}
|
|
85
|
-
}
|
|
89
|
+
}
|
|
Binary file
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
import styles from './styles';
|
|
15
15
|
import COLORS from '../../theme';
|
|
16
16
|
import { ButtonProps } from './type';
|
|
17
|
-
import { preventMultiPress, usePressScale } from '../../interactions';
|
|
17
|
+
import { preventMultiPress, usePressScale } from '../../utils/interactions';
|
|
18
18
|
|
|
19
19
|
export type { ButtonProps };
|
|
20
20
|
|
|
@@ -79,7 +79,7 @@ const Button: React.FC<ButtonProps> = ({
|
|
|
79
79
|
!disabled && primaryColor && { backgroundColor: primaryColor },
|
|
80
80
|
disabled && disabledColor && { backgroundColor: disabledColor },
|
|
81
81
|
// Support both prop names for backwards compatibility
|
|
82
|
-
additionalStyle
|
|
82
|
+
additionalStyle
|
|
83
83
|
];
|
|
84
84
|
|
|
85
85
|
// Combine animated style
|
|
@@ -92,7 +92,7 @@ const Button: React.FC<ButtonProps> = ({
|
|
|
92
92
|
onPressOut={isAnimated ? handlePressOut : undefined}
|
|
93
93
|
activeOpacity={activeOpacity}
|
|
94
94
|
disabled={disabled || fetching}
|
|
95
|
-
style={[animatedStyle]}
|
|
95
|
+
style={[animatedStyle]}
|
|
96
96
|
>
|
|
97
97
|
<View style={containerStyle} testID={testID}>
|
|
98
98
|
{fetching ? (
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, fireEvent } from '@testing-library/react-native';
|
|
3
|
+
import CheckBox from '../index';
|
|
4
|
+
|
|
5
|
+
describe('CheckBox', () => {
|
|
6
|
+
it('renders correctly', () => {
|
|
7
|
+
const { getByTestId } = render(
|
|
8
|
+
<CheckBox checked={false} onToggle={() => { }} testID="checkbox" />
|
|
9
|
+
);
|
|
10
|
+
expect(getByTestId('checkbox')).toBeTruthy();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('displays label when provided', () => {
|
|
14
|
+
const { getByText } = render(
|
|
15
|
+
<CheckBox checked={false} onToggle={() => { }} label="Accept Terms" />
|
|
16
|
+
);
|
|
17
|
+
expect(getByText('Accept Terms')).toBeTruthy();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('calls onToggle when pressed', () => {
|
|
21
|
+
const onToggleMock = jest.fn();
|
|
22
|
+
const { getByTestId } = render(
|
|
23
|
+
<CheckBox checked={false} onToggle={onToggleMock} testID="checkbox" />
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
fireEvent.press(getByTestId('checkbox'));
|
|
27
|
+
expect(onToggleMock).toHaveBeenCalledWith(true);
|
|
28
|
+
expect(onToggleMock).toHaveBeenCalledTimes(1);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('calls onToggle with false when checked is true', () => {
|
|
32
|
+
const onToggleMock = jest.fn();
|
|
33
|
+
const { getByTestId } = render(
|
|
34
|
+
<CheckBox checked={true} onToggle={onToggleMock} testID="checkbox" />
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
fireEvent.press(getByTestId('checkbox'));
|
|
38
|
+
expect(onToggleMock).toHaveBeenCalledWith(false);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('does not call onToggle when disabled', () => {
|
|
42
|
+
const onToggleMock = jest.fn();
|
|
43
|
+
const { getByTestId } = render(
|
|
44
|
+
<CheckBox checked={false} onToggle={onToggleMock} disabled testID="checkbox" />
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
fireEvent.press(getByTestId('checkbox'));
|
|
48
|
+
expect(onToggleMock).not.toHaveBeenCalled();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('renders checked state correctly', () => {
|
|
52
|
+
// This is a visual test, but we can verify props/styles if needed,
|
|
53
|
+
// or just rely on the component integration.
|
|
54
|
+
// In React Native testing library, verifying styles is possible but often brittle.
|
|
55
|
+
// We'll trust the logic verification above.
|
|
56
|
+
const { getByTestId } = render(
|
|
57
|
+
<CheckBox checked={true} onToggle={() => { }} testID="checkbox" />
|
|
58
|
+
);
|
|
59
|
+
expect(getByTestId('checkbox')).toBeTruthy();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React, { memo } from 'react';
|
|
2
|
+
import { TouchableOpacity, Image, View, Text, ViewStyle } from 'react-native';
|
|
3
|
+
import styles from './styles';
|
|
4
|
+
import CheckIcon from '../../assets/imgs/whiteCheck.png';
|
|
5
|
+
import COLORS from '../../theme';
|
|
6
|
+
import { CheckBoxProps } from './type';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* CheckBox - A customizable checkbox component
|
|
10
|
+
*/
|
|
11
|
+
const CheckBox: React.FC<CheckBoxProps> = ({
|
|
12
|
+
checked = false,
|
|
13
|
+
onToggle,
|
|
14
|
+
label,
|
|
15
|
+
disabled = false,
|
|
16
|
+
activeColor = COLORS.primary,
|
|
17
|
+
inactiveColor = COLORS.gray,
|
|
18
|
+
checkColor,
|
|
19
|
+
containerStyle,
|
|
20
|
+
labelStyle,
|
|
21
|
+
boxStyle,
|
|
22
|
+
testID,
|
|
23
|
+
}) => {
|
|
24
|
+
const handlePress = () => {
|
|
25
|
+
if (!disabled && onToggle) {
|
|
26
|
+
onToggle(!checked);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const boxStyles: ViewStyle[] = [
|
|
31
|
+
styles.box,
|
|
32
|
+
!checked && { borderColor: inactiveColor },
|
|
33
|
+
checked && styles.checkedBox,
|
|
34
|
+
checked && { backgroundColor: activeColor, borderColor: activeColor },
|
|
35
|
+
disabled && styles.disabledBox,
|
|
36
|
+
boxStyle as ViewStyle,
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<TouchableOpacity
|
|
41
|
+
style={[styles.container, containerStyle]}
|
|
42
|
+
onPress={handlePress}
|
|
43
|
+
activeOpacity={0.8}
|
|
44
|
+
disabled={disabled}
|
|
45
|
+
testID={testID}
|
|
46
|
+
>
|
|
47
|
+
<View style={boxStyles}>
|
|
48
|
+
{checked && (
|
|
49
|
+
<Image
|
|
50
|
+
source={CheckIcon}
|
|
51
|
+
style={[styles.icon, checkColor ? { tintColor: checkColor } : undefined]}
|
|
52
|
+
/>
|
|
53
|
+
)}
|
|
54
|
+
</View>
|
|
55
|
+
{label && (
|
|
56
|
+
<Text style={[styles.label, disabled && styles.disabledLabel, labelStyle]}>
|
|
57
|
+
{label}
|
|
58
|
+
</Text>
|
|
59
|
+
)}
|
|
60
|
+
</TouchableOpacity>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export default memo(CheckBox);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import COLORS, { FONT_SIZES } from '../../theme';
|
|
3
|
+
|
|
4
|
+
const styles = StyleSheet.create({
|
|
5
|
+
container: {
|
|
6
|
+
flexDirection: 'row',
|
|
7
|
+
alignItems: 'center',
|
|
8
|
+
},
|
|
9
|
+
touchable: {
|
|
10
|
+
flexDirection: 'row',
|
|
11
|
+
alignItems: 'center',
|
|
12
|
+
},
|
|
13
|
+
box: {
|
|
14
|
+
width: 24,
|
|
15
|
+
height: 24,
|
|
16
|
+
borderWidth: 1,
|
|
17
|
+
borderColor: COLORS.gray,
|
|
18
|
+
borderRadius: 5,
|
|
19
|
+
justifyContent: 'center',
|
|
20
|
+
alignItems: 'center',
|
|
21
|
+
backgroundColor: COLORS.white,
|
|
22
|
+
},
|
|
23
|
+
checkedBox: {
|
|
24
|
+
width: 24,
|
|
25
|
+
height: 24,
|
|
26
|
+
borderWidth: 1,
|
|
27
|
+
borderColor: COLORS.primary,
|
|
28
|
+
borderRadius: 5,
|
|
29
|
+
justifyContent: 'center',
|
|
30
|
+
alignItems: 'center',
|
|
31
|
+
backgroundColor: COLORS.primary,
|
|
32
|
+
},
|
|
33
|
+
disabledBox: {
|
|
34
|
+
backgroundColor: COLORS.grayBg,
|
|
35
|
+
borderColor: COLORS.gray,
|
|
36
|
+
},
|
|
37
|
+
icon: {
|
|
38
|
+
width: 16,
|
|
39
|
+
height: 16,
|
|
40
|
+
resizeMode: 'contain',
|
|
41
|
+
},
|
|
42
|
+
label: {
|
|
43
|
+
marginLeft: 10,
|
|
44
|
+
fontSize: FONT_SIZES.f16 || 16,
|
|
45
|
+
color: COLORS.black,
|
|
46
|
+
},
|
|
47
|
+
disabledLabel: {
|
|
48
|
+
color: COLORS.gray,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export default styles;
|
|
53
|
+
|
|
54
|
+
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { StyleProp, ViewStyle, TextStyle, ImageStyle } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export interface CheckBoxProps {
|
|
4
|
+
/**
|
|
5
|
+
* Whether the checkbox is checked
|
|
6
|
+
*/
|
|
7
|
+
checked: boolean;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Callback function called when the checkbox is toggled
|
|
11
|
+
*/
|
|
12
|
+
onToggle: (checked: boolean) => void;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Optional label text to display next to the checkbox
|
|
16
|
+
*/
|
|
17
|
+
label?: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Whether the checkbox is disabled
|
|
21
|
+
*/
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Color of the box when checked (defaults to theme primary)
|
|
26
|
+
*/
|
|
27
|
+
activeColor?: string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Color of the box when unchecked (defaults to theme lightGray or border color)
|
|
31
|
+
*/
|
|
32
|
+
inactiveColor?: string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Color of the checkmark icon (defaults to white)
|
|
36
|
+
*/
|
|
37
|
+
checkColor?: string;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Additional style for the container
|
|
41
|
+
*/
|
|
42
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Additional style for the label text
|
|
46
|
+
*/
|
|
47
|
+
labelStyle?: StyleProp<TextStyle>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Additional style for the checkbox square
|
|
51
|
+
*/
|
|
52
|
+
boxStyle?: StyleProp<ViewStyle>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Test ID for testing
|
|
56
|
+
*/
|
|
57
|
+
testID?: string;
|
|
58
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Components
|
|
2
|
-
export {default as Button } from './components/Button/index';
|
|
2
|
+
export { default as Button } from './components/Button/index';
|
|
3
3
|
export type { ButtonProps } from './components/Button';
|
|
4
4
|
|
|
5
5
|
export { default as BottomTabs } from './components/BottomTabs';
|
|
@@ -8,9 +8,12 @@ export type { BottomTabsProps, TabItem } from './components/BottomTabs';
|
|
|
8
8
|
export { default as ConfirmationPopUp } from './components/ConfirmationPopUp';
|
|
9
9
|
export type { ConfirmationPopUpProps } from './components/ConfirmationPopUp';
|
|
10
10
|
|
|
11
|
+
export { default as CheckBox } from './components/CheckBox';
|
|
12
|
+
export type { CheckBoxProps } from './components/CheckBox/type';
|
|
13
|
+
|
|
11
14
|
|
|
12
15
|
// Theme utilities (for customization)
|
|
13
16
|
export { default as COLORS, FONT_FAMILY, FONT_SIZES } from './theme';
|
|
14
17
|
|
|
15
18
|
// Utils
|
|
16
|
-
export * from './interactions';
|
|
19
|
+
export * from './utils/interactions';
|
|
File without changes
|
|
File without changes
|
|
File without changes
|