@ncds/ui-admin 1.8.4 → 1.8.5

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 (177) hide show
  1. package/dist/cjs/assets/scripts/featuredIcon.js +87 -0
  2. package/dist/cjs/assets/scripts/notification/FloatingNotification.js +178 -0
  3. package/dist/cjs/assets/scripts/notification/FullWidthNotification.js +133 -0
  4. package/dist/cjs/assets/scripts/notification/MessageNotification.js +159 -0
  5. package/dist/cjs/assets/scripts/notification/Notification.js +120 -0
  6. package/dist/cjs/assets/scripts/notification/const/classNames.js +50 -0
  7. package/dist/cjs/assets/scripts/notification/const/icons.js +31 -0
  8. package/dist/cjs/assets/scripts/notification/const/index.js +87 -0
  9. package/dist/cjs/assets/scripts/notification/const/sizes.js +46 -0
  10. package/dist/cjs/assets/scripts/notification/const/types.js +14 -0
  11. package/dist/cjs/assets/scripts/notification/index.js +116 -0
  12. package/dist/cjs/assets/scripts/notification/positionSync.js +180 -0
  13. package/dist/cjs/assets/scripts/notification/utils.js +122 -0
  14. package/dist/cjs/assets/scripts/shared/ButtonCloseX.js +45 -0
  15. package/dist/cjs/assets/scripts/utils/sanitize.js +39 -0
  16. package/dist/cjs/src/components/data-display/data-grid/DataGrid.js +5 -1
  17. package/dist/cjs/src/components/data-display/table/Table.js +118 -96
  18. package/dist/cjs/src/components/data-display/table/useTableScrollbars.js +187 -0
  19. package/dist/cjs/src/components/forms-and-input/combo-box/ComboBox.js +11 -10
  20. package/dist/cjs/src/components/forms-and-input/image-file-input/ImageFileInput.js +5 -2
  21. package/dist/cjs/src/components/forms-and-input/select-box/SelectBox.js +67 -29
  22. package/dist/cjs/src/components/overlays/dropdown/Dropdown.js +47 -19
  23. package/dist/cjs/src/components/overlays/notification/CalloutNotification.js +25 -0
  24. package/dist/cjs/src/components/overlays/notification/FloatingNotification.js +86 -13
  25. package/dist/cjs/src/components/overlays/notification/Notification.js +7 -0
  26. package/dist/cjs/src/components/overlays/notification/host.js +12 -0
  27. package/dist/cjs/src/components/overlays/tooltip/Tooltip.js +57 -44
  28. package/dist/cjs/src/components/select-dropdown/SelectDropdown.js +2 -1
  29. package/dist/cjs/src/contexts/FloatingContext.js +11 -0
  30. package/dist/cjs/src/contexts/index.js +16 -0
  31. package/dist/cjs/src/hooks/index.js +11 -0
  32. package/dist/cjs/src/hooks/useFloatingPosition.js +78 -0
  33. package/dist/cjs/src/hooks/usePortalState.js +17 -0
  34. package/dist/cjs/src/utils/dropdown/maxSelection.js +35 -0
  35. package/dist/cjs/src/utils/dropdown/multiSelect.js +72 -15
  36. package/dist/esm/assets/scripts/featuredIcon.js +80 -0
  37. package/dist/esm/assets/scripts/notification/FloatingNotification.js +171 -0
  38. package/dist/esm/assets/scripts/notification/FullWidthNotification.js +126 -0
  39. package/dist/esm/assets/scripts/notification/MessageNotification.js +152 -0
  40. package/dist/esm/assets/scripts/notification/Notification.js +113 -0
  41. package/dist/esm/assets/scripts/notification/const/classNames.js +44 -0
  42. package/dist/esm/assets/scripts/notification/const/icons.js +25 -0
  43. package/dist/esm/assets/scripts/notification/const/index.js +4 -0
  44. package/dist/esm/assets/scripts/notification/const/sizes.js +40 -0
  45. package/dist/esm/assets/scripts/notification/const/types.js +8 -0
  46. package/dist/esm/assets/scripts/notification/index.js +10 -0
  47. package/dist/esm/assets/scripts/notification/positionSync.js +171 -0
  48. package/dist/esm/assets/scripts/notification/utils.js +109 -0
  49. package/dist/esm/assets/scripts/shared/ButtonCloseX.js +37 -0
  50. package/dist/esm/assets/scripts/utils/sanitize.js +31 -0
  51. package/dist/esm/src/components/data-display/data-grid/DataGrid.js +5 -1
  52. package/dist/esm/src/components/data-display/table/Table.js +118 -96
  53. package/dist/esm/src/components/data-display/table/useTableScrollbars.js +179 -0
  54. package/dist/esm/src/components/forms-and-input/combo-box/ComboBox.js +11 -10
  55. package/dist/esm/src/components/forms-and-input/image-file-input/ImageFileInput.js +5 -2
  56. package/dist/esm/src/components/forms-and-input/select-box/SelectBox.js +67 -29
  57. package/dist/esm/src/components/overlays/dropdown/Dropdown.js +47 -19
  58. package/dist/esm/src/components/overlays/notification/CalloutNotification.js +19 -0
  59. package/dist/esm/src/components/overlays/notification/FloatingNotification.js +86 -14
  60. package/dist/esm/src/components/overlays/notification/Notification.js +7 -0
  61. package/dist/esm/src/components/overlays/notification/host.js +9 -0
  62. package/dist/esm/src/components/overlays/tooltip/Tooltip.js +58 -45
  63. package/dist/esm/src/components/select-dropdown/SelectDropdown.js +2 -1
  64. package/dist/esm/src/contexts/FloatingContext.js +4 -0
  65. package/dist/esm/src/contexts/index.js +1 -0
  66. package/dist/esm/src/hooks/index.js +1 -0
  67. package/dist/esm/src/hooks/useFloatingPosition.js +71 -0
  68. package/dist/esm/src/hooks/usePortalState.js +10 -0
  69. package/dist/esm/src/utils/dropdown/maxSelection.js +27 -0
  70. package/dist/esm/src/utils/dropdown/multiSelect.js +70 -14
  71. package/dist/temp/assets/scripts/featuredIcon.d.ts +22 -0
  72. package/dist/temp/assets/scripts/featuredIcon.js +79 -0
  73. package/dist/temp/assets/scripts/notification/FloatingNotification.d.ts +24 -0
  74. package/dist/temp/assets/scripts/notification/FloatingNotification.js +156 -0
  75. package/dist/temp/assets/scripts/notification/FullWidthNotification.d.ts +21 -0
  76. package/dist/temp/assets/scripts/notification/FullWidthNotification.js +111 -0
  77. package/dist/temp/assets/scripts/notification/MessageNotification.d.ts +22 -0
  78. package/dist/temp/assets/scripts/notification/MessageNotification.js +140 -0
  79. package/dist/temp/assets/scripts/notification/Notification.d.ts +22 -0
  80. package/dist/temp/assets/scripts/notification/Notification.js +112 -0
  81. package/dist/temp/assets/scripts/notification/const/classNames.d.ts +43 -0
  82. package/dist/temp/assets/scripts/notification/const/classNames.js +44 -0
  83. package/dist/temp/assets/scripts/notification/const/icons.d.ts +25 -0
  84. package/dist/temp/assets/scripts/notification/const/icons.js +25 -0
  85. package/dist/temp/assets/scripts/notification/const/index.d.ts +5 -0
  86. package/dist/temp/assets/scripts/notification/const/index.js +4 -0
  87. package/dist/temp/assets/scripts/notification/const/sizes.d.ts +32 -0
  88. package/dist/temp/assets/scripts/notification/const/sizes.js +40 -0
  89. package/dist/temp/assets/scripts/notification/const/types.d.ts +19 -0
  90. package/dist/temp/assets/scripts/notification/const/types.js +8 -0
  91. package/dist/temp/assets/scripts/notification/index.d.ts +8 -0
  92. package/dist/temp/assets/scripts/notification/index.js +10 -0
  93. package/dist/temp/assets/scripts/notification/positionSync.d.ts +50 -0
  94. package/dist/temp/assets/scripts/notification/positionSync.js +170 -0
  95. package/dist/temp/assets/scripts/notification/utils.d.ts +8 -0
  96. package/dist/temp/assets/scripts/notification/utils.js +115 -0
  97. package/dist/temp/assets/scripts/shared/ButtonCloseX.d.ts +5 -0
  98. package/dist/temp/assets/scripts/shared/ButtonCloseX.js +33 -0
  99. package/dist/temp/assets/scripts/utils/sanitize.d.ts +22 -0
  100. package/dist/temp/assets/scripts/utils/sanitize.js +31 -0
  101. package/dist/temp/src/components/data-display/data-grid/DataGrid.js +1 -1
  102. package/dist/temp/src/components/data-display/data-grid/DataGrid.types.d.ts +7 -0
  103. package/dist/temp/src/components/data-display/table/Table.d.ts +4 -1
  104. package/dist/temp/src/components/data-display/table/Table.js +53 -68
  105. package/dist/temp/src/components/data-display/table/types.d.ts +18 -0
  106. package/dist/temp/src/components/data-display/table/useTableScrollbars.d.ts +25 -0
  107. package/dist/temp/src/components/data-display/table/useTableScrollbars.js +136 -0
  108. package/dist/temp/src/components/forms-and-input/combo-box/ComboBox.d.ts +8 -0
  109. package/dist/temp/src/components/forms-and-input/combo-box/ComboBox.js +7 -11
  110. package/dist/temp/src/components/forms-and-input/image-file-input/ImageFileInput.js +1 -1
  111. package/dist/temp/src/components/forms-and-input/select-box/SelectBox.d.ts +13 -0
  112. package/dist/temp/src/components/forms-and-input/select-box/SelectBox.js +30 -3
  113. package/dist/temp/src/components/overlays/dropdown/Dropdown.d.ts +5 -0
  114. package/dist/temp/src/components/overlays/dropdown/Dropdown.js +35 -11
  115. package/dist/temp/src/components/overlays/notification/CalloutNotification.d.ts +9 -0
  116. package/dist/temp/src/components/overlays/notification/CalloutNotification.js +6 -0
  117. package/dist/temp/src/components/overlays/notification/FloatingNotification.d.ts +15 -0
  118. package/dist/temp/src/components/overlays/notification/FloatingNotification.js +81 -13
  119. package/dist/temp/src/components/overlays/notification/Notification.d.ts +18 -3
  120. package/dist/temp/src/components/overlays/notification/Notification.js +4 -0
  121. package/dist/temp/src/components/overlays/notification/host.d.ts +9 -0
  122. package/dist/temp/src/components/overlays/notification/host.js +9 -0
  123. package/dist/temp/src/components/overlays/tooltip/Tooltip.d.ts +5 -1
  124. package/dist/temp/src/components/overlays/tooltip/Tooltip.js +25 -22
  125. package/dist/temp/src/components/select-dropdown/SelectDropdown.d.ts +6 -0
  126. package/dist/temp/src/components/select-dropdown/SelectDropdown.js +2 -2
  127. package/dist/temp/src/contexts/FloatingContext.d.ts +6 -0
  128. package/dist/temp/src/contexts/FloatingContext.js +4 -0
  129. package/dist/temp/src/contexts/index.d.ts +1 -0
  130. package/dist/temp/src/contexts/index.js +1 -0
  131. package/dist/temp/src/hooks/index.d.ts +1 -0
  132. package/dist/temp/src/hooks/index.js +1 -0
  133. package/dist/temp/src/hooks/useFloatingPosition.d.ts +19 -0
  134. package/dist/temp/src/hooks/useFloatingPosition.js +55 -0
  135. package/dist/temp/src/hooks/usePortalState.d.ts +6 -0
  136. package/dist/temp/src/hooks/usePortalState.js +7 -0
  137. package/dist/temp/src/utils/dropdown/maxSelection.d.ts +24 -0
  138. package/dist/temp/src/utils/dropdown/maxSelection.js +28 -0
  139. package/dist/temp/src/utils/dropdown/multiSelect.d.ts +42 -2
  140. package/dist/temp/src/utils/dropdown/multiSelect.js +66 -13
  141. package/dist/types/assets/scripts/featuredIcon.d.ts +22 -0
  142. package/dist/types/assets/scripts/notification/FloatingNotification.d.ts +24 -0
  143. package/dist/types/assets/scripts/notification/FullWidthNotification.d.ts +21 -0
  144. package/dist/types/assets/scripts/notification/MessageNotification.d.ts +22 -0
  145. package/dist/types/assets/scripts/notification/Notification.d.ts +22 -0
  146. package/dist/types/assets/scripts/notification/const/classNames.d.ts +43 -0
  147. package/dist/types/assets/scripts/notification/const/icons.d.ts +25 -0
  148. package/dist/types/assets/scripts/notification/const/index.d.ts +5 -0
  149. package/dist/types/assets/scripts/notification/const/sizes.d.ts +32 -0
  150. package/dist/types/assets/scripts/notification/const/types.d.ts +19 -0
  151. package/dist/types/assets/scripts/notification/index.d.ts +8 -0
  152. package/dist/types/assets/scripts/notification/positionSync.d.ts +50 -0
  153. package/dist/types/assets/scripts/notification/utils.d.ts +8 -0
  154. package/dist/types/assets/scripts/shared/ButtonCloseX.d.ts +5 -0
  155. package/dist/types/assets/scripts/utils/sanitize.d.ts +22 -0
  156. package/dist/types/src/components/data-display/data-grid/DataGrid.types.d.ts +7 -0
  157. package/dist/types/src/components/data-display/table/Table.d.ts +4 -1
  158. package/dist/types/src/components/data-display/table/types.d.ts +18 -0
  159. package/dist/types/src/components/data-display/table/useTableScrollbars.d.ts +25 -0
  160. package/dist/types/src/components/forms-and-input/combo-box/ComboBox.d.ts +8 -0
  161. package/dist/types/src/components/forms-and-input/select-box/SelectBox.d.ts +13 -0
  162. package/dist/types/src/components/overlays/dropdown/Dropdown.d.ts +5 -0
  163. package/dist/types/src/components/overlays/notification/CalloutNotification.d.ts +9 -0
  164. package/dist/types/src/components/overlays/notification/FloatingNotification.d.ts +15 -0
  165. package/dist/types/src/components/overlays/notification/Notification.d.ts +18 -3
  166. package/dist/types/src/components/overlays/notification/host.d.ts +9 -0
  167. package/dist/types/src/components/overlays/tooltip/Tooltip.d.ts +5 -1
  168. package/dist/types/src/components/select-dropdown/SelectDropdown.d.ts +6 -0
  169. package/dist/types/src/contexts/FloatingContext.d.ts +6 -0
  170. package/dist/types/src/contexts/index.d.ts +1 -0
  171. package/dist/types/src/hooks/index.d.ts +1 -0
  172. package/dist/types/src/hooks/useFloatingPosition.d.ts +19 -0
  173. package/dist/types/src/hooks/usePortalState.d.ts +6 -0
  174. package/dist/types/src/utils/dropdown/maxSelection.d.ts +24 -0
  175. package/dist/types/src/utils/dropdown/multiSelect.d.ts +42 -2
  176. package/dist/ui-admin/assets/styles/style.css +304 -64
  177. package/package.json +1 -1
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.FeaturedIcon = void 0;
7
+ // React 컴포넌트와 동일하게 구성
8
+ const iconSizeMap = {
9
+ sm: 16,
10
+ md: 20,
11
+ lg: 24,
12
+ xl: 28
13
+ };
14
+ class FeaturedIcon {
15
+ constructor(options) {
16
+ this.options = {
17
+ theme: 'light-circle',
18
+ color: 'neutral',
19
+ size: 'sm',
20
+ className: '',
21
+ ...options
22
+ };
23
+ this.element = this.createElement();
24
+ }
25
+ // svgString ( ICON SVG ) 을 받아서 요소를 생성
26
+ createElement() {
27
+ const {
28
+ theme,
29
+ color,
30
+ size,
31
+ className,
32
+ svgString
33
+ } = this.options;
34
+ // React FeaturedIcon과 동일한 클래스 구조
35
+ const classes = ['ncua-featured-icon', `ncua-featured-icon--${theme}`, `ncua-featured-icon--${color}`, `ncua-featured-icon--${size}`];
36
+ if (className) {
37
+ classes.push(className);
38
+ }
39
+ const div = document.createElement('div');
40
+ div.className = classes.join(' ');
41
+ // outline-circle 테마일 때 추가 요소들 (React 컴포넌트와 동일)
42
+ if (theme === 'outline-circle') {
43
+ const innerOutline = document.createElement('div');
44
+ innerOutline.className = 'ncua-featured-icon__outline ncua-featured-icon__outline--inner';
45
+ div.appendChild(innerOutline);
46
+ const outerOutline = document.createElement('div');
47
+ outerOutline.className = 'ncua-featured-icon__outline ncua-featured-icon__outline--outer';
48
+ div.appendChild(outerOutline);
49
+ }
50
+ // SVG 아이콘 추가
51
+ const iconSize = iconSizeMap[size];
52
+ const svgWithSize = this.addSizeToSvg(svgString, iconSize);
53
+ div.innerHTML += svgWithSize;
54
+ return div;
55
+ }
56
+ addSizeToSvg(svgString, size) {
57
+ return svgString.replace(/<svg([^>]*)>/, `<svg$1 width="${size}" height="${size}">`);
58
+ }
59
+ // Public methods
60
+ getElement() {
61
+ return this.element;
62
+ }
63
+ updateColor(color) {
64
+ this.element.className = this.element.className.replace(/ncua-featured-icon--(neutral|error|warning|success)/, `ncua-featured-icon--${color}`);
65
+ this.options.color = color;
66
+ }
67
+ updateSize(size) {
68
+ const iconSize = iconSizeMap[size];
69
+ this.element.className = this.element.className.replace(/ncua-featured-icon--(sm|md|lg|xl)/, `ncua-featured-icon--${size}`);
70
+ const svgIcon = this.element.querySelector('svg');
71
+ if (svgIcon) {
72
+ svgIcon.setAttribute('width', String(iconSize));
73
+ svgIcon.setAttribute('height', String(iconSize));
74
+ }
75
+ this.options.size = size;
76
+ }
77
+ destroy() {
78
+ if (this.element.parentNode) {
79
+ this.element.parentNode.removeChild(this.element);
80
+ }
81
+ }
82
+ // Static factory method
83
+ static create(options) {
84
+ return new FeaturedIcon(options);
85
+ }
86
+ }
87
+ exports.FeaturedIcon = FeaturedIcon;
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.FloatingNotification = void 0;
7
+ var _breakpoint = require("../../../src/constant/breakpoint");
8
+ var _featuredIcon = require("../featuredIcon");
9
+ var _ButtonCloseX = require("../shared/ButtonCloseX");
10
+ var _sanitize = require("../utils/sanitize");
11
+ var _const = require("./const");
12
+ var _utils = require("./utils");
13
+ class FloatingNotification {
14
+ constructor(options) {
15
+ this.options = {
16
+ color: 'neutral',
17
+ className: '',
18
+ actions: [],
19
+ autoClose: 0,
20
+ supportingText: undefined,
21
+ ...options
22
+ };
23
+ this.element = this.createElement();
24
+ this.bindEvents();
25
+ this.setupAutoClose();
26
+ this.setupMobileListener();
27
+ }
28
+ createElement() {
29
+ const {
30
+ title,
31
+ supportingText,
32
+ color,
33
+ className,
34
+ actions,
35
+ onClose
36
+ } = this.options;
37
+ // 플로팅 알림에서 info 색상 사용 시 neutral로 대체
38
+ let actualColor = color;
39
+ if (color === 'info') {
40
+ actualColor = 'neutral';
41
+ }
42
+ const wrapper = (0, _utils.createWrapperElement)(_const.CLASS_NAMES.FLOATING.BASE, actualColor, className);
43
+ const iconFunction = _const.FLOATING_ICON_MAP[actualColor];
44
+ const mobile = (0, _utils.isMobile)();
45
+ // FeaturedIcon 생성
46
+ let featuredIconElement = null;
47
+ if (iconFunction) {
48
+ const size = _const.getSizes.featuredIcon(mobile);
49
+ const iconSize = _const.getSizes.iconPixel(mobile);
50
+ const iconSvg = iconFunction(iconSize);
51
+ this.featuredIcon = _featuredIcon.FeaturedIcon.create({
52
+ svgString: iconSvg,
53
+ theme: 'dark-circle',
54
+ color: actualColor,
55
+ size: size
56
+ });
57
+ featuredIconElement = this.featuredIcon.getElement();
58
+ }
59
+ wrapper.innerHTML = (0, _sanitize.sanitizeHtml)(this.buildTemplate({
60
+ title,
61
+ supportingText,
62
+ actions,
63
+ onClose,
64
+ isMobile: mobile
65
+ }));
66
+ // FeaturedIcon을 container에 추가
67
+ if (featuredIconElement) {
68
+ const container = wrapper.querySelector(`.${_const.CLASS_NAMES.FLOATING.CONTAINER}`);
69
+ if (container) {
70
+ container.insertBefore(featuredIconElement, container.firstChild);
71
+ }
72
+ }
73
+ return wrapper;
74
+ }
75
+ buildTemplate(params) {
76
+ const {
77
+ title,
78
+ supportingText,
79
+ actions,
80
+ onClose,
81
+ isMobile
82
+ } = params;
83
+ return `
84
+ <div class="${_const.CLASS_NAMES.FLOATING.CONTENT}">
85
+ <div class="${_const.CLASS_NAMES.FLOATING.CONTAINER}">
86
+ <div class="${_const.CLASS_NAMES.FLOATING.TEXT_CONTAINER}">
87
+ <div class="${_const.CLASS_NAMES.FLOATING.TITLE_WRAPPER}">
88
+ <span class="${_const.CLASS_NAMES.FLOATING.TITLE}">${title}</span>
89
+ </div>
90
+ ${(0, _utils.renderSupportingText)(supportingText, _const.CLASS_NAMES.FLOATING.SUPPORTING_TEXT)}
91
+ ${actions && actions.length > 0 ? (0, _utils.renderActions)(actions, _const.CLASS_NAMES.FLOATING.ACTIONS) : ''}
92
+ </div>
93
+ </div>
94
+ </div>
95
+ ${this.renderCloseButton(onClose, isMobile)}
96
+ `;
97
+ }
98
+ renderCloseButton(onClose) {
99
+ let isMobile = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
100
+ if (!onClose) return '';
101
+ const size = _const.getSizes.closeButton(isMobile);
102
+ return (0, _ButtonCloseX.ButtonCloseX)(size, 'light', _const.CLASS_NAMES.FLOATING.CLOSE_BUTTON, '알림 닫기', onClose);
103
+ }
104
+ setupMobileListener() {
105
+ const mediaQuery = window.matchMedia(_breakpoint.MEDIA_QUERY.mobile);
106
+ const handleChange = e => {
107
+ this.updateMobileStyles(e.matches);
108
+ if (e.matches && this.options.onClose) {
109
+ this.options.onClose();
110
+ this.remove();
111
+ }
112
+ };
113
+ handleChange({
114
+ matches: mediaQuery.matches
115
+ });
116
+ mediaQuery.addEventListener('change', handleChange);
117
+ this.mobileCleanup = () => {
118
+ mediaQuery.removeEventListener('change', handleChange);
119
+ };
120
+ }
121
+ updateMobileStyles(mobile) {
122
+ if (this.featuredIcon) {
123
+ const newSize = _const.getSizes.featuredIcon(mobile);
124
+ this.featuredIcon.updateSize(newSize);
125
+ }
126
+ const closeButton = this.element.querySelector('.ncua-button-close-x');
127
+ if (closeButton) {
128
+ const newSize = _const.getSizes.closeButton(mobile);
129
+ const newSvgSize = _const.getSizes.closeButtonSvg(newSize);
130
+ closeButton.className = closeButton.className.replace(/ncua-button-close-x--(xs|sm)/, `ncua-button-close-x--${newSize}`);
131
+ const svg = closeButton.querySelector('svg');
132
+ if (svg) {
133
+ svg.setAttribute('width', newSvgSize.toString());
134
+ svg.setAttribute('height', newSvgSize.toString());
135
+ }
136
+ }
137
+ }
138
+ bindEvents() {
139
+ (0, _utils.bindNotificationEvents)(this.element, this.options.actions, this.options.onClose, () => this.remove());
140
+ }
141
+ setupAutoClose() {
142
+ this.autoCloseTimer = (0, _utils.setupAutoClose)(this.options.autoClose, this.options.onClose, () => this.remove());
143
+ }
144
+ // Public methods
145
+ getElement() {
146
+ return this.element;
147
+ }
148
+ appendTo(parent) {
149
+ parent.appendChild(this.element);
150
+ }
151
+ remove() {
152
+ if (this.autoCloseTimer) {
153
+ clearTimeout(this.autoCloseTimer);
154
+ this.autoCloseTimer = undefined;
155
+ }
156
+ if (this.element?.parentNode) {
157
+ this.element.parentNode.removeChild(this.element);
158
+ }
159
+ }
160
+ destroy() {
161
+ // FeaturedIcon 정리
162
+ if (this.featuredIcon) {
163
+ this.featuredIcon.destroy();
164
+ this.featuredIcon = undefined;
165
+ }
166
+ // 모바일 리스너 정리
167
+ if (this.mobileCleanup) {
168
+ this.mobileCleanup();
169
+ this.mobileCleanup = undefined;
170
+ }
171
+ this.remove();
172
+ }
173
+ // Static factory methods
174
+ static create(options) {
175
+ return new FloatingNotification(options);
176
+ }
177
+ }
178
+ exports.FloatingNotification = FloatingNotification;
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.FullWidthNotification = void 0;
7
+ var _sanitize = require("../utils/sanitize");
8
+ var _const = require("./const");
9
+ var _utils = require("./utils");
10
+ class FullWidthNotification {
11
+ constructor(options) {
12
+ this.options = {
13
+ color: 'neutral',
14
+ className: '',
15
+ actions: [],
16
+ autoClose: 0,
17
+ supportingText: undefined,
18
+ ...options
19
+ };
20
+ this.element = this.createElement();
21
+ this.bindEvents();
22
+ this.setupAutoClose();
23
+ }
24
+ createElement() {
25
+ const {
26
+ title,
27
+ supportingText,
28
+ color,
29
+ className,
30
+ actions,
31
+ onClose,
32
+ supportTextLink,
33
+ onHidePermanently
34
+ } = this.options;
35
+ const wrapper = (0, _utils.createWrapperElement)(_const.CLASS_NAMES.FULL_WIDTH.BASE, color, className);
36
+ const iconHtml = _const.FULL_WIDTH_ICON_MAP[color](_const.FULL_WIDTH_SIZES.ICON);
37
+ wrapper.innerHTML = (0, _sanitize.sanitizeHtml)(this.buildTemplate({
38
+ iconHtml,
39
+ title,
40
+ supportingText,
41
+ actions,
42
+ onClose,
43
+ supportTextLink,
44
+ onHidePermanently
45
+ }));
46
+ return wrapper;
47
+ }
48
+ buildTemplate(params) {
49
+ const {
50
+ iconHtml,
51
+ title,
52
+ supportingText,
53
+ actions,
54
+ onClose,
55
+ supportTextLink,
56
+ onHidePermanently
57
+ } = params;
58
+ return `
59
+ <div class="${_const.CLASS_NAMES.FULL_WIDTH.CONTAINER}">
60
+ <div class="${_const.CLASS_NAMES.FULL_WIDTH.CONTENT}">
61
+ <div class="${_const.CLASS_NAMES.FULL_WIDTH.CONTENT_WRAPPER}">
62
+ <div class="${_const.CLASS_NAMES.FULL_WIDTH.ICON}">${iconHtml}</div>
63
+ <div class="${_const.CLASS_NAMES.FULL_WIDTH.TEXT_CONTAINER}">
64
+ <span class="${_const.CLASS_NAMES.FULL_WIDTH.TITLE}">${title}</span>
65
+ ${(0, _utils.renderSupportingText)(supportingText, _const.CLASS_NAMES.FULL_WIDTH.SUPPORTING_TEXT, supportTextLink)}
66
+ </div>
67
+ </div>
68
+ <div class="${_const.CLASS_NAMES.FULL_WIDTH.ACTIONS_CONTAINER}">
69
+ ${actions && actions.length > 0 ? (0, _utils.renderActions)(actions, _const.CLASS_NAMES.FULL_WIDTH.ACTIONS) : ''}
70
+ ${this.renderHidePermanentlyButton(onHidePermanently)}
71
+ ${this.renderCloseButton(onClose)}
72
+ </div>
73
+ </div>
74
+ </div>
75
+ `;
76
+ }
77
+ renderHidePermanentlyButton(onHidePermanently) {
78
+ if (!onHidePermanently) return '';
79
+ return `
80
+ <button type="button" class="ncua-notification__action-button ncua-notification__action-button--text ncua-full-width-notification__link" data-hide-permanently="true">
81
+ 다시보지 않기
82
+ </button>
83
+ `;
84
+ }
85
+ renderCloseButton(onClose) {
86
+ if (!onClose) return '';
87
+ return `
88
+ <button type="button" class="${_const.CLASS_NAMES.FULL_WIDTH.CLOSE_BUTTON}" aria-label="알림 닫기">
89
+ ${_const.SVG_ICONS['x-close'](_const.FULL_WIDTH_SIZES.CLOSE_BUTTON)}
90
+ </button>
91
+ `;
92
+ }
93
+ bindEvents() {
94
+ (0, _utils.bindNotificationEvents)(this.element, this.options.actions, this.options.onClose, () => this.remove());
95
+ // 다시보지 않기 버튼 이벤트 바인딩
96
+ if (this.options.onHidePermanently) {
97
+ const hidePermanentlyButton = this.element.querySelector('[data-hide-permanently="true"]');
98
+ if (hidePermanentlyButton) {
99
+ hidePermanentlyButton.addEventListener('click', () => {
100
+ this.options.onHidePermanently?.();
101
+ this.remove();
102
+ });
103
+ }
104
+ }
105
+ }
106
+ setupAutoClose() {
107
+ this.autoCloseTimer = (0, _utils.setupAutoClose)(this.options.autoClose, this.options.onClose, () => this.remove());
108
+ }
109
+ // Public methods
110
+ getElement() {
111
+ return this.element;
112
+ }
113
+ appendTo(parent) {
114
+ parent.appendChild(this.element);
115
+ }
116
+ remove() {
117
+ if (this.autoCloseTimer) {
118
+ clearTimeout(this.autoCloseTimer);
119
+ this.autoCloseTimer = undefined;
120
+ }
121
+ if (this.element?.parentNode) {
122
+ this.element.parentNode.removeChild(this.element);
123
+ }
124
+ }
125
+ destroy() {
126
+ this.remove();
127
+ }
128
+ // Static factory methods
129
+ static create(options) {
130
+ return new FullWidthNotification(options);
131
+ }
132
+ }
133
+ exports.FullWidthNotification = FullWidthNotification;
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.MessageNotification = void 0;
7
+ var _featuredIcon = require("../featuredIcon");
8
+ var _sanitize = require("../utils/sanitize");
9
+ var _const = require("./const");
10
+ var _utils = require("./utils");
11
+ class MessageNotification {
12
+ constructor(options) {
13
+ this.options = {
14
+ color: 'neutral',
15
+ className: '',
16
+ actions: [],
17
+ autoClose: 0,
18
+ supportingText: undefined,
19
+ ...options
20
+ };
21
+ this.element = this.createElement();
22
+ this.bindEvents();
23
+ this.setupAutoClose();
24
+ }
25
+ createElement() {
26
+ const {
27
+ title,
28
+ supportingText,
29
+ color,
30
+ className,
31
+ actions,
32
+ onClose,
33
+ onHidePermanently
34
+ } = this.options;
35
+ // message 타입은 neutral, error, warning, success 4가지 색상만 지원
36
+ let actualColor = color;
37
+ if (color === 'info') {
38
+ actualColor = 'neutral';
39
+ }
40
+ const wrapper = (0, _utils.createWrapperElement)(_const.CLASS_NAMES.MESSAGE.BASE, actualColor, className);
41
+ const iconFunction = _const.FLOATING_ICON_MAP[actualColor];
42
+ // FeaturedIcon 생성
43
+ let featuredIconElement = null;
44
+ if (iconFunction) {
45
+ const iconSvg = iconFunction(_const.MESSAGE_SIZES.ICON_PIXEL);
46
+ this.featuredIcon = _featuredIcon.FeaturedIcon.create({
47
+ svgString: iconSvg,
48
+ theme: 'light-circle',
49
+ color: actualColor,
50
+ size: _const.MESSAGE_SIZES.FEATURED_ICON
51
+ });
52
+ featuredIconElement = this.featuredIcon.getElement();
53
+ }
54
+ wrapper.innerHTML = (0, _sanitize.sanitizeHtml)(this.buildTemplate({
55
+ title,
56
+ supportingText,
57
+ actions,
58
+ onClose,
59
+ onHidePermanently
60
+ }));
61
+ // FeaturedIcon을 content-wrapper에 추가
62
+ if (featuredIconElement) {
63
+ const contentWrapper = wrapper.querySelector(`.${_const.CLASS_NAMES.MESSAGE.CONTENT_WRAPPER}`);
64
+ if (contentWrapper) {
65
+ contentWrapper.insertBefore(featuredIconElement, contentWrapper.firstChild);
66
+ }
67
+ }
68
+ return wrapper;
69
+ }
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
+ bindEvents() {
115
+ (0, _utils.bindNotificationEvents)(this.element, this.options.actions, this.options.onClose, () => this.remove());
116
+ // 다시보지 않기 버튼 이벤트 바인딩
117
+ if (this.options.onHidePermanently) {
118
+ const hidePermanentlyButton = this.element.querySelector('[data-hide-permanently="true"]');
119
+ if (hidePermanentlyButton) {
120
+ hidePermanentlyButton.addEventListener('click', () => {
121
+ this.options.onHidePermanently?.();
122
+ this.remove();
123
+ });
124
+ }
125
+ }
126
+ }
127
+ setupAutoClose() {
128
+ this.autoCloseTimer = (0, _utils.setupAutoClose)(this.options.autoClose, this.options.onClose, () => this.remove());
129
+ }
130
+ // Public methods
131
+ getElement() {
132
+ return this.element;
133
+ }
134
+ appendTo(parent) {
135
+ parent.appendChild(this.element);
136
+ }
137
+ remove() {
138
+ if (this.autoCloseTimer) {
139
+ clearTimeout(this.autoCloseTimer);
140
+ this.autoCloseTimer = undefined;
141
+ }
142
+ if (this.element?.parentNode) {
143
+ this.element.parentNode.removeChild(this.element);
144
+ }
145
+ }
146
+ destroy() {
147
+ // FeaturedIcon 정리
148
+ if (this.featuredIcon) {
149
+ this.featuredIcon.destroy();
150
+ this.featuredIcon = undefined;
151
+ }
152
+ this.remove();
153
+ }
154
+ // Static factory methods
155
+ static create(options) {
156
+ return new MessageNotification(options);
157
+ }
158
+ }
159
+ exports.MessageNotification = MessageNotification;
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.NcuaNotification = void 0;
7
+ var _FloatingNotification = require("./FloatingNotification");
8
+ var _FullWidthNotification = require("./FullWidthNotification");
9
+ var _MessageNotification = require("./MessageNotification");
10
+ var _positionSync = require("./positionSync");
11
+ // 통합 Notification 클래스 (글로벌 Web Notifications API와의 식별자 충돌을 피하기 위해 NcuaNotification 으로 명명)
12
+ class NcuaNotification {
13
+ constructor(options) {
14
+ const {
15
+ type = 'floating',
16
+ ...baseOptions
17
+ } = options;
18
+ this.resolvedType = type;
19
+ if (type === 'message') {
20
+ this.instance = new _MessageNotification.MessageNotification(baseOptions);
21
+ } else if (type === 'full-width') {
22
+ this.instance = new _FullWidthNotification.FullWidthNotification(baseOptions);
23
+ } else {
24
+ this.instance = new _FloatingNotification.FloatingNotification(baseOptions);
25
+ }
26
+ }
27
+ // 모든 메서드를 instance에 위임
28
+ getElement() {
29
+ return this.instance.getElement();
30
+ }
31
+ appendTo(parent) {
32
+ return this.instance.appendTo(parent);
33
+ }
34
+ remove() {
35
+ return this.instance.remove();
36
+ }
37
+ destroy() {
38
+ return this.instance.destroy();
39
+ }
40
+ show(parent) {
41
+ // 사용자가 부모를 명시한 경우 기존 동작 유지 (legacy 호환).
42
+ if (parent) {
43
+ this.instance.appendTo(parent);
44
+ return;
45
+ }
46
+ // §5.1 — floating 은 자동으로 우측 상단 호스트에 append.
47
+ // 시각적으로는 최신 토스트가 상단에 노출되고, 이전 토스트들은 그 아래로 12px 씩 겹쳐 쌓인다
48
+ // (LIFO, §5.4 "최신 상단" 준수. godomall5 등 기존 admin wrapper 와 동일 정책.
49
+ // 겹침 너비는 --ncua-floating-notification-stack-overlap CSS 변수로 오버라이드 가능).
50
+ //
51
+ // SSR 가드는 mountFloatingNotificationHost 내부의 isBrowserEnv() 로 위임 — null 이면
52
+ // 토스트가 표시될 환경이 아니라는 의미이므로 silently return 한다 (document.body 에 append
53
+ // 시도하는 fallthrough 는 SSR 에서 ReferenceError 를 일으키므로 금지).
54
+ if (this.resolvedType === 'floating') {
55
+ const host = (0, _positionSync.mountFloatingNotificationHost)();
56
+ if (host) {
57
+ this.instance.appendTo(host);
58
+ }
59
+ return;
60
+ }
61
+ // full-width / message는 기존대로 body에 append.
62
+ this.instance.appendTo(document.body);
63
+ }
64
+ // Static factory methods
65
+ static create(options) {
66
+ return new NcuaNotification(options);
67
+ }
68
+ // Convenience method for creating notifications with specific color
69
+ static createWithColor(color, title, supportingText, options) {
70
+ const autoCloseMap = {
71
+ success: 3000,
72
+ error: 5000,
73
+ warning: 3000,
74
+ info: 3000,
75
+ neutral: 0
76
+ };
77
+ return new NcuaNotification({
78
+ title,
79
+ supportingText,
80
+ color,
81
+ type: 'floating',
82
+ autoClose: autoCloseMap[color],
83
+ ...options
84
+ });
85
+ }
86
+ // 클래스를 생성하지 않고도 기본 floating 알림 생성을 하기 위한 함수들
87
+ static success(title, supportingText, options) {
88
+ const notification = NcuaNotification.createWithColor('success', title, supportingText, options);
89
+ notification.show();
90
+ return notification;
91
+ }
92
+ static error(title, supportingText, options) {
93
+ const notification = NcuaNotification.createWithColor('error', title, supportingText, options);
94
+ notification.show();
95
+ return notification;
96
+ }
97
+ static warning(title, supportingText, options) {
98
+ const notification = NcuaNotification.createWithColor('warning', title, supportingText, options);
99
+ notification.show();
100
+ return notification;
101
+ }
102
+ static info(title, supportingText, options) {
103
+ const notification = NcuaNotification.createWithColor('info', title, supportingText, options);
104
+ notification.show();
105
+ return notification;
106
+ }
107
+ static neutral(title, supportingText, options) {
108
+ const notification = NcuaNotification.createWithColor('neutral', title, supportingText, options);
109
+ notification.show();
110
+ return notification;
111
+ }
112
+ // showFullWidth method for backward compatibility
113
+ static showFullWidth(options) {
114
+ return new NcuaNotification({
115
+ ...options,
116
+ type: 'full-width'
117
+ });
118
+ }
119
+ }
120
+ exports.NcuaNotification = NcuaNotification;