kokotable 0.95.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 (308) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +320 -0
  3. package/contract/table-request.schema.json +424 -0
  4. package/dist/core/src/adapters/sources.d.ts +59 -0
  5. package/dist/core/src/adapters/sources.js +235 -0
  6. package/dist/core/src/client/aggregate.d.ts +94 -0
  7. package/dist/core/src/client/aggregate.js +222 -0
  8. package/dist/core/src/client/groupRows.d.ts +40 -0
  9. package/dist/core/src/client/groupRows.js +145 -0
  10. package/dist/core/src/client/runClientQuery.d.ts +67 -0
  11. package/dist/core/src/client/runClientQuery.js +157 -0
  12. package/dist/core/src/columns/ColumnBuilder.d.ts +121 -0
  13. package/dist/core/src/columns/ColumnBuilder.js +273 -0
  14. package/dist/core/src/columns/cascade.d.ts +24 -0
  15. package/dist/core/src/columns/cascade.js +93 -0
  16. package/dist/core/src/columns/deriveOperators.d.ts +38 -0
  17. package/dist/core/src/columns/deriveOperators.js +94 -0
  18. package/dist/core/src/columns/expandSorting.d.ts +19 -0
  19. package/dist/core/src/columns/expandSorting.js +52 -0
  20. package/dist/core/src/columns/helper.d.ts +196 -0
  21. package/dist/core/src/columns/helper.js +250 -0
  22. package/dist/core/src/columns/labels.d.ts +12 -0
  23. package/dist/core/src/columns/labels.js +21 -0
  24. package/dist/core/src/contract.d.ts +12 -0
  25. package/dist/core/src/contract.js +12 -0
  26. package/dist/core/src/contracts/aiColumnMeta.d.ts +102 -0
  27. package/dist/core/src/contracts/aiColumnMeta.js +197 -0
  28. package/dist/core/src/contracts/describeColumns.d.ts +48 -0
  29. package/dist/core/src/contracts/describeColumns.js +40 -0
  30. package/dist/core/src/contracts/exportData.d.ts +150 -0
  31. package/dist/core/src/contracts/exportData.js +228 -0
  32. package/dist/core/src/contracts/index.d.ts +6 -0
  33. package/dist/core/src/contracts/index.js +12 -0
  34. package/dist/core/src/contracts/legacyUrl.d.ts +47 -0
  35. package/dist/core/src/contracts/legacyUrl.js +156 -0
  36. package/dist/core/src/contracts/preset.d.ts +104 -0
  37. package/dist/core/src/contracts/preset.js +141 -0
  38. package/dist/core/src/contracts/presetStore.d.ts +81 -0
  39. package/dist/core/src/contracts/presetStore.js +146 -0
  40. package/dist/core/src/contracts/usePresets.d.ts +51 -0
  41. package/dist/core/src/contracts/usePresets.js +170 -0
  42. package/dist/core/src/defaults.d.ts +7 -0
  43. package/dist/core/src/defaults.js +9 -0
  44. package/dist/core/src/filters/codec.d.ts +20 -0
  45. package/dist/core/src/filters/codec.js +61 -0
  46. package/dist/core/src/filters/date.d.ts +30 -0
  47. package/dist/core/src/filters/date.js +179 -0
  48. package/dist/core/src/filters/describe.d.ts +45 -0
  49. package/dist/core/src/filters/describe.js +189 -0
  50. package/dist/core/src/filters/kind.d.ts +52 -0
  51. package/dist/core/src/filters/kind.js +110 -0
  52. package/dist/core/src/filters/kinds/_list.d.ts +13 -0
  53. package/dist/core/src/filters/kinds/_list.js +42 -0
  54. package/dist/core/src/filters/kinds/boolean.d.ts +3 -0
  55. package/dist/core/src/filters/kinds/boolean.js +21 -0
  56. package/dist/core/src/filters/kinds/cascade.d.ts +6 -0
  57. package/dist/core/src/filters/kinds/cascade.js +16 -0
  58. package/dist/core/src/filters/kinds/commonCode.d.ts +3 -0
  59. package/dist/core/src/filters/kinds/commonCode.js +13 -0
  60. package/dist/core/src/filters/kinds/date.d.ts +9 -0
  61. package/dist/core/src/filters/kinds/date.js +32 -0
  62. package/dist/core/src/filters/kinds/enum.d.ts +4 -0
  63. package/dist/core/src/filters/kinds/enum.js +13 -0
  64. package/dist/core/src/filters/kinds/index.d.ts +49 -0
  65. package/dist/core/src/filters/kinds/index.js +39 -0
  66. package/dist/core/src/filters/kinds/linear.d.ts +5 -0
  67. package/dist/core/src/filters/kinds/linear.js +16 -0
  68. package/dist/core/src/filters/kinds/number.d.ts +5 -0
  69. package/dist/core/src/filters/kinds/number.js +19 -0
  70. package/dist/core/src/filters/kinds/period.d.ts +4 -0
  71. package/dist/core/src/filters/kinds/period.js +17 -0
  72. package/dist/core/src/filters/kinds/relation.d.ts +5 -0
  73. package/dist/core/src/filters/kinds/relation.js +17 -0
  74. package/dist/core/src/filters/kinds/schedule.d.ts +5 -0
  75. package/dist/core/src/filters/kinds/schedule.js +16 -0
  76. package/dist/core/src/filters/kinds/text.d.ts +4 -0
  77. package/dist/core/src/filters/kinds/text.js +18 -0
  78. package/dist/core/src/filters/linear.d.ts +33 -0
  79. package/dist/core/src/filters/linear.js +65 -0
  80. package/dist/core/src/filters/list.d.ts +32 -0
  81. package/dist/core/src/filters/list.js +87 -0
  82. package/dist/core/src/filters/number.d.ts +17 -0
  83. package/dist/core/src/filters/number.js +82 -0
  84. package/dist/core/src/filters/registry.d.ts +23 -0
  85. package/dist/core/src/filters/registry.js +121 -0
  86. package/dist/core/src/filters/relation.d.ts +26 -0
  87. package/dist/core/src/filters/relation.js +75 -0
  88. package/dist/core/src/filters/schedule.d.ts +21 -0
  89. package/dist/core/src/filters/schedule.js +60 -0
  90. package/dist/core/src/filters/text.d.ts +44 -0
  91. package/dist/core/src/filters/text.js +127 -0
  92. package/dist/core/src/hooks/index.d.ts +6 -0
  93. package/dist/core/src/hooks/index.js +6 -0
  94. package/dist/core/src/hooks/useDataTable.d.ts +13 -0
  95. package/dist/core/src/hooks/useDataTable.js +109 -0
  96. package/dist/core/src/hooks/useGrouping.d.ts +33 -0
  97. package/dist/core/src/hooks/useGrouping.js +57 -0
  98. package/dist/core/src/hooks/useSearchHistory.d.ts +20 -0
  99. package/dist/core/src/hooks/useSearchHistory.js +52 -0
  100. package/dist/core/src/hooks/useTableData.d.ts +25 -0
  101. package/dist/core/src/hooks/useTableData.js +49 -0
  102. package/dist/core/src/hooks/useTableFromDefinition.d.ts +47 -0
  103. package/dist/core/src/hooks/useTableFromDefinition.js +174 -0
  104. package/dist/core/src/hooks/useTableSearch.d.ts +10 -0
  105. package/dist/core/src/hooks/useTableSearch.js +434 -0
  106. package/dist/core/src/hooks/useUrlSync.d.ts +64 -0
  107. package/dist/core/src/hooks/useUrlSync.js +145 -0
  108. package/dist/core/src/index.d.ts +38 -0
  109. package/dist/core/src/index.js +43 -0
  110. package/dist/core/src/pivot/runClientPivot.d.ts +101 -0
  111. package/dist/core/src/pivot/runClientPivot.js +230 -0
  112. package/dist/core/src/pivot/transforms.d.ts +19 -0
  113. package/dist/core/src/pivot/transforms.js +105 -0
  114. package/dist/core/src/registry.d.ts +46 -0
  115. package/dist/core/src/registry.js +67 -0
  116. package/dist/core/src/types/column.d.ts +213 -0
  117. package/dist/core/src/types/column.js +1 -0
  118. package/dist/core/src/types/data.d.ts +63 -0
  119. package/dist/core/src/types/data.js +1 -0
  120. package/dist/core/src/types/definition.d.ts +239 -0
  121. package/dist/core/src/types/definition.js +59 -0
  122. package/dist/core/src/types/filter.d.ts +94 -0
  123. package/dist/core/src/types/filter.js +1 -0
  124. package/dist/core/src/types/filterKind.d.ts +204 -0
  125. package/dist/core/src/types/filterKind.js +1 -0
  126. package/dist/core/src/types/grouping.d.ts +80 -0
  127. package/dist/core/src/types/grouping.js +4 -0
  128. package/dist/core/src/types/index.d.ts +8 -0
  129. package/dist/core/src/types/index.js +8 -0
  130. package/dist/core/src/types/operators.d.ts +64 -0
  131. package/dist/core/src/types/operators.js +108 -0
  132. package/dist/core/src/types/request.d.ts +114 -0
  133. package/dist/core/src/types/request.js +1 -0
  134. package/dist/core/src/types/search.d.ts +112 -0
  135. package/dist/core/src/types/search.js +1 -0
  136. package/dist/core/src/types/sources.d.ts +84 -0
  137. package/dist/core/src/types/sources.js +1 -0
  138. package/dist/core/src/types/table.d.ts +40 -0
  139. package/dist/core/src/types/table.js +1 -0
  140. package/dist/core/src/utils/compare.d.ts +13 -0
  141. package/dist/core/src/utils/compare.js +53 -0
  142. package/dist/core/src/utils/dateText.d.ts +12 -0
  143. package/dist/core/src/utils/dateText.js +30 -0
  144. package/dist/core/src/utils/getValue.d.ts +9 -0
  145. package/dist/core/src/utils/getValue.js +32 -0
  146. package/dist/index.d.ts +1 -0
  147. package/dist/index.js +2 -0
  148. package/dist/mui/src/TableLayout.d.ts +75 -0
  149. package/dist/mui/src/TableLayout.js +162 -0
  150. package/dist/mui/src/TableScreen.d.ts +70 -0
  151. package/dist/mui/src/TableScreen.js +174 -0
  152. package/dist/mui/src/addons/FilterModal.d.ts +45 -0
  153. package/dist/mui/src/addons/FilterModal.js +39 -0
  154. package/dist/mui/src/addons/FilterStatusModal.d.ts +40 -0
  155. package/dist/mui/src/addons/FilterStatusModal.js +68 -0
  156. package/dist/mui/src/addons/PresetBar.d.ts +56 -0
  157. package/dist/mui/src/addons/PresetBar.js +145 -0
  158. package/dist/mui/src/addons/ShareDropdown.d.ts +35 -0
  159. package/dist/mui/src/addons/ShareDropdown.js +41 -0
  160. package/dist/mui/src/addons/searchStore.d.ts +44 -0
  161. package/dist/mui/src/addons/searchStore.js +112 -0
  162. package/dist/mui/src/addons/searchSummary.d.ts +106 -0
  163. package/dist/mui/src/addons/searchSummary.js +109 -0
  164. package/dist/mui/src/columns/displayColumns.d.ts +100 -0
  165. package/dist/mui/src/columns/displayColumns.js +174 -0
  166. package/dist/mui/src/content/CardContent.d.ts +24 -0
  167. package/dist/mui/src/content/CardContent.js +25 -0
  168. package/dist/mui/src/content/ColumnMenu.d.ts +43 -0
  169. package/dist/mui/src/content/ColumnMenu.js +40 -0
  170. package/dist/mui/src/content/ColumnVisibilityMenu.d.ts +14 -0
  171. package/dist/mui/src/content/ColumnVisibilityMenu.js +37 -0
  172. package/dist/mui/src/content/EditCell.d.ts +19 -0
  173. package/dist/mui/src/content/EditCell.js +61 -0
  174. package/dist/mui/src/content/HeaderCell.d.ts +59 -0
  175. package/dist/mui/src/content/HeaderCell.js +88 -0
  176. package/dist/mui/src/content/SelectionActionBar.d.ts +17 -0
  177. package/dist/mui/src/content/SelectionActionBar.js +19 -0
  178. package/dist/mui/src/content/SortControl.d.ts +17 -0
  179. package/dist/mui/src/content/SortControl.js +45 -0
  180. package/dist/mui/src/content/TableContent.d.ts +191 -0
  181. package/dist/mui/src/content/TableContent.js +525 -0
  182. package/dist/mui/src/content/TableErrorFallback.d.ts +24 -0
  183. package/dist/mui/src/content/TableErrorFallback.js +29 -0
  184. package/dist/mui/src/content/cellError.d.ts +13 -0
  185. package/dist/mui/src/content/cellError.js +20 -0
  186. package/dist/mui/src/content/cellRenderers.d.ts +71 -0
  187. package/dist/mui/src/content/cellRenderers.js +127 -0
  188. package/dist/mui/src/content/cellValue.d.ts +27 -0
  189. package/dist/mui/src/content/cellValue.js +82 -0
  190. package/dist/mui/src/content/columnOrder.d.ts +7 -0
  191. package/dist/mui/src/content/columnOrder.js +48 -0
  192. package/dist/mui/src/content/density.d.ts +13 -0
  193. package/dist/mui/src/content/density.js +12 -0
  194. package/dist/mui/src/content/menuItems.d.ts +118 -0
  195. package/dist/mui/src/content/menuItems.js +128 -0
  196. package/dist/mui/src/content/pinning.d.ts +17 -0
  197. package/dist/mui/src/content/pinning.js +65 -0
  198. package/dist/mui/src/exporters/index.d.ts +1 -0
  199. package/dist/mui/src/exporters/index.js +1 -0
  200. package/dist/mui/src/exporters/useExportFormatters.d.ts +13 -0
  201. package/dist/mui/src/exporters/useExportFormatters.js +17 -0
  202. package/dist/mui/src/filter/FilterArea.d.ts +40 -0
  203. package/dist/mui/src/filter/FilterArea.js +37 -0
  204. package/dist/mui/src/filter/FilterInput.d.ts +14 -0
  205. package/dist/mui/src/filter/FilterInput.js +18 -0
  206. package/dist/mui/src/filter/inputs/DateFilterInput.d.ts +14 -0
  207. package/dist/mui/src/filter/inputs/DateFilterInput.js +112 -0
  208. package/dist/mui/src/filter/inputs/LinearFilterInput.d.ts +10 -0
  209. package/dist/mui/src/filter/inputs/LinearFilterInput.js +35 -0
  210. package/dist/mui/src/filter/inputs/NumberFilterInput.d.ts +12 -0
  211. package/dist/mui/src/filter/inputs/NumberFilterInput.js +111 -0
  212. package/dist/mui/src/filter/inputs/OperatorMenu.d.ts +14 -0
  213. package/dist/mui/src/filter/inputs/OperatorMenu.js +25 -0
  214. package/dist/mui/src/filter/inputs/RelationFilterInput.d.ts +11 -0
  215. package/dist/mui/src/filter/inputs/RelationFilterInput.js +67 -0
  216. package/dist/mui/src/filter/inputs/ScheduleFilterInput.d.ts +8 -0
  217. package/dist/mui/src/filter/inputs/ScheduleFilterInput.js +17 -0
  218. package/dist/mui/src/filter/inputs/SelectFilterInput.d.ts +16 -0
  219. package/dist/mui/src/filter/inputs/SelectFilterInput.js +57 -0
  220. package/dist/mui/src/filter/inputs/TextFilterInput.d.ts +13 -0
  221. package/dist/mui/src/filter/inputs/TextFilterInput.js +55 -0
  222. package/dist/mui/src/filter/kinds.d.ts +58 -0
  223. package/dist/mui/src/filter/kinds.js +103 -0
  224. package/dist/mui/src/grouping/AggregateChip.d.ts +55 -0
  225. package/dist/mui/src/grouping/AggregateChip.js +128 -0
  226. package/dist/mui/src/grouping/AggregationChips.d.ts +49 -0
  227. package/dist/mui/src/grouping/AggregationChips.js +80 -0
  228. package/dist/mui/src/grouping/AggregationSettingsButton.d.ts +14 -0
  229. package/dist/mui/src/grouping/AggregationSettingsButton.js +19 -0
  230. package/dist/mui/src/grouping/GroupingBar.d.ts +59 -0
  231. package/dist/mui/src/grouping/GroupingBar.js +267 -0
  232. package/dist/mui/src/grouping/StepExpandButton.d.ts +12 -0
  233. package/dist/mui/src/grouping/StepExpandButton.js +18 -0
  234. package/dist/mui/src/grouping/groupRow.d.ts +68 -0
  235. package/dist/mui/src/grouping/groupRow.js +129 -0
  236. package/dist/mui/src/headers/defaultHeader.d.ts +28 -0
  237. package/dist/mui/src/headers/defaultHeader.js +90 -0
  238. package/dist/mui/src/headers/defineHeader.d.ts +21 -0
  239. package/dist/mui/src/headers/defineHeader.js +68 -0
  240. package/dist/mui/src/headers/index.d.ts +5 -0
  241. package/dist/mui/src/headers/index.js +3 -0
  242. package/dist/mui/src/headers/meta.d.ts +18 -0
  243. package/dist/mui/src/headers/meta.js +11 -0
  244. package/dist/mui/src/headers/types.d.ts +84 -0
  245. package/dist/mui/src/headers/types.js +1 -0
  246. package/dist/mui/src/index.d.ts +110 -0
  247. package/dist/mui/src/index.js +79 -0
  248. package/dist/mui/src/layout/ResizeHandle.d.ts +30 -0
  249. package/dist/mui/src/layout/ResizeHandle.js +66 -0
  250. package/dist/mui/src/menus/columnMenu.d.ts +45 -0
  251. package/dist/mui/src/menus/columnMenu.js +144 -0
  252. package/dist/mui/src/menus/copy.d.ts +5 -0
  253. package/dist/mui/src/menus/copy.js +25 -0
  254. package/dist/mui/src/menus/index.d.ts +6 -0
  255. package/dist/mui/src/menus/index.js +4 -0
  256. package/dist/mui/src/menus/resolve.d.ts +15 -0
  257. package/dist/mui/src/menus/resolve.js +60 -0
  258. package/dist/mui/src/menus/rowMenu.d.ts +46 -0
  259. package/dist/mui/src/menus/rowMenu.js +76 -0
  260. package/dist/mui/src/pagination/PaginationArea.d.ts +16 -0
  261. package/dist/mui/src/pagination/PaginationArea.js +23 -0
  262. package/dist/mui/src/pivot/PivotTable.d.ts +18 -0
  263. package/dist/mui/src/pivot/PivotTable.js +100 -0
  264. package/dist/mui/src/provider/KokoTableProvider.d.ts +184 -0
  265. package/dist/mui/src/provider/KokoTableProvider.js +118 -0
  266. package/dist/mui/src/provider/labels.d.ts +85 -0
  267. package/dist/mui/src/provider/labels.js +104 -0
  268. package/dist/mui/src/registry.d.ts +30 -0
  269. package/dist/mui/src/registry.js +5 -0
  270. package/dist/mui/src/toolbar/GlobalFilterField.d.ts +36 -0
  271. package/dist/mui/src/toolbar/GlobalFilterField.js +78 -0
  272. package/dist/mui/src/virtual/VirtualTableContent.d.ts +41 -0
  273. package/dist/mui/src/virtual/VirtualTableContent.js +58 -0
  274. package/dist/mui/src/virtual/VirtualTableScreen.d.ts +13 -0
  275. package/dist/mui/src/virtual/VirtualTableScreen.js +23 -0
  276. package/dist/mui/src/virtual.d.ts +4 -0
  277. package/dist/mui/src/virtual.js +4 -0
  278. package/dist/mui/src/virtualColumns/VirtualColumnCard.d.ts +26 -0
  279. package/dist/mui/src/virtualColumns/VirtualColumnCard.js +29 -0
  280. package/dist/mui/src/virtualColumns/VirtualColumnDialog.d.ts +27 -0
  281. package/dist/mui/src/virtualColumns/VirtualColumnDialog.js +154 -0
  282. package/dist/mui/src/virtualColumns/VirtualColumnSection.d.ts +31 -0
  283. package/dist/mui/src/virtualColumns/VirtualColumnSection.js +55 -0
  284. package/dist/mui/src/virtualColumns/expression.d.ts +68 -0
  285. package/dist/mui/src/virtualColumns/expression.js +489 -0
  286. package/dist/mui/src/virtualColumns/useVirtualColumns.d.ts +67 -0
  287. package/dist/mui/src/virtualColumns/useVirtualColumns.js +111 -0
  288. package/dist/mui/src/virtualColumns/virtualColumnDefs.d.ts +29 -0
  289. package/dist/mui/src/virtualColumns/virtualColumnDefs.js +51 -0
  290. package/dist/mui-virtual.d.ts +1 -0
  291. package/dist/mui-virtual.js +2 -0
  292. package/dist/mui.d.ts +1 -0
  293. package/dist/mui.js +2 -0
  294. package/dist/query/src/index.d.ts +6 -0
  295. package/dist/query/src/index.js +7 -0
  296. package/dist/query/src/serverPivot.d.ts +42 -0
  297. package/dist/query/src/serverPivot.js +153 -0
  298. package/dist/query/src/useServerGrouping.d.ts +52 -0
  299. package/dist/query/src/useServerGrouping.js +186 -0
  300. package/dist/query/src/useServerTable.d.ts +20 -0
  301. package/dist/query/src/useServerTable.js +106 -0
  302. package/dist/query/src/useServerTableData.d.ts +48 -0
  303. package/dist/query/src/useServerTableData.js +64 -0
  304. package/dist/query/src/wire.d.ts +16 -0
  305. package/dist/query/src/wire.js +32 -0
  306. package/dist/query.d.ts +1 -0
  307. package/dist/query.js +2 -0
  308. package/package.json +125 -0
@@ -0,0 +1,100 @@
1
+ import type { ReactNode } from "react";
2
+ import type { Row, RowData, Table } from "@tanstack/react-table";
3
+ import type { TableColumnDef, TableColumnDefs } from "../../../core/src/index";
4
+ /**
5
+ * 표시 전용 컬럼(display column) — 기존 MRT 의 `mrt-row-select` / `mrt-row-expand` /
6
+ * `mrt-row-actions` / `mrt-row-numbers` 에 대응한다.
7
+ *
8
+ * TanStack 은 컬럼 목록에 없는 열을 그릴 수 없으므로 **`useDataTable` 의 `columns` 에
9
+ * 함께 넘겨야 한다** (`withDisplayColumns` 로 합친다). `useTableSearch` 의 `columns` 에는
10
+ * 넣지 않는다 — 필터·정렬 후보가 아니다(accessor 가 없어 `getCanFilter/getCanSort` 도 false).
11
+ *
12
+ * id 는 모두 `koko-row-` 접두를 가진다. 컬럼 표시 토글·컬럼 메뉴는 이 접두로 걸러낸다.
13
+ */
14
+ export declare const DISPLAY_COLUMN_PREFIX = "koko-row-";
15
+ /** MRT 가 쓰던 접두 — 저장된 프리셋(`columnVisibility`/`columnOrder`)과 호환하려면 `legacyIds` 로 이 id 를 쓴다 */
16
+ export declare const LEGACY_DISPLAY_COLUMN_PREFIX = "mrt-row-";
17
+ export declare const ROW_SELECT_COLUMN_ID = "koko-row-select";
18
+ export declare const ROW_EXPAND_COLUMN_ID = "koko-row-expand";
19
+ export declare const ROW_ACTIONS_COLUMN_ID = "koko-row-actions";
20
+ export declare const ROW_NUMBER_COLUMN_ID = "koko-row-number";
21
+ /** MRT 의 display column id — `withDisplayColumns(cols, { legacyIds: true })` 가 쓴다 */
22
+ export declare const LEGACY_DISPLAY_COLUMN_IDS: {
23
+ readonly select: "mrt-row-select";
24
+ readonly expand: "mrt-row-expand";
25
+ readonly actions: "mrt-row-actions";
26
+ readonly number: "mrt-row-numbers";
27
+ };
28
+ export declare function isDisplayColumnId(id: string): boolean;
29
+ export interface SelectionColumnOptions {
30
+ /** 헤더 전체 선택 체크박스. `enableMultiRowSelection: false` 면 자동으로 숨긴다 */
31
+ selectAll?: boolean;
32
+ size?: number;
33
+ /** 컬럼 id. 기본 `koko-row-select`, 프리셋 호환이 필요하면 `mrt-row-select` */
34
+ id?: string;
35
+ }
36
+ /**
37
+ * 체크박스 컬럼. 다중 선택이 꺼진 테이블(`tableOptions.enableMultiRowSelection: false`)
38
+ * 에서는 라디오로 그리고 헤더 전체 선택을 숨긴다.
39
+ * 선택 가능 여부는 `tableOptions.enableRowSelection` (boolean 또는 `(row) => boolean`) 이 정한다.
40
+ */
41
+ export declare function selectionColumn<T extends RowData>(options?: SelectionColumnOptions): TableColumnDef<T, unknown>;
42
+ export interface ExpandColumnOptions {
43
+ /** 헤더에 전체 펼침/접기 버튼 */
44
+ expandAll?: boolean;
45
+ size?: number;
46
+ /** 컬럼 id. 기본 `koko-row-expand`, 프리셋 호환이 필요하면 `mrt-row-expand` */
47
+ id?: string;
48
+ }
49
+ /** 이 행이 펼쳐질 수 있는가 — `tableOptions.getRowCanExpand` 가 있으면 그 판단을 따른다 */
50
+ export declare function canExpandRow<T extends RowData>(row: Row<T>, table: Table<T>): boolean;
51
+ /**
52
+ * 확장 토글 컬럼. `TableContent.renderDetailPanel` 과 짝이다.
53
+ *
54
+ * TanStack 의 `expanded` 상태는 `getExpandedRowModel` 을 등록하지 않아도
55
+ * `row.toggleExpanded()` / `row.getIsExpanded()` 로 관리된다 — row model 은 하위 행
56
+ * (subRows) 을 평탄화할 때만 필요하고 detail panel 은 하위 행이 아니다.
57
+ */
58
+ export declare function expandColumn<T extends RowData>(options?: ExpandColumnOptions): TableColumnDef<T, unknown>;
59
+ export interface RowActionsColumnOptions<T extends RowData> {
60
+ /** 기존 `renderRowActions({ row, table })` 대응 — 인자 `table` 은 TanStack 인스턴스다 */
61
+ render: (row: Row<T>, table: Table<T>) => ReactNode;
62
+ /** `withDisplayColumns` 가 배치할 위치. 기존 `positionActionsColumn` */
63
+ position?: "first" | "last";
64
+ header?: ReactNode;
65
+ size?: number;
66
+ /** 컬럼 id. 기본 `koko-row-actions`, 프리셋 호환이 필요하면 `mrt-row-actions` */
67
+ id?: string;
68
+ }
69
+ export declare function rowActionsColumn<T extends RowData>(options: RowActionsColumnOptions<T>): TableColumnDef<T, unknown>;
70
+ export interface RowNumberColumnOptions {
71
+ header?: ReactNode;
72
+ size?: number;
73
+ /** 컬럼 id. 기본 `koko-row-number`, 프리셋 호환이 필요하면 `mrt-row-numbers` */
74
+ id?: string;
75
+ }
76
+ /**
77
+ * 행 번호 — 페이지 오프셋을 반영한다(`pagination.pageIndex * pageSize + row.index + 1`).
78
+ * `useDataTable` 은 페이지가 잘린 행만 TanStack 에 넣으므로 `row.index` 는 페이지 내 순번이다.
79
+ */
80
+ export declare function rowNumberColumn<T extends RowData>(options?: RowNumberColumnOptions): TableColumnDef<T, unknown>;
81
+ export interface WithDisplayColumnsOptions<T extends RowData> {
82
+ /** 기존 `enableRowNumbers` */
83
+ rowNumber?: boolean | RowNumberColumnOptions;
84
+ /** 기존 `enableRowSelection` (선택 가능 여부 자체는 `tableOptions.enableRowSelection`) */
85
+ selection?: boolean | SelectionColumnOptions;
86
+ /** 기존 `enableExpanding` + `renderDetailPanel` */
87
+ expand?: boolean | ExpandColumnOptions;
88
+ /** 기존 `enableRowActions` + `renderRowActions` + `positionActionsColumn` */
89
+ rowActions?: RowActionsColumnOptions<T>;
90
+ /**
91
+ * id 를 MRT 것(`mrt-row-select`/`mrt-row-expand`/`mrt-row-actions`/`mrt-row-numbers`)으로 쓴다 —
92
+ * 저장된 프리셋의 `columnVisibility`/`columnOrder` 키가 그대로 맞는다. 개별 옵션의 `id` 가 우선한다.
93
+ */
94
+ legacyIds?: boolean;
95
+ }
96
+ /**
97
+ * 데이터 컬럼 앞뒤에 표시 전용 컬럼을 끼운다. 순서는 MRT 와 같다:
98
+ * `actions(first)` → `expand` → `select` → `number` → 데이터 컬럼 → `actions(last)`.
99
+ */
100
+ export declare function withDisplayColumns<T extends RowData>(columns: TableColumnDefs<T>, options: WithDisplayColumnsOptions<T>): TableColumnDefs<T>;
@@ -0,0 +1,174 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Checkbox, IconButton, Radio, Tooltip } from "@mui/material";
3
+ import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
4
+ import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight";
5
+ import UnfoldLessIcon from "@mui/icons-material/UnfoldLess";
6
+ import UnfoldMoreIcon from "@mui/icons-material/UnfoldMore";
7
+ import { useKokoTableConfig } from "../provider/KokoTableProvider";
8
+ /** 헤더 전체 선택 — 라벨은 Provider 에서 (`labels.ui.selectAll`) */
9
+ function SelectAllCheckbox({ table }) {
10
+ const { labels } = useKokoTableConfig();
11
+ return (_jsx(Checkbox, { size: "small", inputProps: { "aria-label": labels.ui.selectAll }, checked: table.getIsAllRowsSelected(), indeterminate: !table.getIsAllRowsSelected() && table.getIsSomeRowsSelected(), onChange: table.getToggleAllRowsSelectedHandler(), sx: { p: 0.25 } }));
12
+ }
13
+ /**
14
+ * 표시 전용 컬럼(display column) — 기존 MRT 의 `mrt-row-select` / `mrt-row-expand` /
15
+ * `mrt-row-actions` / `mrt-row-numbers` 에 대응한다.
16
+ *
17
+ * TanStack 은 컬럼 목록에 없는 열을 그릴 수 없으므로 **`useDataTable` 의 `columns` 에
18
+ * 함께 넘겨야 한다** (`withDisplayColumns` 로 합친다). `useTableSearch` 의 `columns` 에는
19
+ * 넣지 않는다 — 필터·정렬 후보가 아니다(accessor 가 없어 `getCanFilter/getCanSort` 도 false).
20
+ *
21
+ * id 는 모두 `koko-row-` 접두를 가진다. 컬럼 표시 토글·컬럼 메뉴는 이 접두로 걸러낸다.
22
+ */
23
+ export const DISPLAY_COLUMN_PREFIX = "koko-row-";
24
+ /** MRT 가 쓰던 접두 — 저장된 프리셋(`columnVisibility`/`columnOrder`)과 호환하려면 `legacyIds` 로 이 id 를 쓴다 */
25
+ export const LEGACY_DISPLAY_COLUMN_PREFIX = "mrt-row-";
26
+ export const ROW_SELECT_COLUMN_ID = `${DISPLAY_COLUMN_PREFIX}select`;
27
+ export const ROW_EXPAND_COLUMN_ID = `${DISPLAY_COLUMN_PREFIX}expand`;
28
+ export const ROW_ACTIONS_COLUMN_ID = `${DISPLAY_COLUMN_PREFIX}actions`;
29
+ export const ROW_NUMBER_COLUMN_ID = `${DISPLAY_COLUMN_PREFIX}number`;
30
+ /** MRT 의 display column id — `withDisplayColumns(cols, { legacyIds: true })` 가 쓴다 */
31
+ export const LEGACY_DISPLAY_COLUMN_IDS = {
32
+ select: "mrt-row-select",
33
+ expand: "mrt-row-expand",
34
+ actions: "mrt-row-actions",
35
+ number: "mrt-row-numbers",
36
+ };
37
+ export function isDisplayColumnId(id) {
38
+ return id.startsWith(DISPLAY_COLUMN_PREFIX) || id.startsWith(LEGACY_DISPLAY_COLUMN_PREFIX);
39
+ }
40
+ /** 표시 전용 컬럼 공통 — 정렬·필터·숨김·리사이즈 대상이 아니다 */
41
+ function displayBase(id, size, extra = {}) {
42
+ return {
43
+ id,
44
+ header: "",
45
+ size,
46
+ minSize: size,
47
+ maxSize: size,
48
+ enableSorting: false,
49
+ enableColumnFilter: false,
50
+ enableGlobalFilter: false,
51
+ enableHiding: false,
52
+ enableResizing: false,
53
+ enableGrouping: false,
54
+ ...extra,
55
+ };
56
+ }
57
+ /**
58
+ * 체크박스 컬럼. 다중 선택이 꺼진 테이블(`tableOptions.enableMultiRowSelection: false`)
59
+ * 에서는 라디오로 그리고 헤더 전체 선택을 숨긴다.
60
+ * 선택 가능 여부는 `tableOptions.enableRowSelection` (boolean 또는 `(row) => boolean`) 이 정한다.
61
+ */
62
+ export function selectionColumn(options = {}) {
63
+ const { selectAll = true, size = 48, id = ROW_SELECT_COLUMN_ID } = options;
64
+ return displayBase(id, size, {
65
+ header: ({ table }) => {
66
+ if (!selectAll || table.options.enableMultiRowSelection === false)
67
+ return null;
68
+ return _jsx(SelectAllCheckbox, { table: table });
69
+ },
70
+ cell: ({ row, table }) => {
71
+ const multi = table.options.enableMultiRowSelection !== false;
72
+ const common = {
73
+ size: "small",
74
+ checked: row.getIsSelected(),
75
+ disabled: !row.getCanSelect(),
76
+ onChange: row.getToggleSelectedHandler(),
77
+ // 행 클릭 선택(`selectOnRowClick`)과 겹치면 두 번 토글된다
78
+ onClick: (event) => event.stopPropagation(),
79
+ inputProps: { "aria-label": "행 선택" },
80
+ sx: { p: 0.25 },
81
+ };
82
+ return multi ? _jsx(Checkbox, { ...common }) : _jsx(Radio, { ...common });
83
+ },
84
+ });
85
+ }
86
+ /** 이 행이 펼쳐질 수 있는가 — `tableOptions.getRowCanExpand` 가 있으면 그 판단을 따른다 */
87
+ export function canExpandRow(row, table) {
88
+ if (table.options.enableExpanding === false)
89
+ return false;
90
+ return table.options.getRowCanExpand ? row.getCanExpand() : true;
91
+ }
92
+ /**
93
+ * 확장 토글 컬럼. `TableContent.renderDetailPanel` 과 짝이다.
94
+ *
95
+ * TanStack 의 `expanded` 상태는 `getExpandedRowModel` 을 등록하지 않아도
96
+ * `row.toggleExpanded()` / `row.getIsExpanded()` 로 관리된다 — row model 은 하위 행
97
+ * (subRows) 을 평탄화할 때만 필요하고 detail panel 은 하위 행이 아니다.
98
+ */
99
+ export function expandColumn(options = {}) {
100
+ const { expandAll = true, size = 48, id = ROW_EXPAND_COLUMN_ID } = options;
101
+ return displayBase(id, size, {
102
+ header: ({ table }) => {
103
+ if (!expandAll)
104
+ return null;
105
+ const all = table.getIsAllRowsExpanded();
106
+ return (_jsx(Tooltip, { title: all ? "모두 접기" : "모두 펼치기", children: _jsx(IconButton, { size: "small", "aria-label": all ? "모두 접기" : "모두 펼치기", onClick: () => table.toggleAllRowsExpanded(!all), children: all ? _jsx(UnfoldLessIcon, { fontSize: "small" }) : _jsx(UnfoldMoreIcon, { fontSize: "small" }) }) }));
107
+ },
108
+ cell: ({ row, table }) => {
109
+ if (!canExpandRow(row, table))
110
+ return null;
111
+ const expanded = row.getIsExpanded();
112
+ return (_jsx(IconButton, { size: "small", "aria-label": expanded ? "접기" : "펼치기", "aria-expanded": expanded, onClick: (event) => {
113
+ event.stopPropagation();
114
+ row.toggleExpanded();
115
+ }, children: expanded ? _jsx(KeyboardArrowDownIcon, { fontSize: "small" }) : _jsx(KeyboardArrowRightIcon, { fontSize: "small" }) }));
116
+ },
117
+ });
118
+ }
119
+ export function rowActionsColumn(options) {
120
+ const { render, header = "", size = 96, id = ROW_ACTIONS_COLUMN_ID } = options;
121
+ const column = displayBase(id, size, {
122
+ header: () => header,
123
+ cell: ({ row, table }) => (
124
+ // 액션 버튼 클릭이 행 클릭(선택·상세)으로 번지지 않게 한다
125
+ _jsx("span", { onClick: (event) => event.stopPropagation(), style: { display: "inline-flex", alignItems: "center" }, children: render(row, table) })),
126
+ });
127
+ column.meta = {
128
+ ...(column.meta ?? {}),
129
+ // 렌더러가 읽지 않는 로컬 표식 — `withDisplayColumns` 가 위치를 정할 때 쓴다
130
+ rowActionsPosition: options.position ?? "last",
131
+ };
132
+ return column;
133
+ }
134
+ /**
135
+ * 행 번호 — 페이지 오프셋을 반영한다(`pagination.pageIndex * pageSize + row.index + 1`).
136
+ * `useDataTable` 은 페이지가 잘린 행만 TanStack 에 넣으므로 `row.index` 는 페이지 내 순번이다.
137
+ */
138
+ export function rowNumberColumn(options = {}) {
139
+ const { header = "#", size = 56, id = ROW_NUMBER_COLUMN_ID } = options;
140
+ return displayBase(id, size, {
141
+ header: () => header,
142
+ cell: ({ row, table }) => {
143
+ const pagination = table.getState().pagination;
144
+ const offset = pagination && pagination.pageSize > 0 && table.options.manualPagination !== false
145
+ ? pagination.pageIndex * pagination.pageSize
146
+ : 0;
147
+ return (_jsx("span", { style: { color: "var(--mui-palette-text-secondary, #6b7280)", fontVariantNumeric: "tabular-nums" }, children: (offset + row.index + 1).toLocaleString("ko-KR") }));
148
+ },
149
+ });
150
+ }
151
+ /**
152
+ * 데이터 컬럼 앞뒤에 표시 전용 컬럼을 끼운다. 순서는 MRT 와 같다:
153
+ * `actions(first)` → `expand` → `select` → `number` → 데이터 컬럼 → `actions(last)`.
154
+ */
155
+ export function withDisplayColumns(columns, options) {
156
+ const leading = [];
157
+ const trailing = [];
158
+ const legacy = options.legacyIds ? LEGACY_DISPLAY_COLUMN_IDS : undefined;
159
+ const opts = (given, fallbackId) => {
160
+ const base = (typeof given === "object" ? given : {});
161
+ return fallbackId && !base.id ? { ...base, id: fallbackId } : base;
162
+ };
163
+ if (options.rowActions) {
164
+ const actions = rowActionsColumn(opts(options.rowActions, legacy?.actions));
165
+ (options.rowActions.position === "first" ? leading : trailing).push(actions);
166
+ }
167
+ if (options.expand)
168
+ leading.push(expandColumn(opts(options.expand, legacy?.expand)));
169
+ if (options.selection)
170
+ leading.push(selectionColumn(opts(options.selection, legacy?.select)));
171
+ if (options.rowNumber)
172
+ leading.push(rowNumberColumn(opts(options.rowNumber, legacy?.number)));
173
+ return [...leading, ...columns, ...trailing];
174
+ }
@@ -0,0 +1,24 @@
1
+ import type { ReactNode } from "react";
2
+ import type { RowData } from "@tanstack/react-table";
3
+ import type { AnyContentSource } from "../../../core/src/index";
4
+ export interface CardContentProps<T extends RowData> {
5
+ source: AnyContentSource<T>;
6
+ /** 카드 하나를 그리는 함수 */
7
+ renderCard: (row: T, index: number) => ReactNode;
8
+ /** 반응형 열 수 (12분할) */
9
+ columns?: {
10
+ xs?: number;
11
+ sm?: number;
12
+ md?: number;
13
+ lg?: number;
14
+ };
15
+ emptyMessage?: ReactNode;
16
+ }
17
+ /**
18
+ * 콘텐츠 구역 — 카드 그리드.
19
+ *
20
+ * **테이블 인스턴스를 요구하지 않는다.** `ContentSource` 만 있으면 되므로
21
+ * `contentSource(data)` 를 넘겨 테이블 없이 화면을 구성할 수 있다.
22
+ * 같은 필터·페이지네이션 컴포넌트를 그대로 옆에 붙일 수 있는 게 요점이다.
23
+ */
24
+ export declare function CardContent<T extends RowData>({ source, renderCard, columns, emptyMessage, }: CardContentProps<T>): import("react").JSX.Element;
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Alert, Box, Button, Card, CardContent as MuiCardContent, Grid, LinearProgress, Typography } from "@mui/material";
3
+ import { toContentSource } from "../../../core/src/index";
4
+ /**
5
+ * 콘텐츠 구역 — 카드 그리드.
6
+ *
7
+ * **테이블 인스턴스를 요구하지 않는다.** `ContentSource` 만 있으면 되므로
8
+ * `contentSource(data)` 를 넘겨 테이블 없이 화면을 구성할 수 있다.
9
+ * 같은 필터·페이지네이션 컴포넌트를 그대로 옆에 붙일 수 있는 게 요점이다.
10
+ */
11
+ export function CardContent({ source, renderCard, columns = { xs: 12, sm: 6, md: 4, lg: 3 }, emptyMessage = "표시할 데이터가 없습니다", }) {
12
+ const content = toContentSource(source);
13
+ const status = content.getStatus();
14
+ const rows = content.getRows();
15
+ if (status.isError) {
16
+ return (_jsx(Alert, { severity: "error", action: _jsx(Button, { color: "inherit", size: "small", onClick: () => content.refetch(), children: "\uB2E4\uC2DC \uC2DC\uB3C4" }), children: status.error?.message ?? "조회에 실패했습니다" }));
17
+ }
18
+ if (status.isInitialLoading) {
19
+ return (_jsx(Box, { sx: { py: 6, textAlign: "center", color: "text.secondary" }, children: "\uBD88\uB7EC\uC624\uB294 \uC911\u2026" }));
20
+ }
21
+ if (status.isEmpty) {
22
+ return (_jsx(Box, { sx: { py: 6, textAlign: "center", color: "text.secondary" }, children: _jsx(Typography, { variant: "body2", children: emptyMessage }) }));
23
+ }
24
+ return (_jsxs(Box, { sx: { position: "relative" }, children: [status.isLoading && _jsx(LinearProgress, { sx: { position: "absolute", top: -4, left: 0, right: 0 } }), _jsx(Grid, { container: true, spacing: 2, children: rows.map((row, index) => (_jsx(Grid, { size: columns, children: _jsx(Card, { variant: "outlined", sx: { height: "100%" }, children: _jsx(MuiCardContent, { children: renderCard(row, index) }) }) }, index))) })] }));
25
+ }
@@ -0,0 +1,43 @@
1
+ import type { AggregationSpec } from "../../../core/src/index";
2
+ import { type PopoverPosition } from "@mui/material";
3
+ import type { Column, Header, RowData, Table } from "@tanstack/react-table";
4
+ import type { SortSource } from "../../../core/src/index";
5
+ import { type ColumnMenuItemsFn } from "./menuItems";
6
+ export { moveColumn, canMoveColumn } from "./columnOrder";
7
+ export type ColumnMenuAnchor = HTMLElement | PopoverPosition;
8
+ export interface ColumnMenuProps<T extends RowData> {
9
+ table: Table<T>;
10
+ column: Column<T, unknown>;
11
+ /** 헤더 인스턴스 — 없으면 테이블에서 찾는다 */
12
+ header?: Header<T, unknown>;
13
+ sort?: SortSource;
14
+ /** 현재 그룹 기준. 미지정 시 `table.getState().grouping` */
15
+ grouping?: string[];
16
+ /** 있으면 "그룹 기준 추가/제거" 항목이 생긴다 */
17
+ onGroupingChange?: (grouping: string[]) => void;
18
+ aggregation?: AggregationSpec;
19
+ onAggregationChange?: (next: AggregationSpec) => void;
20
+ /** 있으면 "필터 열기" 항목이 생긴다. 미지정 시 Provider `onOpenFilter` */
21
+ onOpenFilter?: (column: Column<T, unknown>, table: Table<T>) => void;
22
+ /** 항목 추가·제거·재배열 — 레지스트리를 해석한 기본 항목을 `ctx.defaultItems` 로 받는다 */
23
+ items?: ColumnMenuItemsFn<T>;
24
+ /**
25
+ * 외부 앵커 — 요소(버튼)면 그 아래, 좌표면 그 자리에 연다 (`HeaderCell` 의 메뉴 트리거 슬롯·우클릭).
26
+ * 있으면 내부 버튼 상태보다 우선한다.
27
+ */
28
+ anchor?: ColumnMenuAnchor | null;
29
+ /** 외부 앵커로 연 메뉴를 닫을 때 */
30
+ onAnchorClose?: () => void;
31
+ /** @deprecated `anchor` 로 통합 — 우클릭 좌표 */
32
+ anchorPosition?: PopoverPosition | null;
33
+ /** @deprecated `onAnchorClose` */
34
+ onAnchorPositionClose?: () => void;
35
+ /** 메뉴 버튼을 그리지 않는다 — 트리거를 밖에서 그릴 때 (`HeaderCell` 슬롯) */
36
+ hideButton?: boolean;
37
+ }
38
+ /**
39
+ * 헤더 컬럼 메뉴 — 정렬 / 고정 / 이동 / 숨기기 / 그룹 기준 / 필터 열기 / 너비 초기화 / 헤더 복사.
40
+ * 항목은 Provider `menus.column` 레지스트리에서 오고(`when` 으로 조건부), `items` prop 이 마지막으로 손본다.
41
+ * 드래그 순서 변경은 두지 않는다(버튼 이동으로 충분하고 터치·접근성이 낫다).
42
+ */
43
+ export declare function ColumnMenu<T extends RowData>({ table, column, header, sort, grouping, onGroupingChange, aggregation, onAggregationChange, onOpenFilter, items, anchor, onAnchorClose, anchorPosition, onAnchorPositionClose, hideButton, }: ColumnMenuProps<T>): import("react").JSX.Element;
@@ -0,0 +1,40 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { IconButton, Menu } from "@mui/material";
4
+ import MoreVertIcon from "@mui/icons-material/MoreVert";
5
+ import { useKokoTableConfig } from "../provider/KokoTableProvider";
6
+ import { MenuItemList, defaultColumnMenuItems, } from "./menuItems";
7
+ export { moveColumn, canMoveColumn } from "./columnOrder";
8
+ function isElement(anchor) {
9
+ return typeof anchor.getBoundingClientRect === "function";
10
+ }
11
+ /**
12
+ * 헤더 컬럼 메뉴 — 정렬 / 고정 / 이동 / 숨기기 / 그룹 기준 / 필터 열기 / 너비 초기화 / 헤더 복사.
13
+ * 항목은 Provider `menus.column` 레지스트리에서 오고(`when` 으로 조건부), `items` prop 이 마지막으로 손본다.
14
+ * 드래그 순서 변경은 두지 않는다(버튼 이동으로 충분하고 터치·접근성이 낫다).
15
+ */
16
+ export function ColumnMenu({ table, column, header, sort, grouping, onGroupingChange, aggregation, onAggregationChange, onOpenFilter, items, anchor, onAnchorClose, anchorPosition, onAnchorPositionClose, hideButton = false, }) {
17
+ const { labels, menus, headers, onOpenFilter: providerOpenFilter } = useKokoTableConfig();
18
+ const [anchorEl, setAnchorEl] = useState(null);
19
+ const external = anchor ?? anchorPosition ?? null;
20
+ const close = () => {
21
+ setAnchorEl(null);
22
+ if (external)
23
+ (onAnchorClose ?? onAnchorPositionClose)?.();
24
+ };
25
+ const openFilter = (onOpenFilter ?? providerOpenFilter);
26
+ const ctx = {
27
+ column, table, sort, header,
28
+ grouping: grouping ?? table.getState().grouping ?? [],
29
+ onGroupingChange,
30
+ aggregation, onAggregationChange,
31
+ openFilter: openFilter ? () => openFilter(column, table) : undefined,
32
+ };
33
+ // 상태(정렬·고정·순서)가 바뀔 때마다 disabled 가 다시 계산되도록 메뉴가 열려 있는 동안 매 렌더 새로 만든다
34
+ const defaultItems = defaultColumnMenuItems(ctx, labels, menus.column, headers);
35
+ const resolved = items ? items({ ...ctx, defaultItems }) : defaultItems;
36
+ const open = !!anchorEl || !!external;
37
+ const externalEl = external && isElement(external) ? external : null;
38
+ const externalPos = external && !isElement(external) ? external : null;
39
+ return (_jsxs(_Fragment, { children: [!hideButton && (_jsx(IconButton, { size: "small", "aria-label": `${column.id} ${labels.ui.columnMenu}`, "aria-haspopup": "menu", className: "koko-column-menu-button", onClick: (event) => { event.stopPropagation(); setAnchorEl(event.currentTarget); }, sx: { p: 0.25, ml: 0.25, opacity: anchorEl ? 1 : 0.35, "&:hover": { opacity: 1 } }, children: _jsx(MoreVertIcon, { sx: { fontSize: 16 } }) })), _jsx(Menu, { open: open, onClose: close, anchorEl: externalPos ? undefined : (externalEl ?? anchorEl), anchorReference: externalPos ? "anchorPosition" : "anchorEl", anchorPosition: externalPos ?? undefined, onContextMenu: (event) => { event.preventDefault(); event.stopPropagation(); }, children: _jsx(MenuItemList, { items: resolved, ctx: ctx, onPick: close }) })] }));
40
+ }
@@ -0,0 +1,14 @@
1
+ import { type ReactNode } from "react";
2
+ import { type RowData, type Table } from "@tanstack/react-table";
3
+ export interface ColumnVisibilityMenuProps<T extends RowData> {
4
+ table: Table<T>;
5
+ /** 버튼 라벨. 아이콘만 쓰려면 "" */
6
+ label?: ReactNode;
7
+ size?: "small" | "medium";
8
+ }
9
+ /**
10
+ * 컬럼 표시 토글 — 기존 MRT `ShowHideColumnsMenu` 대응.
11
+ * `forceHidden`(값 보관 전용) 과 표시 전용 컬럼은 목록에서 뺀다.
12
+ * 표시 상태는 `useDataTable` 이 제어형으로 들고 있어 토글이 다음 렌더에 되돌아가지 않는다.
13
+ */
14
+ export declare function ColumnVisibilityMenu<T extends RowData>({ table, label, size, }: ColumnVisibilityMenuProps<T>): import("react").JSX.Element;
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Button, Checkbox, Divider, ListItemIcon, ListItemText, Menu, MenuItem, Tooltip, } from "@mui/material";
4
+ import ViewColumnIcon from "@mui/icons-material/ViewColumn";
5
+ import { flexRender } from "@tanstack/react-table";
6
+ import { columnMetaOf } from "../../../core/src/index";
7
+ import { isDisplayColumnId } from "../columns/displayColumns";
8
+ function headerLabel(table, column) {
9
+ const header = column.columnDef.header;
10
+ if (typeof header === "string")
11
+ return header;
12
+ if (header === undefined)
13
+ return column.id;
14
+ // 함수 헤더는 헤더 컨텍스트가 필요하다 — 숨겨진 컬럼은 헤더가 없으므로 id 로 대신한다
15
+ const found = table.getFlatHeaders().find((h) => h.column.id === column.id);
16
+ return found ? flexRender(header, found.getContext()) : column.id;
17
+ }
18
+ /**
19
+ * 컬럼 표시 토글 — 기존 MRT `ShowHideColumnsMenu` 대응.
20
+ * `forceHidden`(값 보관 전용) 과 표시 전용 컬럼은 목록에서 뺀다.
21
+ * 표시 상태는 `useDataTable` 이 제어형으로 들고 있어 토글이 다음 렌더에 되돌아가지 않는다.
22
+ */
23
+ export function ColumnVisibilityMenu({ table, label = "컬럼", size = "small", }) {
24
+ const [anchorEl, setAnchorEl] = useState(null);
25
+ const columns = table.getAllLeafColumns().filter((column) => column.getCanHide() && !isDisplayColumnId(column.id) && !columnMetaOf(column.columnDef)?.forceHidden);
26
+ const visibleCount = columns.filter((column) => column.getIsVisible()).length;
27
+ const allVisible = visibleCount === columns.length;
28
+ const setAll = (visible) => {
29
+ table.setColumnVisibility((prev) => {
30
+ const next = { ...prev };
31
+ for (const column of columns)
32
+ next[column.id] = visible;
33
+ return next;
34
+ });
35
+ };
36
+ return (_jsxs(_Fragment, { children: [_jsx(Tooltip, { title: "\uCEEC\uB7FC \uD45C\uC2DC/\uC228\uAE40", children: _jsx(Button, { size: size, color: "inherit", startIcon: _jsx(ViewColumnIcon, {}), "aria-label": "\uCEEC\uB7FC \uD45C\uC2DC/\uC228\uAE40", onClick: (event) => setAnchorEl(event.currentTarget), children: label }) }), _jsxs(Menu, { anchorEl: anchorEl, open: !!anchorEl, onClose: () => setAnchorEl(null), children: [_jsx(MenuItem, { dense: true, onClick: () => setAll(true), disabled: allVisible, children: _jsx(ListItemText, { primary: "\uC804\uCCB4 \uD45C\uC2DC" }) }), _jsx(MenuItem, { dense: true, onClick: () => setAll(false), disabled: visibleCount === 0, children: _jsx(ListItemText, { primary: "\uC804\uCCB4 \uC228\uAE40" }) }), _jsx(Divider, {}), columns.map((column) => (_jsxs(MenuItem, { dense: true, onClick: () => column.toggleVisibility(), children: [_jsx(ListItemIcon, { children: _jsx(Checkbox, { size: "small", edge: "start", checked: column.getIsVisible(), tabIndex: -1, disableRipple: true, inputProps: { "aria-label": `${column.id} 표시` }, sx: { p: 0 } }) }), _jsx(ListItemText, { primary: headerLabel(table, column) })] }, column.id)))] })] }));
37
+ }
@@ -0,0 +1,19 @@
1
+ import type { RowData } from "@tanstack/react-table";
2
+ import type { ColumnMeta } from "../../../core/src/index";
3
+ export type EditSpecMeta = NonNullable<ColumnMeta["edit"]>;
4
+ export interface EditCellProps<T extends RowData> {
5
+ spec: EditSpecMeta;
6
+ value: unknown;
7
+ row: T;
8
+ /** 값 확정 — Enter/blur(텍스트·숫자) 또는 선택 즉시(select) */
9
+ onCommit: (value: unknown) => void;
10
+ /** Escape */
11
+ onCancel?: () => void;
12
+ autoFocus?: boolean;
13
+ }
14
+ /**
15
+ * 인라인 편집 입력 — `meta.edit`(EditSpec) 을 읽어 그린다.
16
+ * text/number 는 TextField, select 는 variant 에 따라 dropdown/chip/button.
17
+ * 기존 `renderEditCell.tsx` + `EditSelectComponents.tsx` 를 합친 것이다.
18
+ */
19
+ export declare function EditCell<T extends RowData>({ spec, value, row, onCommit, onCancel, autoFocus, }: EditCellProps<T>): import("react").JSX.Element;
@@ -0,0 +1,61 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { Box, Chip, MenuItem, TextField, ToggleButton, ToggleButtonGroup } from "@mui/material";
4
+ function resolveOptions(spec, row) {
5
+ const options = spec.options;
6
+ if (!options)
7
+ return [];
8
+ return typeof options === "function" ? options(row) : options;
9
+ }
10
+ /**
11
+ * 인라인 편집 입력 — `meta.edit`(EditSpec) 을 읽어 그린다.
12
+ * text/number 는 TextField, select 는 variant 에 따라 dropdown/chip/button.
13
+ * 기존 `renderEditCell.tsx` + `EditSelectComponents.tsx` 를 합친 것이다.
14
+ */
15
+ export function EditCell({ spec, value, row, onCommit, onCancel, autoFocus = true, }) {
16
+ const size = spec.size ?? "small";
17
+ const color = spec.color ?? "primary";
18
+ const initial = value === null || value === undefined ? "" : String(value);
19
+ const [local, setLocal] = useState(initial);
20
+ useEffect(() => { setLocal(initial); }, [initial]);
21
+ if (spec.kind === "select") {
22
+ const options = resolveOptions(spec, row);
23
+ const select = (next) => {
24
+ setLocal(next);
25
+ onCommit(next);
26
+ };
27
+ if (spec.variant === "chip") {
28
+ return (_jsx(Box, { sx: { display: "flex", gap: 0.5, flexWrap: "wrap" }, children: options.map((option) => (_jsx(Chip, { label: option.label, size: size, color: color, variant: local === option.value ? "filled" : "outlined", onClick: () => select(option.value), sx: { cursor: "pointer" } }, option.value))) }));
29
+ }
30
+ if (spec.variant === "button") {
31
+ return (_jsx(ToggleButtonGroup, { exclusive: true, size: size, color: color, value: local, onChange: (_, next) => { if (next !== null)
32
+ select(next); }, sx: { flexWrap: "wrap" }, children: options.map((option) => (_jsx(ToggleButton, { value: option.value, sx: { py: 0.25, px: 1, fontSize: "0.75rem" }, children: option.label }, option.value))) }));
33
+ }
34
+ return (_jsx(TextField, { select: true, size: "small", fullWidth: true, autoFocus: autoFocus, value: local, onChange: (event) => select(event.target.value), onKeyDown: (event) => { if (event.key === "Escape")
35
+ onCancel?.(); }, slotProps: { htmlInput: { "aria-label": "값 선택", ...spec.inputProps } }, children: options.map((option) => (_jsx(MenuItem, { value: option.value, children: option.label }, option.value))) }));
36
+ }
37
+ const isNumber = spec.kind === "number";
38
+ const commit = () => {
39
+ if (isNumber) {
40
+ if (local.trim() === "")
41
+ return onCommit(null);
42
+ const parsed = Number(local);
43
+ return onCommit(Number.isNaN(parsed) ? value : parsed);
44
+ }
45
+ onCommit(local);
46
+ };
47
+ const onKeyDown = (event) => {
48
+ // 헤더 정렬 등 상위 단축키로 번지지 않게 한다
49
+ event.stopPropagation();
50
+ if (event.key === "Enter") {
51
+ event.preventDefault();
52
+ commit();
53
+ }
54
+ else if (event.key === "Escape") {
55
+ event.preventDefault();
56
+ setLocal(initial);
57
+ onCancel?.();
58
+ }
59
+ };
60
+ return (_jsx(TextField, { size: "small", variant: "standard", fullWidth: true, autoFocus: autoFocus, type: isNumber ? "number" : "text", value: local, onChange: (event) => setLocal(event.target.value), onBlur: commit, onKeyDown: onKeyDown, slotProps: { htmlInput: { "aria-label": "값 입력", ...spec.inputProps } } }));
61
+ }
@@ -0,0 +1,59 @@
1
+ import type { AggregationSpec } from "../../../core/src/index";
2
+ import { type ReactNode } from "react";
3
+ import { type TableCellProps } from "@mui/material";
4
+ import { type Column, type Header, type RowData, type Table } from "@tanstack/react-table";
5
+ import type { SortSource } from "../../../core/src/index";
6
+ import { type ColumnMenuItemsFn } from "./menuItems";
7
+ import type { HeaderDef } from "../headers/types";
8
+ export { headerRuleMetaOf, resolveCellAlign } from "../headers/meta";
9
+ export type { HeaderRuleMeta, CellAlign } from "../headers/meta";
10
+ export interface RenderHeaderContext<T extends RowData> {
11
+ header: Header<T, unknown>;
12
+ table?: Table<T>;
13
+ /** 기본 규칙으로 만든 헤더 내용 (`columnDef.header` 렌더 결과) */
14
+ defaultContent: ReactNode;
15
+ }
16
+ export interface HeaderCellProps<T extends RowData> {
17
+ header: Header<T, unknown>;
18
+ sort?: SortSource;
19
+ /** 컬럼 메뉴(고정·이동·숨기기)를 붙이려면 테이블 인스턴스가 필요하다. 없으면 `header.getContext().table` */
20
+ table?: Table<T>;
21
+ /** 컬럼 메뉴 표시. 기본 true. 우클릭 메뉴도 같이 꺼진다 */
22
+ enableColumnMenu?: boolean;
23
+ size?: "small" | "medium";
24
+ /**
25
+ * 헤더를 끌어 `GroupingBar` 에 놓으면 그룹 기준이 되게 한다 — `draggable` 을 켜고
26
+ * `dataTransfer` 에 `text/koko-column` = 컬럼 id 를 싣는다.
27
+ * 기본값은 `table.options.enableGrouping === true` (표시 전용 컬럼·`rules.canGroup` 거짓은 제외).
28
+ */
29
+ draggableGroup?: boolean;
30
+ /** 컬럼 메뉴 항목 추가·제거·재배열 (레지스트리 결과가 `defaultItems`) */
31
+ columnMenuItems?: ColumnMenuItemsFn<T>;
32
+ /** 현재 그룹 기준 (메뉴의 "그룹 기준 추가/제거" 판단용) */
33
+ grouping?: string[];
34
+ /** 있으면 메뉴에 "그룹 기준 추가/제거" 항목이 생긴다 */
35
+ onGroupingChange?: (grouping: string[]) => void;
36
+ /** 그룹핑 중 집계 함수 토글 (메뉴 "집계" 항목) */
37
+ aggregation?: AggregationSpec;
38
+ onAggregationChange?: (next: AggregationSpec) => void;
39
+ /** 있으면 메뉴에 "필터 열기" 항목이 생긴다 (미지정 시 Provider `onOpenFilter`) */
40
+ onOpenFilter?: (column: Column<T, unknown>, table: Table<T>) => void;
41
+ /** `TableCell` 에 얹을 props — sx 는 기본 위에 병합된다 */
42
+ headerCellProps?: (header: Header<T, unknown>, table: Table<T> | undefined) => TableCellProps | undefined;
43
+ /** 헤더 내용 규칙 덮어쓰기 — 단위·필수 표시·툴팁 등. `defaultContent` 를 감싸거나 대체한다 (content 슬롯 앞 단계) */
44
+ renderHeader?: (ctx: RenderHeaderContext<T>) => ReactNode;
45
+ /** 이 셀에만 쓸 헤더 정의 — `meta.header` 와 Provider `headers[]` 보다 우선 */
46
+ headerDef?: HeaderDef<T>;
47
+ }
48
+ /**
49
+ * 헤더 셀 — 바깥 `<th>`(colSpan · 고정 sticky · 폭 · 드래그 · 우클릭 메뉴)를 맡고,
50
+ * 안쪽 내용은 **헤더 정의**(`defineHeader`)가 그린다.
51
+ *
52
+ * 정의 적용 순서: `headerDef` prop → `column.meta.header`(id 또는 정의) → Provider `headers[]` 중 `when` 이 참인 첫 정의 → 기본.
53
+ * 정의의 `rules` 는 여기서 해석돼 정렬 클릭·리사이즈 핸들·드래그·메뉴 항목 `when` 과 TanStack `column.getCan*()` 모두에 반영된다.
54
+ *
55
+ * 정렬은 `SortSource` 로만 받는다. 콘텐츠 계약에 섞지 않은 이유는
56
+ * 카드 화면처럼 헤더가 없는 곳에서도 정렬 컨트롤을 따로 둘 수 있어야 하기 때문이다.
57
+ * 컬럼 단위 규칙은 `meta.headerTooltip` / `meta.headerAlign` / `meta.align` 을 읽는다.
58
+ */
59
+ export declare function HeaderCell<T extends RowData>({ header, sort, table: tableProp, enableColumnMenu, size, draggableGroup, columnMenuItems, grouping, onGroupingChange, aggregation, onAggregationChange, onOpenFilter, headerCellProps, renderHeader, headerDef, }: HeaderCellProps<T>): import("react").JSX.Element;