@ncds/ui-admin 1.8.21-alpha.11 → 1.8.21-alpha.13

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 (26) hide show
  1. package/dist/cjs/src/components/overlays/notification/CalloutNotification.js +6 -1
  2. package/dist/cjs/src/components/overlays/notification/Notification.js +22 -2
  3. package/dist/cjs/src/components/overlays/notification/__tests__/CalloutNotification.test.js +128 -0
  4. package/dist/cjs/src/components/overlays/notification/__tests__/Notification.test.js +83 -0
  5. package/dist/cjs/src/generated/scoped-css.js +1 -1
  6. package/dist/esm/src/components/overlays/notification/CalloutNotification.js +6 -1
  7. package/dist/esm/src/components/overlays/notification/Notification.js +22 -2
  8. package/dist/esm/src/components/overlays/notification/__tests__/CalloutNotification.test.js +125 -0
  9. package/dist/esm/src/components/overlays/notification/__tests__/Notification.test.js +80 -0
  10. package/dist/esm/src/generated/scoped-css.js +1 -1
  11. package/dist/temp/src/components/overlays/notification/CalloutNotification.d.ts +3 -1
  12. package/dist/temp/src/components/overlays/notification/CalloutNotification.js +5 -1
  13. package/dist/temp/src/components/overlays/notification/Notification.d.ts +12 -2
  14. package/dist/temp/src/components/overlays/notification/Notification.js +9 -4
  15. package/dist/temp/src/components/overlays/notification/__tests__/CalloutNotification.test.d.ts +1 -0
  16. package/dist/temp/src/components/overlays/notification/__tests__/CalloutNotification.test.js +108 -0
  17. package/dist/temp/src/components/overlays/notification/__tests__/Notification.test.d.ts +1 -0
  18. package/dist/temp/src/components/overlays/notification/__tests__/Notification.test.js +71 -0
  19. package/dist/temp/src/generated/scoped-css.js +1 -1
  20. package/dist/types/src/components/overlays/notification/CalloutNotification.d.ts +3 -1
  21. package/dist/types/src/components/overlays/notification/Notification.d.ts +12 -2
  22. package/dist/types/src/components/overlays/notification/__tests__/CalloutNotification.test.d.ts +1 -0
  23. package/dist/types/src/components/overlays/notification/__tests__/Notification.test.d.ts +1 -0
  24. package/dist/ui-admin/assets/styles/style.css +7 -0
  25. package/dist/ui-admin/assets/styles/style.scoped.css +7 -0
  26. package/package.json +1 -1
@@ -8,16 +8,21 @@ var _jsxRuntime = require("react/jsx-runtime");
8
8
  var _classnames = _interopRequireDefault(require("classnames"));
9
9
  var _react = require("react");
10
10
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ const WIDTH_CLASS = {
12
+ full: 'ncua-callout-notification--full',
13
+ fit: 'ncua-callout-notification--fit'
14
+ };
11
15
  const CalloutNotification = exports.CalloutNotification = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
12
16
  let {
13
17
  color = 'neutral',
14
18
  className,
15
19
  title,
20
+ width,
16
21
  ...rest
17
22
  } = _ref;
18
23
  return (0, _jsxRuntime.jsx)("div", {
19
24
  ref: ref,
20
- className: (0, _classnames.default)('ncua-callout-notification', `ncua-callout-notification--${color}`, className),
25
+ className: (0, _classnames.default)('ncua-callout-notification', `ncua-callout-notification--${color}`, width && WIDTH_CLASS[width], className),
21
26
  ...rest,
22
27
  children: title
23
28
  });
@@ -10,10 +10,15 @@ var _CalloutNotification = require("./CalloutNotification");
10
10
  var _FloatingNotification = require("./FloatingNotification");
11
11
  var _FullWidthNotification = require("./FullWidthNotification");
12
12
  var _MessageNotification = require("./MessageNotification");
13
- const Notification = exports.Notification = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
13
+ const Notification = exports.Notification = /*#__PURE__*/(0, _react.forwardRef)(
14
+ // 단일 type 에만 유효한 prop 은 rest 에서 분리해 해당 분기로만 명시 전달한다.
15
+ // rest 에 남기면 다른 type 의 하위 컴포넌트가 div 로 스프레드해 DOM 속성으로 출력된다.
16
+ (_ref, ref) => {
14
17
  let {
15
18
  type = 'floating',
16
19
  color = 'neutral',
20
+ width,
21
+ supportTextLink,
17
22
  ...rest
18
23
  } = _ref;
19
24
  if (type === 'floating') {
@@ -26,6 +31,7 @@ const Notification = exports.Notification = /*#__PURE__*/(0, _react.forwardRef)(
26
31
  if (type === 'full-width') {
27
32
  return (0, _jsxRuntime.jsx)(_FullWidthNotification.FullWidthNotification, {
28
33
  color: color,
34
+ supportTextLink: supportTextLink,
29
35
  ...rest,
30
36
  ref: ref
31
37
  });
@@ -38,9 +44,23 @@ const Notification = exports.Notification = /*#__PURE__*/(0, _react.forwardRef)(
38
44
  });
39
45
  }
40
46
  if (type === 'callout') {
47
+ // 나머지 3개 type 이 공유하는 prop 은 callout 이 지원하지 않으므로 여기서 제외한다.
48
+ const {
49
+ icon: _icon,
50
+ supportingText: _supportingText,
51
+ actions: _actions,
52
+ autoClose: _autoClose,
53
+ onClose: _onClose,
54
+ onHidePermanently: _onHidePermanently,
55
+ hidePermanentlyLabel: _hidePermanentlyLabel,
56
+ portal: _portal,
57
+ ...calloutProps
58
+ } = rest;
41
59
  return (0, _jsxRuntime.jsx)(_CalloutNotification.CalloutNotification, {
42
60
  color: color,
43
- ...rest
61
+ width: width,
62
+ ...calloutProps,
63
+ ref: ref
44
64
  });
45
65
  }
46
66
  return null;
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+
3
+ var _react = require("react");
4
+ var _client = require("react-dom/client");
5
+ var _testUtils = require("react-dom/test-utils");
6
+ var _vitest = require("vitest");
7
+ var _CalloutNotification = require("../CalloutNotification");
8
+ var _Notification = require("../Notification");
9
+ // @vitest-environment jsdom
10
+
11
+ // React 18에서 act() 사용 시 필요한 플래그 (미설정 시 console.error 경고 발생)
12
+ globalThis.IS_REACT_ACT_ENVIRONMENT = true;
13
+ const BASE = 'ncua-callout-notification';
14
+ let root = null;
15
+ let container = null;
16
+ const mount = element => {
17
+ container = document.createElement('div');
18
+ document.body.appendChild(container);
19
+ root = (0, _client.createRoot)(container);
20
+ (0, _testUtils.act)(() => {
21
+ root?.render(element);
22
+ });
23
+ const rendered = container.firstElementChild;
24
+ if (!(rendered instanceof HTMLElement)) throw new Error('callout 이 렌더되지 않았다');
25
+ return rendered;
26
+ };
27
+ const renderCallout = function () {
28
+ let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
29
+ return mount(/*#__PURE__*/(0, _react.createElement)(_CalloutNotification.CalloutNotification, {
30
+ title: '안내 문구',
31
+ ...props
32
+ }));
33
+ };
34
+ const renderNotification = function () {
35
+ let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
36
+ return mount(/*#__PURE__*/(0, _react.createElement)(_Notification.Notification, {
37
+ type: 'callout',
38
+ title: '안내 문구',
39
+ ...props
40
+ }));
41
+ };
42
+ (0, _vitest.afterEach)(() => {
43
+ (0, _testUtils.act)(() => {
44
+ root?.unmount();
45
+ });
46
+ container?.remove();
47
+ root = null;
48
+ container = null;
49
+ });
50
+ (0, _vitest.describe)('CalloutNotification — width prop', () => {
51
+ (0, _vitest.it)('width 미지정 시 너비 클래스를 붙이지 않는다 (부모 너비를 채우는 기본 스타일 유지)', () => {
52
+ const element = renderCallout();
53
+ (0, _vitest.expect)(element.classList.contains('ncua-callout-notification--full')).toBe(false);
54
+ (0, _vitest.expect)(element.classList.contains('ncua-callout-notification--fit')).toBe(false);
55
+ });
56
+ (0, _vitest.it)("width='full' 은 --full modifier 를 붙인다", () => {
57
+ const element = renderCallout({
58
+ width: 'full'
59
+ });
60
+ (0, _vitest.expect)(element.classList.contains('ncua-callout-notification--full')).toBe(true);
61
+ (0, _vitest.expect)(element.classList.contains('ncua-callout-notification--fit')).toBe(false);
62
+ });
63
+ (0, _vitest.it)("width='fit' 은 --fit modifier 를 붙인다", () => {
64
+ const element = renderCallout({
65
+ width: 'fit'
66
+ });
67
+ (0, _vitest.expect)(element.classList.contains('ncua-callout-notification--fit')).toBe(true);
68
+ (0, _vitest.expect)(element.classList.contains('ncua-callout-notification--full')).toBe(false);
69
+ });
70
+ (0, _vitest.it)('width 는 DOM 속성으로 새지 않는다', () => {
71
+ const element = renderCallout({
72
+ width: 'fit'
73
+ });
74
+ (0, _vitest.expect)(element.hasAttribute('width')).toBe(false);
75
+ });
76
+ (0, _vitest.it)('width 는 베이스/컬러 클래스와 외부 className 을 유지한 채 추가된다', () => {
77
+ const element = renderCallout({
78
+ width: 'fit',
79
+ color: 'info',
80
+ className: 'custom'
81
+ });
82
+ (0, _vitest.expect)(element.classList.contains(BASE)).toBe(true);
83
+ (0, _vitest.expect)(element.classList.contains(`${BASE}--info`)).toBe(true);
84
+ (0, _vitest.expect)(element.classList.contains('custom')).toBe(true);
85
+ });
86
+ });
87
+ (0, _vitest.describe)('Notification type="callout" — 위임 계약', () => {
88
+ (0, _vitest.it)('width 를 CalloutNotification 으로 전달한다', () => {
89
+ const element = renderNotification({
90
+ width: 'fit'
91
+ });
92
+ (0, _vitest.expect)(element.classList.contains(BASE)).toBe(true);
93
+ (0, _vitest.expect)(element.classList.contains('ncua-callout-notification--fit')).toBe(true);
94
+ });
95
+ // Notification 의 callout 분기가 제외하는 prop 전체. 여기 누락된 prop 은 DOM 속성으로 출력된다.
96
+ (0, _vitest.it)('callout 이 지원하지 않는 prop 은 DOM 속성으로 새지 않는다', () => {
97
+ const element = renderNotification({
98
+ icon: () => null,
99
+ supportingText: '보조 문구',
100
+ supportTextLink: 'https://example.com',
101
+ actions: [{
102
+ label: '확인',
103
+ onClick: () => undefined
104
+ }],
105
+ autoClose: 3000,
106
+ portal: true,
107
+ onClose: () => undefined,
108
+ onHidePermanently: () => undefined,
109
+ hidePermanentlyLabel: '다시 보지 않기'
110
+ });
111
+ for (const attr of ['icon', 'supportingtext', 'supporttextlink', 'actions', 'autoclose', 'portal', 'onclose', 'onhidepermanently', 'hidepermanentlylabel']) {
112
+ (0, _vitest.expect)(element.hasAttribute(attr), attr).toBe(false);
113
+ }
114
+ (0, _vitest.expect)(element.textContent).toBe('안내 문구');
115
+ });
116
+ (0, _vitest.it)('ref 를 callout 루트 엘리먼트로 전달한다', () => {
117
+ let captured = null;
118
+ mount(/*#__PURE__*/(0, _react.createElement)(_Notification.Notification, {
119
+ type: 'callout',
120
+ title: '안내 문구',
121
+ ref: node => {
122
+ captured = node;
123
+ }
124
+ }));
125
+ (0, _vitest.expect)(captured).not.toBeNull();
126
+ (0, _vitest.expect)(captured.classList.contains(BASE)).toBe(true);
127
+ });
128
+ });
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+
3
+ var _react = require("react");
4
+ var _client = require("react-dom/client");
5
+ var _testUtils = require("react-dom/test-utils");
6
+ var _vitest = require("vitest");
7
+ var _Notification = require("../Notification");
8
+ // @vitest-environment jsdom
9
+
10
+ globalThis.IS_REACT_ACT_ENVIRONMENT = true;
11
+ let root = null;
12
+ let container = null;
13
+ (0, _vitest.beforeAll)(() => {
14
+ // jsdom 미구현 API 보정 — FloatingNotification 의 모바일 리스너가 window.matchMedia 를 호출한다.
15
+ if (typeof window.matchMedia !== 'function') {
16
+ const stub = query => ({
17
+ matches: false,
18
+ media: query,
19
+ onchange: null,
20
+ addEventListener: () => undefined,
21
+ removeEventListener: () => undefined,
22
+ addListener: () => undefined,
23
+ removeListener: () => undefined,
24
+ dispatchEvent: () => false
25
+ });
26
+ window.matchMedia = stub;
27
+ }
28
+ });
29
+ // 정의되지 않은 type 의 런타임 동작까지 고정하므로 props 를 넓게 받는다.
30
+ const render = props => {
31
+ container = document.createElement('div');
32
+ document.body.appendChild(container);
33
+ root = (0, _client.createRoot)(container);
34
+ (0, _testUtils.act)(() => {
35
+ root?.render(/*#__PURE__*/(0, _react.createElement)(_Notification.Notification, {
36
+ title: '안내 문구',
37
+ ...props
38
+ }));
39
+ });
40
+ const rendered = container.firstElementChild;
41
+ return rendered instanceof HTMLElement ? rendered : null;
42
+ };
43
+ (0, _vitest.afterEach)(() => {
44
+ (0, _testUtils.act)(() => {
45
+ root?.unmount();
46
+ });
47
+ container?.remove();
48
+ root = null;
49
+ container = null;
50
+ });
51
+ (0, _vitest.describe)('Notification — type 별 위임', () => {
52
+ _vitest.it.each([['floating', 'ncua-floating-notification'], ['full-width', 'ncua-full-width-notification'], ['message', 'ncua-message-notification'], ['callout', 'ncua-callout-notification']])('type=%s 는 %s 를 렌더한다', (type, baseClass) => {
53
+ const element = render({
54
+ type
55
+ });
56
+ (0, _vitest.expect)(element?.classList.contains(baseClass)).toBe(true);
57
+ });
58
+ (0, _vitest.it)('type 미지정은 floating 으로 렌더한다', () => {
59
+ const element = render({});
60
+ (0, _vitest.expect)(element?.classList.contains('ncua-floating-notification')).toBe(true);
61
+ });
62
+ _vitest.it.each(['floating', 'full-width', 'message'])('type=%s 에 callout 전용 width 를 주어도 DOM 속성으로 새지 않는다', type => {
63
+ const element = render({
64
+ type,
65
+ width: 'fit'
66
+ });
67
+ (0, _vitest.expect)(element?.hasAttribute('width')).toBe(false);
68
+ });
69
+ _vitest.it.each(['floating', 'message'])('type=%s 에 full-width 전용 supportTextLink 를 주어도 DOM 속성으로 새지 않는다', type => {
70
+ const element = render({
71
+ type,
72
+ supportingText: '보조',
73
+ supportTextLink: 'https://example.com'
74
+ });
75
+ (0, _vitest.expect)(element?.hasAttribute('supporttextlink')).toBe(false);
76
+ });
77
+ (0, _vitest.it)('정의되지 않은 type 은 아무것도 렌더하지 않는다', () => {
78
+ const element = render({
79
+ type: 'banner'
80
+ });
81
+ (0, _vitest.expect)(element).toBeNull();
82
+ });
83
+ });