@bigtablet/design-system 1.18.0 → 1.18.2
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/README.md +27 -633
- package/dist/index.css +1 -0
- package/dist/index.d.ts +108 -9
- package/dist/next.d.ts +6 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/@bigtablet/design-system)
|
|
8
8
|
[](LICENSE)
|
|
9
|
+
[](https://github.com/Bigtablet/bigtablet-design-system/actions)
|
|
9
10
|
|
|
10
11
|
Bigtablet의 공식 디자인 시스템으로, Foundation(디자인 토큰)과 Components(UI 컴포넌트)로 구성된 통합 UI 라이브러리입니다.
|
|
11
12
|
|
|
@@ -15,19 +16,6 @@ Bigtablet의 공식 디자인 시스템으로, Foundation(디자인 토큰)과 C
|
|
|
15
16
|
|
|
16
17
|
---
|
|
17
18
|
|
|
18
|
-
## 목차
|
|
19
|
-
|
|
20
|
-
- [주요 특징](#주요-특징)
|
|
21
|
-
- [설치](#설치)
|
|
22
|
-
- [빠른 시작](#빠른-시작)
|
|
23
|
-
- [Vanilla JS (HTML/CSS/JS)](#vanilla-js-htmlcssjs)
|
|
24
|
-
- [컴포넌트](#컴포넌트)
|
|
25
|
-
- [Foundation (디자인 토큰)](#foundation-디자인-토큰)
|
|
26
|
-
- [개발 가이드](#개발-가이드)
|
|
27
|
-
- [기여하기](#기여하기)
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
19
|
## 주요 특징
|
|
32
20
|
|
|
33
21
|
- **React 19 지원** - 최신 React 버전 완벽 지원
|
|
@@ -36,7 +24,7 @@ Bigtablet의 공식 디자인 시스템으로, Foundation(디자인 토큰)과 C
|
|
|
36
24
|
- **Vanilla JS** - Thymeleaf, JSP 등 서버 템플릿 지원
|
|
37
25
|
- **디자인 토큰** - 일관된 색상, 타이포그래피, 간격 시스템
|
|
38
26
|
- **접근성(a11y)** - 키보드 네비게이션, 스크린 리더 호환
|
|
39
|
-
- **
|
|
27
|
+
- **86% 테스트 커버리지** - 안정적인 컴포넌트 품질
|
|
40
28
|
|
|
41
29
|
---
|
|
42
30
|
|
|
@@ -88,655 +76,61 @@ import '@bigtablet/design-system/style.css';
|
|
|
88
76
|
export default function Layout({ children }) {
|
|
89
77
|
return (
|
|
90
78
|
<div>
|
|
91
|
-
<Sidebar
|
|
92
|
-
items={[
|
|
93
|
-
{ label: '홈', href: '/' },
|
|
94
|
-
{ label: '대시보드', href: '/dashboard' }
|
|
95
|
-
]}
|
|
96
|
-
/>
|
|
79
|
+
<Sidebar items={[{ label: '홈', href: '/' }]} />
|
|
97
80
|
<main>{children}</main>
|
|
98
81
|
</div>
|
|
99
82
|
);
|
|
100
83
|
}
|
|
101
84
|
```
|
|
102
85
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
## Vanilla JS (HTML/CSS/JS)
|
|
106
|
-
|
|
107
|
-
React 없이 **Thymeleaf, JSP, PHP** 등 서버 템플릿 환경에서 사용할 수 있습니다.
|
|
86
|
+
### Vanilla JS (HTML/CSS/JS)
|
|
108
87
|
|
|
109
88
|
```html
|
|
110
|
-
<!-- CSS -->
|
|
111
89
|
<link rel="stylesheet" href="https://unpkg.com/@bigtablet/design-system/dist/vanilla/bigtablet.min.css">
|
|
112
|
-
|
|
113
|
-
<!-- JS (선택) -->
|
|
114
90
|
<script src="https://unpkg.com/@bigtablet/design-system/dist/vanilla/bigtablet.min.js"></script>
|
|
115
|
-
```
|
|
116
91
|
|
|
117
|
-
```html
|
|
118
92
|
<button class="bt-button bt-button--md bt-button--primary">버튼</button>
|
|
119
|
-
|
|
120
|
-
<div class="bt-text-field">
|
|
121
|
-
<label class="bt-text-field__label">이메일</label>
|
|
122
|
-
<div class="bt-text-field__wrap">
|
|
123
|
-
<input type="text" class="bt-text-field__input bt-text-field__input--outline bt-text-field__input--md">
|
|
124
|
-
</div>
|
|
125
|
-
</div>
|
|
126
93
|
```
|
|
127
94
|
|
|
128
|
-
👉 **[Vanilla JS 전체 문서 보기](./docs/VANILLA.md)**
|
|
129
|
-
|
|
130
95
|
---
|
|
131
96
|
|
|
132
97
|
## 컴포넌트
|
|
133
98
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
<Button>클릭</Button>
|
|
143
|
-
|
|
144
|
-
// Variants
|
|
145
|
-
<Button variant="primary">Primary</Button>
|
|
146
|
-
<Button variant="secondary">Secondary</Button>
|
|
147
|
-
<Button variant="ghost">Ghost</Button>
|
|
148
|
-
<Button variant="danger">Danger</Button>
|
|
149
|
-
|
|
150
|
-
// Sizes
|
|
151
|
-
<Button size="sm">Small</Button>
|
|
152
|
-
<Button size="md">Medium</Button>
|
|
153
|
-
<Button size="lg">Large</Button>
|
|
154
|
-
|
|
155
|
-
// 너비 조절
|
|
156
|
-
<Button width="200px">고정 너비</Button>
|
|
157
|
-
<Button width="100%">전체 너비</Button>
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
| Prop | Type | Default | Description |
|
|
161
|
-
|------|------|---------|-------------|
|
|
162
|
-
| `variant` | `'primary' \| 'secondary' \| 'ghost' \| 'danger'` | `'primary'` | 버튼 스타일 |
|
|
163
|
-
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 버튼 크기 |
|
|
164
|
-
| `width` | `string` | `'100%'` | 버튼 너비 |
|
|
165
|
-
| `disabled` | `boolean` | `false` | 비활성화 |
|
|
166
|
-
|
|
167
|
-
#### Select
|
|
168
|
-
|
|
169
|
-
```tsx
|
|
170
|
-
import { Select } from '@bigtablet/design-system';
|
|
171
|
-
|
|
172
|
-
const options = [
|
|
173
|
-
{ value: 'apple', label: '사과' },
|
|
174
|
-
{ value: 'banana', label: '바나나' },
|
|
175
|
-
{ value: 'orange', label: '오렌지', disabled: true },
|
|
176
|
-
];
|
|
177
|
-
|
|
178
|
-
// 기본 사용
|
|
179
|
-
<Select
|
|
180
|
-
label="과일 선택"
|
|
181
|
-
options={options}
|
|
182
|
-
placeholder="선택하세요"
|
|
183
|
-
onChange={(value, option) => console.log(value, option)}
|
|
184
|
-
/>
|
|
185
|
-
|
|
186
|
-
// Controlled
|
|
187
|
-
const [fruit, setFruit] = useState<string | null>(null);
|
|
188
|
-
<Select
|
|
189
|
-
options={options}
|
|
190
|
-
value={fruit}
|
|
191
|
-
onChange={(value) => setFruit(value)}
|
|
192
|
-
/>
|
|
193
|
-
|
|
194
|
-
// Variants & Sizes
|
|
195
|
-
<Select options={options} variant="outline" size="md" />
|
|
196
|
-
<Select options={options} variant="filled" size="lg" />
|
|
197
|
-
<Select options={options} variant="ghost" size="sm" />
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
| Prop | Type | Default | Description |
|
|
201
|
-
|------|------|---------|-------------|
|
|
202
|
-
| `options` | `SelectOption[]` | required | 옵션 목록 |
|
|
203
|
-
| `value` | `string \| null` | - | 선택된 값 (controlled) |
|
|
204
|
-
| `defaultValue` | `string \| null` | `null` | 기본 선택값 |
|
|
205
|
-
| `onChange` | `(value, option) => void` | - | 변경 핸들러 |
|
|
206
|
-
| `placeholder` | `string` | `'Select…'` | 플레이스홀더 |
|
|
207
|
-
| `variant` | `'outline' \| 'filled' \| 'ghost'` | `'outline'` | 스타일 |
|
|
208
|
-
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 크기 |
|
|
209
|
-
| `fullWidth` | `boolean` | `false` | 전체 너비 |
|
|
210
|
-
| `disabled` | `boolean` | `false` | 비활성화 |
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
### Form
|
|
215
|
-
|
|
216
|
-
#### TextField
|
|
217
|
-
|
|
218
|
-
```tsx
|
|
219
|
-
import { TextField } from '@bigtablet/design-system';
|
|
220
|
-
|
|
221
|
-
// 기본 사용
|
|
222
|
-
<TextField label="이름" placeholder="이름을 입력하세요" />
|
|
223
|
-
|
|
224
|
-
// 상태 표시
|
|
225
|
-
<TextField label="이메일" error helperText="유효하지 않은 이메일입니다" />
|
|
226
|
-
<TextField label="이메일" success helperText="사용 가능한 이메일입니다" />
|
|
227
|
-
|
|
228
|
-
// 아이콘
|
|
229
|
-
import { Search, Eye } from 'lucide-react';
|
|
230
|
-
<TextField leftIcon={<Search size={16} />} placeholder="검색..." />
|
|
231
|
-
<TextField rightIcon={<Eye size={16} />} type="password" />
|
|
232
|
-
|
|
233
|
-
// Variants
|
|
234
|
-
<TextField variant="outline" label="Outline" />
|
|
235
|
-
<TextField variant="filled" label="Filled" />
|
|
236
|
-
<TextField variant="ghost" label="Ghost" />
|
|
237
|
-
|
|
238
|
-
// 값 변환 (자동 포맷팅)
|
|
239
|
-
<TextField
|
|
240
|
-
label="전화번호"
|
|
241
|
-
transformValue={(v) => v.replace(/\D/g, '').slice(0, 11)}
|
|
242
|
-
onChangeAction={(value) => console.log(value)}
|
|
243
|
-
/>
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
| Prop | Type | Default | Description |
|
|
247
|
-
|------|------|---------|-------------|
|
|
248
|
-
| `label` | `string` | - | 라벨 |
|
|
249
|
-
| `helperText` | `string` | - | 도움말 텍스트 |
|
|
250
|
-
| `error` | `boolean` | `false` | 에러 상태 |
|
|
251
|
-
| `success` | `boolean` | `false` | 성공 상태 |
|
|
252
|
-
| `variant` | `'outline' \| 'filled' \| 'ghost'` | `'outline'` | 스타일 |
|
|
253
|
-
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 크기 |
|
|
254
|
-
| `leftIcon` | `ReactNode` | - | 왼쪽 아이콘 |
|
|
255
|
-
| `rightIcon` | `ReactNode` | - | 오른쪽 아이콘 |
|
|
256
|
-
| `fullWidth` | `boolean` | `false` | 전체 너비 |
|
|
257
|
-
| `onChangeAction` | `(value: string) => void` | - | 값 변경 콜백 |
|
|
258
|
-
| `transformValue` | `(value: string) => string` | - | 값 변환 함수 |
|
|
259
|
-
|
|
260
|
-
#### DatePicker
|
|
261
|
-
|
|
262
|
-
```tsx
|
|
263
|
-
import { DatePicker } from '@bigtablet/design-system';
|
|
264
|
-
|
|
265
|
-
// 기본 사용 (연-월-일)
|
|
266
|
-
const [date, setDate] = useState('');
|
|
267
|
-
<DatePicker
|
|
268
|
-
label="생년월일"
|
|
269
|
-
value={date}
|
|
270
|
-
onChange={setDate}
|
|
271
|
-
/>
|
|
272
|
-
|
|
273
|
-
// 연-월 모드
|
|
274
|
-
<DatePicker
|
|
275
|
-
label="시작 월"
|
|
276
|
-
mode="year-month"
|
|
277
|
-
value={date}
|
|
278
|
-
onChange={setDate}
|
|
279
|
-
/>
|
|
280
|
-
|
|
281
|
-
// 범위 제한
|
|
282
|
-
<DatePicker
|
|
283
|
-
label="예약일"
|
|
284
|
-
startYear={2020}
|
|
285
|
-
endYear={2030}
|
|
286
|
-
selectableRange="until-today" // 오늘까지만 선택 가능
|
|
287
|
-
value={date}
|
|
288
|
-
onChange={setDate}
|
|
289
|
-
/>
|
|
290
|
-
|
|
291
|
-
// 너비 조절
|
|
292
|
-
<DatePicker label="날짜" width={300} onChange={setDate} />
|
|
293
|
-
<DatePicker label="날짜" width="50%" onChange={setDate} />
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
| Prop | Type | Default | Description |
|
|
297
|
-
|------|------|---------|-------------|
|
|
298
|
-
| `label` | `string` | - | 라벨 |
|
|
299
|
-
| `value` | `string` | - | 선택된 날짜 (`'YYYY-MM-DD'` 또는 `'YYYY-MM'`) |
|
|
300
|
-
| `onChange` | `(value: string) => void` | required | 변경 핸들러 |
|
|
301
|
-
| `mode` | `'year-month' \| 'year-month-day'` | `'year-month-day'` | 날짜 선택 모드 |
|
|
302
|
-
| `startYear` | `number` | `1950` | 시작 연도 |
|
|
303
|
-
| `endYear` | `number` | `현재년도 + 10` | 종료 연도 |
|
|
304
|
-
| `selectableRange` | `'all' \| 'until-today'` | `'all'` | 선택 가능 범위 |
|
|
305
|
-
| `minDate` | `string` | - | 최소 날짜 |
|
|
306
|
-
| `width` | `number \| string` | `'100%'` | 너비 |
|
|
307
|
-
| `disabled` | `boolean` | `false` | 비활성화 |
|
|
308
|
-
|
|
309
|
-
#### Checkbox
|
|
310
|
-
|
|
311
|
-
```tsx
|
|
312
|
-
import { Checkbox } from '@bigtablet/design-system';
|
|
313
|
-
|
|
314
|
-
// 기본 사용
|
|
315
|
-
<Checkbox label="동의합니다" />
|
|
316
|
-
|
|
317
|
-
// Controlled
|
|
318
|
-
const [checked, setChecked] = useState(false);
|
|
319
|
-
<Checkbox
|
|
320
|
-
label="알림 받기"
|
|
321
|
-
checked={checked}
|
|
322
|
-
onChange={(e) => setChecked(e.target.checked)}
|
|
323
|
-
/>
|
|
324
|
-
|
|
325
|
-
// Indeterminate (부분 선택)
|
|
326
|
-
<Checkbox label="전체 선택" indeterminate />
|
|
327
|
-
|
|
328
|
-
// Sizes
|
|
329
|
-
<Checkbox size="sm" label="Small" />
|
|
330
|
-
<Checkbox size="md" label="Medium" />
|
|
331
|
-
<Checkbox size="lg" label="Large" />
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
| Prop | Type | Default | Description |
|
|
335
|
-
|------|------|---------|-------------|
|
|
336
|
-
| `label` | `ReactNode` | - | 라벨 |
|
|
337
|
-
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 크기 |
|
|
338
|
-
| `indeterminate` | `boolean` | `false` | 부분 선택 상태 |
|
|
339
|
-
| `checked` | `boolean` | - | 체크 상태 |
|
|
340
|
-
| `disabled` | `boolean` | `false` | 비활성화 |
|
|
341
|
-
|
|
342
|
-
#### Radio
|
|
343
|
-
|
|
344
|
-
```tsx
|
|
345
|
-
import { Radio } from '@bigtablet/design-system';
|
|
346
|
-
|
|
347
|
-
const [selected, setSelected] = useState('option1');
|
|
348
|
-
|
|
349
|
-
<Radio
|
|
350
|
-
name="options"
|
|
351
|
-
value="option1"
|
|
352
|
-
label="옵션 1"
|
|
353
|
-
checked={selected === 'option1'}
|
|
354
|
-
onChange={(e) => setSelected(e.target.value)}
|
|
355
|
-
/>
|
|
356
|
-
<Radio
|
|
357
|
-
name="options"
|
|
358
|
-
value="option2"
|
|
359
|
-
label="옵션 2"
|
|
360
|
-
checked={selected === 'option2'}
|
|
361
|
-
onChange={(e) => setSelected(e.target.value)}
|
|
362
|
-
/>
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
#### Switch
|
|
366
|
-
|
|
367
|
-
```tsx
|
|
368
|
-
import { Switch } from '@bigtablet/design-system';
|
|
369
|
-
|
|
370
|
-
// 기본 사용
|
|
371
|
-
<Switch onChange={(checked) => console.log(checked)} />
|
|
372
|
-
|
|
373
|
-
// Controlled
|
|
374
|
-
const [isOn, setIsOn] = useState(false);
|
|
375
|
-
<Switch checked={isOn} onChange={setIsOn} />
|
|
376
|
-
|
|
377
|
-
// Sizes
|
|
378
|
-
<Switch size="sm" />
|
|
379
|
-
<Switch size="md" />
|
|
380
|
-
<Switch size="lg" />
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
| Prop | Type | Default | Description |
|
|
384
|
-
|------|------|---------|-------------|
|
|
385
|
-
| `checked` | `boolean` | - | 켜짐 상태 (controlled) |
|
|
386
|
-
| `defaultChecked` | `boolean` | `false` | 기본 상태 |
|
|
387
|
-
| `onChange` | `(checked: boolean) => void` | - | 변경 핸들러 |
|
|
388
|
-
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 크기 |
|
|
389
|
-
| `disabled` | `boolean` | `false` | 비활성화 |
|
|
390
|
-
|
|
391
|
-
#### FileInput
|
|
392
|
-
|
|
393
|
-
```tsx
|
|
394
|
-
import { FileInput } from '@bigtablet/design-system';
|
|
395
|
-
|
|
396
|
-
<FileInput
|
|
397
|
-
label="파일 선택"
|
|
398
|
-
accept="image/*"
|
|
399
|
-
onFiles={(files) => console.log(files)}
|
|
400
|
-
/>
|
|
401
|
-
|
|
402
|
-
// 여러 파일
|
|
403
|
-
<FileInput
|
|
404
|
-
label="이미지 업로드"
|
|
405
|
-
accept="image/*"
|
|
406
|
-
multiple
|
|
407
|
-
onFiles={(files) => console.log(files)}
|
|
408
|
-
/>
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
| Prop | Type | Default | Description |
|
|
412
|
-
|------|------|---------|-------------|
|
|
413
|
-
| `label` | `string` | `'파일 선택'` | 버튼 라벨 |
|
|
414
|
-
| `accept` | `string` | - | 허용 파일 타입 |
|
|
415
|
-
| `onFiles` | `(files: FileList \| null) => void` | - | 파일 선택 핸들러 |
|
|
416
|
-
| `multiple` | `boolean` | `false` | 다중 선택 |
|
|
417
|
-
| `disabled` | `boolean` | `false` | 비활성화 |
|
|
418
|
-
|
|
419
|
-
---
|
|
420
|
-
|
|
421
|
-
### Feedback
|
|
422
|
-
|
|
423
|
-
#### Alert
|
|
424
|
-
|
|
425
|
-
```tsx
|
|
426
|
-
import { AlertProvider, useAlert } from '@bigtablet/design-system';
|
|
427
|
-
|
|
428
|
-
// App에 Provider 추가
|
|
429
|
-
function App() {
|
|
430
|
-
return (
|
|
431
|
-
<AlertProvider>
|
|
432
|
-
<YourComponent />
|
|
433
|
-
</AlertProvider>
|
|
434
|
-
);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// 사용
|
|
438
|
-
function YourComponent() {
|
|
439
|
-
const { showAlert } = useAlert();
|
|
440
|
-
|
|
441
|
-
const handleDelete = () => {
|
|
442
|
-
showAlert({
|
|
443
|
-
variant: 'warning',
|
|
444
|
-
title: '삭제 확인',
|
|
445
|
-
message: '정말 삭제하시겠습니까?',
|
|
446
|
-
showCancel: true,
|
|
447
|
-
confirmText: '삭제',
|
|
448
|
-
cancelText: '취소',
|
|
449
|
-
onConfirm: () => console.log('삭제됨'),
|
|
450
|
-
onCancel: () => console.log('취소됨'),
|
|
451
|
-
});
|
|
452
|
-
};
|
|
453
|
-
|
|
454
|
-
return <button onClick={handleDelete}>삭제</button>;
|
|
455
|
-
}
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
| Option | Type | Default | Description |
|
|
459
|
-
|--------|------|---------|-------------|
|
|
460
|
-
| `variant` | `'info' \| 'success' \| 'warning' \| 'error'` | `'info'` | 알림 타입 |
|
|
461
|
-
| `title` | `ReactNode` | - | 제목 |
|
|
462
|
-
| `message` | `ReactNode` | - | 메시지 |
|
|
463
|
-
| `confirmText` | `string` | `'확인'` | 확인 버튼 텍스트 |
|
|
464
|
-
| `cancelText` | `string` | `'취소'` | 취소 버튼 텍스트 |
|
|
465
|
-
| `showCancel` | `boolean` | `false` | 취소 버튼 표시 |
|
|
466
|
-
| `actionsAlign` | `'left' \| 'center' \| 'right'` | `'right'` | 버튼 정렬 |
|
|
467
|
-
| `onConfirm` | `() => void` | - | 확인 핸들러 |
|
|
468
|
-
| `onCancel` | `() => void` | - | 취소 핸들러 |
|
|
469
|
-
|
|
470
|
-
#### Toast
|
|
471
|
-
|
|
472
|
-
```tsx
|
|
473
|
-
import { ToastProvider, useToast } from '@bigtablet/design-system';
|
|
474
|
-
|
|
475
|
-
// App에 Provider 추가
|
|
476
|
-
function App() {
|
|
477
|
-
return (
|
|
478
|
-
<>
|
|
479
|
-
<ToastProvider />
|
|
480
|
-
<YourComponent />
|
|
481
|
-
</>
|
|
482
|
-
);
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
// 사용
|
|
486
|
-
function YourComponent() {
|
|
487
|
-
const toast = useToast();
|
|
488
|
-
|
|
489
|
-
return (
|
|
490
|
-
<div>
|
|
491
|
-
<button onClick={() => toast.success('저장되었습니다')}>성공</button>
|
|
492
|
-
<button onClick={() => toast.error('오류가 발생했습니다')}>에러</button>
|
|
493
|
-
<button onClick={() => toast.warning('주의가 필요합니다')}>경고</button>
|
|
494
|
-
<button onClick={() => toast.info('참고 정보입니다')}>정보</button>
|
|
495
|
-
<button onClick={() => toast.message('일반 메시지')}>메시지</button>
|
|
496
|
-
</div>
|
|
497
|
-
);
|
|
498
|
-
}
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
#### Spinner
|
|
502
|
-
|
|
503
|
-
```tsx
|
|
504
|
-
import { Spinner } from '@bigtablet/design-system';
|
|
505
|
-
|
|
506
|
-
<Spinner /> // 기본 (24px)
|
|
507
|
-
<Spinner size={16} /> // 작은 크기
|
|
508
|
-
<Spinner size={48} /> // 큰 크기
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
#### TopLoading
|
|
512
|
-
|
|
513
|
-
```tsx
|
|
514
|
-
import { TopLoading } from '@bigtablet/design-system';
|
|
515
|
-
|
|
516
|
-
// Indeterminate (무한 로딩)
|
|
517
|
-
<TopLoading isLoading />
|
|
518
|
-
|
|
519
|
-
// Progress (진행률 표시)
|
|
520
|
-
<TopLoading isLoading progress={65} />
|
|
521
|
-
|
|
522
|
-
// 커스텀 스타일
|
|
523
|
-
<TopLoading isLoading color="#ff0000" height={5} />
|
|
524
|
-
|
|
525
|
-
// 숨기기
|
|
526
|
-
<TopLoading isLoading={false} />
|
|
527
|
-
```
|
|
528
|
-
|
|
529
|
-
| Prop | Type | Default | Description |
|
|
530
|
-
|------|------|---------|-------------|
|
|
531
|
-
| `isLoading` | `boolean` | `true` | 표시 여부 |
|
|
532
|
-
| `progress` | `number` | - | 진행률 (0-100), 없으면 indeterminate |
|
|
533
|
-
| `color` | `string` | primary | 로딩바 색상 |
|
|
534
|
-
| `height` | `number` | `3` | 로딩바 높이 (px) |
|
|
535
|
-
|
|
536
|
-
---
|
|
537
|
-
|
|
538
|
-
### Navigation
|
|
539
|
-
|
|
540
|
-
#### Pagination
|
|
541
|
-
|
|
542
|
-
```tsx
|
|
543
|
-
import { Pagination } from '@bigtablet/design-system';
|
|
544
|
-
|
|
545
|
-
const [page, setPage] = useState(1);
|
|
546
|
-
|
|
547
|
-
<Pagination
|
|
548
|
-
page={page}
|
|
549
|
-
totalPages={20}
|
|
550
|
-
onChange={setPage}
|
|
551
|
-
/>
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
| Prop | Type | Default | Description |
|
|
555
|
-
|------|------|---------|-------------|
|
|
556
|
-
| `page` | `number` | required | 현재 페이지 |
|
|
557
|
-
| `totalPages` | `number` | required | 전체 페이지 수 |
|
|
558
|
-
| `onChange` | `(page: number) => void` | required | 페이지 변경 핸들러 |
|
|
559
|
-
|
|
560
|
-
#### Sidebar (Next.js)
|
|
561
|
-
|
|
562
|
-
```tsx
|
|
563
|
-
import { Sidebar } from '@bigtablet/design-system/next';
|
|
564
|
-
import { Home, Settings, Users } from 'lucide-react';
|
|
565
|
-
|
|
566
|
-
const items = [
|
|
567
|
-
{ href: '/', label: '홈', icon: Home },
|
|
568
|
-
{ href: '/users', label: '사용자', icon: Users },
|
|
569
|
-
{
|
|
570
|
-
type: 'group',
|
|
571
|
-
id: 'settings',
|
|
572
|
-
label: '설정',
|
|
573
|
-
icon: Settings,
|
|
574
|
-
children: [
|
|
575
|
-
{ href: '/settings/profile', label: '프로필' },
|
|
576
|
-
{ href: '/settings/security', label: '보안' },
|
|
577
|
-
],
|
|
578
|
-
},
|
|
579
|
-
];
|
|
580
|
-
|
|
581
|
-
<Sidebar
|
|
582
|
-
items={items}
|
|
583
|
-
activePath={pathname}
|
|
584
|
-
match="startsWith"
|
|
585
|
-
brandHref="/main"
|
|
586
|
-
/>
|
|
587
|
-
```
|
|
588
|
-
|
|
589
|
-
| Prop | Type | Default | Description |
|
|
590
|
-
|------|------|---------|-------------|
|
|
591
|
-
| `items` | `SidebarItem[]` | `[]` | 메뉴 아이템 |
|
|
592
|
-
| `activePath` | `string` | - | 현재 활성 경로 |
|
|
593
|
-
| `match` | `'startsWith' \| 'exact'` | `'startsWith'` | 경로 매칭 방식 |
|
|
594
|
-
| `brandHref` | `string` | `'/main'` | 로고 클릭 시 이동 경로 |
|
|
595
|
-
| `onItemSelect` | `(href: string) => void` | - | 아이템 선택 핸들러 |
|
|
99
|
+
| Category | Components |
|
|
100
|
+
|----------|------------|
|
|
101
|
+
| **General** | Button, Select |
|
|
102
|
+
| **Form** | TextField, Checkbox, Radio, Switch, DatePicker, FileInput |
|
|
103
|
+
| **Feedback** | Alert, Toast, Spinner, TopLoading |
|
|
104
|
+
| **Navigation** | Pagination, Sidebar |
|
|
105
|
+
| **Overlay** | Modal |
|
|
106
|
+
| **Display** | Card |
|
|
596
107
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
### Overlay
|
|
600
|
-
|
|
601
|
-
#### Modal
|
|
602
|
-
|
|
603
|
-
```tsx
|
|
604
|
-
import { Modal } from '@bigtablet/design-system';
|
|
605
|
-
|
|
606
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
607
|
-
|
|
608
|
-
<button onClick={() => setIsOpen(true)}>모달 열기</button>
|
|
609
|
-
|
|
610
|
-
<Modal
|
|
611
|
-
open={isOpen}
|
|
612
|
-
onClose={() => setIsOpen(false)}
|
|
613
|
-
title="모달 제목"
|
|
614
|
-
width={600}
|
|
615
|
-
>
|
|
616
|
-
<p>모달 내용입니다.</p>
|
|
617
|
-
</Modal>
|
|
618
|
-
```
|
|
619
|
-
|
|
620
|
-
| Prop | Type | Default | Description |
|
|
621
|
-
|------|------|---------|-------------|
|
|
622
|
-
| `open` | `boolean` | required | 열림 상태 |
|
|
623
|
-
| `onClose` | `() => void` | - | 닫기 핸들러 |
|
|
624
|
-
| `title` | `ReactNode` | - | 제목 |
|
|
625
|
-
| `width` | `number \| string` | `520` | 모달 너비 |
|
|
626
|
-
| `closeOnOverlay` | `boolean` | `true` | 오버레이 클릭 시 닫기 |
|
|
627
|
-
|
|
628
|
-
---
|
|
629
|
-
|
|
630
|
-
### Display
|
|
631
|
-
|
|
632
|
-
#### Card
|
|
633
|
-
|
|
634
|
-
```tsx
|
|
635
|
-
import { Card } from '@bigtablet/design-system';
|
|
636
|
-
|
|
637
|
-
<Card heading="카드 제목">
|
|
638
|
-
<p>카드 내용입니다.</p>
|
|
639
|
-
</Card>
|
|
640
|
-
|
|
641
|
-
// 스타일 옵션
|
|
642
|
-
<Card heading="제목" shadow="lg" padding="lg" bordered>
|
|
643
|
-
내용
|
|
644
|
-
</Card>
|
|
645
|
-
```
|
|
646
|
-
|
|
647
|
-
| Prop | Type | Default | Description |
|
|
648
|
-
|------|------|---------|-------------|
|
|
649
|
-
| `heading` | `ReactNode` | - | 카드 제목 |
|
|
650
|
-
| `shadow` | `'none' \| 'sm' \| 'md' \| 'lg'` | `'sm'` | 그림자 |
|
|
651
|
-
| `padding` | `'none' \| 'sm' \| 'md' \| 'lg'` | `'md'` | 내부 여백 |
|
|
652
|
-
| `bordered` | `boolean` | `false` | 테두리 표시 |
|
|
108
|
+
👉 **[전체 컴포넌트 문서](./docs/COMPONENTS.md)**
|
|
653
109
|
|
|
654
110
|
---
|
|
655
111
|
|
|
656
|
-
##
|
|
112
|
+
## 문서
|
|
657
113
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
.
|
|
664
|
-
|
|
665
|
-
padding: token.$spacing_md;
|
|
666
|
-
border-radius: token.$radius_sm;
|
|
667
|
-
font-size: token.$font_size_base;
|
|
668
|
-
}
|
|
669
|
-
```
|
|
670
|
-
|
|
671
|
-
### 주요 토큰
|
|
672
|
-
|
|
673
|
-
| Category | Examples |
|
|
674
|
-
|----------|----------|
|
|
675
|
-
| **Colors** | `$color_primary`, `$color_error`, `$color_text_primary` |
|
|
676
|
-
| **Spacing** | `$spacing_xs` (4px), `$spacing_sm` (8px), `$spacing_md` (16px) |
|
|
677
|
-
| **Typography** | `$font_size_sm`, `$font_size_base`, `$font_weight_medium` |
|
|
678
|
-
| **Radius** | `$radius_sm` (4px), `$radius_md` (8px), `$radius_lg` (12px) |
|
|
679
|
-
| **Shadows** | `$shadow_sm`, `$shadow_md`, `$shadow_lg` |
|
|
680
|
-
| **Z-Index** | `$z_dropdown`, `$z_modal`, `$z_toast` |
|
|
681
|
-
|
|
682
|
-
---
|
|
683
|
-
|
|
684
|
-
## 프로젝트 구조
|
|
685
|
-
|
|
686
|
-
```
|
|
687
|
-
src/
|
|
688
|
-
├── styles/
|
|
689
|
-
│ ├── ts/ # TypeScript 디자인 토큰
|
|
690
|
-
│ └── scss/ # SCSS 토큰 및 믹스인
|
|
691
|
-
├── ui/
|
|
692
|
-
│ ├── general/ # Button, Select
|
|
693
|
-
│ ├── form/ # TextField, Checkbox, Radio, Switch, DatePicker, FileInput
|
|
694
|
-
│ ├── feedback/ # Alert, Toast, Spinner, TopLoading
|
|
695
|
-
│ ├── navigation/ # Pagination, Sidebar
|
|
696
|
-
│ ├── overlay/ # Modal
|
|
697
|
-
│ └── display/ # Card
|
|
698
|
-
├── index.ts # Pure React 진입점
|
|
699
|
-
└── next.ts # Next.js 진입점
|
|
700
|
-
```
|
|
114
|
+
| 문서 | 설명 |
|
|
115
|
+
|------|------|
|
|
116
|
+
| [Components](./docs/COMPONENTS.md) | 컴포넌트 API 및 사용법 |
|
|
117
|
+
| [Vanilla JS](./docs/VANILLA.md) | HTML/CSS/JS 환경 가이드 |
|
|
118
|
+
| [Architecture](./docs/ARCHITECTURE.md) | 프로젝트 구조 및 아키텍처 |
|
|
119
|
+
| [Contributing](./docs/CONTRIBUTING.md) | 기여 가이드라인 |
|
|
120
|
+
| [Testing](./docs/TESTING.md) | 테스트 작성 가이드 |
|
|
701
121
|
|
|
702
122
|
---
|
|
703
123
|
|
|
704
|
-
## 개발
|
|
124
|
+
## 개발
|
|
705
125
|
|
|
706
126
|
```bash
|
|
707
|
-
#
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
# 의존성 설치
|
|
712
|
-
pnpm install
|
|
713
|
-
|
|
714
|
-
# Storybook 실행
|
|
715
|
-
pnpm storybook
|
|
716
|
-
|
|
717
|
-
# 빌드
|
|
718
|
-
pnpm build
|
|
127
|
+
pnpm install # 의존성 설치
|
|
128
|
+
pnpm storybook # Storybook 실행 (port 6006)
|
|
129
|
+
pnpm build # 라이브러리 빌드
|
|
130
|
+
pnpm test # 테스트 실행
|
|
719
131
|
```
|
|
720
132
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
## 기여하기
|
|
724
|
-
|
|
725
|
-
1. Fork the repository
|
|
726
|
-
2. Create your feature branch (`git checkout -b feat/amazing-feature`)
|
|
727
|
-
3. Commit your changes (`git commit -m 'feat: add amazing feature'`)
|
|
728
|
-
4. Push to the branch (`git push origin feat/amazing-feature`)
|
|
729
|
-
5. Open a Pull Request to `develop` branch
|
|
730
|
-
|
|
731
|
-
### Commit Convention
|
|
732
|
-
|
|
733
|
-
| Label | Description |
|
|
734
|
-
|-------|-------------|
|
|
735
|
-
| `feat` | 새로운 기능 |
|
|
736
|
-
| `fix` | 버그/코드 수정 |
|
|
737
|
-
| `docs` | 문서 수정 |
|
|
738
|
-
| `style` | 코드 스타일 변경 |
|
|
739
|
-
| `config` | 설정 파일 수정 |
|
|
133
|
+
👉 **[개발 환경 설정](./docs/CONTRIBUTING.md#개발-환경-설정)**
|
|
740
134
|
|
|
741
135
|
---
|
|
742
136
|
|
package/dist/index.css
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,12 @@ interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
8
8
|
padding?: "none" | "sm" | "md" | "lg";
|
|
9
9
|
bordered?: boolean;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* 카드 컴포넌트를 렌더링한다.
|
|
13
|
+
* 그림자/패딩/테두리 옵션을 조합해 레이아웃 컨테이너를 구성한다.
|
|
14
|
+
* @param props 카드 속성
|
|
15
|
+
* @returns 렌더링된 카드 UI
|
|
16
|
+
*/
|
|
11
17
|
declare const Card: ({ heading, shadow, padding, bordered, className, children, ...props }: CardProps) => react_jsx_runtime.JSX.Element;
|
|
12
18
|
|
|
13
19
|
type AlertVariant = "info" | "success" | "warning" | "error";
|
|
@@ -26,16 +32,33 @@ interface AlertOptions {
|
|
|
26
32
|
interface AlertContextValue {
|
|
27
33
|
showAlert: (options: AlertOptions) => void;
|
|
28
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* AlertContext를 사용하는 훅.
|
|
37
|
+
* Provider 외부에서 호출되면 오류를 던진다.
|
|
38
|
+
* @returns alert 컨트롤러
|
|
39
|
+
*/
|
|
29
40
|
declare const useAlert: () => AlertContextValue;
|
|
41
|
+
/**
|
|
42
|
+
* 알림 모달을 제어하는 Provider를 렌더링한다.
|
|
43
|
+
* 내부 상태를 통해 AlertModal 표시와 확인/취소 흐름을 관리한다.
|
|
44
|
+
* @param props Provider 속성
|
|
45
|
+
* @returns 렌더링된 Provider와 모달
|
|
46
|
+
*/
|
|
30
47
|
declare const AlertProvider: React.FC<{
|
|
31
48
|
children: React.ReactNode;
|
|
32
49
|
}>;
|
|
33
50
|
|
|
34
51
|
interface SpinnerProps {
|
|
35
52
|
size?: number;
|
|
36
|
-
/**
|
|
53
|
+
/** 스피너 접근성 레이블 (기본값: "Loading") */
|
|
37
54
|
ariaLabel?: string;
|
|
38
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* 스피너를 렌더링한다.
|
|
58
|
+
* 크기와 접근성 레이블을 적용한 뒤 상태 표시용 요소를 반환한다.
|
|
59
|
+
* @param props 스피너 속성
|
|
60
|
+
* @returns 렌더링된 스피너 요소
|
|
61
|
+
*/
|
|
39
62
|
declare const Spinner: ({ size, ariaLabel }: SpinnerProps) => react_jsx_runtime.JSX.Element;
|
|
40
63
|
|
|
41
64
|
interface TopLoadingProps {
|
|
@@ -50,11 +73,23 @@ interface TopLoadingProps {
|
|
|
50
73
|
/** 프로그레스 바의 접근성 레이블 (기본값: "Page loading") */
|
|
51
74
|
ariaLabel?: string;
|
|
52
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* 상단 로딩바를 렌더링한다.
|
|
78
|
+
* 표시 여부와 진행률에 따라 determinate/indeterminate 상태를 구성한다.
|
|
79
|
+
* @param props 로딩바 속성
|
|
80
|
+
* @returns 렌더링된 로딩바 요소 또는 null
|
|
81
|
+
*/
|
|
53
82
|
declare const TopLoading: ({ progress, color, height, isLoading, ariaLabel, }: TopLoadingProps) => react_jsx_runtime.JSX.Element | null;
|
|
54
83
|
|
|
55
84
|
interface ToastProviderProps {
|
|
56
85
|
containerId?: string;
|
|
57
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* 토스트 컨테이너를 렌더링한다.
|
|
89
|
+
* 기본 옵션을 설정하고 전역 토스트 표시 영역을 제공한다.
|
|
90
|
+
* @param props 토스트 컨테이너 속성
|
|
91
|
+
* @returns 렌더링된 토스트 컨테이너
|
|
92
|
+
*/
|
|
58
93
|
declare const ToastProvider: ({ containerId }: ToastProviderProps) => react_jsx_runtime.JSX.Element;
|
|
59
94
|
|
|
60
95
|
declare const useToast: (containerId?: string) => {
|
|
@@ -68,14 +103,20 @@ declare const useToast: (containerId?: string) => {
|
|
|
68
103
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
69
104
|
variant?: "primary" | "secondary" | "ghost" | "danger";
|
|
70
105
|
size?: "sm" | "md" | "lg";
|
|
71
|
-
/**
|
|
106
|
+
/** 버튼이 컨테이너의 전체 너비를 차지할지 여부 */
|
|
72
107
|
fullWidth?: boolean;
|
|
73
108
|
/**
|
|
74
|
-
*
|
|
75
|
-
* @deprecated
|
|
109
|
+
* 버튼의 커스텀 너비
|
|
110
|
+
* @deprecated `fullWidth` 사용 또는 CSS로 처리
|
|
76
111
|
*/
|
|
77
112
|
width?: string;
|
|
78
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* 버튼을 렌더링한다.
|
|
116
|
+
* 전달된 props로 클래스 조합과 인라인 스타일을 계산한 뒤 버튼 요소를 반환한다.
|
|
117
|
+
* @param props 버튼 속성
|
|
118
|
+
* @returns 렌더링된 버튼 요소
|
|
119
|
+
*/
|
|
79
120
|
declare const Button: ({ variant, size, fullWidth, width, className, style, ...props }: ButtonProps) => react_jsx_runtime.JSX.Element;
|
|
80
121
|
|
|
81
122
|
interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> {
|
|
@@ -83,18 +124,38 @@ interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>
|
|
|
83
124
|
size?: "sm" | "md" | "lg";
|
|
84
125
|
indeterminate?: boolean;
|
|
85
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* 체크박스를 렌더링한다.
|
|
129
|
+
* indeterminate 상태를 반영하고 라벨을 포함한 UI를 구성한다.
|
|
130
|
+
* @param props 체크박스 속성
|
|
131
|
+
* @param ref 입력 요소 참조
|
|
132
|
+
* @returns 렌더링된 체크박스 UI
|
|
133
|
+
*/
|
|
86
134
|
declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
|
|
87
135
|
|
|
88
136
|
interface FileInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
89
137
|
label?: string;
|
|
90
138
|
onFiles?: (files: FileList | null) => void;
|
|
91
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* 파일 입력 컴포넌트를 렌더링한다.
|
|
142
|
+
* 내부 input 변경을 감지해 파일 목록을 콜백으로 전달한다.
|
|
143
|
+
* @param props 파일 입력 속성
|
|
144
|
+
* @returns 렌더링된 파일 입력 UI
|
|
145
|
+
*/
|
|
92
146
|
declare const FileInput: ({ label, onFiles, className, disabled, ...props }: FileInputProps) => react_jsx_runtime.JSX.Element;
|
|
93
147
|
|
|
94
148
|
interface RadioProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> {
|
|
95
149
|
label?: React.ReactNode;
|
|
96
150
|
size?: "sm" | "md" | "lg";
|
|
97
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* 라디오 버튼을 렌더링한다.
|
|
154
|
+
* 크기별 클래스와 라벨을 조합해 UI를 구성한다.
|
|
155
|
+
* @param props 라디오 속성
|
|
156
|
+
* @param ref 입력 요소 참조
|
|
157
|
+
* @returns 렌더링된 라디오 UI
|
|
158
|
+
*/
|
|
98
159
|
declare const Radio: React.ForwardRefExoticComponent<RadioProps & React.RefAttributes<HTMLInputElement>>;
|
|
99
160
|
|
|
100
161
|
type SelectSize = "sm" | "md" | "lg";
|
|
@@ -119,6 +180,12 @@ interface SelectProps {
|
|
|
119
180
|
className?: string;
|
|
120
181
|
textAlign?: "left" | "center";
|
|
121
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* 셀렉트 컴포넌트를 렌더링한다.
|
|
185
|
+
* 제어형/비제어형 상태를 정리하고, 키보드/마우스 상호작용과 드롭다운 표시를 관리한다.
|
|
186
|
+
* @param props 셀렉트 속성
|
|
187
|
+
* @returns 렌더링된 셀렉트 UI
|
|
188
|
+
*/
|
|
122
189
|
declare const Select: ({ id, label, placeholder, options, value, onChange, defaultValue, disabled, size, variant, fullWidth, className, textAlign, }: SelectProps) => react_jsx_runtime.JSX.Element;
|
|
123
190
|
|
|
124
191
|
interface SwitchProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onChange"> {
|
|
@@ -127,9 +194,16 @@ interface SwitchProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>
|
|
|
127
194
|
onChange?: (checked: boolean) => void;
|
|
128
195
|
size?: "sm" | "md" | "lg";
|
|
129
196
|
disabled?: boolean;
|
|
130
|
-
/**
|
|
197
|
+
/** 스위치 접근성 레이블(스크린 리더용) */
|
|
131
198
|
ariaLabel: string;
|
|
132
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* 스위치를 렌더링한다.
|
|
202
|
+
* 제어형/비제어형 상태를 판별해 토글 로직을 수행하고 버튼 형태의 스위치 UI를 반환한다.
|
|
203
|
+
* @param props 스위치 속성
|
|
204
|
+
* @param ref 버튼 참조
|
|
205
|
+
* @returns 렌더링된 스위치 요소
|
|
206
|
+
*/
|
|
133
207
|
declare const Switch: React.ForwardRefExoticComponent<SwitchProps & React.RefAttributes<HTMLButtonElement>>;
|
|
134
208
|
|
|
135
209
|
type TextFieldVariant = "outline" | "filled" | "ghost";
|
|
@@ -149,6 +223,13 @@ interface TextFieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement
|
|
|
149
223
|
defaultValue?: string;
|
|
150
224
|
transformValue?: (value: string) => string;
|
|
151
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* 텍스트 필드를 렌더링한다.
|
|
228
|
+
* 제어형/비제어형 값을 동기화하고, 조합 입력(IME)을 고려해 변경 이벤트를 전달한다.
|
|
229
|
+
* @param props 텍스트 필드 속성
|
|
230
|
+
* @param ref 입력 요소 참조
|
|
231
|
+
* @returns 렌더링된 텍스트 필드 UI
|
|
232
|
+
*/
|
|
152
233
|
declare const TextField: React.ForwardRefExoticComponent<TextFieldProps & React.RefAttributes<HTMLInputElement>>;
|
|
153
234
|
|
|
154
235
|
type DatePickerMode = "year-month" | "year-month-day";
|
|
@@ -163,14 +244,20 @@ interface DatePickerProps {
|
|
|
163
244
|
minDate?: string;
|
|
164
245
|
selectableRange?: SelectableRange;
|
|
165
246
|
disabled?: boolean;
|
|
166
|
-
/**
|
|
247
|
+
/** 데이트 피커가 컨테이너의 전체 너비를 차지할지 여부 */
|
|
167
248
|
fullWidth?: boolean;
|
|
168
249
|
/**
|
|
169
|
-
*
|
|
170
|
-
* @deprecated
|
|
250
|
+
* 데이트 피커의 커스텀 너비
|
|
251
|
+
* @deprecated `fullWidth` 사용 또는 CSS로 처리
|
|
171
252
|
*/
|
|
172
253
|
width?: number | string;
|
|
173
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* 연/월/일 선택형 데이트 피커를 렌더링한다.
|
|
257
|
+
* 입력 값과 선택 범위를 기준으로 옵션을 계산하고, 선택 변경을 상위로 전달한다.
|
|
258
|
+
* @param props 데이트 피커 속성
|
|
259
|
+
* @returns 렌더링된 데이트 피커 UI
|
|
260
|
+
*/
|
|
174
261
|
declare const DatePicker: ({ label, value, onChange, mode, startYear, endYear, minDate, selectableRange, disabled, fullWidth, width, }: DatePickerProps) => react_jsx_runtime.JSX.Element;
|
|
175
262
|
|
|
176
263
|
interface PaginationProps {
|
|
@@ -178,6 +265,12 @@ interface PaginationProps {
|
|
|
178
265
|
totalPages: number;
|
|
179
266
|
onChange: (page: number) => void;
|
|
180
267
|
}
|
|
268
|
+
/**
|
|
269
|
+
* 페이지네이션을 렌더링한다.
|
|
270
|
+
* 이전/다음 버튼과 페이지 목록을 구성해 전달된 콜백으로 페이지 변경을 전달한다.
|
|
271
|
+
* @param props 페이지네이션 속성
|
|
272
|
+
* @returns 렌더링된 페이지네이션 UI
|
|
273
|
+
*/
|
|
181
274
|
declare const Pagination: ({ page, totalPages, onChange }: PaginationProps) => react_jsx_runtime.JSX.Element;
|
|
182
275
|
|
|
183
276
|
interface ModalProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
@@ -186,9 +279,15 @@ interface ModalProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title">
|
|
|
186
279
|
closeOnOverlay?: boolean;
|
|
187
280
|
width?: number | string;
|
|
188
281
|
title?: React.ReactNode;
|
|
189
|
-
/**
|
|
282
|
+
/** 모달 접근성 레이블(기본값: title 또는 "Dialog") */
|
|
190
283
|
ariaLabel?: string;
|
|
191
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* 모달을 렌더링한다.
|
|
287
|
+
* 포커스 트랩과 스크롤 잠금을 적용하고, 열림 상태에 따라 오버레이/패널을 구성한다.
|
|
288
|
+
* @param props 모달 속성
|
|
289
|
+
* @returns 열림 상태일 때 렌더링된 모달, 닫힘 상태면 null
|
|
290
|
+
*/
|
|
192
291
|
declare const Modal: ({ open, onClose, closeOnOverlay, width, title, children, className, ariaLabel, ...props }: ModalProps) => react_jsx_runtime.JSX.Element | null;
|
|
193
292
|
|
|
194
293
|
export { AlertProvider, Button, Card, Checkbox, DatePicker, FileInput, Modal, Pagination, Radio, Select, type SelectOption, Spinner, Switch, TextField, ToastProvider, TopLoading, useAlert, useToast };
|
package/dist/next.d.ts
CHANGED
|
@@ -26,6 +26,12 @@ interface SidebarProps {
|
|
|
26
26
|
match?: MatchMode;
|
|
27
27
|
brandHref?: string;
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* 사이드바를 렌더링한다.
|
|
31
|
+
* 활성 경로를 기준으로 메뉴 상태를 계산하고 그룹 열림/닫힘을 관리한다.
|
|
32
|
+
* @param props 사이드바 속성
|
|
33
|
+
* @returns 렌더링된 사이드바 UI
|
|
34
|
+
*/
|
|
29
35
|
declare const Sidebar: ({ items, activePath, onItemSelect, className, style, match, brandHref, }: SidebarProps) => react_jsx_runtime.JSX.Element;
|
|
30
36
|
|
|
31
37
|
export { Sidebar, type SidebarItem, type SidebarProps };
|