@axis-ds/ui-react 1.5.2 → 1.6.1
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/avatar.d.mts +10 -0
- package/dist/avatar/avatar.d.ts +10 -0
- package/dist/avatar/avatar.js +24 -2
- package/dist/avatar/avatar.mjs +24 -2
- package/dist/command/index.d.mts +7 -7
- package/dist/command/index.d.ts +7 -7
- package/package.json +2 -2
package/dist/avatar/avatar.d.mts
CHANGED
|
@@ -17,6 +17,16 @@ interface AvatarProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps
|
|
|
17
17
|
/**
|
|
18
18
|
* 사용자 프로필 이미지를 표시하는 아바타 컴포넌트
|
|
19
19
|
* 이미지 로드 실패 시 이니셜 fallback을 표시한다.
|
|
20
|
+
*
|
|
21
|
+
* 실패 판정은 두 경로다(WI-0054).
|
|
22
|
+
* 1. `<img onError>`: 하이드레이션 뒤(또는 클라이언트 렌더)에 난 오류.
|
|
23
|
+
* 2. 마운트 시 검사: 서버 렌더된 이미지의 오류가 하이드레이션 전에 끝나면 onError 가 붙기 전이라
|
|
24
|
+
* 이벤트를 놓친다. 그래서 마운트(와 src 변경) 때 `complete && naturalWidth === 0` 이면 실패 후보로 보고,
|
|
25
|
+
* `img.decode()` 가 거부될 때만 실패로 확정한다. 고유 크기가 없는 SVG 처럼 정상 로드인데
|
|
26
|
+
* naturalWidth 가 0 일 수 있는 이미지는 decode 가 이행되므로 실패로 보지 않는다.
|
|
27
|
+
* decode 가 없는 환경에서는 판정하지 않는다(종전 동작).
|
|
28
|
+
*
|
|
29
|
+
* 실패 상태는 실패한 src 와 함께 기억한다. src 가 바뀌면 렌더 중에 초기화해 새 이미지를 다시 시도한다.
|
|
20
30
|
*/
|
|
21
31
|
declare const Avatar: React.ForwardRefExoticComponent<AvatarProps & React.RefAttributes<HTMLDivElement>>;
|
|
22
32
|
|
package/dist/avatar/avatar.d.ts
CHANGED
|
@@ -17,6 +17,16 @@ interface AvatarProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps
|
|
|
17
17
|
/**
|
|
18
18
|
* 사용자 프로필 이미지를 표시하는 아바타 컴포넌트
|
|
19
19
|
* 이미지 로드 실패 시 이니셜 fallback을 표시한다.
|
|
20
|
+
*
|
|
21
|
+
* 실패 판정은 두 경로다(WI-0054).
|
|
22
|
+
* 1. `<img onError>`: 하이드레이션 뒤(또는 클라이언트 렌더)에 난 오류.
|
|
23
|
+
* 2. 마운트 시 검사: 서버 렌더된 이미지의 오류가 하이드레이션 전에 끝나면 onError 가 붙기 전이라
|
|
24
|
+
* 이벤트를 놓친다. 그래서 마운트(와 src 변경) 때 `complete && naturalWidth === 0` 이면 실패 후보로 보고,
|
|
25
|
+
* `img.decode()` 가 거부될 때만 실패로 확정한다. 고유 크기가 없는 SVG 처럼 정상 로드인데
|
|
26
|
+
* naturalWidth 가 0 일 수 있는 이미지는 decode 가 이행되므로 실패로 보지 않는다.
|
|
27
|
+
* decode 가 없는 환경에서는 판정하지 않는다(종전 동작).
|
|
28
|
+
*
|
|
29
|
+
* 실패 상태는 실패한 src 와 함께 기억한다. src 가 바뀌면 렌더 중에 초기화해 새 이미지를 다시 시도한다.
|
|
20
30
|
*/
|
|
21
31
|
declare const Avatar: React.ForwardRefExoticComponent<AvatarProps & React.RefAttributes<HTMLDivElement>>;
|
|
22
32
|
|
package/dist/avatar/avatar.js
CHANGED
|
@@ -38,7 +38,28 @@ var import_utils = require("../utils.js");
|
|
|
38
38
|
var import_variants = require("./variants.js");
|
|
39
39
|
const Avatar = React.forwardRef(
|
|
40
40
|
({ className, size, src, alt, fallback, ...props }, ref) => {
|
|
41
|
-
const [
|
|
41
|
+
const [failedSrc, setFailedSrc] = React.useState(null);
|
|
42
|
+
if (failedSrc !== null && failedSrc !== src) {
|
|
43
|
+
setFailedSrc(null);
|
|
44
|
+
}
|
|
45
|
+
const hasError = failedSrc !== null && failedSrc === src;
|
|
46
|
+
const imgRef = React.useRef(null);
|
|
47
|
+
React.useEffect(() => {
|
|
48
|
+
const img = imgRef.current;
|
|
49
|
+
if (!img || !src) return;
|
|
50
|
+
if (!img.complete || img.naturalWidth !== 0) return;
|
|
51
|
+
if (typeof img.decode !== "function") return;
|
|
52
|
+
let cancelled = false;
|
|
53
|
+
img.decode().then(
|
|
54
|
+
() => void 0,
|
|
55
|
+
() => {
|
|
56
|
+
if (!cancelled) setFailedSrc(src);
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
return () => {
|
|
60
|
+
cancelled = true;
|
|
61
|
+
};
|
|
62
|
+
}, [src]);
|
|
42
63
|
const initials = React.useMemo(() => {
|
|
43
64
|
if (fallback) return fallback;
|
|
44
65
|
if (!alt) return "?";
|
|
@@ -53,10 +74,11 @@ const Avatar = React.forwardRef(
|
|
|
53
74
|
children: src && !hasError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
54
75
|
"img",
|
|
55
76
|
{
|
|
77
|
+
ref: imgRef,
|
|
56
78
|
src,
|
|
57
79
|
alt: alt || "Avatar",
|
|
58
80
|
className: "aspect-square h-full w-full object-cover",
|
|
59
|
-
onError: () =>
|
|
81
|
+
onError: () => setFailedSrc(src)
|
|
60
82
|
}
|
|
61
83
|
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex h-full w-full items-center justify-center bg-[var(--axis-surface-tertiary)] text-[var(--axis-text-secondary)] font-medium", children: initials })
|
|
62
84
|
}
|
package/dist/avatar/avatar.mjs
CHANGED
|
@@ -5,7 +5,28 @@ import { cn } from "../utils.mjs";
|
|
|
5
5
|
import { avatarVariants } from "./variants.mjs";
|
|
6
6
|
const Avatar = React.forwardRef(
|
|
7
7
|
({ className, size, src, alt, fallback, ...props }, ref) => {
|
|
8
|
-
const [
|
|
8
|
+
const [failedSrc, setFailedSrc] = React.useState(null);
|
|
9
|
+
if (failedSrc !== null && failedSrc !== src) {
|
|
10
|
+
setFailedSrc(null);
|
|
11
|
+
}
|
|
12
|
+
const hasError = failedSrc !== null && failedSrc === src;
|
|
13
|
+
const imgRef = React.useRef(null);
|
|
14
|
+
React.useEffect(() => {
|
|
15
|
+
const img = imgRef.current;
|
|
16
|
+
if (!img || !src) return;
|
|
17
|
+
if (!img.complete || img.naturalWidth !== 0) return;
|
|
18
|
+
if (typeof img.decode !== "function") return;
|
|
19
|
+
let cancelled = false;
|
|
20
|
+
img.decode().then(
|
|
21
|
+
() => void 0,
|
|
22
|
+
() => {
|
|
23
|
+
if (!cancelled) setFailedSrc(src);
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
return () => {
|
|
27
|
+
cancelled = true;
|
|
28
|
+
};
|
|
29
|
+
}, [src]);
|
|
9
30
|
const initials = React.useMemo(() => {
|
|
10
31
|
if (fallback) return fallback;
|
|
11
32
|
if (!alt) return "?";
|
|
@@ -20,10 +41,11 @@ const Avatar = React.forwardRef(
|
|
|
20
41
|
children: src && !hasError ? /* @__PURE__ */ jsx(
|
|
21
42
|
"img",
|
|
22
43
|
{
|
|
44
|
+
ref: imgRef,
|
|
23
45
|
src,
|
|
24
46
|
alt: alt || "Avatar",
|
|
25
47
|
className: "aspect-square h-full w-full object-cover",
|
|
26
|
-
onError: () =>
|
|
48
|
+
onError: () => setFailedSrc(src)
|
|
27
49
|
}
|
|
28
50
|
) : /* @__PURE__ */ jsx("span", { className: "flex h-full w-full items-center justify-center bg-[var(--axis-surface-tertiary)] text-[var(--axis-text-secondary)] font-medium", children: initials })
|
|
29
51
|
}
|
package/dist/command/index.d.mts
CHANGED
|
@@ -10,7 +10,7 @@ declare const Command: React.ForwardRefExoticComponent<Omit<{
|
|
|
10
10
|
ref?: React.Ref<HTMLDivElement>;
|
|
11
11
|
} & {
|
|
12
12
|
asChild?: boolean;
|
|
13
|
-
}, "
|
|
13
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
14
14
|
label?: string;
|
|
15
15
|
shouldFilter?: boolean;
|
|
16
16
|
filter?: (value: string, search: string, keywords?: string[]) => number;
|
|
@@ -26,7 +26,7 @@ declare const CommandInput: React.ForwardRefExoticComponent<Omit<Omit<Pick<Pick<
|
|
|
26
26
|
ref?: React.Ref<HTMLInputElement>;
|
|
27
27
|
} & {
|
|
28
28
|
asChild?: boolean;
|
|
29
|
-
}, "
|
|
29
|
+
}, "key" | "asChild" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "value" | "type"> & {
|
|
30
30
|
value?: string;
|
|
31
31
|
onValueChange?: (search: string) => void;
|
|
32
32
|
} & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -37,7 +37,7 @@ declare const CommandList: React.ForwardRefExoticComponent<Omit<{
|
|
|
37
37
|
ref?: React.Ref<HTMLDivElement>;
|
|
38
38
|
} & {
|
|
39
39
|
asChild?: boolean;
|
|
40
|
-
}, "
|
|
40
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
41
41
|
label?: string;
|
|
42
42
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
43
43
|
/** 검색 결과가 없을 때 표시되는 빈 상태 컴포넌트 */
|
|
@@ -47,7 +47,7 @@ declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
|
|
|
47
47
|
ref?: React.Ref<HTMLDivElement>;
|
|
48
48
|
} & {
|
|
49
49
|
asChild?: boolean;
|
|
50
|
-
}, "
|
|
50
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
51
51
|
/** 관련 명령어 항목들을 그룹화하는 컴포넌트 */
|
|
52
52
|
declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
|
|
53
53
|
children?: React.ReactNode;
|
|
@@ -55,7 +55,7 @@ declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
|
|
|
55
55
|
ref?: React.Ref<HTMLDivElement>;
|
|
56
56
|
} & {
|
|
57
57
|
asChild?: boolean;
|
|
58
|
-
}, "
|
|
58
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "heading" | "value"> & {
|
|
59
59
|
heading?: React.ReactNode;
|
|
60
60
|
value?: string;
|
|
61
61
|
forceMount?: boolean;
|
|
@@ -65,7 +65,7 @@ declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<R
|
|
|
65
65
|
ref?: React.Ref<HTMLDivElement>;
|
|
66
66
|
} & {
|
|
67
67
|
asChild?: boolean;
|
|
68
|
-
}, "
|
|
68
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
69
69
|
alwaysRender?: boolean;
|
|
70
70
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
71
71
|
/** 명령어 팔레트의 개별 선택 가능한 항목 */
|
|
@@ -75,7 +75,7 @@ declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
|
|
|
75
75
|
ref?: React.Ref<HTMLDivElement>;
|
|
76
76
|
} & {
|
|
77
77
|
asChild?: boolean;
|
|
78
|
-
}, "
|
|
78
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "onSelect" | "disabled" | "value"> & {
|
|
79
79
|
disabled?: boolean;
|
|
80
80
|
onSelect?: (value: string) => void;
|
|
81
81
|
value?: string;
|
package/dist/command/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ declare const Command: React.ForwardRefExoticComponent<Omit<{
|
|
|
10
10
|
ref?: React.Ref<HTMLDivElement>;
|
|
11
11
|
} & {
|
|
12
12
|
asChild?: boolean;
|
|
13
|
-
}, "
|
|
13
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
14
14
|
label?: string;
|
|
15
15
|
shouldFilter?: boolean;
|
|
16
16
|
filter?: (value: string, search: string, keywords?: string[]) => number;
|
|
@@ -26,7 +26,7 @@ declare const CommandInput: React.ForwardRefExoticComponent<Omit<Omit<Pick<Pick<
|
|
|
26
26
|
ref?: React.Ref<HTMLInputElement>;
|
|
27
27
|
} & {
|
|
28
28
|
asChild?: boolean;
|
|
29
|
-
}, "
|
|
29
|
+
}, "key" | "asChild" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "value" | "type"> & {
|
|
30
30
|
value?: string;
|
|
31
31
|
onValueChange?: (search: string) => void;
|
|
32
32
|
} & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -37,7 +37,7 @@ declare const CommandList: React.ForwardRefExoticComponent<Omit<{
|
|
|
37
37
|
ref?: React.Ref<HTMLDivElement>;
|
|
38
38
|
} & {
|
|
39
39
|
asChild?: boolean;
|
|
40
|
-
}, "
|
|
40
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
41
41
|
label?: string;
|
|
42
42
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
43
43
|
/** 검색 결과가 없을 때 표시되는 빈 상태 컴포넌트 */
|
|
@@ -47,7 +47,7 @@ declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
|
|
|
47
47
|
ref?: React.Ref<HTMLDivElement>;
|
|
48
48
|
} & {
|
|
49
49
|
asChild?: boolean;
|
|
50
|
-
}, "
|
|
50
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
51
51
|
/** 관련 명령어 항목들을 그룹화하는 컴포넌트 */
|
|
52
52
|
declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
|
|
53
53
|
children?: React.ReactNode;
|
|
@@ -55,7 +55,7 @@ declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
|
|
|
55
55
|
ref?: React.Ref<HTMLDivElement>;
|
|
56
56
|
} & {
|
|
57
57
|
asChild?: boolean;
|
|
58
|
-
}, "
|
|
58
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "heading" | "value"> & {
|
|
59
59
|
heading?: React.ReactNode;
|
|
60
60
|
value?: string;
|
|
61
61
|
forceMount?: boolean;
|
|
@@ -65,7 +65,7 @@ declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<R
|
|
|
65
65
|
ref?: React.Ref<HTMLDivElement>;
|
|
66
66
|
} & {
|
|
67
67
|
asChild?: boolean;
|
|
68
|
-
}, "
|
|
68
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
69
69
|
alwaysRender?: boolean;
|
|
70
70
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
71
71
|
/** 명령어 팔레트의 개별 선택 가능한 항목 */
|
|
@@ -75,7 +75,7 @@ declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
|
|
|
75
75
|
ref?: React.Ref<HTMLDivElement>;
|
|
76
76
|
} & {
|
|
77
77
|
asChild?: boolean;
|
|
78
|
-
}, "
|
|
78
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "onSelect" | "disabled" | "value"> & {
|
|
79
79
|
disabled?: boolean;
|
|
80
80
|
onSelect?: (value: string) => void;
|
|
81
81
|
value?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axis-ds/ui-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "AXIS Design System - Core React UI Components",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -292,7 +292,7 @@
|
|
|
292
292
|
"clsx": "^2.1.0",
|
|
293
293
|
"cmdk": "^1.1.1",
|
|
294
294
|
"tailwind-merge": "^2.5.0",
|
|
295
|
-
"@axis-ds/tokens": "1.
|
|
295
|
+
"@axis-ds/tokens": "1.6.0"
|
|
296
296
|
},
|
|
297
297
|
"devDependencies": {
|
|
298
298
|
"@testing-library/jest-dom": "^6.9.1",
|