@stackshift-ui/avatar 6.0.13-beta.2 → 7.0.0-beta.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/package.json +12 -9
- package/src/avatar.test.tsx +73 -21
- package/src/avatar.tsx +53 -66
- package/src/setupTests.ts +4 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackshift-ui/avatar",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "7.0.0-beta.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
"author": "WebriQ <info@webriq.com>",
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@testing-library/react": "^16.0.1",
|
|
17
|
+
"@testing-library/jest-dom": "^6.5.0",
|
|
18
|
+
"@testing-library/user-event": "^14.6.1",
|
|
17
19
|
"@types/node": "^22.7.0",
|
|
18
20
|
"@types/react": "^18.3.9",
|
|
19
21
|
"@types/react-dom": "^18.3.0",
|
|
@@ -29,22 +31,23 @@
|
|
|
29
31
|
"typescript": "^5.6.2",
|
|
30
32
|
"vite-tsconfig-paths": "^5.0.1",
|
|
31
33
|
"vitest": "^2.1.1",
|
|
32
|
-
"@stackshift-ui/
|
|
33
|
-
"@stackshift-ui/
|
|
34
|
+
"@stackshift-ui/typescript-config": "6.0.10",
|
|
35
|
+
"@stackshift-ui/eslint-config": "6.0.10"
|
|
34
36
|
},
|
|
35
37
|
"dependencies": {
|
|
38
|
+
"@radix-ui/react-avatar": "^1.1.10",
|
|
36
39
|
"classnames": "^2.5.1",
|
|
37
|
-
"@stackshift-ui/
|
|
38
|
-
"@stackshift-ui/
|
|
39
|
-
"@stackshift-ui/
|
|
40
|
-
"@stackshift-ui/
|
|
40
|
+
"@stackshift-ui/scripts": "6.1.0-beta.0",
|
|
41
|
+
"@stackshift-ui/flex": "7.0.0-beta.0",
|
|
42
|
+
"@stackshift-ui/image": "6.1.0-beta.0",
|
|
43
|
+
"@stackshift-ui/system": "6.1.0-beta.0"
|
|
41
44
|
},
|
|
42
45
|
"peerDependencies": {
|
|
46
|
+
"@stackshift-ui/system": ">=6.1.0-beta.0",
|
|
43
47
|
"@types/react": "16.8 - 19",
|
|
44
48
|
"next": "10 - 14",
|
|
45
49
|
"react": "16.8 - 19",
|
|
46
|
-
"react-dom": "16.8 - 19"
|
|
47
|
-
"@stackshift-ui/system": ">=6.0.11-beta.2"
|
|
50
|
+
"react-dom": "16.8 - 19"
|
|
48
51
|
},
|
|
49
52
|
"peerDependenciesMeta": {
|
|
50
53
|
"next": {
|
package/src/avatar.test.tsx
CHANGED
|
@@ -1,24 +1,76 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
2
|
+
import { beforeEach } from "node:test";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { afterEach, describe, expect, test, vi } from "vitest";
|
|
5
|
+
import { Avatar, AvatarFallback, AvatarImage } from "./avatar";
|
|
6
|
+
|
|
7
|
+
describe("avatar", () => {
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
vi.clearAllMocks();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
vi.mock("./avatar", async () => {
|
|
14
|
+
const actual = await vi.importActual("./avatar");
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
...actual,
|
|
18
|
+
AvatarImage: (props: React.ImgHTMLAttributes<HTMLImageElement>) => {
|
|
19
|
+
return <img {...props} />;
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
22
|
});
|
|
23
23
|
});
|
|
24
|
+
|
|
25
|
+
test("Common: Avatar - test if renders image when src is provided", () => {
|
|
26
|
+
const loadMock = vi.fn();
|
|
27
|
+
|
|
28
|
+
const { unmount } = render(
|
|
29
|
+
<Avatar data-testid="avatar" className="avatar-class">
|
|
30
|
+
<AvatarImage
|
|
31
|
+
data-testid="avatar-image"
|
|
32
|
+
onLoad={loadMock}
|
|
33
|
+
src="https://github.com/shadcn.png"
|
|
34
|
+
alt="@shadcn"
|
|
35
|
+
/>
|
|
36
|
+
<AvatarFallback>CN</AvatarFallback>
|
|
37
|
+
</Avatar>,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const image = screen.getByRole("img");
|
|
41
|
+
fireEvent.load(image);
|
|
42
|
+
expect(loadMock).toHaveBeenCalled();
|
|
43
|
+
|
|
44
|
+
const avatar = screen.getByTestId("avatar");
|
|
45
|
+
expect(avatar).toHaveClass("avatar-class");
|
|
46
|
+
expect(image).toHaveAttribute("src", "https://github.com/shadcn.png");
|
|
47
|
+
expect(image).toHaveAttribute("alt", "@shadcn");
|
|
48
|
+
unmount();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("Common: Avatar - test if renders fallback when image fails to load", () => {
|
|
52
|
+
const loadMock = vi.fn();
|
|
53
|
+
const errorMock = vi.fn();
|
|
54
|
+
|
|
55
|
+
const { unmount } = render(
|
|
56
|
+
<Avatar data-testid="avatar" className="avatar-class">
|
|
57
|
+
<AvatarImage
|
|
58
|
+
data-testid="avatar-image"
|
|
59
|
+
onLoad={loadMock}
|
|
60
|
+
onError={errorMock}
|
|
61
|
+
src="https://github.com/shadcn.png"
|
|
62
|
+
alt="@shadcn"
|
|
63
|
+
/>
|
|
64
|
+
<AvatarFallback>CN</AvatarFallback>
|
|
65
|
+
</Avatar>,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const image = screen.getByRole("img");
|
|
69
|
+
fireEvent.error(image);
|
|
70
|
+
expect(errorMock).toHaveBeenCalled();
|
|
71
|
+
|
|
72
|
+
const fallback = screen.getByText("CN");
|
|
73
|
+
expect(fallback).toBeInTheDocument();
|
|
74
|
+
unmount();
|
|
75
|
+
});
|
|
24
76
|
});
|
package/src/avatar.tsx
CHANGED
|
@@ -1,76 +1,63 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import cn from "classnames";
|
|
5
|
-
import type { ElementType, HTMLProps, ReactNode } from "react";
|
|
6
|
-
import { useState } from "react";
|
|
1
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
2
|
+
import { cn, DefaultComponent, useStackShiftUIComponents } from "@stackshift-ui/system";
|
|
3
|
+
import * as React from "react";
|
|
7
4
|
|
|
8
|
-
|
|
5
|
+
const displayNameAvatar = "Avatar";
|
|
6
|
+
const displayNameAvatarImage = "AvatarImage";
|
|
7
|
+
const displayNameAvatarFallback = "AvatarFallback";
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
children?: ReactNode;
|
|
16
|
-
className?: string;
|
|
17
|
-
as?: ElementType;
|
|
18
|
-
}
|
|
9
|
+
const Avatar = React.forwardRef<
|
|
10
|
+
React.ElementRef<typeof AvatarPrimitive.Root>,
|
|
11
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
|
12
|
+
>(({ className, ...props }, ref) => {
|
|
13
|
+
const { [displayNameAvatar]: Component = DefaultComponent } = useStackShiftUIComponents();
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
...props
|
|
31
|
-
}) => {
|
|
32
|
-
const components = useStackShiftUIComponents();
|
|
33
|
-
const { [displayName]: Component = DefaultComponent } = components;
|
|
15
|
+
return (
|
|
16
|
+
<Component
|
|
17
|
+
as={AvatarPrimitive.Root}
|
|
18
|
+
ref={ref}
|
|
19
|
+
className={cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className)}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
Avatar.displayName = displayNameAvatar;
|
|
34
25
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
xl: 160,
|
|
41
|
-
};
|
|
42
|
-
const avatarSize = typeof size === "number" ? `${size}px` : `${sizeMap[size]}px`;
|
|
43
|
-
const initials = text ? text?.split(" ")?.reduce((acc, curr) => acc + curr[0], "") : "AB";
|
|
44
|
-
const baseClass = `relative flex rounded-full aspect-square overflow-hidden border-2 border-solid border-primary`;
|
|
26
|
+
const AvatarImage = React.forwardRef<
|
|
27
|
+
React.ElementRef<typeof AvatarPrimitive.Image>,
|
|
28
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
|
29
|
+
>(({ className, ...props }, ref) => {
|
|
30
|
+
const { [displayNameAvatarImage]: Component = DefaultComponent } = useStackShiftUIComponents();
|
|
45
31
|
|
|
46
32
|
return (
|
|
47
33
|
<Component
|
|
48
|
-
as={
|
|
49
|
-
|
|
50
|
-
|
|
34
|
+
as={AvatarPrimitive.Image}
|
|
35
|
+
ref={ref}
|
|
36
|
+
className={cn("aspect-square h-full w-full", className)}
|
|
51
37
|
{...props}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
height={100}
|
|
71
|
-
onLoad={() => setLoaded(true)}
|
|
72
|
-
/>
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
AvatarImage.displayName = displayNameAvatarImage;
|
|
42
|
+
|
|
43
|
+
const AvatarFallback = React.forwardRef<
|
|
44
|
+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
|
45
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
|
46
|
+
>(({ className, ...props }, ref) => {
|
|
47
|
+
const { [displayNameAvatarFallback]: Component = DefaultComponent } = useStackShiftUIComponents();
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Component
|
|
51
|
+
as={AvatarPrimitive.Fallback}
|
|
52
|
+
ref={ref}
|
|
53
|
+
className={cn(
|
|
54
|
+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
|
55
|
+
className,
|
|
73
56
|
)}
|
|
74
|
-
|
|
57
|
+
{...props}
|
|
58
|
+
/>
|
|
75
59
|
);
|
|
76
|
-
};
|
|
60
|
+
});
|
|
61
|
+
AvatarFallback.displayName = displayNameAvatarFallback;
|
|
62
|
+
|
|
63
|
+
export { Avatar, AvatarFallback, AvatarImage };
|