@ncds/ui-admin 1.8.21-alpha.4 → 1.8.21-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/FullWidthNotification.js +17 -6
- package/dist/cjs/assets/scripts/notification/MessageNotification.js +10 -48
- package/dist/cjs/assets/scripts/notification/const/classNames.js +3 -0
- package/dist/cjs/assets/scripts/notification/const/index.js +1 -1
- package/dist/cjs/assets/scripts/notification/const/sizes.js +4 -2
- package/dist/cjs/assets/scripts/notification/messageTemplate.js +106 -0
- package/dist/cjs/assets/scripts/notification/utils.js +40 -4
- package/dist/cjs/constant/notification.js +21 -0
- package/dist/cjs/src/components/overlays/notification/FullWidthNotification.js +3 -1
- package/dist/cjs/src/components/overlays/notification/MessageNotification.js +14 -54
- package/dist/cjs/src/components/overlays/notification/MessageNotificationParts.js +92 -0
- package/dist/cjs/src/components/overlays/notification/__tests__/MessageNotification.test.js +246 -0
- package/dist/cjs/src/components/overlays/notification/__tests__/hidePermanentlyLabel.test.js +209 -0
- package/dist/cjs/src/generated/scoped-css.js +1 -1
- package/dist/esm/assets/scripts/notification/FullWidthNotification.js +17 -6
- package/dist/esm/assets/scripts/notification/MessageNotification.js +12 -50
- package/dist/esm/assets/scripts/notification/const/classNames.js +3 -0
- package/dist/esm/assets/scripts/notification/const/index.js +3 -2
- package/dist/esm/assets/scripts/notification/const/sizes.js +4 -2
- package/dist/esm/assets/scripts/notification/messageTemplate.js +100 -0
- package/dist/esm/assets/scripts/notification/utils.js +39 -4
- package/dist/esm/constant/notification.js +15 -0
- package/dist/esm/src/components/overlays/notification/FullWidthNotification.js +3 -1
- package/dist/esm/src/components/overlays/notification/MessageNotification.js +15 -55
- package/dist/esm/src/components/overlays/notification/MessageNotificationParts.js +85 -0
- package/dist/esm/src/components/overlays/notification/__tests__/MessageNotification.test.js +243 -0
- package/dist/esm/src/components/overlays/notification/__tests__/hidePermanentlyLabel.test.js +206 -0
- package/dist/esm/src/generated/scoped-css.js +1 -1
- package/dist/temp/assets/scripts/notification/FullWidthNotification.d.ts +6 -0
- package/dist/temp/assets/scripts/notification/FullWidthNotification.js +14 -5
- package/dist/temp/assets/scripts/notification/MessageNotification.d.ts +0 -3
- package/dist/temp/assets/scripts/notification/MessageNotification.js +9 -44
- package/dist/temp/assets/scripts/notification/const/classNames.d.ts +1 -0
- package/dist/temp/assets/scripts/notification/const/classNames.js +3 -0
- package/dist/temp/assets/scripts/notification/const/index.d.ts +3 -3
- package/dist/temp/assets/scripts/notification/const/index.js +3 -2
- package/dist/temp/assets/scripts/notification/const/sizes.d.ts +2 -2
- package/dist/temp/assets/scripts/notification/const/sizes.js +4 -2
- package/dist/temp/assets/scripts/notification/const/types.d.ts +30 -2
- package/dist/temp/assets/scripts/notification/messageTemplate.d.ts +15 -0
- package/dist/temp/assets/scripts/notification/messageTemplate.js +79 -0
- package/dist/temp/assets/scripts/notification/utils.d.ts +19 -2
- package/dist/temp/assets/scripts/notification/utils.js +39 -5
- package/dist/temp/constant/notification.d.ts +15 -0
- package/dist/temp/constant/notification.js +15 -0
- package/dist/temp/src/components/overlays/notification/FullWidthNotification.d.ts +6 -0
- package/dist/temp/src/components/overlays/notification/FullWidthNotification.js +3 -2
- package/dist/temp/src/components/overlays/notification/MessageNotification.d.ts +6 -0
- package/dist/temp/src/components/overlays/notification/MessageNotification.js +4 -13
- package/dist/temp/src/components/overlays/notification/MessageNotificationParts.d.ts +28 -0
- package/dist/temp/src/components/overlays/notification/MessageNotificationParts.js +28 -0
- package/dist/temp/src/components/overlays/notification/Notification.d.ts +11 -2
- package/dist/temp/src/components/overlays/notification/__tests__/MessageNotification.test.d.ts +1 -0
- package/dist/temp/src/components/overlays/notification/__tests__/MessageNotification.test.js +190 -0
- package/dist/temp/src/components/overlays/notification/__tests__/hidePermanentlyLabel.test.d.ts +1 -0
- package/dist/temp/src/components/overlays/notification/__tests__/hidePermanentlyLabel.test.js +160 -0
- package/dist/temp/src/generated/scoped-css.js +1 -1
- package/dist/types/assets/scripts/notification/FullWidthNotification.d.ts +6 -0
- package/dist/types/assets/scripts/notification/MessageNotification.d.ts +0 -3
- package/dist/types/assets/scripts/notification/const/classNames.d.ts +1 -0
- package/dist/types/assets/scripts/notification/const/index.d.ts +3 -3
- package/dist/types/assets/scripts/notification/const/sizes.d.ts +2 -2
- package/dist/types/assets/scripts/notification/const/types.d.ts +30 -2
- package/dist/types/assets/scripts/notification/messageTemplate.d.ts +15 -0
- package/dist/types/assets/scripts/notification/utils.d.ts +19 -2
- package/dist/types/constant/notification.d.ts +15 -0
- package/dist/types/src/components/overlays/notification/FullWidthNotification.d.ts +6 -0
- package/dist/types/src/components/overlays/notification/MessageNotification.d.ts +6 -0
- package/dist/types/src/components/overlays/notification/MessageNotificationParts.d.ts +28 -0
- package/dist/types/src/components/overlays/notification/Notification.d.ts +11 -2
- package/dist/types/src/components/overlays/notification/__tests__/MessageNotification.test.d.ts +1 -0
- package/dist/types/src/components/overlays/notification/__tests__/hidePermanentlyLabel.test.d.ts +1 -0
- package/dist/ui-admin/assets/styles/style.css +21 -33
- package/dist/ui-admin/assets/styles/style.scoped.css +21 -33
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.FullWidthNotification = void 0;
|
|
7
|
+
var _notification = require("../../../constant/notification");
|
|
7
8
|
var _sanitize = require("../utils/sanitize");
|
|
8
9
|
var _const = require("./const");
|
|
9
10
|
var _utils = require("./utils");
|
|
@@ -30,7 +31,8 @@ class FullWidthNotification {
|
|
|
30
31
|
actions,
|
|
31
32
|
onClose,
|
|
32
33
|
supportTextLink,
|
|
33
|
-
onHidePermanently
|
|
34
|
+
onHidePermanently,
|
|
35
|
+
hidePermanentlyLabel
|
|
34
36
|
} = this.options;
|
|
35
37
|
const wrapper = (0, _utils.createWrapperElement)(_const.CLASS_NAMES.FULL_WIDTH.BASE, color, className);
|
|
36
38
|
const iconHtml = _const.FULL_WIDTH_ICON_MAP[color](_const.FULL_WIDTH_SIZES.ICON);
|
|
@@ -41,7 +43,8 @@ class FullWidthNotification {
|
|
|
41
43
|
actions,
|
|
42
44
|
onClose,
|
|
43
45
|
supportTextLink,
|
|
44
|
-
onHidePermanently
|
|
46
|
+
onHidePermanently,
|
|
47
|
+
hidePermanentlyLabel
|
|
45
48
|
}));
|
|
46
49
|
return wrapper;
|
|
47
50
|
}
|
|
@@ -53,7 +56,8 @@ class FullWidthNotification {
|
|
|
53
56
|
actions,
|
|
54
57
|
onClose,
|
|
55
58
|
supportTextLink,
|
|
56
|
-
onHidePermanently
|
|
59
|
+
onHidePermanently,
|
|
60
|
+
hidePermanentlyLabel
|
|
57
61
|
} = params;
|
|
58
62
|
return `
|
|
59
63
|
<div class="${_const.CLASS_NAMES.FULL_WIDTH.CONTAINER}">
|
|
@@ -67,18 +71,25 @@ class FullWidthNotification {
|
|
|
67
71
|
</div>
|
|
68
72
|
<div class="${_const.CLASS_NAMES.FULL_WIDTH.ACTIONS_CONTAINER}">
|
|
69
73
|
${actions && actions.length > 0 ? (0, _utils.renderActions)(actions, _const.CLASS_NAMES.FULL_WIDTH.ACTIONS) : ''}
|
|
70
|
-
${this.renderHidePermanentlyButton(onHidePermanently)}
|
|
74
|
+
${this.renderHidePermanentlyButton(onHidePermanently, hidePermanentlyLabel)}
|
|
71
75
|
${this.renderCloseButton(onClose)}
|
|
72
76
|
</div>
|
|
73
77
|
</div>
|
|
74
78
|
</div>
|
|
75
79
|
`;
|
|
76
80
|
}
|
|
77
|
-
|
|
81
|
+
/**
|
|
82
|
+
* 다시보지 않기 버튼.
|
|
83
|
+
*
|
|
84
|
+
* `label`은 이 함수의 반환값이 `wrapper.innerHTML`에 들어가기 전에 `sanitizeHtml`로
|
|
85
|
+
* 처리되므로 별도 이스케이프하지 않는다 — `renderSupportingText`와 같은 정책이다.
|
|
86
|
+
*/
|
|
87
|
+
renderHidePermanentlyButton(onHidePermanently, hidePermanentlyLabel) {
|
|
78
88
|
if (!onHidePermanently) return '';
|
|
89
|
+
const label = hidePermanentlyLabel ?? _notification.HIDE_PERMANENTLY_LABEL.fullWidth;
|
|
79
90
|
return `
|
|
80
91
|
<button type="button" class="ncua-notification__action-button ncua-notification__action-button--text ncua-full-width-notification__link" data-hide-permanently="true">
|
|
81
|
-
|
|
92
|
+
${label}
|
|
82
93
|
</button>
|
|
83
94
|
`;
|
|
84
95
|
}
|
|
@@ -7,6 +7,7 @@ exports.MessageNotification = void 0;
|
|
|
7
7
|
var _featuredIcon = require("../featuredIcon");
|
|
8
8
|
var _sanitize = require("../utils/sanitize");
|
|
9
9
|
var _const = require("./const");
|
|
10
|
+
var _messageTemplate = require("./messageTemplate");
|
|
10
11
|
var _utils = require("./utils");
|
|
11
12
|
class MessageNotification {
|
|
12
13
|
constructor(options) {
|
|
@@ -30,7 +31,8 @@ class MessageNotification {
|
|
|
30
31
|
className,
|
|
31
32
|
actions,
|
|
32
33
|
onClose,
|
|
33
|
-
onHidePermanently
|
|
34
|
+
onHidePermanently,
|
|
35
|
+
hidePermanentlyLabel
|
|
34
36
|
} = this.options;
|
|
35
37
|
// message 타입은 neutral, error, warning, success 4가지 색상만 지원
|
|
36
38
|
let actualColor = color;
|
|
@@ -47,16 +49,20 @@ class MessageNotification {
|
|
|
47
49
|
svgString: iconSvg,
|
|
48
50
|
theme: 'light-circle',
|
|
49
51
|
color: actualColor,
|
|
50
|
-
size: _const.MESSAGE_SIZES.FEATURED_ICON
|
|
52
|
+
size: _const.MESSAGE_SIZES.FEATURED_ICON,
|
|
53
|
+
// React 구현과 동일하게 `__icon`(flex-shrink: 0)을 부여한다.
|
|
54
|
+
// 누락 시 긴 타이틀에서 아이콘이 찌그러진다.
|
|
55
|
+
className: _const.CLASS_NAMES.MESSAGE.ICON
|
|
51
56
|
});
|
|
52
57
|
featuredIconElement = this.featuredIcon.getElement();
|
|
53
58
|
}
|
|
54
|
-
wrapper.innerHTML = (0, _sanitize.sanitizeHtml)(
|
|
59
|
+
wrapper.innerHTML = (0, _sanitize.sanitizeHtml)((0, _messageTemplate.buildMessageTemplate)({
|
|
55
60
|
title,
|
|
56
61
|
supportingText,
|
|
57
62
|
actions,
|
|
58
63
|
onClose,
|
|
59
|
-
onHidePermanently
|
|
64
|
+
onHidePermanently,
|
|
65
|
+
hidePermanentlyLabel
|
|
60
66
|
}));
|
|
61
67
|
// FeaturedIcon을 content-wrapper에 추가
|
|
62
68
|
if (featuredIconElement) {
|
|
@@ -67,50 +73,6 @@ class MessageNotification {
|
|
|
67
73
|
}
|
|
68
74
|
return wrapper;
|
|
69
75
|
}
|
|
70
|
-
buildTemplate(params) {
|
|
71
|
-
const {
|
|
72
|
-
title,
|
|
73
|
-
supportingText,
|
|
74
|
-
actions,
|
|
75
|
-
onClose,
|
|
76
|
-
onHidePermanently
|
|
77
|
-
} = params;
|
|
78
|
-
return `
|
|
79
|
-
<div class="${_const.CLASS_NAMES.MESSAGE.CONTAINER}">
|
|
80
|
-
<div class="${_const.CLASS_NAMES.MESSAGE.CONTENT}">
|
|
81
|
-
<div class="${_const.CLASS_NAMES.MESSAGE.CONTENT_WRAPPER}">
|
|
82
|
-
<div class="${_const.CLASS_NAMES.MESSAGE.TEXT_CONTAINER}">
|
|
83
|
-
<span class="${_const.CLASS_NAMES.MESSAGE.TITLE}">${title}</span>
|
|
84
|
-
${(0, _utils.renderSupportingText)(supportingText, _const.CLASS_NAMES.MESSAGE.SUPPORTING_TEXT)}
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
|
-
<div class="${_const.CLASS_NAMES.MESSAGE.ACTIONS_CONTAINER}">
|
|
88
|
-
${actions && actions.length > 0 ? (0, _utils.renderActions)(actions, _const.CLASS_NAMES.MESSAGE.ACTIONS) : ''}
|
|
89
|
-
</div>
|
|
90
|
-
<div class="${_const.CLASS_NAMES.MESSAGE.ACTIONS_CONTAINER}">
|
|
91
|
-
${this.renderHidePermanentlyButton(onHidePermanently)}
|
|
92
|
-
${this.renderCloseButton(onClose)}
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
95
|
-
</div>
|
|
96
|
-
`;
|
|
97
|
-
}
|
|
98
|
-
renderHidePermanentlyButton(onHidePermanently) {
|
|
99
|
-
if (!onHidePermanently) return '';
|
|
100
|
-
return `
|
|
101
|
-
<button type="button" class="${_const.CLASS_NAMES.COMMON.ACTION_BUTTON} ${_const.CLASS_NAMES.COMMON.ACTION_BUTTON}--text ${_const.CLASS_NAMES.MESSAGE.HIDE_LINK}" data-hide-permanently="true">
|
|
102
|
-
다시 보지 않기
|
|
103
|
-
</button>
|
|
104
|
-
`;
|
|
105
|
-
}
|
|
106
|
-
renderCloseButton(onClose) {
|
|
107
|
-
if (!onClose) return '';
|
|
108
|
-
return `
|
|
109
|
-
<button type="button" class="${_const.CLASS_NAMES.MESSAGE.CLOSE_BUTTON}" aria-label="알림 닫기">
|
|
110
|
-
${_const.SVG_ICONS['x-close'](_const.MESSAGE_SIZES.CLOSE_BUTTON).replace('stroke="currentColor"', `stroke="#2F2F30"`)}
|
|
111
|
-
</button>
|
|
112
|
-
`;
|
|
113
|
-
}
|
|
114
76
|
bindEvents() {
|
|
115
77
|
(0, _utils.bindNotificationEvents)(this.element, this.options.actions, this.options.onClose, () => this.remove());
|
|
116
78
|
// 다시보지 않기 버튼 이벤트 바인딩
|
|
@@ -41,6 +41,9 @@ const CLASS_NAMES = exports.CLASS_NAMES = {
|
|
|
41
41
|
SUPPORTING_TEXT: 'ncua-message-notification__supporting-text',
|
|
42
42
|
ACTIONS_CONTAINER: 'ncua-message-notification__actions-container',
|
|
43
43
|
ACTIONS: 'ncua-message-notification__actions',
|
|
44
|
+
// 다시 보지 않기 + 닫기 그룹 전용 래퍼. ACTIONS_CONTAINER를 재사용하면
|
|
45
|
+
// 해당 클래스의 gap(12px)이 그룹 내부에도 적용되어 8px 규격이 깨진다.
|
|
46
|
+
FOOTER_CONTAINER: 'ncua-message-notification__footer-container',
|
|
44
47
|
HIDE_LINK: 'ncua-message-notification__hide-link',
|
|
45
48
|
CLOSE_BUTTON: 'ncua-message-notification__close-button'
|
|
46
49
|
},
|
|
@@ -81,7 +81,7 @@ Object.defineProperty(exports, "getSizes", {
|
|
|
81
81
|
return _sizes.getSizes;
|
|
82
82
|
}
|
|
83
83
|
});
|
|
84
|
-
var _icons = require("./icons");
|
|
85
84
|
var _classNames = require("./classNames");
|
|
85
|
+
var _icons = require("./icons");
|
|
86
86
|
var _sizes = require("./sizes");
|
|
87
87
|
var _types = require("./types");
|
|
@@ -32,9 +32,11 @@ const FULL_WIDTH_SIZES = exports.FULL_WIDTH_SIZES = {
|
|
|
32
32
|
CLOSE_BUTTON: '20'
|
|
33
33
|
};
|
|
34
34
|
// Message 알림 고정 사이즈
|
|
35
|
+
// FEATURED_ICON(원 크기)과 ICON_PIXEL(내부 SVG 크기)은 항상 짝을 맞춰야 한다.
|
|
36
|
+
// 'md' = 40px 원 / 20px 아이콘 (FeaturedIcon iconSizeMap 기준)
|
|
35
37
|
const MESSAGE_SIZES = exports.MESSAGE_SIZES = {
|
|
36
|
-
FEATURED_ICON: '
|
|
37
|
-
ICON_PIXEL: '
|
|
38
|
+
FEATURED_ICON: 'md',
|
|
39
|
+
ICON_PIXEL: '20',
|
|
38
40
|
CLOSE_BUTTON: '20'
|
|
39
41
|
};
|
|
40
42
|
// 사이즈 유틸리티 함수들
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.buildMessageTemplate = buildMessageTemplate;
|
|
7
|
+
var _notification = require("../../../constant/notification");
|
|
8
|
+
var _const = require("./const");
|
|
9
|
+
var _utils = require("./utils");
|
|
10
|
+
/**
|
|
11
|
+
* message 타입 액션 버튼 사이즈. TO-BE 규격 28px이며 React `<Button size="xs">`와 같다.
|
|
12
|
+
* floating / full-width는 이 값을 쓰지 않고 `renderActions`의 기본값('sm')을 유지한다.
|
|
13
|
+
*/
|
|
14
|
+
const ACTION_BUTTON_SIZE = 'xs';
|
|
15
|
+
/**
|
|
16
|
+
* Message Notification의 마크업을 만든다.
|
|
17
|
+
* React 구현(`src/components/overlays/notification/MessageNotification.tsx`)과
|
|
18
|
+
* 동일한 클래스 트리를 산출해야 한다 — SCSS 한 벌을 두 구현이 공유한다.
|
|
19
|
+
*/
|
|
20
|
+
function buildMessageTemplate(params) {
|
|
21
|
+
const {
|
|
22
|
+
title,
|
|
23
|
+
supportingText,
|
|
24
|
+
actions,
|
|
25
|
+
onClose,
|
|
26
|
+
onHidePermanently,
|
|
27
|
+
hidePermanentlyLabel
|
|
28
|
+
} = params;
|
|
29
|
+
return `
|
|
30
|
+
<div class="${_const.CLASS_NAMES.MESSAGE.CONTAINER}">
|
|
31
|
+
<div class="${_const.CLASS_NAMES.MESSAGE.CONTENT}">
|
|
32
|
+
<div class="${_const.CLASS_NAMES.MESSAGE.CONTENT_WRAPPER}">
|
|
33
|
+
<div class="${_const.CLASS_NAMES.MESSAGE.TEXT_CONTAINER}">
|
|
34
|
+
<span class="${_const.CLASS_NAMES.MESSAGE.TITLE}">${title}</span>
|
|
35
|
+
${(0, _utils.renderSupportingText)(supportingText, _const.CLASS_NAMES.MESSAGE.SUPPORTING_TEXT)}
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
${renderActionsContainer({
|
|
39
|
+
actions,
|
|
40
|
+
onClose,
|
|
41
|
+
onHidePermanently,
|
|
42
|
+
hidePermanentlyLabel
|
|
43
|
+
})}
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
`;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 액션 버튼 그룹과 닫기 그룹을 함께 감싸는 우측 영역.
|
|
50
|
+
* 이 컨테이너의 gap(12px)이 두 그룹 사이 간격을 만든다.
|
|
51
|
+
* 표시할 요소가 하나도 없으면 빈 컨테이너를 남기지 않는다.
|
|
52
|
+
*/
|
|
53
|
+
function renderActionsContainer(params) {
|
|
54
|
+
const {
|
|
55
|
+
actions,
|
|
56
|
+
onClose,
|
|
57
|
+
onHidePermanently,
|
|
58
|
+
hidePermanentlyLabel
|
|
59
|
+
} = params;
|
|
60
|
+
const actionsHtml = (0, _utils.renderActions)(actions ?? [], _const.CLASS_NAMES.MESSAGE.ACTIONS, ACTION_BUTTON_SIZE);
|
|
61
|
+
const footerHtml = renderFooterContainer({
|
|
62
|
+
onClose,
|
|
63
|
+
onHidePermanently,
|
|
64
|
+
hidePermanentlyLabel
|
|
65
|
+
});
|
|
66
|
+
if (!actionsHtml && !footerHtml) return '';
|
|
67
|
+
return `<div class="${_const.CLASS_NAMES.MESSAGE.ACTIONS_CONTAINER}">${actionsHtml}${footerHtml}</div>`;
|
|
68
|
+
}
|
|
69
|
+
/** 다시 보지 않기 + 닫기 그룹. 전용 래퍼를 쓰는 이유는 `CLASS_NAMES.MESSAGE.FOOTER_CONTAINER` 참조. */
|
|
70
|
+
function renderFooterContainer(params) {
|
|
71
|
+
const {
|
|
72
|
+
onClose,
|
|
73
|
+
onHidePermanently,
|
|
74
|
+
hidePermanentlyLabel
|
|
75
|
+
} = params;
|
|
76
|
+
if (!onHidePermanently && !onClose) return '';
|
|
77
|
+
return `
|
|
78
|
+
<div class="${_const.CLASS_NAMES.MESSAGE.FOOTER_CONTAINER}">
|
|
79
|
+
${renderHidePermanentlyButton(onHidePermanently, hidePermanentlyLabel)}
|
|
80
|
+
${renderCloseButton(onClose)}
|
|
81
|
+
</div>
|
|
82
|
+
`;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 다시 보지 않기 버튼.
|
|
86
|
+
*
|
|
87
|
+
* `label`은 이 함수의 반환값이 `wrapper.innerHTML`에 들어가기 전에 `sanitizeHtml`로
|
|
88
|
+
* 처리되므로 별도 이스케이프하지 않는다 — `renderSupportingText`와 같은 정책이다.
|
|
89
|
+
*/
|
|
90
|
+
function renderHidePermanentlyButton(onHidePermanently, hidePermanentlyLabel) {
|
|
91
|
+
if (!onHidePermanently) return '';
|
|
92
|
+
const label = hidePermanentlyLabel ?? _notification.HIDE_PERMANENTLY_LABEL.message;
|
|
93
|
+
return `
|
|
94
|
+
<button type="button" class="${_const.CLASS_NAMES.COMMON.ACTION_BUTTON} ${_const.CLASS_NAMES.MESSAGE.HIDE_LINK}" data-hide-permanently="true">
|
|
95
|
+
${label}
|
|
96
|
+
</button>
|
|
97
|
+
`;
|
|
98
|
+
}
|
|
99
|
+
function renderCloseButton(onClose) {
|
|
100
|
+
if (!onClose) return '';
|
|
101
|
+
return `
|
|
102
|
+
<button type="button" class="${_const.CLASS_NAMES.MESSAGE.CLOSE_BUTTON}" aria-label="알림 닫기">
|
|
103
|
+
${_const.SVG_ICONS['x-close'](_const.MESSAGE_SIZES.CLOSE_BUTTON).replace('stroke="currentColor"', 'stroke="#2F2F30"')}
|
|
104
|
+
</button>
|
|
105
|
+
`;
|
|
106
|
+
}
|
|
@@ -9,6 +9,7 @@ exports.createWrapperElement = createWrapperElement;
|
|
|
9
9
|
exports.isMobile = void 0;
|
|
10
10
|
exports.renderActions = renderActions;
|
|
11
11
|
exports.renderSupportingText = renderSupportingText;
|
|
12
|
+
exports.resolveActionHierarchy = resolveActionHierarchy;
|
|
12
13
|
exports.setupAutoClose = setupAutoClose;
|
|
13
14
|
var _breakpoint = require("../../../src/constant/breakpoint");
|
|
14
15
|
var _const = require("./const");
|
|
@@ -57,16 +58,51 @@ function renderSupportingText(supportingText, className, supportTextLink) {
|
|
|
57
58
|
// unsafe URL이거나 link가 없으면 링크 없이 텍스트만 렌더링
|
|
58
59
|
return `<span class="${className}">${supportingText}</span>`;
|
|
59
60
|
}
|
|
61
|
+
/** 액션 버튼 색상을 지정하지 않았을 때의 기본값. React `MessageNotificationParts`와 같다. */
|
|
62
|
+
const DEFAULT_ACTION_HIERARCHY = 'text';
|
|
63
|
+
/**
|
|
64
|
+
* 액션 버튼의 색상 수식자를 현행 어휘로 정규화한다.
|
|
65
|
+
*
|
|
66
|
+
* 구 어휘(`'link'` / `'link-gray'`)는 Link 컴포넌트의 색상 이름을 빌려 쓴 것이라
|
|
67
|
+
* `ncua-btn--link`에 대응하는 CSS가 존재하지 않았다. 기존 CDN 사용처를 깨지 않기 위해
|
|
68
|
+
* 타입에서 제거하는 대신 이 지점에서 실제 Button 테마로 매핑한다.
|
|
69
|
+
*
|
|
70
|
+
* 렌더(`renderActions`)와 이벤트 바인딩(`bindNotificationEvents`)이 이 함수를 함께 써야
|
|
71
|
+
* `data-action` 키가 어긋나지 않는다.
|
|
72
|
+
*/
|
|
73
|
+
function resolveActionHierarchy(hierarchy) {
|
|
74
|
+
switch (hierarchy) {
|
|
75
|
+
case undefined:
|
|
76
|
+
return DEFAULT_ACTION_HIERARCHY;
|
|
77
|
+
case 'link':
|
|
78
|
+
return 'text';
|
|
79
|
+
case 'link-gray':
|
|
80
|
+
return 'text-gray';
|
|
81
|
+
default:
|
|
82
|
+
return hierarchy;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** 액션 버튼의 클릭 라우팅 키. 렌더와 바인딩이 같은 규칙으로 만들어야 한다. */
|
|
86
|
+
function buildActionKey(action) {
|
|
87
|
+
return `${action.label}-${resolveActionHierarchy(action.hierarchy)}`;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* 액션 버튼 그룹 HTML을 만든다.
|
|
91
|
+
*
|
|
92
|
+
* `size` 기본값 'sm'은 floating / full-width 타입의 기존 렌더링을 그대로 보존하기 위한 것이다.
|
|
93
|
+
* message 타입만 TO-BE 규격(28px)에 맞춰 'xs'를 넘긴다 — React `<Button size="xs">`와 동일.
|
|
94
|
+
*/
|
|
60
95
|
function renderActions(actions, wrapperClass) {
|
|
96
|
+
let size = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'sm';
|
|
61
97
|
// 액션이 없으면 빈 문자열 반환
|
|
62
98
|
if (!actions || actions.length === 0) {
|
|
63
99
|
return '';
|
|
64
100
|
}
|
|
65
101
|
const buttonsHtml = actions.map(action => {
|
|
66
102
|
const buttonHtml = `
|
|
67
|
-
<button
|
|
68
|
-
class="ncua-btn ncua-btn
|
|
69
|
-
data-action="${action
|
|
103
|
+
<button
|
|
104
|
+
class="ncua-btn ncua-btn--${size} ncua-btn--${resolveActionHierarchy(action.hierarchy)}"
|
|
105
|
+
data-action="${buildActionKey(action)}"
|
|
70
106
|
>
|
|
71
107
|
${action.label}
|
|
72
108
|
</button>`;
|
|
@@ -92,7 +128,7 @@ function bindNotificationEvents(element, actions, onClose, onRemove) {
|
|
|
92
128
|
if (actionData) {
|
|
93
129
|
let matchedAction = null;
|
|
94
130
|
for (const action of actions) {
|
|
95
|
-
const expectedDataAction =
|
|
131
|
+
const expectedDataAction = buildActionKey(action);
|
|
96
132
|
if (actionData === expectedDataAction) {
|
|
97
133
|
matchedAction = action;
|
|
98
134
|
break;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.HIDE_PERMANENTLY_LABEL = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* 다시보지 않기 버튼의 타입별 기본 문구.
|
|
9
|
+
*
|
|
10
|
+
* `hidePermanentlyLabel`을 지정하지 않았을 때 쓰인다.
|
|
11
|
+
* React(`src/components/overlays/notification/`)와 Vanilla(`assets/scripts/notification/`)
|
|
12
|
+
* 두 구현이 이 상수를 함께 참조한다 — 문구가 하드코딩으로 흩어져 서로 어긋나던 문제(#460)를
|
|
13
|
+
* 막기 위한 단일 출처다.
|
|
14
|
+
*
|
|
15
|
+
* `message`와 `fullWidth`의 띄어쓰기가 다른 것은 오타가 아니라 현행 유지다.
|
|
16
|
+
* 표기 통일은 별도 결정 사항이며, 결정되면 이 파일 한 곳만 고치면 된다.
|
|
17
|
+
*/
|
|
18
|
+
const HIDE_PERMANENTLY_LABEL = exports.HIDE_PERMANENTLY_LABEL = {
|
|
19
|
+
message: '다시 보지 않기',
|
|
20
|
+
fullWidth: '다시보지 않기'
|
|
21
|
+
};
|
|
@@ -9,6 +9,7 @@ var _uiAdminIcon = require("@ncds/ui-admin-icon");
|
|
|
9
9
|
var _classnames = _interopRequireDefault(require("classnames"));
|
|
10
10
|
var _react = require("react");
|
|
11
11
|
var _color = require("../../../../constant/color");
|
|
12
|
+
var _notification = require("../../../../constant/notification");
|
|
12
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
14
|
const iconMap = {
|
|
14
15
|
neutral: _uiAdminIcon.MessageChatSquare,
|
|
@@ -35,6 +36,7 @@ const FullWidthNotification = exports.FullWidthNotification = /*#__PURE__*/(0, _
|
|
|
35
36
|
autoClose = 0,
|
|
36
37
|
supportTextLink,
|
|
37
38
|
onHidePermanently,
|
|
39
|
+
hidePermanentlyLabel = _notification.HIDE_PERMANENTLY_LABEL.fullWidth,
|
|
38
40
|
...rest
|
|
39
41
|
} = _ref;
|
|
40
42
|
const [shouldRemove, setShouldRemove] = (0, _react.useState)(false);
|
|
@@ -116,7 +118,7 @@ const FullWidthNotification = exports.FullWidthNotification = /*#__PURE__*/(0, _
|
|
|
116
118
|
type: "button",
|
|
117
119
|
className: (0, _classnames.default)('ncua-notification__action-button', 'ncua-notification__action-button--text', 'ncua-full-width-notification__link'),
|
|
118
120
|
onClick: onHidePermanently,
|
|
119
|
-
children:
|
|
121
|
+
children: hidePermanentlyLabel
|
|
120
122
|
}), onClose && (0, _jsxRuntime.jsx)("button", {
|
|
121
123
|
type: "button",
|
|
122
124
|
className: "ncua-full-width-notification__close-button",
|
|
@@ -9,8 +9,7 @@ var _uiAdminIcon = require("@ncds/ui-admin-icon");
|
|
|
9
9
|
var _classnames = _interopRequireDefault(require("classnames"));
|
|
10
10
|
var _react = require("react");
|
|
11
11
|
var _color = require("../../../../constant/color");
|
|
12
|
-
var
|
|
13
|
-
var _FeaturedIcon = require("../../image-and-icons/featured-icon/FeaturedIcon");
|
|
12
|
+
var _MessageNotificationParts = require("./MessageNotificationParts");
|
|
14
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
14
|
const iconMap = {
|
|
16
15
|
neutral: _uiAdminIcon.Pin02,
|
|
@@ -34,18 +33,11 @@ const MessageNotification = exports.MessageNotification = /*#__PURE__*/(0, _reac
|
|
|
34
33
|
className,
|
|
35
34
|
actions,
|
|
36
35
|
onHidePermanently,
|
|
36
|
+
hidePermanentlyLabel,
|
|
37
37
|
...rest
|
|
38
38
|
} = _ref;
|
|
39
39
|
// message 타입은 neutral, error, warning, success 4가지 색상만 지원
|
|
40
40
|
const validColor = color === 'info' ? 'neutral' : color;
|
|
41
|
-
const iconColor = validColor;
|
|
42
|
-
const featuredIconProps = {
|
|
43
|
-
icon: Icon || iconMap[validColor] || _uiAdminIcon.Pin02,
|
|
44
|
-
size: 'lg',
|
|
45
|
-
color: iconColor,
|
|
46
|
-
theme: 'light-circle'
|
|
47
|
-
};
|
|
48
|
-
const closeIconColor = _color.COLOR[iconColorMap[validColor] || 'gray700'];
|
|
49
41
|
return (0, _jsxRuntime.jsx)("div", {
|
|
50
42
|
ref: ref,
|
|
51
43
|
className: (0, _classnames.default)('ncua-message-notification', `ncua-message-notification--${validColor}`, className),
|
|
@@ -55,50 +47,18 @@ const MessageNotification = exports.MessageNotification = /*#__PURE__*/(0, _reac
|
|
|
55
47
|
className: "ncua-message-notification__container",
|
|
56
48
|
children: (0, _jsxRuntime.jsxs)("div", {
|
|
57
49
|
className: "ncua-message-notification__content",
|
|
58
|
-
children: [(0, _jsxRuntime.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
children: supportingText
|
|
71
|
-
})]
|
|
72
|
-
})]
|
|
73
|
-
}), (0, _jsxRuntime.jsx)("div", {
|
|
74
|
-
className: "ncua-message-notification__actions-container",
|
|
75
|
-
children: actions && (0, _jsxRuntime.jsx)("div", {
|
|
76
|
-
className: "ncua-message-notification__actions",
|
|
77
|
-
children: actions.map(action => (0, _jsxRuntime.jsx)(_button.Button, {
|
|
78
|
-
size: "xs",
|
|
79
|
-
hierarchy: action.hierarchy || 'text',
|
|
80
|
-
label: action.label,
|
|
81
|
-
onClick: action?.onClick
|
|
82
|
-
}, `${action.label}-${action.hierarchy}`))
|
|
83
|
-
})
|
|
84
|
-
}), (0, _jsxRuntime.jsxs)("div", {
|
|
85
|
-
className: "ncua-message-notification__footer-container",
|
|
86
|
-
children: [onHidePermanently && (0, _jsxRuntime.jsx)("button", {
|
|
87
|
-
type: "button",
|
|
88
|
-
className: (0, _classnames.default)('ncua-notification__action-button', 'ncua-notification__action-button--link', 'ncua-message-notification__hide-link'),
|
|
89
|
-
onClick: onHidePermanently,
|
|
90
|
-
children: "\uB2E4\uC2DC \uBCF4\uC9C0 \uC54A\uAE30"
|
|
91
|
-
}), onClose && (0, _jsxRuntime.jsx)("button", {
|
|
92
|
-
type: "button",
|
|
93
|
-
className: "ncua-message-notification__close-button",
|
|
94
|
-
onClick: onClose,
|
|
95
|
-
"aria-label": "\uC54C\uB9BC \uB2EB\uAE30",
|
|
96
|
-
children: (0, _jsxRuntime.jsx)(_uiAdminIcon.XClose, {
|
|
97
|
-
width: 20,
|
|
98
|
-
height: 20,
|
|
99
|
-
color: closeIconColor
|
|
100
|
-
})
|
|
101
|
-
})]
|
|
50
|
+
children: [(0, _jsxRuntime.jsx)(_MessageNotificationParts.MessageNotificationContent, {
|
|
51
|
+
title: title,
|
|
52
|
+
supportingText: supportingText,
|
|
53
|
+
icon: Icon || iconMap[validColor],
|
|
54
|
+
iconColor: validColor,
|
|
55
|
+
showIcon: Boolean(iconMap[validColor])
|
|
56
|
+
}), (0, _jsxRuntime.jsx)(_MessageNotificationParts.MessageNotificationActions, {
|
|
57
|
+
actions: actions,
|
|
58
|
+
onClose: onClose,
|
|
59
|
+
onHidePermanently: onHidePermanently,
|
|
60
|
+
hidePermanentlyLabel: hidePermanentlyLabel,
|
|
61
|
+
closeIconColor: _color.COLOR[iconColorMap[validColor] || 'gray700']
|
|
102
62
|
})]
|
|
103
63
|
})
|
|
104
64
|
})
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.MessageNotificationContent = exports.MessageNotificationActions = void 0;
|
|
7
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
8
|
+
var _uiAdminIcon = require("@ncds/ui-admin-icon");
|
|
9
|
+
var _notification = require("../../../../constant/notification");
|
|
10
|
+
var _button = require("../../action/button");
|
|
11
|
+
var _FeaturedIcon = require("../../image-and-icons/featured-icon/FeaturedIcon");
|
|
12
|
+
/** 아이콘 + 제목/서포팅 텍스트 영역. */
|
|
13
|
+
const MessageNotificationContent = _ref => {
|
|
14
|
+
let {
|
|
15
|
+
title,
|
|
16
|
+
supportingText,
|
|
17
|
+
icon,
|
|
18
|
+
iconColor,
|
|
19
|
+
showIcon
|
|
20
|
+
} = _ref;
|
|
21
|
+
const featuredIconProps = {
|
|
22
|
+
icon: icon || _uiAdminIcon.Pin02,
|
|
23
|
+
size: 'md',
|
|
24
|
+
color: iconColor,
|
|
25
|
+
theme: 'light-circle'
|
|
26
|
+
};
|
|
27
|
+
return (0, _jsxRuntime.jsxs)("div", {
|
|
28
|
+
className: "ncua-message-notification__content-wrapper",
|
|
29
|
+
children: [showIcon && (0, _jsxRuntime.jsx)(_FeaturedIcon.FeaturedIcon, {
|
|
30
|
+
...featuredIconProps,
|
|
31
|
+
className: "ncua-message-notification__icon"
|
|
32
|
+
}), (0, _jsxRuntime.jsxs)("div", {
|
|
33
|
+
className: "ncua-message-notification__text-container",
|
|
34
|
+
children: [(0, _jsxRuntime.jsx)("span", {
|
|
35
|
+
className: "ncua-message-notification__title",
|
|
36
|
+
children: title
|
|
37
|
+
}), supportingText && (0, _jsxRuntime.jsx)("span", {
|
|
38
|
+
className: "ncua-message-notification__supporting-text",
|
|
39
|
+
children: supportingText
|
|
40
|
+
})]
|
|
41
|
+
})]
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* 액션 버튼 그룹 + 닫기 그룹을 감싸는 우측 영역.
|
|
46
|
+
* 이 컨테이너의 gap(12px)이 두 그룹 사이 간격을 만든다.
|
|
47
|
+
* 표시할 요소가 하나도 없으면 빈 컨테이너를 남기지 않는다.
|
|
48
|
+
*/
|
|
49
|
+
exports.MessageNotificationContent = MessageNotificationContent;
|
|
50
|
+
const MessageNotificationActions = _ref2 => {
|
|
51
|
+
let {
|
|
52
|
+
actions,
|
|
53
|
+
onClose,
|
|
54
|
+
onHidePermanently,
|
|
55
|
+
hidePermanentlyLabel = _notification.HIDE_PERMANENTLY_LABEL.message,
|
|
56
|
+
closeIconColor
|
|
57
|
+
} = _ref2;
|
|
58
|
+
const hasActions = Boolean(actions?.length);
|
|
59
|
+
const hasFooter = Boolean(onHidePermanently || onClose);
|
|
60
|
+
if (!hasActions && !hasFooter) return null;
|
|
61
|
+
return (0, _jsxRuntime.jsxs)("div", {
|
|
62
|
+
className: "ncua-message-notification__actions-container",
|
|
63
|
+
children: [hasActions && (0, _jsxRuntime.jsx)("div", {
|
|
64
|
+
className: "ncua-message-notification__actions",
|
|
65
|
+
children: actions?.map(action => (0, _jsxRuntime.jsx)(_button.Button, {
|
|
66
|
+
size: "xs",
|
|
67
|
+
hierarchy: action.hierarchy || 'text',
|
|
68
|
+
label: action.label,
|
|
69
|
+
onClick: action?.onClick
|
|
70
|
+
}, `${action.label}-${action.hierarchy}`))
|
|
71
|
+
}), hasFooter && (0, _jsxRuntime.jsxs)("div", {
|
|
72
|
+
className: "ncua-message-notification__footer-container",
|
|
73
|
+
children: [onHidePermanently && (0, _jsxRuntime.jsx)("button", {
|
|
74
|
+
type: "button",
|
|
75
|
+
className: "ncua-notification__action-button ncua-message-notification__hide-link",
|
|
76
|
+
onClick: onHidePermanently,
|
|
77
|
+
children: hidePermanentlyLabel
|
|
78
|
+
}), onClose && (0, _jsxRuntime.jsx)("button", {
|
|
79
|
+
type: "button",
|
|
80
|
+
className: "ncua-message-notification__close-button",
|
|
81
|
+
onClick: onClose,
|
|
82
|
+
"aria-label": "\uC54C\uB9BC \uB2EB\uAE30",
|
|
83
|
+
children: (0, _jsxRuntime.jsx)(_uiAdminIcon.XClose, {
|
|
84
|
+
width: 20,
|
|
85
|
+
height: 20,
|
|
86
|
+
color: closeIconColor
|
|
87
|
+
})
|
|
88
|
+
})]
|
|
89
|
+
})]
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
exports.MessageNotificationActions = MessageNotificationActions;
|