ferns-ui 0.14.0 → 0.15.0
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/dist/Avatar.d.ts +13 -0
- package/dist/Avatar.js +45 -25
- package/dist/Avatar.js.map +1 -1
- package/package.json +4 -2
- package/src/Avatar.tsx +51 -6
package/dist/Avatar.d.ts
CHANGED
|
@@ -23,6 +23,19 @@ interface AvatarProps {
|
|
|
23
23
|
* The URL of the user's image.
|
|
24
24
|
*/
|
|
25
25
|
src?: string;
|
|
26
|
+
/**
|
|
27
|
+
* The fit for the image within the Avatar: "cover" | "contain" | "none".
|
|
28
|
+
* Default is undefined. See Image.tsx for more info
|
|
29
|
+
*/
|
|
30
|
+
imageFit?: "cover" | "contain" | "none";
|
|
31
|
+
/**
|
|
32
|
+
* Allow user to edit the image of the avatar
|
|
33
|
+
*/
|
|
34
|
+
editAvatarImage?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Function to handle the avatar image edit
|
|
37
|
+
*/
|
|
38
|
+
onChange?: (val: any) => void;
|
|
26
39
|
}
|
|
27
40
|
export declare const Avatar: (props: AvatarProps) => React.ReactElement;
|
|
28
41
|
export {};
|
package/dist/Avatar.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { launchImageLibraryAsync, MediaTypeOptions } from "expo-image-picker";
|
|
1
2
|
import React, { useState } from "react";
|
|
2
3
|
import { Image, Text, View } from "react-native";
|
|
3
4
|
import { Box } from "./Box";
|
|
5
|
+
import { iconSizeToNumber } from "./Common";
|
|
6
|
+
import { Icon } from "./Icon";
|
|
4
7
|
import { Unifier } from "./Unifier";
|
|
5
8
|
const sizes = {
|
|
6
9
|
xs: 24,
|
|
@@ -10,9 +13,10 @@ const sizes = {
|
|
|
10
13
|
xl: 120,
|
|
11
14
|
};
|
|
12
15
|
export const Avatar = (props) => {
|
|
13
|
-
var _a;
|
|
16
|
+
var _a, _b;
|
|
14
17
|
const [isImageLoaded, setIsImageLoaded] = useState(true);
|
|
15
|
-
const
|
|
18
|
+
const [src, setSrc] = useState((_a = props.src) !== null && _a !== void 0 ? _a : undefined);
|
|
19
|
+
const { name, initials, outline, size = "md", imageFit = "contain", editAvatarImage, onChange, } = props;
|
|
16
20
|
const width = sizes[size];
|
|
17
21
|
const height = sizes[size];
|
|
18
22
|
const radius = sizes[size] / 2;
|
|
@@ -24,28 +28,44 @@ export const Avatar = (props) => {
|
|
|
24
28
|
.join("")
|
|
25
29
|
.toLocaleUpperCase();
|
|
26
30
|
const handleImageError = () => setIsImageLoaded(false);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
:
|
|
48
|
-
|
|
49
|
-
|
|
31
|
+
const pickImage = async () => {
|
|
32
|
+
// TODO: Add permission request to use camera to take a picture
|
|
33
|
+
const result = await launchImageLibraryAsync({
|
|
34
|
+
mediaTypes: MediaTypeOptions.Images,
|
|
35
|
+
allowsEditing: true,
|
|
36
|
+
});
|
|
37
|
+
if (!result.cancelled) {
|
|
38
|
+
setSrc(result.uri);
|
|
39
|
+
if (onChange) {
|
|
40
|
+
onChange(result);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
return (React.createElement(Box, { border: outline ? "white" : undefined, height: height, overflow: "hidden", position: "relative", rounding: "circle", width: editAvatarImage ? width + iconSizeToNumber(size) : width },
|
|
45
|
+
editAvatarImage && (React.createElement(Box, { bottom: true, position: "absolute", right: true, zIndex: 5, onClick: pickImage },
|
|
46
|
+
React.createElement(Icon, { color: "black", name: "edit", size: size }))),
|
|
47
|
+
src && isImageLoaded ? (
|
|
48
|
+
// TODO: Make our Image component rounding work so that we can use it for Avatar. Currently it creates an
|
|
49
|
+
// unrounded box around the Image.
|
|
50
|
+
React.createElement(Image, { resizeMode: imageFit, source: { uri: src, cache: "force-cache" }, style: {
|
|
51
|
+
borderRadius: radius,
|
|
52
|
+
height,
|
|
53
|
+
width,
|
|
54
|
+
display: "flex",
|
|
55
|
+
alignItems: "center",
|
|
56
|
+
justifyContent: "center",
|
|
57
|
+
overflow: "hidden",
|
|
58
|
+
}, onError: handleImageError })) : (React.createElement(View, { style: {
|
|
59
|
+
height,
|
|
60
|
+
width,
|
|
61
|
+
borderRadius: radius,
|
|
62
|
+
display: "flex",
|
|
63
|
+
alignItems: "center",
|
|
64
|
+
justifyContent: "center",
|
|
65
|
+
backgroundColor: props.backgroundColor
|
|
66
|
+
? Unifier.theme[props.backgroundColor]
|
|
67
|
+
: Unifier.theme.gray,
|
|
68
|
+
} },
|
|
69
|
+
React.createElement(Text, { style: { fontSize, color: (_b = props.textColor) !== null && _b !== void 0 ? _b : Unifier.theme.darkGray } }, computedInitials)))));
|
|
50
70
|
};
|
|
51
71
|
//# sourceMappingURL=Avatar.js.map
|
package/dist/Avatar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Avatar.js","sourceRoot":"","sources":["../src/Avatar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAC,QAAQ,EAAC,MAAM,OAAO,CAAC;AACtC,OAAO,EAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"Avatar.js","sourceRoot":"","sources":["../src/Avatar.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ferns-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"scripts": {
|
|
@@ -145,6 +145,7 @@
|
|
|
145
145
|
"eslint-plugin-unused-imports": "2.0.0",
|
|
146
146
|
"expo-font": "^10.0.5",
|
|
147
147
|
"expo-haptics": "~11.3.0",
|
|
148
|
+
"expo-image-picker": "^13.3.1",
|
|
148
149
|
"lodash": "^4.17.21",
|
|
149
150
|
"mixpanel-browser": "^2.38.0",
|
|
150
151
|
"moment-timezone": "^0.5.35",
|
|
@@ -176,13 +177,14 @@
|
|
|
176
177
|
"@react-native-picker/picker": "2.4.4",
|
|
177
178
|
"expo-font": "^10.0.5",
|
|
178
179
|
"expo-haptics": "~11.3.0",
|
|
180
|
+
"expo-image-picker": "^13.3.1",
|
|
179
181
|
"lodash": "^4.17.21",
|
|
180
182
|
"mixpanel-browser": "^2.38.0",
|
|
181
183
|
"moment-timezone": "^0.5.35",
|
|
182
184
|
"react": "^18.2.0",
|
|
183
185
|
"react-app-polyfill": "^3.0.0",
|
|
184
|
-
"react-dev-utils": "^12.0.1",
|
|
185
186
|
"react-datetime-picker": "^4.0.1",
|
|
187
|
+
"react-dev-utils": "^12.0.1",
|
|
186
188
|
"react-dom": "18.2.0",
|
|
187
189
|
"react-native": "0.69.4",
|
|
188
190
|
"react-native-calendars": "^1.1288.2",
|
package/src/Avatar.tsx
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import {launchImageLibraryAsync, MediaTypeOptions} from "expo-image-picker";
|
|
1
2
|
import React, {useState} from "react";
|
|
2
|
-
import {Image, Text, View} from "react-native";
|
|
3
|
+
import {Image, ImageResizeMode, Text, View} from "react-native";
|
|
3
4
|
|
|
4
5
|
import {Box} from "./Box";
|
|
5
|
-
import {AllColors} from "./Common";
|
|
6
|
+
import {AllColors, iconSizeToNumber} from "./Common";
|
|
7
|
+
import {Icon} from "./Icon";
|
|
6
8
|
import {Unifier} from "./Unifier";
|
|
7
9
|
|
|
8
10
|
const sizes = {
|
|
@@ -38,11 +40,33 @@ interface AvatarProps {
|
|
|
38
40
|
* The URL of the user's image.
|
|
39
41
|
*/
|
|
40
42
|
src?: string;
|
|
43
|
+
/**
|
|
44
|
+
* The fit for the image within the Avatar: "cover" | "contain" | "none".
|
|
45
|
+
* Default is undefined. See Image.tsx for more info
|
|
46
|
+
*/
|
|
47
|
+
imageFit?: "cover" | "contain" | "none";
|
|
48
|
+
/**
|
|
49
|
+
* Allow user to edit the image of the avatar
|
|
50
|
+
*/
|
|
51
|
+
editAvatarImage?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Function to handle the avatar image edit
|
|
54
|
+
*/
|
|
55
|
+
onChange?: (val: any) => void;
|
|
41
56
|
}
|
|
42
57
|
|
|
43
58
|
export const Avatar = (props: AvatarProps): React.ReactElement => {
|
|
44
59
|
const [isImageLoaded, setIsImageLoaded] = useState(true);
|
|
45
|
-
const
|
|
60
|
+
const [src, setSrc] = useState(props.src ?? undefined);
|
|
61
|
+
const {
|
|
62
|
+
name,
|
|
63
|
+
initials,
|
|
64
|
+
outline,
|
|
65
|
+
size = "md",
|
|
66
|
+
imageFit = "contain",
|
|
67
|
+
editAvatarImage,
|
|
68
|
+
onChange,
|
|
69
|
+
} = props;
|
|
46
70
|
const width = sizes[size];
|
|
47
71
|
const height = sizes[size];
|
|
48
72
|
const radius = sizes[size] / 2;
|
|
@@ -57,6 +81,22 @@ export const Avatar = (props: AvatarProps): React.ReactElement => {
|
|
|
57
81
|
.toLocaleUpperCase();
|
|
58
82
|
|
|
59
83
|
const handleImageError = () => setIsImageLoaded(false);
|
|
84
|
+
|
|
85
|
+
const pickImage = async () => {
|
|
86
|
+
// TODO: Add permission request to use camera to take a picture
|
|
87
|
+
const result = await launchImageLibraryAsync({
|
|
88
|
+
mediaTypes: MediaTypeOptions.Images,
|
|
89
|
+
allowsEditing: true,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (!result.cancelled) {
|
|
93
|
+
setSrc(result.uri);
|
|
94
|
+
if (onChange) {
|
|
95
|
+
onChange(result);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
60
100
|
return (
|
|
61
101
|
<Box
|
|
62
102
|
border={outline ? "white" : undefined}
|
|
@@ -64,13 +104,18 @@ export const Avatar = (props: AvatarProps): React.ReactElement => {
|
|
|
64
104
|
overflow="hidden"
|
|
65
105
|
position="relative"
|
|
66
106
|
rounding="circle"
|
|
67
|
-
width={width}
|
|
107
|
+
width={editAvatarImage ? width + iconSizeToNumber(size) : width}
|
|
68
108
|
>
|
|
109
|
+
{editAvatarImage && (
|
|
110
|
+
<Box bottom position="absolute" right zIndex={5} onClick={pickImage}>
|
|
111
|
+
<Icon color="black" name="edit" size={size} />
|
|
112
|
+
</Box>
|
|
113
|
+
)}
|
|
69
114
|
{src && isImageLoaded ? (
|
|
70
115
|
// TODO: Make our Image component rounding work so that we can use it for Avatar. Currently it creates an
|
|
71
|
-
//
|
|
116
|
+
// unrounded box around the Image.
|
|
72
117
|
<Image
|
|
73
|
-
resizeMode=
|
|
118
|
+
resizeMode={imageFit as ImageResizeMode}
|
|
74
119
|
source={{uri: src, cache: "force-cache"}}
|
|
75
120
|
style={{
|
|
76
121
|
borderRadius: radius,
|