@reopt-ai/opt-ui 1.4.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.
- package/CHANGELOG.md +40 -0
- package/COMPONENT_CATALOG.md +3000 -0
- package/LICENSE +21 -0
- package/README.md +244 -0
- package/dist/chunk-3GWWZKX7.js +38 -0
- package/dist/chunk-AFF2HPE5.cjs +5008 -0
- package/dist/chunk-ELWICXYY.js +4745 -0
- package/dist/chunk-N4NDU5ET.cjs +4745 -0
- package/dist/chunk-ONE3C5RV.cjs +38 -0
- package/dist/chunk-QWBHD54V.js +3218 -0
- package/dist/chunk-RBM2RNC2.js +5008 -0
- package/dist/chunk-X5WCXJAF.cjs +3218 -0
- package/dist/core/index.cjs +324 -0
- package/dist/core/index.d.cts +5 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.js +324 -0
- package/dist/docs/01-getting-started.md +129 -0
- package/dist/docs/02-components/01-core.md +1841 -0
- package/dist/docs/02-components/02-visuals.md +11 -0
- package/dist/docs/02-components/03-shells.md +1361 -0
- package/dist/docs/02-components/04-surfaces.md +11 -0
- package/dist/docs/02-components/index.md +106 -0
- package/dist/docs/03-recipes/01-forms.md +471 -0
- package/dist/docs/03-recipes/02-dashboards.md +397 -0
- package/dist/docs/03-recipes/03-layouts.md +424 -0
- package/dist/docs/04-theming.md +232 -0
- package/dist/docs/05-migration/01-breaking-changes.md +117 -0
- package/dist/docs/05-migration/02-formstore.md +336 -0
- package/dist/docs/06-troubleshooting.md +119 -0
- package/dist/docs/index.md +71 -0
- package/dist/id-registry.cjs +1875 -0
- package/dist/id-registry.d.cts +27 -0
- package/dist/id-registry.d.ts +27 -0
- package/dist/id-registry.js +1875 -0
- package/dist/id-registry.json +3799 -0
- package/dist/index-BZ_lBlO1.d.ts +474 -0
- package/dist/index-BuvxoWHf.d.cts +474 -0
- package/dist/index-DlAcuvQp.d.cts +1686 -0
- package/dist/index-Slu5hOj1.d.ts +1686 -0
- package/dist/index.cjs +9959 -0
- package/dist/index.d.cts +2351 -0
- package/dist/index.d.ts +2351 -0
- package/dist/index.js +9959 -0
- package/dist/meta.cjs +6898 -0
- package/dist/meta.d.cts +36 -0
- package/dist/meta.d.ts +36 -0
- package/dist/meta.js +6869 -0
- package/dist/shells/index.cjs +65 -0
- package/dist/shells/index.d.cts +5 -0
- package/dist/shells/index.d.ts +5 -0
- package/dist/shells/index.js +65 -0
- package/dist/tailwind.css +401 -0
- package/dist/theme/presets/default.css +355 -0
- package/dist/theme/presets/minimal.css +354 -0
- package/dist/theme/presets/mono-dark.css +354 -0
- package/dist/theme/presets/natural.css +181 -0
- package/dist/theme/presets/pro.css +354 -0
- package/dist/types-D4-0lwaE.d.cts +298 -0
- package/dist/types-D4-0lwaE.d.ts +298 -0
- package/dist/visuals/index.cjs +4 -0
- package/dist/visuals/index.d.cts +1 -0
- package/dist/visuals/index.d.ts +1 -0
- package/dist/visuals/index.js +4 -0
- package/package.json +165 -0
|
@@ -0,0 +1,1841 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Core Components"
|
|
3
|
+
description: "59 Core layer components — props, examples, keyboard shortcuts."
|
|
4
|
+
version: "1.4.1"
|
|
5
|
+
generated: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Core Components (59)
|
|
9
|
+
|
|
10
|
+
## Input
|
|
11
|
+
|
|
12
|
+
| Component | Description | Key Exports |
|
|
13
|
+
| --------------- | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
14
|
+
| Input | 독립적인 텍스트 입력 컴포넌트. 레이블, 에러, 힌트, 아이콘 지원. | `Input` |
|
|
15
|
+
| Textarea | 멀티라인 텍스트 입력. Input과 동일한 API (label, error, hint). | `Textarea` |
|
|
16
|
+
| NumberInput | 숫자 입력 컴포넌트. +/- 버튼, nullable/clear, unit suffix, invalid draft alert, min/max, step, 키보드 화살표를 지원합니다. | `NumberInput` |
|
|
17
|
+
| Checkbox | 독립적인 체크박스 컴포넌트. 레이블, 설명, 그룹과 DOM property까지 동기화되는 indeterminate 상태를 지원합니다. | `Checkbox`, `CheckboxGroup` |
|
|
18
|
+
| RadioGroup | 독립적인 라디오 그룹 컴포넌트. 그룹 설명과 항목별 설명을 분리 연결하고 다양한 크기를 지원합니다. | `RadioGroup`, `Radio` |
|
|
19
|
+
| Switch | 토글 스위치 컴포넌트. 3가지 크기와 레이블/설명의 명시적 접근성 연결을 지원합니다. | `Switch` |
|
|
20
|
+
| Select | 드롭다운 선택 컴포넌트. 5-part anatomy: Root, Label, Trigger, Popover, Item. | `SelectRoot`, `SelectLabel`, `SelectTrigger`, `SelectPopover`, `SelectItem` |
|
|
21
|
+
| Combobox | 자동완성 검색 입력. 7 exports: Root, Input, Popover, Item, Group, GroupLabel, Empty. | `ComboboxRoot`, `ComboboxInput`, `ComboboxPopover`, `ComboboxItem`, `ComboboxGroup`, `ComboboxGroupLabel`, `ComboboxEmpty` |
|
|
22
|
+
| DateRangePicker | 날짜 범위 선택 컴포넌트. 프리셋, 달력 UI, 포커스 관리와 RTL 방향 탐색 아이콘을 지원합니다. | `DateRangePicker` |
|
|
23
|
+
| TagInput | 태그 입력 컴포넌트. 텍스트를 입력하고 Enter로 태그를 추가, Backspace로 삭제합니다. | `TagInput` |
|
|
24
|
+
| ColorPicker | 색상 선택 컴포넌트. 프리셋 팔레트와 hex 입력을 지원합니다. | `ColorPicker` |
|
|
25
|
+
| IconPicker | 아이콘 선택 컴포넌트. 검색, 그룹별 분류, semantic key 기반 Lucide 아이콘과 커스텀 ReactNode를 지원합니다. | `IconPicker` |
|
|
26
|
+
| Slider | 범위 슬라이더 입력. native range input 래핑, 범위로 정규화된 값/ARIA 상태, 값 표시와 포맷 함수를 지원합니다. | `Slider` |
|
|
27
|
+
|
|
28
|
+
### Input
|
|
29
|
+
|
|
30
|
+
> 독립적인 텍스트 입력 컴포넌트. 레이블, 에러, 힌트, 아이콘 지원.
|
|
31
|
+
|
|
32
|
+
**Import:** `import { Input } from "@reopt-ai/opt-ui"`
|
|
33
|
+
|
|
34
|
+
| Prop | Type | Required | Default | Description |
|
|
35
|
+
| ----------- | ----------- | -------- | ------- | ------------------------------------------- |
|
|
36
|
+
| `label` | `string` | | | 입력 필드 레이블 |
|
|
37
|
+
| `error` | `string` | | | 에러 메시지. 표시 시 aria-invalid=true 설정 |
|
|
38
|
+
| `hint` | `string` | | | 힌트 텍스트 (에러 없을 때만 표시) |
|
|
39
|
+
| `leftIcon` | `ReactNode` | | | 입력 필드 왼쪽에 표시할 아이콘 |
|
|
40
|
+
| `rightIcon` | `ReactNode` | | | 입력 필드 오른쪽에 표시할 아이콘 |
|
|
41
|
+
| `fullWidth` | `boolean` | | false | 전체 너비 사용 여부 |
|
|
42
|
+
|
|
43
|
+
**Examples:**
|
|
44
|
+
|
|
45
|
+
_기본 사용:_
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import { Input } from "@reopt-ai/opt-ui";
|
|
49
|
+
|
|
50
|
+
<Input
|
|
51
|
+
label="이메일"
|
|
52
|
+
hint="업무용 이메일을 입력하세요"
|
|
53
|
+
placeholder="user@example.com"
|
|
54
|
+
value={email}
|
|
55
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
56
|
+
/>;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
_FormStore 연동:_
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import {
|
|
63
|
+
useFormStore,
|
|
64
|
+
FormRoot,
|
|
65
|
+
FormField,
|
|
66
|
+
FormControl,
|
|
67
|
+
FormLabel,
|
|
68
|
+
Input,
|
|
69
|
+
} from "@reopt-ai/opt-ui";
|
|
70
|
+
|
|
71
|
+
const store = useFormStore({ defaultValues: { name: "" } });
|
|
72
|
+
|
|
73
|
+
<FormRoot store={store}>
|
|
74
|
+
<FormField name="name">
|
|
75
|
+
<FormLabel name="name">이름</FormLabel>
|
|
76
|
+
<FormControl name="name">
|
|
77
|
+
<Input />
|
|
78
|
+
</FormControl>
|
|
79
|
+
</FormField>
|
|
80
|
+
</FormRoot>;
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Textarea
|
|
84
|
+
|
|
85
|
+
> 멀티라인 텍스트 입력. Input과 동일한 API (label, error, hint).
|
|
86
|
+
|
|
87
|
+
**Import:** `import { Textarea } from "@reopt-ai/opt-ui"`
|
|
88
|
+
|
|
89
|
+
| Prop | Type | Required | Default | Description |
|
|
90
|
+
| ----------- | ------------------------------------------------ | -------- | ---------- | ---------------- |
|
|
91
|
+
| `label` | `string` | | | 입력 필드 레이블 |
|
|
92
|
+
| `error` | `string` | | | 에러 메시지 |
|
|
93
|
+
| `hint` | `string` | | | 힌트 텍스트 |
|
|
94
|
+
| `fullWidth` | `boolean` | | false | 전체 너비 사용 |
|
|
95
|
+
| `resize` | `"none" \| "vertical" \| "horizontal" \| "both"` | | "vertical" | 크기 조절 방향 |
|
|
96
|
+
| `rows` | `number` | | 4 | 표시 줄 수 |
|
|
97
|
+
|
|
98
|
+
### NumberInput
|
|
99
|
+
|
|
100
|
+
> 숫자 입력 컴포넌트. +/- 버튼, nullable/clear, unit suffix, invalid draft alert, min/max, step, 키보드 화살표를 지원합니다.
|
|
101
|
+
|
|
102
|
+
**Import:** `import { NumberInput } from "@reopt-ai/opt-ui"`
|
|
103
|
+
|
|
104
|
+
| Prop | Type | Required | Default | Description |
|
|
105
|
+
| ---------------- | --------------------------------- | -------- | ------- | ------------------------------------------------ |
|
|
106
|
+
| `value` | `number \| null` | | | 제어 모드 값. nullable=true일 때 null 허용 |
|
|
107
|
+
| `defaultValue` | `number \| null` | | 0 | 비제어 모드 초기값. nullable=true일 때 null 허용 |
|
|
108
|
+
| `onChange` | `(value: number \| null) => void` | | | 값 변경 핸들러 |
|
|
109
|
+
| `nullable` | `boolean` | | false | 빈 값을 null로 커밋할지 여부 |
|
|
110
|
+
| `clearable` | `boolean` | | false | nullable 값 지우기 버튼 표시 |
|
|
111
|
+
| `min` | `number` | | | 최솟값 |
|
|
112
|
+
| `max` | `number` | | | 최댓값 |
|
|
113
|
+
| `step` | `number` | | 1 | 증감 단위 |
|
|
114
|
+
| `label` | `string` | | | 라벨 텍스트 |
|
|
115
|
+
| `unit` | `ReactNode` | | | 입력값 단위 suffix |
|
|
116
|
+
| `disabled` | `boolean` | | | 비활성 상태 |
|
|
117
|
+
| `disabledReason` | `string` | | | aria-disabled 상태에서 노출할 비활성 사유 |
|
|
118
|
+
| `labels` | `NumberInputLabels` | | | 입력/증감/clear/invalid 접근성 문구 |
|
|
119
|
+
|
|
120
|
+
### Checkbox
|
|
121
|
+
|
|
122
|
+
> 독립적인 체크박스 컴포넌트. 레이블, 설명, 그룹과 DOM property까지 동기화되는 indeterminate 상태를 지원합니다.
|
|
123
|
+
|
|
124
|
+
**Import:** `import { Checkbox } from "@reopt-ai/opt-ui"`
|
|
125
|
+
|
|
126
|
+
**Checkbox:**
|
|
127
|
+
|
|
128
|
+
| Prop | Type | Required | Default | Description |
|
|
129
|
+
| ---------------- | ---------------------------- | -------- | ------- | ---------------------------------- |
|
|
130
|
+
| `label` | `string` | | | 체크박스 레이블 |
|
|
131
|
+
| `description` | `string` | | | 레이블 아래 설명 텍스트 |
|
|
132
|
+
| `checked` | `boolean` | | | 제어 모드: 체크 상태 |
|
|
133
|
+
| `defaultChecked` | `boolean` | | | 비제어 모드: 초기 체크 상태 |
|
|
134
|
+
| `onChange` | `(checked: boolean) => void` | | | 상태 변경 핸들러 |
|
|
135
|
+
| `size` | `"sm" \| "md" \| "lg"` | | "md" | 체크박스 크기 |
|
|
136
|
+
| `value` | `string` | | | CheckboxGroup 내에서 사용할 값 |
|
|
137
|
+
| `indeterminate` | `boolean` | | false | 불확정 상태 표시 (마이너스 아이콘) |
|
|
138
|
+
|
|
139
|
+
**CheckboxGroup:**
|
|
140
|
+
|
|
141
|
+
| Prop | Type | Required | Default | Description |
|
|
142
|
+
| -------------- | ---------------------------- | -------- | ---------- | ------------------------------ |
|
|
143
|
+
| `value` | `string[]` | | | 제어 모드: 선택된 값 배열 |
|
|
144
|
+
| `defaultValue` | `string[]` | | [] | 비제어 모드: 초기 선택 값 배열 |
|
|
145
|
+
| `onChange` | `(value: string[]) => void` | | | 선택 변경 핸들러 |
|
|
146
|
+
| `orientation` | `"horizontal" \| "vertical"` | | "vertical" | 레이아웃 방향 |
|
|
147
|
+
| `label` | `string` | | | 그룹 레이블 |
|
|
148
|
+
|
|
149
|
+
### RadioGroup
|
|
150
|
+
|
|
151
|
+
> 독립적인 라디오 그룹 컴포넌트. 그룹 설명과 항목별 설명을 분리 연결하고 다양한 크기를 지원합니다.
|
|
152
|
+
|
|
153
|
+
**Import:** `import { RadioGroup } from "@reopt-ai/opt-ui"`
|
|
154
|
+
|
|
155
|
+
**RadioGroup:**
|
|
156
|
+
|
|
157
|
+
| Prop | Type | Required | Default | Description |
|
|
158
|
+
| -------------- | ---------------------------- | -------- | ---------- | ------------------------- |
|
|
159
|
+
| `value` | `string` | | | 제어 모드: 선택된 값 |
|
|
160
|
+
| `defaultValue` | `string` | | "" | 비제어 모드: 초기 선택 값 |
|
|
161
|
+
| `onChange` | `(value: string) => void` | | | 선택 변경 핸들러 |
|
|
162
|
+
| `orientation` | `"horizontal" \| "vertical"` | | "vertical" | 레이아웃 방향 |
|
|
163
|
+
| `label` | `string` | | | 그룹 레이블 |
|
|
164
|
+
| `name` | `string` | | | 폼 제출 시 사용할 이름 |
|
|
165
|
+
|
|
166
|
+
**Radio:**
|
|
167
|
+
|
|
168
|
+
| Prop | Type | Required | Default | Description |
|
|
169
|
+
| ------------- | ---------------------- | -------- | ------- | ---------------------------------------------------------- |
|
|
170
|
+
| `value` | `string` | | | 라디오 값 (RadioGroup 안에서는 부모가 관리하므로 optional) |
|
|
171
|
+
| `label` | `string` | | | 라디오 레이블 |
|
|
172
|
+
| `description` | `string` | | | 레이블 아래 설명 텍스트 |
|
|
173
|
+
| `size` | `"sm" \| "md" \| "lg"` | | "md" | 라디오 크기 |
|
|
174
|
+
|
|
175
|
+
### Switch
|
|
176
|
+
|
|
177
|
+
> 토글 스위치 컴포넌트. 3가지 크기와 레이블/설명의 명시적 접근성 연결을 지원합니다.
|
|
178
|
+
|
|
179
|
+
**Import:** `import { Switch } from "@reopt-ai/opt-ui"`
|
|
180
|
+
|
|
181
|
+
| Prop | Type | Required | Default | Description |
|
|
182
|
+
| ---------------- | ---------------------------- | -------- | ------- | --------------------------- |
|
|
183
|
+
| `label` | `string` | | | 스위치 레이블 |
|
|
184
|
+
| `description` | `string` | | | 레이블 아래 설명 텍스트 |
|
|
185
|
+
| `checked` | `boolean` | | | 제어 모드: 체크 상태 |
|
|
186
|
+
| `defaultChecked` | `boolean` | | | 비제어 모드: 초기 체크 상태 |
|
|
187
|
+
| `onChange` | `(checked: boolean) => void` | | | 상태 변경 핸들러 |
|
|
188
|
+
| `size` | `"sm" \| "md" \| "lg"` | | "md" | 스위치 크기 |
|
|
189
|
+
| `disabled` | `boolean` | | | 비활성화 상태 |
|
|
190
|
+
|
|
191
|
+
### Select
|
|
192
|
+
|
|
193
|
+
> 드롭다운 선택 컴포넌트. 5-part anatomy: Root, Label, Trigger, Popover, Item.
|
|
194
|
+
|
|
195
|
+
**Import:** `import { SelectRoot } from "@reopt-ai/opt-ui"`
|
|
196
|
+
|
|
197
|
+
**SelectRoot:**
|
|
198
|
+
|
|
199
|
+
| Prop | Type | Required | Default | Description |
|
|
200
|
+
| --------------- | ------------------------------------- | -------- | ------- | -------------------------------------------------------- |
|
|
201
|
+
| `value` | `string \| string[]` | | | 제어 모드: 현재 선택 값 (multiple이면 string[]) |
|
|
202
|
+
| `onValueChange` | `(value: string \| string[]) => void` | | | 제어 모드: 값 변경 핸들러 |
|
|
203
|
+
| `defaultValue` | `string \| string[]` | | | 비제어 모드: 초기값 |
|
|
204
|
+
| `multiple` | `boolean` | | | 다중 선택 허용 (값이 string[]이 됨) |
|
|
205
|
+
| `name` | `string` | | | 폼 필드명. 선택값마다 hidden input을 렌더해 폼 전송 지원 |
|
|
206
|
+
|
|
207
|
+
**SelectLabel:**
|
|
208
|
+
|
|
209
|
+
| Prop | Type | Required | Default | Description |
|
|
210
|
+
| ---------- | ----------- | -------- | ------- | ------------- |
|
|
211
|
+
| `children` | `ReactNode` | Yes | | 레이블 텍스트 |
|
|
212
|
+
|
|
213
|
+
**SelectTrigger:**
|
|
214
|
+
|
|
215
|
+
| Prop | Type | Required | Default | Description |
|
|
216
|
+
| ----------- | ----------- | -------- | ------- | ---------------------------- |
|
|
217
|
+
| `children` | `ReactNode` | Yes | | 트리거 내용 (선택된 값 표시) |
|
|
218
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
219
|
+
|
|
220
|
+
**SelectPopover:**
|
|
221
|
+
|
|
222
|
+
| Prop | Type | Required | Default | Description |
|
|
223
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
224
|
+
| `children` | `ReactNode` | Yes | | SelectItem 목록 |
|
|
225
|
+
| `sameWidth` | `boolean` | | true | 트리거와 같은 너비 |
|
|
226
|
+
| `gutter` | `number` | | 4 | 트리거와의 간격 (px) |
|
|
227
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
228
|
+
|
|
229
|
+
**SelectItem:**
|
|
230
|
+
|
|
231
|
+
| Prop | Type | Required | Default | Description |
|
|
232
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
233
|
+
| `value` | `string` | Yes | | 옵션 값 |
|
|
234
|
+
| `children` | `ReactNode` | Yes | | 옵션 레이블 |
|
|
235
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
236
|
+
|
|
237
|
+
**Examples:**
|
|
238
|
+
|
|
239
|
+
_기본 선택:_
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
import {
|
|
243
|
+
SelectRoot,
|
|
244
|
+
SelectLabel,
|
|
245
|
+
SelectTrigger,
|
|
246
|
+
SelectPopover,
|
|
247
|
+
SelectItem,
|
|
248
|
+
} from "@reopt-ai/opt-ui";
|
|
249
|
+
|
|
250
|
+
<SelectRoot value={role} onValueChange={setRole}>
|
|
251
|
+
<SelectLabel>역할</SelectLabel>
|
|
252
|
+
<SelectTrigger>{role || "선택하세요"}</SelectTrigger>
|
|
253
|
+
<SelectPopover>
|
|
254
|
+
<SelectItem value="admin">관리자</SelectItem>
|
|
255
|
+
<SelectItem value="editor">편집자</SelectItem>
|
|
256
|
+
<SelectItem value="viewer">뷰어</SelectItem>
|
|
257
|
+
</SelectPopover>
|
|
258
|
+
</SelectRoot>;
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Combobox
|
|
262
|
+
|
|
263
|
+
> 자동완성 검색 입력. 7 exports: Root, Input, Popover, Item, Group, GroupLabel, Empty.
|
|
264
|
+
|
|
265
|
+
**Import:** `import { ComboboxRoot } from "@reopt-ai/opt-ui"`
|
|
266
|
+
|
|
267
|
+
**ComboboxRoot:**
|
|
268
|
+
|
|
269
|
+
| Prop | Type | Required | Default | Description |
|
|
270
|
+
| ------------------ | ------------------------- | -------- | ------- | -------------------------- |
|
|
271
|
+
| `setValue` | `(value: string) => void` | | | 입력값 변경 핸들러 |
|
|
272
|
+
| `resetValueOnHide` | `boolean` | | false | 팝오버 닫힐 때 입력값 리셋 |
|
|
273
|
+
|
|
274
|
+
**ComboboxInput:**
|
|
275
|
+
|
|
276
|
+
| Prop | Type | Required | Default | Description |
|
|
277
|
+
| ------------- | --------- | -------- | ------- | ---------------------- |
|
|
278
|
+
| `placeholder` | `string` | | | 플레이스홀더 텍스트 |
|
|
279
|
+
| `autoSelect` | `boolean` | | false | 첫 항목 자동 선택 |
|
|
280
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
281
|
+
|
|
282
|
+
**ComboboxPopover:**
|
|
283
|
+
|
|
284
|
+
| Prop | Type | Required | Default | Description |
|
|
285
|
+
| ----------- | ----------- | -------- | ------- | ----------------------- |
|
|
286
|
+
| `children` | `ReactNode` | Yes | | ComboboxItem/Group 목록 |
|
|
287
|
+
| `sameWidth` | `boolean` | | true | 입력과 같은 너비 |
|
|
288
|
+
| `gutter` | `number` | | 4 | 입력과의 간격 (px) |
|
|
289
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
290
|
+
|
|
291
|
+
**ComboboxItem:**
|
|
292
|
+
|
|
293
|
+
| Prop | Type | Required | Default | Description |
|
|
294
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
295
|
+
| `value` | `string` | Yes | | 항목 값 |
|
|
296
|
+
| `children` | `ReactNode` | Yes | | 항목 내용 |
|
|
297
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
298
|
+
|
|
299
|
+
**ComboboxGroup:**
|
|
300
|
+
|
|
301
|
+
| Prop | Type | Required | Default | Description |
|
|
302
|
+
| ---------- | ----------- | -------- | ------- | ---------------------- |
|
|
303
|
+
| `children` | `ReactNode` | Yes | | GroupLabel + Item 그룹 |
|
|
304
|
+
|
|
305
|
+
**ComboboxGroupLabel:**
|
|
306
|
+
|
|
307
|
+
| Prop | Type | Required | Default | Description |
|
|
308
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
309
|
+
| `children` | `ReactNode` | Yes | | 그룹 레이블 |
|
|
310
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
311
|
+
|
|
312
|
+
**ComboboxEmpty:**
|
|
313
|
+
|
|
314
|
+
| Prop | Type | Required | Default | Description |
|
|
315
|
+
| ----------- | ----------- | -------- | ------------------ | ---------------------- |
|
|
316
|
+
| `children` | `ReactNode` | | "결과가 없습니다." | 빈 상태 메시지 |
|
|
317
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
318
|
+
|
|
319
|
+
### DateRangePicker
|
|
320
|
+
|
|
321
|
+
> 날짜 범위 선택 컴포넌트. 프리셋, 달력 UI, 포커스 관리와 RTL 방향 탐색 아이콘을 지원합니다.
|
|
322
|
+
|
|
323
|
+
**Import:** `import { DateRangePicker } from "@reopt-ai/opt-ui"`
|
|
324
|
+
|
|
325
|
+
| Prop | Type | Required | Default | Description |
|
|
326
|
+
| --------------------- | ----------------------------------------------------- | -------- | ------------------- | ------------------------------------------------------ |
|
|
327
|
+
| `value` | `DateRange` | | | 제어 모드: { start: Date \| null, end: Date \| null } |
|
|
328
|
+
| `onChange` | `(range: DateRange) => void` | | | 범위 변경 핸들러 |
|
|
329
|
+
| `presets` | `DateRangePreset[]` | | | 빠른 선택 프리셋 배열 (기본: Today, Last 7/30/90 days) |
|
|
330
|
+
| `placeholder` | `string` | | "Select date range" | 미선택 시 표시 텍스트 |
|
|
331
|
+
| `label` | `string` | | | 입력 필드 레이블 |
|
|
332
|
+
| `disabled` | `boolean` | | false | 비활성화 상태 |
|
|
333
|
+
| `format` | `(date: Date) => string` | | | 날짜 포맷 함수 |
|
|
334
|
+
| `comparison` | `boolean` | | false | 비교 모드 활성화 |
|
|
335
|
+
| `comparisonMode` | `"previous" \| "year-over-year"` | | "previous" | 비교 기준 (이전 기간 / 전년 동기) |
|
|
336
|
+
| `onComparisonChange` | `(comparison: boolean, mode: ComparisonMode) => void` | | | 비교 모드 변경 콜백 |
|
|
337
|
+
| `showGranularity` | `boolean` | | false | 시간 단위 선택기 표시 |
|
|
338
|
+
| `granularity` | `"hour" \| "day" \| "week" \| "month"` | | "day" | 시간 단위 |
|
|
339
|
+
| `onGranularityChange` | `(granularity: DateGranularity) => void` | | | 시간 단위 변경 콜백 |
|
|
340
|
+
|
|
341
|
+
### TagInput
|
|
342
|
+
|
|
343
|
+
> 태그 입력 컴포넌트. 텍스트를 입력하고 Enter로 태그를 추가, Backspace로 삭제합니다.
|
|
344
|
+
|
|
345
|
+
**Import:** `import { TagInput } from "@reopt-ai/opt-ui"`
|
|
346
|
+
|
|
347
|
+
| Prop | Type | Required | Default | Description |
|
|
348
|
+
| ----------------- | -------------------------- | -------- | ---------------- | ----------------------------------------- |
|
|
349
|
+
| `value` | `string[]` | | | 제어 모드: 현재 태그 배열 |
|
|
350
|
+
| `onChange` | `(tags: string[]) => void` | | | 태그 변경 핸들러 |
|
|
351
|
+
| `placeholder` | `string` | | "Add tag..." | 입력 플레이스홀더 |
|
|
352
|
+
| `label` | `string` | | | 입력 필드 레이블 |
|
|
353
|
+
| `maxTags` | `number` | | | 최대 태그 수 |
|
|
354
|
+
| `disabled` | `boolean` | | false | 비활성화 상태 |
|
|
355
|
+
| `suggestions` | `string[]` | | | 자동완성 드롭다운에 표시할 추천 태그 목록 |
|
|
356
|
+
| `delimiters` | `(string \| RegExp)[]` | | [",", ";", "\n"] | 붙여넣기 시 태그를 분할할 구분자 목록 |
|
|
357
|
+
| `allowDuplicates` | `boolean` | | false | 중복 태그 허용 여부 |
|
|
358
|
+
|
|
359
|
+
### ColorPicker
|
|
360
|
+
|
|
361
|
+
> 색상 선택 컴포넌트. 프리셋 팔레트와 hex 입력을 지원합니다.
|
|
362
|
+
|
|
363
|
+
**Import:** `import { ColorPicker } from "@reopt-ai/opt-ui"`
|
|
364
|
+
|
|
365
|
+
| Prop | Type | Required | Default | Description |
|
|
366
|
+
| ---------- | ------------------------- | -------- | ------- | -------------------------------------- |
|
|
367
|
+
| `value` | `string` | | | 제어 모드: hex 색상 값 (예: '#3b82f6') |
|
|
368
|
+
| `onChange` | `(color: string) => void` | | | 색상 변경 핸들러 |
|
|
369
|
+
| `presets` | `string[]` | | | 프리셋 색상 배열 (기본 16색) |
|
|
370
|
+
| `label` | `string` | | | 입력 필드 레이블 |
|
|
371
|
+
| `disabled` | `boolean` | | false | 비활성화 상태 |
|
|
372
|
+
|
|
373
|
+
### IconPicker
|
|
374
|
+
|
|
375
|
+
> 아이콘 선택 컴포넌트. 검색, 그룹별 분류, semantic key 기반 Lucide 아이콘과 커스텀 ReactNode를 지원합니다.
|
|
376
|
+
|
|
377
|
+
**Import:** `import { IconPicker } from "@reopt-ai/opt-ui"`
|
|
378
|
+
|
|
379
|
+
| Prop | Type | Required | Default | Description |
|
|
380
|
+
| ---------- | -------------------------- | -------- | ------- | ------------------------------------------ |
|
|
381
|
+
| `value` | `string` | | | 제어 모드: 선택된 아이콘 ID |
|
|
382
|
+
| `onChange` | `(iconId: string) => void` | | | 아이콘 변경 핸들러 |
|
|
383
|
+
| `icons` | `IconDef[]` | | | 아이콘 목록 (기본 24개 Lucide 아이콘 제공) |
|
|
384
|
+
| `label` | `string` | | | 입력 필드 레이블 |
|
|
385
|
+
| `disabled` | `boolean` | | false | 비활성화 상태 |
|
|
386
|
+
|
|
387
|
+
### Slider
|
|
388
|
+
|
|
389
|
+
> 범위 슬라이더 입력. native range input 래핑, 범위로 정규화된 값/ARIA 상태, 값 표시와 포맷 함수를 지원합니다.
|
|
390
|
+
|
|
391
|
+
**Import:** `import { Slider } from "@reopt-ai/opt-ui"`
|
|
392
|
+
|
|
393
|
+
| Prop | Type | Required | Default | Description |
|
|
394
|
+
| -------------- | --------------------------- | -------- | ------- | ------------------ |
|
|
395
|
+
| `value` | `number` | | | 제어 모드 값 |
|
|
396
|
+
| `defaultValue` | `number` | | 0 | 비제어 모드 초기값 |
|
|
397
|
+
| `onChange` | `(value: number) => void` | | | 값 변경 핸들러 |
|
|
398
|
+
| `min` | `number` | | 0 | 최솟값 |
|
|
399
|
+
| `max` | `number` | | 100 | 최댓값 |
|
|
400
|
+
| `step` | `number` | | 1 | 증감 단위 |
|
|
401
|
+
| `label` | `string` | | | 레이블 텍스트 |
|
|
402
|
+
| `showValue` | `boolean` | | false | 현재 값 표시 여부 |
|
|
403
|
+
| `formatValue` | `(value: number) => string` | | | 값 포맷 함수 |
|
|
404
|
+
| `disabled` | `boolean` | | | 비활성화 |
|
|
405
|
+
| `className` | `string` | | | 최외곽 CSS 클래스 |
|
|
406
|
+
|
|
407
|
+
## Form Integration
|
|
408
|
+
|
|
409
|
+
| Component | Description | Key Exports |
|
|
410
|
+
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
411
|
+
| Form | 접근성 폼 시스템. opt-ui-primitives Form API 기반. 31 exports: FormRoot, FormProvider, FormGroup, FormGroupLabel, FormDescription, FormField, FormControl, FormInput, FormTextarea, FormSelect, FormSelectPopover, FormSelectItem, FormSwitch, FormLabel, FormError, FormSubmit, FormCheckbox, FormRadioGroup, FormRadio, FormPush, FormRemove, FormReset, FormNumberInput, FormSlider, FormStarRating, FormColorPicker, FormIconPicker, FormTagInput, FormDateRangePicker + useFormStore, useFormContext hooks. | `FormRoot`, `FormProvider`, `FormGroup`, `FormGroupLabel`, `FormDescription`, `FormField`, `FormControl`, `FormInput`, `FormTextarea`, `FormSelect`, `FormSelectPopover`, `FormSelectItem`, `FormSwitch`, `FormLabel`, `FormError`, `FormSubmit`, `FormCheckbox`, `FormRadioGroup`, `FormRadio`, `FormPush`, `FormRemove`, `FormReset`, `FormNumberInput`, `FormSlider`, `FormStarRating`, `FormColorPicker`, `FormIconPicker`, `FormTagInput`, `FormDateRangePicker`, `useFormStore`, `useFormContext` |
|
|
412
|
+
|
|
413
|
+
### Form
|
|
414
|
+
|
|
415
|
+
> 접근성 폼 시스템. opt-ui-primitives Form API 기반. 31 exports: FormRoot, FormProvider, FormGroup, FormGroupLabel, FormDescription, FormField, FormControl, FormInput, FormTextarea, FormSelect, FormSelectPopover, FormSelectItem, FormSwitch, FormLabel, FormError, FormSubmit, FormCheckbox, FormRadioGroup, FormRadio, FormPush, FormRemove, FormReset, FormNumberInput, FormSlider, FormStarRating, FormColorPicker, FormIconPicker, FormTagInput, FormDateRangePicker + useFormStore, useFormContext hooks.
|
|
416
|
+
|
|
417
|
+
**Import:** `import { FormRoot } from "@reopt-ai/opt-ui"`
|
|
418
|
+
|
|
419
|
+
**FormRoot:**
|
|
420
|
+
|
|
421
|
+
| Prop | Type | Required | Default | Description |
|
|
422
|
+
| ----------- | ----------- | -------- | ------- | ------------------------------------------------------------------------ |
|
|
423
|
+
| `store` | `FormStore` | | | useFormStore()로 생성한 폼 스토어. 미지정 시 자식의 FormProvider가 제공. |
|
|
424
|
+
| `children` | `ReactNode` | Yes | | 폼 필드들 |
|
|
425
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
426
|
+
|
|
427
|
+
**FormInput:**
|
|
428
|
+
|
|
429
|
+
| Prop | Type | Required | Default | Description |
|
|
430
|
+
| ------------- | -------- | -------- | ------- | ------------------------------- |
|
|
431
|
+
| `name` | `string` | Yes | | 폼 필드 이름 (스토어 키와 매칭) |
|
|
432
|
+
| `type` | `string` | | "text" | 입력 타입 |
|
|
433
|
+
| `placeholder` | `string` | | | 플레이스홀더 |
|
|
434
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
435
|
+
|
|
436
|
+
**FormTextarea:**
|
|
437
|
+
|
|
438
|
+
| Prop | Type | Required | Default | Description |
|
|
439
|
+
| ------------- | ------------------------------------------------ | -------- | ---------- | --------------- |
|
|
440
|
+
| `name` | `string` | Yes | | 폼 필드 이름 |
|
|
441
|
+
| `rows` | `number` | | 4 | 표시 줄 수 |
|
|
442
|
+
| `resize` | `"none" \| "vertical" \| "horizontal" \| "both"` | | "vertical" | 크기 조절 방향 |
|
|
443
|
+
| `placeholder` | `string` | | | 플레이스홀더 |
|
|
444
|
+
| `className` | `string` | | | 추가 CSS 클래스 |
|
|
445
|
+
|
|
446
|
+
**FormSelect:**
|
|
447
|
+
|
|
448
|
+
| Prop | Type | Required | Default | Description |
|
|
449
|
+
| ------------- | ----------- | -------- | ------- | ------------------------------ |
|
|
450
|
+
| `name` | `string` | Yes | | 폼 필드 이름 |
|
|
451
|
+
| `children` | `ReactNode` | Yes | | FormSelectPopover 등 자식 요소 |
|
|
452
|
+
| `placeholder` | `string` | | | 미선택 시 표시 텍스트 |
|
|
453
|
+
| `className` | `string` | | | 추가 CSS 클래스 |
|
|
454
|
+
|
|
455
|
+
**FormSelectPopover:**
|
|
456
|
+
|
|
457
|
+
| Prop | Type | Required | Default | Description |
|
|
458
|
+
| ----------- | ----------- | -------- | ------- | -------------------- |
|
|
459
|
+
| `children` | `ReactNode` | Yes | | FormSelectItem 목록 |
|
|
460
|
+
| `sameWidth` | `boolean` | | true | 트리거와 같은 너비 |
|
|
461
|
+
| `gutter` | `number` | | 4 | 트리거와의 간격 (px) |
|
|
462
|
+
|
|
463
|
+
**FormSelectItem:**
|
|
464
|
+
|
|
465
|
+
| Prop | Type | Required | Default | Description |
|
|
466
|
+
| ---------- | ----------- | -------- | ------- | ----------- |
|
|
467
|
+
| `value` | `string` | Yes | | 옵션 값 |
|
|
468
|
+
| `children` | `ReactNode` | Yes | | 옵션 레이블 |
|
|
469
|
+
|
|
470
|
+
**FormSwitch:**
|
|
471
|
+
|
|
472
|
+
| Prop | Type | Required | Default | Description |
|
|
473
|
+
| ---------- | ---------------------- | -------- | ------- | ------------- |
|
|
474
|
+
| `name` | `string` | Yes | | 폼 필드 이름 |
|
|
475
|
+
| `size` | `"sm" \| "md" \| "lg"` | | "md" | 스위치 크기 |
|
|
476
|
+
| `disabled` | `boolean` | | | 비활성화 상태 |
|
|
477
|
+
|
|
478
|
+
**FormLabel:**
|
|
479
|
+
|
|
480
|
+
| Prop | Type | Required | Default | Description |
|
|
481
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
482
|
+
| `name` | `string` | Yes | | 연결된 필드 이름 |
|
|
483
|
+
| `children` | `ReactNode` | Yes | | 레이블 텍스트 |
|
|
484
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
485
|
+
|
|
486
|
+
**FormError:**
|
|
487
|
+
|
|
488
|
+
| Prop | Type | Required | Default | Description |
|
|
489
|
+
| ----------- | -------- | -------- | ------- | ---------------------- |
|
|
490
|
+
| `name` | `string` | Yes | | 연결된 필드 이름 |
|
|
491
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
492
|
+
|
|
493
|
+
**FormSubmit:**
|
|
494
|
+
|
|
495
|
+
| Prop | Type | Required | Default | Description |
|
|
496
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
497
|
+
| `children` | `ReactNode` | Yes | | 버튼 텍스트 |
|
|
498
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
499
|
+
|
|
500
|
+
**FormProvider:**
|
|
501
|
+
|
|
502
|
+
| Prop | Type | Required | Default | Description |
|
|
503
|
+
| ---------- | ----------- | -------- | ------- | --------------------------------- |
|
|
504
|
+
| `store` | `FormStore` | Yes | | useFormStore()로 생성한 폼 스토어 |
|
|
505
|
+
| `children` | `ReactNode` | Yes | | 자식 폼 요소 |
|
|
506
|
+
|
|
507
|
+
**FormGroup:**
|
|
508
|
+
|
|
509
|
+
| Prop | Type | Required | Default | Description |
|
|
510
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
511
|
+
| `children` | `ReactNode` | Yes | | 그룹 내 필드들 |
|
|
512
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
513
|
+
|
|
514
|
+
**FormGroupLabel:**
|
|
515
|
+
|
|
516
|
+
| Prop | Type | Required | Default | Description |
|
|
517
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
518
|
+
| `children` | `ReactNode` | Yes | | 그룹 레이블 텍스트 |
|
|
519
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
520
|
+
|
|
521
|
+
**FormDescription:**
|
|
522
|
+
|
|
523
|
+
| Prop | Type | Required | Default | Description |
|
|
524
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
525
|
+
| `name` | `string` | Yes | | 연결된 필드 이름 |
|
|
526
|
+
| `children` | `ReactNode` | Yes | | 도움말 텍스트 |
|
|
527
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
528
|
+
|
|
529
|
+
**FormField:**
|
|
530
|
+
|
|
531
|
+
| Prop | Type | Required | Default | Description |
|
|
532
|
+
| ----------- | ----------- | -------- | ------- | ------------------------ |
|
|
533
|
+
| `name` | `string` | Yes | | 필드 이름 |
|
|
534
|
+
| `children` | `ReactNode` | Yes | | label + input + error 등 |
|
|
535
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
536
|
+
|
|
537
|
+
**FormControl:**
|
|
538
|
+
|
|
539
|
+
| Prop | Type | Required | Default | Description |
|
|
540
|
+
| ----------- | -------- | -------- | ------- | ---------------------- |
|
|
541
|
+
| `name` | `string` | Yes | | 연결된 필드 이름 |
|
|
542
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
543
|
+
|
|
544
|
+
**FormCheckbox:**
|
|
545
|
+
|
|
546
|
+
| Prop | Type | Required | Default | Description |
|
|
547
|
+
| ----------- | -------- | -------- | ------- | ------------------------ |
|
|
548
|
+
| `name` | `string` | Yes | | 폼 필드 이름 (스토어 키) |
|
|
549
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
550
|
+
|
|
551
|
+
**FormRadioGroup:**
|
|
552
|
+
|
|
553
|
+
| Prop | Type | Required | Default | Description |
|
|
554
|
+
| ----------- | ----------- | -------- | ------- | ------------------------ |
|
|
555
|
+
| `name` | `string` | Yes | | 폼 필드 이름 (스토어 키) |
|
|
556
|
+
| `children` | `ReactNode` | Yes | | FormRadio 목록 |
|
|
557
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
558
|
+
|
|
559
|
+
**FormRadio:**
|
|
560
|
+
|
|
561
|
+
| Prop | Type | Required | Default | Description |
|
|
562
|
+
| ----------- | -------- | -------- | ------- | ------------------------ |
|
|
563
|
+
| `name` | `string` | Yes | | 폼 필드 이름 (스토어 키) |
|
|
564
|
+
| `value` | `string` | Yes | | 라디오 값 |
|
|
565
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
566
|
+
|
|
567
|
+
**FormPush:**
|
|
568
|
+
|
|
569
|
+
| Prop | Type | Required | Default | Description |
|
|
570
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
571
|
+
| `name` | `string` | Yes | | 배열 필드 이름 |
|
|
572
|
+
| `value` | `unknown` | Yes | | 추가할 기본값 |
|
|
573
|
+
| `children` | `ReactNode` | Yes | | 버튼 텍스트 |
|
|
574
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
575
|
+
|
|
576
|
+
**FormRemove:**
|
|
577
|
+
|
|
578
|
+
| Prop | Type | Required | Default | Description |
|
|
579
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
580
|
+
| `name` | `string` | Yes | | 배열 필드 이름 |
|
|
581
|
+
| `index` | `number` | Yes | | 제거할 인덱스 |
|
|
582
|
+
| `children` | `ReactNode` | Yes | | 버튼 텍스트 |
|
|
583
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
584
|
+
|
|
585
|
+
**FormReset:**
|
|
586
|
+
|
|
587
|
+
| Prop | Type | Required | Default | Description |
|
|
588
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
589
|
+
| `children` | `ReactNode` | Yes | | 버튼 텍스트 |
|
|
590
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
591
|
+
|
|
592
|
+
**useFormContext:**
|
|
593
|
+
|
|
594
|
+
| Prop | Type | Required | Default | Description |
|
|
595
|
+
| ---- | ---- | -------- | ------- | ----------- |
|
|
596
|
+
|
|
597
|
+
**useFormStore:**
|
|
598
|
+
|
|
599
|
+
| Prop | Type | Required | Default | Description |
|
|
600
|
+
| --------------- | ------------------------- | -------- | ------- | ----------- |
|
|
601
|
+
| `defaultValues` | `Record<string, unknown>` | | | 초기 폼 값 |
|
|
602
|
+
|
|
603
|
+
**Examples:**
|
|
604
|
+
|
|
605
|
+
_기본 폼:_
|
|
606
|
+
|
|
607
|
+
```tsx
|
|
608
|
+
import {
|
|
609
|
+
useFormStore,
|
|
610
|
+
FormRoot,
|
|
611
|
+
FormField,
|
|
612
|
+
FormControl,
|
|
613
|
+
FormLabel,
|
|
614
|
+
FormError,
|
|
615
|
+
FormSubmit,
|
|
616
|
+
Input,
|
|
617
|
+
} from "@reopt-ai/opt-ui";
|
|
618
|
+
|
|
619
|
+
const store = useFormStore({ defaultValues: { name: "", email: "" } });
|
|
620
|
+
|
|
621
|
+
<FormRoot store={store}>
|
|
622
|
+
<FormField name="name">
|
|
623
|
+
<FormLabel name="name">이름</FormLabel>
|
|
624
|
+
<FormControl name="name">
|
|
625
|
+
<Input />
|
|
626
|
+
</FormControl>
|
|
627
|
+
<FormError name="name" />
|
|
628
|
+
</FormField>
|
|
629
|
+
<FormSubmit>저장</FormSubmit>
|
|
630
|
+
</FormRoot>;
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
_검증 + 비동기 제출:_
|
|
634
|
+
|
|
635
|
+
```tsx
|
|
636
|
+
import {
|
|
637
|
+
useFormStore,
|
|
638
|
+
FormRoot,
|
|
639
|
+
FormField,
|
|
640
|
+
FormControl,
|
|
641
|
+
FormLabel,
|
|
642
|
+
FormError,
|
|
643
|
+
FormSubmit,
|
|
644
|
+
Input,
|
|
645
|
+
} from "@reopt-ai/opt-ui";
|
|
646
|
+
|
|
647
|
+
const store = useFormStore({
|
|
648
|
+
defaultValues: { email: "" },
|
|
649
|
+
validate: (values) => {
|
|
650
|
+
const errors: Record<string, string> = {};
|
|
651
|
+
if (!values.email) errors.email = "이메일을 입력하세요";
|
|
652
|
+
return errors;
|
|
653
|
+
},
|
|
654
|
+
onSubmit: async (values) => {
|
|
655
|
+
await fetch("/api/submit", {
|
|
656
|
+
method: "POST",
|
|
657
|
+
body: JSON.stringify(values),
|
|
658
|
+
});
|
|
659
|
+
},
|
|
660
|
+
});
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
_schemaValidator (Zod):_
|
|
664
|
+
|
|
665
|
+
```tsx
|
|
666
|
+
import { useFormStore, schemaValidator } from "@reopt-ai/opt-ui";
|
|
667
|
+
import { z } from "zod";
|
|
668
|
+
|
|
669
|
+
const schema = z.object({
|
|
670
|
+
name: z.string().min(1, "필수 항목"),
|
|
671
|
+
age: z.number().min(0, "0 이상"),
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
const store = useFormStore({
|
|
675
|
+
defaultValues: { name: "", age: 0 },
|
|
676
|
+
validate: schemaValidator(schema),
|
|
677
|
+
});
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
## Display
|
|
681
|
+
|
|
682
|
+
| Component | Description | Key Exports |
|
|
683
|
+
| -------------- | --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
|
684
|
+
| Kbd | 키보드 단축키를 시각적으로 표시하는 인라인 뱃지 컴포넌트. | `Kbd` |
|
|
685
|
+
| Button | 접근성 버튼 컴포넌트. 4가지 변형(primary, secondary, ghost, danger), 3가지 크기, 로딩/아이콘과 aria-busy 상태를 지원합니다. | `Button` |
|
|
686
|
+
| Badge | 인라인 상태 뱃지. 5가지 색상 변형, 상태 점(dot) 옵션 지원. | `Badge` |
|
|
687
|
+
| Alert | 알림 메시지 컴포넌트. 4가지 변형(info, success, warning, error), 제목/본문/닫기 버튼 지원. | `Alert` |
|
|
688
|
+
| Spinner | 로딩 상태 표시 스피너. 3가지 크기와 장식용 aria-hidden 모드를 지원합니다. | `Spinner` |
|
|
689
|
+
| LoadingOverlay | 로딩 오버레이. 중복 status 없이 하나의 aria-busy 라이브 영역으로 콘텐츠 위 로딩 상태를 표시합니다. | `LoadingOverlay` |
|
|
690
|
+
| Progress | 진행률 표시. Linear/Circular, determinate/indeterminate 변형과 안전하게 보정된 ARIA 값을 지원합니다. | `Progress`, `CircularProgress` |
|
|
691
|
+
| Avatar | 사용자 아바타. 이미지, 이니셜 자동 생성, 스크린 리더에 노출되는 상태 인디케이터, 그룹을 지원합니다. | `Avatar`, `AvatarGroup` |
|
|
692
|
+
| Skeleton | 로딩 플레이스홀더. text/circular/rectangular 변형. 프리셋 컴포넌트 포함. | `Skeleton`, `SkeletonText`, `SkeletonAvatar`, `SkeletonCard`, `SkeletonTable` |
|
|
693
|
+
| Card | 범용 카드 컨테이너. Header, Title, Description, Content, Footer 하위 컴포넌트 포함. | `Card`, `CardHeader`, `CardTitle`, `CardDescription`, `CardContent`, `CardFooter` |
|
|
694
|
+
| Breadcrumb | 현재 위치를 표시하고 계층 탐색을 제공하는 컴포넌트. | `Breadcrumb` |
|
|
695
|
+
| EmptyState | 데이터가 없을 때 표시하는 빈 상태 컴포넌트. 아이콘, 제목, 설명, 액션 버튼 지원. | `EmptyState` |
|
|
696
|
+
| StatCard | 트렌드 방향과 변화량을 표시하는 통계 카드. | `StatCard` |
|
|
697
|
+
| Logo | 아이콘+텍스트 조합, 이미지, 링크 래핑을 지원하는 로고 컴포넌트. Sidebar 등에서 활용. | `Logo` |
|
|
698
|
+
|
|
699
|
+
### Kbd
|
|
700
|
+
|
|
701
|
+
> 키보드 단축키를 시각적으로 표시하는 인라인 뱃지 컴포넌트.
|
|
702
|
+
|
|
703
|
+
**Import:** `import { Kbd } from "@reopt-ai/opt-ui"`
|
|
704
|
+
|
|
705
|
+
| Prop | Type | Required | Default | Description |
|
|
706
|
+
| ---------- | ----------- | -------- | ------- | -------------------- |
|
|
707
|
+
| `children` | `ReactNode` | Yes | | 표시할 단축키 텍스트 |
|
|
708
|
+
|
|
709
|
+
### Button
|
|
710
|
+
|
|
711
|
+
> 접근성 버튼 컴포넌트. 4가지 변형(primary, secondary, ghost, danger), 3가지 크기, 로딩/아이콘과 aria-busy 상태를 지원합니다.
|
|
712
|
+
|
|
713
|
+
**Import:** `import { Button } from "@reopt-ai/opt-ui"`
|
|
714
|
+
|
|
715
|
+
| Prop | Type | Required | Default | Description |
|
|
716
|
+
| ----------- | ------------------------------------------------- | -------- | --------- | ----------------------------------------- |
|
|
717
|
+
| `variant` | `"primary" \| "secondary" \| "ghost" \| "danger"` | | "primary" | 버튼 스타일 변형 |
|
|
718
|
+
| `size` | `"sm" \| "md" \| "lg"` | | "md" | 버튼 크기 |
|
|
719
|
+
| `loading` | `boolean` | | false | 로딩 상태. true면 스피너 표시 및 비활성화 |
|
|
720
|
+
| `leftIcon` | `ReactNode` | | | 버튼 텍스트 왼쪽에 표시할 아이콘 |
|
|
721
|
+
| `rightIcon` | `ReactNode` | | | 버튼 텍스트 오른쪽에 표시할 아이콘 |
|
|
722
|
+
| `disabled` | `boolean` | | | 비활성화 상태 |
|
|
723
|
+
|
|
724
|
+
**Examples:**
|
|
725
|
+
|
|
726
|
+
_버튼 변형:_
|
|
727
|
+
|
|
728
|
+
```tsx
|
|
729
|
+
import { Button } from "@reopt-ai/opt-ui";
|
|
730
|
+
|
|
731
|
+
<Button variant="primary">Primary</Button>
|
|
732
|
+
<Button variant="secondary">Secondary</Button>
|
|
733
|
+
<Button variant="ghost">Ghost</Button>
|
|
734
|
+
<Button variant="danger" disabled>Danger</Button>
|
|
735
|
+
<Button variant="primary" loading>저장 중...</Button>
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
### Badge
|
|
739
|
+
|
|
740
|
+
> 인라인 상태 뱃지. 5가지 색상 변형, 상태 점(dot) 옵션 지원.
|
|
741
|
+
|
|
742
|
+
**Import:** `import { Badge } from "@reopt-ai/opt-ui"`
|
|
743
|
+
|
|
744
|
+
| Prop | Type | Required | Default | Description |
|
|
745
|
+
| -------------- | ---------------------------------------------------------- | -------- | --------- | -------------------------------------------- |
|
|
746
|
+
| `variant` | `"default" \| "success" \| "warning" \| "error" \| "info"` | | "default" | 뱃지 색상 변형 |
|
|
747
|
+
| `size` | `"sm" \| "md"` | | "md" | 뱃지 크기 |
|
|
748
|
+
| `dot` | `boolean` | | false | 상태 점 표시 여부 |
|
|
749
|
+
| `progress` | `number` | | | 원형 프로그레스 값 (0-100). 설정 시 dot 무시 |
|
|
750
|
+
| `progressSize` | `number` | | 16 | 프로그레스 링 SVG 크기 (px) |
|
|
751
|
+
|
|
752
|
+
### Alert
|
|
753
|
+
|
|
754
|
+
> 알림 메시지 컴포넌트. 4가지 변형(info, success, warning, error), 제목/본문/닫기 버튼 지원.
|
|
755
|
+
|
|
756
|
+
**Import:** `import { Alert } from "@reopt-ai/opt-ui"`
|
|
757
|
+
|
|
758
|
+
| Prop | Type | Required | Default | Description |
|
|
759
|
+
| ------------- | --------------------------------------------- | -------- | ------- | ----------------------------------------------------- |
|
|
760
|
+
| `variant` | `"info" \| "success" \| "warning" \| "error"` | | "info" | 알림 변형 (색상 및 아이콘 결정) |
|
|
761
|
+
| `title` | `string` | | | 알림 제목 |
|
|
762
|
+
| `icon` | `ReactNode` | | | 커스텀 아이콘. 미지정 시 변형에 따른 기본 아이콘 사용 |
|
|
763
|
+
| `dismissible` | `boolean` | | false | 닫기 버튼 표시 여부 |
|
|
764
|
+
| `onDismiss` | `() => void` | | | 닫기 버튼 클릭 핸들러 |
|
|
765
|
+
|
|
766
|
+
### Spinner
|
|
767
|
+
|
|
768
|
+
> 로딩 상태 표시 스피너. 3가지 크기와 장식용 aria-hidden 모드를 지원합니다.
|
|
769
|
+
|
|
770
|
+
**Import:** `import { Spinner } from "@reopt-ai/opt-ui"`
|
|
771
|
+
|
|
772
|
+
| Prop | Type | Required | Default | Description |
|
|
773
|
+
| ------ | ---------------------- | -------- | ------- | ----------- |
|
|
774
|
+
| `size` | `"sm" \| "md" \| "lg"` | | "md" | 스피너 크기 |
|
|
775
|
+
|
|
776
|
+
### LoadingOverlay
|
|
777
|
+
|
|
778
|
+
> 로딩 오버레이. 중복 status 없이 하나의 aria-busy 라이브 영역으로 콘텐츠 위 로딩 상태를 표시합니다.
|
|
779
|
+
|
|
780
|
+
**Import:** `import { LoadingOverlay } from "@reopt-ai/opt-ui"`
|
|
781
|
+
**Dependencies:** spinner (core)
|
|
782
|
+
|
|
783
|
+
| Prop | Type | Required | Default | Description |
|
|
784
|
+
| ---------- | ----------- | -------- | ---------- | ------------- |
|
|
785
|
+
| `loading` | `boolean` | Yes | | 로딩 상태 |
|
|
786
|
+
| `children` | `ReactNode` | Yes | | 감싸는 콘텐츠 |
|
|
787
|
+
| `label` | `string` | | "Loading…" | 로딩 텍스트 |
|
|
788
|
+
|
|
789
|
+
### Progress
|
|
790
|
+
|
|
791
|
+
> 진행률 표시. Linear/Circular, determinate/indeterminate 변형과 안전하게 보정된 ARIA 값을 지원합니다.
|
|
792
|
+
|
|
793
|
+
**Import:** `import { Progress } from "@reopt-ai/opt-ui"`
|
|
794
|
+
|
|
795
|
+
**Progress:**
|
|
796
|
+
|
|
797
|
+
| Prop | Type | Required | Default | Description |
|
|
798
|
+
| --------------- | ------------------------------------------------ | -------- | --------- | ------------------------------------ |
|
|
799
|
+
| `value` | `number` | | | 현재 값. 생략하면 indeterminate 상태 |
|
|
800
|
+
| `max` | `number` | | 100 | 최대 값 |
|
|
801
|
+
| `size` | `"sm" \| "md" \| "lg"` | | "md" | 진행바 높이 |
|
|
802
|
+
| `variant` | `"default" \| "success" \| "warning" \| "error"` | | "default" | 색상 변형 |
|
|
803
|
+
| `showLabel` | `boolean` | | false | 퍼센트 표시 |
|
|
804
|
+
| `label` | `string` | | | 레이블 텍스트 |
|
|
805
|
+
| `animated` | `boolean` | | true | 애니메이션 활성화 |
|
|
806
|
+
| `indeterminate` | `boolean` | | false | 값을 알 수 없는 진행 상태 |
|
|
807
|
+
|
|
808
|
+
**CircularProgress:**
|
|
809
|
+
|
|
810
|
+
| Prop | Type | Required | Default | Description |
|
|
811
|
+
| --------------- | ------------------------------------------------ | -------- | --------- | ------------------------------------ |
|
|
812
|
+
| `value` | `number` | | | 현재 값. 생략하면 indeterminate 상태 |
|
|
813
|
+
| `max` | `number` | | 100 | 최대 값 |
|
|
814
|
+
| `size` | `number` | | 48 | 원 크기 (px) |
|
|
815
|
+
| `strokeWidth` | `number` | | 4 | 선 두께 |
|
|
816
|
+
| `variant` | `"default" \| "success" \| "warning" \| "error"` | | "default" | 색상 변형 |
|
|
817
|
+
| `showLabel` | `boolean` | | false | 중앙에 퍼센트 표시 |
|
|
818
|
+
| `label` | `string` | | | 접근성 레이블 |
|
|
819
|
+
| `indeterminate` | `boolean` | | false | 값을 알 수 없는 진행 상태 |
|
|
820
|
+
|
|
821
|
+
### Avatar
|
|
822
|
+
|
|
823
|
+
> 사용자 아바타. 이미지, 이니셜 자동 생성, 스크린 리더에 노출되는 상태 인디케이터, 그룹을 지원합니다.
|
|
824
|
+
|
|
825
|
+
**Import:** `import { Avatar } from "@reopt-ai/opt-ui"`
|
|
826
|
+
|
|
827
|
+
**Avatar:**
|
|
828
|
+
|
|
829
|
+
| Prop | Type | Required | Default | Description |
|
|
830
|
+
| ---------- | ------------------------------------------- | -------- | ------- | -------------------------------------- |
|
|
831
|
+
| `src` | `string` | | | 이미지 URL |
|
|
832
|
+
| `alt` | `string` | | | 이미지 대체 텍스트 |
|
|
833
|
+
| `name` | `string` | | | 사용자 이름 (이니셜 생성 및 색상 결정) |
|
|
834
|
+
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | | "md" | 아바타 크기 |
|
|
835
|
+
| `fallback` | `ReactNode` | | | 이미지 실패 시 표시할 콘텐츠 |
|
|
836
|
+
| `status` | `"online" \| "offline" \| "busy" \| "away"` | | | 상태 인디케이터 |
|
|
837
|
+
|
|
838
|
+
**AvatarGroup:**
|
|
839
|
+
|
|
840
|
+
| Prop | Type | Required | Default | Description |
|
|
841
|
+
| ---------- | -------------------------------------- | -------- | ------- | -------------- |
|
|
842
|
+
| `max` | `number` | | 4 | 최대 표시 개수 |
|
|
843
|
+
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | | "md" | 아바타 크기 |
|
|
844
|
+
| `children` | `ReactNode` | Yes | | Avatar 요소들 |
|
|
845
|
+
|
|
846
|
+
### Skeleton
|
|
847
|
+
|
|
848
|
+
> 로딩 플레이스홀더. text/circular/rectangular 변형. 프리셋 컴포넌트 포함.
|
|
849
|
+
|
|
850
|
+
**Import:** `import { Skeleton } from "@reopt-ai/opt-ui"`
|
|
851
|
+
|
|
852
|
+
**Skeleton:**
|
|
853
|
+
|
|
854
|
+
| Prop | Type | Required | Default | Description |
|
|
855
|
+
| ---------- | --------------------------------------- | -------- | ------- | ----------------------- |
|
|
856
|
+
| `variant` | `"text" \| "circular" \| "rectangular"` | | "text" | 스켈레톤 형태 |
|
|
857
|
+
| `width` | `string \| number` | | | 너비 (px 또는 CSS 값) |
|
|
858
|
+
| `height` | `string \| number` | | | 높이 (px 또는 CSS 값) |
|
|
859
|
+
| `lines` | `number` | | 1 | text variant일 때 줄 수 |
|
|
860
|
+
| `animated` | `boolean` | | true | 펄스 애니메이션 활성화 |
|
|
861
|
+
|
|
862
|
+
**SkeletonText:**
|
|
863
|
+
|
|
864
|
+
| Prop | Type | Required | Default | Description |
|
|
865
|
+
| ------- | -------- | -------- | ------- | ------------ |
|
|
866
|
+
| `lines` | `number` | | 3 | 텍스트 줄 수 |
|
|
867
|
+
|
|
868
|
+
**SkeletonAvatar:**
|
|
869
|
+
|
|
870
|
+
| Prop | Type | Required | Default | Description |
|
|
871
|
+
| ------ | -------- | -------- | ------- | ---------------- |
|
|
872
|
+
| `size` | `number` | | 40 | 아바타 크기 (px) |
|
|
873
|
+
|
|
874
|
+
**SkeletonTable:**
|
|
875
|
+
|
|
876
|
+
| Prop | Type | Required | Default | Description |
|
|
877
|
+
| --------- | -------- | -------- | ------- | ------------ |
|
|
878
|
+
| `rows` | `number` | | 5 | 테이블 행 수 |
|
|
879
|
+
| `columns` | `number` | | 4 | 테이블 열 수 |
|
|
880
|
+
|
|
881
|
+
### Card
|
|
882
|
+
|
|
883
|
+
> 범용 카드 컨테이너. Header, Title, Description, Content, Footer 하위 컴포넌트 포함.
|
|
884
|
+
|
|
885
|
+
**Import:** `import { Card } from "@reopt-ai/opt-ui"`
|
|
886
|
+
|
|
887
|
+
**Card:**
|
|
888
|
+
|
|
889
|
+
| Prop | Type | Required | Default | Description |
|
|
890
|
+
| ------------------ | ----------------------------------- | -------- | --------- | ------------------------------ |
|
|
891
|
+
| `variant` | `"default" \| "outline" \| "ghost"` | | "default" | 카드 스타일 변형 |
|
|
892
|
+
| `padding` | `"none" \| "sm" \| "md" \| "lg"` | | "md" | 내부 패딩 크기 |
|
|
893
|
+
| `selectable` | `boolean` | | false | 선택 가능 모드 활성화 |
|
|
894
|
+
| `selected` | `boolean` | | | 선택 상태 (selectable=true 시) |
|
|
895
|
+
| `onSelectedChange` | `(selected: boolean) => void` | | | 선택 상태 변경 콜백 |
|
|
896
|
+
|
|
897
|
+
**CardHeader:**
|
|
898
|
+
|
|
899
|
+
| Prop | Type | Required | Default | Description |
|
|
900
|
+
| ---- | ---- | -------- | ------- | ----------- |
|
|
901
|
+
|
|
902
|
+
**CardTitle:**
|
|
903
|
+
|
|
904
|
+
| Prop | Type | Required | Default | Description |
|
|
905
|
+
| ---- | ---- | -------- | ------- | ----------- |
|
|
906
|
+
|
|
907
|
+
**CardDescription:**
|
|
908
|
+
|
|
909
|
+
| Prop | Type | Required | Default | Description |
|
|
910
|
+
| ---- | ---- | -------- | ------- | ----------- |
|
|
911
|
+
|
|
912
|
+
**CardContent:**
|
|
913
|
+
|
|
914
|
+
| Prop | Type | Required | Default | Description |
|
|
915
|
+
| ---- | ---- | -------- | ------- | ----------- |
|
|
916
|
+
|
|
917
|
+
**CardFooter:**
|
|
918
|
+
|
|
919
|
+
| Prop | Type | Required | Default | Description |
|
|
920
|
+
| ---- | ---- | -------- | ------- | ----------- |
|
|
921
|
+
|
|
922
|
+
**Examples:**
|
|
923
|
+
|
|
924
|
+
_카드 레이아웃:_
|
|
925
|
+
|
|
926
|
+
```tsx
|
|
927
|
+
import {
|
|
928
|
+
Card,
|
|
929
|
+
CardHeader,
|
|
930
|
+
CardTitle,
|
|
931
|
+
CardDescription,
|
|
932
|
+
CardContent,
|
|
933
|
+
} from "@reopt-ai/opt-ui";
|
|
934
|
+
|
|
935
|
+
<Card>
|
|
936
|
+
<CardHeader>
|
|
937
|
+
<CardTitle>프로젝트 요약</CardTitle>
|
|
938
|
+
<CardDescription>최근 7일간 활동 현황</CardDescription>
|
|
939
|
+
</CardHeader>
|
|
940
|
+
<CardContent>
|
|
941
|
+
<p>활성 사용자: 1,234명</p>
|
|
942
|
+
</CardContent>
|
|
943
|
+
</Card>;
|
|
944
|
+
```
|
|
945
|
+
|
|
946
|
+
### Breadcrumb
|
|
947
|
+
|
|
948
|
+
> 현재 위치를 표시하고 계층 탐색을 제공하는 컴포넌트.
|
|
949
|
+
|
|
950
|
+
**Import:** `import { Breadcrumb } from "@reopt-ai/opt-ui"`
|
|
951
|
+
|
|
952
|
+
| Prop | Type | Required | Default | Description |
|
|
953
|
+
| ------------ | -------------------------------- | -------- | ------- | ------------------------------------------- |
|
|
954
|
+
| `items` | `BreadcrumbItem[]` | Yes | | 경로 항목 배열. { id, label, href?, icon? } |
|
|
955
|
+
| `separator` | `ReactNode` | | "/" | 항목 간 구분자 |
|
|
956
|
+
| `onNavigate` | `(item: BreadcrumbItem) => void` | | | 항목 클릭 핸들러 |
|
|
957
|
+
|
|
958
|
+
### EmptyState
|
|
959
|
+
|
|
960
|
+
> 데이터가 없을 때 표시하는 빈 상태 컴포넌트. 아이콘, 제목, 설명, 액션 버튼 지원.
|
|
961
|
+
|
|
962
|
+
**Import:** `import { EmptyState } from "@reopt-ai/opt-ui"`
|
|
963
|
+
|
|
964
|
+
| Prop | Type | Required | Default | Description |
|
|
965
|
+
| ------------- | -------------------- | -------- | ------- | -------------------------------------------- |
|
|
966
|
+
| `title` | `string` | Yes | | 빈 상태 제목 |
|
|
967
|
+
| `description` | `string` | | | 빈 상태 설명 |
|
|
968
|
+
| `icon` | `ReactNode` | | | 표시할 아이콘 |
|
|
969
|
+
| `actions` | `EmptyStateAction[]` | | | 액션 버튼 배열. { label, onClick, variant? } |
|
|
970
|
+
|
|
971
|
+
### StatCard
|
|
972
|
+
|
|
973
|
+
> 트렌드 방향과 변화량을 표시하는 통계 카드.
|
|
974
|
+
|
|
975
|
+
**Import:** `import { StatCard } from "@reopt-ai/opt-ui"`
|
|
976
|
+
|
|
977
|
+
| Prop | Type | Required | Default | Description |
|
|
978
|
+
| -------- | ----------------------------- | -------- | ------- | ------------------------------- |
|
|
979
|
+
| `title` | `string` | Yes | | 통계 제목 |
|
|
980
|
+
| `value` | `string` | Yes | | 통계 값 |
|
|
981
|
+
| `change` | `string` | Yes | | 변화량 텍스트 (예: '+12.5%') |
|
|
982
|
+
| `trend` | `"up" \| "down" \| "neutral"` | Yes | | 트렌드 방향. 색상과 아이콘 결정 |
|
|
983
|
+
|
|
984
|
+
### Logo
|
|
985
|
+
|
|
986
|
+
> 아이콘+텍스트 조합, 이미지, 링크 래핑을 지원하는 로고 컴포넌트. Sidebar 등에서 활용.
|
|
987
|
+
|
|
988
|
+
**Import:** `import { Logo } from "@reopt-ai/opt-ui"`
|
|
989
|
+
|
|
990
|
+
| Prop | Type | Required | Default | Description |
|
|
991
|
+
| ----------- | ---------------------- | -------- | ------- | -------------------------------- |
|
|
992
|
+
| `src` | `string` | | | 로고 이미지 URL |
|
|
993
|
+
| `icon` | `ReactNode` | | | 로고 아이콘 — src 미설정 시 표시 |
|
|
994
|
+
| `text` | `string` | | | 텍스트 레이블 |
|
|
995
|
+
| `alt` | `string` | | "Logo" | 이미지 alt 텍스트 |
|
|
996
|
+
| `size` | `"sm" \| "md" \| "lg"` | | "md" | 크기 (sm=24px, md=32px, lg=40px) |
|
|
997
|
+
| `href` | `string` | | | 링크 URL — 설정 시 <a>로 래핑 |
|
|
998
|
+
| `onClick` | `() => void` | | | 클릭 핸들러 |
|
|
999
|
+
| `className` | `string` | | | 커스텀 CSS 클래스 |
|
|
1000
|
+
|
|
1001
|
+
## Navigation & Overlay
|
|
1002
|
+
|
|
1003
|
+
| Component | Description | Key Exports |
|
|
1004
|
+
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
1005
|
+
| Menu | 메뉴바 + 개별 메뉴 시스템. 10 exports: MenubarRoot, MenubarContainer, MenuRoot, MenuTrigger, MenuButtonArrow, MenuPopover, MenuItem, MenuItemCheckbox, MenuItemRadio, MenuSeparator. | `MenubarRoot`, `MenubarContainer`, `MenuRoot`, `MenuTrigger`, `MenuButtonArrow`, `MenuPopover`, `MenuItem`, `MenuItemCheckbox`, `MenuItemRadio`, `MenuSeparator` |
|
|
1006
|
+
| DropdownMenu | Menu Core 위의 간편 래퍼. 단일 트리거 드롭다운 메뉴에 특화되었습니다. | `DropdownMenu`, `DropdownTrigger`, `DropdownContent`, `DropdownItem`, `DropdownSeparator` |
|
|
1007
|
+
| Popover | Popover 프리미티브 래퍼. 트리거 요소에 연결된 플로팅 콘텐츠를 표시합니다. | `PopoverRoot`, `PopoverTrigger`, `PopoverContent`, `PopoverClose` |
|
|
1008
|
+
| Tabs | 탭 패널 시스템. 4-part anatomy: Root, TabList, Tab, TabPanel. | `TabsRoot`, `TabList`, `Tab`, `TabPanel` |
|
|
1009
|
+
| Disclosure | 접기/펼치기 콘텐츠 영역. 3-part anatomy: Root, Trigger, Content. | `DisclosureRoot`, `DisclosureTrigger`, `DisclosureContent` |
|
|
1010
|
+
| Dialog | 모달 다이얼로그. 9-part anatomy: Root, Disclosure, Panel, Heading, Description, Dismiss, Header, Body, Footer. | `DialogRoot`, `DialogDisclosure`, `DialogPanel`, `AlertDialogPanel`, `DialogHeading`, `DialogDescription`, `DialogDismiss`, `DialogHeader`, `DialogBody`, `DialogFooter` |
|
|
1011
|
+
| Drawer | 사이드/하단 슬라이드 패널. Dialog 기반 compound 패턴으로 접근성을 보장합니다. | `DrawerRoot`, `DrawerPanel`, `DrawerClose` |
|
|
1012
|
+
| Toolbar | 툴바 컨테이너 + 툴팁. 7 exports: ToolbarRoot, ToolbarContainer, ToolbarButton, ToolbarSeparator, TooltipProvider, TooltipAnchor, Tooltip. | `ToolbarRoot`, `ToolbarContainer`, `ToolbarButton`, `ToolbarSeparator`, `TooltipProvider`, `TooltipAnchor`, `Tooltip` |
|
|
1013
|
+
| Pagination | 페이지 넘김 네비게이션. ellipsis 포함 페이지 번호, compact/count variant, totalPages/cursor pagination, Prev/Next 버튼을 제공합니다. | `Pagination` |
|
|
1014
|
+
|
|
1015
|
+
### Menu
|
|
1016
|
+
|
|
1017
|
+
> 메뉴바 + 개별 메뉴 시스템. 10 exports: MenubarRoot, MenubarContainer, MenuRoot, MenuTrigger, MenuButtonArrow, MenuPopover, MenuItem, MenuItemCheckbox, MenuItemRadio, MenuSeparator.
|
|
1018
|
+
|
|
1019
|
+
**Import:** `import { MenubarRoot } from "@reopt-ai/opt-ui"`
|
|
1020
|
+
|
|
1021
|
+
**MenubarRoot:**
|
|
1022
|
+
|
|
1023
|
+
| Prop | Type | Required | Default | Description |
|
|
1024
|
+
| ---- | ---- | -------- | ------- | ----------- |
|
|
1025
|
+
|
|
1026
|
+
**MenubarContainer:**
|
|
1027
|
+
|
|
1028
|
+
| Prop | Type | Required | Default | Description |
|
|
1029
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
1030
|
+
| `children` | `ReactNode` | Yes | | MenuRoot 요소들 |
|
|
1031
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1032
|
+
|
|
1033
|
+
**MenuRoot:**
|
|
1034
|
+
|
|
1035
|
+
| Prop | Type | Required | Default | Description |
|
|
1036
|
+
| ---- | ---- | -------- | ------- | ----------- |
|
|
1037
|
+
|
|
1038
|
+
**MenuTrigger:**
|
|
1039
|
+
|
|
1040
|
+
| Prop | Type | Required | Default | Description |
|
|
1041
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
1042
|
+
| `children` | `ReactNode` | Yes | | 메뉴 버튼 레이블 |
|
|
1043
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1044
|
+
|
|
1045
|
+
**MenuButtonArrow:**
|
|
1046
|
+
|
|
1047
|
+
| Prop | Type | Required | Default | Description |
|
|
1048
|
+
| ----------- | -------- | -------- | ------- | ----------------- |
|
|
1049
|
+
| `className` | `string` | | | 화살표 CSS 클래스 |
|
|
1050
|
+
|
|
1051
|
+
**MenuPopover:**
|
|
1052
|
+
|
|
1053
|
+
| Prop | Type | Required | Default | Description |
|
|
1054
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
1055
|
+
| `children` | `ReactNode` | Yes | | MenuItem 목록 |
|
|
1056
|
+
| `gutter` | `number` | | 8 | 트리거와의 간격 (px) |
|
|
1057
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1058
|
+
|
|
1059
|
+
**MenuItem:**
|
|
1060
|
+
|
|
1061
|
+
| Prop | Type | Required | Default | Description |
|
|
1062
|
+
| ----------- | ------------ | -------- | ------- | ---------------------- |
|
|
1063
|
+
| `children` | `ReactNode` | Yes | | 메뉴 항목 내용 |
|
|
1064
|
+
| `onClick` | `() => void` | | | 클릭 핸들러 |
|
|
1065
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1066
|
+
|
|
1067
|
+
**MenuItemCheckbox:**
|
|
1068
|
+
|
|
1069
|
+
| Prop | Type | Required | Default | Description |
|
|
1070
|
+
| ----------- | -------------------------- | -------- | ------- | ---------------------- |
|
|
1071
|
+
| `name` | `string` | Yes | | 체크박스 이름 |
|
|
1072
|
+
| `value` | `string` | Yes | | 체크박스 값 |
|
|
1073
|
+
| `checked` | `boolean` | | | 체크 상태 |
|
|
1074
|
+
| `onChange` | `(e: ChangeEvent) => void` | | | 변경 핸들러 |
|
|
1075
|
+
| `children` | `ReactNode` | Yes | | 항목 내용 |
|
|
1076
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1077
|
+
|
|
1078
|
+
**MenuItemRadio:**
|
|
1079
|
+
|
|
1080
|
+
| Prop | Type | Required | Default | Description |
|
|
1081
|
+
| ----------- | -------------------------- | -------- | ------- | ---------------------- |
|
|
1082
|
+
| `name` | `string` | Yes | | 라디오 그룹 이름 |
|
|
1083
|
+
| `value` | `string` | Yes | | 라디오 값 |
|
|
1084
|
+
| `checked` | `boolean` | | | 선택 상태 |
|
|
1085
|
+
| `onChange` | `(e: ChangeEvent) => void` | | | 변경 핸들러 |
|
|
1086
|
+
| `children` | `ReactNode` | Yes | | 항목 내용 |
|
|
1087
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1088
|
+
|
|
1089
|
+
**MenuSeparator:**
|
|
1090
|
+
|
|
1091
|
+
| Prop | Type | Required | Default | Description |
|
|
1092
|
+
| ----------- | -------- | -------- | ------- | ---------------------- |
|
|
1093
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1094
|
+
|
|
1095
|
+
### DropdownMenu
|
|
1096
|
+
|
|
1097
|
+
> Menu Core 위의 간편 래퍼. 단일 트리거 드롭다운 메뉴에 특화되었습니다.
|
|
1098
|
+
|
|
1099
|
+
**Import:** `import { DropdownMenu } from "@reopt-ai/opt-ui"`
|
|
1100
|
+
|
|
1101
|
+
**DropdownContent:**
|
|
1102
|
+
|
|
1103
|
+
| Prop | Type | Required | Default | Description |
|
|
1104
|
+
| -------- | -------- | -------- | ------- | -------------------- |
|
|
1105
|
+
| `gutter` | `number` | | 4 | 트리거와의 간격 (px) |
|
|
1106
|
+
|
|
1107
|
+
**DropdownItem:**
|
|
1108
|
+
|
|
1109
|
+
| Prop | Type | Required | Default | Description |
|
|
1110
|
+
| ---------- | ---------------------------- | -------- | --------- | --------------------------------------------------- |
|
|
1111
|
+
| `variant` | `"default" \| "destructive"` | | "default" | 메뉴 아이템 시각 변형. destructive는 위험 작업 강조 |
|
|
1112
|
+
| `onClick` | `() => void` | | | 항목 클릭 핸들러 |
|
|
1113
|
+
| `disabled` | `boolean` | | | 비활성 상태 |
|
|
1114
|
+
|
|
1115
|
+
### Popover
|
|
1116
|
+
|
|
1117
|
+
> Popover 프리미티브 래퍼. 트리거 요소에 연결된 플로팅 콘텐츠를 표시합니다.
|
|
1118
|
+
|
|
1119
|
+
**Import:** `import { PopoverRoot } from "@reopt-ai/opt-ui"`
|
|
1120
|
+
|
|
1121
|
+
| Prop | Type | Required | Default | Description |
|
|
1122
|
+
| ----------- | -------- | -------- | ------- | -------------------- |
|
|
1123
|
+
| `gutter` | `number` | | 8 | 트리거와의 간격 (px) |
|
|
1124
|
+
| `className` | `string` | | | 커스텀 CSS 클래스 |
|
|
1125
|
+
|
|
1126
|
+
### Tabs
|
|
1127
|
+
|
|
1128
|
+
> 탭 패널 시스템. 4-part anatomy: Root, TabList, Tab, TabPanel.
|
|
1129
|
+
|
|
1130
|
+
**Import:** `import { TabsRoot } from "@reopt-ai/opt-ui"`
|
|
1131
|
+
|
|
1132
|
+
**TabsRoot:**
|
|
1133
|
+
|
|
1134
|
+
| Prop | Type | Required | Default | Description |
|
|
1135
|
+
| ------------------- | ------------------------------ | -------- | ------- | ------------------------- |
|
|
1136
|
+
| `defaultSelectedId` | `string` | | | 초기 선택된 탭 ID |
|
|
1137
|
+
| `selectedId` | `string \| null` | | | 제어 모드: 선택된 탭 ID |
|
|
1138
|
+
| `setSelectedId` | `(id: string \| null) => void` | | | 제어 모드: 탭 변경 핸들러 |
|
|
1139
|
+
|
|
1140
|
+
**TabList:**
|
|
1141
|
+
|
|
1142
|
+
| Prop | Type | Required | Default | Description |
|
|
1143
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
1144
|
+
| `children` | `ReactNode` | Yes | | Tab 요소들 |
|
|
1145
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1146
|
+
|
|
1147
|
+
**Tab:**
|
|
1148
|
+
|
|
1149
|
+
| Prop | Type | Required | Default | Description |
|
|
1150
|
+
| ----------- | ----------- | -------- | ------- | ------------------------------------ |
|
|
1151
|
+
| `id` | `string` | Yes | | 탭 고유 ID (TabPanel의 tabId와 매칭) |
|
|
1152
|
+
| `children` | `ReactNode` | Yes | | 탭 레이블 |
|
|
1153
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1154
|
+
|
|
1155
|
+
**TabPanel:**
|
|
1156
|
+
|
|
1157
|
+
| Prop | Type | Required | Default | Description |
|
|
1158
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
1159
|
+
| `tabId` | `string` | Yes | | 연결된 Tab의 ID |
|
|
1160
|
+
| `children` | `ReactNode` | Yes | | 패널 콘텐츠 |
|
|
1161
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1162
|
+
|
|
1163
|
+
### Disclosure
|
|
1164
|
+
|
|
1165
|
+
> 접기/펼치기 콘텐츠 영역. 3-part anatomy: Root, Trigger, Content.
|
|
1166
|
+
|
|
1167
|
+
**Import:** `import { DisclosureRoot } from "@reopt-ai/opt-ui"`
|
|
1168
|
+
|
|
1169
|
+
**DisclosureRoot:**
|
|
1170
|
+
|
|
1171
|
+
| Prop | Type | Required | Default | Description |
|
|
1172
|
+
| ------------- | ------------------------- | -------- | ------- | --------------------------- |
|
|
1173
|
+
| `open` | `boolean` | | | 제어 모드: 열림 상태 |
|
|
1174
|
+
| `setOpen` | `(open: boolean) => void` | | | 제어 모드: 상태 변경 핸들러 |
|
|
1175
|
+
| `defaultOpen` | `boolean` | | false | 비제어 모드: 초기 열림 상태 |
|
|
1176
|
+
|
|
1177
|
+
**DisclosureTrigger:**
|
|
1178
|
+
|
|
1179
|
+
| Prop | Type | Required | Default | Description |
|
|
1180
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
1181
|
+
| `children` | `ReactNode` | Yes | | 트리거 내용 |
|
|
1182
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1183
|
+
|
|
1184
|
+
**DisclosureContent:**
|
|
1185
|
+
|
|
1186
|
+
| Prop | Type | Required | Default | Description |
|
|
1187
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
1188
|
+
| `children` | `ReactNode` | Yes | | 접히는 콘텐츠 |
|
|
1189
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1190
|
+
|
|
1191
|
+
### Dialog
|
|
1192
|
+
|
|
1193
|
+
> 모달 다이얼로그. 9-part anatomy: Root, Disclosure, Panel, Heading, Description, Dismiss, Header, Body, Footer.
|
|
1194
|
+
|
|
1195
|
+
**Import:** `import { DialogRoot } from "@reopt-ai/opt-ui"`
|
|
1196
|
+
|
|
1197
|
+
**DialogRoot:**
|
|
1198
|
+
|
|
1199
|
+
| Prop | Type | Required | Default | Description |
|
|
1200
|
+
| --------- | ------------------------- | -------- | ------- | --------------------------- |
|
|
1201
|
+
| `open` | `boolean` | | | 제어 모드: 열림 상태 |
|
|
1202
|
+
| `setOpen` | `(open: boolean) => void` | | | 제어 모드: 상태 변경 핸들러 |
|
|
1203
|
+
|
|
1204
|
+
**DialogDisclosure:**
|
|
1205
|
+
|
|
1206
|
+
| Prop | Type | Required | Default | Description |
|
|
1207
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
1208
|
+
| `children` | `ReactNode` | Yes | | 트리거 버튼 내용 |
|
|
1209
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1210
|
+
|
|
1211
|
+
**DialogPanel:**
|
|
1212
|
+
|
|
1213
|
+
| Prop | Type | Required | Default | Description |
|
|
1214
|
+
| ----------- | ------------------------------------------------ | -------- | ------------------- | ---------------------- |
|
|
1215
|
+
| `children` | `ReactNode` | Yes | | 다이얼로그 콘텐츠 |
|
|
1216
|
+
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl" \| "full"` | | "md" | 최대 너비 프리셋 |
|
|
1217
|
+
| `backdrop` | `ReactElement` | | <div> (반투명 배경) | 배경 오버레이 요소 |
|
|
1218
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1219
|
+
|
|
1220
|
+
**DialogHeading:**
|
|
1221
|
+
|
|
1222
|
+
| Prop | Type | Required | Default | Description |
|
|
1223
|
+
| ---------- | ----------- | -------- | ------- | --------------------------------------- |
|
|
1224
|
+
| `children` | `ReactNode` | Yes | | 제목 텍스트 (자동 aria-labelledby 연결) |
|
|
1225
|
+
|
|
1226
|
+
**DialogDescription:**
|
|
1227
|
+
|
|
1228
|
+
| Prop | Type | Required | Default | Description |
|
|
1229
|
+
| ---------- | ----------- | -------- | ------- | ---------------------------------------- |
|
|
1230
|
+
| `children` | `ReactNode` | Yes | | 설명 텍스트 (자동 aria-describedby 연결) |
|
|
1231
|
+
|
|
1232
|
+
**DialogDismiss:**
|
|
1233
|
+
|
|
1234
|
+
| Prop | Type | Required | Default | Description |
|
|
1235
|
+
| ---------- | ----------- | -------- | ------- | -------------- |
|
|
1236
|
+
| `children` | `ReactNode` | | | 닫기 버튼 내용 |
|
|
1237
|
+
|
|
1238
|
+
**DialogHeader:**
|
|
1239
|
+
|
|
1240
|
+
| Prop | Type | Required | Default | Description |
|
|
1241
|
+
| ---------- | ----------- | -------- | ------- | -------------------------------------------- |
|
|
1242
|
+
| `children` | `ReactNode` | Yes | | Heading, Description, Dismiss 등 헤더 콘텐츠 |
|
|
1243
|
+
|
|
1244
|
+
**DialogBody:**
|
|
1245
|
+
|
|
1246
|
+
| Prop | Type | Required | Default | Description |
|
|
1247
|
+
| ---------- | ----------- | -------- | ------- | ------------------------- |
|
|
1248
|
+
| `children` | `ReactNode` | Yes | | 스크롤 가능한 본문 콘텐츠 |
|
|
1249
|
+
|
|
1250
|
+
**DialogFooter:**
|
|
1251
|
+
|
|
1252
|
+
| Prop | Type | Required | Default | Description |
|
|
1253
|
+
| ---------- | ----------- | -------- | ------- | -------------- |
|
|
1254
|
+
| `children` | `ReactNode` | Yes | | 액션 버튼 영역 |
|
|
1255
|
+
|
|
1256
|
+
**Examples:**
|
|
1257
|
+
|
|
1258
|
+
_모달 대화상자:_
|
|
1259
|
+
|
|
1260
|
+
```tsx
|
|
1261
|
+
import {
|
|
1262
|
+
DialogRoot,
|
|
1263
|
+
DialogDisclosure,
|
|
1264
|
+
DialogPanel,
|
|
1265
|
+
DialogHeading,
|
|
1266
|
+
DialogDismiss,
|
|
1267
|
+
} from "@reopt-ai/opt-ui";
|
|
1268
|
+
|
|
1269
|
+
<DialogRoot>
|
|
1270
|
+
<DialogDisclosure>열기</DialogDisclosure>
|
|
1271
|
+
<DialogPanel size="md">
|
|
1272
|
+
<DialogHeading>확인</DialogHeading>
|
|
1273
|
+
<p>변경 사항을 저장하시겠습니까?</p>
|
|
1274
|
+
<DialogDismiss>닫기</DialogDismiss>
|
|
1275
|
+
</DialogPanel>
|
|
1276
|
+
</DialogRoot>;
|
|
1277
|
+
```
|
|
1278
|
+
|
|
1279
|
+
### Drawer
|
|
1280
|
+
|
|
1281
|
+
> 사이드/하단 슬라이드 패널. Dialog 기반 compound 패턴으로 접근성을 보장합니다.
|
|
1282
|
+
|
|
1283
|
+
**Import:** `import { DrawerRoot } from "@reopt-ai/opt-ui"`
|
|
1284
|
+
|
|
1285
|
+
**DrawerRoot:**
|
|
1286
|
+
|
|
1287
|
+
| Prop | Type | Required | Default | Description |
|
|
1288
|
+
| --------- | ------------ | -------- | ------- | ------------------- |
|
|
1289
|
+
| `open` | `boolean` | | | 제어 모드 열림 상태 |
|
|
1290
|
+
| `onClose` | `() => void` | | | 닫힘 콜백 |
|
|
1291
|
+
|
|
1292
|
+
**DrawerPanel:**
|
|
1293
|
+
|
|
1294
|
+
| Prop | Type | Required | Default | Description |
|
|
1295
|
+
| ----------------------- | -------------------------------- | -------- | ------- | -------------------------------------- |
|
|
1296
|
+
| `side` | `"left" \| "right" \| "bottom"` | | "right" | 슬라이드 방향 |
|
|
1297
|
+
| `size` | `"sm" \| "md" \| "lg" \| "full"` | | "md" | 패널 크기 |
|
|
1298
|
+
| `swipeToDismiss` | `boolean` | | true | 가장자리 방향으로 드래그해 닫기 활성화 |
|
|
1299
|
+
| `swipeDismissThreshold` | `number` | | 80 | 닫힘 커밋에 필요한 드래그 거리(px) |
|
|
1300
|
+
|
|
1301
|
+
### Toolbar
|
|
1302
|
+
|
|
1303
|
+
> 툴바 컨테이너 + 툴팁. 7 exports: ToolbarRoot, ToolbarContainer, ToolbarButton, ToolbarSeparator, TooltipProvider, TooltipAnchor, Tooltip.
|
|
1304
|
+
|
|
1305
|
+
**Import:** `import { ToolbarRoot } from "@reopt-ai/opt-ui"`
|
|
1306
|
+
|
|
1307
|
+
**ToolbarRoot:**
|
|
1308
|
+
|
|
1309
|
+
| Prop | Type | Required | Default | Description |
|
|
1310
|
+
| ----------- | --------- | -------- | ------- | ---------------- |
|
|
1311
|
+
| `focusLoop` | `boolean` | | false | 포커스 순환 여부 |
|
|
1312
|
+
|
|
1313
|
+
**ToolbarContainer:**
|
|
1314
|
+
|
|
1315
|
+
| Prop | Type | Required | Default | Description |
|
|
1316
|
+
| ----------- | ----------- | -------- | ------- | ------------------------------ |
|
|
1317
|
+
| `children` | `ReactNode` | Yes | | ToolbarButton/Separator 요소들 |
|
|
1318
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1319
|
+
|
|
1320
|
+
**ToolbarButton:**
|
|
1321
|
+
|
|
1322
|
+
| Prop | Type | Required | Default | Description |
|
|
1323
|
+
| ----------- | ------------ | -------- | ------- | ---------------------- |
|
|
1324
|
+
| `children` | `ReactNode` | Yes | | 버튼 내용 |
|
|
1325
|
+
| `onClick` | `() => void` | | | 클릭 핸들러 |
|
|
1326
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1327
|
+
|
|
1328
|
+
**ToolbarSeparator:**
|
|
1329
|
+
|
|
1330
|
+
| Prop | Type | Required | Default | Description |
|
|
1331
|
+
| ----------- | -------- | -------- | ------- | ---------------------- |
|
|
1332
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1333
|
+
|
|
1334
|
+
**TooltipProvider:**
|
|
1335
|
+
|
|
1336
|
+
| Prop | Type | Required | Default | Description |
|
|
1337
|
+
| ---- | ---- | -------- | ------- | ----------- |
|
|
1338
|
+
|
|
1339
|
+
**TooltipAnchor:**
|
|
1340
|
+
|
|
1341
|
+
| Prop | Type | Required | Default | Description |
|
|
1342
|
+
| ---------- | -------------- | -------- | ------- | ------------------ |
|
|
1343
|
+
| `render` | `ReactElement` | | | 앵커로 사용할 요소 |
|
|
1344
|
+
| `children` | `ReactNode` | | | 앵커 내용 |
|
|
1345
|
+
|
|
1346
|
+
**Tooltip:**
|
|
1347
|
+
|
|
1348
|
+
| Prop | Type | Required | Default | Description |
|
|
1349
|
+
| ----------- | ----------- | -------- | ------- | ---------------------- |
|
|
1350
|
+
| `children` | `ReactNode` | Yes | | 툴팁 내용 |
|
|
1351
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1352
|
+
|
|
1353
|
+
### Pagination
|
|
1354
|
+
|
|
1355
|
+
> 페이지 넘김 네비게이션. ellipsis 포함 페이지 번호, compact/count variant, totalPages/cursor pagination, Prev/Next 버튼을 제공합니다.
|
|
1356
|
+
|
|
1357
|
+
**Import:** `import { Pagination } from "@reopt-ai/opt-ui"`
|
|
1358
|
+
|
|
1359
|
+
| Prop | Type | Required | Default | Description |
|
|
1360
|
+
| ----------------- | ------------------------------------------- | -------- | ------------ | ------------------------------------------- |
|
|
1361
|
+
| `totalItems` | `number` | | | 전체 항목 수 |
|
|
1362
|
+
| `totalPages` | `number` | | | 전체 페이지 수. 전체 항목 수를 모를 때 사용 |
|
|
1363
|
+
| `hasMore` | `boolean` | | | cursor pagination에서 다음 페이지 존재 여부 |
|
|
1364
|
+
| `pageSize` | `number` | | | 페이지당 항목 수 |
|
|
1365
|
+
| `currentPage` | `number` | Yes | | 현재 페이지 (1부터 시작) |
|
|
1366
|
+
| `onPageChange` | `(page: number) => void` | Yes | | 페이지 변경 콜백 |
|
|
1367
|
+
| `showPageNumbers` | `boolean` | | true | 페이지 번호 표시 여부 |
|
|
1368
|
+
| `siblingCount` | `number` | | 1 | 현재 페이지 좌우 표시할 페이지 수 |
|
|
1369
|
+
| `variant` | `"pages" \| "count" \| "compact" \| "none"` | | "pages" | 중앙 표시 방식 |
|
|
1370
|
+
| `isDisabled` | `boolean` | | false | 전체 pagination 비활성화 |
|
|
1371
|
+
| `label` | `string` | | "Pagination" | navigation landmark 접근성 라벨 |
|
|
1372
|
+
| `labels` | `PaginationLabels` | | | Prev/Next/page/count 접근성 및 표시 문구 |
|
|
1373
|
+
|
|
1374
|
+
## Layout
|
|
1375
|
+
|
|
1376
|
+
| Component | Description | Key Exports |
|
|
1377
|
+
| ------------- | ------------------------------------------------------------------------------- | ---------------------------------------------------------- |
|
|
1378
|
+
| CompositeZone | Composite 기반 2D 키보드 탐색 컨테이너. 화살표 키로 자식 요소 간 이동 가능. | `CompositeZone` |
|
|
1379
|
+
| PageHeader | 페이지 제목, 설명, 액션 슬롯을 제공하는 레이아웃 헤더 컴포넌트. | `PageHeader` |
|
|
1380
|
+
| ScrollArea | 커스텀 스크롤바를 제공하는 스크롤 컨테이너. 수직/수평/양방향 지원. | `ScrollArea` |
|
|
1381
|
+
| Container | 최대 너비 제약과 중앙 정렬을 제공하는 래퍼. 페이지 콘텐츠 폭 제한용. | `Container` |
|
|
1382
|
+
| Section | 시맨틱 스페이싱 블록. 제목이 있으면 aria-labelledby를 자동 설정합니다. | `Section` |
|
|
1383
|
+
| Resizable | react-resizable-panels 래퍼. 드래그로 크기를 조절할 수 있는 패널 분할 레이아웃. | `ResizablePanelGroup`, `ResizablePanel`, `ResizableHandle` |
|
|
1384
|
+
| VirtualList | 가상 스크롤 리스트. 대량 데이터를 윈도잉 기법으로 효율적으로 렌더링합니다. | `VirtualList` |
|
|
1385
|
+
|
|
1386
|
+
### CompositeZone
|
|
1387
|
+
|
|
1388
|
+
> Composite 기반 2D 키보드 탐색 컨테이너. 화살표 키로 자식 요소 간 이동 가능.
|
|
1389
|
+
|
|
1390
|
+
**Import:** `import { CompositeZone } from "@reopt-ai/opt-ui"`
|
|
1391
|
+
|
|
1392
|
+
| Prop | Type | Required | Default | Description |
|
|
1393
|
+
| ----------- | ----------- | -------- | ------- | --------------------------------- |
|
|
1394
|
+
| `children` | `ReactNode` | Yes | | CompositeRow + CompositeItem 자식 |
|
|
1395
|
+
| `label` | `string` | Yes | | aria-label 값 |
|
|
1396
|
+
| `focusLoop` | `boolean` | | true | 포커스가 끝에서 처음으로 순환 |
|
|
1397
|
+
| `focusWrap` | `boolean` | | true | 행 끝에서 다음 행으로 이동 |
|
|
1398
|
+
| `className` | `string` | | | 컨테이너 CSS 클래스 |
|
|
1399
|
+
|
|
1400
|
+
### PageHeader
|
|
1401
|
+
|
|
1402
|
+
> 페이지 제목, 설명, 액션 슬롯을 제공하는 레이아웃 헤더 컴포넌트.
|
|
1403
|
+
|
|
1404
|
+
**Import:** `import { PageHeader } from "@reopt-ai/opt-ui"`
|
|
1405
|
+
|
|
1406
|
+
| Prop | Type | Required | Default | Description |
|
|
1407
|
+
| ------------- | ----------- | -------- | ------- | ----------------------------------- |
|
|
1408
|
+
| `title` | `string` | Yes | | 페이지 제목 |
|
|
1409
|
+
| `description` | `string` | | | 제목 아래 설명 텍스트 |
|
|
1410
|
+
| `actions` | `ReactNode` | | | 오른쪽에 표시할 액션 슬롯 (버튼 등) |
|
|
1411
|
+
| `className` | `string` | | | 커스텀 CSS 클래스 |
|
|
1412
|
+
|
|
1413
|
+
### ScrollArea
|
|
1414
|
+
|
|
1415
|
+
> 커스텀 스크롤바를 제공하는 스크롤 컨테이너. 수직/수평/양방향 지원.
|
|
1416
|
+
|
|
1417
|
+
**Import:** `import { ScrollArea } from "@reopt-ai/opt-ui"`
|
|
1418
|
+
|
|
1419
|
+
| Prop | Type | Required | Default | Description |
|
|
1420
|
+
| ------------- | -------------------------------------- | -------- | ---------- | ----------------- |
|
|
1421
|
+
| `children` | `ReactNode` | Yes | | 스크롤할 콘텐츠 |
|
|
1422
|
+
| `orientation` | `"vertical" \| "horizontal" \| "both"` | | "vertical" | 스크롤 방향 |
|
|
1423
|
+
| `className` | `string` | | | 커스텀 CSS 클래스 |
|
|
1424
|
+
|
|
1425
|
+
### Container
|
|
1426
|
+
|
|
1427
|
+
> 최대 너비 제약과 중앙 정렬을 제공하는 래퍼. 페이지 콘텐츠 폭 제한용.
|
|
1428
|
+
|
|
1429
|
+
**Import:** `import { Container } from "@reopt-ai/opt-ui"`
|
|
1430
|
+
|
|
1431
|
+
| Prop | Type | Required | Default | Description |
|
|
1432
|
+
| ----------- | ------------------------------------------------- | -------- | ------- | ------------------------ |
|
|
1433
|
+
| `children` | `ReactNode` | Yes | | 래핑할 콘텐츠 |
|
|
1434
|
+
| `maxWidth` | `"sm" \| "md" \| "lg" \| "xl" \| "2xl" \| "full"` | | "xl" | 최대 너비 크기 |
|
|
1435
|
+
| `center` | `boolean` | | true | 중앙 정렬 여부 (mx-auto) |
|
|
1436
|
+
| `className` | `string` | | | 커스텀 CSS 클래스 |
|
|
1437
|
+
|
|
1438
|
+
### Section
|
|
1439
|
+
|
|
1440
|
+
> 시맨틱 스페이싱 블록. 제목이 있으면 aria-labelledby를 자동 설정합니다.
|
|
1441
|
+
|
|
1442
|
+
**Import:** `import { Section } from "@reopt-ai/opt-ui"`
|
|
1443
|
+
|
|
1444
|
+
| Prop | Type | Required | Default | Description |
|
|
1445
|
+
| ------------- | ----------- | -------- | ------- | --------------------- |
|
|
1446
|
+
| `children` | `ReactNode` | Yes | | 섹션 콘텐츠 |
|
|
1447
|
+
| `title` | `string` | | | 섹션 제목 (h3) |
|
|
1448
|
+
| `description` | `string` | | | 제목 아래 설명 텍스트 |
|
|
1449
|
+
| `className` | `string` | | | 커스텀 CSS 클래스 |
|
|
1450
|
+
|
|
1451
|
+
### Resizable
|
|
1452
|
+
|
|
1453
|
+
> react-resizable-panels 래퍼. 드래그로 크기를 조절할 수 있는 패널 분할 레이아웃.
|
|
1454
|
+
|
|
1455
|
+
**Import:** `import { ResizablePanelGroup } from "@reopt-ai/opt-ui"`
|
|
1456
|
+
|
|
1457
|
+
**ResizablePanelGroup:**
|
|
1458
|
+
|
|
1459
|
+
| Prop | Type | Required | Default | Description |
|
|
1460
|
+
| ------------ | ---------------------------- | -------- | ------- | ---------------------------------------- |
|
|
1461
|
+
| `direction` | `"horizontal" \| "vertical"` | Yes | | 패널 분할 방향 |
|
|
1462
|
+
| `children` | `ReactNode` | Yes | | ResizablePanel + ResizableHandle 조합 |
|
|
1463
|
+
| `autoSaveId` | `string` | | | 로컬 스토리지에 크기 상태 저장 (고유 ID) |
|
|
1464
|
+
| `className` | `string` | | | 커스텀 CSS 클래스 |
|
|
1465
|
+
|
|
1466
|
+
**ResizablePanel:**
|
|
1467
|
+
|
|
1468
|
+
| Prop | Type | Required | Default | Description |
|
|
1469
|
+
| ------------- | ----------- | -------- | ------- | ----------------------------- |
|
|
1470
|
+
| `defaultSize` | `number` | | | 초기 크기 (퍼센트, 0-100) |
|
|
1471
|
+
| `minSize` | `number` | | | 최소 크기 (퍼센트) |
|
|
1472
|
+
| `maxSize` | `number` | | | 최대 크기 (퍼센트) |
|
|
1473
|
+
| `collapsible` | `boolean` | | false | 최소 크기 이하 시 접히기 허용 |
|
|
1474
|
+
| `children` | `ReactNode` | Yes | | 패널 콘텐츠 |
|
|
1475
|
+
| `className` | `string` | | | 커스텀 CSS 클래스 |
|
|
1476
|
+
|
|
1477
|
+
**ResizableHandle:**
|
|
1478
|
+
|
|
1479
|
+
| Prop | Type | Required | Default | Description |
|
|
1480
|
+
| ------------ | --------- | -------- | ------- | ----------------------- |
|
|
1481
|
+
| `withHandle` | `boolean` | | false | 시각적 드래그 핸들 표시 |
|
|
1482
|
+
| `className` | `string` | | | 커스텀 CSS 클래스 |
|
|
1483
|
+
|
|
1484
|
+
### VirtualList
|
|
1485
|
+
|
|
1486
|
+
> 가상 스크롤 리스트. 대량 데이터를 윈도잉 기법으로 효율적으로 렌더링합니다.
|
|
1487
|
+
|
|
1488
|
+
**Import:** `import { VirtualList } from "@reopt-ai/opt-ui"`
|
|
1489
|
+
|
|
1490
|
+
| Prop | Type | Required | Default | Description |
|
|
1491
|
+
| ------------ | --------------------------------------- | -------- | ------- | --------------------------------- |
|
|
1492
|
+
| `items` | `T[]` | Yes | | 렌더링할 항목 배열 |
|
|
1493
|
+
| `renderItem` | `(item: T, index: number) => ReactNode` | Yes | | 항목 렌더 함수 |
|
|
1494
|
+
| `itemHeight` | `number` | Yes | | 각 항목의 고정 높이(px) |
|
|
1495
|
+
| `overscan` | `number` | | 3 | 뷰포트 밖에 미리 렌더링할 항목 수 |
|
|
1496
|
+
|
|
1497
|
+
## Builder
|
|
1498
|
+
|
|
1499
|
+
| Component | Description | Key Exports |
|
|
1500
|
+
| ---------------- | ------------------------------------------------------------------------- | ------------------ |
|
|
1501
|
+
| StepBuilder | 순서가 있는 단계를 추가, 제거, 재정렬할 수 있는 빌더 컴포넌트. | `StepBuilder` |
|
|
1502
|
+
| ConditionBuilder | AND/OR 로직으로 조건 그룹을 구성하는 빌더. 속성, 연산자, 값을 조합합니다. | `ConditionBuilder` |
|
|
1503
|
+
|
|
1504
|
+
### StepBuilder
|
|
1505
|
+
|
|
1506
|
+
> 순서가 있는 단계를 추가, 제거, 재정렬할 수 있는 빌더 컴포넌트.
|
|
1507
|
+
|
|
1508
|
+
**Import:** `import { StepBuilder } from "@reopt-ai/opt-ui"`
|
|
1509
|
+
|
|
1510
|
+
| Prop | Type | Required | Default | Description |
|
|
1511
|
+
| ---------- | ---------------------------- | -------- | ------- | --------------------------------------- |
|
|
1512
|
+
| `steps` | `StepDef[]` | Yes | | 단계 배열 ({ id, label, description? }) |
|
|
1513
|
+
| `onChange` | `(steps: StepDef[]) => void` | Yes | | 단계 변경 핸들러 |
|
|
1514
|
+
| `label` | `string` | | | 빌더 레이블 |
|
|
1515
|
+
| `maxSteps` | `number` | | | 최대 단계 수 |
|
|
1516
|
+
|
|
1517
|
+
### ConditionBuilder
|
|
1518
|
+
|
|
1519
|
+
> AND/OR 로직으로 조건 그룹을 구성하는 빌더. 속성, 연산자, 값을 조합합니다.
|
|
1520
|
+
|
|
1521
|
+
**Import:** `import { ConditionBuilder } from "@reopt-ai/opt-ui"`
|
|
1522
|
+
|
|
1523
|
+
| Prop | Type | Required | Default | Description |
|
|
1524
|
+
| --------------------- | --------------------------------------- | -------- | ------------------ | -------------------------------------- |
|
|
1525
|
+
| `groups` | `ConditionGroup[]` | Yes | | 조건 그룹 배열 |
|
|
1526
|
+
| `onChange` | `(groups: ConditionGroup[]) => void` | Yes | | 그룹 변경 핸들러 |
|
|
1527
|
+
| `properties` | `string[]` | | | 선택 가능한 속성 목록 (기본 10개 제공) |
|
|
1528
|
+
| `label` | `string` | | | 빌더 레이블 |
|
|
1529
|
+
| `nested` | `boolean` | | false | 중첩 AND/OR 그룹 활성화 |
|
|
1530
|
+
| `maxDepth` | `number` | | 3 | 최대 중첩 깊이 |
|
|
1531
|
+
| `conditionTypes` | `Record<string, ConditionTypeRenderer>` | | | 이질적 조건 타입 렌더러 레지스트리 |
|
|
1532
|
+
| `onPreview` | `(groups: ConditionGroup[]) => void` | | | 조건 변경 시 미리보기 콜백 |
|
|
1533
|
+
| `previewCount` | `number` | | | 매치 카운트 표시 (toLocaleString 포맷) |
|
|
1534
|
+
| `addNestedGroupLabel` | `string` | | "Add nested group" | 중첩 그룹 추가 버튼 텍스트 |
|
|
1535
|
+
|
|
1536
|
+
## Other
|
|
1537
|
+
|
|
1538
|
+
| Component | Description | Key Exports |
|
|
1539
|
+
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1540
|
+
| Text | 본문, 레이블, 보조 설명, 코드에 일관된 의미 기반 타이포그래피를 적용합니다. | `Text` |
|
|
1541
|
+
| Heading | 문서의 의미 계층과 시각적 타이포그래피 계층을 독립적으로 제어합니다. | `Heading` |
|
|
1542
|
+
| Separator | 콘텐츠를 구분하는 가로/세로 디바이더. 라벨을 넣으면 가운데 정렬 구분선이 된다. | `Separator` |
|
|
1543
|
+
| OtpField | 일회용 코드(OTP)/PIN 입력. 셀 단위 입력, 붙여넣기 분배, 자동 포커스 이동, 백스페이스 네비게이션과 폼 이름/오류 연결을 지원합니다. | `OtpField` |
|
|
1544
|
+
| Toggle | 눌림(pressed) 두 상태 버튼. 단독 사용하거나 ToggleGroup으로 묶어 단일/다중 선택을 만든다. | `Toggle`, `ToggleGroup` |
|
|
1545
|
+
| Accordion | 수직으로 쌓인 펼침/접힘 패널. single(한 개)/multiple(여러 개) 모드와 collapsible 지원. | `AccordionRoot`, `AccordionItem`, `AccordionTrigger`, `AccordionContent` |
|
|
1546
|
+
| Meter | 범위 내 스칼라 측정값 게이지 (디스크 사용량·점수·용량 등). role=meter로 작업 진행률(Progress)과 구분된다. | `Meter` |
|
|
1547
|
+
| BlockLayout | Block 루트 레이아웃. flex + 기본 section spacing 적용, loading prop으로 LoadingOverlay 자동 래핑. | `BlockLayout` |
|
|
1548
|
+
| createBlock | Block 팩토리 함수. BlockLayout 래핑을 구조적으로 강제하여 loading/className 처리를 자동화합니다. | `createBlock` |
|
|
1549
|
+
| StarRating | 1~N점 별점을 선택하는 인터랙티브 레이팅 입력. 읽기 전용 표시도 지원. | `StarRating` |
|
|
1550
|
+
| ErrorBoundary | React 에러 바운더리. 자식 컴포넌트 렌더 에러를 잡아 fallback UI를 표시합니다. | `ErrorBoundary` |
|
|
1551
|
+
| Command | cmdk 스타일 명령 anatomy. 자동 필터링 + 키보드 내비게이션. 인라인 또는 CommandDialog로 사용. | `Command`, `CommandDialog`, `CommandInput`, `CommandList`, `CommandEmpty`, `CommandGroup`, `CommandItem`, `CommandSeparator`, `CommandShortcut` |
|
|
1552
|
+
| ShaderSurface | ogl 기반 애니메이션 WebGL 셰이더 배경. 럭셔리 프리셋(메탈릭/실크/유리 등) + 색·파라미터로 배경·카드 배경을 만든다. 정지 프레임·PNG 캡처·WebGL 폴백 지원. | `ShaderSurface` |
|
|
1553
|
+
|
|
1554
|
+
### Text
|
|
1555
|
+
|
|
1556
|
+
> 본문, 레이블, 보조 설명, 코드에 일관된 의미 기반 타이포그래피를 적용합니다.
|
|
1557
|
+
|
|
1558
|
+
**Import:** `import { Text } from "@reopt-ai/opt-ui"`
|
|
1559
|
+
|
|
1560
|
+
| Prop | Type | Required | Default | Description |
|
|
1561
|
+
| ---------- | ----------------------------------------------------- | -------- | ------- | --------------------- |
|
|
1562
|
+
| `as` | `"span" \| "p" \| "div" \| "label" \| "code"` | | | 렌더링할 HTML 요소 |
|
|
1563
|
+
| `variant` | `"body" \| "label" \| "supporting" \| "code"` | | | 시각적 텍스트 역할 |
|
|
1564
|
+
| `tone` | `"primary" \| "secondary" \| "tertiary" \| "inherit"` | | | 의미 기반 텍스트 색상 |
|
|
1565
|
+
| `truncate` | `boolean` | | | 한 줄 말줄임 적용 |
|
|
1566
|
+
| `children` | `ReactNode` | | | 텍스트 콘텐츠 |
|
|
1567
|
+
|
|
1568
|
+
### Heading
|
|
1569
|
+
|
|
1570
|
+
> 문서의 의미 계층과 시각적 타이포그래피 계층을 독립적으로 제어합니다.
|
|
1571
|
+
|
|
1572
|
+
**Import:** `import { Heading } from "@reopt-ai/opt-ui"`
|
|
1573
|
+
|
|
1574
|
+
| Prop | Type | Required | Default | Description |
|
|
1575
|
+
| ---------- | ------------------------------------------------------------------------ | -------- | ------- | ------------------------ |
|
|
1576
|
+
| `level` | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | | | 의미 기반 HTML 제목 레벨 |
|
|
1577
|
+
| `variant` | `"heading-1" … "heading-6" \| "display-1" \| "display-2" \| "display-3"` | | | 시각적 제목 역할 |
|
|
1578
|
+
| `children` | `ReactNode` | | | 제목 콘텐츠 |
|
|
1579
|
+
|
|
1580
|
+
### Separator
|
|
1581
|
+
|
|
1582
|
+
> 콘텐츠를 구분하는 가로/세로 디바이더. 라벨을 넣으면 가운데 정렬 구분선이 된다.
|
|
1583
|
+
|
|
1584
|
+
**Import:** `import { Separator } from "@reopt-ai/opt-ui"`
|
|
1585
|
+
|
|
1586
|
+
| Prop | Type | Required | Default | Description |
|
|
1587
|
+
| ------------- | ---------------------------- | -------- | ------- | ------------------------------------- |
|
|
1588
|
+
| `orientation` | `"horizontal" \| "vertical"` | | | 구분선 방향 (기본 horizontal) |
|
|
1589
|
+
| `decorative` | `boolean` | | | 접근성 트리에서 숨김 (순수 시각 구분) |
|
|
1590
|
+
| `children` | `ReactNode` | | | 가운데 라벨 (horizontal 전용) |
|
|
1591
|
+
| `className` | `string` | | | 추가 CSS 클래스 |
|
|
1592
|
+
|
|
1593
|
+
### OtpField
|
|
1594
|
+
|
|
1595
|
+
> 일회용 코드(OTP)/PIN 입력. 셀 단위 입력, 붙여넣기 분배, 자동 포커스 이동, 백스페이스 네비게이션과 폼 이름/오류 연결을 지원합니다.
|
|
1596
|
+
|
|
1597
|
+
**Import:** `import { OtpField } from "@reopt-ai/opt-ui"`
|
|
1598
|
+
|
|
1599
|
+
| Prop | Type | Required | Default | Description |
|
|
1600
|
+
| -------------- | ----------------------------- | -------- | ------- | ------------------------------------------- |
|
|
1601
|
+
| `length` | `number` | | | 셀 개수 (기본 6) |
|
|
1602
|
+
| `value` | `string` | | | 제어 모드 값 |
|
|
1603
|
+
| `defaultValue` | `string` | | | 비제어 초기값 |
|
|
1604
|
+
| `onChange` | `(value: string) => void` | | | 값 변경 콜백 |
|
|
1605
|
+
| `onComplete` | `(value: string) => void` | | | 모든 셀이 채워지면 1회 호출 |
|
|
1606
|
+
| `type` | `"numeric" \| "alphanumeric"` | | | 허용 문자 (기본 numeric) |
|
|
1607
|
+
| `mask` | `boolean` | | | 채워진 셀을 점(•)으로 마스킹 (PIN 용) |
|
|
1608
|
+
| `disabled` | `boolean` | | | 비활성화 |
|
|
1609
|
+
| `name` | `string` | | | 폼 필드명. 전체 값을 담은 hidden input 렌더 |
|
|
1610
|
+
| `label` | `string` | | | 필드 레이블 |
|
|
1611
|
+
| `error` | `string` | | | 에러 메시지 |
|
|
1612
|
+
| `hint` | `string` | | | 도움말 텍스트 |
|
|
1613
|
+
|
|
1614
|
+
### Toggle
|
|
1615
|
+
|
|
1616
|
+
> 눌림(pressed) 두 상태 버튼. 단독 사용하거나 ToggleGroup으로 묶어 단일/다중 선택을 만든다.
|
|
1617
|
+
|
|
1618
|
+
**Import:** `import { Toggle } from "@reopt-ai/opt-ui"`
|
|
1619
|
+
|
|
1620
|
+
**Toggle:**
|
|
1621
|
+
|
|
1622
|
+
| Prop | Type | Required | Default | Description |
|
|
1623
|
+
| ----------------- | ---------------------------- | -------- | ------- | ---------------------------------------- |
|
|
1624
|
+
| `pressed` | `boolean` | | | 제어 모드: 눌림 상태 (단독 사용) |
|
|
1625
|
+
| `defaultPressed` | `boolean` | | | 비제어 초기 눌림 상태 (단독 사용) |
|
|
1626
|
+
| `onPressedChange` | `(pressed: boolean) => void` | | | 눌림 상태 변경 콜백 (단독 사용) |
|
|
1627
|
+
| `value` | `string` | | | ToggleGroup 내에서 이 토글을 식별하는 값 |
|
|
1628
|
+
| `size` | `"sm" \| "md"` | | | 크기 (기본 md) |
|
|
1629
|
+
| `disabled` | `boolean` | | | 비활성화 |
|
|
1630
|
+
| `children` | `ReactNode` | | | 토글 콘텐츠 |
|
|
1631
|
+
|
|
1632
|
+
**ToggleGroup:**
|
|
1633
|
+
|
|
1634
|
+
| Prop | Type | Required | Default | Description |
|
|
1635
|
+
| ---------------- | ------------------------------------- | -------- | ------- | ------------------------------------------------- |
|
|
1636
|
+
| `value` | `string \| string[]` | | | 선택 값. 단일은 string, toggleMultiple은 string[] |
|
|
1637
|
+
| `defaultValue` | `string \| string[]` | | | 비제어 초기 선택 값 |
|
|
1638
|
+
| `onValueChange` | `(value: string \| string[]) => void` | | | 선택 변경 콜백 |
|
|
1639
|
+
| `toggleMultiple` | `boolean` | | | 동시에 여러 개 눌림 허용 |
|
|
1640
|
+
| `orientation` | `"horizontal" \| "vertical"` | | | 배치 방향 (기본 horizontal) |
|
|
1641
|
+
| `disabled` | `boolean` | | | 그룹 전체 비활성화 |
|
|
1642
|
+
| `children` | `ReactNode` | | | Toggle 항목들 |
|
|
1643
|
+
|
|
1644
|
+
### Accordion
|
|
1645
|
+
|
|
1646
|
+
> 수직으로 쌓인 펼침/접힘 패널. single(한 개)/multiple(여러 개) 모드와 collapsible 지원.
|
|
1647
|
+
|
|
1648
|
+
**Import:** `import { AccordionRoot } from "@reopt-ai/opt-ui"`
|
|
1649
|
+
|
|
1650
|
+
**AccordionRoot:**
|
|
1651
|
+
|
|
1652
|
+
| Prop | Type | Required | Default | Description |
|
|
1653
|
+
| --------------- | --------------------------------------------- | -------- | ------- | ------------------------------------------------------------- |
|
|
1654
|
+
| `type` | `"single" \| "multiple"` | | | 한 개만 열림(single) 또는 여러 개 열림(multiple). 기본 single |
|
|
1655
|
+
| `value` | `string \| string[] \| null` | | | 열린 항목 값. single은 string\|null, multiple은 string[] |
|
|
1656
|
+
| `defaultValue` | `string \| string[] \| null` | | | 비제어 초기 열림 값 |
|
|
1657
|
+
| `onValueChange` | `(value: string \| string[] \| null) => void` | | | 열림 변경 콜백 |
|
|
1658
|
+
| `collapsible` | `boolean` | | | single 모드에서 열린 패널을 다시 닫을 수 있게 허용 |
|
|
1659
|
+
| `disabled` | `boolean` | | | 전체 비활성화 |
|
|
1660
|
+
| `animated` | `boolean` | | | 콘텐츠 enter/leave 애니메이션 (기본 true) |
|
|
1661
|
+
| `children` | `ReactNode` | | | AccordionItem 목록 |
|
|
1662
|
+
|
|
1663
|
+
**AccordionItem:**
|
|
1664
|
+
|
|
1665
|
+
| Prop | Type | Required | Default | Description |
|
|
1666
|
+
| ---------- | ----------- | -------- | ------- | ------------------ |
|
|
1667
|
+
| `value` | `string` | Yes | | 항목 식별 값 |
|
|
1668
|
+
| `disabled` | `boolean` | | | 이 항목만 비활성화 |
|
|
1669
|
+
| `children` | `ReactNode` | | | Trigger + Content |
|
|
1670
|
+
|
|
1671
|
+
**AccordionTrigger:**
|
|
1672
|
+
|
|
1673
|
+
| Prop | Type | Required | Default | Description |
|
|
1674
|
+
| ---------- | ----------- | -------- | ------- | ----------------------------------- |
|
|
1675
|
+
| `children` | `ReactNode` | Yes | | 헤더 라벨 (쉐브론 아이콘 자동 추가) |
|
|
1676
|
+
|
|
1677
|
+
**AccordionContent:**
|
|
1678
|
+
|
|
1679
|
+
| Prop | Type | Required | Default | Description |
|
|
1680
|
+
| ---------- | ----------- | -------- | ------- | ------------------ |
|
|
1681
|
+
| `children` | `ReactNode` | Yes | | 펼쳐지는 패널 본문 |
|
|
1682
|
+
|
|
1683
|
+
### Meter
|
|
1684
|
+
|
|
1685
|
+
> 범위 내 스칼라 측정값 게이지 (디스크 사용량·점수·용량 등). role=meter로 작업 진행률(Progress)과 구분된다.
|
|
1686
|
+
|
|
1687
|
+
**Import:** `import { Meter } from "@reopt-ai/opt-ui"`
|
|
1688
|
+
|
|
1689
|
+
| Prop | Type | Required | Default | Description |
|
|
1690
|
+
| ----------- | ------------------------------------------------ | -------- | --------- | ------------- |
|
|
1691
|
+
| `value` | `number` | Yes | | 현재 값 |
|
|
1692
|
+
| `min` | `number` | | 0 | 최소 값 |
|
|
1693
|
+
| `max` | `number` | | 100 | 최대 값 |
|
|
1694
|
+
| `size` | `"sm" \| "md" \| "lg"` | | "md" | 게이지 높이 |
|
|
1695
|
+
| `variant` | `"default" \| "success" \| "warning" \| "error"` | | "default" | 색상 변형 |
|
|
1696
|
+
| `showValue` | `boolean` | | false | 퍼센트 표시 |
|
|
1697
|
+
| `label` | `string` | | | 레이블 텍스트 |
|
|
1698
|
+
|
|
1699
|
+
### BlockLayout
|
|
1700
|
+
|
|
1701
|
+
> Block 루트 레이아웃. flex + 기본 section spacing 적용, loading prop으로 LoadingOverlay 자동 래핑.
|
|
1702
|
+
|
|
1703
|
+
**Import:** `import { BlockLayout } from "@reopt-ai/opt-ui"`
|
|
1704
|
+
|
|
1705
|
+
| Prop | Type | Required | Default | Description |
|
|
1706
|
+
| -------------- | --------------------------------------------- | -------- | --------- | ------------------------------------------------------------------------------------ |
|
|
1707
|
+
| `children` | `ReactNode` | Yes | | Block 콘텐츠 |
|
|
1708
|
+
| `loading` | `boolean` | | | 로딩 상태. 설정 시 LoadingOverlay로 자동 래핑 |
|
|
1709
|
+
| `loadingLabel` | `string` | | | LoadingOverlay 접근성 레이블 |
|
|
1710
|
+
| `spacing` | `"section" \| "group" \| "element" \| "none"` | | "section" | Block 최상위 자식 사이 간격. 데이터 밀도가 높은 Block는 group/element로 낮출 수 있음 |
|
|
1711
|
+
| `className` | `string` | | | 기본 스타일 오버라이드 |
|
|
1712
|
+
|
|
1713
|
+
**Examples:**
|
|
1714
|
+
|
|
1715
|
+
_Block 루트:_
|
|
1716
|
+
|
|
1717
|
+
```tsx
|
|
1718
|
+
import { BlockLayout, PageHeader } from "@reopt-ai/opt-ui";
|
|
1719
|
+
|
|
1720
|
+
<BlockLayout loading={isLoading} spacing="section">
|
|
1721
|
+
<PageHeader title="대시보드" description="프로젝트 현황" />
|
|
1722
|
+
<section>콘텐츠 영역</section>
|
|
1723
|
+
</BlockLayout>;
|
|
1724
|
+
```
|
|
1725
|
+
|
|
1726
|
+
### createBlock
|
|
1727
|
+
|
|
1728
|
+
> Block 팩토리 함수. BlockLayout 래핑을 구조적으로 강제하여 loading/className 처리를 자동화합니다.
|
|
1729
|
+
|
|
1730
|
+
**Import:** `import { createBlock } from "@reopt-ai/opt-ui"`
|
|
1731
|
+
|
|
1732
|
+
| Prop | Type | Required | Default | Description |
|
|
1733
|
+
| ------------------------- | --------------------------------------------------------- | -------- | ------- | ----------------------------------- |
|
|
1734
|
+
| `name` | `string` | Yes | | 컴포넌트 displayName |
|
|
1735
|
+
| `render` | `(props: Omit<P, 'loading' \| 'className'>) => ReactNode` | Yes | | 콘텐츠를 반환하는 렌더 함수 |
|
|
1736
|
+
| `options.layoutClassName` | `string` | | | BlockLayout에 전달할 기본 className |
|
|
1737
|
+
|
|
1738
|
+
**Examples:**
|
|
1739
|
+
|
|
1740
|
+
_Block 팩토리:_
|
|
1741
|
+
|
|
1742
|
+
```tsx
|
|
1743
|
+
import { createBlock, PageHeader } from "@reopt-ai/opt-ui";
|
|
1744
|
+
|
|
1745
|
+
interface MyDashboardProps {
|
|
1746
|
+
title: string;
|
|
1747
|
+
count: number;
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
const MyDashboard = createBlock<MyDashboardProps>(
|
|
1751
|
+
"MyDashboard",
|
|
1752
|
+
({ title, count }) => (
|
|
1753
|
+
<>
|
|
1754
|
+
<PageHeader title={title} />
|
|
1755
|
+
<p>항목 수: {count}</p>
|
|
1756
|
+
</>
|
|
1757
|
+
),
|
|
1758
|
+
);
|
|
1759
|
+
|
|
1760
|
+
// loading, className은 자동 처리
|
|
1761
|
+
<MyDashboard title="개요" count={42} loading={false} />;
|
|
1762
|
+
```
|
|
1763
|
+
|
|
1764
|
+
### StarRating
|
|
1765
|
+
|
|
1766
|
+
> 1~N점 별점을 선택하는 인터랙티브 레이팅 입력. 읽기 전용 표시도 지원.
|
|
1767
|
+
|
|
1768
|
+
**Import:** `import { StarRating } from "@reopt-ai/opt-ui"`
|
|
1769
|
+
|
|
1770
|
+
| Prop | Type | Required | Default | Description |
|
|
1771
|
+
| ---------- | ------------------------- | -------- | ------- | ---------------- |
|
|
1772
|
+
| `value` | `number` | | | 현재 선택된 별점 |
|
|
1773
|
+
| `onChange` | `(value: number) => void` | | | 별점 변경 콜백 |
|
|
1774
|
+
| `max` | `number` | | 5 | 최대 별 개수 |
|
|
1775
|
+
| `readOnly` | `boolean` | | false | 읽기 전용 모드 |
|
|
1776
|
+
| `size` | `"sm" \| "md" \| "lg"` | | "md" | 별 아이콘 크기 |
|
|
1777
|
+
|
|
1778
|
+
### ErrorBoundary
|
|
1779
|
+
|
|
1780
|
+
> React 에러 바운더리. 자식 컴포넌트 렌더 에러를 잡아 fallback UI를 표시합니다.
|
|
1781
|
+
|
|
1782
|
+
**Import:** `import { ErrorBoundary } from "@reopt-ai/opt-ui"`
|
|
1783
|
+
|
|
1784
|
+
| Prop | Type | Required | Default | Description |
|
|
1785
|
+
| ---------- | -------------------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------- |
|
|
1786
|
+
| `children` | `ReactNode` | Yes | | 에러를 감시할 자식 컴포넌트 |
|
|
1787
|
+
| `fallback` | `ReactNode \| ((error: Error) => ReactNode)` | | | 에러 발생 시 표시할 UI. 함수 전달 시 에러 객체를 인자로 받음. 미지정 시 Alert error 표시 |
|
|
1788
|
+
| `onError` | `(error: Error, info: ErrorInfo) => void` | | | 에러 발생 시 호출되는 콜백 (에러 리포팅용) |
|
|
1789
|
+
|
|
1790
|
+
### Command
|
|
1791
|
+
|
|
1792
|
+
> cmdk 스타일 명령 anatomy. 자동 필터링 + 키보드 내비게이션. 인라인 또는 CommandDialog로 사용.
|
|
1793
|
+
|
|
1794
|
+
**Import:** `import { Command } from "@reopt-ai/opt-ui"`
|
|
1795
|
+
|
|
1796
|
+
**Command:**
|
|
1797
|
+
|
|
1798
|
+
| Prop | Type | Required | Default | Description |
|
|
1799
|
+
| -------------- | ---------------------------------------------------------------- | -------- | ------- | --------------------------------------------------- |
|
|
1800
|
+
| `shouldFilter` | `boolean` | | | 자동 필터링 여부 (기본 true) |
|
|
1801
|
+
| `filter` | `(value: string, search: string, keywords: string[]) => boolean` | | | 커스텀 필터 함수 (기본: case-insensitive substring) |
|
|
1802
|
+
|
|
1803
|
+
**CommandInput:**
|
|
1804
|
+
|
|
1805
|
+
| Prop | Type | Required | Default | Description |
|
|
1806
|
+
| ------------------ | ----------- | -------- | ------- | ----------------------------------- |
|
|
1807
|
+
| `trailing` | `ReactNode` | | | 검색 입력 우측에 표시할 보조 콘텐츠 |
|
|
1808
|
+
| `wrapperClassName` | `string` | | | 입력 wrapper className |
|
|
1809
|
+
|
|
1810
|
+
**CommandList:**
|
|
1811
|
+
|
|
1812
|
+
| Prop | Type | Required | Default | Description |
|
|
1813
|
+
| ------------ | -------- | -------- | ---------- | ------------------- |
|
|
1814
|
+
| `aria-label` | `string` | | "Commands" | listbox 접근성 라벨 |
|
|
1815
|
+
|
|
1816
|
+
**CommandItem:**
|
|
1817
|
+
|
|
1818
|
+
| Prop | Type | Required | Default | Description |
|
|
1819
|
+
| ---------- | ------------------------- | -------- | ------- | ---------------------------------------- |
|
|
1820
|
+
| `value` | `string` | Yes | | 이 항목의 검색 가능 값 (고유 식별자) |
|
|
1821
|
+
| `keywords` | `string[]` | | | value에 더해 검색어와 비교할 추가 키워드 |
|
|
1822
|
+
| `onSelect` | `(value: string) => void` | | | Enter/클릭 시 호출 |
|
|
1823
|
+
|
|
1824
|
+
### ShaderSurface
|
|
1825
|
+
|
|
1826
|
+
> ogl 기반 애니메이션 WebGL 셰이더 배경. 럭셔리 프리셋(메탈릭/실크/유리 등) + 색·파라미터로 배경·카드 배경을 만든다. 정지 프레임·PNG 캡처·WebGL 폴백 지원.
|
|
1827
|
+
|
|
1828
|
+
**Import:** `import { ShaderSurface } from "@reopt-ai/opt-ui"`
|
|
1829
|
+
|
|
1830
|
+
| Prop | Type | Required | Default | Description |
|
|
1831
|
+
| ------------ | ---------------- | -------- | ------- | ------------------------------------------ |
|
|
1832
|
+
| `preset` | `ShaderPresetId` | Yes | | 렌더할 셰이더 프리셋 id |
|
|
1833
|
+
| `colors` | `string[]` | | | hex 색상 배열 (미지정 시 프리셋 기본 색) |
|
|
1834
|
+
| `scale` | `number` | | | 패턴 스케일 |
|
|
1835
|
+
| `speed` | `number` | | | 애니메이션 속도 |
|
|
1836
|
+
| `distortion` | `number` | | | 왜곡 강도 |
|
|
1837
|
+
| `grain` | `number` | | | 필름 그레인 양 |
|
|
1838
|
+
| `contrast` | `number` | | | 하이라이트 대비 |
|
|
1839
|
+
| `angle` | `number` | | | 회전 각도(도) |
|
|
1840
|
+
| `paused` | `boolean` | | | true면 단일 프레임만 렌더 (카드 배경 등) |
|
|
1841
|
+
| `dpr` | `number` | | | device pixel ratio 상한 (기본 min(dpr, 2)) |
|