@idbrnd/design-system 1.7.3 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +314 -80
- package/dist/components/Table/Pagination/Pagination.d.ts +5 -0
- package/dist/components/Table/Pagination/Pagination.types.d.ts +51 -0
- package/dist/components/Table/Table.d.ts +5 -0
- package/dist/components/Table/Table.types.d.ts +38 -0
- package/dist/components/Table/TableContainer.d.ts +15 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +3296 -1354
- package/dist/style.css +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -68,6 +68,10 @@ export default function App() {
|
|
|
68
68
|
- [ChipGroup](#chipgroup)
|
|
69
69
|
- [FilterChip](#filterchip)
|
|
70
70
|
- [FilterBar](#filterbar)
|
|
71
|
+
- [테이블](#테이블)
|
|
72
|
+
- [TableContainer](#tablecontainer)
|
|
73
|
+
- [Table](#table)
|
|
74
|
+
- [Pagination](#pagination)
|
|
71
75
|
- [기타](#기타)
|
|
72
76
|
- [Spinner](#spinner)
|
|
73
77
|
|
|
@@ -226,26 +230,26 @@ function InputExample() {
|
|
|
226
230
|
}
|
|
227
231
|
```
|
|
228
232
|
|
|
229
|
-
| Prop | 타입
|
|
230
|
-
| ------------------------ |
|
|
231
|
-
| `type` | `HTMLInputTypeAttribute`
|
|
232
|
-
| `designType` | `"outline"` \| `"fill"`
|
|
233
|
-
| `size` | `"default"` \| `"small"`
|
|
234
|
-
| `variant` | `"basic"` \| `"error"` \| `"onTyping"` \| `"typed"` \| `"onFocus"` \| `"success"` | 자동 계산
|
|
235
|
-
| `width` | `number \| string`
|
|
236
|
-
| `value` | `string \| number \| readonly string[]`
|
|
237
|
-
| `onChange` | `ChangeEventHandler<HTMLInputElement>`
|
|
238
|
-
| `heading` | `boolean`
|
|
239
|
-
| `headingContent` | `ReactNode`
|
|
240
|
-
| `required` | `boolean`
|
|
241
|
-
| `description` | `ReactNode \| boolean`
|
|
242
|
-
| `fixedDescriptionHeight` | `boolean`
|
|
243
|
-
| `errorMessage` | `ReactNode`
|
|
244
|
-
| `leadingIcon` | `ReactNode`
|
|
245
|
-
| `trailingContent` | `ReactNode`
|
|
246
|
-
| `readOnly` | `boolean`
|
|
247
|
-
| `disabled` | `boolean`
|
|
248
|
-
| `customStyle` | `CSSProperties`
|
|
233
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
234
|
+
| ------------------------ | --------------------------------------------------------------------------------- | -------------- | ---------------------------------------------------------------------- |
|
|
235
|
+
| `type` | `HTMLInputTypeAttribute` | `"text"` | 실제 HTML input 타입 (`text`, `password`, `email` 등) |
|
|
236
|
+
| `designType` | `"outline"` \| `"fill"` | `"outline"` | Input 컨테이너 외형 |
|
|
237
|
+
| `size` | `"default"` \| `"small"` | `"default"` | Input 높이 |
|
|
238
|
+
| `variant` | `"basic"` \| `"error"` \| `"onTyping"` \| `"typed"` \| `"onFocus"` \| `"success"` | 자동 계산 | 수동 상태 지정. `errorMessage`가 있으면 `error`가 우선 적용 |
|
|
239
|
+
| `width` | `number \| string` | `"100%"` | 루트 너비 |
|
|
240
|
+
| `value` | `string \| number \| readonly string[]` | — | **(필수)** 입력값 |
|
|
241
|
+
| `onChange` | `ChangeEventHandler<HTMLInputElement>` | — | 값 변경 핸들러 |
|
|
242
|
+
| `heading` | `boolean` | `true` | 상단 라벨 표시 여부 |
|
|
243
|
+
| `headingContent` | `ReactNode` | `"Label"` | 상단 라벨 내용 |
|
|
244
|
+
| `required` | `boolean` | `false` | 필수 입력 표시 및 native `required` 속성 적용 |
|
|
245
|
+
| `description` | `ReactNode \| boolean` | `false` | 하단 안내 문구. `true`면 기본 안내 문구를 사용 |
|
|
246
|
+
| `fixedDescriptionHeight` | `boolean` | `true` | helper 영역 높이 고정 여부 |
|
|
247
|
+
| `errorMessage` | `ReactNode` | 기본 에러 문구 | 의미 있는 값이 전달되면 에러 상태가 자동 적용되고 해당 메시지가 표시됨 |
|
|
248
|
+
| `leadingIcon` | `ReactNode` | — | 입력 필드 좌측 아이콘 |
|
|
249
|
+
| `trailingContent` | `ReactNode` | — | 입력 필드 우측 콘텐츠 |
|
|
250
|
+
| `readOnly` | `boolean` | `false` | 읽기 전용 |
|
|
251
|
+
| `disabled` | `boolean` | `false` | 비활성화 |
|
|
252
|
+
| `customStyle` | `CSSProperties` | `{}` | 루트 컨테이너에 적용할 추가 인라인 스타일 |
|
|
249
253
|
|
|
250
254
|
유의사항:
|
|
251
255
|
|
|
@@ -264,7 +268,14 @@ function InputExample() {
|
|
|
264
268
|
value={value}
|
|
265
269
|
onChange={onChange}
|
|
266
270
|
errorMessage={
|
|
267
|
-
<span
|
|
271
|
+
<span
|
|
272
|
+
style={{
|
|
273
|
+
display: "inline-block",
|
|
274
|
+
maxWidth: "240px",
|
|
275
|
+
whiteSpace: "normal",
|
|
276
|
+
wordBreak: "keep-all",
|
|
277
|
+
}}
|
|
278
|
+
>
|
|
268
279
|
긴 에러 문구를 이 케이스에서만 두 줄로
|
|
269
280
|
<br />
|
|
270
281
|
보여주고 싶을 때 사용할 수 있습니다.
|
|
@@ -285,7 +296,7 @@ function SearchExample() {
|
|
|
285
296
|
const [keyword, setKeyword] = useState("");
|
|
286
297
|
const messages = {
|
|
287
298
|
minLength: "검색어를 2자 이상 입력해 주세요.",
|
|
288
|
-
maxLength: "검색어는 19자 이하로 입력해 주세요."
|
|
299
|
+
maxLength: "검색어는 19자 이하로 입력해 주세요.",
|
|
289
300
|
};
|
|
290
301
|
const searchErrorMessage =
|
|
291
302
|
keyword.length === 1
|
|
@@ -306,19 +317,19 @@ function SearchExample() {
|
|
|
306
317
|
}
|
|
307
318
|
```
|
|
308
319
|
|
|
309
|
-
| Prop | 타입 | 기본값 | 설명
|
|
310
|
-
| -------------- | ----------------------------------------------------- | ----------- |
|
|
311
|
-
| `value` | `string` | — | **(필수)** 입력값
|
|
312
|
-
| `onChange` | `ChangeEventHandler` | — | **(필수)** 변경 핸들러
|
|
313
|
-
| `onSearch` | `(value: string) => void` | — | 검색 실행 콜백
|
|
314
|
-
| `onClear` | `() => void` | — | 삭제 버튼 클릭 콜백. 미지정 시 기본 동작 사용
|
|
315
|
-
| `size` | `"default"` \| `"small"` | `"default"` | 크기
|
|
316
|
-
| `variant` | `"default"` \| `"onTyping"` \| `"typed"` \| `"error"` | — | 상태 변형. `errorMessage`가 있으면 `error`가 우선 적용
|
|
320
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
321
|
+
| -------------- | ----------------------------------------------------- | ----------- | -------------------------------------------------------------------- |
|
|
322
|
+
| `value` | `string` | — | **(필수)** 입력값 |
|
|
323
|
+
| `onChange` | `ChangeEventHandler` | — | **(필수)** 변경 핸들러 |
|
|
324
|
+
| `onSearch` | `(value: string) => void` | — | 검색 실행 콜백 |
|
|
325
|
+
| `onClear` | `() => void` | — | 삭제 버튼 클릭 콜백. 미지정 시 기본 동작 사용 |
|
|
326
|
+
| `size` | `"default"` \| `"small"` | `"default"` | 크기 |
|
|
327
|
+
| `variant` | `"default"` \| `"onTyping"` \| `"typed"` \| `"error"` | — | 상태 변형. `errorMessage`가 있으면 `error`가 우선 적용 |
|
|
317
328
|
| `errorMessage` | `ReactNode` | — | 의미 있는 값이 전달되면 에러 상태가 자동 적용되고 해당 문구가 표시됨 |
|
|
318
|
-
| `maxLength` | `number` | `20` | native `input`의 `maxLength` 속성으로 전달
|
|
319
|
-
| `heading` | `boolean` | `false` | 상단 heading 표시 여부
|
|
320
|
-
| `disabled` | `boolean` | `false` | 비활성화
|
|
321
|
-
| `customStyle` | `CSSProperties` | — | 추가 인라인 스타일
|
|
329
|
+
| `maxLength` | `number` | `20` | native `input`의 `maxLength` 속성으로 전달 |
|
|
330
|
+
| `heading` | `boolean` | `false` | 상단 heading 표시 여부 |
|
|
331
|
+
| `disabled` | `boolean` | `false` | 비활성화 |
|
|
332
|
+
| `customStyle` | `CSSProperties` | — | 추가 인라인 스타일 |
|
|
322
333
|
|
|
323
334
|
- `SearchBar`는 UI 컴포넌트로만 동작하며, 길이 검증이나 번역 문구 생성 로직은 포함하지 않습니다.
|
|
324
335
|
- `errorMessage`가 비거나 내용 없는 JSX 래퍼만 남으면 에러로 처리하지 않고, `variant` prop 또는 기본 자동 상태(`default`/`typed`)로 되돌아갑니다.
|
|
@@ -375,7 +386,7 @@ function CheckBoxExample() {
|
|
|
375
386
|
| `checked` | `boolean` | — | **(필수)** 체크 상태 |
|
|
376
387
|
| `onChange` | `(checked: boolean) => void` | — | 변경 핸들러 |
|
|
377
388
|
| `indeterminate` | `boolean` | `false` | `checked={true}`와 함께 사용 시 대시(–) 아이콘 표시 |
|
|
378
|
-
| `children` | `ReactNode` | — | 체크박스 우측에 렌더링할 라벨/콘텐츠
|
|
389
|
+
| `children` | `ReactNode` | — | 체크박스 우측에 렌더링할 라벨/콘텐츠 |
|
|
379
390
|
| `variant` | `"primary"` \| `"assistive"` | `"primary"` | 색상 변형 |
|
|
380
391
|
| `size` | `"medium"` \| `"small"` | `"medium"` | 크기 |
|
|
381
392
|
| `density` | `"default"` \| `"compact"` | `"default"` | wrapper 밀도 |
|
|
@@ -417,18 +428,18 @@ function RadioGroupExample() {
|
|
|
417
428
|
}
|
|
418
429
|
```
|
|
419
430
|
|
|
420
|
-
| Prop | 타입 | 기본값 | 설명
|
|
421
|
-
| ------------- | ---------------------------- | ----------- |
|
|
422
|
-
| `checked` | `boolean` | — | **(필수)** 선택 상태
|
|
423
|
-
| `onChange` | `(checked: boolean) => void` | — | 변경 핸들러
|
|
424
|
-
| `name` | `string` | — | input name 속성
|
|
425
|
-
| `value` | `string` | — | input value 속성
|
|
431
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
432
|
+
| ------------- | ---------------------------- | ----------- | ---------------------------------- |
|
|
433
|
+
| `checked` | `boolean` | — | **(필수)** 선택 상태 |
|
|
434
|
+
| `onChange` | `(checked: boolean) => void` | — | 변경 핸들러 |
|
|
435
|
+
| `name` | `string` | — | input name 속성 |
|
|
436
|
+
| `value` | `string` | — | input value 속성 |
|
|
426
437
|
| `children` | `ReactNode` | — | 라디오 우측에 렌더링할 라벨/콘텐츠 |
|
|
427
|
-
| `variant` | `"primary"` \| `"assistive"` | `"primary"` | 색상 변형
|
|
428
|
-
| `size` | `"medium"` \| `"small"` | `"medium"` | 크기
|
|
429
|
-
| `density` | `"default"` \| `"compact"` | `"default"` | wrapper 밀도
|
|
430
|
-
| `disabled` | `boolean` | `false` | 비활성화
|
|
431
|
-
| `customStyle` | `CSSProperties` | — | 추가 인라인 스타일
|
|
438
|
+
| `variant` | `"primary"` \| `"assistive"` | `"primary"` | 색상 변형 |
|
|
439
|
+
| `size` | `"medium"` \| `"small"` | `"medium"` | 크기 |
|
|
440
|
+
| `density` | `"default"` \| `"compact"` | `"default"` | wrapper 밀도 |
|
|
441
|
+
| `disabled` | `boolean` | `false` | 비활성화 |
|
|
442
|
+
| `customStyle` | `CSSProperties` | — | 추가 인라인 스타일 |
|
|
432
443
|
|
|
433
444
|
유의사항:
|
|
434
445
|
|
|
@@ -955,16 +966,16 @@ import { Chip } from "@idbrnd/design-system";
|
|
|
955
966
|
</Chip>
|
|
956
967
|
```
|
|
957
968
|
|
|
958
|
-
| Prop
|
|
959
|
-
|
|
960
|
-
| `variant`
|
|
961
|
-
| `size`
|
|
962
|
-
| `selected`
|
|
963
|
-
| `disabled`
|
|
964
|
-
| `leadingSlot`
|
|
965
|
-
| `trailingSlot` | `ReactNode`
|
|
966
|
-
| `onClick`
|
|
967
|
-
| `customStyle`
|
|
969
|
+
| Prop | Type | Default | Description |
|
|
970
|
+
| -------------- | ------------------------------------------------------- | ----------- | --------------------------- |
|
|
971
|
+
| `variant` | `"fillWeak" \| "fill" \| "outline" \| "outlineSurface"` | `"outline"` | 칩 스타일 |
|
|
972
|
+
| `size` | `"large" \| "medium" \| "small" \| "xsmall"` | `"medium"` | 칩 크기 |
|
|
973
|
+
| `selected` | `boolean` | `false` | 선택 상태 |
|
|
974
|
+
| `disabled` | `boolean` | `false` | 비활성화 |
|
|
975
|
+
| `leadingSlot` | `ReactNode` | — | 텍스트 왼쪽 콘텐츠 |
|
|
976
|
+
| `trailingSlot` | `ReactNode` | — | 텍스트 오른쪽 콘텐츠 |
|
|
977
|
+
| `onClick` | `MouseEventHandler` | — | 클릭 핸들러 |
|
|
978
|
+
| `customStyle` | `CSSProperties` | — | 루트 엘리먼트 인라인 스타일 |
|
|
968
979
|
|
|
969
980
|
---
|
|
970
981
|
|
|
@@ -1005,14 +1016,14 @@ function toggle(prev: DropdownOption[], item: DropdownOption) {
|
|
|
1005
1016
|
</ChipGroup>
|
|
1006
1017
|
```
|
|
1007
1018
|
|
|
1008
|
-
| Prop
|
|
1009
|
-
|
|
1010
|
-
| `type`
|
|
1011
|
-
| `size`
|
|
1012
|
-
| `gradient`
|
|
1013
|
-
| `leadingSlot`
|
|
1014
|
-
| `leadingElementSlot` | `ReactNode`
|
|
1015
|
-
| `customStyle`
|
|
1019
|
+
| Prop | Type | Default | Description |
|
|
1020
|
+
| -------------------- | -------------------------------------------- | ------------- | ----------------------------------------------------- |
|
|
1021
|
+
| `type` | `"selection" \| "suggestion"` | `"selection"` | `selection`: 줄바꿈, `suggestion`: 가로 드래그 캐러셀 |
|
|
1022
|
+
| `size` | `"large" \| "medium" \| "small" \| "xsmall"` | `"medium"` | 칩 간격 크기 |
|
|
1023
|
+
| `gradient` | `boolean` | `false` | `suggestion` 타입에서 스크롤 시 양끝 그라데이션 표시 |
|
|
1024
|
+
| `leadingSlot` | `ReactNode` | — | 칩 목록 앞 텍스트/라벨 |
|
|
1025
|
+
| `leadingElementSlot` | `ReactNode` | — | 칩 목록 앞 구분선 포함 엘리먼트 |
|
|
1026
|
+
| `customStyle` | `CSSProperties` | — | 루트 엘리먼트 인라인 스타일 |
|
|
1016
1027
|
|
|
1017
1028
|
---
|
|
1018
1029
|
|
|
@@ -1060,15 +1071,15 @@ const [sort, setSort] = useState<DropdownOption | undefined>();
|
|
|
1060
1071
|
</FilterChip>
|
|
1061
1072
|
```
|
|
1062
1073
|
|
|
1063
|
-
| Prop
|
|
1064
|
-
|
|
1065
|
-
| `options`
|
|
1066
|
-
| `onSelect`
|
|
1067
|
-
| `selectedValue`
|
|
1068
|
-
| `dropdownType`
|
|
1069
|
-
| `dropdownAlign`
|
|
1070
|
-
| `dropdownWidth`
|
|
1071
|
-
| `showSelectedLabel` | `boolean`
|
|
1074
|
+
| Prop | Type | Default | Description |
|
|
1075
|
+
| ------------------- | ----------------------------------------------- | --------- | ----------------------------------------------------------- |
|
|
1076
|
+
| `options` | `DropdownOption[]` | (필수) | 드롭다운 옵션 목록 |
|
|
1077
|
+
| `onSelect` | `(option: DropdownOption \| undefined) => void` | (필수) | 선택/해제 콜백. 이미 선택된 옵션 재클릭 시 `undefined` 전달 |
|
|
1078
|
+
| `selectedValue` | `string` | — | 현재 선택된 옵션의 `value` |
|
|
1079
|
+
| `dropdownType` | `"basic" \| "search"` | `"basic"` | `search`: 검색 입력란 포함 |
|
|
1080
|
+
| `dropdownAlign` | `"left" \| "center"` | `"left"` | 드롭다운 정렬 방향 |
|
|
1081
|
+
| `dropdownWidth` | `number` | — | 드롭다운 너비 (px) |
|
|
1082
|
+
| `showSelectedLabel` | `boolean` | `false` | `children`을 prefix로, 선택값 label을 옆에 함께 표시 |
|
|
1072
1083
|
|
|
1073
1084
|
---
|
|
1074
1085
|
|
|
@@ -1097,13 +1108,226 @@ import { FilterBar, FilterChip } from "@idbrnd/design-system";
|
|
|
1097
1108
|
</FilterBar>
|
|
1098
1109
|
```
|
|
1099
1110
|
|
|
1100
|
-
| Prop
|
|
1101
|
-
|
|
1102
|
-
| `size`
|
|
1103
|
-
| `verticalPadding`
|
|
1104
|
-
| `leadingElementSlot`
|
|
1105
|
-
| `trailingElementSlot` | `ReactNode`
|
|
1106
|
-
| `customStyle`
|
|
1111
|
+
| Prop | Type | Default | Description |
|
|
1112
|
+
| --------------------- | -------------------------------------------- | ---------- | ------------------------------------------------------------------ |
|
|
1113
|
+
| `size` | `"large" \| "medium" \| "small" \| "xsmall"` | `"medium"` | 칩 간격 및 슬롯 폰트 크기 |
|
|
1114
|
+
| `verticalPadding` | `boolean` | `false` | `true`: 위아래 8px 패딩, 그라데이션 없음. `false`: 그라데이션 사용 |
|
|
1115
|
+
| `leadingElementSlot` | `ReactNode` | — | 칩 목록 앞 구분선 포함 엘리먼트 |
|
|
1116
|
+
| `trailingElementSlot` | `ReactNode` | — | 칩 목록 뒤 엘리먼트 (초기화 버튼 등) |
|
|
1117
|
+
| `customStyle` | `CSSProperties` | — | 루트 엘리먼트 인라인 스타일 |
|
|
1118
|
+
|
|
1119
|
+
---
|
|
1120
|
+
|
|
1121
|
+
## 테이블
|
|
1122
|
+
|
|
1123
|
+
`TableContainer`, `Table`, `Pagination` 3개의 컴포넌트로 구성됩니다. 내부적으로 [TanStack Table v8](https://tanstack.com/table/v8)을 사용하므로 `@tanstack/react-table` 패키지가 필요합니다.
|
|
1124
|
+
|
|
1125
|
+
```bash
|
|
1126
|
+
npm install @tanstack/react-table
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1129
|
+
### TableContainer
|
|
1130
|
+
|
|
1131
|
+
`Table`과 `Pagination`을 감싸는 레이아웃 컨테이너입니다. `variant`를 `Table`과 동일하게 맞춰야 합니다.
|
|
1132
|
+
|
|
1133
|
+
```tsx
|
|
1134
|
+
import { TableContainer, Table, Pagination } from "@idbrnd/design-system";
|
|
1135
|
+
|
|
1136
|
+
<TableContainer variant="content">
|
|
1137
|
+
<Table table={table} variant="content" />
|
|
1138
|
+
<Pagination ... />
|
|
1139
|
+
</TableContainer>
|
|
1140
|
+
```
|
|
1141
|
+
|
|
1142
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
1143
|
+
| ------------- | ------------------------- | ---------- | ------------------------------------------------------------------------ |
|
|
1144
|
+
| `variant` | `"normal"` \| `"content"` | `"normal"` | `Table` variant와 동일하게 설정. `content`는 외곽선 + border-radius 적용 |
|
|
1145
|
+
| `customStyle` | `CSSProperties` | — | 추가 인라인 스타일 |
|
|
1146
|
+
| `className` | `string` | — | 추가 클래스명 |
|
|
1147
|
+
| `children` | `ReactNode` | — | `Table`, `Pagination` 등 |
|
|
1148
|
+
|
|
1149
|
+
---
|
|
1150
|
+
|
|
1151
|
+
### Table
|
|
1152
|
+
|
|
1153
|
+
TanStack Table 인스턴스를 받아 렌더링하는 컴포넌트입니다.
|
|
1154
|
+
|
|
1155
|
+
```tsx
|
|
1156
|
+
import { Table } from "@idbrnd/design-system";
|
|
1157
|
+
import {
|
|
1158
|
+
useReactTable,
|
|
1159
|
+
getCoreRowModel,
|
|
1160
|
+
getSortedRowModel,
|
|
1161
|
+
type SortingState,
|
|
1162
|
+
} from "@tanstack/react-table";
|
|
1163
|
+
|
|
1164
|
+
// 기본 사용
|
|
1165
|
+
const table = useReactTable({
|
|
1166
|
+
data,
|
|
1167
|
+
columns,
|
|
1168
|
+
getCoreRowModel: getCoreRowModel(),
|
|
1169
|
+
});
|
|
1170
|
+
|
|
1171
|
+
<Table table={table} variant="normal" />
|
|
1172
|
+
|
|
1173
|
+
// 정렬
|
|
1174
|
+
const [sorting, setSorting] = useState<SortingState>([]);
|
|
1175
|
+
const table = useReactTable({
|
|
1176
|
+
data,
|
|
1177
|
+
columns,
|
|
1178
|
+
state: { sorting },
|
|
1179
|
+
onSortingChange: setSorting,
|
|
1180
|
+
getCoreRowModel: getCoreRowModel(),
|
|
1181
|
+
getSortedRowModel: getSortedRowModel(),
|
|
1182
|
+
});
|
|
1183
|
+
|
|
1184
|
+
<Table table={table} />
|
|
1185
|
+
|
|
1186
|
+
// 행 선택 (체크박스)
|
|
1187
|
+
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
|
1188
|
+
const table = useReactTable({
|
|
1189
|
+
data,
|
|
1190
|
+
columns,
|
|
1191
|
+
enableRowSelection: true,
|
|
1192
|
+
state: { rowSelection },
|
|
1193
|
+
onRowSelectionChange: setRowSelection,
|
|
1194
|
+
getCoreRowModel: getCoreRowModel(),
|
|
1195
|
+
});
|
|
1196
|
+
|
|
1197
|
+
<Table table={table} selectable />
|
|
1198
|
+
|
|
1199
|
+
// 행 클릭 (체크박스 없이 인터랙션)
|
|
1200
|
+
<Table
|
|
1201
|
+
table={table}
|
|
1202
|
+
onRowClick={(row) => console.log(row.original)}
|
|
1203
|
+
/>
|
|
1204
|
+
|
|
1205
|
+
// 로딩 스켈레톤
|
|
1206
|
+
<Table table={table} loading skeletonRowCount={10} />
|
|
1207
|
+
|
|
1208
|
+
// 빈 상태
|
|
1209
|
+
<Table
|
|
1210
|
+
table={table}
|
|
1211
|
+
emptyTitle="데이터가 없습니다"
|
|
1212
|
+
emptyDescription="새 항목을 추가해 주세요"
|
|
1213
|
+
/>
|
|
1214
|
+
```
|
|
1215
|
+
|
|
1216
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
1217
|
+
| ------------------ | --------------------------- | ---------- | ------------------------------------------------------------- |
|
|
1218
|
+
| `table` | `Table<TData>` | — | `useReactTable()`로 생성한 TanStack Table 인스턴스 (필수) |
|
|
1219
|
+
| `variant` | `"normal"` \| `"content"` | `"normal"` | 테이블 스타일 변형 |
|
|
1220
|
+
| `selectable` | `boolean` | `false` | 첫 번째 컬럼에 체크박스 표시. `enableRowSelection` 설정 필요 |
|
|
1221
|
+
| `interactive` | `boolean` | `false` | 행 hover/focus/pressed 인터랙션 활성화 |
|
|
1222
|
+
| `onRowClick` | `(row: Row<TData>) => void` | — | 행 클릭 콜백. 제공 시 체크박스 없이도 행에 인터랙션 효과 적용 |
|
|
1223
|
+
| `loading` | `boolean` | `false` | 로딩 스켈레톤 표시 |
|
|
1224
|
+
| `skeletonRowCount` | `number` | `5` | 로딩 스켈레톤 행 수 |
|
|
1225
|
+
| `emptyContent` | `ReactNode` | — | 데이터 없을 때 표시할 커스텀 콘텐츠 (전체 오버라이드) |
|
|
1226
|
+
| `emptyTitle` | `string` | — | 빈 상태 제목 |
|
|
1227
|
+
| `emptyDescription` | `string` | — | 빈 상태 설명 |
|
|
1228
|
+
| `customStyle` | `CSSProperties` | — | 추가 인라인 스타일 |
|
|
1229
|
+
| `className` | `string` | — | 추가 클래스명 |
|
|
1230
|
+
|
|
1231
|
+
**단일 행 선택**
|
|
1232
|
+
|
|
1233
|
+
`enableMultiRowSelection: false`와 `onRowSelectionChange` 오버라이드로 구현합니다.
|
|
1234
|
+
|
|
1235
|
+
```tsx
|
|
1236
|
+
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
|
1237
|
+
|
|
1238
|
+
const table = useReactTable({
|
|
1239
|
+
data,
|
|
1240
|
+
columns,
|
|
1241
|
+
enableRowSelection: true,
|
|
1242
|
+
enableMultiRowSelection: false,
|
|
1243
|
+
state: { rowSelection },
|
|
1244
|
+
onRowSelectionChange: (updater) => {
|
|
1245
|
+
const next =
|
|
1246
|
+
typeof updater === "function" ? updater(rowSelection) : updater;
|
|
1247
|
+
const newlySelected = Object.keys(next).find((id) => !rowSelection[id]);
|
|
1248
|
+
setRowSelection(newlySelected ? { [newlySelected]: true } : {});
|
|
1249
|
+
},
|
|
1250
|
+
getCoreRowModel: getCoreRowModel(),
|
|
1251
|
+
});
|
|
1252
|
+
```
|
|
1253
|
+
|
|
1254
|
+
---
|
|
1255
|
+
|
|
1256
|
+
### Pagination
|
|
1257
|
+
|
|
1258
|
+
```tsx
|
|
1259
|
+
import { Pagination } from "@idbrnd/design-system";
|
|
1260
|
+
import {
|
|
1261
|
+
useReactTable,
|
|
1262
|
+
getPaginationRowModel,
|
|
1263
|
+
type PaginationState,
|
|
1264
|
+
} from "@tanstack/react-table";
|
|
1265
|
+
|
|
1266
|
+
const [pagination, setPagination] = useState<PaginationState>({
|
|
1267
|
+
pageIndex: 0,
|
|
1268
|
+
pageSize: 10,
|
|
1269
|
+
});
|
|
1270
|
+
|
|
1271
|
+
const table = useReactTable({
|
|
1272
|
+
data,
|
|
1273
|
+
columns,
|
|
1274
|
+
state: { pagination },
|
|
1275
|
+
onPaginationChange: setPagination,
|
|
1276
|
+
getCoreRowModel: getCoreRowModel(),
|
|
1277
|
+
getPaginationRowModel: getPaginationRowModel(),
|
|
1278
|
+
});
|
|
1279
|
+
|
|
1280
|
+
// 기본
|
|
1281
|
+
<Pagination
|
|
1282
|
+
table={table}
|
|
1283
|
+
pageCount={table.getPageCount()}
|
|
1284
|
+
canPreviousPage={table.getCanPreviousPage()}
|
|
1285
|
+
canNextPage={table.getCanNextPage()}
|
|
1286
|
+
onPreviousPage={() => table.previousPage()}
|
|
1287
|
+
onNextPage={() => table.nextPage()}
|
|
1288
|
+
/>
|
|
1289
|
+
|
|
1290
|
+
// compact variant + 페이지 이동 입력란
|
|
1291
|
+
<Pagination
|
|
1292
|
+
table={table}
|
|
1293
|
+
pageCount={table.getPageCount()}
|
|
1294
|
+
canPreviousPage={table.getCanPreviousPage()}
|
|
1295
|
+
canNextPage={table.getCanNextPage()}
|
|
1296
|
+
onPreviousPage={() => table.previousPage()}
|
|
1297
|
+
onNextPage={() => table.nextPage()}
|
|
1298
|
+
variant="compact"
|
|
1299
|
+
trailingContent
|
|
1300
|
+
/>
|
|
1301
|
+
|
|
1302
|
+
// 첫/마지막 페이지 고정 + 생략 부호
|
|
1303
|
+
<Pagination
|
|
1304
|
+
table={table}
|
|
1305
|
+
pageCount={table.getPageCount()}
|
|
1306
|
+
canPreviousPage={table.getCanPreviousPage()}
|
|
1307
|
+
canNextPage={table.getCanNextPage()}
|
|
1308
|
+
onPreviousPage={() => table.previousPage()}
|
|
1309
|
+
onNextPage={() => table.nextPage()}
|
|
1310
|
+
boundary
|
|
1311
|
+
/>
|
|
1312
|
+
```
|
|
1313
|
+
|
|
1314
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
1315
|
+
| ----------------- | ------------------------------------------- | --------------- | -------------------------------------------------------------------------- |
|
|
1316
|
+
| `table` | `Table<TData>` | — | TanStack Table 인스턴스 (필수) |
|
|
1317
|
+
| `pageCount` | `number` | — | 전체 페이지 수 (필수). 서버사이드 시 직접 전달 |
|
|
1318
|
+
| `canPreviousPage` | `boolean` | — | 이전 페이지 버튼 활성화 여부 (필수) |
|
|
1319
|
+
| `canNextPage` | `boolean` | — | 다음 페이지 버튼 활성화 여부 (필수) |
|
|
1320
|
+
| `onPreviousPage` | `() => void` | — | 이전 페이지 이동 콜백 (필수) |
|
|
1321
|
+
| `onNextPage` | `() => void` | — | 다음 페이지 이동 콜백 (필수) |
|
|
1322
|
+
| `variant` | `"extended"` \| `"compact"` \| `"minimize"` | `"extended"` | `extended`: 최대 10개, `compact`: 최대 7개, `minimize`: 현재/전체 텍스트만 |
|
|
1323
|
+
| `boundary` | `boolean` | `false` | `false`: 슬라이딩 윈도우, `true`: 첫·끝 페이지 고정 + `...` 생략 |
|
|
1324
|
+
| `trailingContent` | `boolean` | `false` | 우측에 "페이지 이동" 입력란 표시 |
|
|
1325
|
+
| `prevLabel` | `string` | `"이전"` | 이전 버튼 레이블 |
|
|
1326
|
+
| `nextLabel` | `string` | `"다음"` | 다음 버튼 레이블 |
|
|
1327
|
+
| `jumpLabel` | `string` | `"페이지 이동"` | 페이지 이동 입력란 레이블 |
|
|
1328
|
+
| `loading` | `boolean` | `false` | 로딩 스켈레톤 표시 |
|
|
1329
|
+
| `customStyle` | `CSSProperties` | — | 추가 인라인 스타일 |
|
|
1330
|
+
| `className` | `string` | — | 추가 클래스명 |
|
|
1107
1331
|
|
|
1108
1332
|
---
|
|
1109
1333
|
|
|
@@ -1224,6 +1448,12 @@ import type {
|
|
|
1224
1448
|
DropdownOption,
|
|
1225
1449
|
DropdownType,
|
|
1226
1450
|
DropdownAlign,
|
|
1451
|
+
|
|
1452
|
+
// Table
|
|
1453
|
+
TableProps,
|
|
1454
|
+
TableVariant,
|
|
1455
|
+
PaginationProps,
|
|
1456
|
+
PaginationVariant,
|
|
1227
1457
|
} from "@idbrnd/design-system";
|
|
1228
1458
|
```
|
|
1229
1459
|
|
|
@@ -1237,4 +1467,8 @@ import type {
|
|
|
1237
1467
|
- `showToast`, `showSnackbar`는 내부적으로 `document.body`에 포털을 생성하므로 브라우저 환경에서 호출해야 합니다.
|
|
1238
1468
|
- `Select`와 `Dropdown`의 드롭다운 목록은 `document.body`에 포탈로 렌더링되므로 브라우저 환경에서만 동작합니다.
|
|
1239
1469
|
- `Select`는 폼 필드용, `Dropdown`은 컨텍스트 메뉴/액션 드롭다운용으로 사용을 권장합니다.
|
|
1470
|
+
- `Table`은 `@tanstack/react-table`의 `useReactTable()`로 생성한 인스턴스를 필수로 받습니다. TanStack Table을 별도 설치해야 합니다.
|
|
1471
|
+
- `TableContainer`의 `variant`는 `Table`의 `variant`와 반드시 동일하게 맞춰야 레이아웃이 올바르게 적용됩니다.
|
|
1472
|
+
- `Table`에서 `selectable` 사용 시 `useReactTable`에 `enableRowSelection`, `state.rowSelection`, `onRowSelectionChange`를 함께 설정해야 합니다.
|
|
1473
|
+
- `Pagination`에서 서버사이드 페이지네이션을 사용할 경우 `pageCount`를 서버 응답 기준으로 직접 계산해 전달해야 합니다.
|
|
1240
1474
|
- CSS 변수/타이포그래피를 포함한 스타일을 위해 `@idbrnd/design-system/style.css` import를 권장합니다.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PaginationProps, PaginationVariant } from "./Pagination.types";
|
|
2
|
+
export type { PaginationVariant };
|
|
3
|
+
export type { PaginationProps };
|
|
4
|
+
declare function Pagination<TData>({ table, pageCount, canPreviousPage, canNextPage, onPreviousPage, onNextPage, variant, boundary, trailingContent, loading, prevLabel, nextLabel, jumpLabel, customStyle, className, }: PaginationProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export default Pagination;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
import type { Table } from "@tanstack/react-table";
|
|
3
|
+
export type PaginationVariant = "extended" | "compact" | "minimize";
|
|
4
|
+
export interface PaginationProps<TData> {
|
|
5
|
+
/** TanStack Table 인스턴스 */
|
|
6
|
+
table: Table<TData>;
|
|
7
|
+
/** 전체 페이지 수 (서버사이드 페이지네이션 시 직접 전달) */
|
|
8
|
+
pageCount: number;
|
|
9
|
+
/** 이전/다음 버튼 활성화 여부 */
|
|
10
|
+
canPreviousPage: boolean;
|
|
11
|
+
canNextPage: boolean;
|
|
12
|
+
/** 이전 페이지 이동 콜백 */
|
|
13
|
+
onPreviousPage: () => void;
|
|
14
|
+
/** 다음 페이지 이동 콜백 */
|
|
15
|
+
onNextPage: () => void;
|
|
16
|
+
/** 페이지네이션 레이아웃 형태
|
|
17
|
+
* - `extended`: 최대 10개 페이지 번호 노출 (기본값)
|
|
18
|
+
* - `compact`: 최대 7개 페이지 번호 노출
|
|
19
|
+
* - `minimize`: 페이지 번호 대신 "현재/전체" 텍스트만 노출
|
|
20
|
+
* @defaultValue `'extended'`
|
|
21
|
+
*/
|
|
22
|
+
variant?: PaginationVariant;
|
|
23
|
+
/** 첫/마지막 페이지 고정 + 생략 부호 처리 여부
|
|
24
|
+
* - `false`: 현재 페이지 중심의 슬라이딩 윈도우
|
|
25
|
+
* - `true`: 첫·끝 페이지를 항상 고정하고 중간을 ... 으로 축약
|
|
26
|
+
* @defaultValue `false`
|
|
27
|
+
*/
|
|
28
|
+
boundary?: boolean;
|
|
29
|
+
/** 우측 "페이지 이동" 입력란 표시 여부
|
|
30
|
+
* @defaultValue `false`
|
|
31
|
+
*/
|
|
32
|
+
trailingContent?: boolean;
|
|
33
|
+
/** 이전 버튼 레이블
|
|
34
|
+
* @defaultValue `'이전'`
|
|
35
|
+
*/
|
|
36
|
+
prevLabel?: string;
|
|
37
|
+
/** 다음 버튼 레이블
|
|
38
|
+
* @defaultValue `'다음'`
|
|
39
|
+
*/
|
|
40
|
+
nextLabel?: string;
|
|
41
|
+
/** 페이지 이동 입력란 레이블
|
|
42
|
+
* @defaultValue `'페이지 이동'`
|
|
43
|
+
*/
|
|
44
|
+
jumpLabel?: string;
|
|
45
|
+
/** 로딩 스켈레톤 상태 */
|
|
46
|
+
loading?: boolean;
|
|
47
|
+
/** 루트 엘리먼트 인라인 스타일 */
|
|
48
|
+
customStyle?: CSSProperties;
|
|
49
|
+
/** 추가 클래스명 */
|
|
50
|
+
className?: string;
|
|
51
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TableProps, TableVariant } from "./Table.types";
|
|
2
|
+
export type { TableVariant };
|
|
3
|
+
export type { TableProps };
|
|
4
|
+
declare function Table<TData>({ table, variant, selectable, interactive, loading, skeletonRowCount, emptyContent, emptyTitle, emptyDescription, customStyle, className, onRowClick, }: TableProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export default Table;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
2
|
+
import type { Row, Table } from "@tanstack/react-table";
|
|
3
|
+
export type TableVariant = "normal" | "content";
|
|
4
|
+
export interface TableProps<TData> {
|
|
5
|
+
/** useReactTable()로 생성한 TanStack Table 인스턴스 */
|
|
6
|
+
table: Table<TData>;
|
|
7
|
+
/** 테이블 스타일 변형
|
|
8
|
+
* @defaultValue `'normal'`
|
|
9
|
+
*/
|
|
10
|
+
variant?: TableVariant;
|
|
11
|
+
/** 첫 번째 컬럼에 행 선택 체크박스 표시 여부.
|
|
12
|
+
* useReactTable에 `enableRowSelection`, `state.rowSelection`, `onRowSelectionChange` 설정 필요
|
|
13
|
+
* @defaultValue `false`
|
|
14
|
+
*/
|
|
15
|
+
selectable?: boolean;
|
|
16
|
+
/** 행 hover/focus/pressed/selected 인터랙션 활성화 여부
|
|
17
|
+
* @defaultValue `false`
|
|
18
|
+
*/
|
|
19
|
+
interactive?: boolean;
|
|
20
|
+
/** 행 클릭 콜백. 제공 시 체크박스 없이도 행에 인터랙션 효과 적용 */
|
|
21
|
+
onRowClick?: (row: Row<TData>) => void;
|
|
22
|
+
/** 로딩 상태 */
|
|
23
|
+
loading?: boolean;
|
|
24
|
+
/** 로딩 스켈레톤 행 수
|
|
25
|
+
* @defaultValue `5`
|
|
26
|
+
*/
|
|
27
|
+
skeletonRowCount?: number;
|
|
28
|
+
/** 데이터가 없을 때 표시할 내용 (전체 오버라이드) */
|
|
29
|
+
emptyContent?: ReactNode;
|
|
30
|
+
/** 빈 상태 제목 */
|
|
31
|
+
emptyTitle?: string;
|
|
32
|
+
/** 빈 상태 설명 */
|
|
33
|
+
emptyDescription?: string;
|
|
34
|
+
/** 루트 엘리먼트 인라인 스타일 */
|
|
35
|
+
customStyle?: CSSProperties;
|
|
36
|
+
/** 추가 클래스명 */
|
|
37
|
+
className?: string;
|
|
38
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
2
|
+
import type { TableVariant } from "./Table.types";
|
|
3
|
+
export interface TableContainerProps {
|
|
4
|
+
/** 테이블 스타일 변형 — Table 컴포넌트의 variant와 동일하게 맞춰야 합니다.
|
|
5
|
+
* - `normal`: 단순 외곽선
|
|
6
|
+
* - `content`: 외곽선 + border-radius (Pagination도 border 안에 포함)
|
|
7
|
+
* @defaultValue `'normal'`
|
|
8
|
+
*/
|
|
9
|
+
variant?: TableVariant;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
customStyle?: CSSProperties;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function TableContainer({ variant, children, customStyle, className, }: TableContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export default TableContainer;
|