moru-krds-react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +61 -0
  3. package/dist/accordion/index.d.ts +63 -0
  4. package/dist/accordion/index.d.ts.map +1 -0
  5. package/dist/accordion/index.js +145 -0
  6. package/dist/accordion/index.js.map +1 -0
  7. package/dist/alert/index.d.ts +44 -0
  8. package/dist/alert/index.d.ts.map +1 -0
  9. package/dist/alert/index.js +66 -0
  10. package/dist/alert/index.js.map +1 -0
  11. package/dist/avatar/index.d.ts +102 -0
  12. package/dist/avatar/index.d.ts.map +1 -0
  13. package/dist/avatar/index.js +146 -0
  14. package/dist/avatar/index.js.map +1 -0
  15. package/dist/badge/index.d.ts +49 -0
  16. package/dist/badge/index.d.ts.map +1 -0
  17. package/dist/badge/index.js +41 -0
  18. package/dist/badge/index.js.map +1 -0
  19. package/dist/breadcrumb/index.d.ts +43 -0
  20. package/dist/breadcrumb/index.d.ts.map +1 -0
  21. package/dist/breadcrumb/index.js +43 -0
  22. package/dist/breadcrumb/index.js.map +1 -0
  23. package/dist/button/index.d.ts +78 -0
  24. package/dist/button/index.d.ts.map +1 -0
  25. package/dist/button/index.js +83 -0
  26. package/dist/button/index.js.map +1 -0
  27. package/dist/checkbox/index.d.ts +97 -0
  28. package/dist/checkbox/index.d.ts.map +1 -0
  29. package/dist/checkbox/index.js +110 -0
  30. package/dist/checkbox/index.js.map +1 -0
  31. package/dist/combobox/index.d.ts +135 -0
  32. package/dist/combobox/index.d.ts.map +1 -0
  33. package/dist/combobox/index.js +416 -0
  34. package/dist/combobox/index.js.map +1 -0
  35. package/dist/context-menu/index.d.ts +94 -0
  36. package/dist/context-menu/index.d.ts.map +1 -0
  37. package/dist/context-menu/index.js +399 -0
  38. package/dist/context-menu/index.js.map +1 -0
  39. package/dist/critical-alert/index.d.ts +39 -0
  40. package/dist/critical-alert/index.d.ts.map +1 -0
  41. package/dist/critical-alert/index.js +50 -0
  42. package/dist/critical-alert/index.js.map +1 -0
  43. package/dist/data-table/index.d.ts +94 -0
  44. package/dist/data-table/index.d.ts.map +1 -0
  45. package/dist/data-table/index.js +128 -0
  46. package/dist/data-table/index.js.map +1 -0
  47. package/dist/disclosure/index.d.ts +35 -0
  48. package/dist/disclosure/index.d.ts.map +1 -0
  49. package/dist/disclosure/index.js +54 -0
  50. package/dist/disclosure/index.js.map +1 -0
  51. package/dist/drawer/index.d.ts +106 -0
  52. package/dist/drawer/index.d.ts.map +1 -0
  53. package/dist/drawer/index.js +352 -0
  54. package/dist/drawer/index.js.map +1 -0
  55. package/dist/empty-state/index.d.ts +86 -0
  56. package/dist/empty-state/index.d.ts.map +1 -0
  57. package/dist/empty-state/index.js +138 -0
  58. package/dist/empty-state/index.js.map +1 -0
  59. package/dist/env.d.js +1 -0
  60. package/dist/env.d.js.map +1 -0
  61. package/dist/field/index.d.ts +149 -0
  62. package/dist/field/index.d.ts.map +1 -0
  63. package/dist/field/index.js +121 -0
  64. package/dist/field/index.js.map +1 -0
  65. package/dist/file-upload/index.d.ts +140 -0
  66. package/dist/file-upload/index.d.ts.map +1 -0
  67. package/dist/file-upload/index.js +249 -0
  68. package/dist/file-upload/index.js.map +1 -0
  69. package/dist/footer/index.d.ts +155 -0
  70. package/dist/footer/index.d.ts.map +1 -0
  71. package/dist/footer/index.js +186 -0
  72. package/dist/footer/index.js.map +1 -0
  73. package/dist/header/index.d.ts +170 -0
  74. package/dist/header/index.d.ts.map +1 -0
  75. package/dist/header/index.js +258 -0
  76. package/dist/header/index.js.map +1 -0
  77. package/dist/identifier/index.d.ts +38 -0
  78. package/dist/identifier/index.d.ts.map +1 -0
  79. package/dist/identifier/index.js +55 -0
  80. package/dist/identifier/index.js.map +1 -0
  81. package/dist/in-page-navigation/index.d.ts +71 -0
  82. package/dist/in-page-navigation/index.d.ts.map +1 -0
  83. package/dist/in-page-navigation/index.js +137 -0
  84. package/dist/in-page-navigation/index.js.map +1 -0
  85. package/dist/index.d.ts +57 -0
  86. package/dist/index.d.ts.map +1 -0
  87. package/dist/index.js +47 -0
  88. package/dist/index.js.map +1 -0
  89. package/dist/input-group/index.d.ts +66 -0
  90. package/dist/input-group/index.d.ts.map +1 -0
  91. package/dist/input-group/index.js +85 -0
  92. package/dist/input-group/index.js.map +1 -0
  93. package/dist/lib/krds.d.ts +45 -0
  94. package/dist/lib/krds.d.ts.map +1 -0
  95. package/dist/lib/krds.js +11 -0
  96. package/dist/lib/krds.js.map +1 -0
  97. package/dist/lib/link.d.ts +34 -0
  98. package/dist/lib/link.d.ts.map +1 -0
  99. package/dist/lib/link.js +8 -0
  100. package/dist/lib/link.js.map +1 -0
  101. package/dist/main-menu/index.d.ts +123 -0
  102. package/dist/main-menu/index.d.ts.map +1 -0
  103. package/dist/main-menu/index.js +613 -0
  104. package/dist/main-menu/index.js.map +1 -0
  105. package/dist/masthead/index.d.ts +25 -0
  106. package/dist/masthead/index.d.ts.map +1 -0
  107. package/dist/masthead/index.js +21 -0
  108. package/dist/masthead/index.js.map +1 -0
  109. package/dist/modal/index.d.ts +105 -0
  110. package/dist/modal/index.d.ts.map +1 -0
  111. package/dist/modal/index.js +285 -0
  112. package/dist/modal/index.js.map +1 -0
  113. package/dist/pagination/index.d.ts +58 -0
  114. package/dist/pagination/index.d.ts.map +1 -0
  115. package/dist/pagination/index.js +82 -0
  116. package/dist/pagination/index.js.map +1 -0
  117. package/dist/progress/index.d.ts +58 -0
  118. package/dist/progress/index.d.ts.map +1 -0
  119. package/dist/progress/index.js +125 -0
  120. package/dist/progress/index.js.map +1 -0
  121. package/dist/radio/index.d.ts +111 -0
  122. package/dist/radio/index.d.ts.map +1 -0
  123. package/dist/radio/index.js +136 -0
  124. package/dist/radio/index.js.map +1 -0
  125. package/dist/resize/index.d.ts +118 -0
  126. package/dist/resize/index.d.ts.map +1 -0
  127. package/dist/resize/index.js +342 -0
  128. package/dist/resize/index.js.map +1 -0
  129. package/dist/scroll-area/index.d.ts +40 -0
  130. package/dist/scroll-area/index.d.ts.map +1 -0
  131. package/dist/scroll-area/index.js +52 -0
  132. package/dist/scroll-area/index.js.map +1 -0
  133. package/dist/select/index.d.ts +67 -0
  134. package/dist/select/index.d.ts.map +1 -0
  135. package/dist/select/index.js +61 -0
  136. package/dist/select/index.js.map +1 -0
  137. package/dist/separator/index.d.ts +47 -0
  138. package/dist/separator/index.d.ts.map +1 -0
  139. package/dist/separator/index.js +61 -0
  140. package/dist/separator/index.js.map +1 -0
  141. package/dist/side-navigation/index.d.ts +78 -0
  142. package/dist/side-navigation/index.d.ts.map +1 -0
  143. package/dist/side-navigation/index.js +188 -0
  144. package/dist/side-navigation/index.js.map +1 -0
  145. package/dist/skeleton/index.d.ts +76 -0
  146. package/dist/skeleton/index.d.ts.map +1 -0
  147. package/dist/skeleton/index.js +78 -0
  148. package/dist/skeleton/index.js.map +1 -0
  149. package/dist/skip-link/index.d.ts +46 -0
  150. package/dist/skip-link/index.d.ts.map +1 -0
  151. package/dist/skip-link/index.js +37 -0
  152. package/dist/skip-link/index.js.map +1 -0
  153. package/dist/spinner/index.d.ts +58 -0
  154. package/dist/spinner/index.d.ts.map +1 -0
  155. package/dist/spinner/index.js +36 -0
  156. package/dist/spinner/index.js.map +1 -0
  157. package/dist/step-indicator/index.d.ts +41 -0
  158. package/dist/step-indicator/index.d.ts.map +1 -0
  159. package/dist/step-indicator/index.js +63 -0
  160. package/dist/step-indicator/index.js.map +1 -0
  161. package/dist/structured-list/index.d.ts +150 -0
  162. package/dist/structured-list/index.d.ts.map +1 -0
  163. package/dist/structured-list/index.js +194 -0
  164. package/dist/structured-list/index.js.map +1 -0
  165. package/dist/tab/index.d.ts +108 -0
  166. package/dist/tab/index.d.ts.map +1 -0
  167. package/dist/tab/index.js +198 -0
  168. package/dist/tab/index.js.map +1 -0
  169. package/dist/table/index.d.ts +75 -0
  170. package/dist/table/index.d.ts.map +1 -0
  171. package/dist/table/index.js +91 -0
  172. package/dist/table/index.js.map +1 -0
  173. package/dist/tag/index.d.ts +71 -0
  174. package/dist/tag/index.d.ts.map +1 -0
  175. package/dist/tag/index.js +45 -0
  176. package/dist/tag/index.js.map +1 -0
  177. package/dist/text-input/index.d.ts +69 -0
  178. package/dist/text-input/index.d.ts.map +1 -0
  179. package/dist/text-input/index.js +70 -0
  180. package/dist/text-input/index.js.map +1 -0
  181. package/dist/text-list/index.d.ts +71 -0
  182. package/dist/text-list/index.d.ts.map +1 -0
  183. package/dist/text-list/index.js +79 -0
  184. package/dist/text-list/index.js.map +1 -0
  185. package/dist/textarea/index.d.ts +29 -0
  186. package/dist/textarea/index.d.ts.map +1 -0
  187. package/dist/textarea/index.js +69 -0
  188. package/dist/textarea/index.js.map +1 -0
  189. package/dist/toast/index.d.ts +76 -0
  190. package/dist/toast/index.d.ts.map +1 -0
  191. package/dist/toast/index.js +183 -0
  192. package/dist/toast/index.js.map +1 -0
  193. package/dist/tooltip/index.d.ts +84 -0
  194. package/dist/tooltip/index.d.ts.map +1 -0
  195. package/dist/tooltip/index.js +329 -0
  196. package/dist/tooltip/index.js.map +1 -0
  197. package/package.json +57 -0
  198. package/src/accordion/index.tsx +251 -0
  199. package/src/alert/index.tsx +111 -0
  200. package/src/avatar/index.tsx +272 -0
  201. package/src/badge/index.tsx +91 -0
  202. package/src/breadcrumb/index.tsx +125 -0
  203. package/src/button/index.tsx +190 -0
  204. package/src/checkbox/index.tsx +247 -0
  205. package/src/combobox/index.tsx +700 -0
  206. package/src/context-menu/index.tsx +623 -0
  207. package/src/critical-alert/index.tsx +102 -0
  208. package/src/data-table/index.tsx +289 -0
  209. package/src/disclosure/index.tsx +87 -0
  210. package/src/drawer/index.tsx +516 -0
  211. package/src/empty-state/index.tsx +256 -0
  212. package/src/env.d.ts +10 -0
  213. package/src/field/index.tsx +307 -0
  214. package/src/file-upload/index.tsx +492 -0
  215. package/src/footer/index.tsx +393 -0
  216. package/src/header/index.tsx +498 -0
  217. package/src/identifier/index.tsx +96 -0
  218. package/src/in-page-navigation/index.tsx +258 -0
  219. package/src/index.ts +72 -0
  220. package/src/input-group/index.tsx +197 -0
  221. package/src/lib/krds.ts +75 -0
  222. package/src/lib/link.tsx +35 -0
  223. package/src/main-menu/index.tsx +912 -0
  224. package/src/masthead/index.tsx +50 -0
  225. package/src/modal/index.tsx +457 -0
  226. package/src/pagination/index.tsx +198 -0
  227. package/src/progress/index.tsx +198 -0
  228. package/src/radio/index.tsx +283 -0
  229. package/src/resize/index.tsx +541 -0
  230. package/src/scroll-area/index.tsx +96 -0
  231. package/src/select/index.tsx +136 -0
  232. package/src/separator/index.tsx +107 -0
  233. package/src/side-navigation/index.tsx +336 -0
  234. package/src/skeleton/index.tsx +172 -0
  235. package/src/skip-link/index.tsx +89 -0
  236. package/src/spinner/index.tsx +98 -0
  237. package/src/step-indicator/index.tsx +122 -0
  238. package/src/structured-list/index.tsx +395 -0
  239. package/src/tab/index.tsx +348 -0
  240. package/src/table/index.tsx +186 -0
  241. package/src/tag/index.tsx +127 -0
  242. package/src/text-input/index.tsx +156 -0
  243. package/src/text-list/index.tsx +177 -0
  244. package/src/textarea/index.tsx +113 -0
  245. package/src/toast/index.tsx +311 -0
  246. package/src/tooltip/index.tsx +496 -0
  247. package/styles/krds-tailwind.css +335 -0
@@ -0,0 +1,94 @@
1
+ import type { ComponentPropsWithRef, ReactNode } from 'react';
2
+ import { type KrdsTone } from '../lib/krds';
3
+ /**
4
+ * 데이터 표 — 킷 `krds-table-wrap` + `tbl data` 위에 정렬·고정 헤더·빈 상태를 얹은 것.
5
+ *
6
+ * 열을 `columns` 로 넘겨 목록을 그린다. 표를 손으로 짤 때는 `ui/table` 의 조각을 쓴다.
7
+ * `caption` 은 **화면에 보이지 않는 보조기기 설명**이다 — 보이는 제목은 `heading` 이다.
8
+ * 정렬 버튼은 `onSortChange` 를 주었을 때만 그려지고, 행 강조는 `rowTone` 으로만 준다
9
+ * (`<tr>` 배경은 킷 셀 배경에 덮인다). 빈 셀에는 `-` 가 자동으로 들어간다.
10
+ *
11
+ * @example
12
+ * <DataTable
13
+ * caption="공지사항 목록 표로 번호, 제목, 작성자, 등록일 순으로 구성되어 있다."
14
+ * heading="공지사항"
15
+ * columns={[
16
+ * { key: 'title', header: '제목', cell: (r) => r.title, sortable: true },
17
+ * { key: 'hit', header: '조회', cell: (r) => r.hit, numeric: true },
18
+ * ]}
19
+ * rows={rows}
20
+ * rowKey={(r) => r.id}
21
+ * sort={sort}
22
+ * onSortChange={setSort}
23
+ * />
24
+ *
25
+ * 자세히: docs/krds/09-부품-노트.md#데이터표
26
+ */
27
+ /** 정렬 방향. */
28
+ export type SortDirection = 'asc' | 'desc';
29
+ /** 지금 어느 열을 어느 방향으로 정렬하고 있는가. */
30
+ export type SortState = {
31
+ /** 열의 `sortKey`(없으면 `key`). */
32
+ key: string;
33
+ direction: SortDirection;
34
+ };
35
+ export type DataColumn<T> = {
36
+ /** React key 이자 기본 정렬 키. */
37
+ key: string;
38
+ /** 열 제목. `<th scope="col">` 안에 들어간다. */
39
+ header: ReactNode;
40
+ /** 한 칸의 내용. */
41
+ cell: (row: T, index: number) => ReactNode;
42
+ /** `cell` 이 빈 값을 돌려줬을 때 넣을 것. 기본 `-`. 정말 비우려면 `null` 을 준다. */
43
+ empty?: ReactNode;
44
+ /** 양적 데이터(개수·퍼센트·용량). 오른쪽 정렬 + 자릿수 고정. 날짜·전화번호에는 주지 마라. */
45
+ numeric?: boolean;
46
+ /** `<colgroup><col style="width:…">` 로 나간다. */
47
+ width?: number | string;
48
+ /** 이 열로 정렬할 수 있는가. `onSortChange` 가 없으면 무시한다. */
49
+ sortable?: boolean;
50
+ /** 정렬 키를 열 `key` 와 다르게 둘 때(예: 화면은 `author`, 질의는 `author_name`). */
51
+ sortKey?: string;
52
+ /** 이 열을 행 머리글(`<th scope="row">`)로 낸다. 표 단위 `rowHeader` 보다 우선한다. */
53
+ rowHeader?: boolean;
54
+ /** 열 제목 칸에만 더할 클래스. */
55
+ headerClassName?: string;
56
+ /** 이 열의 데이터 칸에 더할 클래스. */
57
+ cellClassName?: string;
58
+ };
59
+ export type DataTableProps<T> = Omit<ComponentPropsWithRef<'div'>, 'children'> & {
60
+ /** 보조기기가 읽을 표 설명. 화면에는 보이지 않는다 — 열 이름을 모두 담아 한 문장으로 적는다. */
61
+ caption: string;
62
+ /** 화면에 보이는 제목. 표 바깥에 그린다. */
63
+ heading?: ReactNode;
64
+ /** 제목을 어떤 태그로 낼지. 문서 목차에 넣으려면 `h2`~`h5` 를 준다. */
65
+ headingAs?: 'h2' | 'h3' | 'h4' | 'h5' | 'p' | 'div';
66
+ columns: DataColumn<T>[];
67
+ rows: T[];
68
+ rowKey: (row: T, index: number) => string | number;
69
+ /** 행이 하나도 없을 때 표 안에 그릴 것. 셀 하나가 빈 것은 `column.empty` 가 맡는다. */
70
+ empty?: ReactNode;
71
+ /** 첫 열을 행 머리글(`<th scope="row">`)로 낸다. 행마다 이름이 있는 표에 쓴다. */
72
+ rowHeader?: boolean;
73
+ /** 행 강조색. 「편집 중」·「실패」처럼 뜻이 있는 강조에만 쓴다. 셀마다 칠한다. */
74
+ rowTone?: (row: T, index: number) => KrdsTone | undefined;
75
+ /** `<tr>` 에 더할 클래스. 배경색은 여기 주지 마라 — 킷 셀 배경에 덮인다(`rowTone` 을 쓴다). */
76
+ rowClassName?: (row: T, index: number) => string | undefined;
77
+ /** 지금 정렬 상태. `null`/생략이면 정렬 안 함. */
78
+ sort?: SortState | null;
79
+ /**
80
+ * 정렬 헤더를 눌렀을 때. **이 콜백이 있어야 정렬 버튼이 그려진다.**
81
+ * 정렬 뒤에는 `rows` 만 갈아 끼운다 — 표를 통째로 다시 마운트하면 초점이 날아간다.
82
+ */
83
+ onSortChange?: (next: SortState) => void;
84
+ /** 열 제목 줄을 위에 붙박는다. `maxHeight` 와 같이 줘야 표 안에서 스크롤된다. */
85
+ stickyHeader?: boolean;
86
+ /** 표 영역 최대 높이. 주면 세로 스크롤이 생긴다. */
87
+ maxHeight?: number | string;
88
+ /** 좁은 화면에서 셀을 줄바꿈하지 않고 가로로 스크롤(킷 `mob-scroll`). 기본 참. */
89
+ mobileScroll?: boolean;
90
+ /** 넓은 화면에서도 가로 스크롤(킷 `scroll`). `maxHeight` 와 같이 쓰면 무시한다. */
91
+ horizontalScroll?: boolean;
92
+ };
93
+ export declare function DataTable<T>({ caption, heading, headingAs: Heading, columns, rows, rowKey, empty, rowHeader, rowTone, rowClassName, sort, onSortChange, stickyHeader, maxHeight, mobileScroll, horizontalScroll, className, ...rest }: DataTableProps<T>): import("react").JSX.Element;
94
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data-table/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { cx } from "../lib/krds.js";
3
+ const ROW_TONE = {
4
+ primary: "bg-primary-surface",
5
+ secondary: "bg-secondary-surface",
6
+ gray: "bg-surface-subtler",
7
+ point: "bg-point-surface",
8
+ danger: "bg-danger-surface",
9
+ warning: "bg-warning-surface",
10
+ success: "bg-success-surface",
11
+ information: "bg-information-surface"
12
+ };
13
+ function isBlank(value) {
14
+ if (value === null || value === void 0 || value === "") return true;
15
+ return Array.isArray(value) && value.length === 0;
16
+ }
17
+ function withPlaceholder(value, empty) {
18
+ if (!isBlank(value)) return value;
19
+ return empty === void 0 ? "-" : empty;
20
+ }
21
+ function sortHint(direction) {
22
+ if (direction === "asc") return "\uC624\uB984\uCC28\uC21C \uC815\uB82C\uB428, \uB204\uB974\uBA74 \uB0B4\uB9BC\uCC28\uC21C \uC815\uB82C";
23
+ if (direction === "desc") return "\uB0B4\uB9BC\uCC28\uC21C \uC815\uB82C\uB428, \uB204\uB974\uBA74 \uC624\uB984\uCC28\uC21C \uC815\uB82C";
24
+ return "\uC815\uB82C \uC548 \uD568, \uB204\uB974\uBA74 \uC624\uB984\uCC28\uC21C \uC815\uB82C";
25
+ }
26
+ function DataTable({
27
+ caption,
28
+ heading,
29
+ headingAs: Heading = "div",
30
+ columns,
31
+ rows,
32
+ rowKey,
33
+ empty = "\uC790\uB8CC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
34
+ rowHeader = false,
35
+ rowTone,
36
+ rowClassName,
37
+ sort,
38
+ onSortChange,
39
+ stickyHeader = false,
40
+ maxHeight,
41
+ mobileScroll = true,
42
+ horizontalScroll = false,
43
+ className,
44
+ ...rest
45
+ }) {
46
+ const hasWidth = columns.some((c) => c.width !== void 0);
47
+ const scrolls = maxHeight !== void 0;
48
+ return /* @__PURE__ */ jsxs("div", { className: cx("flex flex-col gap-2", className), ...rest, children: [
49
+ heading != null && /* @__PURE__ */ jsx(Heading, { className: "text-heading-xxs font-bold text-fg-bolder", children: heading }),
50
+ /* @__PURE__ */ jsx(
51
+ "div",
52
+ {
53
+ className: cx(
54
+ "krds-table-wrap",
55
+ mobileScroll && "mob-scroll",
56
+ // 킷 `.scroll` 은 overflow-y 를 hidden 으로 잠근다 — 세로 스크롤과 같이 쓸 수 없다.
57
+ horizontalScroll && !scrolls && "scroll",
58
+ scrolls && "overflow-auto"
59
+ ),
60
+ style: scrolls ? { maxHeight } : void 0,
61
+ children: /* @__PURE__ */ jsxs("table", { className: "tbl col data", style: (horizontalScroll || mobileScroll) && !hasWidth ? { tableLayout: "auto" } : void 0, children: [
62
+ /* @__PURE__ */ jsx("caption", { children: caption }),
63
+ hasWidth && /* @__PURE__ */ jsx("colgroup", { children: columns.map((col) => /* @__PURE__ */ jsx("col", { style: col.width !== void 0 ? { width: col.width } : void 0 }, col.key)) }),
64
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: columns.map((col) => {
65
+ const key = col.sortKey ?? col.key;
66
+ const direction = sort && sort.key === key ? sort.direction : void 0;
67
+ const active = direction !== void 0;
68
+ const canSort = col.sortable === true && onSortChange !== void 0;
69
+ return /* @__PURE__ */ jsx(
70
+ "th",
71
+ {
72
+ scope: "col",
73
+ "aria-sort": canSort ? active ? direction === "asc" ? "ascending" : "descending" : "none" : void 0,
74
+ className: cx(
75
+ col.numeric && "text-right",
76
+ // 킷 thead 배경(`--krds-table--data-thead-surface`)이 불투명이라 그대로 붙박아도 비치지 않는다.
77
+ stickyHeader && "sticky top-0 z-10",
78
+ col.headerClassName
79
+ ) || void 0,
80
+ children: canSort ? /* @__PURE__ */ jsxs(
81
+ "button",
82
+ {
83
+ type: "button",
84
+ className: cx(
85
+ "inline-flex items-center gap-1 text-left",
86
+ col.numeric && "w-full justify-end"
87
+ ),
88
+ onClick: () => onSortChange?.({ key, direction: direction === "asc" ? "desc" : "asc" }),
89
+ children: [
90
+ col.header,
91
+ /* @__PURE__ */ jsx(
92
+ "i",
93
+ {
94
+ className: cx(
95
+ "svg-icon ico-angle size-4 shrink-0 bg-fg-bolder",
96
+ direction === "asc" && "up",
97
+ !active && "opacity-40"
98
+ ),
99
+ "aria-hidden": "true"
100
+ }
101
+ ),
102
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: sortHint(direction) })
103
+ ]
104
+ }
105
+ ) : col.header
106
+ },
107
+ col.key
108
+ );
109
+ }) }) }),
110
+ /* @__PURE__ */ jsx("tbody", { children: rows.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: columns.length, className: "py-10 text-center text-fg-subtle", children: empty }) }) : rows.map((row, i) => {
111
+ const tone = rowTone?.(row, i);
112
+ const toneClass = tone && ROW_TONE[tone];
113
+ return /* @__PURE__ */ jsx("tr", { className: rowClassName?.(row, i), children: columns.map((col, j) => {
114
+ const asRowHeader = col.rowHeader ?? (rowHeader && j === 0);
115
+ const cellClass = cx(col.numeric && "text-right tabular-nums", toneClass, col.cellClassName) || void 0;
116
+ const content = withPlaceholder(col.cell(row, i), col.empty);
117
+ return asRowHeader ? /* @__PURE__ */ jsx("th", { scope: "row", className: cx("font-bold", cellClass), children: content }, col.key) : /* @__PURE__ */ jsx("td", { className: cellClass, children: content }, col.key);
118
+ }) }, rowKey(row, i));
119
+ }) })
120
+ ] })
121
+ }
122
+ )
123
+ ] });
124
+ }
125
+ export {
126
+ DataTable
127
+ };
128
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/data-table/index.tsx"],"sourcesContent":["import type { ComponentPropsWithRef, ReactNode } from 'react';\nimport { cx, type KrdsTone } from '../lib/krds';\n\n/**\n * 데이터 표 — 킷 `krds-table-wrap` + `tbl data` 위에 정렬·고정 헤더·빈 상태를 얹은 것.\n *\n * 열을 `columns` 로 넘겨 목록을 그린다. 표를 손으로 짤 때는 `ui/table` 의 조각을 쓴다.\n * `caption` 은 **화면에 보이지 않는 보조기기 설명**이다 — 보이는 제목은 `heading` 이다.\n * 정렬 버튼은 `onSortChange` 를 주었을 때만 그려지고, 행 강조는 `rowTone` 으로만 준다\n * (`<tr>` 배경은 킷 셀 배경에 덮인다). 빈 셀에는 `-` 가 자동으로 들어간다.\n *\n * @example\n * <DataTable\n * caption=\"공지사항 목록 표로 번호, 제목, 작성자, 등록일 순으로 구성되어 있다.\"\n * heading=\"공지사항\"\n * columns={[\n * { key: 'title', header: '제목', cell: (r) => r.title, sortable: true },\n * { key: 'hit', header: '조회', cell: (r) => r.hit, numeric: true },\n * ]}\n * rows={rows}\n * rowKey={(r) => r.id}\n * sort={sort}\n * onSortChange={setSort}\n * />\n *\n * 자세히: docs/krds/09-부품-노트.md#데이터표\n */\n\n/** 정렬 방향. */\nexport type SortDirection = 'asc' | 'desc';\n\n/** 지금 어느 열을 어느 방향으로 정렬하고 있는가. */\nexport type SortState = {\n /** 열의 `sortKey`(없으면 `key`). */\n key: string;\n direction: SortDirection;\n};\n\nexport type DataColumn<T> = {\n /** React key 이자 기본 정렬 키. */\n key: string;\n /** 열 제목. `<th scope=\"col\">` 안에 들어간다. */\n header: ReactNode;\n /** 한 칸의 내용. */\n cell: (row: T, index: number) => ReactNode;\n /** `cell` 이 빈 값을 돌려줬을 때 넣을 것. 기본 `-`. 정말 비우려면 `null` 을 준다. */\n empty?: ReactNode;\n /** 양적 데이터(개수·퍼센트·용량). 오른쪽 정렬 + 자릿수 고정. 날짜·전화번호에는 주지 마라. */\n numeric?: boolean;\n /** `<colgroup><col style=\"width:…\">` 로 나간다. */\n width?: number | string;\n /** 이 열로 정렬할 수 있는가. `onSortChange` 가 없으면 무시한다. */\n sortable?: boolean;\n /** 정렬 키를 열 `key` 와 다르게 둘 때(예: 화면은 `author`, 질의는 `author_name`). */\n sortKey?: string;\n /** 이 열을 행 머리글(`<th scope=\"row\">`)로 낸다. 표 단위 `rowHeader` 보다 우선한다. */\n rowHeader?: boolean;\n /** 열 제목 칸에만 더할 클래스. */\n headerClassName?: string;\n /** 이 열의 데이터 칸에 더할 클래스. */\n cellClassName?: string;\n};\n\nexport type DataTableProps<T> = Omit<ComponentPropsWithRef<'div'>, 'children'> & {\n /** 보조기기가 읽을 표 설명. 화면에는 보이지 않는다 — 열 이름을 모두 담아 한 문장으로 적는다. */\n caption: string;\n /** 화면에 보이는 제목. 표 바깥에 그린다. */\n heading?: ReactNode;\n /** 제목을 어떤 태그로 낼지. 문서 목차에 넣으려면 `h2`~`h5` 를 준다. */\n headingAs?: 'h2' | 'h3' | 'h4' | 'h5' | 'p' | 'div';\n columns: DataColumn<T>[];\n rows: T[];\n rowKey: (row: T, index: number) => string | number;\n /** 행이 하나도 없을 때 표 안에 그릴 것. 셀 하나가 빈 것은 `column.empty` 가 맡는다. */\n empty?: ReactNode;\n /** 첫 열을 행 머리글(`<th scope=\"row\">`)로 낸다. 행마다 이름이 있는 표에 쓴다. */\n rowHeader?: boolean;\n /** 행 강조색. 「편집 중」·「실패」처럼 뜻이 있는 강조에만 쓴다. 셀마다 칠한다. */\n rowTone?: (row: T, index: number) => KrdsTone | undefined;\n /** `<tr>` 에 더할 클래스. 배경색은 여기 주지 마라 — 킷 셀 배경에 덮인다(`rowTone` 을 쓴다). */\n rowClassName?: (row: T, index: number) => string | undefined;\n /** 지금 정렬 상태. `null`/생략이면 정렬 안 함. */\n sort?: SortState | null;\n /**\n * 정렬 헤더를 눌렀을 때. **이 콜백이 있어야 정렬 버튼이 그려진다.**\n * 정렬 뒤에는 `rows` 만 갈아 끼운다 — 표를 통째로 다시 마운트하면 초점이 날아간다.\n */\n onSortChange?: (next: SortState) => void;\n /** 열 제목 줄을 위에 붙박는다. `maxHeight` 와 같이 줘야 표 안에서 스크롤된다. */\n stickyHeader?: boolean;\n /** 표 영역 최대 높이. 주면 세로 스크롤이 생긴다. */\n maxHeight?: number | string;\n /** 좁은 화면에서 셀을 줄바꿈하지 않고 가로로 스크롤(킷 `mob-scroll`). 기본 참. */\n mobileScroll?: boolean;\n /** 넓은 화면에서도 가로 스크롤(킷 `scroll`). `maxHeight` 와 같이 쓰면 무시한다. */\n horizontalScroll?: boolean;\n};\n\n/** 행 강조색 → 유틸리티. 넓은 면이라 `surface` 축이고, gray 만 짝이 없어 중립 면 토큰을 쓴다. */\nconst ROW_TONE: Record<KrdsTone, string> = {\n primary: 'bg-primary-surface',\n secondary: 'bg-secondary-surface',\n gray: 'bg-surface-subtler',\n point: 'bg-point-surface',\n danger: 'bg-danger-surface',\n warning: 'bg-warning-surface',\n success: 'bg-success-surface',\n information: 'bg-information-surface',\n};\n\n/** `-` 로 바꿔야 하는 빈 값인가. `0` 과 `false` 는 값이다. `ui/table` 의 `Td` 와 같은 판정이다. */\nfunction isBlank(value: ReactNode): boolean {\n if (value === null || value === undefined || value === '') return true;\n return Array.isArray(value) && value.length === 0;\n}\n\n/** 빈 셀의 대시 플레이스홀더. `empty` 를 `null` 로 주면 정말 비운다. */\nfunction withPlaceholder(value: ReactNode, empty: ReactNode): ReactNode {\n if (!isBlank(value)) return value;\n return empty === undefined ? '-' : empty;\n}\n\n/** 정렬 버튼이 스크린리더에 읽어 줄 현재 상태와 다음 동작. */\nfunction sortHint(direction: SortDirection | undefined): string {\n if (direction === 'asc') return '오름차순 정렬됨, 누르면 내림차순 정렬';\n if (direction === 'desc') return '내림차순 정렬됨, 누르면 오름차순 정렬';\n return '정렬 안 함, 누르면 오름차순 정렬';\n}\n\nexport function DataTable<T>({\n caption,\n heading,\n headingAs: Heading = 'div',\n columns,\n rows,\n rowKey,\n empty = '자료가 없습니다.',\n rowHeader = false,\n rowTone,\n rowClassName,\n sort,\n onSortChange,\n stickyHeader = false,\n maxHeight,\n mobileScroll = true,\n horizontalScroll = false,\n className,\n ...rest\n}: DataTableProps<T>) {\n const hasWidth = columns.some((c) => c.width !== undefined);\n const scrolls = maxHeight !== undefined;\n\n return (\n <div className={cx('flex flex-col gap-2', className)} {...rest}>\n {heading != null && (\n <Heading className=\"text-heading-xxs font-bold text-fg-bolder\">{heading}</Heading>\n )}\n\n <div\n className={cx(\n 'krds-table-wrap',\n mobileScroll && 'mob-scroll',\n // 킷 `.scroll` 은 overflow-y 를 hidden 으로 잠근다 — 세로 스크롤과 같이 쓸 수 없다.\n horizontalScroll && !scrolls && 'scroll',\n scrolls && 'overflow-auto',\n )}\n style={scrolls ? { maxHeight } : undefined}\n >\n {/* 가로로 스크롤되는 표는 열 폭을 내용에 맞춘다.\n 킷이 `table{table-layout:fixed}` 를 전역으로 못 박아 두어, 폭을 안 주면 열이 전부 같은 너비로 쪼개진다.\n 그 상태에서 `whitespace-nowrap` 을 준 칸(날짜·조작 단추)은 잘리지 않고 **옆 칸 위로 흘러넘쳐** 글자가 겹쳤다\n (관리자 콘텐츠 목록에서 게시일 141px 이 108px 칸을 넘어 출력기간과 포개졌다).\n 스크롤 상자 안에서는 표가 넓어져도 되므로 `auto` 가 맞다(`mob-scroll` 도 데스크톱에서 overflow-x:auto 다 — 실측).\n 스크롤이 아예 없는 표만 `fixed` 로 둔다 — 거기서는 한 열이 길어지면 나머지를 밀어내므로 균등 분배가 낫다.\n 폭을 손으로 준 표(`hasWidth`)도 건드리지 않는다. */}\n <table className=\"tbl col data\" style={(horizontalScroll || mobileScroll) && !hasWidth ? { tableLayout: 'auto' } : undefined}>\n {/* 킷이 !important 로 숨긴다 — 보조기기 전용이다. 보이는 제목은 위 `heading`. */}\n <caption>{caption}</caption>\n\n {hasWidth && (\n <colgroup>\n {columns.map((col) => (\n <col key={col.key} style={col.width !== undefined ? { width: col.width } : undefined} />\n ))}\n </colgroup>\n )}\n\n <thead>\n <tr>\n {columns.map((col) => {\n const key = col.sortKey ?? col.key;\n const direction = sort && sort.key === key ? sort.direction : undefined;\n const active = direction !== undefined;\n const canSort = col.sortable === true && onSortChange !== undefined;\n\n return (\n <th\n key={col.key}\n scope=\"col\"\n // 정렬 가능한 열은 정렬 중이 아니어도 `none` 을 달아야 「정렬할 수 있는 열」임이 전달된다.\n aria-sort={\n canSort ? (active ? (direction === 'asc' ? 'ascending' : 'descending') : 'none') : undefined\n }\n className={\n cx(\n col.numeric && 'text-right',\n // 킷 thead 배경(`--krds-table--data-thead-surface`)이 불투명이라 그대로 붙박아도 비치지 않는다.\n stickyHeader && 'sticky top-0 z-10',\n col.headerClassName,\n ) || undefined\n }\n >\n {canSort ? (\n <button\n type=\"button\"\n // 킷이 button 을 `font:inherit;color:inherit;background:transparent` 로 되돌려 주므로\n // 열 제목의 굵기·크기·색을 그대로 물려받는다. 배치만 잡으면 된다.\n className={cx(\n 'inline-flex items-center gap-1 text-left',\n col.numeric && 'w-full justify-end',\n )}\n onClick={() =>\n onSortChange?.({ key, direction: direction === 'asc' ? 'desc' : 'asc' })\n }\n >\n {col.header}\n {/* size-4(16px) = KRDS `--krds-icon--size-small`. 킷 기본값 large(24px)는 15px 제목에 너무 크다. */}\n <i\n className={cx(\n 'svg-icon ico-angle size-4 shrink-0 bg-fg-bolder',\n direction === 'asc' && 'up',\n !active && 'opacity-40',\n )}\n aria-hidden=\"true\"\n />\n <span className=\"sr-only\">{sortHint(direction)}</span>\n </button>\n ) : (\n col.header\n )}\n </th>\n );\n })}\n </tr>\n </thead>\n\n <tbody>\n {rows.length === 0 ? (\n <tr>\n {/* KRDS 에 빈 상태 부품이 없다 — 유틸리티로 그린다. py-10 = KRDS padding 40. */}\n <td colSpan={columns.length} className=\"py-10 text-center text-fg-subtle\">\n {empty}\n </td>\n </tr>\n ) : (\n rows.map((row, i) => {\n const tone = rowTone?.(row, i);\n const toneClass = tone && ROW_TONE[tone];\n\n return (\n <tr key={rowKey(row, i)} className={rowClassName?.(row, i)}>\n {columns.map((col, j) => {\n const asRowHeader = col.rowHeader ?? (rowHeader && j === 0);\n const cellClass =\n cx(col.numeric && 'text-right tabular-nums', toneClass, col.cellClassName) || undefined;\n // 빈 셀에는 대시(-) — `Td` 와 같은 규칙이다(함정 ⑤).\n const content = withPlaceholder(col.cell(row, i), col.empty);\n\n // 킷은 tbody 의 th 도 regular 로 그린다 — 행 머리글은 굵게 되돌린다.\n return asRowHeader ? (\n <th key={col.key} scope=\"row\" className={cx('font-bold', cellClass)}>\n {content}\n </th>\n ) : (\n <td key={col.key} className={cellClass}>\n {content}\n </td>\n );\n })}\n </tr>\n );\n })\n )}\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,35 @@
1
+ import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
+ /**
3
+ * 디스클로저(더 보기/접기) — KRDS `krds-disclosure`.
4
+ *
5
+ * 한 덩이의 **부가** 안내를 접었다 편다. 기본은 접힌 상태이고 한 섹션에 하나만 둔다.
6
+ * 여러 덩이를 목록으로 접었다 펴려면 `Accordion`, 내용을 갈아 끼우려면 `Tab` 이다.
7
+ * 오류 문구·중요한 정보·입력칸은 넣지 마라 — 접힌 안쪽은 보이지 않은 채 제출된다.
8
+ * 꺾쇠 아이콘은 킷이 그리므로 `<i class="svg-icon">` 를 따로 넣지 않는다.
9
+ *
10
+ * @example
11
+ * <Disclosure label="신청 서비스안내">
12
+ * <TextList marker="dash">
13
+ * <TextListItem>하나의 아이디로 여러 전자정부 서비스를 이용할 수 있습니다.</TextListItem>
14
+ * </TextList>
15
+ * </Disclosure>
16
+ *
17
+ * 자세히: docs/krds/09-부품-노트.md#상세보기
18
+ */
19
+ export type DisclosureProps = ComponentPropsWithRef<'div'> & {
20
+ /** 버튼에 보이는 글. 펼칠 내용을 유추할 수 있는 제목이어야 한다. */
21
+ label: ReactNode;
22
+ /** 처음부터 펼쳐 둘까. 기본 false 가 규격이다 — 되도록 바꾸지 마라. */
23
+ defaultOpen?: boolean;
24
+ /** 바깥에서 여닫기를 쥘 때. 주면 통제 모드가 되고 내부 상태는 쓰지 않는다. */
25
+ open?: boolean;
26
+ /** 사용자가 버튼을 눌러 상태가 바뀔 때. 통제 모드에서는 이걸 받아 직접 `open` 을 옮긴다. */
27
+ onOpenChange?: (open: boolean) => void;
28
+ /** 버튼(`btn-conts-expand`)에 덧붙일 클래스. */
29
+ buttonClassName?: string;
30
+ /** 안쪽 내용 상자(`expand-in`)에 덧붙일 클래스. */
31
+ contentClassName?: string;
32
+ children?: ReactNode;
33
+ };
34
+ export declare function Disclosure({ label, defaultOpen, open: openProp, onOpenChange, buttonClassName, contentClassName, className, children, ...rest }: DisclosureProps): import("react").JSX.Element;
35
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/disclosure/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAmB,KAAK,qBAAqB,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGpF;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,MAAM,eAAe,GAAG,qBAAqB,CAAC,KAAK,CAAC,GAAG;IAC3D,2CAA2C;IAC3C,KAAK,EAAE,SAAS,CAAC;IACjB,gDAAgD;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iDAAiD;IACjD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,4DAA4D;IAC5D,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,uCAAuC;IACvC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sCAAsC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,WAAmB,EACnB,IAAI,EAAE,QAAQ,EACd,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,SAAS,EACT,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,eAAe,+BAqCjB"}
@@ -0,0 +1,54 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useId, useState } from "react";
4
+ import { cx } from "../lib/krds.js";
5
+ function Disclosure({
6
+ label,
7
+ defaultOpen = false,
8
+ open: openProp,
9
+ onOpenChange,
10
+ buttonClassName,
11
+ contentClassName,
12
+ className,
13
+ children,
14
+ ...rest
15
+ }) {
16
+ const [selfOpen, setSelfOpen] = useState(defaultOpen);
17
+ const controlled = openProp !== void 0;
18
+ const open = controlled ? openProp : selfOpen;
19
+ const reactId = useId();
20
+ const contentId = `disclosure-${reactId}`;
21
+ function toggle() {
22
+ const next = !open;
23
+ if (!controlled) setSelfOpen(next);
24
+ onOpenChange?.(next);
25
+ }
26
+ return (
27
+ // `conts-expand-area` 는 킷 CSS 에 규칙이 없지만 마크업 샘플과 맞추려고 남긴다.
28
+ /* @__PURE__ */ jsxs(
29
+ "div",
30
+ {
31
+ className: cx("krds-disclosure", "conts-expand-area", open && "active", className),
32
+ ...rest,
33
+ children: [
34
+ /* @__PURE__ */ jsx(
35
+ "button",
36
+ {
37
+ type: "button",
38
+ className: cx("btn-conts-expand", buttonClassName),
39
+ "aria-expanded": open,
40
+ "aria-controls": contentId,
41
+ onClick: toggle,
42
+ children: label
43
+ }
44
+ ),
45
+ /* @__PURE__ */ jsx("div", { className: "expand-wrap", id: contentId, inert: !open, children: /* @__PURE__ */ jsx("div", { className: cx("expand-in", contentClassName), children }) })
46
+ ]
47
+ }
48
+ )
49
+ );
50
+ }
51
+ export {
52
+ Disclosure
53
+ };
54
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/disclosure/index.tsx"],"sourcesContent":["'use client';\n\nimport { useId, useState, type ComponentPropsWithRef, type ReactNode } from 'react';\nimport { cx } from '../lib/krds';\n\n/**\n * 디스클로저(더 보기/접기) — KRDS `krds-disclosure`.\n *\n * 한 덩이의 **부가** 안내를 접었다 편다. 기본은 접힌 상태이고 한 섹션에 하나만 둔다.\n * 여러 덩이를 목록으로 접었다 펴려면 `Accordion`, 내용을 갈아 끼우려면 `Tab` 이다.\n * 오류 문구·중요한 정보·입력칸은 넣지 마라 — 접힌 안쪽은 보이지 않은 채 제출된다.\n * 꺾쇠 아이콘은 킷이 그리므로 `<i class=\"svg-icon\">` 를 따로 넣지 않는다.\n *\n * @example\n * <Disclosure label=\"신청 서비스안내\">\n * <TextList marker=\"dash\">\n * <TextListItem>하나의 아이디로 여러 전자정부 서비스를 이용할 수 있습니다.</TextListItem>\n * </TextList>\n * </Disclosure>\n *\n * 자세히: docs/krds/09-부품-노트.md#상세보기\n */\n\nexport type DisclosureProps = ComponentPropsWithRef<'div'> & {\n /** 버튼에 보이는 글. 펼칠 내용을 유추할 수 있는 제목이어야 한다. */\n label: ReactNode;\n /** 처음부터 펼쳐 둘까. 기본 false 가 규격이다 — 되도록 바꾸지 마라. */\n defaultOpen?: boolean;\n /** 바깥에서 여닫기를 쥘 때. 주면 통제 모드가 되고 내부 상태는 쓰지 않는다. */\n open?: boolean;\n /** 사용자가 버튼을 눌러 상태가 바뀔 때. 통제 모드에서는 이걸 받아 직접 `open` 을 옮긴다. */\n onOpenChange?: (open: boolean) => void;\n /** 버튼(`btn-conts-expand`)에 덧붙일 클래스. */\n buttonClassName?: string;\n /** 안쪽 내용 상자(`expand-in`)에 덧붙일 클래스. */\n contentClassName?: string;\n children?: ReactNode;\n};\n\nexport function Disclosure({\n label,\n defaultOpen = false,\n open: openProp,\n onOpenChange,\n buttonClassName,\n contentClassName,\n className,\n children,\n ...rest\n}: DisclosureProps) {\n const [selfOpen, setSelfOpen] = useState(defaultOpen);\n // 통제/비통제 겸용. `open` 을 준 쪽이 이긴다.\n const controlled = openProp !== undefined;\n const open = controlled ? openProp : selfOpen;\n\n // 킷 JS 는 `disclosure-<난수>` 를 만들어 붙인다. React 는 useId 로 서버·클라이언트가 같은 값을 낸다.\n const reactId = useId();\n const contentId = `disclosure-${reactId}`;\n\n function toggle() {\n const next = !open;\n if (!controlled) setSelfOpen(next);\n onOpenChange?.(next);\n }\n\n return (\n // `conts-expand-area` 는 킷 CSS 에 규칙이 없지만 마크업 샘플과 맞추려고 남긴다.\n <div\n className={cx('krds-disclosure', 'conts-expand-area', open && 'active', className)}\n {...rest}\n >\n <button\n type=\"button\"\n className={cx('btn-conts-expand', buttonClassName)}\n aria-expanded={open}\n aria-controls={contentId}\n onClick={toggle}\n >\n {label}\n </button>\n {/* 접힌 동안 `inert` — 킷 JS 와 같다. 초점·클릭·보조기술을 한 번에 막는다. */}\n <div className=\"expand-wrap\" id={contentId} inert={!open}>\n <div className={cx('expand-in', contentClassName)}>{children}</div>\n </div>\n </div>\n );\n}\n"],"mappings":";AAmEI,SAIE,KAJF;AAjEJ,SAAS,OAAO,gBAA4D;AAC5E,SAAS,UAAU;AAoCZ,SAAS,WAAW;AAAA,EACzB;AAAA,EACA,cAAc;AAAA,EACd,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAoB;AAClB,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,WAAW;AAEpD,QAAM,aAAa,aAAa;AAChC,QAAM,OAAO,aAAa,WAAW;AAGrC,QAAM,UAAU,MAAM;AACtB,QAAM,YAAY,cAAc,OAAO;AAEvC,WAAS,SAAS;AAChB,UAAM,OAAO,CAAC;AACd,QAAI,CAAC,WAAY,aAAY,IAAI;AACjC,mBAAe,IAAI;AAAA,EACrB;AAEA;AAAA;AAAA,IAEE;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,GAAG,mBAAmB,qBAAqB,QAAQ,UAAU,SAAS;AAAA,QAChF,GAAG;AAAA,QAEJ;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAW,GAAG,oBAAoB,eAAe;AAAA,cACjD,iBAAe;AAAA,cACf,iBAAe;AAAA,cACf,SAAS;AAAA,cAER;AAAA;AAAA,UACH;AAAA,UAEA,oBAAC,SAAI,WAAU,eAAc,IAAI,WAAW,OAAO,CAAC,MAClD,8BAAC,SAAI,WAAW,GAAG,aAAa,gBAAgB,GAAI,UAAS,GAC/D;AAAA;AAAA;AAAA,IACF;AAAA;AAEJ;","names":[]}
@@ -0,0 +1,106 @@
1
+ import { type ComponentPropsWithRef, type CSSProperties, type ReactNode } from 'react';
2
+ /**
3
+ * 서랍(측면 패널) — KRDS 에 없다. 모양은 KRDS 토큰, 동작은 `Modal` 과 같은 보충 부품이다.
4
+ *
5
+ * 목록 옆에서 필터·상세를 여는 자리. 폭은 `size` 3단에서 고른다(픽셀을 넘기지 마라).
6
+ * 확정·취소는 `Drawer.Footer` 에 두고 제출이 가장 오른쪽이다.
7
+ * 뒤 화면을 계속 쓸 수 있어야 하면 `modal={false}` — 이때는 초점을 가두지 않는다.
8
+ * 화면 한복판에 띄우는 대화상자는 `ui/modal` 이다.
9
+ *
10
+ * @example
11
+ * <Drawer.Root open={open} onClose={close} side="right" size="small">
12
+ * <Drawer.Header extra={<Drawer.Close />}>검색 조건</Drawer.Header>
13
+ * <Drawer.Body>…필터 폼…</Drawer.Body>
14
+ * <Drawer.Footer split>
15
+ * <Button variant="text" onClick={reset}>초기화</Button>
16
+ * <Button variant="primary" onClick={apply}>적용</Button>
17
+ * </Drawer.Footer>
18
+ * </Drawer.Root>
19
+ *
20
+ * 자세히: docs/krds/09-부품-노트.md#서랍
21
+ */
22
+ /** 어느 쪽에서 나오는가. 아래에서 올라오는 것은 킷의 바텀시트(`ui/modal` 의 `type`) 자리다. */
23
+ export type DrawerSide = 'left' | 'right';
24
+ /** 폭 3단 — 400 / 560 / 760px. 킷 모달과 같은 눈금이다. */
25
+ export type DrawerSize = 'small' | 'medium' | 'large';
26
+ export type DrawerRootProps = ComponentPropsWithRef<'div'> & {
27
+ /** 열림 여부. 상태는 화면 쪽이 쥔다. */
28
+ open: boolean;
29
+ /** 닫아 달라는 요청 — Esc·딤 클릭·`Drawer.Close` 에서 온다. */
30
+ onClose: () => void;
31
+ /** 나오는 방향. 기본 오른쪽. */
32
+ side?: DrawerSide;
33
+ /** 기본 small(400px). 3단에서 고른다. */
34
+ size?: DrawerSize;
35
+ /** 딤을 깔고 초점을 가두는가. 기본 true — false 면 뒤 화면을 계속 쓸 수 있다. */
36
+ modal?: boolean;
37
+ /** Esc 로 닫을 수 있는가. */
38
+ dismissible?: boolean;
39
+ /** 딤을 눌렀을 때 닫는가. 기본 true — 값을 잃으면 곤란한 서랍에서는 꺼라. */
40
+ closeOnBackdrop?: boolean;
41
+ /** 열릴 때 첫 초점. 기본 `panel`(보조기술이 이름부터 읽는다) · `first` 는 첫 초점 요소로 보낸다. */
42
+ initialFocus?: 'panel' | 'first';
43
+ /** 포털 대상. 기본 `document.body`. */
44
+ container?: Element | null;
45
+ /** 패널(흰 면)에 붙일 클래스. 바깥틀은 `className` 이 받는다. */
46
+ panelClassName?: string;
47
+ /** 패널에 붙일 인라인 style. 폭을 3단 밖으로 바꿔야 할 때. */
48
+ panelStyle?: CSSProperties;
49
+ children?: ReactNode;
50
+ };
51
+ /**
52
+ * 서랍 바깥틀. 포털 · 초점 가둠 · Esc · 스크롤 잠금 · 초점 복귀를 여기서 한다.
53
+ *
54
+ * `Drawer.Header` 를 두면 `aria-labelledby` 가 자동으로 붙는다. 헤더 없이 쓸 거면
55
+ * `aria-label` 을 직접 넘겨라 — 대화상자에는 반드시 이름이 있어야 한다.
56
+ */
57
+ export declare function DrawerRoot({ open, onClose, side, size, modal, dismissible, closeOnBackdrop, initialFocus, container, panelClassName, panelStyle, className, style, children, onKeyDown, onMouseDown, ...rest }: DrawerRootProps): import("react").ReactPortal | null;
58
+ export type DrawerHeaderProps = ComponentPropsWithRef<'div'> & {
59
+ /** 제목 태그 단계. 기본 h2 — 화면의 제목 위계에 맞춘다. */
60
+ level?: 1 | 2 | 3 | 4 | 5 | 6;
61
+ /** 제목을 눈에서만 감춘다. 이름 자체는 남는다. */
62
+ hideTitle?: boolean;
63
+ /** 제목 요소에 붙일 클래스. */
64
+ titleClassName?: string;
65
+ /** 제목 오른쪽 자리. 닫기 버튼(`Drawer.Close`)을 여기에 둔다. */
66
+ extra?: ReactNode;
67
+ };
68
+ /**
69
+ * 제목 줄. 이 부품을 두면 서랍의 접근 가능한 이름이 자동으로 이어진다.
70
+ *
71
+ * @example
72
+ * <Drawer.Header extra={<Drawer.Close />}>검색 조건</Drawer.Header>
73
+ */
74
+ export declare function DrawerHeader({ level, hideTitle, titleClassName, extra, className, children, ...rest }: DrawerHeaderProps): import("react").JSX.Element;
75
+ /** 본문. 스크롤이 생기면 `tabindex="0"` 을 붙여 키보드로도 굴릴 수 있게 한다. */
76
+ export declare function DrawerBody({ className, children, ref, ...rest }: ComponentPropsWithRef<'div'>): import("react").JSX.Element;
77
+ export type DrawerFooterProps = ComponentPropsWithRef<'div'> & {
78
+ /** 좌우로 갈라 놓는다. 왼쪽에 보조 액션, 오른쪽에 확정 액션을 둘 때. */
79
+ split?: boolean;
80
+ };
81
+ /**
82
+ * 푸터 — 확정·취소 액션 자리. 제출(primary)이 가장 오른쪽이다.
83
+ * `split` 을 주면 왼쪽 보조 액션과 오른쪽 확정 액션으로 갈라 놓는다.
84
+ */
85
+ export declare function DrawerFooter({ split, className, children, ...rest }: DrawerFooterProps): import("react").JSX.Element;
86
+ export type DrawerCloseProps = Omit<ComponentPropsWithRef<'button'>, 'children'> & {
87
+ /** 스크린리더가 읽을 이름. 아이콘만 있는 버튼이라 반드시 있어야 한다. */
88
+ label?: string;
89
+ };
90
+ /**
91
+ * 닫기 버튼 — 킷 `krds-btn small icon` + `ico-popup-close`.
92
+ * **모달과 달리 `Drawer.Header` 의 `extra` 에 넣는다.**
93
+ *
94
+ * @example
95
+ * <Drawer.Header extra={<Drawer.Close />}>필터</Drawer.Header>
96
+ */
97
+ export declare function DrawerClose({ label, className, onClick, type, ...rest }: DrawerCloseProps): import("react").JSX.Element;
98
+ /** 합성용 묶음. `Root` · `Header` · `Body` · `Footer` · `Close`. */
99
+ export declare const Drawer: {
100
+ Root: typeof DrawerRoot;
101
+ Header: typeof DrawerHeader;
102
+ Body: typeof DrawerBody;
103
+ Footer: typeof DrawerFooter;
104
+ Close: typeof DrawerClose;
105
+ };
106
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/drawer/index.tsx"],"names":[],"mappings":"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"}