@ncds/ui-admin 1.8.26-alpha.5 → 1.8.26-alpha.6
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/cjs/assets/scripts/notification/MessageNotification.js +6 -9
- package/dist/cjs/assets/scripts/notification/const/icons.js +17 -8
- package/dist/cjs/assets/scripts/notification/const/index.js +6 -0
- package/dist/cjs/constant/notification.js +0 -1
- package/dist/cjs/src/components/overlays/notification/FloatingNotification.js +1 -1
- package/dist/cjs/src/components/overlays/notification/MessageNotification.js +13 -9
- package/dist/cjs/src/components/overlays/notification/__tests__/MessageNotification.test.js +55 -13
- package/dist/cjs/src/generated/scoped-css.js +1 -1
- package/dist/esm/assets/scripts/notification/MessageNotification.js +7 -10
- package/dist/esm/assets/scripts/notification/const/icons.js +16 -7
- package/dist/esm/assets/scripts/notification/const/index.js +1 -1
- package/dist/esm/constant/notification.js +0 -1
- package/dist/esm/src/components/overlays/notification/FloatingNotification.js +1 -1
- package/dist/esm/src/components/overlays/notification/MessageNotification.js +13 -9
- package/dist/esm/src/components/overlays/notification/__tests__/MessageNotification.test.js +55 -13
- package/dist/esm/src/generated/scoped-css.js +1 -1
- package/dist/temp/assets/scripts/notification/MessageNotification.d.ts +1 -1
- package/dist/temp/assets/scripts/notification/MessageNotification.js +7 -11
- package/dist/temp/assets/scripts/notification/const/icons.d.ts +6 -6
- package/dist/temp/assets/scripts/notification/const/icons.js +16 -7
- package/dist/temp/assets/scripts/notification/const/index.d.ts +1 -1
- package/dist/temp/assets/scripts/notification/const/index.js +1 -1
- package/dist/temp/assets/scripts/notification/const/types.d.ts +1 -1
- package/dist/temp/constant/notification.d.ts +0 -1
- package/dist/temp/constant/notification.js +0 -1
- package/dist/temp/src/components/overlays/notification/FloatingNotification.js +1 -1
- package/dist/temp/src/components/overlays/notification/MessageNotification.d.ts +1 -1
- package/dist/temp/src/components/overlays/notification/MessageNotification.js +9 -8
- package/dist/temp/src/components/overlays/notification/Notification.d.ts +2 -2
- package/dist/temp/src/components/overlays/notification/__tests__/MessageNotification.test.js +44 -9
- package/dist/temp/src/generated/scoped-css.js +1 -1
- package/dist/types/assets/scripts/notification/MessageNotification.d.ts +1 -1
- package/dist/types/assets/scripts/notification/const/icons.d.ts +6 -6
- package/dist/types/assets/scripts/notification/const/index.d.ts +1 -1
- package/dist/types/assets/scripts/notification/const/types.d.ts +1 -1
- package/dist/types/constant/notification.d.ts +0 -1
- package/dist/types/src/components/overlays/notification/MessageNotification.d.ts +1 -1
- package/dist/types/src/components/overlays/notification/Notification.d.ts +2 -2
- package/dist/ui-admin/assets/styles/style.css +17 -11
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@ export declare class MessageNotification {
|
|
|
9
9
|
private featuredIcon?;
|
|
10
10
|
constructor(options: MessageNotificationOptions);
|
|
11
11
|
private createElement;
|
|
12
|
-
/** 색상별 FeaturedIcon. default 는 md(40/20), block 은 sm(32/16). */
|
|
12
|
+
/** 색상별 FeaturedIcon. default 는 md(40/20), block 은 sm(32/16). info 아이콘만 variant 별로 다르다. */
|
|
13
13
|
private createFeaturedIcon;
|
|
14
14
|
private bindEvents;
|
|
15
15
|
private setupAutoClose;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FeaturedIcon } from '../featuredIcon';
|
|
2
2
|
import { sanitizeHtml } from '../utils/sanitize';
|
|
3
|
-
import { CLASS_NAMES, MESSAGE_BLOCK_SIZES, MESSAGE_ICON_MAP, MESSAGE_SIZES } from './const';
|
|
3
|
+
import { CLASS_NAMES, MESSAGE_BLOCK_ICON_MAP, MESSAGE_BLOCK_SIZES, MESSAGE_ICON_MAP, MESSAGE_SIZES } from './const';
|
|
4
4
|
import { buildMessageTemplate } from './messageTemplate';
|
|
5
5
|
import { applySupportTextLinkTarget, bindNotificationEvents, createWrapperElement, setupAutoClose } from './utils';
|
|
6
6
|
export class MessageNotification {
|
|
@@ -21,16 +21,14 @@ export class MessageNotification {
|
|
|
21
21
|
createElement() {
|
|
22
22
|
const { title, supportingText, color, className, actions, onClose, hideCloseButton, onHidePermanently, hidePermanentlyLabel, variant, supportTextLink, supportTextLinkTarget, } = this.options;
|
|
23
23
|
const isBlock = variant === 'block';
|
|
24
|
-
// default 는 neutral, error, warning, success 4가지 색상만 지원 — info 는 block 에서만 유지한다.
|
|
25
|
-
const actualColor = !isBlock && color === 'info' ? 'neutral' : color;
|
|
26
24
|
const wrapperClassName = [isBlock ? CLASS_NAMES.MESSAGE.BLOCK : '', className].filter(Boolean).join(' ');
|
|
27
|
-
const wrapper = createWrapperElement(CLASS_NAMES.MESSAGE.BASE,
|
|
28
|
-
const featuredIconElement = this.createFeaturedIcon(
|
|
25
|
+
const wrapper = createWrapperElement(CLASS_NAMES.MESSAGE.BASE, color, wrapperClassName);
|
|
26
|
+
const featuredIconElement = this.createFeaturedIcon(color, isBlock);
|
|
29
27
|
wrapper.innerHTML = sanitizeHtml(buildMessageTemplate({
|
|
30
28
|
title,
|
|
31
29
|
supportingText,
|
|
32
30
|
supportTextLink: isBlock ? supportTextLink : undefined,
|
|
33
|
-
color
|
|
31
|
+
color,
|
|
34
32
|
actions,
|
|
35
33
|
onClose,
|
|
36
34
|
hideCloseButton,
|
|
@@ -47,16 +45,14 @@ export class MessageNotification {
|
|
|
47
45
|
}
|
|
48
46
|
return wrapper;
|
|
49
47
|
}
|
|
50
|
-
/** 색상별 FeaturedIcon. default 는 md(40/20), block 은 sm(32/16). */
|
|
48
|
+
/** 색상별 FeaturedIcon. default 는 md(40/20), block 은 sm(32/16). info 아이콘만 variant 별로 다르다. */
|
|
51
49
|
createFeaturedIcon(color, isBlock) {
|
|
52
|
-
const iconFunction = MESSAGE_ICON_MAP[color];
|
|
53
|
-
if (!iconFunction)
|
|
54
|
-
return null;
|
|
50
|
+
const iconFunction = (isBlock ? MESSAGE_BLOCK_ICON_MAP : MESSAGE_ICON_MAP)[color];
|
|
55
51
|
const sizes = isBlock ? MESSAGE_BLOCK_SIZES : MESSAGE_SIZES;
|
|
56
52
|
this.featuredIcon = FeaturedIcon.create({
|
|
57
53
|
svgString: iconFunction(sizes.ICON_PIXEL),
|
|
58
54
|
theme: 'light-circle',
|
|
59
|
-
// FeaturedIcon 에는 info 색이 없다.
|
|
55
|
+
// FeaturedIcon 에는 info 색이 없다. info 의 violet 톤은 message SCSS 가 덮어쓴다.
|
|
60
56
|
color: (color === 'info' ? 'neutral' : color),
|
|
61
57
|
size: sizes.FEATURED_ICON,
|
|
62
58
|
// React 구현과 동일하게 `__icon`(flex-shrink: 0)을 부여한다.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { NotificationColor } from './types';
|
|
2
|
+
type IconFunction = (size: string) => string;
|
|
2
3
|
export declare const SVG_ICONS: {
|
|
3
4
|
readonly 'pin-02': (size: string) => string;
|
|
4
5
|
readonly 'alert-triangle': (size: string) => string;
|
|
@@ -23,9 +24,8 @@ export declare const ICON_MAP: {
|
|
|
23
24
|
readonly success: (size: string) => string;
|
|
24
25
|
readonly info: (size: string) => string;
|
|
25
26
|
};
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export declare const MESSAGE_ICON_MAP: Partial<Record<NotificationColor, (size: string) => string>>;
|
|
27
|
+
/** message 기본 타입 아이콘. floating 과 같은 4색에 info(neutral 과 같은 핀)를 더한다. */
|
|
28
|
+
export declare const MESSAGE_ICON_MAP: Record<NotificationColor, IconFunction>;
|
|
29
|
+
/** block 변형 아이콘. info 만 InfoCircle 로 다르다 (#536 유지). */
|
|
30
|
+
export declare const MESSAGE_BLOCK_ICON_MAP: Record<NotificationColor, IconFunction>;
|
|
31
|
+
export {};
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* message block 변형의 InfoCircle. `SVG_ICONS['info-circle']`은 full-width 전용 class·color 가 박혀 있어
|
|
3
|
+
* 쓰지 않는다 (`.ncua-full-width-notification__icon`은 모바일에서 숨겨진다).
|
|
4
|
+
*/
|
|
5
|
+
const INFO_CIRCLE_ICON = (size) => `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" fill="none" viewBox="0 0 24 24" stroke="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 16v-4m0-4h.01M22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10"></path></svg>`;
|
|
1
6
|
// SVG 아이콘들 (크기는 동적으로 설정)
|
|
2
7
|
export const SVG_ICONS = {
|
|
3
8
|
'pin-02': (size) => `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" fill="none" viewBox="0 0 24 24" stroke="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.377 15.616 2.72 21.273m8.974-14.631-1.56 1.56a2 2 0 0 1-.264.242 1 1 0 0 1-.207.111c-.082.032-.17.05-.347.085l-3.665.733c-.952.19-1.428.286-1.65.537a1 1 0 0 0-.243.8c.046.333.39.677 1.076 1.363l7.086 7.086c.686.687 1.03 1.03 1.362 1.076a1 1 0 0 0 .801-.242c.251-.223.346-.7.537-1.651l.733-3.665c.035-.176.053-.265.085-.347a1 1 0 0 1 .11-.207c.051-.072.115-.136.242-.263l1.561-1.561c.082-.082.122-.122.167-.158q.06-.047.126-.085c.05-.029.103-.051.208-.097l2.495-1.069c.727-.312 1.091-.467 1.256-.72a1 1 0 0 0 .144-.747c-.06-.295-.34-.575-.9-1.135l-5.142-5.143c-.56-.56-.84-.84-1.135-.9a1 1 0 0 0-.748.145c-.252.165-.407.529-.72 1.256l-1.068 2.495a2 2 0 0 1-.097.208 1 1 0 0 1-.085.126 2 2 0 0 1-.158.167"></path></svg>`,
|
|
@@ -23,12 +28,16 @@ export const FULL_WIDTH_ICON_MAP = {
|
|
|
23
28
|
info: SVG_ICONS['info-circle'],
|
|
24
29
|
};
|
|
25
30
|
export const ICON_MAP = FULL_WIDTH_ICON_MAP;
|
|
26
|
-
/**
|
|
27
|
-
* message 타입 아이콘. floating 과 같은 4색에 block 변형 전용 info 를 더한다.
|
|
28
|
-
* `SVG_ICONS['info-circle']`은 full-width 전용 class·color 가 박혀 있어 쓰지 않는다
|
|
29
|
-
* (`.ncua-full-width-notification__icon`은 모바일에서 숨겨진다).
|
|
30
|
-
*/
|
|
31
|
+
/** message 기본 타입 아이콘. floating 과 같은 4색에 info(neutral 과 같은 핀)를 더한다. */
|
|
31
32
|
export const MESSAGE_ICON_MAP = {
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
neutral: SVG_ICONS['pin-02'],
|
|
34
|
+
error: SVG_ICONS['alert-triangle'],
|
|
35
|
+
warning: SVG_ICONS['alert-circle'],
|
|
36
|
+
success: SVG_ICONS['check-circle'],
|
|
37
|
+
info: SVG_ICONS['pin-02'],
|
|
38
|
+
};
|
|
39
|
+
/** block 변형 아이콘. info 만 InfoCircle 로 다르다 (#536 유지). */
|
|
40
|
+
export const MESSAGE_BLOCK_ICON_MAP = {
|
|
41
|
+
...MESSAGE_ICON_MAP,
|
|
42
|
+
info: INFO_CIRCLE_ICON,
|
|
34
43
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { CLASS_NAMES } from './classNames';
|
|
2
|
-
export { FLOATING_ICON_MAP, FULL_WIDTH_ICON_MAP, ICON_MAP, MESSAGE_ICON_MAP, SVG_ICONS } from './icons';
|
|
2
|
+
export { FLOATING_ICON_MAP, FULL_WIDTH_ICON_MAP, ICON_MAP, MESSAGE_BLOCK_ICON_MAP, MESSAGE_ICON_MAP, SVG_ICONS, } from './icons';
|
|
3
3
|
export { CLOSE_BUTTON_SIZES, CLOSE_BUTTON_SVG_SIZES, FEATURED_ICON_SIZES, FULL_WIDTH_SIZES, getSizes, ICON_PIXEL_SIZES, MESSAGE_BLOCK_SIZES, MESSAGE_SIZES, } from './sizes';
|
|
4
4
|
export type { BaseNotificationOptions, LegacyNotificationHierarchy, NotificationAction, NotificationActionButtonSize, NotificationColor, NotificationHierarchy, NotificationLinkTarget, NotificationVariant, } from './types';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// Re-export all constants and types from separate files
|
|
2
2
|
export { CLASS_NAMES } from './classNames';
|
|
3
|
-
export { FLOATING_ICON_MAP, FULL_WIDTH_ICON_MAP, ICON_MAP, MESSAGE_ICON_MAP, SVG_ICONS } from './icons';
|
|
3
|
+
export { FLOATING_ICON_MAP, FULL_WIDTH_ICON_MAP, ICON_MAP, MESSAGE_BLOCK_ICON_MAP, MESSAGE_ICON_MAP, SVG_ICONS, } from './icons';
|
|
4
4
|
export { CLOSE_BUTTON_SIZES, CLOSE_BUTTON_SVG_SIZES, FEATURED_ICON_SIZES, FULL_WIDTH_SIZES, getSizes, ICON_PIXEL_SIZES, MESSAGE_BLOCK_SIZES, MESSAGE_SIZES, } from './sizes';
|
|
@@ -2,7 +2,7 @@ export type NotificationColor = 'neutral' | 'error' | 'warning' | 'success' | 'i
|
|
|
2
2
|
/**
|
|
3
3
|
* message 타입의 표시 변형. React `NotificationVariant`와 같은 어휘다.
|
|
4
4
|
* - `'default'`: 기존 message
|
|
5
|
-
* - `'block'`: 서브 페이지 공지용 (흰 배경, FeaturedIcon sm, 제목 + 텍스트 링크 1행, info
|
|
5
|
+
* - `'block'`: 서브 페이지 공지용 (흰 배경, FeaturedIcon sm, 제목 + 텍스트 링크 1행, info 아이콘 InfoCircle)
|
|
6
6
|
*/
|
|
7
7
|
export type NotificationVariant = 'default' | 'block';
|
|
8
8
|
/**
|
|
@@ -17,7 +17,6 @@ export declare const HIDE_PERMANENTLY_LABEL: {
|
|
|
17
17
|
* message 타입 닫기(X) 아이콘의 color 별 색.
|
|
18
18
|
*
|
|
19
19
|
* React(`MessageNotification.tsx`)와 Vanilla(`messageTemplate.ts`)가 함께 참조하는 단일 출처다.
|
|
20
|
-
* `info`는 `variant: 'block'`에서만 렌더된다(default 는 neutral 로 폴백).
|
|
21
20
|
*/
|
|
22
21
|
export declare const MESSAGE_CLOSE_ICON_COLOR: {
|
|
23
22
|
readonly neutral: string;
|
|
@@ -18,7 +18,6 @@ export const HIDE_PERMANENTLY_LABEL = {
|
|
|
18
18
|
* message 타입 닫기(X) 아이콘의 color 별 색.
|
|
19
19
|
*
|
|
20
20
|
* React(`MessageNotification.tsx`)와 Vanilla(`messageTemplate.ts`)가 함께 참조하는 단일 출처다.
|
|
21
|
-
* `info`는 `variant: 'block'`에서만 렌더된다(default 는 neutral 로 폴백).
|
|
22
21
|
*/
|
|
23
22
|
export const MESSAGE_CLOSE_ICON_COLOR = {
|
|
24
23
|
neutral: COLOR.gray700,
|
|
@@ -54,7 +54,7 @@ interface MessageNotificationProps extends Omit<ComponentPropsWithoutRef<'div'>,
|
|
|
54
54
|
*/
|
|
55
55
|
hidePermanentlyLabel?: ReactNode;
|
|
56
56
|
/**
|
|
57
|
-
* 표시 변형. `'block'`은 서브 페이지 공지용(흰 배경, FeaturedIcon sm, 제목 + 텍스트 링크 1
|
|
57
|
+
* 표시 변형. `'block'`은 서브 페이지 공지용(흰 배경, FeaturedIcon sm, 제목 + 텍스트 링크 1행)
|
|
58
58
|
* @default 'default'
|
|
59
59
|
*/
|
|
60
60
|
variant?: NotificationVariant;
|
|
@@ -5,26 +5,27 @@ import { forwardRef } from 'react';
|
|
|
5
5
|
import { MESSAGE_CLOSE_ICON_COLOR } from '../../../../constant/notification';
|
|
6
6
|
import { MessageNotificationActions, MessageNotificationContent } from './MessageNotificationParts';
|
|
7
7
|
import { useAutoClose } from './useAutoClose';
|
|
8
|
-
const
|
|
8
|
+
const DEFAULT_ICON_MAP = {
|
|
9
9
|
neutral: Pin02,
|
|
10
10
|
error: AlertTriangle,
|
|
11
11
|
warning: AlertCircle,
|
|
12
12
|
success: CheckCircle,
|
|
13
|
-
//
|
|
14
|
-
info:
|
|
13
|
+
// 디자인 기준 default 의 info 는 neutral 과 같은 핀이다.
|
|
14
|
+
info: Pin02,
|
|
15
15
|
};
|
|
16
|
+
// block 의 info 는 InfoCircle 을 유지한다 (#536).
|
|
17
|
+
const BLOCK_ICON_MAP = { ...DEFAULT_ICON_MAP, info: InfoCircle };
|
|
16
18
|
const MessageNotification = forwardRef(({ title, supportingText, icon: Icon, color = 'neutral', onClose, hideCloseButton = false, autoClose, className, actions, onHidePermanently, hidePermanentlyLabel, variant = 'default', supportTextLink, supportTextLinkTarget, ...rest }, ref) => {
|
|
17
19
|
const isBlock = variant === 'block';
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const featuredIconColor = validColor === 'info' ? 'neutral' : validColor;
|
|
20
|
+
const iconMap = isBlock ? BLOCK_ICON_MAP : DEFAULT_ICON_MAP;
|
|
21
|
+
// FeaturedIcon 에는 info 색이 없다. info 의 violet 톤은 message SCSS 가 덮어쓴다.
|
|
22
|
+
const featuredIconColor = color === 'info' ? 'neutral' : color;
|
|
22
23
|
// message 는 부모가 언마운트로 닫으므로 hideCloseButton 기본 autoClose 를 적용하지 않는다.
|
|
23
24
|
const shouldRemove = useAutoClose({ autoClose, onClose });
|
|
24
25
|
if (shouldRemove) {
|
|
25
26
|
return null;
|
|
26
27
|
}
|
|
27
|
-
return (_jsx("div", { ref: ref, className: classNames('ncua-message-notification', `ncua-message-notification--${
|
|
28
|
+
return (_jsx("div", { ref: ref, className: classNames('ncua-message-notification', `ncua-message-notification--${color}`, { 'ncua-message-notification--block': isBlock }, className), role: "alert", ...rest, children: _jsx("div", { className: "ncua-message-notification__container", children: _jsxs("div", { className: "ncua-message-notification__content", children: [_jsx(MessageNotificationContent, { title: title, supportingText: supportingText, supportTextLink: isBlock ? supportTextLink : undefined, supportTextLinkTarget: supportTextLinkTarget, icon: Icon || iconMap[color], iconColor: featuredIconColor, iconSize: isBlock ? 'sm' : 'md' }), _jsx(MessageNotificationActions, { actions: actions, onClose: onClose, hideCloseButton: hideCloseButton, onHidePermanently: onHidePermanently, hidePermanentlyLabel: hidePermanentlyLabel, closeIconColor: MESSAGE_CLOSE_ICON_COLOR[color] })] }) }) }));
|
|
28
29
|
});
|
|
29
30
|
MessageNotification.displayName = 'MessageNotification';
|
|
30
31
|
export { MessageNotification };
|
|
@@ -107,10 +107,10 @@ interface NotificationProps extends Omit<ComponentPropsWithoutRef<'div'>, 'title
|
|
|
107
107
|
/**
|
|
108
108
|
* message 타입의 표시 변형 (선택사항). message 타입에서만 동작한다.
|
|
109
109
|
*
|
|
110
|
-
* - `'default'`: 기존 message (color 별 배경·테두리, 제목 + 본문 2
|
|
110
|
+
* - `'default'`: 기존 message (color 별 배경·테두리, 제목 + 본문 2행)
|
|
111
111
|
* - `'block'`: 서브 페이지 공지용. 흰 배경·gray-100 테두리·shadow-sm, FeaturedIcon sm,
|
|
112
112
|
* 제목 + 텍스트 링크 1행(`supportingText` 가 링크 텍스트, `supportTextLink` 가 href).
|
|
113
|
-
*
|
|
113
|
+
* info 아이콘은 InfoCircle.
|
|
114
114
|
*
|
|
115
115
|
* @default 'default'
|
|
116
116
|
*/
|
package/dist/temp/src/components/overlays/notification/__tests__/MessageNotification.test.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// @vitest-environment jsdom
|
|
2
|
+
import { InfoCircle, Pin02 } from '@ncds/ui-admin-icon';
|
|
2
3
|
import { createElement } from 'react';
|
|
3
4
|
import { createRoot } from 'react-dom/client';
|
|
4
5
|
import { act } from 'react-dom/test-utils';
|
|
@@ -18,16 +19,26 @@ const SELECTOR = {
|
|
|
18
19
|
CLOSE_BUTTON: '.ncua-message-notification__close-button',
|
|
19
20
|
};
|
|
20
21
|
const mounted = [];
|
|
21
|
-
function
|
|
22
|
+
function mount(element) {
|
|
22
23
|
const container = document.createElement('div');
|
|
23
24
|
document.body.appendChild(container);
|
|
24
25
|
const root = createRoot(container);
|
|
25
26
|
act(() => {
|
|
26
|
-
root.render(
|
|
27
|
+
root.render(element);
|
|
27
28
|
});
|
|
28
29
|
mounted.push({ root, container });
|
|
29
30
|
return container;
|
|
30
31
|
}
|
|
32
|
+
function renderMessageNotification(props = {}) {
|
|
33
|
+
return mount(createElement(MessageNotification, { title: '알림 제목', ...props }));
|
|
34
|
+
}
|
|
35
|
+
/** 아이콘 컴포넌트를 단독 렌더해 `path[d]` 를 얻는다. 아이콘 판정은 d 비교로 한다. */
|
|
36
|
+
function iconPathD(Icon) {
|
|
37
|
+
return mount(createElement(Icon)).querySelector('path')?.getAttribute('d') ?? null;
|
|
38
|
+
}
|
|
39
|
+
function renderedIconPathD(container) {
|
|
40
|
+
return container.querySelector(`${SELECTOR.ICON} svg path`)?.getAttribute('d') ?? null;
|
|
41
|
+
}
|
|
31
42
|
afterEach(() => {
|
|
32
43
|
for (const { root, container } of mounted.splice(0)) {
|
|
33
44
|
act(() => {
|
|
@@ -114,15 +125,39 @@ describe('MessageNotification (React) — DOM 구조 계약', () => {
|
|
|
114
125
|
]);
|
|
115
126
|
});
|
|
116
127
|
});
|
|
117
|
-
describe('MessageNotification (React) —
|
|
118
|
-
it('
|
|
119
|
-
// Given/When:
|
|
128
|
+
describe('MessageNotification (React) — color="info" (#568)', () => {
|
|
129
|
+
it('R-01: color="info" 는 neutral 로 폴백하지 않고 --info 수식자로 렌더한다', () => {
|
|
130
|
+
// Given/When: variant 미지정, info 색상으로 렌더하면
|
|
131
|
+
const root = renderMessageNotification({ color: 'info' }).querySelector(SELECTOR.ROOT);
|
|
132
|
+
// Then: info 수식자가 있고 neutral 수식자는 없다
|
|
133
|
+
expect(root?.classList.contains('ncua-message-notification--info')).toBe(true);
|
|
134
|
+
expect(root?.classList.contains('ncua-message-notification--neutral')).toBe(false);
|
|
135
|
+
});
|
|
136
|
+
it('R-02: 기본 info 아이콘은 neutral 과 같은 Pin02 다', () => {
|
|
137
|
+
// Given/When: variant 미지정, info 색상으로 렌더하면
|
|
120
138
|
const container = renderMessageNotification({ color: 'info' });
|
|
121
|
-
// Then:
|
|
122
|
-
const
|
|
123
|
-
expect(
|
|
124
|
-
expect(
|
|
139
|
+
// Then: 아이콘 path 가 Pin02 와 같다
|
|
140
|
+
const expected = iconPathD(Pin02);
|
|
141
|
+
expect(expected).not.toBeNull();
|
|
142
|
+
expect(renderedIconPathD(container)).toBe(expected);
|
|
143
|
+
});
|
|
144
|
+
it('R-03: info 의 FeaturedIcon 은 neutral·md 로 렌더한다 (violet 톤은 SCSS 가 덮는다)', () => {
|
|
145
|
+
// Given/When: variant 미지정, info 색상으로 렌더하면
|
|
146
|
+
const icon = renderMessageNotification({ color: 'info' }).querySelector(SELECTOR.ICON);
|
|
147
|
+
// Then: FeaturedIcon 에는 info 색이 없으므로 neutral 수식자와 md 사이즈가 유지된다
|
|
148
|
+
expect(icon?.classList.contains('ncua-featured-icon--neutral')).toBe(true);
|
|
149
|
+
expect(icon?.classList.contains('ncua-featured-icon--md')).toBe(true);
|
|
125
150
|
});
|
|
151
|
+
it('R-04: block 의 info 아이콘은 InfoCircle 을 유지한다', () => {
|
|
152
|
+
// Given/When: block 변형에 info 색상으로 렌더하면
|
|
153
|
+
const container = renderMessageNotification({ variant: 'block', color: 'info' });
|
|
154
|
+
// Then: 아이콘 path 가 InfoCircle 과 같다 (#536 회귀)
|
|
155
|
+
const expected = iconPathD(InfoCircle);
|
|
156
|
+
expect(expected).not.toBeNull();
|
|
157
|
+
expect(renderedIconPathD(container)).toBe(expected);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
describe('MessageNotification (React) — 공개 API 회귀 방지', () => {
|
|
126
161
|
it('닫기/다시 보지 않기 클릭 시 핸들러가 호출되고 접근성 속성이 유지된다', () => {
|
|
127
162
|
// Given: 핸들러를 지정해 렌더하고
|
|
128
163
|
const onClose = vi.fn();
|