Skip to content

Commit ab514c9

Browse files
committed
Add configs and source code
1 parent 842f798 commit ab514c9

22 files changed

+9221
-0
lines changed

.eslintrc.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module.exports = {
2+
root: true,
3+
extends: '@react-native-community',
4+
parser: '@typescript-eslint/parser',
5+
plugins: ['@typescript-eslint'],
6+
overrides: [
7+
{
8+
files: ['*.ts', '*.tsx'],
9+
rules: {
10+
'@typescript-eslint/no-shadow': ['error'],
11+
'no-shadow': 'off',
12+
'no-undef': 'off',
13+
},
14+
},
15+
],
16+
};

.gitattributes

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.pbxproj -text
2+
# specific for windows script files
3+
*.bat text eol=crlf

.gitignore

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# OSX
2+
#
3+
.DS_Store
4+
5+
# node.js
6+
#
7+
node_modules/
8+
npm-debug.log
9+
yarn-debug.log
10+
yarn-error.log

.npmignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
example/
2+
demo.gif
3+
demo.mp4

.prettierrc.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module.exports = {
2+
semi: true,
3+
tabWidth: 2,
4+
useTabs: false,
5+
printWidth: 100,
6+
singleQuote: true,
7+
bracketSpacing: true,
8+
bracketSameLine: false,
9+
trailingComma: "all"
10+
};

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Nick Seryakov
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

babel.config.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
presets: ['module:metro-react-native-babel-preset'],
3+
};

jest.config.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
preset: 'react-native',
3+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
4+
testPathIgnorePatterns: ['/example/', '/node_modules/'],
5+
};

package.json

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{
2+
"name": "react-native-userpic",
3+
"version": "1.0.0",
4+
"description": "React Native user picture / user avatar with support for gravatar, user's initials, unique colors, badges, statuses and more",
5+
"author": "Nick Seryakov (https://github.com/kolking)",
6+
"license": "MIT",
7+
"homepage": "https://github.com/kolking/react-native-userpic#readme",
8+
"repository": {
9+
"type": "git",
10+
"url": "git+https://[email protected]/kolking/react-native-userpic.git"
11+
},
12+
"bugs": {
13+
"url": "https://github.com/kolking/react-native-userpic/issues"
14+
},
15+
"keywords": [
16+
"react-native",
17+
"ios",
18+
"android",
19+
"userpic",
20+
"avatar",
21+
"gravatar",
22+
"user picture",
23+
"user image",
24+
"user avatar",
25+
"initials",
26+
"badge"
27+
],
28+
"main": "src/index",
29+
"react-native": "src/index",
30+
"source": "src/index",
31+
"scripts": {
32+
"test": "jest",
33+
"lint": "eslint --ext .js,.jsx,.ts,.tsx ./",
34+
"validate": "yarn tsc && yarn lint --fix && yarn test -u"
35+
},
36+
"dependencies": {
37+
"js-md5": "^0.7.3"
38+
},
39+
"devDependencies": {
40+
"@babel/core": "^7.12.9",
41+
"@babel/runtime": "^7.12.5",
42+
"@react-native-community/eslint-config": "^2.0.0",
43+
"@types/jest": "^26.0.23",
44+
"@types/js-md5": "^0.4.3",
45+
"@types/react-native": "^0.67.3",
46+
"@types/react-test-renderer": "^17.0.1",
47+
"@typescript-eslint/eslint-plugin": "^5.17.0",
48+
"@typescript-eslint/parser": "^5.17.0",
49+
"babel-jest": "^26.6.3",
50+
"eslint": "^7.32.0",
51+
"jest": "^26.6.3",
52+
"metro-react-native-babel-preset": "^0.67.0",
53+
"react": "17.0.2",
54+
"react-native": "0.68.2",
55+
"react-test-renderer": "17.0.2",
56+
"typescript": "^4.4.4"
57+
},
58+
"resolutions": {
59+
"@types/react": "^17"
60+
},
61+
"peerDependencies": {
62+
"react": "*",
63+
"react-native": "*"
64+
},
65+
"jest": {
66+
"preset": "react-native",
67+
"moduleFileExtensions": [
68+
"ts",
69+
"tsx",
70+
"js",
71+
"jsx",
72+
"json",
73+
"node"
74+
]
75+
},
76+
"publishConfig": {
77+
"registry": "https://registry.npmjs.org/"
78+
}
79+
}

src/Badge.tsx

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import React, { useEffect, useState } from 'react';
2+
import {
3+
Animated,
4+
PixelRatio,
5+
StyleProp,
6+
StyleSheet,
7+
Text,
8+
TextStyle,
9+
ViewProps,
10+
ViewStyle,
11+
} from 'react-native';
12+
13+
import { clamp, getRadius } from './helpers';
14+
15+
const minSize = 15;
16+
const maxSize = 40;
17+
18+
export interface BadgeProps extends ViewProps {
19+
size?: number;
20+
color?: string;
21+
borderRadius?: number | string;
22+
animate?: boolean;
23+
value?: number | boolean | string;
24+
limit?: number | boolean;
25+
style?: StyleProp<ViewStyle>;
26+
textStyle?: StyleProp<TextStyle>;
27+
}
28+
29+
export const Badge: React.FC<BadgeProps> = ({
30+
size = 20,
31+
color = '#ff3b30',
32+
borderRadius = '50%',
33+
animate = true,
34+
value,
35+
limit = 99,
36+
style,
37+
textStyle,
38+
...props
39+
}) => {
40+
const toValue = value ? 1 : 0;
41+
const [animatedValue] = useState(() => new Animated.Value(toValue));
42+
43+
useEffect(() => {
44+
Animated.spring(animatedValue, {
45+
tension: 60,
46+
friction: 6,
47+
toValue: toValue,
48+
useNativeDriver: true,
49+
}).start();
50+
}, [animatedValue, toValue]);
51+
52+
if (!value) {
53+
return null;
54+
}
55+
56+
let content = null;
57+
let height = styles.root.minHeight;
58+
59+
if (typeof value === 'number' || typeof value === 'string') {
60+
height = clamp(Math.round(size), minSize, maxSize);
61+
62+
const fontSize = PixelRatio.roundToNearestPixel(height * 0.6);
63+
const displayValue = typeof value === 'number' && limit && value > limit ? `${limit}+` : value;
64+
const textStyles = [
65+
{
66+
fontSize,
67+
marginHorizontal: fontSize / 2,
68+
},
69+
styles.text,
70+
textStyle,
71+
];
72+
73+
content = (
74+
<Text style={textStyles} numberOfLines={1}>
75+
{displayValue}
76+
</Text>
77+
);
78+
}
79+
80+
const rootStyles = [
81+
{
82+
height,
83+
minWidth: height,
84+
backgroundColor: color,
85+
borderRadius: getRadius(borderRadius, height),
86+
},
87+
styles.root,
88+
style,
89+
];
90+
91+
if (animate) {
92+
rootStyles.push({ transform: [{ scale: animatedValue as any }] });
93+
}
94+
95+
return (
96+
<Animated.View {...props} style={rootStyles}>
97+
{content}
98+
</Animated.View>
99+
);
100+
};
101+
102+
const styles = StyleSheet.create({
103+
root: {
104+
minHeight: 10,
105+
alignSelf: 'center',
106+
alignItems: 'center',
107+
justifyContent: 'center',
108+
},
109+
text: {
110+
color: '#fff',
111+
fontWeight: '400',
112+
fontFamily: 'System',
113+
includeFontPadding: false,
114+
textAlignVertical: 'center',
115+
backgroundColor: 'transparent',
116+
},
117+
});

0 commit comments

Comments
 (0)