Skip to content

Commit 873e8b9

Browse files
committed
refactor(avatar): ♻️ remove usage of useAvatarProps hook,
move Avatar Props into component file and pass through required props into children components
1 parent 45bcb49 commit 873e8b9

File tree

8 files changed

+99
-132
lines changed

8 files changed

+99
-132
lines changed

src/components/avatar-group/AvatarGroup.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import { isUndefined } from "lodash";
44
import { Box, BoxProps } from "../../primitives";
55
import { useTheme } from "../../theme";
66
import { createContext, getValidChildren } from "../../utils";
7-
import { Avatar } from "../avatar/Avatar";
8-
import { AvatarProps } from "../avatar/avatarPropTypes";
7+
import { Avatar, AvatarProps } from "../avatar";
98

109
import { AvatarGroupWrapper } from "./AvatarGroupWrapper";
1110

src/components/avatar-group/AvatarGroupWrapper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import React from "react";
33
import { Box, BoxProps } from "../../primitives";
44
import { useTheme } from "../../theme";
55
import { styleAdapter } from "../../utils";
6-
import { AvatarSizes } from "../avatar/avatarPropTypes";
6+
import { AvatarSizes } from "../avatar";
77

88
export interface AvatarGroupWrapperProps extends BoxProps {
99
size?: AvatarSizes;

src/components/avatar/Avatar.tsx

Lines changed: 88 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import React, { forwardRef, useState } from "react";
2+
import { ImageProps, ImageSourcePropType } from "react-native";
23

34
import { DefaultUser } from "../../icons";
4-
import { Box, Text } from "../../primitives";
5+
import { Box, BoxProps, Text } from "../../primitives";
56
import { useTheme } from "../../theme";
6-
import { createComponent, cx, styleAdapter } from "../../utils";
7+
import { createComponent, cx, isUndefined, styleAdapter } from "../../utils";
8+
import { useAvatarGroup } from "../avatar-group";
79
import { Icon } from "../icon";
810

911
import { AvatarImage } from "./AvatarImage";
10-
import { useAvatarProps } from "./AvatarProps";
11-
import type { AvatarProps, AvatarSizes } from "./avatarPropTypes";
1212
import { AvatarStatus } from "./AvatarStatus";
1313

1414
function getInitials(name: string, size: AvatarSizes) {
@@ -28,63 +28,126 @@ function getInitials(name: string, size: AvatarSizes) {
2828
: initials.toUpperCase();
2929
}
3030

31+
export type AvatarSizes = "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
32+
export type AvatarStatusType = "active" | "away" | "sleep" | "typing" | null;
33+
34+
export interface AvatarProps extends BoxProps {
35+
/**
36+
* React Native Image component Props, except for source
37+
*/
38+
imageProps: Omit<ImageProps, "source">;
39+
/**
40+
* The image source (either a remote URL or a local file resource).
41+
* Check https://reactnative.dev/docs/image#imagesource
42+
*/
43+
src: ImageSourcePropType;
44+
/**
45+
* How large should avatar be?
46+
*
47+
* @default xl
48+
*/
49+
size: AvatarSizes;
50+
/**
51+
* If `true`, Avatar looks like a squared.
52+
*
53+
* @default false
54+
*/
55+
squared: boolean;
56+
/**
57+
* Name prop used for `alt` & calculate placeholder initials.
58+
*/
59+
name: string;
60+
/**
61+
* Shows AvatarBadge with the given type
62+
*
63+
* @default none
64+
*/
65+
status: AvatarStatusType;
66+
/**
67+
* StatusIndicator's Background Color & StatusIndicator Ring Color.
68+
*
69+
* @default ["bg-white-900", "ring-white-900"]"
70+
*/
71+
parentsBackground: string;
72+
}
73+
3174
const RNAvatar: React.FC<Partial<AvatarProps>> = forwardRef<
3275
typeof Box,
3376
Partial<AvatarProps>
3477
>((props, ref) => {
3578
const tailwind = useTheme();
3679
const avatarTheme = useTheme("avatar");
37-
const { _imageProps, _basicProps, _otherProps, _statusProps } =
38-
useAvatarProps(props);
39-
const { name, style, ...boxProps } = _otherProps;
40-
const isSourceAvailable = React.useMemo(
41-
() => (_imageProps?.src ? true : false),
42-
[_imageProps?.src],
43-
);
80+
81+
const avatarGroupProps = useAvatarGroup();
82+
83+
const {
84+
size = avatarGroupProps?.size || "xl",
85+
squared = false,
86+
name,
87+
style,
88+
src,
89+
status,
90+
parentsBackground = "text-white-900",
91+
imageProps = {},
92+
...boxProps
93+
} = props;
94+
95+
const isSquared = isUndefined(avatarGroupProps)
96+
? squared
97+
: avatarGroupProps.squared;
98+
99+
const isSourceAvailable = React.useMemo(() => (src ? true : false), [src]);
44100
const [imageAvailable, setImageAvailable] = useState(isSourceAvailable);
45101
const loadFallback = () => setImageAvailable(false);
46102

47103
return (
48104
<Box
49105
style={[
50-
avatarTheme.borderRadius.size[_basicProps.size],
106+
avatarTheme.borderRadius.size[size],
51107
tailwind.style(
52108
cx(
53109
avatarTheme.base,
54-
avatarTheme.size[_basicProps.size],
55-
!_basicProps.squared ? avatarTheme.circular : "",
110+
avatarTheme.size[size],
111+
!isSquared ? avatarTheme.circular : "",
56112
),
57113
),
58114
styleAdapter(style),
59115
]}
60116
ref={ref}
61117
{...boxProps}
62118
>
63-
{imageAvailable && _imageProps.src ? (
64-
<AvatarImage {..._imageProps} handleFallback={loadFallback} />
119+
{imageAvailable && src ? (
120+
<AvatarImage
121+
size={size}
122+
imageProps={imageProps}
123+
src={src}
124+
squared={isSquared}
125+
handleFallback={loadFallback}
126+
/>
65127
) : name ? (
66128
<Text
67129
style={tailwind.style(
68-
cx(
69-
avatarTheme.initials.base,
70-
avatarTheme.initials.size[_basicProps.size],
71-
),
130+
cx(avatarTheme.initials.base, avatarTheme.initials.size[size]),
72131
)}
73132
adjustsFontSizeToFit
74133
allowFontScaling={false}
75134
>
76-
{getInitials(name, _basicProps.size)}
135+
{getInitials(name, size)}
77136
</Text>
78137
) : (
79138
<Icon
80139
icon={<DefaultUser />}
81-
style={tailwind.style(
82-
cx(avatarTheme.defaultUserIcon[_basicProps.size]),
83-
)}
140+
style={tailwind.style(cx(avatarTheme.defaultUserIcon[size]))}
84141
color={tailwind.getColor("text-gray-800")}
85142
/>
86143
)}
87-
{_statusProps.status && <AvatarStatus {..._statusProps} />}
144+
{status && (
145+
<AvatarStatus
146+
parentsBackground={parentsBackground}
147+
size={size}
148+
status={status}
149+
/>
150+
)}
88151
</Box>
89152
);
90153
});

src/components/avatar/AvatarImage.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,19 @@ import { Image } from "react-native";
44
import { useTheme } from "../../theme";
55
import { cx } from "../../utils";
66

7-
import { AvatarImageProps } from "./avatarPropTypes";
7+
import { AvatarProps } from "./Avatar";
88

9-
interface CAvatarImageProps extends AvatarImageProps {
9+
interface AvatarImageProps
10+
extends Pick<AvatarProps, "imageProps" | "src" | "squared" | "size"> {
1011
handleFallback: () => void;
1112
}
1213

13-
export const AvatarImage: React.FC<CAvatarImageProps> = ({
14+
export const AvatarImage: React.FC<AvatarImageProps> = ({
1415
imageProps,
1516
src,
16-
handleFallback,
1717
squared,
1818
size,
19+
handleFallback,
1920
}) => {
2021
const tailwind = useTheme();
2122
const avatarTheme = useTheme("avatar");

src/components/avatar/AvatarProps.tsx

Lines changed: 0 additions & 57 deletions
This file was deleted.

src/components/avatar/AvatarStatus.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { AnimatedBox, Box } from "../../primitives";
1414
import { useTheme } from "../../theme";
1515
import { cx } from "../../utils";
1616

17-
import { AvatarSizes, AvatarStatusProps } from "./avatarPropTypes";
17+
import { AvatarProps, AvatarSizes } from "./Avatar";
1818

1919
interface TypingStatusProps {
2020
size: Partial<AvatarSizes>;
@@ -100,11 +100,9 @@ const TypingComponent: React.FC<TypingStatusProps> = ({
100100
);
101101
};
102102

103-
export const AvatarStatus: React.FC<AvatarStatusProps> = ({
104-
status,
105-
size = "xl",
106-
parentsBackground = "text-white-900",
107-
}) => {
103+
export const AvatarStatus: React.FC<
104+
Pick<AvatarProps, "status" | "size" | "parentsBackground">
105+
> = ({ status, size, parentsBackground }) => {
108106
const tailwind = useTheme();
109107
const avatarStatusTheme = useTheme("avatar");
110108
switch (status) {

src/components/avatar/avatarPropTypes.ts

Lines changed: 0 additions & 36 deletions
This file was deleted.

src/components/avatar/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export * from "./Avatar";
22
export * from "./AvatarImage";
33
export * from "./AvatarProps";
4-
export * from "./avatarPropTypes";
54
export * from "./AvatarStatus";

0 commit comments

Comments
 (0)