@thewrong/ui 0.1.0

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 (125) hide show
  1. package/README.md +65 -0
  2. package/dist/index.cjs.js +40 -0
  3. package/dist/index.es.js +8066 -0
  4. package/dist/src/components/_shared/form-size-tokens.d.ts +16 -0
  5. package/dist/src/components/action-toast/ActionToast.d.ts +56 -0
  6. package/dist/src/components/action-toast/index.d.ts +2 -0
  7. package/dist/src/components/animated-height/AnimatedHeight.d.ts +30 -0
  8. package/dist/src/components/animated-height/index.d.ts +2 -0
  9. package/dist/src/components/badge/Badge.d.ts +2 -0
  10. package/dist/src/components/badge/index.d.ts +2 -0
  11. package/dist/src/components/badge/types.d.ts +56 -0
  12. package/dist/src/components/badge/utils.d.ts +13 -0
  13. package/dist/src/components/button/Button.d.ts +2 -0
  14. package/dist/src/components/button/index.d.ts +2 -0
  15. package/dist/src/components/button/types.d.ts +22 -0
  16. package/dist/src/components/button/utils.d.ts +6 -0
  17. package/dist/src/components/checkbox/Checkbox.d.ts +33 -0
  18. package/dist/src/components/checkbox/index.d.ts +2 -0
  19. package/dist/src/components/checkbox/types.d.ts +33 -0
  20. package/dist/src/components/checkbox/utils.d.ts +33 -0
  21. package/dist/src/components/collapsible/Collapsible.d.ts +36 -0
  22. package/dist/src/components/collapsible/index.d.ts +2 -0
  23. package/dist/src/components/date-input/DateInput.d.ts +27 -0
  24. package/dist/src/components/date-input/index.d.ts +1 -0
  25. package/dist/src/components/date-picker/date-picker.d.ts +34 -0
  26. package/dist/src/components/date-picker/date-range-picker.d.ts +21 -0
  27. package/dist/src/components/date-picker/index.d.ts +5 -0
  28. package/dist/src/components/date-picker/month-picker.d.ts +25 -0
  29. package/dist/src/components/drawer/Drawer.d.ts +18 -0
  30. package/dist/src/components/drawer/index.d.ts +2 -0
  31. package/dist/src/components/info-tooltip/InfoTooltip.d.ts +11 -0
  32. package/dist/src/components/info-tooltip/index.d.ts +2 -0
  33. package/dist/src/components/input/Input.d.ts +10 -0
  34. package/dist/src/components/input/PasswordInput.d.ts +8 -0
  35. package/dist/src/components/input/format.d.ts +38 -0
  36. package/dist/src/components/input/index.d.ts +4 -0
  37. package/dist/src/components/input/types.d.ts +131 -0
  38. package/dist/src/components/input/utils.d.ts +17 -0
  39. package/dist/src/components/loading-spinner/LoadingSpinner.d.ts +16 -0
  40. package/dist/src/components/loading-spinner/index.d.ts +2 -0
  41. package/dist/src/components/modal/Modal.d.ts +51 -0
  42. package/dist/src/components/modal/ModalSubView.d.ts +61 -0
  43. package/dist/src/components/modal/StandardModal.d.ts +59 -0
  44. package/dist/src/components/modal/index.d.ts +6 -0
  45. package/dist/src/components/page-title/PageTitle.d.ts +17 -0
  46. package/dist/src/components/page-title/index.d.ts +1 -0
  47. package/dist/src/components/popover/Popover.d.ts +28 -0
  48. package/dist/src/components/popover/index.d.ts +2 -0
  49. package/dist/src/components/search-box/ExactMatchToggle.d.ts +14 -0
  50. package/dist/src/components/search-box/SearchBox.d.ts +35 -0
  51. package/dist/src/components/search-box/SearchBoxChips.d.ts +12 -0
  52. package/dist/src/components/search-box/SearchBoxDateRange.d.ts +20 -0
  53. package/dist/src/components/search-box/SearchBoxDateSingle.d.ts +17 -0
  54. package/dist/src/components/search-box/SearchBoxField.d.ts +11 -0
  55. package/dist/src/components/search-box/SearchBoxFloatingInput.d.ts +24 -0
  56. package/dist/src/components/search-box/SearchBoxFloatingSelect.d.ts +19 -0
  57. package/dist/src/components/search-box/SearchBoxMonth.d.ts +14 -0
  58. package/dist/src/components/search-box/SearchBoxMultiSelect.d.ts +25 -0
  59. package/dist/src/components/search-box/SearchBoxSheetContext.d.ts +8 -0
  60. package/dist/src/components/search-box/dateRangePresets.d.ts +10 -0
  61. package/dist/src/components/search-box/index.d.ts +5 -0
  62. package/dist/src/components/search-box/parseDateRange.d.ts +15 -0
  63. package/dist/src/components/search-box/parseSearchValues.d.ts +38 -0
  64. package/dist/src/components/search-box/types.d.ts +67 -0
  65. package/dist/src/components/search-box/useSearchBoxState.d.ts +30 -0
  66. package/dist/src/components/select/MultiSelect.d.ts +69 -0
  67. package/dist/src/components/select/Select.d.ts +81 -0
  68. package/dist/src/components/select/index.d.ts +4 -0
  69. package/dist/src/components/select/loading-dots.d.ts +9 -0
  70. package/dist/src/components/select/types.d.ts +141 -0
  71. package/dist/src/components/select/utils.d.ts +16 -0
  72. package/dist/src/components/switch/Switch.d.ts +17 -0
  73. package/dist/src/components/switch/index.d.ts +2 -0
  74. package/dist/src/components/switch/types.d.ts +10 -0
  75. package/dist/src/components/switch/utils.d.ts +14 -0
  76. package/dist/src/components/table/accordion-table.d.ts +31 -0
  77. package/dist/src/components/table/column-group-utils.d.ts +49 -0
  78. package/dist/src/components/table/components/ColumnPresetSelector.d.ts +36 -0
  79. package/dist/src/components/table/components/ColumnSettingsTable.d.ts +25 -0
  80. package/dist/src/components/table/components/KeyboardNavButton.d.ts +12 -0
  81. package/dist/src/components/table/components/PageJumpInput.d.ts +16 -0
  82. package/dist/src/components/table/components/Pagination.d.ts +38 -0
  83. package/dist/src/components/table/components/PaginationFooter.d.ts +28 -0
  84. package/dist/src/components/table/components/SortableHeaderCell.d.ts +27 -0
  85. package/dist/src/components/table/hooks/useColumnPresets.d.ts +48 -0
  86. package/dist/src/components/table/hooks/useColumnResize.d.ts +99 -0
  87. package/dist/src/components/table/hooks/useFillEmptyRows.d.ts +51 -0
  88. package/dist/src/components/table/hooks/useInfiniteScroll.d.ts +58 -0
  89. package/dist/src/components/table/hooks/useTableColumnState.d.ts +30 -0
  90. package/dist/src/components/table/hooks/useTableDragSelection.d.ts +35 -0
  91. package/dist/src/components/table/hooks/useTableSort.d.ts +47 -0
  92. package/dist/src/components/table/hooks/useVirtualTable.d.ts +49 -0
  93. package/dist/src/components/table/index.d.ts +27 -0
  94. package/dist/src/components/table/mini-table.d.ts +44 -0
  95. package/dist/src/components/table/paginated-mini-table.d.ts +28 -0
  96. package/dist/src/components/table/paginated-table.d.ts +8 -0
  97. package/dist/src/components/table/table.d.ts +10 -0
  98. package/dist/src/components/table/types.d.ts +409 -0
  99. package/dist/src/components/table/utils.d.ts +47 -0
  100. package/dist/src/components/table-checkbox/TableCheckbox.d.ts +16 -0
  101. package/dist/src/components/table-checkbox/index.d.ts +1 -0
  102. package/dist/src/components/table-page-layout/TablePageLayout.d.ts +22 -0
  103. package/dist/src/components/table-page-layout/index.d.ts +1 -0
  104. package/dist/src/components/textarea/Textarea.d.ts +10 -0
  105. package/dist/src/components/textarea/index.d.ts +2 -0
  106. package/dist/src/components/textarea/types.d.ts +38 -0
  107. package/dist/src/components/toast/ToastProvider.d.ts +26 -0
  108. package/dist/src/components/toast/index.d.ts +3 -0
  109. package/dist/src/components/toolbar/Toolbar.d.ts +114 -0
  110. package/dist/src/components/toolbar/index.d.ts +2 -0
  111. package/dist/src/components/tooltip/Tooltip.d.ts +18 -0
  112. package/dist/src/components/tooltip/index.d.ts +2 -0
  113. package/dist/src/hooks/index.d.ts +4 -0
  114. package/dist/src/hooks/useBottomSheetDrag.d.ts +41 -0
  115. package/dist/src/hooks/useClickOutside.d.ts +16 -0
  116. package/dist/src/hooks/useMediaQuery.d.ts +15 -0
  117. package/dist/src/hooks/useScrollLock.d.ts +8 -0
  118. package/dist/src/index.d.ts +27 -0
  119. package/dist/src/lib/Portal.d.ts +12 -0
  120. package/dist/src/lib/column-preset-storage.d.ts +54 -0
  121. package/dist/src/lib/index.d.ts +6 -0
  122. package/dist/src/lib/overlay-stack.d.ts +13 -0
  123. package/dist/src/lib/utils.d.ts +11 -0
  124. package/dist/ui.css +3 -0
  125. package/package.json +128 -0
@@ -0,0 +1,131 @@
1
+ import { ComponentPropsWithoutRef, ReactNode, Ref } from 'react';
2
+ /**
3
+ * Input 컴포넌트의 Variant 타입
4
+ */
5
+ export type InputVariant = "box" | "line" | "big" | "hero";
6
+ /**
7
+ * Input 컴포넌트의 사이즈. Button/Select/Textarea와 동일 토큰. box variant에서만 적용.
8
+ * - mini: 다건 입력/표 형식 컴팩트 모드(특히 모바일)
9
+ * - small: 다건 입력/표 형식 기본
10
+ * - medium: 폼 단독 입력 기본
11
+ * - large: 메인 페이지의 강조 입력
12
+ */
13
+ export type InputSize = "mini" | "small" | "medium" | "large";
14
+ /**
15
+ * Input 컴포넌트의 Label 표시 방식 타입
16
+ */
17
+ export type InputLabelOption = "appear" | "sustain";
18
+ /**
19
+ * Input 컴포넌트의 Value 타입
20
+ */
21
+ export type InputValue = string | number;
22
+ /**
23
+ * Format 함수 타입
24
+ */
25
+ export type FormatTransform = (value: InputValue) => InputValue;
26
+ export type FormatReset = (formattedValue: InputValue) => InputValue;
27
+ /**
28
+ * Format 옵션
29
+ */
30
+ export interface InputFormat {
31
+ /**
32
+ * 입력값을 포맷팅된 값으로 변환해요.
33
+ * 예: "1000000" → "1,000,000"
34
+ */
35
+ transform: FormatTransform;
36
+ /**
37
+ * 포맷팅된 값을 원본 값으로 복원해요.
38
+ * 예: "1,000,000" → "1000000"
39
+ */
40
+ reset?: FormatReset;
41
+ }
42
+ /**
43
+ * Input 컴포넌트의 공통 Props
44
+ */
45
+ export interface InputCommonProps {
46
+ /**
47
+ * 텍스트 필드의 모양
48
+ */
49
+ variant: InputVariant;
50
+ /**
51
+ * 사이즈 — box variant에서만 동작.
52
+ * @default 'medium'
53
+ */
54
+ inputSize?: InputSize;
55
+ /**
56
+ * 텍스트 필드의 상단의 라벨
57
+ */
58
+ label?: string;
59
+ /**
60
+ * label 표시 방식
61
+ * 'appear': value가 있을 때만 label이 보여요
62
+ * 'sustain': 항상 label이 보여요
63
+ * @default 'appear'
64
+ */
65
+ labelOption?: InputLabelOption;
66
+ /**
67
+ * 텍스트 필드의 하단의 도움말
68
+ */
69
+ help?: ReactNode;
70
+ /**
71
+ * 텍스트 필드의 에러 여부
72
+ * @default false
73
+ */
74
+ hasError?: boolean;
75
+ /**
76
+ * 텍스트 필드의 비활성화 여부
77
+ * @default false
78
+ */
79
+ disabled?: boolean;
80
+ /**
81
+ * 입력 필드 앞에 표시될 텍스트
82
+ */
83
+ prefix?: string;
84
+ /**
85
+ * 입력 필드 뒤에 표시될 텍스트 (예: "원", "%"). 우측 슬롯의 가장 좌측.
86
+ */
87
+ suffix?: string;
88
+ /**
89
+ * 우측 트레일링 아이콘 (lucide-react 등). suffix 다음, clearable 앞에 위치.
90
+ */
91
+ trailingIcon?: ReactNode;
92
+ /**
93
+ * 값이 있을 때 우측에 X 버튼(CircleX)을 노출. 클릭 시 onChange로 빈 값을 emit.
94
+ * disabled에서는 노출하지 않는다. trailingIcon 다음, badge 앞에 위치.
95
+ * @default false
96
+ */
97
+ clearable?: boolean;
98
+ /**
99
+ * 우측 가장 끝에 표시할 뱃지/라벨 ReactNode. 단위 표시나 상태 라벨용.
100
+ */
101
+ badge?: ReactNode;
102
+ /**
103
+ * placeholder 텍스트
104
+ */
105
+ placeholder?: string;
106
+ /**
107
+ * 금액, 휴대폰번호 등 특정 형식으로 변환해요
108
+ */
109
+ format?: InputFormat;
110
+ /**
111
+ * 컨테이너의 추가 props
112
+ */
113
+ containerProps?: ComponentPropsWithoutRef<"div">;
114
+ /**
115
+ * 컨테이너의 ref
116
+ */
117
+ containerRef?: Ref<HTMLDivElement>;
118
+ }
119
+ /**
120
+ * Input 컴포넌트의 Props
121
+ */
122
+ export interface InputProps extends Omit<ComponentPropsWithoutRef<"input">, "color" | "value" | "defaultValue">, InputCommonProps {
123
+ /**
124
+ * 입력값
125
+ */
126
+ value?: InputValue;
127
+ /**
128
+ * 기본값
129
+ */
130
+ defaultValue?: InputValue;
131
+ }
@@ -0,0 +1,17 @@
1
+ import { InputSize, InputVariant } from './types';
2
+ /**
3
+ * Input Variant에 따른 컨테이너(input wrapper) 클래스 매핑.
4
+ * box variant는 새 디자인 적용. line/big/hero는 레거시.
5
+ */
6
+ export declare const getInputVariantClasses: (variant: InputVariant, hasError: boolean, disabled: boolean, size?: InputSize) => string;
7
+ /**
8
+ * input 엘리먼트 자체의 텍스트/배경 클래스.
9
+ */
10
+ export declare const getInputClasses: (variant: InputVariant, hasError: boolean, disabled: boolean, filled: boolean, size?: InputSize) => string;
11
+ /**
12
+ * Trailing 영역(아이콘/clear/라벨) 색상 — 상태에 따라.
13
+ */
14
+ export declare const getInputTrailingIconColor: (hasError: boolean, disabled: boolean, filledOrFocused: boolean) => string;
15
+ export declare const getInputContainerClasses: () => string;
16
+ export declare const getInputLabelClasses: (_variant: InputVariant, hasError: boolean) => string;
17
+ export declare const getInputHelpClasses: (hasError: boolean) => string;
@@ -0,0 +1,16 @@
1
+ export interface LoadingSpinnerProps {
2
+ message?: string;
3
+ size?: "sm" | "md" | "lg";
4
+ className?: string;
5
+ }
6
+ export declare function Spinner({ size }: {
7
+ size?: "sm" | "md" | "lg";
8
+ }): import("react").JSX.Element;
9
+ /**
10
+ * 영역 중앙에 스피너 + 메시지를 표시하는 로딩 표시. 데이터 페칭 중 컨테이너에 채워 쓴다.
11
+ */
12
+ export declare function LoadingSpinner({ message, size, className, }: LoadingSpinnerProps): import("react").JSX.Element;
13
+ /** 인라인(작은) 스피너 — 리스트 하단 더보기 로딩 등. */
14
+ export declare function InlineSpinner({ size }: {
15
+ size?: "sm" | "md" | "lg";
16
+ }): import("react").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export { LoadingSpinner, InlineSpinner, Spinner } from './LoadingSpinner';
2
+ export type { LoadingSpinnerProps } from './LoadingSpinner';
@@ -0,0 +1,51 @@
1
+ export interface ModalProps {
2
+ isOpen: boolean;
3
+ onClose: () => void;
4
+ title?: string;
5
+ /**
6
+ * 데스크탑(sm+) 모달의 고정 폭(px). 지정하지 않으면 콘텐츠 폭에 fit (`sm:w-auto`).
7
+ *
8
+ * 모달은 너비를 애니메이션하지 않는 것이 정책이다(컴포넌트 설명 참고). 따라서 콘텐츠 폭이
9
+ * 인터랙션으로 변할 수 있는 모달은 `widthPx`로 폭을 고정해 폭 변동에 따른 시각적 흔들림을 막는다.
10
+ * 폭이 변하지 않는 단순 모달은 생략해 콘텐츠 폭에 맞춰도 된다.
11
+ * 모바일은 무조건 w-full (이 값 무시).
12
+ */
13
+ widthPx?: number;
14
+ /**
15
+ * 푸터 영역. 지정하면 헤더-바디-푸터 3단 구조로 동작 — 푸터는 스크롤 영역 밖에 고정되고
16
+ * children(=바디)만 자체 스크롤된다. 미지정이면 children 전체가 한 영역에서 스크롤(기본).
17
+ */
18
+ footer?: React.ReactNode;
19
+ /**
20
+ * 바디 스크롤 컨테이너 자체에 좌우 패딩을 부여해 스크롤바가 시트 가장자리가 아니라 안쪽에
21
+ * 떠 있는 모양을 만든다. 이 옵션을 켜면 사용처 본문에서는 좌우 패딩을 제거하고 세로만 둘 것.
22
+ */
23
+ bodyPadded?: boolean;
24
+ /**
25
+ * 모달 바디 위에 우측에서 슬라이드 인 하는 서브뷰. ModalSubView 컴포넌트를 그대로 넘기면 된다.
26
+ * 별도 wrapper(scroll-isolated)에 두어 본문 스크롤과 무관하게 viewport 100% 덮음.
27
+ * subView가 있으면 시트 높이가 자동으로 viewport 기준으로 강제된다 (콘텐츠 따라 자라지 않음).
28
+ */
29
+ subView?: React.ReactNode;
30
+ children: React.ReactNode;
31
+ }
32
+ /**
33
+ * 데스크탑(`sm`+)에서는 중앙 정렬 모달, 모바일에서는 화면 하단에서 올라오는 bottom-sheet으로 동작.
34
+ *
35
+ * - 모바일: 시트가 화면 하단에 붙고 상단 모서리만 둥글다. 핸들 바 표시.
36
+ * 진입/퇴장 모션은 화면 밖에서 슬라이드 (`y: "100%" → 0 → "100%"`).
37
+ * - 데스크탑: 중앙 카드. 살짝 위로 올라오면서 페이드 인/아웃.
38
+ *
39
+ * **높이 변화**: 콘텐츠 높이가 변하는 인터랙션(토글/조건부 영역)은 본문을 `<AnimatedHeight>`로
40
+ * 감싸면 시트 높이가 부드럽게 이행된다. 미적용 시 instant jump.
41
+ *
42
+ * **너비는 고정한다**: 동적 너비 트랜지션은 데스크탑 중앙 정렬(`translateX(-50%)`)의 기준점과
43
+ * 함께 움직여 한쪽으로 밀리는 부자연스러운 모션이 된다(framer-motion `layout`도 transform 정렬과
44
+ * 충돌). 그래서 높이만 애니메이션하고 너비는 고정하는 것을 정책으로 한다. 콘텐츠 폭이 모드 전환
45
+ * 등으로 변할 수 있으면 `widthPx`로 고정해 시트가 흔들리지 않게 할 것.
46
+ *
47
+ * **레이어드 오버레이**: ESC/백드롭은 `overlayStack`에서 자신이 top일 때만 반응한다.
48
+ * ActionToast나 ModalSubView가 위에 떠 있으면(더 높은 priority/나중 push) 자동으로 양보된다.
49
+ * 모달 위에 또 모달을 쌓는 대신 ModalSubView(푸시 네비)나 ActionToast(재확인)로 푸는 것을 권장.
50
+ */
51
+ export declare function Modal({ isOpen, onClose, title, widthPx, footer, bodyPadded, subView, children, }: ModalProps): import("react").JSX.Element;
@@ -0,0 +1,61 @@
1
+ import { ReactNode } from 'react';
2
+ export interface ModalSubViewProps {
3
+ open: boolean;
4
+ /** 뒤로가기 버튼 / ESC 키로 트리거됨. */
5
+ onBack: () => void;
6
+ title?: ReactNode;
7
+ /** 헤더 우측에 추가 액션. 예: 새로고침 버튼. */
8
+ headerRight?: ReactNode;
9
+ /**
10
+ * 바디 스크롤 컨테이너에 좌우 margin(mx-4)을 부여해 스크롤바가 시트 가장자리가 아닌 안쪽에
11
+ * 떠 있는 모양을 만든다. 본 Modal의 bodyPadded와 동일 정책. 디폴트 true.
12
+ * 본문이 카드/테이블처럼 가장자리까지 가야 하면 false로 끄고 호출부가 padding 책임.
13
+ */
14
+ bodyPadded?: boolean;
15
+ /**
16
+ * children을 px-4 py-5 wrapper로 자동 감싼다 (StandardModal과 동일 정책).
17
+ * 호출부가 자체 padding을 가지면 false로 끌 것. 디폴트 true.
18
+ */
19
+ contentPadded?: boolean;
20
+ /**
21
+ * 표시 방식.
22
+ * - "full" (기본): 부모 시트를 통째로 덮으며 우측에서 슬라이드 인.
23
+ * - "drawer": 백드롭 + 우측 일부 영역만 차지하는 사이드 드로어. 부모 본문이 백드롭 뒤로 흐릿하게
24
+ * 보이며 드로어는 우측에서 슬라이드 인.
25
+ */
26
+ variant?: "full" | "drawer";
27
+ children: ReactNode;
28
+ }
29
+ /**
30
+ * 모달 본문 위에 우측에서 슬라이드 인 하는 서브뷰.
31
+ *
32
+ * 데스크탑/모바일 동일하게 부모 Modal의 영역을 `absolute inset-0`로 덮어 한 번에 한 화면만
33
+ * 보이게 한다. 모바일 바텀시트에서 두 시트를 겹치는 어색함 없이 자연스러운 푸시 네비.
34
+ * (레이어드 모달 회피)
35
+ *
36
+ * **부모 Modal 요구사항**: 자식이 `absolute inset-0`로 자리 잡으려면 어딘가에 `position: relative`가
37
+ * 있어야 한다. Modal 컴포넌트 자체가 `relative` 시트라 별도 처리 불필요.
38
+ *
39
+ * **높이 정책 — 서브뷰 콘텐츠 ≤ 부모 모달 콘텐츠**: 서브뷰는 부모 시트 영역을 `absolute inset-0`로
40
+ * 덮으므로 부모 시트의 높이를 그대로 물려받는다. 모달 너비를 애니메이션하지 않는 것과 같은 이유로
41
+ * 시트 높이도 서브뷰 진입 때마다 출렁이게 하지 않는다. 따라서 **서브뷰 콘텐츠 높이는 부모 모달
42
+ * 본문 높이와 같거나 작게** 설계하는 것을 권장한다. "작은 모달인데 서브뷰에만 아주 긴 내용"이
43
+ * 들어가면 서브뷰 안에서만 스크롤이 생겨 부모와 높이가 어긋나 보인다. 긴 목록은 부모 모달 자체를
44
+ * 그만큼 키우거나(`widthPx`/콘텐츠 양 조정), 별도 페이지/Drawer로 분리할 것.
45
+ *
46
+ * **ESC 동작**: SubView가 열려있는 동안 ESC는 SubView의 `onBack`을 부르고 모달은 유지된다.
47
+ * `overlayStack`을 push해 Modal보다 위 layer로 등록 — Modal의 ESC 핸들러는 자기가 top일 때만 실행.
48
+ *
49
+ * @example
50
+ * ```tsx
51
+ * const [subOpen, setSubOpen] = useState(false);
52
+ *
53
+ * <Modal isOpen={open} onClose={onClose} title="한도 수정">
54
+ * <button onClick={() => setSubOpen(true)}>변경 이력 보기</button>
55
+ * <ModalSubView open={subOpen} onBack={() => setSubOpen(false)} title="변경 이력">
56
+ * <AuditLogList ... />
57
+ * </ModalSubView>
58
+ * </Modal>
59
+ * ```
60
+ */
61
+ export declare function ModalSubView({ open, onBack, title, headerRight, bodyPadded, contentPadded, variant, children, }: ModalSubViewProps): import("react").JSX.Element;
@@ -0,0 +1,59 @@
1
+ import { ReactNode } from 'react';
2
+ import { ButtonAppearance, ButtonVariant } from '../../../components/button';
3
+ export interface StandardModalAction {
4
+ label: ReactNode;
5
+ onClick: () => void;
6
+ variant?: ButtonVariant;
7
+ appearance?: ButtonAppearance;
8
+ /** 좌측에 아이콘. 우측 액션엔 거의 안 쓰지만 leftAction(예: 변경이력)에선 자주 사용. */
9
+ leadingIcon?: ReactNode;
10
+ loading?: boolean;
11
+ disabled?: boolean;
12
+ }
13
+ export interface StandardModalProps {
14
+ isOpen: boolean;
15
+ onClose: () => void;
16
+ title?: string;
17
+ widthPx?: number;
18
+ /** 우측 슬라이드 서브뷰. ModalSubView 그대로 전달. */
19
+ subView?: ReactNode;
20
+ /**
21
+ * 우측 주 액션. 보통 "저장" / "확인" 등. variant 기본 primary.
22
+ * 미지정이면 footer 자체가 안 그려진다 (단순 알림성 모달은 base Modal로).
23
+ */
24
+ primaryAction?: StandardModalAction;
25
+ /** 우측 보조 액션. 보통 "취소" / "닫기". variant 기본 secondary, appearance 기본 outlined. */
26
+ secondaryAction?: StandardModalAction;
27
+ /**
28
+ * 좌측 보조 액션. 비대칭 footer (예: 좌측 "변경이력", 우측 "닫기/저장")가 필요할 때.
29
+ * 일반 모달에서는 미지정.
30
+ */
31
+ leftAction?: StandardModalAction;
32
+ /**
33
+ * 본문 자동 padding(`px-4 py-5`)을 끄고 호출부가 직접 padding 책임진다.
34
+ * 본문이 카드/테이블/이미지처럼 자체 가장자리까지 가야 하는 경우.
35
+ */
36
+ bodyNoPadding?: boolean;
37
+ children: ReactNode;
38
+ }
39
+ /**
40
+ * 표준 폼 모달 — Modal 위에 표준 footer + 본문 padding을 강제로 입힌 고수준 컴포넌트.
41
+ *
42
+ * 80% 폼 모달 케이스를 한 번에 표준화한다. 비대칭 액션도 `leftAction` 으로 커버.
43
+ * 자유도가 더 필요한 케이스(footer 자체 자유 배치, 본문에 다른 인터랙션 영역)는
44
+ * base `Modal`로 직접 내려가서 footer/bodyPadded prop을 자유롭게 쓸 것.
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * <StandardModal
49
+ * isOpen={open}
50
+ * onClose={onClose}
51
+ * title="역할 수정"
52
+ * primaryAction={{ label: "저장", onClick: handleSave, loading: isSaving }}
53
+ * secondaryAction={{ label: "닫기", onClick: onClose }}
54
+ * >
55
+ * <Input ... />
56
+ * </StandardModal>
57
+ * ```
58
+ */
59
+ export declare function StandardModal({ isOpen, onClose, title, widthPx, subView, primaryAction, secondaryAction, leftAction, bodyNoPadding, children, }: StandardModalProps): import("react").JSX.Element;
@@ -0,0 +1,6 @@
1
+ export { Modal } from './Modal';
2
+ export type { ModalProps } from './Modal';
3
+ export { ModalSubView } from './ModalSubView';
4
+ export type { ModalSubViewProps } from './ModalSubView';
5
+ export { StandardModal } from './StandardModal';
6
+ export type { StandardModalAction, StandardModalProps } from './StandardModal';
@@ -0,0 +1,17 @@
1
+ interface Props {
2
+ /** 메인 타이틀. 페이지 식별의 1순위 정보. */
3
+ title: string;
4
+ /** 한 줄 설명. title 옆에 baseline 정렬로 표시(없으면 생략). */
5
+ subtitle?: string;
6
+ className?: string;
7
+ }
8
+ /**
9
+ * 페이지 헤더 좌측에 표시되는 타이틀 영역.
10
+ *
11
+ * Breadcrumb 자리를 대체. 라우트 뎁스가 얕을 때 빵부스러기보단 굵은 타이틀 + 부제목이
12
+ * 페이지 식별에 적합. subtitle은 title 옆에 baseline 정렬로 가로 배치 — 좁은 화면에서는 wrap.
13
+ *
14
+ * subtitle 매핑은 `usePageTitle` 훅이 메뉴 데이터의 `description` 필드를 읽어 전달.
15
+ */
16
+ export declare function PageTitle({ title, subtitle, className }: Props): import("react").JSX.Element;
17
+ export {};
@@ -0,0 +1 @@
1
+ export { PageTitle } from './PageTitle';
@@ -0,0 +1,28 @@
1
+ import { ReactNode } from 'react';
2
+ export interface PopoverProps {
3
+ /**
4
+ * 팝오버를 여는 트리거. **비대화형 노드(텍스트·아이콘·span 등)를 권장한다.**
5
+ * 래퍼 span이 `role="button"` + `tabIndex`로 버튼 시맨틱과 키보드 포커스를 부여하기 때문에,
6
+ * 이미 대화형인 요소(`<button>`/`<a>`)를 넘기면 포커스가 중첩되고 role이 겹친다.
7
+ * 대화형 트리거가 꼭 필요하면 그 요소를 직접 쓰지 말고 비대화형 콘텐츠로 감싸 전달할 것.
8
+ */
9
+ trigger: ReactNode;
10
+ /**
11
+ * 팝오버 내용. 함수로 주면 `close` 콜백을 주입받아 내부에서 팝오버를 닫을 수 있다
12
+ * (예: 메뉴 항목 클릭 후 닫기). ReactNode를 그대로 줘도 된다.
13
+ */
14
+ content: ReactNode | ((close: () => void) => ReactNode);
15
+ /** 배치 방향. floating-ui 기반이라 공간 부족 시 자동 flip된다. 기본 bottom. */
16
+ placement?: "top" | "bottom" | "left" | "right";
17
+ /** 열림/닫힘 변화 콜백. 호출처가 open 상태에 따라 폴링 등을 제어할 때 사용. */
18
+ onOpenChange?: (open: boolean) => void;
19
+ }
20
+ /**
21
+ * Popover — `@floating-ui/react` 기반.
22
+ *
23
+ * - **클릭 토글** + 외부 클릭/ESC 자동 닫힘(useDismiss)
24
+ * - **자동 flip / shift**: 공간 부족하면 반대편으로, viewport 경계로 clamp
25
+ * - **스크롤/resize 자동 추적**(autoUpdate)
26
+ * - **Portal 렌더**: 부모 overflow:hidden에 잘리지 않음
27
+ */
28
+ export declare function Popover({ trigger, content, placement, onOpenChange, }: PopoverProps): import("react").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export { Popover } from './Popover';
2
+ export type { PopoverProps } from './Popover';
@@ -0,0 +1,14 @@
1
+ interface Props {
2
+ value: boolean;
3
+ onChange: (next: boolean) => void;
4
+ size: "mini" | "small";
5
+ }
6
+ /**
7
+ * SearchBox "완전일치" 토글.
8
+ *
9
+ * 시안(`완전일치.png`): 박스 없는 인라인 체크 아이콘 + 라벨.
10
+ * - 비활성: 회색 체크 + 회색 라벨
11
+ * - 활성: 파란 체크 + 파란 라벨
12
+ */
13
+ export declare function ExactMatchToggle({ value, onChange, size }: Props): import("react").JSX.Element;
14
+ export {};
@@ -0,0 +1,35 @@
1
+ import { SearchField, SearchValues } from './types';
2
+ interface Props {
3
+ /** 호출부가 `as const satisfies readonly SearchField[]` 패턴을 쓰면 parseSearchValues가
4
+ * 타입을 정확히 추론하므로 readonly 시그니처로 받는다. */
5
+ fields: readonly SearchField[];
6
+ /** 외부에서 적용된 값. 초기값 + 외부에서 강제 변경(예: URL 동기화) 시 반영. */
7
+ values: SearchValues;
8
+ /** [검색] 또는 Enter로 commit. */
9
+ onSearch: (next: SearchValues) => void;
10
+ /** [초기화]. 미지정 시 빈 객체로 onSearch 호출. */
11
+ onClear?: () => void;
12
+ /** 검색 요청 진행 중 — 검색 버튼 비활성화 + Enter/submit no-op. */
13
+ isSubmitting?: boolean;
14
+ /** "완전일치" 옵션 — 지정하면 검색/초기화 좌측에 토글 노출. value/onChange 같이 받는다. */
15
+ exactMatch?: {
16
+ value: boolean;
17
+ onChange: (next: boolean) => void;
18
+ };
19
+ /** className for outer wrapper. */
20
+ className?: string;
21
+ }
22
+ /**
23
+ * 공용 검색박스.
24
+ *
25
+ * 동작 요약:
26
+ * - 입력 즉시 검색 X — [검색]/Enter/[적용](모바일 시트) 시점에만 commit
27
+ * - select 활성값만 칩으로 표시
28
+ * - 데스크톱: 페이지 배경 위에 투명하게 떠 있는 플로팅 라벨 필드 + 우측 액션 버튼
29
+ * - 모바일: 헤더 없이 우측 [초기화][검색][필터] 아이콘 3개만. 필터 클릭 시 바텀시트로 본체 표시.
30
+ * 바텀시트 안에서 입력 후 [적용]을 눌러야 commit (시트 외부 클릭/닫기는 입력 폐기).
31
+ *
32
+ * 페이지에서는 `fields` 배열만 정의해서 넘기고, draft 관리는 SearchBox 내부가 담당.
33
+ */
34
+ export declare function SearchBox({ fields, values, onSearch, onClear, isSubmitting, exactMatch, className, }: Props): import("react").JSX.Element;
35
+ export {};
@@ -0,0 +1,12 @@
1
+ interface ChipData {
2
+ key: string;
3
+ label: string;
4
+ valueLabel: string;
5
+ }
6
+ interface Props {
7
+ chips: ChipData[];
8
+ onRemove: (key: string) => void;
9
+ }
10
+ /** 적용된 select 필드를 칩으로 표시. 칩 클릭 시 해당 필터 제거. hover 시 전체 텍스트 툴팁. */
11
+ export declare function SearchBoxChips({ chips, onRemove }: Props): import("react").JSX.Element | null;
12
+ export {};
@@ -0,0 +1,20 @@
1
+ import { DateRangePreset } from './types';
2
+ interface Props {
3
+ /** "from~to" CSV. 빈 문자열이면 양쪽 모두 비어있음. */
4
+ value: string;
5
+ onChange: (next: string) => void;
6
+ presets?: DateRangePreset[];
7
+ size: "mini" | "small";
8
+ }
9
+ /**
10
+ * 날짜 범위 입력 — DateInput 2개 (직접 타이핑 + 캘린더 popover) + 프리셋 버튼.
11
+ *
12
+ * 레이아웃 그룹화:
13
+ * - 인풋 묶음(from `~` to)은 절대 분리되지 않음. 좁아지면 한 묶음 통째로 다음 줄로.
14
+ * - 프리셋 묶음도 통째로 유지(버튼 텍스트 nowrap).
15
+ * - 두 묶음은 부모 flex-wrap이라 viewport에 따라 한 줄/두 줄 자동 전환.
16
+ *
17
+ * URL 직렬화: 단일 SearchValues 키에 `"from~to"`. 빈 값은 미입력.
18
+ */
19
+ export declare function SearchBoxDateRange({ value, onChange, presets, size }: Props): import("react").JSX.Element;
20
+ export {};
@@ -0,0 +1,17 @@
1
+ import { DateSinglePreset } from './types';
2
+ interface Props {
3
+ /** yyyy-MM-dd 또는 빈 문자열. */
4
+ value: string;
5
+ onChange: (next: string) => void;
6
+ ariaLabel?: string;
7
+ presets?: DateSinglePreset[];
8
+ size: "mini" | "small";
9
+ }
10
+ /**
11
+ * 단일 날짜 입력 — DateInput 1개 + 옵션 프리셋 버튼.
12
+ *
13
+ * SearchBoxDateRange의 단일 버전. 단일 SearchValues 키에 yyyy-MM-dd 직접 저장.
14
+ * 다른 필드 없이 dateSingle만 있는 페이지에서 SearchBox flex-wrap에 자연스럽게 배치된다.
15
+ */
16
+ export declare function SearchBoxDateSingle({ value, onChange, ariaLabel, presets, size, }: Props): import("react").JSX.Element;
17
+ export {};
@@ -0,0 +1,11 @@
1
+ import { SearchField } from './types';
2
+ interface Props {
3
+ field: SearchField;
4
+ value: string;
5
+ onChange: (value: string) => void;
6
+ onEnter?: () => void;
7
+ size: "mini" | "small";
8
+ }
9
+ /** 단일 필드 렌더. type별 컴포넌트 분기. SearchBox 본체에서 분리해 갓 컴포넌트 회피. */
10
+ export declare function SearchBoxField({ field, value, onChange, onEnter, size, }: Props): import("react").JSX.Element;
11
+ export {};
@@ -0,0 +1,24 @@
1
+ interface Props {
2
+ /** 라벨 — 비어 있을 땐 placeholder처럼 인풋 안에 위치, 포커스/값 있을 땐 상단 보더로 부유. */
3
+ label: string;
4
+ value: string;
5
+ onChange: (next: string) => void;
6
+ onEnter?: () => void;
7
+ size: "mini" | "small";
8
+ inputMode?: "text" | "numeric";
9
+ /** 우측 슬롯 — 검색 아이콘/액션 등. 키보드 포커스 색에 영향 X. */
10
+ trailing?: React.ReactNode;
11
+ }
12
+ /**
13
+ * SearchBox 전용 플로팅 라벨 인풋 (MUI outlined TextField 패턴).
14
+ *
15
+ * 동작:
16
+ * - 값 없음 + 미포커스: 라벨이 인풋 중앙 (placeholder 역할)
17
+ * - 포커스 OR 값 있음: 라벨이 상단 보더로 올라가며 작아짐
18
+ * - 보더는 라벨 부유 위치에 노치(틈)를 두지 않고 단순 white 배경으로 라벨이 덮어 가리는 방식.
19
+ * (배경이 투명/이미지일 땐 시안과 차이날 수 있지만 SearchBox 컨테이너는 페이지 배경 위라 OK.)
20
+ *
21
+ * 공용 Input을 건드리지 않기 위해 SearchBox 전용 wrapper로 격리.
22
+ */
23
+ export declare function SearchBoxFloatingInput({ label, value, onChange, onEnter, size, inputMode, trailing, }: Props): import("react").JSX.Element;
24
+ export {};
@@ -0,0 +1,19 @@
1
+ import { SelectOption } from '../../../components/select';
2
+ interface Props {
3
+ /** 라벨 — 미선택일 땐 인풋 안의 placeholder처럼, 선택/포커스 시 상단 보더로 부유. */
4
+ label: string;
5
+ options: SelectOption[];
6
+ value: string;
7
+ onChange: (next: string) => void;
8
+ size: "mini" | "small";
9
+ }
10
+ /**
11
+ * SearchBox 전용 플로팅 라벨 셀렉트.
12
+ *
13
+ * 단일 선택 — value가 빈 문자열이면 미선택(라벨이 안에 머무름).
14
+ * 선택되면 라벨이 상단 보더로 떠오르고 트리거에는 선택 옵션 라벨이 표시됨.
15
+ *
16
+ * SearchBoxFloatingInput과 시각적 일관성을 위해 동일한 사이즈/라벨 규칙 적용.
17
+ */
18
+ export declare function SearchBoxFloatingSelect({ label, options, value, onChange, size, }: Props): import("react").JSX.Element;
19
+ export {};
@@ -0,0 +1,14 @@
1
+ interface Props {
2
+ /** "yyyy-MM" 또는 빈 문자열. */
3
+ value: string;
4
+ onChange: (next: string) => void;
5
+ ariaLabel?: string;
6
+ size: "mini" | "small";
7
+ }
8
+ /**
9
+ * 년월 선택 — MonthPicker 1개. 단일 SearchValues 키에 "yyyy-MM" 직접 저장.
10
+ *
11
+ * dateSingle의 년월 버전. 미선택(빈 값)이면 "년월 선택" placeholder.
12
+ */
13
+ export declare function SearchBoxMonth({ value, onChange, ariaLabel, size }: Props): import("react").JSX.Element;
14
+ export {};
@@ -0,0 +1,25 @@
1
+ import { SelectOption } from '../../../components/select';
2
+ interface Props {
3
+ /** 라벨 — 미선택일 땐 트리거 안의 placeholder처럼, 선택/오픈 시 상단 보더로 부유. */
4
+ label: string;
5
+ options: SelectOption[];
6
+ /** CSV 직렬화된 값. 빈 문자열이면 선택 없음. */
7
+ value: string;
8
+ onChange: (csv: string) => void;
9
+ size: "mini" | "small";
10
+ }
11
+ /**
12
+ * SearchBox 전용 다중 선택. 트리거 버튼 + 드롭다운 체크박스 리스트.
13
+ *
14
+ * 값은 CSV(string) 직렬화 — URL/zod schema와의 호환을 위해 SearchValues `Record<string, string>`
15
+ * 시그니처를 유지한다. 빈 값이면 미선택, "A,B"면 두 항목 선택.
16
+ *
17
+ * SearchBoxFloatingInput/Select와 동일한 플로팅 라벨 UX. 보더와 라벨이 포커스/오픈 시
18
+ * primary-500으로 통일된다.
19
+ *
20
+ * number[] 전용 드롭다운은 적합하지 않아 별도 inline 컴포넌트로 둔다.
21
+ *
22
+ * 위치 계산은 floating-ui 위임 — autoUpdate가 스크롤/리사이즈 시 좌표를 자동 갱신.
23
+ */
24
+ export declare function SearchBoxMultiSelect({ label, options, value, onChange, size, }: Props): import("react").JSX.Element;
25
+ export {};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * SearchBox 모바일 바텀시트 내부 여부를 자식에게 알리는 컨텍스트.
3
+ *
4
+ * 자식 컴포넌트(예: SearchBoxDateRange)가 자체 popover/시트를 띄울 때, 부모 바텀시트가
5
+ * 이미 떠 있는지 알아야 한다. 떠 있으면 시트 두 개가 겹치는 어색함을 피하기 위해
6
+ * ModalSubView(drawer 변형)로 분기.
7
+ */
8
+ export declare const SearchBoxSheetContext: import('react').Context<boolean>;
@@ -0,0 +1,10 @@
1
+ import { DateRangePreset } from './types';
2
+ /** 당일 from/to. 페이지 진입 시 기본 range로 사용. */
3
+ export declare function getTodayDateRange(): {
4
+ from: string;
5
+ to: string;
6
+ };
7
+ /** "from~to" CSV 형태의 당일 SearchValues 값. */
8
+ export declare function getTodayDateRangeValue(): string;
9
+ /** 기본 4종 프리셋 — 전일 / 당일 / 당월 / 전월. 호출 시점의 날짜 기준으로 계산. */
10
+ export declare const DEFAULT_DATE_RANGE_PRESETS: DateRangePreset[];
@@ -0,0 +1,5 @@
1
+ export { SearchBox } from './SearchBox';
2
+ export { parseSearchValues, parseMultiSelectValue, } from './parseSearchValues';
3
+ export { parseDateRangeValue, serializeDateRangeValue, type DateRangeValue, } from './parseDateRange';
4
+ export { DEFAULT_DATE_RANGE_PRESETS, getTodayDateRange, getTodayDateRangeValue, } from './dateRangePresets';
5
+ export type { SearchField, SearchFieldText, SearchFieldSelect, SearchFieldMultiSelect, SearchFieldDateRange, SearchFieldDateSingle, DateRangePreset, DateSinglePreset, SearchValues, } from './types';