@ncds/ui-admin 1.8.25-alpha.0 → 1.8.25-alpha.1

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 (71) hide show
  1. package/dist/cjs/src/components/forms-and-input/combo-box/ComboBox.js +109 -28
  2. package/dist/cjs/src/components/forms-and-input/combo-box/__tests__/ComboBox.portal.test.js +581 -0
  3. package/dist/cjs/src/generated/scoped-css.js +1 -1
  4. package/dist/cjs/src/hooks/__tests__/useFloatingPosition.ssr.test.js +29 -0
  5. package/dist/cjs/src/hooks/__tests__/useFloatingPosition.test.js +322 -0
  6. package/dist/cjs/src/hooks/dropdown/useDropdown.js +2 -1
  7. package/dist/cjs/src/hooks/useFloatingPosition.js +14 -53
  8. package/dist/cjs/src/utils/dropdown/__tests__/dropdownUtils.test.js +316 -0
  9. package/dist/cjs/src/utils/dropdown/dropdownUtils.js +8 -12
  10. package/dist/cjs/src/utils/portal-position/__tests__/portalPosition.test.js +227 -0
  11. package/dist/cjs/src/utils/portal-position/__tests__/portalPosition.tracking.test.js +397 -0
  12. package/dist/cjs/src/utils/portal-position/index.js +16 -0
  13. package/dist/cjs/src/utils/portal-position/portalPosition.js +162 -0
  14. package/dist/esm/src/components/forms-and-input/combo-box/ComboBox.js +109 -28
  15. package/dist/esm/src/components/forms-and-input/combo-box/__tests__/ComboBox.portal.test.js +578 -0
  16. package/dist/esm/src/generated/scoped-css.js +1 -1
  17. package/dist/esm/src/hooks/__tests__/useFloatingPosition.ssr.test.js +26 -0
  18. package/dist/esm/src/hooks/__tests__/useFloatingPosition.test.js +319 -0
  19. package/dist/esm/src/hooks/dropdown/useDropdown.js +2 -1
  20. package/dist/esm/src/hooks/useFloatingPosition.js +15 -54
  21. package/dist/esm/src/utils/dropdown/__tests__/dropdownUtils.test.js +314 -0
  22. package/dist/esm/src/utils/dropdown/dropdownUtils.js +8 -12
  23. package/dist/esm/src/utils/portal-position/__tests__/portalPosition.test.js +225 -0
  24. package/dist/esm/src/utils/portal-position/__tests__/portalPosition.tracking.test.js +394 -0
  25. package/dist/esm/src/utils/portal-position/index.js +1 -0
  26. package/dist/esm/src/utils/portal-position/portalPosition.js +150 -0
  27. package/dist/temp/assets/scripts/notification/const/sizes.d.ts +1 -1
  28. package/dist/temp/src/components/action/button-group/ButtonGroup.d.ts +1 -1
  29. package/dist/temp/src/components/forms-and-input/combo-box/ComboBox.d.ts +6 -0
  30. package/dist/temp/src/components/forms-and-input/combo-box/ComboBox.js +54 -4
  31. package/dist/temp/src/components/forms-and-input/combo-box/__tests__/ComboBox.portal.test.d.ts +1 -0
  32. package/dist/temp/src/components/forms-and-input/combo-box/__tests__/ComboBox.portal.test.js +418 -0
  33. package/dist/temp/src/generated/scoped-css.js +1 -1
  34. package/dist/temp/src/hooks/__tests__/useFloatingPosition.ssr.test.d.ts +1 -0
  35. package/dist/temp/src/hooks/__tests__/useFloatingPosition.ssr.test.js +26 -0
  36. package/dist/temp/src/hooks/__tests__/useFloatingPosition.test.d.ts +1 -0
  37. package/dist/temp/src/hooks/__tests__/useFloatingPosition.test.js +205 -0
  38. package/dist/temp/src/hooks/dropdown/useDropdown.d.ts +3 -1
  39. package/dist/temp/src/hooks/dropdown/useDropdown.js +2 -2
  40. package/dist/temp/src/hooks/dropdown/useDropdownPosition.d.ts +3 -3
  41. package/dist/temp/src/hooks/useFloatingPosition.d.ts +6 -4
  42. package/dist/temp/src/hooks/useFloatingPosition.js +14 -47
  43. package/dist/temp/src/types/dropdown/dropdown.d.ts +2 -1
  44. package/dist/temp/src/utils/dropdown/__tests__/dropdownUtils.test.d.ts +1 -0
  45. package/dist/temp/src/utils/dropdown/__tests__/dropdownUtils.test.js +174 -0
  46. package/dist/temp/src/utils/dropdown/dropdownUtils.js +8 -9
  47. package/dist/temp/src/utils/portal-position/__tests__/portalPosition.test.d.ts +1 -0
  48. package/dist/temp/src/utils/portal-position/__tests__/portalPosition.test.js +181 -0
  49. package/dist/temp/src/utils/portal-position/__tests__/portalPosition.tracking.test.d.ts +1 -0
  50. package/dist/temp/src/utils/portal-position/__tests__/portalPosition.tracking.test.js +301 -0
  51. package/dist/temp/src/utils/portal-position/index.d.ts +1 -0
  52. package/dist/temp/src/utils/portal-position/index.js +1 -0
  53. package/dist/temp/src/utils/portal-position/portalPosition.d.ts +67 -0
  54. package/dist/temp/src/utils/portal-position/portalPosition.js +88 -0
  55. package/dist/types/assets/scripts/notification/const/sizes.d.ts +1 -1
  56. package/dist/types/src/components/action/button-group/ButtonGroup.d.ts +1 -1
  57. package/dist/types/src/components/forms-and-input/combo-box/ComboBox.d.ts +6 -0
  58. package/dist/types/src/components/forms-and-input/combo-box/__tests__/ComboBox.portal.test.d.ts +1 -0
  59. package/dist/types/src/hooks/__tests__/useFloatingPosition.ssr.test.d.ts +1 -0
  60. package/dist/types/src/hooks/__tests__/useFloatingPosition.test.d.ts +1 -0
  61. package/dist/types/src/hooks/dropdown/useDropdown.d.ts +3 -1
  62. package/dist/types/src/hooks/dropdown/useDropdownPosition.d.ts +3 -3
  63. package/dist/types/src/hooks/useFloatingPosition.d.ts +6 -4
  64. package/dist/types/src/types/dropdown/dropdown.d.ts +2 -1
  65. package/dist/types/src/utils/dropdown/__tests__/dropdownUtils.test.d.ts +1 -0
  66. package/dist/types/src/utils/portal-position/__tests__/portalPosition.test.d.ts +1 -0
  67. package/dist/types/src/utils/portal-position/__tests__/portalPosition.tracking.test.d.ts +1 -0
  68. package/dist/types/src/utils/portal-position/index.d.ts +1 -0
  69. package/dist/types/src/utils/portal-position/portalPosition.d.ts +67 -0
  70. package/dist/ui-admin/assets/styles/style.css +13 -1
  71. package/package.json +1 -1
@@ -2,6 +2,8 @@ import { type RefObject } from 'react';
2
2
  interface UseDropdownConfig<T = any> {
3
3
  triggerRef: RefObject<HTMLElement>;
4
4
  dropdownRef?: RefObject<HTMLElement>;
5
+ /** direction 계산 전용 ref. 미지정 시 triggerRef 사용. Portal 모드에서 anchor box 가 다를 때 지정. */
6
+ positionRef?: RefObject<HTMLElement>;
5
7
  maxHeight: number;
6
8
  itemCount: number;
7
9
  optionItems: T[];
@@ -15,7 +17,7 @@ interface UseDropdownConfig<T = any> {
15
17
  */
16
18
  export declare const useDropdown: <T = any>(config: UseDropdownConfig<T>) => {
17
19
  isOpen: boolean;
18
- direction: import("../../types").DropdownDirection;
20
+ direction: import("../../utils/portal-position").PortalDirection;
19
21
  focusedIndex: number;
20
22
  toggleDropdown: () => void;
21
23
  closeDropdown: () => void;
@@ -1,9 +1,9 @@
1
- import type { DropdownDirection, DropdownPositionConfig } from '../../types/dropdown';
1
+ import type { DropdownPositionConfig } from '../../types/dropdown';
2
2
  /**
3
3
  * 드롭다운 위치 계산을 위한 커스텀 훅
4
4
  */
5
5
  export declare const useDropdownPosition: (config: DropdownPositionConfig) => {
6
- direction: DropdownDirection;
6
+ direction: import("../../utils/portal-position").PortalDirection;
7
7
  updatePosition: () => import("../../types/dropdown").DropdownPositionResult;
8
- setDirection: import("react").Dispatch<import("react").SetStateAction<DropdownDirection>>;
8
+ setDirection: import("react").Dispatch<import("react").SetStateAction<import("../../utils/portal-position").PortalDirection>>;
9
9
  };
@@ -1,15 +1,17 @@
1
1
  import { type CSSProperties, type RefObject } from 'react';
2
- type FloatingDirection = 'up' | 'down';
2
+ import { type PortalAlign, type PortalDirection } from '../utils/portal-position';
3
3
  type UseFloatingPositionParams = {
4
4
  enabled: boolean;
5
5
  isOpen: boolean;
6
6
  triggerRef: RefObject<HTMLElement | null>;
7
7
  floatingRef: RefObject<HTMLElement | null>;
8
- direction: FloatingDirection;
8
+ direction: PortalDirection;
9
+ /** trigger 와 floating 요소 사이 간격. 미지정 시 4px */
9
10
  offset?: number;
10
- align?: 'left' | 'right';
11
+ /** 미지정 시 'left' */
12
+ align?: PortalAlign;
11
13
  /**
12
- * true면 floating 요소의 width를 trigger 너비에 맞춘다.
14
+ * true면 floating 요소의 min-width를 trigger 너비로 보장한다 (width 고정이 아니다).
13
15
  * Portal 모드에서 부모가 body로 바뀌면서 min-width: 100% 같은 CSS가 viewport 너비로
14
16
  * 폭주하는 것을 막는다 (예: SelectBox 옵션 패널).
15
17
  */
@@ -1,5 +1,6 @@
1
1
  import type { RefObject } from 'react';
2
- export type DropdownDirection = 'up' | 'down';
2
+ import type { PortalDirection } from '../../utils/portal-position';
3
+ export type DropdownDirection = PortalDirection;
3
4
  export type DropdownPositionConfig = {
4
5
  triggerRef: RefObject<HTMLElement>;
5
6
  maxHeight: number;
@@ -0,0 +1 @@
1
+ export * from './portalPosition';
@@ -0,0 +1,67 @@
1
+ export type PortalDirection = 'up' | 'down';
2
+ export type PortalAlign = 'left' | 'right';
3
+ export type AnchorRect = Readonly<Pick<DOMRectReadOnly, 'top' | 'bottom' | 'left' | 'right' | 'width'>>;
4
+ export declare const PORTAL_PANEL_Z_INDEX = 1500;
5
+ export type ComputePortalPositionInput = Readonly<{
6
+ anchorRect: AnchorRect;
7
+ panelHeight: number;
8
+ panelWidth: number;
9
+ direction: PortalDirection;
10
+ align?: PortalAlign;
11
+ offset?: number;
12
+ }>;
13
+ export type PortalPosition = Readonly<{
14
+ top: number;
15
+ left: number;
16
+ }>;
17
+ export declare const computePortalPosition: ({ anchorRect, panelHeight, panelWidth, direction, align, offset, }: ComputePortalPositionInput) => PortalPosition;
18
+ export type ResolveDropdownDirectionInput = Readonly<{
19
+ anchorRect: Pick<AnchorRect, 'bottom'>;
20
+ panelHeight: number;
21
+ viewportHeight: number;
22
+ gap?: number;
23
+ }>;
24
+ export declare const resolveDropdownDirection: ({ anchorRect, panelHeight, viewportHeight, gap, }: ResolveDropdownDirectionInput) => PortalDirection;
25
+ export type BuildPortalPanelStyleInput = Readonly<{
26
+ anchorRect: AnchorRect;
27
+ panelHeight: number;
28
+ panelWidth: number | null;
29
+ direction: PortalDirection;
30
+ align?: PortalAlign;
31
+ offset?: number;
32
+ /**
33
+ * true 이면 panelWidth 를 무시하고 anchorRect.width 로 minWidth 를 설정한다.
34
+ * align: 'right' 와 조합 시 콘텐츠가 앵커보다 넓으면 우측 정렬이 보장되지 않는다.
35
+ */
36
+ matchAnchorWidth?: boolean;
37
+ }>;
38
+ export type PortalPanelStyle = Readonly<{
39
+ position: 'fixed';
40
+ top: number;
41
+ left: number;
42
+ zIndex: number;
43
+ minWidth?: number;
44
+ }>;
45
+ export declare const buildPortalPanelStyle: ({ anchorRect, panelHeight, panelWidth, direction, align, offset, matchAnchorWidth, }: BuildPortalPanelStyleInput) => PortalPanelStyle;
46
+ export type AnchorGeometryObserverOptions = Readonly<{
47
+ getAnchor: () => HTMLElement | null;
48
+ /**
49
+ * 구독 시점에 1회 호출되어 ResizeObserver 가 부착된다.
50
+ * 구독 후 패널이 교체·마운트되어도 옵저버는 갱신되지 않는다.
51
+ */
52
+ getPanel: () => HTMLElement | null;
53
+ onChange: () => void;
54
+ }>;
55
+ export declare const observeAnchorGeometry: ({ getAnchor, getPanel, onChange, }: AnchorGeometryObserverOptions) => (() => void);
56
+ export type TrackPortalPositionOptions = Readonly<{
57
+ getAnchor: () => HTMLElement | null;
58
+ getPanel: () => HTMLElement | null;
59
+ /** 함수를 넘기면 갱신마다 다시 읽는다 — 열린 뒤 패널 높이가 변하는 소비자가 방향을 재판정할 수 있다 */
60
+ direction: PortalDirection | (() => PortalDirection);
61
+ align?: PortalAlign;
62
+ offset?: number;
63
+ matchAnchorWidth?: boolean;
64
+ onUpdate: (style: PortalPanelStyle) => void;
65
+ }>;
66
+ export declare const trackPortalPosition: ({ onUpdate, ...measureOptions }: TrackPortalPositionOptions) => (() => void);
67
+ export declare const applyPortalPanelStyle: (element: HTMLElement, style: PortalPanelStyle) => void;
@@ -1238,10 +1238,12 @@ button {
1238
1238
  }
1239
1239
 
1240
1240
  .ncua-dropdown {
1241
- --ncua-dropdown-item-height: 36px;
1242
1241
  position: relative;
1243
1242
  display: inline-block;
1244
1243
  }
1244
+ .ncua-dropdown, .ncua-dropdown__menu--portal-root {
1245
+ --ncua-dropdown-item-height: 36px;
1246
+ }
1245
1247
  .ncua-dropdown__trigger {
1246
1248
  cursor: pointer;
1247
1249
  padding: 0;
@@ -5101,6 +5103,16 @@ button {
5101
5103
  margin-inline-start: -10px;
5102
5104
  }
5103
5105
 
5106
+ .ncua-date-picker--portal-input.ncua-date-picker--xs {
5107
+ padding: 5px 10px;
5108
+ font-size: var(--font-size-xs);
5109
+ }
5110
+
5111
+ .ncua-date-picker--portal-input.ncua-date-picker--sm {
5112
+ padding: 7px 12px;
5113
+ font-size: var(--font-size-sm);
5114
+ }
5115
+
5104
5116
  .ncua-range-date-picker {
5105
5117
  display: inline-flex;
5106
5118
  align-items: center;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ncds/ui-admin",
3
- "version": "1.8.25-alpha.0",
3
+ "version": "1.8.25-alpha.1",
4
4
  "description": "nhn-commerce의 어드민 디자인 시스템입니다.",
5
5
  "scripts": {
6
6
  "barrel": "node barrel.js",