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,196 @@
1
+ import type { ReactNode } from "react";
2
+ import type { RowData } from "@tanstack/react-table";
3
+ import type { AggRenderFn, SelectOption, TableColumnDef, ValueOfKey } from "../types/column";
4
+ import type { RelationOperatorName } from "../filters/relation";
5
+ import type { LinearFilterValue, LinearOperatorName } from "../filters/linear";
6
+ import type { ScheduleFields } from "../filters/schedule";
7
+ import { ColumnBuilder, type CellRenderProps, type EditSpec } from "./ColumnBuilder";
8
+ export interface CommonCodeOption {
9
+ idx: number;
10
+ name: string;
11
+ parentIdx?: number;
12
+ ancestorChain?: string;
13
+ }
14
+ export interface CommonCodeLookup {
15
+ /** 코드 경로의 선택지 */
16
+ getOptions(codePath: string, options?: {
17
+ activeOnly?: boolean;
18
+ }): CommonCodeOption[];
19
+ /** 저장값 → 표시 라벨 */
20
+ getLabel(codePath: string, value: unknown): string;
21
+ }
22
+ export interface UserLookup {
23
+ getAll(): Array<{
24
+ idx: number;
25
+ name: string;
26
+ }>;
27
+ getById(idx: number): {
28
+ idx: number;
29
+ name: string;
30
+ } | undefined;
31
+ }
32
+ export interface ColumnHelperDeps {
33
+ commonCodeLookup?: CommonCodeLookup;
34
+ userLookup?: UserLookup;
35
+ /** 폐기된 코드를 선택지에서 뺄지 */
36
+ activeOnly?: boolean;
37
+ }
38
+ /**
39
+ * 프리셋 공통 파라미터. `K` 는 `key` 리터럴 — `keyof T` 이면 빌더의 셀 값 타입 `V` 가
40
+ * `T[K]` 로 추론되고, 점 경로나 동적 문자열이면 `unknown` 이다 (`ValueOfKey`).
41
+ * 기존처럼 `ColumnParams` 로만 쓰면 `K = string` 이라 `unknown` 으로 남는다.
42
+ */
43
+ export interface ColumnParams<K extends string = string> {
44
+ key: K;
45
+ header: string;
46
+ size?: number;
47
+ }
48
+ export interface CompositeComponent {
49
+ key: string;
50
+ /** 서버 집계 함수 — `sum` / `avg` / `min` / `max` / `count_distinct` */
51
+ agg: string;
52
+ }
53
+ export type ColumnFactory<T extends RowData> = (...args: never[]) => ColumnBuilder<T, any> | ColumnBuilder<T, any>[];
54
+ declare function makeBase<T extends RowData>(deps: ColumnHelperDeps): {
55
+ ColumnIsText: <K extends string>(p: ColumnParams<K>) => ColumnBuilder<T, ValueOfKey<T, K>>;
56
+ ColumnIsBoolean: <K extends string>(p: ColumnParams<K>) => ColumnBuilder<T, ValueOfKey<T, K>>;
57
+ ColumnIsDate: <K extends string>(p: ColumnParams<K> & {
58
+ withTime?: boolean;
59
+ }) => ColumnBuilder<T, ValueOfKey<T, K>>;
60
+ /** 콤마 포맷 + 통화/단위 + 소수점 자릿수 */
61
+ ColumnIsNumber: <K extends string>(p: ColumnParams<K> & {
62
+ decimals?: number;
63
+ currency?: string;
64
+ endAdornment?: ReactNode;
65
+ editable?: boolean;
66
+ onCommit?: (value: unknown, row: T) => void;
67
+ }) => ColumnBuilder<T, ValueOfKey<T, K>>;
68
+ /**
69
+ * 특정 숫자 — 기본 `inArray`(쉼표로 구분한 번호 여러 개 → 서버 `IN`), 보조 `equals`(하나).
70
+ * 참조번호처럼 "그 값"을 찾는 컬럼에 범위 필터를 주면 오히려 방해가 된다.
71
+ * 하나만 넣어도 `[값]` 배열로 나가므로 equals 와 결과가 같다.
72
+ */
73
+ ColumnIsSpecificNumber: <K extends string>(p: ColumnParams<K>) => ColumnBuilder<T, ValueOfKey<T, K>>;
74
+ /** IDX 참조번호 — equals 전용 + 칩 표시. 기본은 숨김 */
75
+ ColumnIsIDX: <K extends string>(p: Omit<ColumnParams<K>, "header"> & {
76
+ header?: string;
77
+ display?: {
78
+ display: boolean;
79
+ hideFilter: boolean;
80
+ };
81
+ }) => ColumnBuilder<T, ValueOfKey<T, K>>;
82
+ ColumnIsEnum: <K extends string>(p: ColumnParams<K> & {
83
+ options: SelectOption[];
84
+ multiple?: boolean;
85
+ }) => ColumnBuilder<T, ValueOfKey<T, K>>;
86
+ ColumnIsCommonCode: <K extends string>(p: ColumnParams<K> & {
87
+ codePath: string;
88
+ /** 기본 `true` — 기존 `ColumnIsCommonCode` 의 `isMultiSelect` 기본값과 같다 */
89
+ multiple?: boolean;
90
+ /**
91
+ * 상위 컬럼 id. 주면 **종속 필터**가 된다 — 상위에서 고른 값의 자식만
92
+ * 선택지에 남고, 상위가 바뀌면 무효해진 하위 값이 자동으로 지워진다
93
+ * (`resolveCascadeOptions` / `pruneCascadeValues`).
94
+ */
95
+ dependsOn?: string;
96
+ }) => ColumnBuilder<T, ValueOfKey<T, K>>;
97
+ ColumnIsUser: <K extends string>(p: ColumnParams<K> & {
98
+ multiple?: boolean;
99
+ }) => ColumnBuilder<T, ValueOfKey<T, K>>;
100
+ /**
101
+ * 링크 컬럼. `to` 는 반드시 "/" 로 시작하는 **절대 경로**여야 한다 —
102
+ * 상대 경로는 라우터가 현재 URL 기준으로 해석해 연타 시
103
+ * `/item/view/1/view/1/...` 처럼 경로가 누적된다.
104
+ */
105
+ ColumnIsLink: <K extends string>(p: ColumnParams<K> & {
106
+ to: (props: CellRenderProps<T, ValueOfKey<T, K>>) => string;
107
+ placeholder?: string;
108
+ }) => ColumnBuilder<T, ValueOfKey<T, K>>;
109
+ /** 필터·정렬 없는 표시 전용 컬럼 */
110
+ ColumnIsCustom: <K extends string>(p: ColumnParams<K> & {
111
+ cell: (props: CellRenderProps<T, ValueOfKey<T, K>>) => ReactNode;
112
+ }) => ColumnBuilder<T, ValueOfKey<T, K>>;
113
+ /**
114
+ * 참조 컬럼. `key` 는 서버가 응답에 실어 준 **라벨 컬럼**이라 텍스트 컬럼
115
+ * 그대로다 — 서버측 라벨 검색·정렬이 다른 텍스트 컬럼과 같은 경로로 걸린다.
116
+ * `ColumnIsCustom` 은 accessor 를 죽이고 필터를 끄므로 참조에 쓰면 안 된다.
117
+ */
118
+ ColumnIsReference: <K extends string>(p: ColumnParams<K> & {
119
+ cell: (props: CellRenderProps<T, ValueOfKey<T, K>>) => ReactNode;
120
+ /** 참조 타입 컬럼 — 비어 있는 행은 placeholder 로 그린다 */
121
+ typeKey?: string;
122
+ placeholder?: string;
123
+ }) => ColumnBuilder<T, ValueOfKey<T, K>>;
124
+ /** 1:N 관계 필터 컬럼 */
125
+ ColumnIsRelation: <K extends string>(p: ColumnParams<K> & {
126
+ innerColumns: Array<{
127
+ key: string;
128
+ label: string;
129
+ type?: string;
130
+ }>;
131
+ cell?: (props: CellRenderProps<T, ValueOfKey<T, K>>) => ReactNode;
132
+ operators?: RelationOperatorName[];
133
+ }) => ColumnBuilder<T, ValueOfKey<T, K>>;
134
+ /** 선형결합(수량 조건) 필터 컬럼 */
135
+ ColumnIsLinear: <K extends string>(p: ColumnParams<K> & {
136
+ config: Partial<LinearFilterValue>;
137
+ cell?: (props: CellRenderProps<T, ValueOfKey<T, K>>) => ReactNode;
138
+ operators?: LinearOperatorName[];
139
+ }) => ColumnBuilder<T, ValueOfKey<T, K>>;
140
+ /**
141
+ * 일정 통합 컬럼 — 예정/실제 4개 날짜를 컬럼 하나로 묶는다.
142
+ *
143
+ * 반환: `[통합 컬럼, 숨김 날짜 컬럼 4개]`. 숨김 컬럼의 id 가 실제 필드명이라
144
+ * 서버 QueryBuilder 가 그대로 해석한다.
145
+ */
146
+ ColumnIsSchedule: (p: Omit<ColumnParams, "key"> & {
147
+ key?: string;
148
+ fields?: ScheduleFields;
149
+ }) => ColumnBuilder<T, any>[];
150
+ /**
151
+ * 합성 집계 컬럼 — 여러 컴포넌트를 서버에서 집계하고 하나로 합쳐 보여준다.
152
+ * 반환: `[숨김 컴포넌트 컬럼들, 표시 컬럼]`.
153
+ */
154
+ ColumnIsComposite: <K extends string>(p: ColumnParams<K> & {
155
+ components: CompositeComponent[];
156
+ cell: (props: CellRenderProps<T, ValueOfKey<T, K>>) => ReactNode;
157
+ /** `({ value, columnId, allAggregates }, column)` — 렌더러가 실제로 부르는 규약 (ERP `AggCustomRender`) */
158
+ aggRender?: AggRenderFn;
159
+ }) => ColumnBuilder<T, any>[];
160
+ /**
161
+ * Cascade 컬럼 그룹 — N단계 종속 필터.
162
+ *
163
+ * 통합 컬럼 하나만 표시하고, 레벨별 실제 필드는 `meta.cascadeFilterLevels` 로
164
+ * 남긴다. 레벨 컬럼을 따로 만들지 않는 이유: 헤더 없는 고스트 컬럼이 생기고
165
+ * 사용자 토글로 되살아나기 때문이다. 서버 필터 연산자는 `deriveOperators` 가
166
+ * 이 메타를 펼쳐서 채운다.
167
+ */
168
+ ColumnIsCascade: <K extends string>(p: ColumnParams<K> & {
169
+ /** 상위 → 하위 순서의 실제 필드 경로 */
170
+ levels: string[];
171
+ codePath?: string;
172
+ multiple?: boolean;
173
+ }) => ColumnBuilder<T, any>[];
174
+ };
175
+ export type BaseColumnHelper<T extends RowData> = ReturnType<typeof makeBase<T>>;
176
+ /**
177
+ * 확장 가능한 컬럼 헬퍼.
178
+ *
179
+ * 원본 `class ColumnHelper` 는 메서드가 인스턴스 화살표 프로퍼티라 런타임
180
+ * `Object.assign` 은 됐지만 타입이 따라오지 않았다. `.extend()` 가 교차 타입을
181
+ * 반환하므로 확장분도 그대로 추론된다.
182
+ *
183
+ * @example
184
+ * const helper = createColumnHelper<Row>({ commonCodeLookup })
185
+ * .extend((self) => ({
186
+ * ColumnIsMoney: (p: ColumnParams) => self.ColumnIsNumber({ ...p, currency: "KRW" }),
187
+ * }));
188
+ * helper.ColumnIsMoney({ key: "amount", header: "금액" }); // 타입 추론됨
189
+ */
190
+ export type ColumnHelper<T extends RowData, Ext extends Record<string, ColumnFactory<T>> = Record<never, never>> = BaseColumnHelper<T> & Ext & {
191
+ extend<E extends Record<string, ColumnFactory<T>>>(ext: E | ((self: ColumnHelper<T, Ext>) => E)): ColumnHelper<T, Ext & E>;
192
+ };
193
+ export declare function createColumnHelper<T extends RowData>(deps?: ColumnHelperDeps): ColumnHelper<T>;
194
+ export type { CellRenderProps, EditSpec };
195
+ export { ColumnBuilder };
196
+ export type { TableColumnDef };
@@ -0,0 +1,250 @@
1
+ import { ColumnBuilder } from "./ColumnBuilder";
2
+ import { getValue } from "../utils/getValue";
3
+ import { cascadeKind, commonCodeKind } from "../filters/kinds";
4
+ const toSelectOption = (option) => ({
5
+ label: option.name,
6
+ value: String(option.idx),
7
+ ...(option.ancestorChain ? { ancestorChain: option.ancestorChain } : {}),
8
+ });
9
+ function requireDep(dep, name, preset) {
10
+ if (!dep) {
11
+ throw new Error(`[koko-table] ${preset} 에는 ${name} 이 필요합니다. ` +
12
+ `createColumnHelper({ ${name} }) 로 주입하세요.`);
13
+ }
14
+ return dep;
15
+ }
16
+ // ─────────────────────────────────────────────────────────────
17
+ // 기본 헬퍼
18
+ // ─────────────────────────────────────────────────────────────
19
+ function makeBase(deps) {
20
+ // `key` 리터럴 K → 셀 값 타입 V = T[K] (keyof T 가 아니면 unknown)
21
+ const create = (key, header, type, size) => {
22
+ const builder = new ColumnBuilder(key, header, type);
23
+ if (size !== undefined)
24
+ builder.setSizing({ size });
25
+ return builder;
26
+ };
27
+ const base = {
28
+ ColumnIsText: (p) => create(p.key, p.header, "text", p.size),
29
+ ColumnIsBoolean: (p) => create(p.key, p.header, "boolean", p.size),
30
+ ColumnIsDate: (p) => create(p.key, p.header, p.withTime ? "datetime" : "date", p.size),
31
+ /** 콤마 포맷 + 통화/단위 + 소수점 자릿수 */
32
+ ColumnIsNumber: (p) => {
33
+ const builder = create(p.key, p.header, "number", p.size);
34
+ builder.setMeta({ decimals: p.decimals, currency: p.currency, endAdornment: p.endAdornment });
35
+ if (p.decimals != null) {
36
+ builder.setCell(({ value }) => value == null
37
+ ? ""
38
+ : Number(value).toLocaleString("ko-KR", {
39
+ minimumFractionDigits: p.decimals,
40
+ maximumFractionDigits: p.decimals,
41
+ }));
42
+ }
43
+ if (p.editable)
44
+ builder.setEditable(true, p.onCommit);
45
+ return builder;
46
+ },
47
+ /**
48
+ * 특정 숫자 — 기본 `inArray`(쉼표로 구분한 번호 여러 개 → 서버 `IN`), 보조 `equals`(하나).
49
+ * 참조번호처럼 "그 값"을 찾는 컬럼에 범위 필터를 주면 오히려 방해가 된다.
50
+ * 하나만 넣어도 `[값]` 배열로 나가므로 equals 와 결과가 같다.
51
+ */
52
+ ColumnIsSpecificNumber: (p) => create(p.key, p.header, "number", p.size)
53
+ .setOperators(["inArray", "equals"], "inArray")
54
+ // 번호는 합계·평균이 뜻이 없다 — 집계 후보(AggregationChips·그룹 헤더)에서 뺀다
55
+ .setMeta({ enableAgg: false }),
56
+ /** IDX 참조번호 — equals 전용 + 칩 표시. 기본은 숨김 */
57
+ ColumnIsIDX: (p) => {
58
+ const builder = base
59
+ .ColumnIsSpecificNumber({ key: p.key, header: p.header ?? "참조번호", size: p.size })
60
+ .setMeta({ chip: true });
61
+ builder.setDisplay(p.display ?? { display: false, hideFilter: true });
62
+ return builder;
63
+ },
64
+ ColumnIsEnum: (p) => {
65
+ const builder = create(p.key, p.header, "enum", p.size);
66
+ builder.setVariant(p.multiple ? "multiSelect" : "select");
67
+ builder.setFilterOptions(p.options);
68
+ return builder;
69
+ },
70
+ ColumnIsCommonCode: (p) => {
71
+ const lookup = requireDep(deps.commonCodeLookup, "commonCodeLookup", "ColumnIsCommonCode");
72
+ const all = lookup.getOptions(p.codePath, { activeOnly: deps.activeOnly });
73
+ // 공통코드는 다중 선택이 기본이다. 단일(select) 로 두면 스칼라 값 + `inArray` 로
74
+ // 요청이 나가던 경로라(현재는 배열로 감싸 막아 두었다) 기존 기본값과도 어긋났다.
75
+ const multiple = p.multiple ?? true;
76
+ const builder = base.ColumnIsEnum({ ...p, multiple, options: all.map(toSelectOption) });
77
+ // enum 과 판정은 같지만 id 가 다르다 — Provider 가 공통코드 입력만 따로 바꿀 수 있다
78
+ builder.setFilterKind(commonCodeKind, { variant: multiple ? "multiSelect" : "select" });
79
+ builder.setMeta({ commonCodeParentPath: p.codePath });
80
+ builder.setCell(({ value }) => (value == null ? "" : lookup.getLabel(p.codePath, value)));
81
+ if (p.dependsOn) {
82
+ const children = all.filter((option) => option.parentIdx != null);
83
+ if (children.length === 0 && all.length > 0) {
84
+ // 부모 정보가 없는 코드 목록에 dependsOn 을 걸면 선택지가 영영 비어
85
+ // 필터를 못 쓰게 된다. 조용히 넘어가면 원인을 찾기 어렵다.
86
+ throw new Error(`[koko-table] ColumnIsCascade/dependsOn: "${p.codePath}" 의 코드에 ` +
87
+ "parentIdx 가 없습니다. commonCodeLookup.getOptions 가 부모 idx 를 실어 주어야 합니다.");
88
+ }
89
+ builder.setMeta({
90
+ dependentFilter: {
91
+ dependsOn: p.dependsOn,
92
+ isMultiSelect: multiple,
93
+ allChildOptions: children.map((option) => ({
94
+ idx: option.idx,
95
+ name: option.name,
96
+ parentIdx: option.parentIdx,
97
+ ...(option.ancestorChain ? { ancestorChain: option.ancestorChain } : {}),
98
+ })),
99
+ },
100
+ });
101
+ }
102
+ return builder;
103
+ },
104
+ ColumnIsUser: (p) => {
105
+ const lookup = requireDep(deps.userLookup, "userLookup", "ColumnIsUser");
106
+ const options = lookup
107
+ .getAll()
108
+ .map((user) => ({ label: user.name, value: String(user.idx) }));
109
+ const builder = base.ColumnIsEnum({ ...p, options });
110
+ builder.setCell(({ value }) => value == null ? "" : lookup.getById(Number(value))?.name ?? "");
111
+ return builder;
112
+ },
113
+ /**
114
+ * 링크 컬럼. `to` 는 반드시 "/" 로 시작하는 **절대 경로**여야 한다 —
115
+ * 상대 경로는 라우터가 현재 URL 기준으로 해석해 연타 시
116
+ * `/item/view/1/view/1/...` 처럼 경로가 누적된다.
117
+ */
118
+ ColumnIsLink: (p) => {
119
+ const builder = create(p.key, p.header, "text", p.size);
120
+ builder.setMeta({ link: { to: p.to }, placeholder: p.placeholder ?? "-" });
121
+ return builder;
122
+ },
123
+ /** 필터·정렬 없는 표시 전용 컬럼 */
124
+ ColumnIsCustom: (p) => {
125
+ const builder = create(p.key, p.header, "text", p.size);
126
+ builder.setProps({ enableSorting: false, enableGrouping: false });
127
+ builder.setFilter({ hidden: true });
128
+ builder.setCell(p.cell);
129
+ return builder;
130
+ },
131
+ /**
132
+ * 참조 컬럼. `key` 는 서버가 응답에 실어 준 **라벨 컬럼**이라 텍스트 컬럼
133
+ * 그대로다 — 서버측 라벨 검색·정렬이 다른 텍스트 컬럼과 같은 경로로 걸린다.
134
+ * `ColumnIsCustom` 은 accessor 를 죽이고 필터를 끄므로 참조에 쓰면 안 된다.
135
+ */
136
+ ColumnIsReference: (p) => {
137
+ const builder = create(p.key, p.header, "text", p.size);
138
+ const typeKey = p.typeKey ?? "reference";
139
+ builder.setCell((props) => getValue(props.row, typeKey) ? p.cell(props) : p.placeholder ?? "-");
140
+ return builder;
141
+ },
142
+ /** 1:N 관계 필터 컬럼 */
143
+ ColumnIsRelation: (p) => {
144
+ const builder = create(p.key, p.header, "text", p.size);
145
+ builder.setVariant("relation", p.operators ?? ["hasAny", "hasAll", "hasChild", "hasNotChild"]);
146
+ builder.setProps({ enableSorting: false });
147
+ // 하위 컬럼을 meta 에 남긴다 — 필터 UI 는 렌더 prop 으로 받지만, 컬럼 정의만
148
+ // 읽는 쪽(AI 컨텍스트 추출 등)은 여기를 봐야 자식 구조를 알 수 있다
149
+ builder.setMeta({ relationColumns: p.innerColumns });
150
+ builder.setCell((props) => p.cell?.(props) ?? "-");
151
+ return builder;
152
+ },
153
+ /** 선형결합(수량 조건) 필터 컬럼 */
154
+ ColumnIsLinear: (p) => {
155
+ const builder = create(p.key, p.header, "text", p.size);
156
+ builder.setVariant("linear", p.operators ?? ["linearContains", "linearExists", "linearExact"]);
157
+ builder.setProps({ enableSorting: false });
158
+ builder.setMeta({ linearConfig: p.config });
159
+ builder.setCell((props) => p.cell?.(props) ?? "-");
160
+ return builder;
161
+ },
162
+ /**
163
+ * 일정 통합 컬럼 — 예정/실제 4개 날짜를 컬럼 하나로 묶는다.
164
+ *
165
+ * 반환: `[통합 컬럼, 숨김 날짜 컬럼 4개]`. 숨김 컬럼의 id 가 실제 필드명이라
166
+ * 서버 QueryBuilder 가 그대로 해석한다.
167
+ */
168
+ ColumnIsSchedule: (p) => {
169
+ const fields = {
170
+ plannedStart: "planned_process_date",
171
+ plannedEnd: "planned_finish_date",
172
+ actualStart: "actual_process_date",
173
+ actualEnd: "actual_finish_date",
174
+ ...p.fields,
175
+ };
176
+ const key = p.key ?? "schedule";
177
+ const main = create(key, p.header, "text", p.size);
178
+ main.setVariant("schedule");
179
+ main.setMeta({ scheduleFields: fields, sortExpandsTo: [fields.plannedStart] });
180
+ main.setProps({ accessorFn: (row) => getValue(row, fields.plannedStart) ?? "" });
181
+ const hidden = (path) => new ColumnBuilder(path, "", "date").setDisplay({ display: false, hideFilter: true });
182
+ return [
183
+ main,
184
+ hidden(fields.plannedStart),
185
+ hidden(fields.plannedEnd),
186
+ hidden(fields.actualStart),
187
+ hidden(fields.actualEnd),
188
+ ];
189
+ },
190
+ /**
191
+ * 합성 집계 컬럼 — 여러 컴포넌트를 서버에서 집계하고 하나로 합쳐 보여준다.
192
+ * 반환: `[숨김 컴포넌트 컬럼들, 표시 컬럼]`.
193
+ */
194
+ ColumnIsComposite: (p) => {
195
+ const hidden = p.components.map(({ key, agg }) => new ColumnBuilder(key, key, "number")
196
+ .setDisplay({ display: false, hideFilter: true })
197
+ .setAgg(true, [agg]));
198
+ const display = create(p.key, p.header, "text", p.size);
199
+ display.setProps({ enableSorting: false, enableGrouping: false });
200
+ display.setFilter({ hidden: true });
201
+ display.setCell(p.cell);
202
+ if (p.aggRender)
203
+ display.setMeta({ aggRender: p.aggRender });
204
+ return [...hidden, display];
205
+ },
206
+ /**
207
+ * Cascade 컬럼 그룹 — N단계 종속 필터.
208
+ *
209
+ * 통합 컬럼 하나만 표시하고, 레벨별 실제 필드는 `meta.cascadeFilterLevels` 로
210
+ * 남긴다. 레벨 컬럼을 따로 만들지 않는 이유: 헤더 없는 고스트 컬럼이 생기고
211
+ * 사용자 토글로 되살아나기 때문이다. 서버 필터 연산자는 `deriveOperators` 가
212
+ * 이 메타를 펼쳐서 채운다.
213
+ */
214
+ ColumnIsCascade: (p) => {
215
+ const operator = p.multiple === false ? "equals" : "inArray";
216
+ const builder = create(p.key, p.header, "text", p.size);
217
+ builder.setFilterKind(cascadeKind, { variant: "select", operators: ["inArray", "notInArray"] });
218
+ builder.setMeta({
219
+ cascadeFilterLevels: p.levels.map((key) => ({
220
+ key,
221
+ operator,
222
+ operatorOptions: ["inArray", "notInArray"],
223
+ })),
224
+ sortExpandsTo: p.levels,
225
+ ...(p.codePath ? { commonCodeParentPath: p.codePath } : {}),
226
+ });
227
+ if (deps.commonCodeLookup && p.codePath) {
228
+ const lookup = deps.commonCodeLookup;
229
+ const options = lookup
230
+ .getOptions(p.codePath, { activeOnly: deps.activeOnly })
231
+ .map(toSelectOption);
232
+ builder.setFilterOptions(options);
233
+ }
234
+ return [builder];
235
+ },
236
+ };
237
+ return base;
238
+ }
239
+ export function createColumnHelper(deps = {}) {
240
+ const attach = (helper) => {
241
+ const withExtend = helper;
242
+ withExtend.extend = (ext) => {
243
+ const resolved = typeof ext === "function" ? ext(withExtend) : ext;
244
+ return attach(Object.assign(Object.create(Object.getPrototypeOf(withExtend)), withExtend, resolved));
245
+ };
246
+ return withExtend;
247
+ };
248
+ return attach(makeBase(deps));
249
+ }
250
+ export { ColumnBuilder };
@@ -0,0 +1,12 @@
1
+ import type { RowData } from "@tanstack/react-table";
2
+ import type { TableColumnDefs } from "../types/column";
3
+ /** 컬럼 값 → 표시 라벨. 못 찾으면 undefined */
4
+ export type LabelResolver = (columnId: string, value: unknown) => string | undefined;
5
+ /**
6
+ * 컬럼의 `selectOptions` 에서 라벨을 찾는 해석기.
7
+ *
8
+ * CommonCode 컬럼은 셀에 idx 를 담고 화면에는 이름을 보여준다. 그룹 헤더나
9
+ * 피벗 축이 이걸 해석하지 않으면 "완료" 대신 "3" 이 뜬다.
10
+ * **그룹핑과 피벗이 같은 해석기를 쓰도록** 여기 한 곳에 둔다.
11
+ */
12
+ export declare function createLabelResolver<T extends RowData>(columns: TableColumnDefs<T> | undefined, override?: LabelResolver): LabelResolver;
@@ -0,0 +1,21 @@
1
+ import { columnKey } from "./deriveOperators";
2
+ /**
3
+ * 컬럼의 `selectOptions` 에서 라벨을 찾는 해석기.
4
+ *
5
+ * CommonCode 컬럼은 셀에 idx 를 담고 화면에는 이름을 보여준다. 그룹 헤더나
6
+ * 피벗 축이 이걸 해석하지 않으면 "완료" 대신 "3" 이 뜬다.
7
+ * **그룹핑과 피벗이 같은 해석기를 쓰도록** 여기 한 곳에 둔다.
8
+ */
9
+ export function createLabelResolver(columns, override) {
10
+ if (override)
11
+ return override;
12
+ const byColumn = new Map();
13
+ for (const column of columns ?? []) {
14
+ const id = columnKey(column);
15
+ const options = column.meta?.selectOptions;
16
+ if (!id || !options)
17
+ continue;
18
+ byColumn.set(id, new Map(options.map((option) => [option.value, option.label])));
19
+ }
20
+ return (columnId, value) => byColumn.get(columnId)?.get(String(value));
21
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 백엔드 계약 버전.
3
+ *
4
+ * 프론트는 백엔드 코드를 직접 쓰지 않는다. 서버 모드를 켰을 때 wire 계약
5
+ * (`TableRequest`/`TableResponse`)으로만 호환을 보증하며, 그 계약은 이 패키지에 실린
6
+ * `contract/table-request.schema.json`(백엔드 pydantic `TableRequest` 에서 생성, `kokotable/contract/table-request.schema.json`) 이다.
7
+ * 백엔드 패키지 `koko-table-server` 의 `CONTRACT_VERSION` 과 같은 값이어야 하고,
8
+ * 계약이 바뀌는 릴리스에서만 minor 를 올린다.
9
+ */
10
+ export declare const CONTRACT_VERSION = "0.95.0";
11
+ /** `kokotable/contract/table-request.schema.json` 의 패키지 내 경로 */
12
+ export declare const TABLE_REQUEST_SCHEMA_PATH = "contract/table-request.schema.json";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 백엔드 계약 버전.
3
+ *
4
+ * 프론트는 백엔드 코드를 직접 쓰지 않는다. 서버 모드를 켰을 때 wire 계약
5
+ * (`TableRequest`/`TableResponse`)으로만 호환을 보증하며, 그 계약은 이 패키지에 실린
6
+ * `contract/table-request.schema.json`(백엔드 pydantic `TableRequest` 에서 생성, `kokotable/contract/table-request.schema.json`) 이다.
7
+ * 백엔드 패키지 `koko-table-server` 의 `CONTRACT_VERSION` 과 같은 값이어야 하고,
8
+ * 계약이 바뀌는 릴리스에서만 minor 를 올린다.
9
+ */
10
+ export const CONTRACT_VERSION = "0.95.0";
11
+ /** `kokotable/contract/table-request.schema.json` 의 패키지 내 경로 */
12
+ export const TABLE_REQUEST_SCHEMA_PATH = "contract/table-request.schema.json";
@@ -0,0 +1,102 @@
1
+ /**
2
+ * AI 검색 연동용 컬럼 메타 계약.
3
+ *
4
+ * 왜 필요한가: ERP `features/ai-search/hooks/use-register-table.ts` 는
5
+ * `extractColumnMeta(table.options.columns)` 로 컬럼을 AI 컨텍스트에 올린다.
6
+ * 기존 `features/ai-search/utils/extract-column-meta.ts` 는 MRT 컬럼의
7
+ * `accessorKey` / `meta.columnType` / `filterVariant` / `filterSelectOptions` 를
8
+ * 읽는데, koko 컬럼은 `id` + `accessorFn` / `meta.dataType` + `filter.variant` /
9
+ * `meta.selectOptions` 라서 **0개가 추출된다** (server.md D-3 실측).
10
+ *
11
+ * 두 갈래를 제공한다.
12
+ * - `extractColumnMeta(columns)` — koko 컬럼에서 곧바로 AI 계약 모양을 만든다.
13
+ * 규칙은 기존 extract-column-meta.ts 를 그대로 옮겼다.
14
+ * - `toLegacyColumnDefs(columns)` — 기존 ERP `extractColumnMeta` 를 **수정 없이**
15
+ * 통과하도록 `accessorKey` / `meta.columnType` / `filterVariant` /
16
+ * `filterSelectOptions` 를 덧붙인 사본을 돌려준다. 원본 컬럼은 변형하지 않는다.
17
+ */
18
+ import type { RowData } from "@tanstack/react-table";
19
+ import type { CascadeFilterLevel, ColumnMeta, SelectOption, TableColumnDef, TableColumnDefs } from "../types/column";
20
+ export type AiColumnType = "text" | "number" | "date" | "select" | "multiSelect" | "boolean" | "relation";
21
+ /** 관계(1:N) 컬럼 안쪽 필드 — 구성품·주문상세처럼 자식 행을 가진 컬럼용 */
22
+ export interface AiInnerColumnMeta {
23
+ key: string;
24
+ header: string;
25
+ type: "text" | "number" | "date";
26
+ }
27
+ /** AI 에 전달할 컬럼 메타데이터 */
28
+ export interface AiColumnMeta {
29
+ key: string;
30
+ header: string;
31
+ type: AiColumnType;
32
+ options?: Array<{
33
+ value: string;
34
+ label: string;
35
+ }>;
36
+ /** relation 타입일 때의 하위 컬럼 — groups 조건의 column 으로 쓸 수 있는 것들 */
37
+ inner?: AiInnerColumnMeta[];
38
+ }
39
+ export interface ExtractColumnMetaOptions {
40
+ /**
41
+ * "전체"(`_ALL_SELECTED`) / "(비어있음)"(`EMPTY`) 센티널을 옵션에서 뺀다.
42
+ * 기본 false — 기존 extract-column-meta.ts 는 센티널을 걸러내지 않았으므로
43
+ * 같은 출력을 유지한다.
44
+ */
45
+ stripSentinels?: boolean;
46
+ }
47
+ /** `filter.variant`(없으면 dataType 유추) → AI 계약 타입 */
48
+ export declare function toAiColumnType<T extends RowData>(column: TableColumnDef<T, any>): AiColumnType;
49
+ /**
50
+ * koko 컬럼 정의에서 AI 용 메타데이터를 추출한다.
51
+ *
52
+ * 기존 규칙(`extract-column-meta.ts`)을 그대로 따른다:
53
+ * - 키가 없는 컬럼(display 등)은 건너뛴다
54
+ * - `meta.forceHidden` 은 값 보관 전용이라 AI 컨텍스트에 올리지 않는다
55
+ * - 통합 cascade 는 가상 컬럼 대신 `cascadeFilterLevels` 의 실제 레벨 키를 올린다
56
+ * (연산자가 equals/notEquals 면 select, 아니면 multiSelect)
57
+ * - `meta.relationColumns` 가 있으면 relation + inner
58
+ * - 그 외는 `filter.variant`/`meta.dataType` 으로 타입, select/multiSelect 는 옵션 동봉
59
+ */
60
+ export declare function extractColumnMeta<T extends RowData>(columns: TableColumnDefs<T>, options?: ExtractColumnMetaOptions): AiColumnMeta[];
61
+ /** 기존 `types/columnMeta.ts` → `types/table.ts` 의 `ColumnFilterType` */
62
+ export type LegacyColumnType = "text" | "select" | "date" | "datetime" | "number" | "boolean" | "custom" | "multiSelect" | "relation";
63
+ /** 기존 `columns/utils/filterUtils.ts getFilterVariant` 가 내던 MRT filterVariant */
64
+ export type LegacyFilterVariant = "autocomplete" | "text" | "select" | "multi-select";
65
+ /** 기존 `ColumnMetaData.cascadeFilterLevels` 원소 모양 (koko 는 operator/operatorOptions) */
66
+ export interface LegacyCascadeFilterLevel extends CascadeFilterLevel {
67
+ filterFn: string;
68
+ columnFilterModeOptions: string[];
69
+ }
70
+ export type LegacyCompatColumnMeta = Omit<ColumnMeta, "cascadeFilterLevels"> & {
71
+ columnType: LegacyColumnType;
72
+ cascadeFilterLevels?: LegacyCascadeFilterLevel[];
73
+ };
74
+ /**
75
+ * 기존 ERP `extractColumnMeta` / `getAllColumns().map(c => c.columnDef.meta.columnType)`
76
+ * 가 읽는 필드만 보장한다. 나머지는 koko 컬럼을 그대로 스프레드한다.
77
+ */
78
+ export interface LegacyCompatColumnDef {
79
+ id: string;
80
+ accessorKey: string;
81
+ header?: unknown;
82
+ filterVariant: LegacyFilterVariant;
83
+ filterSelectOptions?: SelectOption[];
84
+ meta: LegacyCompatColumnMeta;
85
+ [key: string]: unknown;
86
+ }
87
+ /**
88
+ * koko `filter.variant` → 기존 `meta.columnType`.
89
+ *
90
+ * 기존 columnType ≈ koko variant 이고, relation 은 기존이 `custom` 으로 찍었다
91
+ * (server.md D-3/D-4 실측). linear/schedule/custom 도 기존에 대응이 없어 `custom`.
92
+ */
93
+ export declare function toLegacyColumnType<T extends RowData>(column: TableColumnDef<T, any>): LegacyColumnType;
94
+ /** 기존 `getFilterVariant(columnType)` 표 */
95
+ export declare function toLegacyFilterVariant(columnType: LegacyColumnType): LegacyFilterVariant;
96
+ /**
97
+ * koko 컬럼 배열 → 기존 `extractColumnMeta` 가 그대로 읽을 수 있는 사본.
98
+ *
99
+ * 키가 없는 컬럼(display)은 결과에서 제외한다 — 기존 함수도 accessorKey 없는 컬럼은
100
+ * 건너뛰므로 결과는 같다. 원본 객체는 변형하지 않는다.
101
+ */
102
+ export declare function toLegacyColumnDefs<T extends RowData>(columns: TableColumnDefs<T>): LegacyCompatColumnDef[];