@ncds/ui-admin 1.8.26-alpha.4 → 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.
Files changed (95) hide show
  1. package/dist/cjs/assets/scripts/notification/FloatingNotification.js +23 -7
  2. package/dist/cjs/assets/scripts/notification/FullWidthNotification.js +14 -3
  3. package/dist/cjs/assets/scripts/notification/MessageNotification.js +9 -9
  4. package/dist/cjs/assets/scripts/notification/Notification.js +8 -2
  5. package/dist/cjs/assets/scripts/notification/const/icons.js +17 -8
  6. package/dist/cjs/assets/scripts/notification/const/index.js +6 -0
  7. package/dist/cjs/assets/scripts/notification/messageTemplate.js +21 -5
  8. package/dist/cjs/constant/notification.js +8 -3
  9. package/dist/cjs/src/components/overlays/notification/FloatingNotification.js +11 -29
  10. package/dist/cjs/src/components/overlays/notification/FullWidthNotification.js +9 -24
  11. package/dist/cjs/src/components/overlays/notification/MessageNotification.js +25 -9
  12. package/dist/cjs/src/components/overlays/notification/MessageNotificationParts.js +5 -2
  13. package/dist/cjs/src/components/overlays/notification/Notification.js +1 -0
  14. package/dist/cjs/src/components/overlays/notification/__tests__/CalloutNotification.test.js +8 -2
  15. package/dist/cjs/src/components/overlays/notification/__tests__/MessageNotification.test.js +55 -13
  16. package/dist/cjs/src/components/overlays/notification/__tests__/Notification.test.js +176 -0
  17. package/dist/cjs/src/components/overlays/notification/useAutoClose.js +39 -0
  18. package/dist/cjs/src/generated/scoped-css.js +1 -1
  19. package/dist/cjs/src/utils/notification/__tests__/resolveAutoClose.test.js +44 -0
  20. package/dist/cjs/src/utils/notification/index.js +12 -0
  21. package/dist/cjs/src/utils/notification/resolveAutoClose.js +22 -0
  22. package/dist/esm/assets/scripts/notification/FloatingNotification.js +23 -7
  23. package/dist/esm/assets/scripts/notification/FullWidthNotification.js +14 -3
  24. package/dist/esm/assets/scripts/notification/MessageNotification.js +10 -10
  25. package/dist/esm/assets/scripts/notification/Notification.js +8 -2
  26. package/dist/esm/assets/scripts/notification/const/icons.js +16 -7
  27. package/dist/esm/assets/scripts/notification/const/index.js +1 -1
  28. package/dist/esm/assets/scripts/notification/messageTemplate.js +21 -5
  29. package/dist/esm/constant/notification.js +7 -2
  30. package/dist/esm/src/components/overlays/notification/FloatingNotification.js +12 -30
  31. package/dist/esm/src/components/overlays/notification/FullWidthNotification.js +10 -25
  32. package/dist/esm/src/components/overlays/notification/MessageNotification.js +25 -9
  33. package/dist/esm/src/components/overlays/notification/MessageNotificationParts.js +5 -2
  34. package/dist/esm/src/components/overlays/notification/Notification.js +1 -0
  35. package/dist/esm/src/components/overlays/notification/__tests__/CalloutNotification.test.js +9 -3
  36. package/dist/esm/src/components/overlays/notification/__tests__/MessageNotification.test.js +55 -13
  37. package/dist/esm/src/components/overlays/notification/__tests__/Notification.test.js +177 -1
  38. package/dist/esm/src/components/overlays/notification/useAutoClose.js +32 -0
  39. package/dist/esm/src/generated/scoped-css.js +1 -1
  40. package/dist/esm/src/utils/notification/__tests__/resolveAutoClose.test.js +42 -0
  41. package/dist/esm/src/utils/notification/index.js +1 -0
  42. package/dist/esm/src/utils/notification/resolveAutoClose.js +15 -0
  43. package/dist/temp/assets/scripts/notification/FloatingNotification.js +10 -6
  44. package/dist/temp/assets/scripts/notification/FullWidthNotification.js +8 -5
  45. package/dist/temp/assets/scripts/notification/MessageNotification.d.ts +1 -1
  46. package/dist/temp/assets/scripts/notification/MessageNotification.js +10 -12
  47. package/dist/temp/assets/scripts/notification/Notification.js +7 -1
  48. package/dist/temp/assets/scripts/notification/const/icons.d.ts +6 -6
  49. package/dist/temp/assets/scripts/notification/const/icons.js +16 -7
  50. package/dist/temp/assets/scripts/notification/const/index.d.ts +1 -1
  51. package/dist/temp/assets/scripts/notification/const/index.js +1 -1
  52. package/dist/temp/assets/scripts/notification/const/types.d.ts +8 -1
  53. package/dist/temp/assets/scripts/notification/messageTemplate.d.ts +1 -0
  54. package/dist/temp/assets/scripts/notification/messageTemplate.js +19 -9
  55. package/dist/temp/constant/notification.d.ts +6 -1
  56. package/dist/temp/constant/notification.js +6 -1
  57. package/dist/temp/src/components/overlays/notification/FloatingNotification.d.ts +8 -0
  58. package/dist/temp/src/components/overlays/notification/FloatingNotification.js +7 -30
  59. package/dist/temp/src/components/overlays/notification/FullWidthNotification.d.ts +7 -0
  60. package/dist/temp/src/components/overlays/notification/FullWidthNotification.js +6 -25
  61. package/dist/temp/src/components/overlays/notification/MessageNotification.d.ts +13 -1
  62. package/dist/temp/src/components/overlays/notification/MessageNotification.js +16 -9
  63. package/dist/temp/src/components/overlays/notification/MessageNotificationParts.d.ts +2 -1
  64. package/dist/temp/src/components/overlays/notification/MessageNotificationParts.js +5 -3
  65. package/dist/temp/src/components/overlays/notification/Notification.d.ts +16 -3
  66. package/dist/temp/src/components/overlays/notification/Notification.js +1 -1
  67. package/dist/temp/src/components/overlays/notification/__tests__/CalloutNotification.test.js +8 -1
  68. package/dist/temp/src/components/overlays/notification/__tests__/MessageNotification.test.js +44 -9
  69. package/dist/temp/src/components/overlays/notification/__tests__/Notification.test.js +128 -1
  70. package/dist/temp/src/components/overlays/notification/useAutoClose.d.ts +15 -0
  71. package/dist/temp/src/components/overlays/notification/useAutoClose.js +25 -0
  72. package/dist/temp/src/generated/scoped-css.js +1 -1
  73. package/dist/temp/src/utils/notification/__tests__/resolveAutoClose.test.d.ts +1 -0
  74. package/dist/temp/src/utils/notification/__tests__/resolveAutoClose.test.js +22 -0
  75. package/dist/temp/src/utils/notification/index.d.ts +1 -0
  76. package/dist/temp/src/utils/notification/index.js +1 -0
  77. package/dist/temp/src/utils/notification/resolveAutoClose.d.ts +14 -0
  78. package/dist/temp/src/utils/notification/resolveAutoClose.js +12 -0
  79. package/dist/types/assets/scripts/notification/MessageNotification.d.ts +1 -1
  80. package/dist/types/assets/scripts/notification/const/icons.d.ts +6 -6
  81. package/dist/types/assets/scripts/notification/const/index.d.ts +1 -1
  82. package/dist/types/assets/scripts/notification/const/types.d.ts +8 -1
  83. package/dist/types/assets/scripts/notification/messageTemplate.d.ts +1 -0
  84. package/dist/types/constant/notification.d.ts +6 -1
  85. package/dist/types/src/components/overlays/notification/FloatingNotification.d.ts +8 -0
  86. package/dist/types/src/components/overlays/notification/FullWidthNotification.d.ts +7 -0
  87. package/dist/types/src/components/overlays/notification/MessageNotification.d.ts +13 -1
  88. package/dist/types/src/components/overlays/notification/MessageNotificationParts.d.ts +2 -1
  89. package/dist/types/src/components/overlays/notification/Notification.d.ts +16 -3
  90. package/dist/types/src/components/overlays/notification/useAutoClose.d.ts +15 -0
  91. package/dist/types/src/utils/notification/__tests__/resolveAutoClose.test.d.ts +1 -0
  92. package/dist/types/src/utils/notification/index.d.ts +1 -0
  93. package/dist/types/src/utils/notification/resolveAutoClose.d.ts +14 -0
  94. package/dist/ui-admin/assets/styles/style.css +17 -11
  95. package/package.json +1 -1
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.FloatingNotification = void 0;
7
7
  var _breakpoint = require("../../../src/constant/breakpoint");
8
+ var _notification = require("../../../src/utils/notification");
8
9
  var _featuredIcon = require("../featuredIcon");
9
10
  var _ButtonCloseX = require("../shared/ButtonCloseX");
10
11
  var _sanitize = require("../utils/sanitize");
@@ -16,9 +17,13 @@ class FloatingNotification {
16
17
  color: 'neutral',
17
18
  className: '',
18
19
  actions: [],
19
- autoClose: 0,
20
+ hideCloseButton: false,
20
21
  supportingText: undefined,
21
- ...options
22
+ ...options,
23
+ autoClose: (0, _notification.resolveAutoClose)({
24
+ autoClose: options.autoClose,
25
+ hideCloseButton: options.hideCloseButton
26
+ })
22
27
  };
23
28
  this.element = this.createElement();
24
29
  this.bindEvents();
@@ -32,7 +37,8 @@ class FloatingNotification {
32
37
  color,
33
38
  className,
34
39
  actions,
35
- onClose
40
+ onClose,
41
+ hideCloseButton
36
42
  } = this.options;
37
43
  // 플로팅 알림에서 info 색상 사용 시 neutral로 대체
38
44
  let actualColor = color;
@@ -61,6 +67,7 @@ class FloatingNotification {
61
67
  supportingText,
62
68
  actions,
63
69
  onClose,
70
+ hideCloseButton,
64
71
  isMobile: mobile
65
72
  }));
66
73
  // FeaturedIcon을 container에 추가
@@ -78,6 +85,7 @@ class FloatingNotification {
78
85
  supportingText,
79
86
  actions,
80
87
  onClose,
88
+ hideCloseButton,
81
89
  isMobile
82
90
  } = params;
83
91
  return `
@@ -92,12 +100,20 @@ class FloatingNotification {
92
100
  </div>
93
101
  </div>
94
102
  </div>
95
- ${this.renderCloseButton(onClose, isMobile)}
103
+ ${this.renderCloseButton({
104
+ onClose,
105
+ isMobile,
106
+ hideCloseButton
107
+ })}
96
108
  `;
97
109
  }
98
- renderCloseButton(onClose) {
99
- let isMobile = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
100
- if (!onClose) return '';
110
+ renderCloseButton(params) {
111
+ const {
112
+ onClose,
113
+ isMobile = false,
114
+ hideCloseButton = false
115
+ } = params;
116
+ if (!onClose || hideCloseButton) return '';
101
117
  const size = _const.getSizes.closeButton(isMobile);
102
118
  return (0, _ButtonCloseX.ButtonCloseX)(size, 'light', _const.CLASS_NAMES.FLOATING.CLOSE_BUTTON, '알림 닫기', onClose);
103
119
  }
@@ -15,6 +15,7 @@ class FullWidthNotification {
15
15
  className: '',
16
16
  actions: [],
17
17
  autoClose: 0,
18
+ hideCloseButton: false,
18
19
  supportingText: undefined,
19
20
  ...options
20
21
  };
@@ -30,6 +31,7 @@ class FullWidthNotification {
30
31
  className,
31
32
  actions,
32
33
  onClose,
34
+ hideCloseButton,
33
35
  supportTextLink,
34
36
  supportTextLinkTarget,
35
37
  onHidePermanently,
@@ -43,6 +45,7 @@ class FullWidthNotification {
43
45
  supportingText,
44
46
  actions,
45
47
  onClose,
48
+ hideCloseButton,
46
49
  supportTextLink,
47
50
  onHidePermanently,
48
51
  hidePermanentlyLabel
@@ -57,6 +60,7 @@ class FullWidthNotification {
57
60
  supportingText,
58
61
  actions,
59
62
  onClose,
63
+ hideCloseButton,
60
64
  supportTextLink,
61
65
  onHidePermanently,
62
66
  hidePermanentlyLabel
@@ -74,7 +78,10 @@ class FullWidthNotification {
74
78
  <div class="${_const.CLASS_NAMES.FULL_WIDTH.ACTIONS_CONTAINER}">
75
79
  ${actions && actions.length > 0 ? (0, _utils.renderActions)(actions, _const.CLASS_NAMES.FULL_WIDTH.ACTIONS) : ''}
76
80
  ${this.renderHidePermanentlyButton(onHidePermanently, hidePermanentlyLabel)}
77
- ${this.renderCloseButton(onClose)}
81
+ ${this.renderCloseButton({
82
+ onClose,
83
+ hideCloseButton
84
+ })}
78
85
  </div>
79
86
  </div>
80
87
  </div>
@@ -95,8 +102,12 @@ class FullWidthNotification {
95
102
  </button>
96
103
  `;
97
104
  }
98
- renderCloseButton(onClose) {
99
- if (!onClose) return '';
105
+ renderCloseButton(params) {
106
+ const {
107
+ onClose,
108
+ hideCloseButton = false
109
+ } = params;
110
+ if (!onClose || hideCloseButton) return '';
100
111
  return `
101
112
  <button type="button" class="${_const.CLASS_NAMES.FULL_WIDTH.CLOSE_BUTTON}" aria-label="알림 닫기">
102
113
  ${_const.SVG_ICONS['x-close'](_const.FULL_WIDTH_SIZES.CLOSE_BUTTON)}
@@ -16,6 +16,7 @@ class MessageNotification {
16
16
  className: '',
17
17
  actions: [],
18
18
  autoClose: 0,
19
+ hideCloseButton: false,
19
20
  supportingText: undefined,
20
21
  ...options
21
22
  };
@@ -31,6 +32,7 @@ class MessageNotification {
31
32
  className,
32
33
  actions,
33
34
  onClose,
35
+ hideCloseButton,
34
36
  onHidePermanently,
35
37
  hidePermanentlyLabel,
36
38
  variant,
@@ -38,18 +40,17 @@ class MessageNotification {
38
40
  supportTextLinkTarget
39
41
  } = this.options;
40
42
  const isBlock = variant === 'block';
41
- // default 는 neutral, error, warning, success 4가지 색상만 지원 — info 는 block 에서만 유지한다.
42
- const actualColor = !isBlock && color === 'info' ? 'neutral' : color;
43
43
  const wrapperClassName = [isBlock ? _const.CLASS_NAMES.MESSAGE.BLOCK : '', className].filter(Boolean).join(' ');
44
- const wrapper = (0, _utils.createWrapperElement)(_const.CLASS_NAMES.MESSAGE.BASE, actualColor, wrapperClassName);
45
- const featuredIconElement = this.createFeaturedIcon(actualColor, isBlock);
44
+ const wrapper = (0, _utils.createWrapperElement)(_const.CLASS_NAMES.MESSAGE.BASE, color, wrapperClassName);
45
+ const featuredIconElement = this.createFeaturedIcon(color, isBlock);
46
46
  wrapper.innerHTML = (0, _sanitize.sanitizeHtml)((0, _messageTemplate.buildMessageTemplate)({
47
47
  title,
48
48
  supportingText,
49
49
  supportTextLink: isBlock ? supportTextLink : undefined,
50
- color: actualColor,
50
+ color,
51
51
  actions,
52
52
  onClose,
53
+ hideCloseButton,
53
54
  onHidePermanently,
54
55
  hidePermanentlyLabel
55
56
  }));
@@ -63,15 +64,14 @@ class MessageNotification {
63
64
  }
64
65
  return wrapper;
65
66
  }
66
- /** 색상별 FeaturedIcon. default 는 md(40/20), block 은 sm(32/16). */
67
+ /** 색상별 FeaturedIcon. default 는 md(40/20), block 은 sm(32/16). info 아이콘만 variant 별로 다르다. */
67
68
  createFeaturedIcon(color, isBlock) {
68
- const iconFunction = _const.MESSAGE_ICON_MAP[color];
69
- if (!iconFunction) return null;
69
+ const iconFunction = (isBlock ? _const.MESSAGE_BLOCK_ICON_MAP : _const.MESSAGE_ICON_MAP)[color];
70
70
  const sizes = isBlock ? _const.MESSAGE_BLOCK_SIZES : _const.MESSAGE_SIZES;
71
71
  this.featuredIcon = _featuredIcon.FeaturedIcon.create({
72
72
  svgString: iconFunction(sizes.ICON_PIXEL),
73
73
  theme: 'light-circle',
74
- // FeaturedIcon 에는 info 색이 없다. block+info 의 violet 톤은 message SCSS 가 덮어쓴다.
74
+ // FeaturedIcon 에는 info 색이 없다. info 의 violet 톤은 message SCSS 가 덮어쓴다.
75
75
  color: color === 'info' ? 'neutral' : color,
76
76
  size: sizes.FEATURED_ICON,
77
77
  // React 구현과 동일하게 `__icon`(flex-shrink: 0)을 부여한다.
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.NcuaNotification = void 0;
7
+ var _notification = require("../../../src/utils/notification");
7
8
  var _FloatingNotification = require("./FloatingNotification");
8
9
  var _FullWidthNotification = require("./FullWidthNotification");
9
10
  var _MessageNotification = require("./MessageNotification");
@@ -79,8 +80,13 @@ class NcuaNotification {
79
80
  supportingText,
80
81
  color,
81
82
  type: 'floating',
82
- autoClose: autoCloseMap[color],
83
- ...options
83
+ ...options,
84
+ // 명시 autoClose > 색상별 기본값 > (floating 이고 hideCloseButton 이면 3초). neutral 은 기본 0 이라 세 번째 분기가 필요.
85
+ autoClose: (0, _notification.resolveAutoClose)({
86
+ autoClose: options?.autoClose,
87
+ hideCloseButton: (options?.type ?? 'floating') === 'floating' && options?.hideCloseButton,
88
+ fallback: autoCloseMap[color]
89
+ })
84
90
  });
85
91
  }
86
92
  // 클래스를 생성하지 않고도 기본 floating 알림 생성을 하기 위한 함수들
@@ -3,7 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.SVG_ICONS = exports.MESSAGE_ICON_MAP = exports.ICON_MAP = exports.FULL_WIDTH_ICON_MAP = exports.FLOATING_ICON_MAP = void 0;
6
+ exports.SVG_ICONS = exports.MESSAGE_ICON_MAP = exports.MESSAGE_BLOCK_ICON_MAP = exports.ICON_MAP = exports.FULL_WIDTH_ICON_MAP = exports.FLOATING_ICON_MAP = void 0;
7
+ /**
8
+ * message block 변형의 InfoCircle. `SVG_ICONS['info-circle']`은 full-width 전용 class·color 가 박혀 있어
9
+ * 쓰지 않는다 (`.ncua-full-width-notification__icon`은 모바일에서 숨겨진다).
10
+ */
11
+ 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>`;
7
12
  // SVG 아이콘들 (크기는 동적으로 설정)
8
13
  const SVG_ICONS = exports.SVG_ICONS = {
9
14
  '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>`,
@@ -29,12 +34,16 @@ const FULL_WIDTH_ICON_MAP = exports.FULL_WIDTH_ICON_MAP = {
29
34
  info: SVG_ICONS['info-circle']
30
35
  };
31
36
  const ICON_MAP = exports.ICON_MAP = FULL_WIDTH_ICON_MAP;
32
- /**
33
- * message 타입 아이콘. floating 과 같은 4색에 block 변형 전용 info 를 더한다.
34
- * `SVG_ICONS['info-circle']`은 full-width 전용 class·color 가 박혀 있어 쓰지 않는다
35
- * (`.ncua-full-width-notification__icon`은 모바일에서 숨겨진다).
36
- */
37
+ /** message 기본 타입 아이콘. floating 과 같은 4색에 info(neutral 과 같은 핀)를 더한다. */
37
38
  const MESSAGE_ICON_MAP = exports.MESSAGE_ICON_MAP = {
38
- ...FLOATING_ICON_MAP,
39
- info: 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>`
39
+ neutral: SVG_ICONS['pin-02'],
40
+ error: SVG_ICONS['alert-triangle'],
41
+ warning: SVG_ICONS['alert-circle'],
42
+ success: SVG_ICONS['check-circle'],
43
+ info: SVG_ICONS['pin-02']
44
+ };
45
+ /** block 변형 아이콘. info 만 InfoCircle 로 다르다 (#536 유지). */
46
+ const MESSAGE_BLOCK_ICON_MAP = exports.MESSAGE_BLOCK_ICON_MAP = {
47
+ ...MESSAGE_ICON_MAP,
48
+ info: INFO_CIRCLE_ICON
40
49
  };
@@ -57,6 +57,12 @@ Object.defineProperty(exports, "ICON_PIXEL_SIZES", {
57
57
  return _sizes.ICON_PIXEL_SIZES;
58
58
  }
59
59
  });
60
+ Object.defineProperty(exports, "MESSAGE_BLOCK_ICON_MAP", {
61
+ enumerable: true,
62
+ get: function () {
63
+ return _icons.MESSAGE_BLOCK_ICON_MAP;
64
+ }
65
+ });
60
66
  Object.defineProperty(exports, "MESSAGE_BLOCK_SIZES", {
61
67
  enumerable: true,
62
68
  get: function () {
@@ -25,6 +25,7 @@ function buildMessageTemplate(params) {
25
25
  color,
26
26
  actions,
27
27
  onClose,
28
+ hideCloseButton,
28
29
  onHidePermanently,
29
30
  hidePermanentlyLabel
30
31
  } = params;
@@ -40,6 +41,7 @@ function buildMessageTemplate(params) {
40
41
  ${renderActionsContainer({
41
42
  actions,
42
43
  onClose,
44
+ hideCloseButton,
43
45
  onHidePermanently,
44
46
  hidePermanentlyLabel,
45
47
  color
@@ -57,6 +59,7 @@ function renderActionsContainer(params) {
57
59
  const {
58
60
  actions,
59
61
  onClose,
62
+ hideCloseButton,
60
63
  onHidePermanently,
61
64
  hidePermanentlyLabel,
62
65
  color
@@ -64,6 +67,7 @@ function renderActionsContainer(params) {
64
67
  const actionsHtml = (0, _utils.renderActions)(actions ?? [], _const.CLASS_NAMES.MESSAGE.ACTIONS, ACTION_BUTTON_SIZE);
65
68
  const footerHtml = renderFooterContainer({
66
69
  onClose,
70
+ hideCloseButton,
67
71
  onHidePermanently,
68
72
  hidePermanentlyLabel,
69
73
  color
@@ -75,15 +79,23 @@ function renderActionsContainer(params) {
75
79
  function renderFooterContainer(params) {
76
80
  const {
77
81
  onClose,
82
+ hideCloseButton,
78
83
  onHidePermanently,
79
84
  hidePermanentlyLabel,
80
85
  color
81
86
  } = params;
82
- if (!onHidePermanently && !onClose) return '';
87
+ // footer 컨테이너와 닫기 버튼이 같은 판정을 보게 해 빈 footer 가 남지 않게 한다.
88
+ // cf. React `MessageNotificationParts.tsx` 의 showCloseButton — 두 구현이 같은 판정을 유지해야 한다.
89
+ const showCloseButton = Boolean(onClose) && !hideCloseButton;
90
+ if (!onHidePermanently && !showCloseButton) return '';
83
91
  return `
84
92
  <div class="${_const.CLASS_NAMES.MESSAGE.FOOTER_CONTAINER}">
85
93
  ${renderHidePermanentlyButton(onHidePermanently, hidePermanentlyLabel)}
86
- ${renderCloseButton(onClose, color)}
94
+ ${renderCloseButton({
95
+ onClose,
96
+ hideCloseButton,
97
+ color
98
+ })}
87
99
  </div>
88
100
  `;
89
101
  }
@@ -106,9 +118,13 @@ function renderHidePermanentlyButton(onHidePermanently, hidePermanentlyLabel) {
106
118
  * 닫기(X) 버튼. 아이콘 색은 React `<XClose color>`와 같이 svg 의 `color` 속성으로 주고
107
119
  * path 는 `stroke="currentColor"`로 상속받는다 — 두 구현이 같은 마크업을 낸다.
108
120
  */
109
- function renderCloseButton(onClose) {
110
- let color = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'neutral';
111
- if (!onClose) return '';
121
+ function renderCloseButton(params) {
122
+ const {
123
+ onClose,
124
+ hideCloseButton = false,
125
+ color = 'neutral'
126
+ } = params;
127
+ if (!onClose || hideCloseButton) return '';
112
128
  const iconColor = _notification.MESSAGE_CLOSE_ICON_COLOR[color];
113
129
  return `
114
130
  <button type="button" class="${_const.CLASS_NAMES.MESSAGE.CLOSE_BUTTON}" aria-label="알림 닫기">
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.MESSAGE_CLOSE_ICON_COLOR = exports.HIDE_PERMANENTLY_LABEL = void 0;
6
+ exports.MESSAGE_CLOSE_ICON_COLOR = exports.HIDE_PERMANENTLY_LABEL = exports.HIDE_CLOSE_BUTTON_AUTO_CLOSE_MS = void 0;
7
7
  var _color = require("./color");
8
8
  /**
9
9
  * 다시보지 않기 버튼의 타입별 기본 문구.
@@ -24,7 +24,6 @@ const HIDE_PERMANENTLY_LABEL = exports.HIDE_PERMANENTLY_LABEL = {
24
24
  * message 타입 닫기(X) 아이콘의 color 별 색.
25
25
  *
26
26
  * React(`MessageNotification.tsx`)와 Vanilla(`messageTemplate.ts`)가 함께 참조하는 단일 출처다.
27
- * `info`는 `variant: 'block'`에서만 렌더된다(default 는 neutral 로 폴백).
28
27
  */
29
28
  const MESSAGE_CLOSE_ICON_COLOR = exports.MESSAGE_CLOSE_ICON_COLOR = {
30
29
  neutral: _color.COLOR.gray700,
@@ -32,4 +31,10 @@ const MESSAGE_CLOSE_ICON_COLOR = exports.MESSAGE_CLOSE_ICON_COLOR = {
32
31
  warning: _color.COLOR.orange500,
33
32
  success: _color.COLOR.green600,
34
33
  info: _color.COLOR.violet600
35
- };
34
+ };
35
+ /**
36
+ * floating(토스트)에서 `hideCloseButton`인데 `autoClose`를 지정하지 않았을 때 적용되는 자동 닫힘 시간(ms).
37
+ * 닫기 버튼이 없는 토스트가 영구히 남지 않게 한다 — DES-SPEC-027 §5.3 Toast Alert 3초.
38
+ * full-width · message 는 부모가 언마운트로 닫으므로 적용하지 않는다.
39
+ */
40
+ const HIDE_CLOSE_BUTTON_AUTO_CLOSE_MS = exports.HIDE_CLOSE_BUTTON_AUTO_CLOSE_MS = 3000;
@@ -15,6 +15,7 @@ var _ButtonCloseX = require("../../action/button/ButtonCloseX");
15
15
  var _FeaturedIcon = require("../../image-and-icons/featured-icon/FeaturedIcon");
16
16
  var _host = require("./host");
17
17
  var _NotificationActionButtons = require("./NotificationActionButtons");
18
+ var _useAutoClose = require("./useAutoClose");
18
19
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
19
20
  // 호스트 싱글톤은 vanilla/React 양쪽이 동일한 함수를 공유한다 — host.ts 가 가까운 진입점 역할을
20
21
  // 하므로 React 컴포넌트는 deep relative path 로 vanilla internals 를 직접 import 하지 않는다.
@@ -34,7 +35,7 @@ const iconMap = {
34
35
  error: _uiAdminIcon.AlertTriangle,
35
36
  warning: _uiAdminIcon.AlertCircle,
36
37
  success: _uiAdminIcon.CheckCircle
37
- // info 는 full-width 전용이라 floating 아이콘 매핑 없음.
38
+ // info 는 floating 에서 지원하지 않으므로 아이콘 매핑 없음.
38
39
  };
39
40
  /**
40
41
  * NotificationColor → FeaturedIconColor 매핑.
@@ -73,13 +74,19 @@ const FloatingNotification = exports.FloatingNotification = /*#__PURE__*/(0, _re
73
74
  supportingText,
74
75
  color = 'neutral',
75
76
  onClose,
77
+ hideCloseButton = false,
76
78
  className,
77
79
  actions,
78
- autoClose = 0,
80
+ autoClose,
79
81
  portal = false,
80
82
  ...rest
81
83
  } = _ref;
82
- const [shouldRemove, setShouldRemove] = (0, _react.useState)(false);
84
+ // floating 은 닫기 버튼이 없는데 autoClose 도 없으면 영구히 남으므로 기본 3초를 준다.
85
+ const shouldRemove = (0, _useAutoClose.useAutoClose)({
86
+ autoClose,
87
+ hideCloseButton,
88
+ onClose
89
+ });
83
90
  const featuredIconProps = {
84
91
  icon: iconMap[color] || _uiAdminIcon.Pin02,
85
92
  size: 'sm',
@@ -89,31 +96,6 @@ const FloatingNotification = exports.FloatingNotification = /*#__PURE__*/(0, _re
89
96
  const isMobile = (0, _useMediaQuery.useMediaQuery)(_breakpoint.MEDIA_QUERY.mobile, {
90
97
  onMatched: onClose
91
98
  });
92
- // onClose 는 매 렌더 새 함수 ref 일 수 있으므로 ref 로 latest 만 보관.
93
- // → autoClose 타이머 effect 의 deps 에서 onClose 를 빼서 타이머 재시작 회피.
94
- // render 본문에서 직접 할당 — useEffect 로 미루면 같은 commit 안에서 fire 되는 타이머가 stale onClose 를 볼 위험.
95
- const onCloseRef = (0, _react.useRef)(onClose);
96
- onCloseRef.current = onClose;
97
- // autoClose 타이머 관리
98
- const timerRef = (0, _react.useRef)(null);
99
- // onClose 는 onCloseRef 로 latest 만 추적하므로 deps 에서 제외 (의도된 패턴).
100
- (0, _react.useEffect)(() => {
101
- // autoClose 가 0 보다 크면 타이머 설정.
102
- if (autoClose > 0) {
103
- timerRef.current = setTimeout(() => {
104
- onCloseRef.current?.();
105
- // DOM 에서 바로 제거
106
- setShouldRemove(true);
107
- }, autoClose);
108
- }
109
- // cleanup: 컴포넌트 언마운트 또는 autoClose 변경 시 타이머 정리
110
- return () => {
111
- if (timerRef.current) {
112
- clearTimeout(timerRef.current);
113
- timerRef.current = null;
114
- }
115
- };
116
- }, [autoClose]);
117
99
  // portal=true 일 때만 호스트가 필요하다.
118
100
  const host = useMountFloatingNotificationHost(portal);
119
101
  // a11y — 카드 root 의 role 과 제목/본문 ID. 색상에 따라 alert(error/warning) / status(나머지) 로 분기.
@@ -163,7 +145,7 @@ const FloatingNotification = exports.FloatingNotification = /*#__PURE__*/(0, _re
163
145
  })]
164
146
  })]
165
147
  })
166
- }), onClose && (0, _jsxRuntime.jsx)(_ButtonCloseX.ButtonCloseX, {
148
+ }), onClose && !hideCloseButton && (0, _jsxRuntime.jsx)(_ButtonCloseX.ButtonCloseX, {
167
149
  theme: "light",
168
150
  className: "ncua-floating-notification__close-button",
169
151
  size: isMobile ? 'sm' : 'xs',
@@ -13,6 +13,7 @@ var _notification = require("../../../../constant/notification");
13
13
  var _url = require("../../../utils/url");
14
14
  var _linkTarget = require("./linkTarget");
15
15
  var _NotificationActionButtons = require("./NotificationActionButtons");
16
+ var _useAutoClose = require("./useAutoClose");
16
17
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
17
18
  const iconMap = {
18
19
  neutral: _uiAdminIcon.MessageChatSquare,
@@ -34,43 +35,27 @@ const FullWidthNotification = exports.FullWidthNotification = /*#__PURE__*/(0, _
34
35
  supportingText,
35
36
  color = 'neutral',
36
37
  onClose,
38
+ hideCloseButton = false,
37
39
  className,
38
40
  actions,
39
- autoClose = 0,
41
+ autoClose,
40
42
  supportTextLink,
41
43
  supportTextLinkTarget,
42
44
  onHidePermanently,
43
45
  hidePermanentlyLabel = _notification.HIDE_PERMANENTLY_LABEL.fullWidth,
44
46
  ...rest
45
47
  } = _ref;
46
- const [shouldRemove, setShouldRemove] = (0, _react.useState)(false);
48
+ // full-width 는 부모가 언마운트로 닫으므로 hideCloseButton 기본 autoClose 를 적용하지 않는다.
49
+ const shouldRemove = (0, _useAutoClose.useAutoClose)({
50
+ autoClose,
51
+ onClose
52
+ });
47
53
  // unsafe URL(javascript: 등)이면 링크 없이 텍스트만 렌더한다 — Vanilla `renderSupportingText` 와 같은 정책.
48
54
  const safeSupportTextLink = supportTextLink && (0, _url.isSafeUrl)(supportTextLink) ? supportTextLink : undefined;
49
55
  const closeIconSize = {
50
56
  width: 20,
51
57
  height: 20
52
58
  };
53
- // autoClose 타이머 관리
54
- const timerRef = (0, _react.useRef)(null);
55
- (0, _react.useEffect)(() => {
56
- // autoClose가 0보다 크면 무조건 타이머 설정
57
- if (autoClose > 0) {
58
- timerRef.current = setTimeout(() => {
59
- if (onClose) {
60
- onClose();
61
- }
62
- // DOM에서 바로 제거
63
- setShouldRemove(true);
64
- }, autoClose);
65
- }
66
- // cleanup 함수: 컴포넌트 언마운트 시 타이머 정리
67
- return () => {
68
- if (timerRef.current) {
69
- clearTimeout(timerRef.current);
70
- timerRef.current = null;
71
- }
72
- };
73
- }, [autoClose, onClose]);
74
59
  // DOM에서 완전히 제거
75
60
  if (shouldRemove) {
76
61
  return null;
@@ -124,7 +109,7 @@ const FullWidthNotification = exports.FullWidthNotification = /*#__PURE__*/(0, _
124
109
  className: (0, _classnames.default)('ncua-notification__action-button', 'ncua-notification__action-button--text', 'ncua-full-width-notification__link'),
125
110
  onClick: onHidePermanently,
126
111
  children: hidePermanentlyLabel
127
- }), onClose && (0, _jsxRuntime.jsx)("button", {
112
+ }), onClose && !hideCloseButton && (0, _jsxRuntime.jsx)("button", {
128
113
  type: "button",
129
114
  className: "ncua-full-width-notification__close-button",
130
115
  onClick: onClose,
@@ -10,13 +10,19 @@ var _classnames = _interopRequireDefault(require("classnames"));
10
10
  var _react = require("react");
11
11
  var _notification = require("../../../../constant/notification");
12
12
  var _MessageNotificationParts = require("./MessageNotificationParts");
13
+ var _useAutoClose = require("./useAutoClose");
13
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
- const iconMap = {
15
+ const DEFAULT_ICON_MAP = {
15
16
  neutral: _uiAdminIcon.Pin02,
16
17
  error: _uiAdminIcon.AlertTriangle,
17
18
  warning: _uiAdminIcon.AlertCircle,
18
19
  success: _uiAdminIcon.CheckCircle,
19
- // info 는 variant="block" 에서만 도달한다 (default 는 neutral 로 폴백).
20
+ // 디자인 기준 default 의 info 는 neutral 과 같은 핀이다.
21
+ info: _uiAdminIcon.Pin02
22
+ };
23
+ // block 의 info 는 InfoCircle 을 유지한다 (#536).
24
+ const BLOCK_ICON_MAP = {
25
+ ...DEFAULT_ICON_MAP,
20
26
  info: _uiAdminIcon.InfoCircle
21
27
  };
22
28
  const MessageNotification = exports.MessageNotification = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
@@ -26,6 +32,8 @@ const MessageNotification = exports.MessageNotification = /*#__PURE__*/(0, _reac
26
32
  icon: Icon,
27
33
  color = 'neutral',
28
34
  onClose,
35
+ hideCloseButton = false,
36
+ autoClose,
29
37
  className,
30
38
  actions,
31
39
  onHidePermanently,
@@ -36,13 +44,20 @@ const MessageNotification = exports.MessageNotification = /*#__PURE__*/(0, _reac
36
44
  ...rest
37
45
  } = _ref;
38
46
  const isBlock = variant === 'block';
39
- // default 는 neutral, error, warning, success 4가지 색상만 지원 — info 는 block 에서만 유지한다.
40
- const validColor = !isBlock && color === 'info' ? 'neutral' : color;
41
- // FeaturedIcon 에는 info 색이 없다. block+info 의 violet 톤은 message SCSS 가 덮어쓴다.
42
- const featuredIconColor = validColor === 'info' ? 'neutral' : validColor;
47
+ const iconMap = isBlock ? BLOCK_ICON_MAP : DEFAULT_ICON_MAP;
48
+ // FeaturedIcon 에는 info 색이 없다. info 의 violet 톤은 message SCSS 가 덮어쓴다.
49
+ const featuredIconColor = color === 'info' ? 'neutral' : color;
50
+ // message 는 부모가 언마운트로 닫으므로 hideCloseButton 기본 autoClose 를 적용하지 않는다.
51
+ const shouldRemove = (0, _useAutoClose.useAutoClose)({
52
+ autoClose,
53
+ onClose
54
+ });
55
+ if (shouldRemove) {
56
+ return null;
57
+ }
43
58
  return (0, _jsxRuntime.jsx)("div", {
44
59
  ref: ref,
45
- className: (0, _classnames.default)('ncua-message-notification', `ncua-message-notification--${validColor}`, {
60
+ className: (0, _classnames.default)('ncua-message-notification', `ncua-message-notification--${color}`, {
46
61
  'ncua-message-notification--block': isBlock
47
62
  }, className),
48
63
  role: "alert",
@@ -56,15 +71,16 @@ const MessageNotification = exports.MessageNotification = /*#__PURE__*/(0, _reac
56
71
  supportingText: supportingText,
57
72
  supportTextLink: isBlock ? supportTextLink : undefined,
58
73
  supportTextLinkTarget: supportTextLinkTarget,
59
- icon: Icon || iconMap[validColor],
74
+ icon: Icon || iconMap[color],
60
75
  iconColor: featuredIconColor,
61
76
  iconSize: isBlock ? 'sm' : 'md'
62
77
  }), (0, _jsxRuntime.jsx)(_MessageNotificationParts.MessageNotificationActions, {
63
78
  actions: actions,
64
79
  onClose: onClose,
80
+ hideCloseButton: hideCloseButton,
65
81
  onHidePermanently: onHidePermanently,
66
82
  hidePermanentlyLabel: hidePermanentlyLabel,
67
- closeIconColor: _notification.MESSAGE_CLOSE_ICON_COLOR[validColor]
83
+ closeIconColor: _notification.MESSAGE_CLOSE_ICON_COLOR[color]
68
84
  })]
69
85
  })
70
86
  })
@@ -61,12 +61,15 @@ const MessageNotificationActions = _ref2 => {
61
61
  let {
62
62
  actions,
63
63
  onClose,
64
+ hideCloseButton = false,
64
65
  onHidePermanently,
65
66
  hidePermanentlyLabel = _notification.HIDE_PERMANENTLY_LABEL.message,
66
67
  closeIconColor
67
68
  } = _ref2;
68
69
  const hasActions = Boolean(actions?.length);
69
- const hasFooter = Boolean(onHidePermanently || onClose);
70
+ // footer 컨테이너와 닫기 버튼이 같은 판정을 보게 해 빈 footer 가 남지 않게 한다.
71
+ const showCloseButton = Boolean(onClose) && !hideCloseButton;
72
+ const hasFooter = Boolean(onHidePermanently) || showCloseButton;
70
73
  if (!hasActions && !hasFooter) return null;
71
74
  return (0, _jsxRuntime.jsxs)("div", {
72
75
  className: "ncua-message-notification__actions-container",
@@ -82,7 +85,7 @@ const MessageNotificationActions = _ref2 => {
82
85
  className: "ncua-notification__action-button ncua-message-notification__hide-link",
83
86
  onClick: onHidePermanently,
84
87
  children: hidePermanentlyLabel
85
- }), onClose && (0, _jsxRuntime.jsx)("button", {
88
+ }), showCloseButton && (0, _jsxRuntime.jsx)("button", {
86
89
  type: "button",
87
90
  className: "ncua-message-notification__close-button",
88
91
  onClick: onClose,
@@ -57,6 +57,7 @@ const Notification = exports.Notification = /*#__PURE__*/(0, _react.forwardRef)(
57
57
  actions: _actions,
58
58
  autoClose: _autoClose,
59
59
  onClose: _onClose,
60
+ hideCloseButton: _hideCloseButton,
60
61
  onHidePermanently: _onHidePermanently,
61
62
  hidePermanentlyLabel: _hidePermanentlyLabel,
62
63
  portal: _portal,