@ncds/ui-admin 1.8.26-alpha.6 → 1.8.26-alpha.8
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/FloatingNotification.js +4 -1
- package/dist/cjs/assets/scripts/notification/FullWidthNotification.js +5 -1
- package/dist/cjs/assets/scripts/notification/MessageNotification.js +7 -16
- package/dist/cjs/assets/scripts/notification/const/classNames.js +0 -2
- package/dist/cjs/assets/scripts/notification/const/icons.js +1 -11
- package/dist/cjs/assets/scripts/notification/const/index.js +0 -12
- package/dist/cjs/assets/scripts/notification/const/sizes.js +1 -6
- package/dist/cjs/assets/scripts/notification/messageTemplate.js +4 -2
- package/dist/cjs/assets/scripts/notification/utils.js +13 -5
- package/dist/cjs/src/components/overlays/notification/MessageNotification.js +4 -19
- package/dist/cjs/src/components/overlays/notification/MessageNotificationParts.js +7 -18
- package/dist/cjs/src/components/overlays/notification/Notification.js +6 -5
- package/dist/cjs/src/components/overlays/notification/__tests__/MessageNotification.test.js +7 -7
- package/dist/cjs/src/components/overlays/notification/__tests__/Notification.test.js +8 -0
- package/dist/cjs/src/components/overlays/notification/__tests__/supportTextLink.test.js +1 -7
- package/dist/cjs/src/generated/scoped-css.js +1 -1
- package/dist/cjs/src/utils/url/isSafeUrl.js +1 -1
- package/dist/cjs/vitest.config.js +12 -1
- package/dist/esm/assets/scripts/notification/FloatingNotification.js +4 -1
- package/dist/esm/assets/scripts/notification/FullWidthNotification.js +5 -1
- package/dist/esm/assets/scripts/notification/MessageNotification.js +9 -18
- package/dist/esm/assets/scripts/notification/const/classNames.js +0 -2
- package/dist/esm/assets/scripts/notification/const/icons.js +0 -10
- package/dist/esm/assets/scripts/notification/const/index.js +2 -2
- package/dist/esm/assets/scripts/notification/const/sizes.js +0 -5
- package/dist/esm/assets/scripts/notification/messageTemplate.js +4 -2
- package/dist/esm/assets/scripts/notification/utils.js +11 -4
- package/dist/esm/src/components/overlays/notification/MessageNotification.js +5 -20
- package/dist/esm/src/components/overlays/notification/MessageNotificationParts.js +7 -18
- package/dist/esm/src/components/overlays/notification/Notification.js +6 -5
- package/dist/esm/src/components/overlays/notification/__tests__/MessageNotification.test.js +8 -8
- package/dist/esm/src/components/overlays/notification/__tests__/Notification.test.js +8 -0
- package/dist/esm/src/components/overlays/notification/__tests__/supportTextLink.test.js +1 -7
- package/dist/esm/src/generated/scoped-css.js +1 -1
- package/dist/esm/src/utils/url/isSafeUrl.js +1 -1
- package/dist/esm/vitest.config.js +12 -1
- package/dist/temp/assets/scripts/notification/FloatingNotification.js +1 -1
- package/dist/temp/assets/scripts/notification/FullWidthNotification.js +1 -1
- package/dist/temp/assets/scripts/notification/MessageNotification.d.ts +1 -1
- package/dist/temp/assets/scripts/notification/MessageNotification.js +9 -15
- package/dist/temp/assets/scripts/notification/const/classNames.d.ts +0 -2
- package/dist/temp/assets/scripts/notification/const/classNames.js +0 -2
- package/dist/temp/assets/scripts/notification/const/icons.d.ts +0 -2
- package/dist/temp/assets/scripts/notification/const/icons.js +0 -10
- package/dist/temp/assets/scripts/notification/const/index.d.ts +3 -3
- package/dist/temp/assets/scripts/notification/const/index.js +2 -2
- package/dist/temp/assets/scripts/notification/const/sizes.d.ts +0 -4
- package/dist/temp/assets/scripts/notification/const/sizes.js +0 -5
- package/dist/temp/assets/scripts/notification/const/types.d.ts +7 -22
- package/dist/temp/assets/scripts/notification/messageTemplate.d.ts +0 -2
- package/dist/temp/assets/scripts/notification/messageTemplate.js +2 -2
- package/dist/temp/assets/scripts/notification/utils.d.ts +10 -1
- package/dist/temp/assets/scripts/notification/utils.js +6 -3
- package/dist/temp/src/components/overlays/notification/FloatingNotification.d.ts +3 -4
- package/dist/temp/src/components/overlays/notification/FullWidthNotification.d.ts +2 -4
- package/dist/temp/src/components/overlays/notification/MessageNotification.d.ts +2 -18
- package/dist/temp/src/components/overlays/notification/MessageNotification.js +4 -8
- package/dist/temp/src/components/overlays/notification/MessageNotificationParts.d.ts +4 -10
- package/dist/temp/src/components/overlays/notification/MessageNotificationParts.js +4 -7
- package/dist/temp/src/components/overlays/notification/Notification.d.ts +8 -28
- package/dist/temp/src/components/overlays/notification/Notification.js +4 -2
- package/dist/temp/src/components/overlays/notification/__tests__/MessageNotification.test.js +12 -9
- package/dist/temp/src/components/overlays/notification/__tests__/Notification.test.js +5 -0
- package/dist/temp/src/components/overlays/notification/__tests__/supportTextLink.test.js +0 -11
- package/dist/temp/src/generated/scoped-css.js +1 -1
- package/dist/temp/src/utils/url/isSafeUrl.d.ts +1 -1
- package/dist/temp/src/utils/url/isSafeUrl.js +1 -1
- package/dist/temp/vitest.config.js +11 -0
- package/dist/types/assets/scripts/notification/MessageNotification.d.ts +1 -1
- package/dist/types/assets/scripts/notification/const/classNames.d.ts +0 -2
- package/dist/types/assets/scripts/notification/const/icons.d.ts +0 -2
- package/dist/types/assets/scripts/notification/const/index.d.ts +3 -3
- package/dist/types/assets/scripts/notification/const/sizes.d.ts +0 -4
- package/dist/types/assets/scripts/notification/const/types.d.ts +7 -22
- package/dist/types/assets/scripts/notification/messageTemplate.d.ts +0 -2
- package/dist/types/assets/scripts/notification/utils.d.ts +10 -1
- package/dist/types/src/components/overlays/notification/FloatingNotification.d.ts +3 -4
- package/dist/types/src/components/overlays/notification/FullWidthNotification.d.ts +2 -4
- package/dist/types/src/components/overlays/notification/MessageNotification.d.ts +2 -18
- package/dist/types/src/components/overlays/notification/MessageNotificationParts.d.ts +4 -10
- package/dist/types/src/components/overlays/notification/Notification.d.ts +8 -28
- package/dist/types/src/utils/url/isSafeUrl.d.ts +1 -1
- package/dist/ui-admin/assets/styles/style.css +0 -19
- package/package.json +2 -2
|
@@ -13,7 +13,7 @@ function resolveBaseOrigin() {
|
|
|
13
13
|
* javascript:, data:, file: 등 위험 프로토콜로 인한 XSS / 외부 페이로드 로딩을 차단.
|
|
14
14
|
*
|
|
15
15
|
* URL 파서가 앞뒤 공백·탭·개행 제거와 scheme 소문자화를 하므로 ` JavaScript:` 같은 우회도 막힌다.
|
|
16
|
-
* React(`
|
|
16
|
+
* React(`FullWidthNotification`)와 Vanilla(`renderSupportingText`)가 공유한다.
|
|
17
17
|
*/
|
|
18
18
|
export function isSafeUrl(url) {
|
|
19
19
|
if (!url.trim()) return false;
|
|
@@ -22,7 +22,18 @@ export default defineConfig({
|
|
|
22
22
|
// 'lcov' 대신 'lcovonly' — 'lcov' 는 HTML 리포트까지 생성한다.
|
|
23
23
|
reporter: ['text-summary', ['lcovonly', {
|
|
24
24
|
projectRoot: REPO_ROOT
|
|
25
|
-
}]]
|
|
25
|
+
}]],
|
|
26
|
+
// 회귀 방지 하한선 — 실측에서 약 2%p 낮춘 값 (ui-admin-mcp 와 같은 여유폭).
|
|
27
|
+
// 실측 기준: 2026-10-12, 25cb4d96 — stmts 54.91 / branch 44.63 / funcs 55.20 / lines 55.80
|
|
28
|
+
// 최종 목표: 93 / 88 (lines 95 · branches 90). 테스트 보강 단계마다 실측 −2 로 인상한다.
|
|
29
|
+
// autoUpdate: false — 값은 실측을 확인하고 사람이 직접 올린다.
|
|
30
|
+
thresholds: {
|
|
31
|
+
autoUpdate: false,
|
|
32
|
+
statements: 53,
|
|
33
|
+
branches: 43,
|
|
34
|
+
functions: 53,
|
|
35
|
+
lines: 54
|
|
36
|
+
}
|
|
26
37
|
}
|
|
27
38
|
}
|
|
28
39
|
});
|
|
@@ -71,7 +71,7 @@ export class FloatingNotification {
|
|
|
71
71
|
<div class="${CLASS_NAMES.FLOATING.TITLE_WRAPPER}">
|
|
72
72
|
<span class="${CLASS_NAMES.FLOATING.TITLE}">${title}</span>
|
|
73
73
|
</div>
|
|
74
|
-
${renderSupportingText(supportingText, CLASS_NAMES.FLOATING.SUPPORTING_TEXT)}
|
|
74
|
+
${renderSupportingText({ supportingText, className: CLASS_NAMES.FLOATING.SUPPORTING_TEXT })}
|
|
75
75
|
${actions && actions.length > 0 ? renderActions(actions, CLASS_NAMES.FLOATING.ACTIONS) : ''}
|
|
76
76
|
</div>
|
|
77
77
|
</div>
|
|
@@ -44,7 +44,7 @@ export class FullWidthNotification {
|
|
|
44
44
|
<div class="${CLASS_NAMES.FULL_WIDTH.ICON}">${iconHtml}</div>
|
|
45
45
|
<div class="${CLASS_NAMES.FULL_WIDTH.TEXT_CONTAINER}">
|
|
46
46
|
<span class="${CLASS_NAMES.FULL_WIDTH.TITLE}">${title}</span>
|
|
47
|
-
${renderSupportingText(supportingText, CLASS_NAMES.FULL_WIDTH.SUPPORTING_TEXT, supportTextLink)}
|
|
47
|
+
${renderSupportingText({ supportingText, className: CLASS_NAMES.FULL_WIDTH.SUPPORTING_TEXT, supportTextLink })}
|
|
48
48
|
</div>
|
|
49
49
|
</div>
|
|
50
50
|
<div class="${CLASS_NAMES.FULL_WIDTH.ACTIONS_CONTAINER}">
|
|
@@ -9,7 +9,7 @@ export declare class MessageNotification {
|
|
|
9
9
|
private featuredIcon?;
|
|
10
10
|
constructor(options: MessageNotificationOptions);
|
|
11
11
|
private createElement;
|
|
12
|
-
/** 색상별 FeaturedIcon.
|
|
12
|
+
/** 색상별 FeaturedIcon. md(40px 원 / 20px 아이콘) 고정. */
|
|
13
13
|
private createFeaturedIcon;
|
|
14
14
|
private bindEvents;
|
|
15
15
|
private setupAutoClose;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { FeaturedIcon } from '../featuredIcon';
|
|
2
2
|
import { sanitizeHtml } from '../utils/sanitize';
|
|
3
|
-
import { CLASS_NAMES,
|
|
3
|
+
import { CLASS_NAMES, MESSAGE_ICON_MAP, MESSAGE_SIZES } from './const';
|
|
4
4
|
import { buildMessageTemplate } from './messageTemplate';
|
|
5
|
-
import {
|
|
5
|
+
import { bindNotificationEvents, createWrapperElement, setupAutoClose } from './utils';
|
|
6
6
|
export class MessageNotification {
|
|
7
7
|
constructor(options) {
|
|
8
8
|
this.options = {
|
|
@@ -19,15 +19,12 @@ export class MessageNotification {
|
|
|
19
19
|
this.setupAutoClose();
|
|
20
20
|
}
|
|
21
21
|
createElement() {
|
|
22
|
-
const { title, supportingText, color, className, actions, onClose, hideCloseButton, onHidePermanently, hidePermanentlyLabel,
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const wrapper = createWrapperElement(CLASS_NAMES.MESSAGE.BASE, color, wrapperClassName);
|
|
26
|
-
const featuredIconElement = this.createFeaturedIcon(color, isBlock);
|
|
22
|
+
const { title, supportingText, color, className, actions, onClose, hideCloseButton, onHidePermanently, hidePermanentlyLabel, } = this.options;
|
|
23
|
+
const wrapper = createWrapperElement(CLASS_NAMES.MESSAGE.BASE, color, className);
|
|
24
|
+
const featuredIconElement = this.createFeaturedIcon(color);
|
|
27
25
|
wrapper.innerHTML = sanitizeHtml(buildMessageTemplate({
|
|
28
26
|
title,
|
|
29
27
|
supportingText,
|
|
30
|
-
supportTextLink: isBlock ? supportTextLink : undefined,
|
|
31
28
|
color,
|
|
32
29
|
actions,
|
|
33
30
|
onClose,
|
|
@@ -35,7 +32,6 @@ export class MessageNotification {
|
|
|
35
32
|
onHidePermanently,
|
|
36
33
|
hidePermanentlyLabel,
|
|
37
34
|
}));
|
|
38
|
-
applySupportTextLinkTarget(wrapper, CLASS_NAMES.MESSAGE.TEXT_CONTAINER, CLASS_NAMES.MESSAGE.LINK, supportTextLinkTarget);
|
|
39
35
|
// FeaturedIcon을 content-wrapper에 추가
|
|
40
36
|
if (featuredIconElement) {
|
|
41
37
|
const contentWrapper = wrapper.querySelector(`.${CLASS_NAMES.MESSAGE.CONTENT_WRAPPER}`);
|
|
@@ -45,16 +41,14 @@ export class MessageNotification {
|
|
|
45
41
|
}
|
|
46
42
|
return wrapper;
|
|
47
43
|
}
|
|
48
|
-
/** 색상별 FeaturedIcon.
|
|
49
|
-
createFeaturedIcon(color
|
|
50
|
-
const iconFunction = (isBlock ? MESSAGE_BLOCK_ICON_MAP : MESSAGE_ICON_MAP)[color];
|
|
51
|
-
const sizes = isBlock ? MESSAGE_BLOCK_SIZES : MESSAGE_SIZES;
|
|
44
|
+
/** 색상별 FeaturedIcon. md(40px 원 / 20px 아이콘) 고정. */
|
|
45
|
+
createFeaturedIcon(color) {
|
|
52
46
|
this.featuredIcon = FeaturedIcon.create({
|
|
53
|
-
svgString:
|
|
47
|
+
svgString: MESSAGE_ICON_MAP[color](MESSAGE_SIZES.ICON_PIXEL),
|
|
54
48
|
theme: 'light-circle',
|
|
55
49
|
// FeaturedIcon 에는 info 색이 없다. info 의 violet 톤은 message SCSS 가 덮어쓴다.
|
|
56
50
|
color: (color === 'info' ? 'neutral' : color),
|
|
57
|
-
size:
|
|
51
|
+
size: MESSAGE_SIZES.FEATURED_ICON,
|
|
58
52
|
// React 구현과 동일하게 `__icon`(flex-shrink: 0)을 부여한다.
|
|
59
53
|
// 누락 시 긴 타이틀에서 아이콘이 찌그러진다.
|
|
60
54
|
className: CLASS_NAMES.MESSAGE.ICON,
|
|
@@ -26,7 +26,6 @@ export declare const CLASS_NAMES: {
|
|
|
26
26
|
};
|
|
27
27
|
readonly MESSAGE: {
|
|
28
28
|
readonly BASE: "ncua-message-notification";
|
|
29
|
-
readonly BLOCK: "ncua-message-notification--block";
|
|
30
29
|
readonly CONTAINER: "ncua-message-notification__container";
|
|
31
30
|
readonly CONTENT: "ncua-message-notification__content";
|
|
32
31
|
readonly CONTENT_WRAPPER: "ncua-message-notification__content-wrapper";
|
|
@@ -34,7 +33,6 @@ export declare const CLASS_NAMES: {
|
|
|
34
33
|
readonly TEXT_CONTAINER: "ncua-message-notification__text-container";
|
|
35
34
|
readonly TITLE: "ncua-message-notification__title";
|
|
36
35
|
readonly SUPPORTING_TEXT: "ncua-message-notification__supporting-text";
|
|
37
|
-
readonly LINK: "ncua-message-notification__link";
|
|
38
36
|
readonly ACTIONS_CONTAINER: "ncua-message-notification__actions-container";
|
|
39
37
|
readonly ACTIONS: "ncua-message-notification__actions";
|
|
40
38
|
readonly FOOTER_CONTAINER: "ncua-message-notification__footer-container";
|
|
@@ -27,7 +27,6 @@ export const CLASS_NAMES = {
|
|
|
27
27
|
},
|
|
28
28
|
MESSAGE: {
|
|
29
29
|
BASE: 'ncua-message-notification',
|
|
30
|
-
BLOCK: 'ncua-message-notification--block',
|
|
31
30
|
CONTAINER: 'ncua-message-notification__container',
|
|
32
31
|
CONTENT: 'ncua-message-notification__content',
|
|
33
32
|
CONTENT_WRAPPER: 'ncua-message-notification__content-wrapper',
|
|
@@ -35,7 +34,6 @@ export const CLASS_NAMES = {
|
|
|
35
34
|
TEXT_CONTAINER: 'ncua-message-notification__text-container',
|
|
36
35
|
TITLE: 'ncua-message-notification__title',
|
|
37
36
|
SUPPORTING_TEXT: 'ncua-message-notification__supporting-text',
|
|
38
|
-
LINK: 'ncua-message-notification__link',
|
|
39
37
|
ACTIONS_CONTAINER: 'ncua-message-notification__actions-container',
|
|
40
38
|
ACTIONS: 'ncua-message-notification__actions',
|
|
41
39
|
// 다시 보지 않기 + 닫기 그룹 전용 래퍼. ACTIONS_CONTAINER를 재사용하면
|
|
@@ -26,6 +26,4 @@ export declare const ICON_MAP: {
|
|
|
26
26
|
};
|
|
27
27
|
/** message 기본 타입 아이콘. floating 과 같은 4색에 info(neutral 과 같은 핀)를 더한다. */
|
|
28
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
29
|
export {};
|
|
@@ -1,8 +1,3 @@
|
|
|
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>`;
|
|
6
1
|
// SVG 아이콘들 (크기는 동적으로 설정)
|
|
7
2
|
export const SVG_ICONS = {
|
|
8
3
|
'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>`,
|
|
@@ -36,8 +31,3 @@ export const MESSAGE_ICON_MAP = {
|
|
|
36
31
|
success: SVG_ICONS['check-circle'],
|
|
37
32
|
info: SVG_ICONS['pin-02'],
|
|
38
33
|
};
|
|
39
|
-
/** block 변형 아이콘. info 만 InfoCircle 로 다르다 (#536 유지). */
|
|
40
|
-
export const MESSAGE_BLOCK_ICON_MAP = {
|
|
41
|
-
...MESSAGE_ICON_MAP,
|
|
42
|
-
info: INFO_CIRCLE_ICON,
|
|
43
|
-
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { CLASS_NAMES } from './classNames';
|
|
2
|
-
export { FLOATING_ICON_MAP, FULL_WIDTH_ICON_MAP, ICON_MAP,
|
|
3
|
-
export { CLOSE_BUTTON_SIZES, CLOSE_BUTTON_SVG_SIZES, FEATURED_ICON_SIZES, FULL_WIDTH_SIZES, getSizes, ICON_PIXEL_SIZES,
|
|
4
|
-
export type { BaseNotificationOptions, LegacyNotificationHierarchy, NotificationAction, NotificationActionButtonSize, NotificationColor, NotificationHierarchy, NotificationLinkTarget,
|
|
2
|
+
export { FLOATING_ICON_MAP, FULL_WIDTH_ICON_MAP, ICON_MAP, MESSAGE_ICON_MAP, SVG_ICONS, } from './icons';
|
|
3
|
+
export { CLOSE_BUTTON_SIZES, CLOSE_BUTTON_SVG_SIZES, FEATURED_ICON_SIZES, FULL_WIDTH_SIZES, getSizes, ICON_PIXEL_SIZES, MESSAGE_SIZES, } from './sizes';
|
|
4
|
+
export type { BaseNotificationOptions, LegacyNotificationHierarchy, NotificationAction, NotificationActionButtonSize, NotificationColor, NotificationHierarchy, NotificationLinkTarget, } 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,
|
|
4
|
-
export { CLOSE_BUTTON_SIZES, CLOSE_BUTTON_SVG_SIZES, FEATURED_ICON_SIZES, FULL_WIDTH_SIZES, getSizes, ICON_PIXEL_SIZES,
|
|
3
|
+
export { FLOATING_ICON_MAP, FULL_WIDTH_ICON_MAP, ICON_MAP, MESSAGE_ICON_MAP, SVG_ICONS, } from './icons';
|
|
4
|
+
export { CLOSE_BUTTON_SIZES, CLOSE_BUTTON_SVG_SIZES, FEATURED_ICON_SIZES, FULL_WIDTH_SIZES, getSizes, ICON_PIXEL_SIZES, MESSAGE_SIZES, } from './sizes';
|
|
@@ -24,10 +24,6 @@ export declare const MESSAGE_SIZES: {
|
|
|
24
24
|
readonly ICON_PIXEL: "20";
|
|
25
25
|
readonly CLOSE_BUTTON: "20";
|
|
26
26
|
};
|
|
27
|
-
export declare const MESSAGE_BLOCK_SIZES: {
|
|
28
|
-
readonly FEATURED_ICON: "sm";
|
|
29
|
-
readonly ICON_PIXEL: "16";
|
|
30
|
-
};
|
|
31
27
|
export declare const getSizes: {
|
|
32
28
|
readonly featuredIcon: (isMobile: boolean) => "sm" | "md";
|
|
33
29
|
readonly iconPixel: (isMobile: boolean) => "20" | "16";
|
|
@@ -33,11 +33,6 @@ export const MESSAGE_SIZES = {
|
|
|
33
33
|
ICON_PIXEL: '20',
|
|
34
34
|
CLOSE_BUTTON: '20',
|
|
35
35
|
};
|
|
36
|
-
// Message 알림 Block 변형 사이즈. 'sm' = 32px 원 / 16px 아이콘. 닫기 버튼은 default 와 같다.
|
|
37
|
-
export const MESSAGE_BLOCK_SIZES = {
|
|
38
|
-
FEATURED_ICON: 'sm',
|
|
39
|
-
ICON_PIXEL: '16',
|
|
40
|
-
};
|
|
41
36
|
// 사이즈 유틸리티 함수들
|
|
42
37
|
export const getSizes = {
|
|
43
38
|
featuredIcon: (isMobile) => (isMobile ? FEATURED_ICON_SIZES.MOBILE : FEATURED_ICON_SIZES.DESKTOP),
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
export type NotificationColor = 'neutral' | 'error' | 'warning' | 'success' | 'info';
|
|
2
|
-
/**
|
|
3
|
-
* message 타입의 표시 변형. React `NotificationVariant`와 같은 어휘다.
|
|
4
|
-
* - `'default'`: 기존 message
|
|
5
|
-
* - `'block'`: 서브 페이지 공지용 (흰 배경, FeaturedIcon sm, 제목 + 텍스트 링크 1행, info 아이콘 InfoCircle)
|
|
6
|
-
*/
|
|
7
|
-
export type NotificationVariant = 'default' | 'block';
|
|
8
2
|
/**
|
|
9
3
|
* 텍스트 링크(`supportTextLink`)를 여는 대상. React `NotificationLinkTarget`과 같은 어휘다.
|
|
10
|
-
* - `'_self'`: 같은 탭
|
|
11
|
-
* - `'_blank'`: 새 탭
|
|
4
|
+
* - `'_self'`: 같은 탭
|
|
5
|
+
* - `'_blank'`: 새 탭 + `rel="noopener noreferrer"`
|
|
12
6
|
*/
|
|
13
7
|
export type NotificationLinkTarget = '_self' | '_blank';
|
|
14
8
|
/**
|
|
@@ -41,32 +35,23 @@ export interface BaseNotificationOptions {
|
|
|
41
35
|
color?: NotificationColor;
|
|
42
36
|
onClose?: () => void;
|
|
43
37
|
/**
|
|
44
|
-
* 닫기
|
|
45
|
-
* autoClose
|
|
46
|
-
* floating 은 `autoClose` 미지정 시 3초 뒤 자동으로 닫힌다(직접 `remove()` 로 닫으려면 `autoClose: 0` 명시).
|
|
47
|
-
* full-width · message 는 `autoClose` 를 명시했을 때만 자동으로 닫힌다.
|
|
38
|
+
* 닫기 버튼 숨김 여부 (기본값 `false`)
|
|
39
|
+
* `true`이면 floating 타입은 autoClose 미지정 시 3초 후 자동으로 닫힘 (onClose 호출, 끄려면 `autoClose: 0`)
|
|
48
40
|
*/
|
|
49
41
|
hideCloseButton?: boolean;
|
|
50
42
|
className?: string;
|
|
51
43
|
actions?: NotificationAction[];
|
|
52
44
|
autoClose?: number;
|
|
53
45
|
/**
|
|
54
|
-
* supportingText에 대한 링크 URL. full-width
|
|
55
|
-
* http/https 만
|
|
46
|
+
* supportingText에 대한 링크 URL. full-width 타입에서만 사용 가능.
|
|
47
|
+
* http/https(상대경로 포함) URL만 링크로 렌더하고 그 외는 텍스트로 렌더한다.
|
|
56
48
|
*/
|
|
57
49
|
supportTextLink?: string;
|
|
58
50
|
/**
|
|
59
|
-
* 텍스트 링크를 여는 대상. `
|
|
60
|
-
* `'_blank'`이면 새 탭으로 열고 `rel="noopener noreferrer"`를 함께 붙인다.
|
|
61
|
-
* `'_blank'`가 아닌 값은 모두 `'_self'`(같은 탭)로 취급한다.
|
|
51
|
+
* 텍스트 링크를 여는 대상. `'_blank'`이면 새 탭 + `rel="noopener noreferrer"`.
|
|
62
52
|
* @default '_self'
|
|
63
53
|
*/
|
|
64
54
|
supportTextLinkTarget?: NotificationLinkTarget;
|
|
65
|
-
/**
|
|
66
|
-
* message 타입의 표시 변형. message 타입에서만 동작한다.
|
|
67
|
-
* @default 'default'
|
|
68
|
-
*/
|
|
69
|
-
variant?: NotificationVariant;
|
|
70
55
|
onHidePermanently?: () => void;
|
|
71
56
|
/**
|
|
72
57
|
* 다시보지 않기 버튼의 라벨. full-width, message 타입에서 사용 가능하며
|
|
@@ -2,8 +2,6 @@ import type { NotificationAction, NotificationColor } from './const';
|
|
|
2
2
|
export interface MessageTemplateParams {
|
|
3
3
|
title: string;
|
|
4
4
|
supportingText?: string;
|
|
5
|
-
/** 지정 시 `supportingText`를 텍스트 링크로 렌더한다 (block 변형 전용, http/https 만 허용). */
|
|
6
|
-
supportTextLink?: string;
|
|
7
5
|
/** 닫기 아이콘 색 결정용. 미지정 시 neutral. */
|
|
8
6
|
color?: NotificationColor;
|
|
9
7
|
actions?: NotificationAction[];
|
|
@@ -12,14 +12,14 @@ const ACTION_BUTTON_SIZE = 'xs';
|
|
|
12
12
|
* 동일한 클래스 트리를 산출해야 한다 — SCSS 한 벌을 두 구현이 공유한다.
|
|
13
13
|
*/
|
|
14
14
|
export function buildMessageTemplate(params) {
|
|
15
|
-
const { title, supportingText,
|
|
15
|
+
const { title, supportingText, color, actions, onClose, hideCloseButton, onHidePermanently, hidePermanentlyLabel } = params;
|
|
16
16
|
return `
|
|
17
17
|
<div class="${CLASS_NAMES.MESSAGE.CONTAINER}">
|
|
18
18
|
<div class="${CLASS_NAMES.MESSAGE.CONTENT}">
|
|
19
19
|
<div class="${CLASS_NAMES.MESSAGE.CONTENT_WRAPPER}">
|
|
20
20
|
<div class="${CLASS_NAMES.MESSAGE.TEXT_CONTAINER}">
|
|
21
21
|
<span class="${CLASS_NAMES.MESSAGE.TITLE}">${title}</span>
|
|
22
|
-
${renderSupportingText(supportingText, CLASS_NAMES.MESSAGE.SUPPORTING_TEXT
|
|
22
|
+
${renderSupportingText({ supportingText, className: CLASS_NAMES.MESSAGE.SUPPORTING_TEXT })}
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
25
25
|
${renderActionsContainer({ actions, onClose, hideCloseButton, onHidePermanently, hidePermanentlyLabel, color })}
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import type { LegacyNotificationHierarchy, NotificationAction, NotificationActionButtonSize, NotificationColor, NotificationHierarchy } from './const';
|
|
2
2
|
export declare function createWrapperElement(baseClass: string, color: NotificationColor, className?: string): HTMLElement;
|
|
3
3
|
export declare function buildClassName(baseClass: string, color: NotificationColor, className?: string): string;
|
|
4
|
-
|
|
4
|
+
interface RenderSupportingTextParams {
|
|
5
|
+
supportingText?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
supportTextLink?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 보조 텍스트 HTML을 만든다. `supportTextLink` 링크는 full-width 전용 클래스(`CLASS_NAMES.FULL_WIDTH.LINK`)로 렌더한다.
|
|
11
|
+
*/
|
|
12
|
+
export declare const renderSupportingText: ({ supportingText, className, supportTextLink, }: RenderSupportingTextParams) => string;
|
|
5
13
|
/**
|
|
6
14
|
* `supportTextLinkTarget`이 `'_blank'`이면 `renderSupportingText`가 만든 링크를 새 탭으로 연다.
|
|
7
15
|
*
|
|
@@ -30,3 +38,4 @@ export declare function renderActions(actions: NotificationAction[], wrapperClas
|
|
|
30
38
|
export declare function bindNotificationEvents(element: HTMLElement, actions: NotificationAction[], onClose?: () => void, onRemove?: () => void): void;
|
|
31
39
|
export declare function setupAutoClose(autoClose: number, onClose?: () => void, onRemove?: () => void): number | undefined;
|
|
32
40
|
export declare const isMobile: () => boolean;
|
|
41
|
+
export {};
|
|
@@ -22,7 +22,10 @@ export function buildClassName(baseClass, color, className) {
|
|
|
22
22
|
function escapeHtmlAttr(str) {
|
|
23
23
|
return str.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''');
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* 보조 텍스트 HTML을 만든다. `supportTextLink` 링크는 full-width 전용 클래스(`CLASS_NAMES.FULL_WIDTH.LINK`)로 렌더한다.
|
|
27
|
+
*/
|
|
28
|
+
export const renderSupportingText = ({ supportingText, className, supportTextLink, }) => {
|
|
26
29
|
if (!supportingText)
|
|
27
30
|
return '';
|
|
28
31
|
// 본문(supportingText) 자체는 이 함수의 호출 결과가 wrapper.innerHTML에
|
|
@@ -30,11 +33,11 @@ export function renderSupportingText(supportingText, className, supportTextLink,
|
|
|
30
33
|
// 이렇게 해야 <br>, <strong> 등 서식용 태그가 그대로 동작한다.
|
|
31
34
|
if (supportTextLink && isSafeUrl(supportTextLink)) {
|
|
32
35
|
const safeLink = escapeHtmlAttr(supportTextLink);
|
|
33
|
-
return `<a href="${safeLink}" class="${
|
|
36
|
+
return `<a href="${safeLink}" class="${CLASS_NAMES.FULL_WIDTH.LINK}"><span class="${className}">${supportingText}</span></a>`;
|
|
34
37
|
}
|
|
35
38
|
// unsafe URL이거나 link가 없으면 링크 없이 텍스트만 렌더링
|
|
36
39
|
return `<span class="${className}">${supportingText}</span>`;
|
|
37
|
-
}
|
|
40
|
+
};
|
|
38
41
|
/**
|
|
39
42
|
* `supportTextLinkTarget`이 `'_blank'`이면 `renderSupportingText`가 만든 링크를 새 탭으로 연다.
|
|
40
43
|
*
|
|
@@ -19,9 +19,8 @@ interface FloatingNotificationProps extends Omit<ComponentPropsWithoutRef<'div'>
|
|
|
19
19
|
*/
|
|
20
20
|
onClose?: () => void;
|
|
21
21
|
/**
|
|
22
|
-
* 닫기
|
|
23
|
-
* autoClose
|
|
24
|
-
* `autoClose` 미지정이면 3초 뒤 자동으로 닫힌다. 부모가 직접 언마운트하려면 `autoClose={0}`을 명시한다.
|
|
22
|
+
* 닫기 버튼 숨김 여부
|
|
23
|
+
* `true`이면 autoClose 미지정 시 3초 후 자동으로 닫힘 (onClose 호출, 끄려면 `autoClose={0}`)
|
|
25
24
|
* @default false
|
|
26
25
|
*/
|
|
27
26
|
hideCloseButton?: boolean;
|
|
@@ -35,7 +34,7 @@ interface FloatingNotificationProps extends Omit<ComponentPropsWithoutRef<'div'>
|
|
|
35
34
|
actions?: NotificationAction[];
|
|
36
35
|
/**
|
|
37
36
|
* 자동 닫기 시간 (밀리초 단위, 0이면 자동으로 닫히지 않음)
|
|
38
|
-
* 미지정 시
|
|
37
|
+
* hideCloseButton이면 미지정 시 3초
|
|
39
38
|
* @default 0
|
|
40
39
|
*/
|
|
41
40
|
autoClose?: number;
|
|
@@ -19,9 +19,7 @@ interface FullWidthNotificationProps extends Omit<ComponentPropsWithoutRef<'div'
|
|
|
19
19
|
*/
|
|
20
20
|
onClose?: () => void;
|
|
21
21
|
/**
|
|
22
|
-
* 닫기
|
|
23
|
-
* autoClose 만료 시 `onClose` 호출은 그대로 유지된다.
|
|
24
|
-
* 기본 자동 닫힘은 없다 — 부모가 언마운트로 닫거나 `autoClose`를 명시한다.
|
|
22
|
+
* 닫기 버튼 숨김 여부
|
|
25
23
|
* @default false
|
|
26
24
|
*/
|
|
27
25
|
hideCloseButton?: boolean;
|
|
@@ -40,7 +38,7 @@ interface FullWidthNotificationProps extends Omit<ComponentPropsWithoutRef<'div'
|
|
|
40
38
|
*/
|
|
41
39
|
autoClose?: number;
|
|
42
40
|
/**
|
|
43
|
-
* info 링크 영역 (선택사항)
|
|
41
|
+
* info 링크 영역 (선택사항). http/https(상대경로 포함) URL만 링크로 렌더하고 그 외는 텍스트로 렌더한다.
|
|
44
42
|
*/
|
|
45
43
|
supportTextLink?: string;
|
|
46
44
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ComponentPropsWithoutRef, type ReactNode } from 'react';
|
|
2
2
|
import type { SlotIconComponent } from '../../../types/side-slot';
|
|
3
|
-
import type { NotificationAction, NotificationColor
|
|
3
|
+
import type { NotificationAction, NotificationColor } from './Notification';
|
|
4
4
|
interface MessageNotificationProps extends Omit<ComponentPropsWithoutRef<'div'>, 'title'> {
|
|
5
5
|
/**
|
|
6
6
|
* 알림 제목 텍스트
|
|
@@ -24,9 +24,7 @@ interface MessageNotificationProps extends Omit<ComponentPropsWithoutRef<'div'>,
|
|
|
24
24
|
*/
|
|
25
25
|
onClose?: () => void;
|
|
26
26
|
/**
|
|
27
|
-
* 닫기
|
|
28
|
-
* autoClose 만료 시 `onClose` 호출은 그대로 유지된다.
|
|
29
|
-
* 기본 자동 닫힘은 없다 — 부모가 언마운트로 닫거나 `autoClose`를 명시한다.
|
|
27
|
+
* 닫기 버튼 숨김 여부
|
|
30
28
|
* @default false
|
|
31
29
|
*/
|
|
32
30
|
hideCloseButton?: boolean;
|
|
@@ -53,20 +51,6 @@ interface MessageNotificationProps extends Omit<ComponentPropsWithoutRef<'div'>,
|
|
|
53
51
|
* @default '다시 보지 않기'
|
|
54
52
|
*/
|
|
55
53
|
hidePermanentlyLabel?: ReactNode;
|
|
56
|
-
/**
|
|
57
|
-
* 표시 변형. `'block'`은 서브 페이지 공지용(흰 배경, FeaturedIcon sm, 제목 + 텍스트 링크 1행)
|
|
58
|
-
* @default 'default'
|
|
59
|
-
*/
|
|
60
|
-
variant?: NotificationVariant;
|
|
61
|
-
/**
|
|
62
|
-
* 텍스트 링크 URL. `variant="block"`에서만 동작하며 `supportingText`가 링크 텍스트가 된다.
|
|
63
|
-
*/
|
|
64
|
-
supportTextLink?: string;
|
|
65
|
-
/**
|
|
66
|
-
* 텍스트 링크를 여는 대상. `'_blank'`이면 새 탭 + `rel="noopener noreferrer"`
|
|
67
|
-
* @default '_self'
|
|
68
|
-
*/
|
|
69
|
-
supportTextLinkTarget?: NotificationLinkTarget;
|
|
70
54
|
}
|
|
71
55
|
declare const MessageNotification: import("react").ForwardRefExoticComponent<MessageNotificationProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
72
56
|
export type { MessageNotificationProps };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { AlertCircle, AlertTriangle, CheckCircle,
|
|
2
|
+
import { AlertCircle, AlertTriangle, CheckCircle, Pin02 } from '@ncds/ui-admin-icon';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
import { forwardRef } from 'react';
|
|
5
5
|
import { MESSAGE_CLOSE_ICON_COLOR } from '../../../../constant/notification';
|
|
@@ -10,14 +10,10 @@ const DEFAULT_ICON_MAP = {
|
|
|
10
10
|
error: AlertTriangle,
|
|
11
11
|
warning: AlertCircle,
|
|
12
12
|
success: CheckCircle,
|
|
13
|
-
// 디자인 기준
|
|
13
|
+
// 디자인 기준 info 는 neutral 과 같은 핀이다.
|
|
14
14
|
info: Pin02,
|
|
15
15
|
};
|
|
16
|
-
|
|
17
|
-
const BLOCK_ICON_MAP = { ...DEFAULT_ICON_MAP, info: InfoCircle };
|
|
18
|
-
const MessageNotification = forwardRef(({ title, supportingText, icon: Icon, color = 'neutral', onClose, hideCloseButton = false, autoClose, className, actions, onHidePermanently, hidePermanentlyLabel, variant = 'default', supportTextLink, supportTextLinkTarget, ...rest }, ref) => {
|
|
19
|
-
const isBlock = variant === 'block';
|
|
20
|
-
const iconMap = isBlock ? BLOCK_ICON_MAP : DEFAULT_ICON_MAP;
|
|
16
|
+
const MessageNotification = forwardRef(({ title, supportingText, icon: Icon, color = 'neutral', onClose, hideCloseButton = false, autoClose, className, actions, onHidePermanently, hidePermanentlyLabel, ...rest }, ref) => {
|
|
21
17
|
// FeaturedIcon 에는 info 색이 없다. info 의 violet 톤은 message SCSS 가 덮어쓴다.
|
|
22
18
|
const featuredIconColor = color === 'info' ? 'neutral' : color;
|
|
23
19
|
// message 는 부모가 언마운트로 닫으므로 hideCloseButton 기본 autoClose 를 적용하지 않는다.
|
|
@@ -25,7 +21,7 @@ const MessageNotification = forwardRef(({ title, supportingText, icon: Icon, col
|
|
|
25
21
|
if (shouldRemove) {
|
|
26
22
|
return null;
|
|
27
23
|
}
|
|
28
|
-
return (_jsx("div", { ref: ref, className: classNames('ncua-message-notification', `ncua-message-notification--${color}`,
|
|
24
|
+
return (_jsx("div", { ref: ref, className: classNames('ncua-message-notification', `ncua-message-notification--${color}`, 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, icon: Icon || DEFAULT_ICON_MAP[color], iconColor: featuredIconColor }), _jsx(MessageNotificationActions, { actions: actions, onClose: onClose, hideCloseButton: hideCloseButton, onHidePermanently: onHidePermanently, hidePermanentlyLabel: hidePermanentlyLabel, closeIconColor: MESSAGE_CLOSE_ICON_COLOR[color] })] }) }) }));
|
|
29
25
|
});
|
|
30
26
|
MessageNotification.displayName = 'MessageNotification';
|
|
31
27
|
export { MessageNotification };
|
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { SlotIconComponent } from '../../../types/side-slot';
|
|
3
|
-
import { type FeaturedIconColor
|
|
4
|
-
import type { NotificationAction
|
|
3
|
+
import { type FeaturedIconColor } from '../../image-and-icons/featured-icon/FeaturedIcon';
|
|
4
|
+
import type { NotificationAction } from './Notification';
|
|
5
5
|
interface MessageNotificationContentProps {
|
|
6
6
|
title: ReactNode;
|
|
7
7
|
supportingText?: ReactNode;
|
|
8
|
-
/** 지정 시 `supportingText`를 이 URL 의 텍스트 링크로 렌더한다 (block 변형 전용). http/https·상대경로가 아니면 텍스트만 렌더. */
|
|
9
|
-
supportTextLink?: string;
|
|
10
|
-
/** 텍스트 링크를 여는 대상. `'_blank'`이면 새 탭 + `rel="noopener noreferrer"`. */
|
|
11
|
-
supportTextLinkTarget?: NotificationLinkTarget;
|
|
12
8
|
icon?: SlotIconComponent;
|
|
13
9
|
iconColor: FeaturedIconColor;
|
|
14
|
-
/** default 는 md(40/20), block 은 sm(32/16). */
|
|
15
|
-
iconSize: FeaturedIconSize;
|
|
16
10
|
}
|
|
17
|
-
/** 아이콘 + 제목/서포팅 텍스트(
|
|
18
|
-
declare const MessageNotificationContent: ({ title, supportingText,
|
|
11
|
+
/** 아이콘 + 제목/서포팅 텍스트 영역. FeaturedIcon 은 md(40px 원 / 20px 아이콘) 고정. */
|
|
12
|
+
declare const MessageNotificationContent: ({ title, supportingText, icon, iconColor }: MessageNotificationContentProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
13
|
interface MessageNotificationActionsProps {
|
|
20
14
|
actions?: NotificationAction[];
|
|
21
15
|
onClose?: () => void;
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Pin02, XClose } from '@ncds/ui-admin-icon';
|
|
3
3
|
import { HIDE_PERMANENTLY_LABEL } from '../../../../constant/notification';
|
|
4
|
-
import { isSafeUrl } from '../../../utils/url';
|
|
5
4
|
import { FeaturedIcon, } from '../../image-and-icons/featured-icon/FeaturedIcon';
|
|
6
|
-
import { getLinkTargetAttributes } from './linkTarget';
|
|
7
5
|
import { NotificationActionButtons } from './NotificationActionButtons';
|
|
8
|
-
/** 아이콘 + 제목/서포팅 텍스트(
|
|
9
|
-
const MessageNotificationContent = ({ title, supportingText,
|
|
6
|
+
/** 아이콘 + 제목/서포팅 텍스트 영역. FeaturedIcon 은 md(40px 원 / 20px 아이콘) 고정. */
|
|
7
|
+
const MessageNotificationContent = ({ title, supportingText, icon, iconColor }) => {
|
|
10
8
|
const featuredIconProps = {
|
|
11
9
|
icon: icon || Pin02,
|
|
12
|
-
size:
|
|
10
|
+
size: 'md',
|
|
13
11
|
color: iconColor,
|
|
14
12
|
theme: 'light-circle',
|
|
15
13
|
};
|
|
16
|
-
|
|
17
|
-
return (_jsxs("div", { className: "ncua-message-notification__content-wrapper", children: [_jsx(FeaturedIcon, { ...featuredIconProps, className: "ncua-message-notification__icon" }), _jsxs("div", { className: "ncua-message-notification__text-container", children: [_jsx("span", { className: "ncua-message-notification__title", children: title }), supportTextLink && isSafeUrl(supportTextLink) && supportingTextNode ? (_jsx("a", { href: supportTextLink, className: "ncua-message-notification__link", ...getLinkTargetAttributes(supportTextLinkTarget), children: supportingTextNode })) : (supportingTextNode)] })] }));
|
|
14
|
+
return (_jsxs("div", { className: "ncua-message-notification__content-wrapper", children: [_jsx(FeaturedIcon, { ...featuredIconProps, className: "ncua-message-notification__icon" }), _jsxs("div", { className: "ncua-message-notification__text-container", children: [_jsx("span", { className: "ncua-message-notification__title", children: title }), supportingText && _jsx("span", { className: "ncua-message-notification__supporting-text", children: supportingText })] })] }));
|
|
18
15
|
};
|
|
19
16
|
/**
|
|
20
17
|
* 액션 버튼 그룹 + 닫기 그룹을 감싸는 우측 영역.
|
|
@@ -6,7 +6,6 @@ import { type CalloutNotificationProps, type CalloutNotificationWidth } from './
|
|
|
6
6
|
type NotificationType = 'floating' | 'full-width' | 'message' | 'callout';
|
|
7
7
|
type NotificationColor = Extract<ColorTone, 'neutral' | 'error' | 'warning' | 'success' | 'info'>;
|
|
8
8
|
type NotificationSize = 'desktop' | 'mobile';
|
|
9
|
-
type NotificationVariant = 'default' | 'block';
|
|
10
9
|
/** 텍스트 링크(`supportTextLink`)를 여는 대상. `'_blank'`이면 새 탭 + `rel="noopener noreferrer"`. */
|
|
11
10
|
type NotificationLinkTarget = '_self' | '_blank';
|
|
12
11
|
interface NotificationAction {
|
|
@@ -39,7 +38,7 @@ interface NotificationProps extends Omit<ComponentPropsWithoutRef<'div'>, 'title
|
|
|
39
38
|
*/
|
|
40
39
|
supportingText?: ReactNode;
|
|
41
40
|
/**
|
|
42
|
-
* 알림 아이콘 컴포넌트 (지정하지 않으면
|
|
41
|
+
* 알림 아이콘 컴포넌트 (지정하지 않으면 color에 따라 기본 아이콘 사용)
|
|
43
42
|
*/
|
|
44
43
|
icon?: SlotIconComponent;
|
|
45
44
|
/**
|
|
@@ -52,14 +51,8 @@ interface NotificationProps extends Omit<ComponentPropsWithoutRef<'div'>, 'title
|
|
|
52
51
|
*/
|
|
53
52
|
onClose?: () => void;
|
|
54
53
|
/**
|
|
55
|
-
* 닫기
|
|
56
|
-
* `true
|
|
57
|
-
* autoClose 만료(및 floating의 모바일 전환) 시 `onClose` 호출은 그대로 유지되므로,
|
|
58
|
-
* "닫기 버튼 없는 자동 닫힘 토스트"(DES-SPEC-027 §5.3)에서 부모가 닫힘 시점을 받을 수 있다.
|
|
59
|
-
*
|
|
60
|
-
* floating(토스트)은 닫을 수단이 사라지지 않도록 `autoClose` 미지정 시 3초 뒤 자동으로 닫힌다
|
|
61
|
-
* (부모가 직접 언마운트해 닫으려면 `autoClose={0}` 명시). full-width · message 는 부모가 언마운트로 닫으므로
|
|
62
|
-
* `autoClose`를 명시했을 때만 자동으로 닫힌다.
|
|
54
|
+
* 닫기 버튼 숨김 여부
|
|
55
|
+
* `true`이면 floating 타입은 autoClose 미지정 시 3초 후 자동으로 닫힘 (onClose 호출, 끄려면 `autoClose={0}`)
|
|
63
56
|
* @default false
|
|
64
57
|
*/
|
|
65
58
|
hideCloseButton?: boolean;
|
|
@@ -74,8 +67,7 @@ interface NotificationProps extends Omit<ComponentPropsWithoutRef<'div'>, 'title
|
|
|
74
67
|
actions?: NotificationAction[];
|
|
75
68
|
/**
|
|
76
69
|
* 자동 닫기 시간 (밀리초 단위, 0이면 자동으로 닫히지 않음)
|
|
77
|
-
* floating, full-width, message 타입에서 동작
|
|
78
|
-
* 미지정 시 0. 단 floating 에서 `hideCloseButton`이면 3초(DES-SPEC-027 §5.3).
|
|
70
|
+
* floating, full-width, message 타입에서 동작 (floating + hideCloseButton은 미지정 시 3초)
|
|
79
71
|
* @default 0
|
|
80
72
|
*/
|
|
81
73
|
autoClose?: number;
|
|
@@ -94,27 +86,15 @@ interface NotificationProps extends Omit<ComponentPropsWithoutRef<'div'>, 'title
|
|
|
94
86
|
hidePermanentlyLabel?: ReactNode;
|
|
95
87
|
/**
|
|
96
88
|
* supportingText 에 연결할 링크 URL (선택사항)
|
|
97
|
-
* full-width
|
|
89
|
+
* full-width 타입에서만 사용 가능. http/https(상대경로 포함) URL만 링크로 렌더하고 그 외는 텍스트로 렌더한다.
|
|
98
90
|
*/
|
|
99
91
|
supportTextLink?: string;
|
|
100
92
|
/**
|
|
101
|
-
* 텍스트 링크를 여는 대상 (선택사항). `
|
|
102
|
-
*
|
|
103
|
-
* full-width 타입, message 타입의 `variant="block"`에서 사용 가능
|
|
93
|
+
* 텍스트 링크를 여는 대상 (선택사항). `'_blank'`이면 새 탭 + `rel="noopener noreferrer"`
|
|
94
|
+
* full-width 타입에서만 사용 가능
|
|
104
95
|
* @default '_self'
|
|
105
96
|
*/
|
|
106
97
|
supportTextLinkTarget?: NotificationLinkTarget;
|
|
107
|
-
/**
|
|
108
|
-
* message 타입의 표시 변형 (선택사항). message 타입에서만 동작한다.
|
|
109
|
-
*
|
|
110
|
-
* - `'default'`: 기존 message (color 별 배경·테두리, 제목 + 본문 2행)
|
|
111
|
-
* - `'block'`: 서브 페이지 공지용. 흰 배경·gray-100 테두리·shadow-sm, FeaturedIcon sm,
|
|
112
|
-
* 제목 + 텍스트 링크 1행(`supportingText` 가 링크 텍스트, `supportTextLink` 가 href).
|
|
113
|
-
* info 아이콘은 InfoCircle.
|
|
114
|
-
*
|
|
115
|
-
* @default 'default'
|
|
116
|
-
*/
|
|
117
|
-
variant?: NotificationVariant;
|
|
118
98
|
/**
|
|
119
99
|
* 너비 동작 (선택사항)
|
|
120
100
|
* callout 타입에서만 사용 가능. 미지정 시 부모 너비를 채운다(100%). 'fit' 은 콘텐츠 너비에 맞춘다
|
|
@@ -135,6 +115,6 @@ interface NotificationProps extends Omit<ComponentPropsWithoutRef<'div'>, 'title
|
|
|
135
115
|
portal?: boolean;
|
|
136
116
|
}
|
|
137
117
|
declare const Notification: import("react").ForwardRefExoticComponent<NotificationProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
138
|
-
export type { NotificationType, NotificationColor, NotificationSize,
|
|
118
|
+
export type { NotificationType, NotificationColor, NotificationSize, NotificationLinkTarget, NotificationAction, NotificationProps, };
|
|
139
119
|
export type { CalloutNotificationProps, CalloutNotificationWidth };
|
|
140
120
|
export { Notification };
|