@ncds/ui-admin 1.8.3 → 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 (217) 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/index.js +33 -0
  23. package/dist/cjs/src/components/layout/block-container/BlockContainer.js +38 -0
  24. package/dist/cjs/src/components/layout/block-container/index.js +16 -0
  25. package/dist/cjs/src/components/layout/block-header/BlockHeader.js +107 -0
  26. package/dist/cjs/src/components/layout/block-header/SubTitle.js +56 -0
  27. package/dist/cjs/src/components/layout/block-header/index.js +27 -0
  28. package/dist/cjs/src/components/layout/page-title/PageTitle.js +95 -0
  29. package/dist/cjs/src/components/layout/page-title/index.js +16 -0
  30. package/dist/cjs/src/components/overlays/dropdown/Dropdown.js +47 -19
  31. package/dist/cjs/src/components/overlays/notification/CalloutNotification.js +25 -0
  32. package/dist/cjs/src/components/overlays/notification/FloatingNotification.js +86 -13
  33. package/dist/cjs/src/components/overlays/notification/Notification.js +7 -0
  34. package/dist/cjs/src/components/overlays/notification/host.js +12 -0
  35. package/dist/cjs/src/components/overlays/tooltip/Tooltip.js +57 -44
  36. package/dist/cjs/src/components/select-dropdown/SelectDropdown.js +2 -1
  37. package/dist/cjs/src/contexts/FloatingContext.js +11 -0
  38. package/dist/cjs/src/contexts/index.js +16 -0
  39. package/dist/cjs/src/hooks/index.js +11 -0
  40. package/dist/cjs/src/hooks/useFloatingPosition.js +78 -0
  41. package/dist/cjs/src/hooks/usePortalState.js +17 -0
  42. package/dist/cjs/src/utils/dropdown/maxSelection.js +35 -0
  43. package/dist/cjs/src/utils/dropdown/multiSelect.js +72 -15
  44. package/dist/esm/assets/scripts/featuredIcon.js +80 -0
  45. package/dist/esm/assets/scripts/notification/FloatingNotification.js +171 -0
  46. package/dist/esm/assets/scripts/notification/FullWidthNotification.js +126 -0
  47. package/dist/esm/assets/scripts/notification/MessageNotification.js +152 -0
  48. package/dist/esm/assets/scripts/notification/Notification.js +113 -0
  49. package/dist/esm/assets/scripts/notification/const/classNames.js +44 -0
  50. package/dist/esm/assets/scripts/notification/const/icons.js +25 -0
  51. package/dist/esm/assets/scripts/notification/const/index.js +4 -0
  52. package/dist/esm/assets/scripts/notification/const/sizes.js +40 -0
  53. package/dist/esm/assets/scripts/notification/const/types.js +8 -0
  54. package/dist/esm/assets/scripts/notification/index.js +10 -0
  55. package/dist/esm/assets/scripts/notification/positionSync.js +171 -0
  56. package/dist/esm/assets/scripts/notification/utils.js +109 -0
  57. package/dist/esm/assets/scripts/shared/ButtonCloseX.js +37 -0
  58. package/dist/esm/assets/scripts/utils/sanitize.js +31 -0
  59. package/dist/esm/src/components/data-display/data-grid/DataGrid.js +5 -1
  60. package/dist/esm/src/components/data-display/table/Table.js +118 -96
  61. package/dist/esm/src/components/data-display/table/useTableScrollbars.js +179 -0
  62. package/dist/esm/src/components/forms-and-input/combo-box/ComboBox.js +11 -10
  63. package/dist/esm/src/components/forms-and-input/image-file-input/ImageFileInput.js +5 -2
  64. package/dist/esm/src/components/forms-and-input/select-box/SelectBox.js +67 -29
  65. package/dist/esm/src/components/index.js +3 -0
  66. package/dist/esm/src/components/layout/block-container/BlockContainer.js +31 -0
  67. package/dist/esm/src/components/layout/block-container/index.js +1 -0
  68. package/dist/esm/src/components/layout/block-header/BlockHeader.js +100 -0
  69. package/dist/esm/src/components/layout/block-header/SubTitle.js +49 -0
  70. package/dist/esm/src/components/layout/block-header/index.js +2 -0
  71. package/dist/esm/src/components/layout/page-title/PageTitle.js +88 -0
  72. package/dist/esm/src/components/layout/page-title/index.js +1 -0
  73. package/dist/esm/src/components/overlays/dropdown/Dropdown.js +47 -19
  74. package/dist/esm/src/components/overlays/notification/CalloutNotification.js +19 -0
  75. package/dist/esm/src/components/overlays/notification/FloatingNotification.js +86 -14
  76. package/dist/esm/src/components/overlays/notification/Notification.js +7 -0
  77. package/dist/esm/src/components/overlays/notification/host.js +9 -0
  78. package/dist/esm/src/components/overlays/tooltip/Tooltip.js +58 -45
  79. package/dist/esm/src/components/select-dropdown/SelectDropdown.js +2 -1
  80. package/dist/esm/src/contexts/FloatingContext.js +4 -0
  81. package/dist/esm/src/contexts/index.js +1 -0
  82. package/dist/esm/src/hooks/index.js +1 -0
  83. package/dist/esm/src/hooks/useFloatingPosition.js +71 -0
  84. package/dist/esm/src/hooks/usePortalState.js +10 -0
  85. package/dist/esm/src/utils/dropdown/maxSelection.js +27 -0
  86. package/dist/esm/src/utils/dropdown/multiSelect.js +70 -14
  87. package/dist/temp/assets/scripts/featuredIcon.d.ts +22 -0
  88. package/dist/temp/assets/scripts/featuredIcon.js +79 -0
  89. package/dist/temp/assets/scripts/notification/FloatingNotification.d.ts +24 -0
  90. package/dist/temp/assets/scripts/notification/FloatingNotification.js +156 -0
  91. package/dist/temp/assets/scripts/notification/FullWidthNotification.d.ts +21 -0
  92. package/dist/temp/assets/scripts/notification/FullWidthNotification.js +111 -0
  93. package/dist/temp/assets/scripts/notification/MessageNotification.d.ts +22 -0
  94. package/dist/temp/assets/scripts/notification/MessageNotification.js +140 -0
  95. package/dist/temp/assets/scripts/notification/Notification.d.ts +22 -0
  96. package/dist/temp/assets/scripts/notification/Notification.js +112 -0
  97. package/dist/temp/assets/scripts/notification/const/classNames.d.ts +43 -0
  98. package/dist/temp/assets/scripts/notification/const/classNames.js +44 -0
  99. package/dist/temp/assets/scripts/notification/const/icons.d.ts +25 -0
  100. package/dist/temp/assets/scripts/notification/const/icons.js +25 -0
  101. package/dist/temp/assets/scripts/notification/const/index.d.ts +5 -0
  102. package/dist/temp/assets/scripts/notification/const/index.js +4 -0
  103. package/dist/temp/assets/scripts/notification/const/sizes.d.ts +32 -0
  104. package/dist/temp/assets/scripts/notification/const/sizes.js +40 -0
  105. package/dist/temp/assets/scripts/notification/const/types.d.ts +19 -0
  106. package/dist/temp/assets/scripts/notification/const/types.js +8 -0
  107. package/dist/temp/assets/scripts/notification/index.d.ts +8 -0
  108. package/dist/temp/assets/scripts/notification/index.js +10 -0
  109. package/dist/temp/assets/scripts/notification/positionSync.d.ts +50 -0
  110. package/dist/temp/assets/scripts/notification/positionSync.js +170 -0
  111. package/dist/temp/assets/scripts/notification/utils.d.ts +8 -0
  112. package/dist/temp/assets/scripts/notification/utils.js +115 -0
  113. package/dist/temp/assets/scripts/shared/ButtonCloseX.d.ts +5 -0
  114. package/dist/temp/assets/scripts/shared/ButtonCloseX.js +33 -0
  115. package/dist/temp/assets/scripts/utils/sanitize.d.ts +22 -0
  116. package/dist/temp/assets/scripts/utils/sanitize.js +31 -0
  117. package/dist/temp/src/components/data-display/data-grid/DataGrid.js +1 -1
  118. package/dist/temp/src/components/data-display/data-grid/DataGrid.types.d.ts +7 -0
  119. package/dist/temp/src/components/data-display/table/Table.d.ts +4 -1
  120. package/dist/temp/src/components/data-display/table/Table.js +53 -68
  121. package/dist/temp/src/components/data-display/table/types.d.ts +18 -0
  122. package/dist/temp/src/components/data-display/table/useTableScrollbars.d.ts +25 -0
  123. package/dist/temp/src/components/data-display/table/useTableScrollbars.js +136 -0
  124. package/dist/temp/src/components/forms-and-input/combo-box/ComboBox.d.ts +8 -0
  125. package/dist/temp/src/components/forms-and-input/combo-box/ComboBox.js +7 -11
  126. package/dist/temp/src/components/forms-and-input/image-file-input/ImageFileInput.js +1 -1
  127. package/dist/temp/src/components/forms-and-input/select-box/SelectBox.d.ts +13 -0
  128. package/dist/temp/src/components/forms-and-input/select-box/SelectBox.js +30 -3
  129. package/dist/temp/src/components/index.d.ts +3 -0
  130. package/dist/temp/src/components/index.js +3 -0
  131. package/dist/temp/src/components/layout/block-container/BlockContainer.d.ts +19 -0
  132. package/dist/temp/src/components/layout/block-container/BlockContainer.js +11 -0
  133. package/dist/temp/src/components/layout/block-container/index.d.ts +1 -0
  134. package/dist/temp/src/components/layout/block-container/index.js +1 -0
  135. package/dist/temp/src/components/layout/block-header/BlockHeader.d.ts +23 -0
  136. package/dist/temp/src/components/layout/block-header/BlockHeader.js +21 -0
  137. package/dist/temp/src/components/layout/block-header/SubTitle.d.ts +19 -0
  138. package/dist/temp/src/components/layout/block-header/SubTitle.js +8 -0
  139. package/dist/temp/src/components/layout/block-header/index.d.ts +2 -0
  140. package/dist/temp/src/components/layout/block-header/index.js +2 -0
  141. package/dist/temp/src/components/layout/page-title/PageTitle.d.ts +22 -0
  142. package/dist/temp/src/components/layout/page-title/PageTitle.js +19 -0
  143. package/dist/temp/src/components/layout/page-title/index.d.ts +1 -0
  144. package/dist/temp/src/components/layout/page-title/index.js +1 -0
  145. package/dist/temp/src/components/overlays/dropdown/Dropdown.d.ts +5 -0
  146. package/dist/temp/src/components/overlays/dropdown/Dropdown.js +35 -11
  147. package/dist/temp/src/components/overlays/notification/CalloutNotification.d.ts +9 -0
  148. package/dist/temp/src/components/overlays/notification/CalloutNotification.js +6 -0
  149. package/dist/temp/src/components/overlays/notification/FloatingNotification.d.ts +15 -0
  150. package/dist/temp/src/components/overlays/notification/FloatingNotification.js +81 -13
  151. package/dist/temp/src/components/overlays/notification/Notification.d.ts +18 -3
  152. package/dist/temp/src/components/overlays/notification/Notification.js +4 -0
  153. package/dist/temp/src/components/overlays/notification/host.d.ts +9 -0
  154. package/dist/temp/src/components/overlays/notification/host.js +9 -0
  155. package/dist/temp/src/components/overlays/tooltip/Tooltip.d.ts +5 -1
  156. package/dist/temp/src/components/overlays/tooltip/Tooltip.js +25 -22
  157. package/dist/temp/src/components/select-dropdown/SelectDropdown.d.ts +6 -0
  158. package/dist/temp/src/components/select-dropdown/SelectDropdown.js +2 -2
  159. package/dist/temp/src/contexts/FloatingContext.d.ts +6 -0
  160. package/dist/temp/src/contexts/FloatingContext.js +4 -0
  161. package/dist/temp/src/contexts/index.d.ts +1 -0
  162. package/dist/temp/src/contexts/index.js +1 -0
  163. package/dist/temp/src/hooks/index.d.ts +1 -0
  164. package/dist/temp/src/hooks/index.js +1 -0
  165. package/dist/temp/src/hooks/useFloatingPosition.d.ts +19 -0
  166. package/dist/temp/src/hooks/useFloatingPosition.js +55 -0
  167. package/dist/temp/src/hooks/usePortalState.d.ts +6 -0
  168. package/dist/temp/src/hooks/usePortalState.js +7 -0
  169. package/dist/temp/src/utils/dropdown/maxSelection.d.ts +24 -0
  170. package/dist/temp/src/utils/dropdown/maxSelection.js +28 -0
  171. package/dist/temp/src/utils/dropdown/multiSelect.d.ts +42 -2
  172. package/dist/temp/src/utils/dropdown/multiSelect.js +66 -13
  173. package/dist/types/assets/scripts/featuredIcon.d.ts +22 -0
  174. package/dist/types/assets/scripts/notification/FloatingNotification.d.ts +24 -0
  175. package/dist/types/assets/scripts/notification/FullWidthNotification.d.ts +21 -0
  176. package/dist/types/assets/scripts/notification/MessageNotification.d.ts +22 -0
  177. package/dist/types/assets/scripts/notification/Notification.d.ts +22 -0
  178. package/dist/types/assets/scripts/notification/const/classNames.d.ts +43 -0
  179. package/dist/types/assets/scripts/notification/const/icons.d.ts +25 -0
  180. package/dist/types/assets/scripts/notification/const/index.d.ts +5 -0
  181. package/dist/types/assets/scripts/notification/const/sizes.d.ts +32 -0
  182. package/dist/types/assets/scripts/notification/const/types.d.ts +19 -0
  183. package/dist/types/assets/scripts/notification/index.d.ts +8 -0
  184. package/dist/types/assets/scripts/notification/positionSync.d.ts +50 -0
  185. package/dist/types/assets/scripts/notification/utils.d.ts +8 -0
  186. package/dist/types/assets/scripts/shared/ButtonCloseX.d.ts +5 -0
  187. package/dist/types/assets/scripts/utils/sanitize.d.ts +22 -0
  188. package/dist/types/src/components/data-display/data-grid/DataGrid.types.d.ts +7 -0
  189. package/dist/types/src/components/data-display/table/Table.d.ts +4 -1
  190. package/dist/types/src/components/data-display/table/types.d.ts +18 -0
  191. package/dist/types/src/components/data-display/table/useTableScrollbars.d.ts +25 -0
  192. package/dist/types/src/components/forms-and-input/combo-box/ComboBox.d.ts +8 -0
  193. package/dist/types/src/components/forms-and-input/select-box/SelectBox.d.ts +13 -0
  194. package/dist/types/src/components/index.d.ts +3 -0
  195. package/dist/types/src/components/layout/block-container/BlockContainer.d.ts +19 -0
  196. package/dist/types/src/components/layout/block-container/index.d.ts +1 -0
  197. package/dist/types/src/components/layout/block-header/BlockHeader.d.ts +23 -0
  198. package/dist/types/src/components/layout/block-header/SubTitle.d.ts +19 -0
  199. package/dist/types/src/components/layout/block-header/index.d.ts +2 -0
  200. package/dist/types/src/components/layout/page-title/PageTitle.d.ts +22 -0
  201. package/dist/types/src/components/layout/page-title/index.d.ts +1 -0
  202. package/dist/types/src/components/overlays/dropdown/Dropdown.d.ts +5 -0
  203. package/dist/types/src/components/overlays/notification/CalloutNotification.d.ts +9 -0
  204. package/dist/types/src/components/overlays/notification/FloatingNotification.d.ts +15 -0
  205. package/dist/types/src/components/overlays/notification/Notification.d.ts +18 -3
  206. package/dist/types/src/components/overlays/notification/host.d.ts +9 -0
  207. package/dist/types/src/components/overlays/tooltip/Tooltip.d.ts +5 -1
  208. package/dist/types/src/components/select-dropdown/SelectDropdown.d.ts +6 -0
  209. package/dist/types/src/contexts/FloatingContext.d.ts +6 -0
  210. package/dist/types/src/contexts/index.d.ts +1 -0
  211. package/dist/types/src/hooks/index.d.ts +1 -0
  212. package/dist/types/src/hooks/useFloatingPosition.d.ts +19 -0
  213. package/dist/types/src/hooks/usePortalState.d.ts +6 -0
  214. package/dist/types/src/utils/dropdown/maxSelection.d.ts +24 -0
  215. package/dist/types/src/utils/dropdown/multiSelect.d.ts +42 -2
  216. package/dist/ui-admin/assets/styles/style.css +596 -64
  217. package/package.json +1 -1
@@ -1,19 +1,64 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { AlertCircle, AlertTriangle, CheckCircle, Pin02 } from '@ncds/ui-admin-icon';
3
3
  import classNames from 'classnames';
4
- import { forwardRef, useEffect, useRef, useState } from 'react';
4
+ import { forwardRef, useEffect, useId, useRef, useState } from 'react';
5
+ import { createPortal } from 'react-dom';
5
6
  import { MEDIA_QUERY } from '../../../constant/breakpoint';
6
7
  import { useMediaQuery } from '../../../hooks/useMediaQuery';
7
8
  import { Button } from '../../action/button';
8
9
  import { ButtonCloseX } from '../../action/button/ButtonCloseX';
9
10
  import { FeaturedIcon } from '../../image-and-icons/featured-icon/FeaturedIcon';
11
+ // 호스트 싱글톤은 vanilla/React 양쪽이 동일한 함수를 공유한다 — host.ts 가 가까운 진입점 역할을
12
+ // 하므로 React 컴포넌트는 deep relative path 로 vanilla internals 를 직접 import 하지 않는다.
13
+ import { mountFloatingNotificationHost } from './host';
14
+ /**
15
+ * 색상별 a11y role.
16
+ * - error/warning → role="alert" (implicit aria-live="assertive": 즉시 발화)
17
+ * - 그 외 → role="status" (implicit aria-live="polite": 현재 발화 끝난 후 발화)
18
+ * role 이 implicit live-region 을 가져오므로 호스트 컨테이너에는 aria-live 를 두지 않는다.
19
+ */
20
+ const ASSERTIVE_COLORS = {
21
+ error: true,
22
+ warning: true
23
+ };
10
24
  const iconMap = {
11
25
  neutral: Pin02,
12
26
  error: AlertTriangle,
13
27
  warning: AlertCircle,
14
28
  success: CheckCircle
15
- // info는 floating에서는 지원하지 않음
29
+ // info full-width 전용이라 floating 아이콘 매핑 없음.
30
+ };
31
+ /**
32
+ * NotificationColor → FeaturedIconColor 매핑.
33
+ * `info` 는 FeaturedIconColor 에 존재하지 않으므로 `neutral` 로 안전 fallback.
34
+ * `satisfies` 가 매핑 누락을 컴파일 타임에 강제하므로 향후 색상이 추가되면 즉시 타입 에러로 잡힌다.
35
+ */
36
+ const iconColorMap = {
37
+ neutral: 'neutral',
38
+ error: 'error',
39
+ warning: 'warning',
40
+ success: 'success',
41
+ info: 'neutral'
16
42
  };
43
+ /**
44
+ * `.ncua-floating-notification-host` 싱글톤을 보장하고 반환하는 훅.
45
+ *
46
+ * 이름의 `useMount...` 는 단순 조회가 아닌 **DOM 부수효과** 를 동반함을 신호한다 —
47
+ * 내부적으로 `mountFloatingNotificationHost()` 를 호출해 document.body 에 호스트를 append 하고
48
+ * (없으면) 글로벌 scroll/resize/MutationObserver 까지 부착한다. 호스트는 페이지 lifetime
49
+ * 싱글톤이므로 언마운트 시 제거하지 않는다.
50
+ *
51
+ * `mountFloatingNotificationHost` 는 **동기 함수** 이므로 effect 안의 호출 → setHost 가 같은 tick
52
+ * 에 끝나 cancellation race 가 없다. cancel flag 는 의미 없어 두지 않는다.
53
+ */
54
+ function useMountFloatingNotificationHost(enabled) {
55
+ const [host, setHost] = useState(null);
56
+ useEffect(() => {
57
+ if (!enabled) return;
58
+ setHost(mountFloatingNotificationHost());
59
+ }, [enabled]);
60
+ return host;
61
+ }
17
62
  const FloatingNotification = /*#__PURE__*/forwardRef((_ref, ref) => {
18
63
  let {
19
64
  title,
@@ -23,49 +68,65 @@ const FloatingNotification = /*#__PURE__*/forwardRef((_ref, ref) => {
23
68
  className,
24
69
  actions,
25
70
  autoClose = 0,
71
+ portal = false,
26
72
  ...rest
27
73
  } = _ref;
28
74
  const [shouldRemove, setShouldRemove] = useState(false);
29
- const iconColor = color;
30
75
  const featuredIconProps = {
31
76
  icon: iconMap[color] || Pin02,
32
77
  size: 'sm',
33
- color: iconColor,
78
+ color: iconColorMap[color],
34
79
  theme: 'dark-circle'
35
80
  };
36
81
  const isMobile = useMediaQuery(MEDIA_QUERY.mobile, {
37
82
  onMatched: onClose
38
83
  });
84
+ // onClose 는 매 렌더 새 함수 ref 일 수 있으므로 ref 로 latest 만 보관.
85
+ // → autoClose 타이머 effect 의 deps 에서 onClose 를 빼서 타이머 재시작 회피.
86
+ // render 본문에서 직접 할당 — useEffect 로 미루면 같은 commit 안에서 fire 되는 타이머가 stale onClose 를 볼 위험.
87
+ const onCloseRef = useRef(onClose);
88
+ onCloseRef.current = onClose;
39
89
  // autoClose 타이머 관리
40
90
  const timerRef = useRef(null);
91
+ // onClose 는 onCloseRef 로 latest 만 추적하므로 deps 에서 제외 (의도된 패턴).
41
92
  useEffect(() => {
42
- // autoClose가 0보다 크면 무조건 타이머 설정
93
+ // autoClose 가 0 보다 크면 타이머 설정.
43
94
  if (autoClose > 0) {
44
95
  timerRef.current = setTimeout(() => {
45
- if (onClose) {
46
- onClose();
47
- }
48
- // DOM에서 바로 제거
96
+ onCloseRef.current?.();
97
+ // DOM 에서 바로 제거
49
98
  setShouldRemove(true);
50
99
  }, autoClose);
51
100
  }
52
- // cleanup 함수: 컴포넌트 언마운트 시 타이머 정리
101
+ // cleanup: 컴포넌트 언마운트 또는 autoClose 변경 시 타이머 정리
53
102
  return () => {
54
103
  if (timerRef.current) {
55
104
  clearTimeout(timerRef.current);
56
105
  timerRef.current = null;
57
106
  }
58
107
  };
59
- }, [autoClose, onClose]);
108
+ }, [autoClose]);
109
+ // portal=true 일 때만 호스트가 필요하다.
110
+ const host = useMountFloatingNotificationHost(portal);
111
+ // a11y — 카드 root 의 role 과 제목/본문 ID. 색상에 따라 alert(error/warning) / status(나머지) 로 분기.
112
+ const reactId = useId();
113
+ const titleId = `${reactId}-title`;
114
+ const descId = `${reactId}-desc`;
115
+ const role = ASSERTIVE_COLORS[color] ? 'alert' : 'status';
60
116
  // DOM에서 완전히 제거
61
117
  if (shouldRemove) {
62
118
  return null;
63
119
  }
64
- return _jsxs("div", {
120
+ const card =
121
+ // a11y/예측가능성 — caller 가 className/id 등 일부는 덮어쓸 수 있게 {...rest} 를 먼저 펼치고,
122
+ // role/aria-labelledby/aria-describedby 같은 컴포넌트 본질 prop 은 그 뒤에 두어 우선 적용.
123
+ _jsxs("div", {
124
+ ...rest,
65
125
  ref: ref,
66
126
  className: classNames('ncua-floating-notification', `ncua-floating-notification--${color}`, className),
67
- role: "alert",
68
- ...rest,
127
+ role: role,
128
+ "aria-labelledby": titleId,
129
+ "aria-describedby": supportingText ? descId : undefined,
69
130
  children: [_jsx("div", {
70
131
  className: "ncua-floating-notification__content",
71
132
  children: _jsxs("div", {
@@ -78,10 +139,12 @@ const FloatingNotification = /*#__PURE__*/forwardRef((_ref, ref) => {
78
139
  children: [_jsx("div", {
79
140
  className: "ncua-floating-notification__title-wrapper",
80
141
  children: _jsx("span", {
142
+ id: titleId,
81
143
  className: "ncua-floating-notification__title",
82
144
  children: title
83
145
  })
84
146
  }), supportingText && _jsx("span", {
147
+ id: descId,
85
148
  className: "ncua-floating-notification__supporting-text",
86
149
  children: supportingText
87
150
  }), actions && _jsx("div", {
@@ -102,5 +165,14 @@ const FloatingNotification = /*#__PURE__*/forwardRef((_ref, ref) => {
102
165
  onClick: onClose
103
166
  })]
104
167
  });
168
+ // 기본은 인라인 렌더 — 부모 JSX 트리에 카드를 그대로 둔다.
169
+ if (!portal) {
170
+ return card;
171
+ }
172
+ // portal=true 인데 SSR이거나 첫 렌더(호스트 미생성)에서는 null. useEffect 후 host 설정되면 재렌더되어 portal 마운트.
173
+ if (!host) {
174
+ return null;
175
+ }
176
+ return /*#__PURE__*/createPortal(card, host);
105
177
  });
106
178
  export { FloatingNotification };
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef } from 'react';
3
+ import { CalloutNotification } from './CalloutNotification';
3
4
  import { FloatingNotification } from './FloatingNotification';
4
5
  import { FullWidthNotification } from './FullWidthNotification';
5
6
  import { MessageNotification } from './MessageNotification';
@@ -30,6 +31,12 @@ const Notification = /*#__PURE__*/forwardRef((_ref, ref) => {
30
31
  ref: ref
31
32
  });
32
33
  }
34
+ if (type === 'callout') {
35
+ return _jsx(CalloutNotification, {
36
+ color: color,
37
+ ...rest
38
+ });
39
+ }
33
40
  return null;
34
41
  });
35
42
  Notification.displayName = 'Notification';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Floating Notification 호스트 관리 — React 측 진입점.
3
+ *
4
+ * 실제 구현은 vanilla/React 가 공유하는 `assets/scripts/notification/positionSync.ts` 에 있고,
5
+ * 외부 노출은 그 폴더의 public barrel(`assets/scripts/notification/index.ts`)이 담당한다.
6
+ * 이 모듈은 React 컴포넌트가 vanilla 내부 파일을 직접 참조하지 않도록 barrel 을 경유하는
7
+ * 한 단계 re-export 만 제공한다 — positionSync.ts 의 위치/이름이 바뀌어도 host.ts 만 영향.
8
+ */
9
+ export { mountFloatingNotificationHost } from '../../../../assets/scripts/notification';
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { AlertCircle, AlertCircleFill, HelpCircle, HelpCircleFill } from '@ncds/ui-admin-icon';
3
3
  import classNames from 'classnames';
4
4
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
@@ -70,6 +70,42 @@ const computePanelCoords = (prefer, anchor, panel) => {
70
70
  calculatedPosition
71
71
  };
72
72
  };
73
+ const buildPanelStyle = (disablePortal, coords, visible, zIndex) => {
74
+ const opacity = visible ? 1 : 0;
75
+ if (disablePortal) return {
76
+ opacity
77
+ };
78
+ return {
79
+ top: `${coords.top}px`,
80
+ left: `${coords.left}px`,
81
+ opacity,
82
+ ...(zIndex && {
83
+ zIndex
84
+ })
85
+ };
86
+ };
87
+ const renderIcon = (iconStyle, iconType, iconSize, iconColor) => {
88
+ if (iconStyle === 'help-circle') {
89
+ return iconType === 'stroke' ? _jsx(HelpCircle, {
90
+ width: iconSize,
91
+ height: iconSize,
92
+ color: iconColor
93
+ }) : _jsx(HelpCircleFill, {
94
+ width: iconSize,
95
+ height: iconSize,
96
+ color: iconColor
97
+ });
98
+ }
99
+ return iconType === 'stroke' ? _jsx(AlertCircle, {
100
+ width: iconSize,
101
+ height: iconSize,
102
+ color: iconColor
103
+ }) : _jsx(AlertCircleFill, {
104
+ width: iconSize,
105
+ height: iconSize,
106
+ color: iconColor
107
+ });
108
+ };
73
109
  export const Tooltip = _ref => {
74
110
  let {
75
111
  tooltipType = 'white',
@@ -83,7 +119,9 @@ export const Tooltip = _ref => {
83
119
  iconColor = 'var(--gray-300)',
84
120
  iconStyle = 'help-circle',
85
121
  className,
86
- zIndex
122
+ zIndex,
123
+ forceVisible,
124
+ disablePortal = false
87
125
  } = _ref;
88
126
  const iconSize = size === 'sm' ? ICON_SIZE_SM : ICON_SIZE_DEFAULT;
89
127
  const anchorRef = useRef(null);
@@ -97,6 +135,7 @@ export const Tooltip = _ref => {
97
135
  const [calculatedPosition, setCalculatedPosition] = useState(position === 'auto' ? 'bottom' : position);
98
136
  const [isVisible, setIsVisible] = useState(false);
99
137
  const [isManuallyClose, setIsManuallyClose] = useState(false);
138
+ const effectiveVisible = forceVisible ?? isVisible;
100
139
  useEffect(() => {
101
140
  setMounted(true);
102
141
  return () => {
@@ -107,7 +146,7 @@ export const Tooltip = _ref => {
107
146
  };
108
147
  }, []);
109
148
  const updatePosition = useCallback(() => {
110
- if (!anchorRef.current || !panelRef.current) return;
149
+ if (disablePortal || !anchorRef.current || !panelRef.current) return;
111
150
  const anchor = anchorRef.current.getBoundingClientRect();
112
151
  const panel = panelRef.current.getBoundingClientRect();
113
152
  const next = computePanelCoords(position, anchor, panel);
@@ -116,9 +155,9 @@ export const Tooltip = _ref => {
116
155
  left: next.left
117
156
  });
118
157
  setCalculatedPosition(next.calculatedPosition);
119
- }, [position]);
158
+ }, [position, disablePortal]);
120
159
  useEffect(() => {
121
- if (!isVisible) return;
160
+ if (!effectiveVisible || disablePortal) return;
122
161
  updatePosition();
123
162
  window.addEventListener('resize', updatePosition, {
124
163
  passive: true
@@ -133,13 +172,10 @@ export const Tooltip = _ref => {
133
172
  capture: true
134
173
  });
135
174
  };
136
- }, [isVisible, updatePosition]);
175
+ }, [effectiveVisible, updatePosition, disablePortal]);
137
176
  const handleMouseEnter = useCallback(() => {
138
177
  if (isManuallyClose) return;
139
- // opacity 전환 전에 좌표 확정 (ref 가드는 updatePosition 내부)
140
178
  updatePosition();
141
- // 웹폰트 로드·max-content 재계산 등 비동기 layout 안정화 후 한 번 더 보정
142
- // 빠른 hover in/out 시 이전 프레임 요청은 취소해 중복/unmount 후 실행 방지
143
179
  if (rafIdRef.current !== null) cancelAnimationFrame(rafIdRef.current);
144
180
  rafIdRef.current = requestAnimationFrame(() => {
145
181
  rafIdRef.current = null;
@@ -163,18 +199,13 @@ export const Tooltip = _ref => {
163
199
  'ncua-tooltip--stroke': iconType === 'stroke',
164
200
  'ncua-tooltip--auto': position === 'auto'
165
201
  }, className), [size, type, hideArrow, iconType, position, className]);
166
- const panelClassName = useMemo(() => classNames('ncua-tooltip-panel', 'ncua-tooltip__bg', `ncua-tooltip__bg--${tooltipType}`, `ncua-tooltip__bg--${finalPosition}`, {
167
- 'ncua-tooltip__bg--visible': isVisible,
168
- 'ncua-tooltip__bg--force-hidden': isManuallyClose
169
- }), [tooltipType, finalPosition, isVisible, isManuallyClose]);
170
- const panelStyle = {
171
- top: `${coords.top}px`,
172
- left: `${coords.left}px`,
173
- opacity: isVisible ? 1 : 0,
174
- ...(zIndex && {
175
- zIndex
176
- })
177
- };
202
+ const panelClassName = useMemo(() => classNames({
203
+ 'ncua-tooltip-panel': !disablePortal
204
+ }, 'ncua-tooltip__bg', `ncua-tooltip__bg--${tooltipType}`, `ncua-tooltip__bg--${finalPosition}`, {
205
+ 'ncua-tooltip__bg--visible': effectiveVisible,
206
+ 'ncua-tooltip__bg--force-hidden': isManuallyClose && !forceVisible
207
+ }), [tooltipType, finalPosition, effectiveVisible, isManuallyClose, forceVisible, disablePortal]);
208
+ const panelStyle = buildPanelStyle(disablePortal, coords, effectiveVisible, zIndex);
178
209
  const portalTarget = mounted ? resolvePortalTarget() : null;
179
210
  const panel = _jsxs("span", {
180
211
  ref: panelRef,
@@ -194,29 +225,11 @@ export const Tooltip = _ref => {
194
225
  "aria-label": "\uD234\uD301 \uB2EB\uAE30"
195
226
  })]
196
227
  });
197
- return _jsxs(_Fragment, {
198
- children: [_jsxs("span", {
199
- ref: anchorRef,
200
- className: tooltipClassName,
201
- onMouseEnter: handleMouseEnter,
202
- onMouseLeave: handleMouseLeave,
203
- children: [iconStyle === 'help-circle' && (iconType === 'stroke' ? _jsx(HelpCircle, {
204
- width: iconSize,
205
- height: iconSize,
206
- color: iconColor
207
- }) : _jsx(HelpCircleFill, {
208
- width: iconSize,
209
- height: iconSize,
210
- color: iconColor
211
- })), iconStyle === 'alert-circle' && (iconType === 'stroke' ? _jsx(AlertCircle, {
212
- width: iconSize,
213
- height: iconSize,
214
- color: iconColor
215
- }) : _jsx(AlertCircleFill, {
216
- width: iconSize,
217
- height: iconSize,
218
- color: iconColor
219
- }))]
220
- }), portalTarget && /*#__PURE__*/createPortal(panel, portalTarget)]
228
+ return _jsxs("span", {
229
+ ref: anchorRef,
230
+ className: tooltipClassName,
231
+ onMouseEnter: handleMouseEnter,
232
+ onMouseLeave: handleMouseLeave,
233
+ children: [renderIcon(iconStyle, iconType, iconSize, iconColor), disablePortal ? panel : portalTarget && /*#__PURE__*/createPortal(panel, portalTarget)]
221
234
  });
222
235
  };
@@ -20,6 +20,7 @@ const SelectDropdown = /*#__PURE__*/forwardRef((_ref, ref) => {
20
20
  multiple = false,
21
21
  showFooterButtons = false,
22
22
  selectAllButtonText = '전체 선택',
23
+ showSelectAllAction = true,
23
24
  onSelectAll,
24
25
  onEdit,
25
26
  onComplete,
@@ -85,7 +86,7 @@ const SelectDropdown = /*#__PURE__*/forwardRef((_ref, ref) => {
85
86
  className: "ncua-select-dropdown__footer-buttons",
86
87
  children: [_jsx("div", {
87
88
  className: "ncua-select-dropdown__footer-left",
88
- children: multiple && _jsx(Button, {
89
+ children: multiple && showSelectAllAction && _jsx(Button, {
89
90
  label: selectAllButtonText,
90
91
  hierarchy: "text",
91
92
  size: "xs",
@@ -0,0 +1,4 @@
1
+ import { createContext, useContext } from 'react';
2
+ const FloatingContext = /*#__PURE__*/createContext(null);
3
+ export const FloatingProvider = FloatingContext.Provider;
4
+ export const useFloatingContext = () => useContext(FloatingContext);
@@ -0,0 +1 @@
1
+ export * from './FloatingContext';
@@ -2,5 +2,6 @@
2
2
  // 드롭다운 관련 hooks
3
3
  export * from './dropdown';
4
4
  export * from './useCallbackRef';
5
+ export * from './useFloatingPosition';
5
6
  export * from './useMediaQuery';
6
7
  export * from './useMergeRefs';
@@ -0,0 +1,71 @@
1
+ import { useLayoutEffect, useState } from 'react';
2
+ const FLOATING_Z_INDEX = 1500;
3
+ export const useFloatingPosition = _ref => {
4
+ let {
5
+ enabled,
6
+ isOpen,
7
+ triggerRef,
8
+ floatingRef,
9
+ direction,
10
+ offset = 4,
11
+ align = 'left',
12
+ matchTriggerWidth = false
13
+ } = _ref;
14
+ const [style, setStyle] = useState(null);
15
+ useLayoutEffect(() => {
16
+ if (!enabled || !isOpen) {
17
+ setStyle(null);
18
+ return;
19
+ }
20
+ const trigger = triggerRef.current;
21
+ if (!trigger) return;
22
+ const calculatePosition = (trigger, floatingHeight, floatingWidth) => {
23
+ const top = direction === 'up' ? trigger.top - floatingHeight - offset : trigger.bottom + offset;
24
+ const left = align === 'right' ? trigger.right - floatingWidth : trigger.left;
25
+ return {
26
+ top,
27
+ left
28
+ };
29
+ };
30
+ const update = () => {
31
+ const t = triggerRef.current;
32
+ const f = floatingRef.current;
33
+ if (!t) return;
34
+ const r = t.getBoundingClientRect();
35
+ const floatingHeight = f?.offsetHeight ?? 0;
36
+ const floatingWidth = matchTriggerWidth ? r.width : f?.offsetWidth ?? r.width;
37
+ const {
38
+ top,
39
+ left
40
+ } = calculatePosition(r, floatingHeight, floatingWidth);
41
+ // matchTriggerWidth=true: width는 max-content(콘텐츠 자연 너비), min-width만 trigger 너비로 보장.
42
+ // 옵션이 짧으면 trigger 너비, 길면 자연 확장 — 기존 absolute 모드와 동일한 UX.
43
+ setStyle({
44
+ position: 'fixed',
45
+ top,
46
+ left,
47
+ zIndex: FLOATING_Z_INDEX,
48
+ ...(matchTriggerWidth ? {
49
+ minWidth: r.width
50
+ } : {})
51
+ });
52
+ };
53
+ update();
54
+ window.addEventListener('scroll', update, true);
55
+ window.addEventListener('resize', update);
56
+ const triggerObserver = new ResizeObserver(update);
57
+ triggerObserver.observe(trigger);
58
+ let floatingObserver;
59
+ if (floatingRef.current) {
60
+ floatingObserver = new ResizeObserver(update);
61
+ floatingObserver.observe(floatingRef.current);
62
+ }
63
+ return () => {
64
+ window.removeEventListener('scroll', update, true);
65
+ window.removeEventListener('resize', update);
66
+ triggerObserver.disconnect();
67
+ floatingObserver?.disconnect();
68
+ };
69
+ }, [enabled, isOpen, direction, offset, align, matchTriggerWidth, triggerRef, floatingRef]);
70
+ return style;
71
+ };
@@ -0,0 +1,10 @@
1
+ import { useFloatingContext } from '../contexts/FloatingContext';
2
+ export const usePortalState = usePortalProp => {
3
+ const floatingContext = useFloatingContext();
4
+ const shouldPortal = usePortalProp ?? floatingContext?.preferPortal ?? false;
5
+ const portalContainer = floatingContext?.portalContainer ?? (typeof document !== 'undefined' ? document.body : null);
6
+ return {
7
+ shouldPortal,
8
+ portalContainer
9
+ };
10
+ };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * SelectBox / ComboBox 공통 — 최대 선택 개수 제한 활성 여부 판정.
3
+ *
4
+ * React 훅(`useMultiSelect`)과 vanilla 드롭다운(`DropdownModel`)가 동일 로직을 공유하므로
5
+ * 두 곳에 정의가 갈라지지 않도록 단일 source-of-truth로 둔다.
6
+ *
7
+ * **계약**
8
+ * - `0` 이상의 정수 → 활성 (단, `0`은 모든 새 선택을 차단하는 의미)
9
+ * - 음수 / 비정수 / `undefined` / `null` → 비활성 (제한 없는 것과 동일)
10
+ *
11
+ * `0`을 활성으로 보는 이유: 호출자가 `maxSelection={0}`을 명시적으로 전달했을 때
12
+ * "선택 자체를 막겠다"는 의도로 해석하기 위함. 음수는 일반적으로 "값 없음"의 sentinel이므로 비활성.
13
+ */
14
+ export const isMaxSelectionLimitActive = maxSelection => typeof maxSelection === 'number' && Number.isInteger(maxSelection) && maxSelection >= 0;
15
+ /**
16
+ * 현재 선택 길이가 최대치에 도달했는지 단일 함수로 판정.
17
+ *
18
+ * 호출 측에서 `>=`을 직접 작성하지 않도록 의미를 노출하고, type predicate가 내부에서 적용되어
19
+ * `maxSelection`의 narrowing이 보장된다 (외부 predicate 호출로 인한 narrowing 누락 방지).
20
+ *
21
+ * - 제한 비활성(음수 / null / undefined / 비정수): 항상 `false`.
22
+ * - 활성: `currentLength >= maxSelection`.
23
+ */
24
+ export const isMaxSelectionReached = (currentLength, maxSelection) => {
25
+ if (!isMaxSelectionLimitActive(maxSelection)) return false;
26
+ return currentLength >= maxSelection;
27
+ };
@@ -1,3 +1,5 @@
1
+ import { useCallback, useMemo } from 'react';
2
+ import { isMaxSelectionLimitActive, isMaxSelectionReached } from './maxSelection';
1
3
  /**
2
4
  * 전체 선택 상태를 확인하는 유틸 함수
3
5
  */
@@ -44,25 +46,79 @@ export const removeTagFromSelected = (selectedValues, tagIdToRemove) => {
44
46
  return selectedValues.filter(id => id !== tagIdToRemove);
45
47
  };
46
48
  /**
47
- * 전체 선택 관련 로직을 번에 처리하는 커스텀 훅
49
+ * 최대 선택 개수 관련 응집을 별도 훅으로 분리.
50
+ *
51
+ * - `isMaxSelectionActive`: 제한 활성 여부.
52
+ * - `isMaxReached`: 현재 선택 길이가 최대치에 도달했는지.
53
+ * - `canAdd(currentLength)`: 새 항목 추가가 허용되는지 (도달 시 `false`).
54
+ *
55
+ * 도메인 규칙(`>=` 비교 등)을 외부로 노출하지 않고 헬퍼를 통해 의미만 반환한다.
56
+ * `useMultiSelect`가 내부에서 사용하지만, 단독으로도 필요한 호출자가 쓸 수 있게 export한다.
48
57
  */
49
- export const useMultiSelect = (selectedValues, options, selectText, deselectText) => {
58
+ export const useMaxSelection = (selectedValues, maxSelection) => {
59
+ const isMaxSelectionActive = isMaxSelectionLimitActive(maxSelection);
60
+ const isMaxReached = isMaxSelectionReached(selectedValues.length, maxSelection);
61
+ const canAdd = useCallback(currentLength => !isMaxSelectionReached(currentLength, maxSelection), [maxSelection]);
62
+ return {
63
+ isMaxSelectionActive,
64
+ isMaxReached,
65
+ canAdd
66
+ };
67
+ };
68
+ /**
69
+ * 전체 선택 관련 로직을 한 번에 처리하는 커스텀 훅.
70
+ *
71
+ * 시그니처는 호출자가 maxSelection만 지정하더라도 텍스트 라벨을 건너뛰지 않도록 옵션 객체로 받는다.
72
+ *
73
+ * **반환의 `tryToggle`**: multiple 토글 결과를 직접 돌려준다.
74
+ * - 새 배열 반환: 정상 토글 (추가 또는 해제).
75
+ * - `null` 반환: 최대 개수 도달로 추가가 차단됨 (호출자는 변경 없이 종료해야 함).
76
+ *
77
+ * 호출자가 `>= maxSelection` 같은 도메인 규칙을 직접 검사하지 않도록 결과만 노출한다.
78
+ */
79
+ export const useMultiSelect = function (selectedValues, options) {
80
+ let config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
81
+ const {
82
+ selectText,
83
+ deselectText,
84
+ maxSelection
85
+ } = config;
50
86
  const isAllSelected = isAllItemsSelected(selectedValues, options);
51
87
  const buttonText = getSelectAllButtonText(selectedValues, options, selectText, deselectText);
52
- const toggleSelectAll = () => {
53
- return handleSelectAllItems(selectedValues, options);
54
- };
55
- const getSelectedTagsData = () => {
56
- return getSelectedTags(selectedValues, options);
57
- };
58
- const removeTag = tagId => {
59
- return removeTagFromSelected(selectedValues, tagId);
60
- };
61
- return {
88
+ const {
89
+ isMaxSelectionActive,
90
+ isMaxReached,
91
+ canAdd
92
+ } = useMaxSelection(selectedValues, maxSelection);
93
+ const toggleSelectAll = useCallback(() => handleSelectAllItems(selectedValues, options), [selectedValues, options]);
94
+ const getSelectedTagsData = useCallback(() => getSelectedTags(selectedValues, options), [selectedValues, options]);
95
+ const removeTag = useCallback(tagId => removeTagFromSelected(selectedValues, tagId), [selectedValues]);
96
+ /**
97
+ * multiple 선택 토글을 한 번에 처리한다.
98
+ * - 이미 포함된 항목: 해제 (배열에서 제거하여 반환).
99
+ * - 미포함 항목: 추가 시도. 최대치 도달이면 `null` 반환(차단).
100
+ *
101
+ * 호출 측은 `null` 여부만 확인하면 되며 maxSelection 도메인 규칙을 알 필요가 없다.
102
+ */
103
+ const tryToggle = useCallback((optionId, currentArray) => {
104
+ const base = Array.isArray(currentArray) ? currentArray : [];
105
+ const idx = base.indexOf(optionId);
106
+ if (idx > -1) {
107
+ const next = [...base];
108
+ next.splice(idx, 1);
109
+ return next;
110
+ }
111
+ if (!canAdd(base.length)) return null;
112
+ return [...base, optionId];
113
+ }, [canAdd]);
114
+ return useMemo(() => ({
62
115
  isAllSelected,
63
116
  buttonText,
64
117
  toggleSelectAll,
65
118
  getSelectedTagsData,
66
- removeTag
67
- };
119
+ removeTag,
120
+ isMaxSelectionActive,
121
+ isMaxReached,
122
+ tryToggle
123
+ }), [isAllSelected, buttonText, toggleSelectAll, getSelectedTagsData, removeTag, isMaxSelectionActive, isMaxReached, tryToggle]);
68
124
  };
@@ -0,0 +1,22 @@
1
+ export type FeaturedIconTheme = 'light-circle' | 'dark-circle' | 'outline-circle' | 'square-outline';
2
+ export type FeaturedIconColor = 'neutral' | 'error' | 'warning' | 'success';
3
+ export type FeaturedIconSize = 'sm' | 'md' | 'lg' | 'xl';
4
+ export interface FeaturedIconOptions {
5
+ svgString: string;
6
+ theme?: FeaturedIconTheme;
7
+ color?: FeaturedIconColor;
8
+ size?: FeaturedIconSize;
9
+ className?: string;
10
+ }
11
+ export declare class FeaturedIcon {
12
+ private element;
13
+ private options;
14
+ constructor(options: FeaturedIconOptions);
15
+ private createElement;
16
+ private addSizeToSvg;
17
+ getElement(): HTMLElement;
18
+ updateColor(color: FeaturedIconColor): void;
19
+ updateSize(size: FeaturedIconSize): void;
20
+ destroy(): void;
21
+ static create(options: FeaturedIconOptions): FeaturedIcon;
22
+ }