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,20 @@
1
+ import type { UseQueryResult } from "@tanstack/react-query";
2
+ import type { RowData } from "@tanstack/react-table";
3
+ import type { TableBundle, TableDefinition, TableResponse } from "../../core/src/index";
4
+ export interface ServerTableBundle<T extends RowData> extends TableBundle<T> {
5
+ readonly mode: "server";
6
+ /** react-query 결과 — 무효화·수동 재시도 등 */
7
+ query: UseQueryResult<TableResponse<T>, Error>;
8
+ }
9
+ /**
10
+ * 서버 모드 조립 — 1층·3층·애드온은 코어(`useDefinitionSearch` / `useDefinitionTable`)를 그대로 쓰고,
11
+ * 2층만 `useServerTableData` + `useServerGrouping` 으로 바꿔 끼운다.
12
+ *
13
+ * 그룹 컬럼이 있으면 **최상위 그룹 노드부터** 받고(`groupExpansion: { path: [] … }` — 서버 응답
14
+ * `groups.nodes`), 펼칠 때 그 경로의 `groupExpansion` 으로 하위를 배치 단위로 받는다.
15
+ * 그때 3층에는 펼쳐서 받은 말단 행(`grouping.rows`)이 실린다.
16
+ *
17
+ * 반환 모양은 클라이언트 조립(`useTableFromDefinition`)과 같은 `TableBundle` 이라
18
+ * `<TableScreen bundle={…} />` 이 어느 쪽인지 몰라도 된다.
19
+ */
20
+ export declare function useServerTable<T extends RowData>(definition: TableDefinition<T>): ServerTableBundle<T>;
@@ -0,0 +1,106 @@
1
+ import { useCallback, useMemo, useState } from "react";
2
+ import { PAGE_SIZE_ALL, DEFAULT_GROUP_BATCH_SIZE, resolveDefinitionMode, useDefinitionSearch, useDefinitionTable, } from "../../core/src/index";
3
+ import { useServerTableData } from "./useServerTableData";
4
+ import { useServerGrouping } from "./useServerGrouping";
5
+ const EMPTY_GROUPING = [];
6
+ /**
7
+ * 서버 모드 조립 — 1층·3층·애드온은 코어(`useDefinitionSearch` / `useDefinitionTable`)를 그대로 쓰고,
8
+ * 2층만 `useServerTableData` + `useServerGrouping` 으로 바꿔 끼운다.
9
+ *
10
+ * 그룹 컬럼이 있으면 **최상위 그룹 노드부터** 받고(`groupExpansion: { path: [] … }` — 서버 응답
11
+ * `groups.nodes`), 펼칠 때 그 경로의 `groupExpansion` 으로 하위를 배치 단위로 받는다.
12
+ * 그때 3층에는 펼쳐서 받은 말단 행(`grouping.rows`)이 실린다.
13
+ *
14
+ * 반환 모양은 클라이언트 조립(`useTableFromDefinition`)과 같은 `TableBundle` 이라
15
+ * `<TableScreen bundle={…} />` 이 어느 쪽인지 몰라도 된다.
16
+ */
17
+ export function useServerTable(definition) {
18
+ const server = definition.server;
19
+ if (resolveDefinitionMode(definition) !== "server" || !server) {
20
+ throw new Error(`[koko-table] useServerTable("${definition.key}"): 서버 모드 정의(\`server.queryFn\`)가 아닙니다 — ` +
21
+ "클라이언트 모드는 kokotable 의 useTableFromDefinition 을 쓰세요.");
22
+ }
23
+ const { search, urlSync, history } = useDefinitionSearch(definition);
24
+ // 응답 가공은 목록·그룹 확장·전체 조회가 같은 함수를 거친다
25
+ const rawQueryFn = server.queryFn;
26
+ const transform = server.transformResponse;
27
+ const queryFn = useMemo(() => (transform
28
+ ? async (request, context) => transform(await rawQueryFn(request, context), request)
29
+ : rawQueryFn), [rawQueryFn, transform]);
30
+ const groupingEnabled = !!definition.grouping?.enabled;
31
+ const groupingColumns = groupingEnabled ? (search.params.grouping ?? EMPTY_GROUPING) : EMPTY_GROUPING;
32
+ const grouped = groupingColumns.length > 0;
33
+ const [batchSize, setBatchSize] = useState(definition.grouping?.batchSize ?? DEFAULT_GROUP_BATCH_SIZE);
34
+ const queryKey = useMemo(() => [definition.key, ...(server.queryKey ?? [])], [definition.key, server.queryKey]);
35
+ const serverData = useServerTableData({
36
+ request: search.request,
37
+ queryFn,
38
+ queryKey,
39
+ enabled: server.enabled,
40
+ staleTime: server.staleTime,
41
+ keepPreviousData: server.keepPreviousData,
42
+ refetchInterval: server.refetchInterval,
43
+ retry: server.retry,
44
+ });
45
+ const group = useServerGrouping({
46
+ request: search.request,
47
+ queryFn,
48
+ grouping: groupingColumns,
49
+ columns: definition.columns,
50
+ headers: serverData.groups,
51
+ batchSize,
52
+ });
53
+ // 그룹 노드 응답은 `data` 가 비어 있다 — 펼쳐서 받아 온 말단 행을 3층에 실어야
54
+ // 셀이 컬럼 정의대로 그려진다
55
+ const data = useMemo(() => (grouped ? { ...serverData, rows: group.rows } : serverData), [serverData, grouped, group.rows]);
56
+ const { table, tableColumns, setTableColumns } = useDefinitionTable({ definition, search, data });
57
+ const fetchAllRows = useCallback(async () => {
58
+ const request = {
59
+ ...search.request,
60
+ // "전체" 는 PAGE_SIZE_ALL 을 명시한다 — 기존 ERP 백엔드는 pagination 미지정을 기본 10건으로
61
+ // 해석하므로, 미지정으로 보내면 서버 버전에 따라 결과가 갈린다
62
+ pagination: { pageIndex: 0, pageSize: PAGE_SIZE_ALL },
63
+ grouping: undefined,
64
+ aggregation: undefined,
65
+ groupExpansion: undefined,
66
+ };
67
+ const response = await queryFn(request, { signal: new AbortController().signal });
68
+ return response.data ?? [];
69
+ }, [queryFn, search.request]);
70
+ const grouping = useMemo(() => {
71
+ if (!groupingEnabled)
72
+ return undefined;
73
+ return {
74
+ enabled: group.enabled,
75
+ grouping: groupingColumns,
76
+ setGrouping: search.setGrouping,
77
+ items: group.items,
78
+ expand: group.expand,
79
+ loadMore: group.loadMore,
80
+ rows: group.rows,
81
+ batchSize,
82
+ setBatchSize,
83
+ };
84
+ }, [
85
+ groupingEnabled, group.enabled, group.items, group.expand, group.loadMore, group.rows,
86
+ groupingColumns, search.setGrouping, batchSize,
87
+ ]);
88
+ return useMemo(() => ({
89
+ definition,
90
+ mode: "server",
91
+ search,
92
+ data,
93
+ table,
94
+ grouping,
95
+ urlSync,
96
+ history,
97
+ request: search.request,
98
+ tableColumns,
99
+ setTableColumns,
100
+ fetchAllRows,
101
+ query: serverData.query,
102
+ }), [
103
+ definition, search, data, table, grouping, urlSync, history, tableColumns, setTableColumns,
104
+ fetchAllRows, serverData.query,
105
+ ]);
106
+ }
@@ -0,0 +1,48 @@
1
+ import { type UseQueryOptions, type UseQueryResult } from "@tanstack/react-query";
2
+ import type { RowData } from "@tanstack/react-table";
3
+ import type { TableData, TableQueryFn, TableRequest, TableResponse } from "../../core/src/index";
4
+ /** 코어 `TableQueryFn` 과 같은 타입 — 기존 import 경로 호환을 위해 다시 내보낸다 */
5
+ export type { TableQueryFn };
6
+ /** `useQuery` 원본 옵션 통과구 — 이 훅이 직접 다루는 키는 뺀다 */
7
+ export type ServerTableQueryOptions<T> = Omit<UseQueryOptions<TableResponse<T>, Error>, "queryKey" | "queryFn" | "enabled" | "staleTime" | "placeholderData" | "throwOnError" | "select">;
8
+ export interface ServerTableDataOptions<T extends RowData> {
9
+ request: TableRequest;
10
+ queryFn: TableQueryFn<T>;
11
+ /** 캐시 구분용 접두 키. 화면마다 달라야 서로의 캐시를 밟지 않는다 */
12
+ queryKey?: readonly unknown[];
13
+ enabled?: boolean;
14
+ staleTime?: number;
15
+ /**
16
+ * @deprecated 효과 없음. 백엔드 `TableRequest` 에 `groupHeaderOnly` 가 없어서 wire 에 싣지
17
+ * 않는다 — `grouping` 이 있으면 항상 `groupExpansion: { path: [] … }` 로 최상위 그룹 노드를
18
+ * 받는다(`toWireRequest`). 옵션은 호출부 호환을 위해 받기만 한다.
19
+ */
20
+ groupHeaderOnly?: boolean;
21
+ /**
22
+ * 응답 가공 — **캐시에 들어가기 전** 한 번 적용된다.
23
+ * `select` 는 렌더마다 돌고 `onSuccess` 는 v5 에서 사라졌으므로 queryFn 안에서 적용한다.
24
+ */
25
+ transformResponse?: (response: TableResponse<T>, request: TableRequest) => TableResponse<T>;
26
+ /**
27
+ * 조건이 바뀌어 재조회하는 동안 이전 행을 유지한다 (기본 true).
28
+ * 끄면 조건이 바뀔 때마다 `isInitialLoading` 이 다시 true 가 되어 스켈레톤이 뜬다.
29
+ */
30
+ keepPreviousData?: boolean;
31
+ refetchInterval?: number | false;
32
+ /** 실패 재시도. 미지정이면 QueryClient 기본값 */
33
+ retry?: boolean | number | ((failureCount: number, error: Error) => boolean);
34
+ /** 나머지 `useQuery` 옵션 */
35
+ queryOptions?: ServerTableQueryOptions<T>;
36
+ }
37
+ export interface ServerTableData<T extends RowData> extends TableData<T> {
38
+ /** 재시도·캐시 무효화 등 세밀한 제어가 필요할 때 */
39
+ query: UseQueryResult<TableResponse<T>, Error>;
40
+ }
41
+ /**
42
+ * 2층 서버 모드 — 요청을 그대로 서버에 보낸다.
43
+ *
44
+ * 코어(`useTableData`)는 클라이언트 모드만 담당하고 의존성이 0이다. 서버 모드는
45
+ * 캐싱·취소가 필요해 react-query 를 쓰므로 이 패키지로 분리했다. 반환 타입은
46
+ * 같은 `TableData` 라서 3층·렌더러는 어느 쪽인지 몰라도 된다.
47
+ */
48
+ export declare function useServerTableData<T extends RowData>(options: ServerTableDataOptions<T>): ServerTableData<T>;
@@ -0,0 +1,64 @@
1
+ import { useMemo } from "react";
2
+ import { keepPreviousData as keepPreviousDataFn, useQuery, } from "@tanstack/react-query";
3
+ import { DEFAULT_TABLE_STALE_TIME } from "../../core/src/index";
4
+ import { toWireRequest } from "./wire";
5
+ const EMPTY = [];
6
+ /**
7
+ * 2층 서버 모드 — 요청을 그대로 서버에 보낸다.
8
+ *
9
+ * 코어(`useTableData`)는 클라이언트 모드만 담당하고 의존성이 0이다. 서버 모드는
10
+ * 캐싱·취소가 필요해 react-query 를 쓰므로 이 패키지로 분리했다. 반환 타입은
11
+ * 같은 `TableData` 라서 3층·렌더러는 어느 쪽인지 몰라도 된다.
12
+ */
13
+ export function useServerTableData(options) {
14
+ const { request, queryFn, queryKey, enabled = true, staleTime = DEFAULT_TABLE_STALE_TIME, transformResponse, keepPreviousData = true, refetchInterval, retry, queryOptions, } = options;
15
+ // 서버 계약(백엔드 `TableRequest`)에 맞춘 본문 — `grouping` 이 있으면 최상위 `groupExpansion`,
16
+ // `groupHeaderOnly` 는 제거. 그룹이 없으면 요청 객체 그대로(참조 동일)다.
17
+ const effectiveRequest = useMemo(() => toWireRequest(request), [request]);
18
+ const query = useQuery({
19
+ ...queryOptions,
20
+ queryKey: [...(queryKey ?? ["koko-table"]), effectiveRequest],
21
+ queryFn: async ({ signal }) => {
22
+ const response = await queryFn(effectiveRequest, { signal });
23
+ return transformResponse ? transformResponse(response, effectiveRequest) : response;
24
+ },
25
+ enabled,
26
+ staleTime,
27
+ // 조건을 바꿔 재조회하는 동안 이전 행을 유지한다 — 매번 빈 표가 번쩍이면
28
+ // 스크롤 위치도 잃고 화면이 튄다
29
+ placeholderData: keepPreviousData ? keepPreviousDataFn : undefined,
30
+ ...(refetchInterval !== undefined ? { refetchInterval } : {}),
31
+ ...(retry !== undefined ? { retry } : {}),
32
+ /**
33
+ * 조회 실패를 렌더 중 throw 하지 않는다.
34
+ *
35
+ * 상위 ErrorBoundary 가 테이블 트리를 파괴하면 리마운트가 캐시의 error 를
36
+ * 다시 읽어 즉시 재-throw 하므로 경계 리셋으로 복구가 안 된다.
37
+ * 에러는 결과에 실어 보내고 콘텐츠 구역이 제자리에서 재시도 UI 를 그린다.
38
+ */
39
+ throwOnError: false,
40
+ });
41
+ // react-query 는 결과를 렌더마다 새 추적 프록시로 돌려준다(`trackResult`). 그 객체를 의존성으로
42
+ // 두면 아무것도 안 바뀌어도 매 렌더 새 값이 되므로, 실제로 읽는 필드만 의존성에 둔다 —
43
+ // 읽는 순간 그 필드가 추적되어 바뀔 때 다시 렌더된다.
44
+ const { data: response, isLoading, isFetching, isError, error, refetch, fetchStatus, dataUpdatedAt } = query;
45
+ return useMemo(() => {
46
+ const rows = response?.data ?? EMPTY;
47
+ return {
48
+ rows,
49
+ // 서버가 총 건수를 안 주면 받은 만큼만 안다 — 페이지 수가 1로 보이는 게
50
+ // 없는 수를 지어내는 것보다 낫다
51
+ total: response?.meta?.total_count ?? rows.length,
52
+ meta: response?.meta ?? null,
53
+ groups: response?.groups ?? null,
54
+ isLoading: isLoading || isFetching,
55
+ isInitialLoading: isLoading,
56
+ isError,
57
+ error: error ?? undefined,
58
+ refetch: () => void refetch(),
59
+ mode: "server",
60
+ query,
61
+ };
62
+ // eslint-disable-next-line react-hooks/exhaustive-deps
63
+ }, [response, isLoading, isFetching, isError, error, refetch, fetchStatus, dataUpdatedAt]);
64
+ }
@@ -0,0 +1,16 @@
1
+ import type { TableRequest } from "../../core/src/index";
2
+ /**
3
+ * 서버에 실제로 보내는 본문 — 백엔드 `QueryBuilder/types.py` 의 `TableRequest` 모양으로 맞춘다.
4
+ *
5
+ * 기존 ERP `useTableQuery.buildParams` 와 같은 규칙이다:
6
+ * - `grouping` 이 있으면 최상위에 `groupExpansion: { path: [], offset: pageIndex*pageSize, limit: pageSize }`
7
+ * 를 싣는다 (`pageSize` = 페이지당 최상위 그룹 수). 서버는 이 값으로 최상위 그룹 노드
8
+ * (`groups.nodes`)를 돌려준다. 하위 확장(`useServerGrouping`)은 이미 `groupExpansion` 을
9
+ * 들고 오므로 그대로 둔다.
10
+ * - `groupHeaderOnly` 는 백엔드 `TableRequest` 에 없는 키라 wire 에서 뺀다 (서버는 무시했고,
11
+ * 있으면 `extra="forbid"` 검증에서 걸린다).
12
+ *
13
+ * `grouping` 이 없으면 요청 객체를 **그대로**(참조 동일) 돌려준다 — react-query 키가
14
+ * 매 렌더 바뀌지 않게 하려는 것이다.
15
+ */
16
+ export declare function toWireRequest(request: TableRequest): TableRequest;
@@ -0,0 +1,32 @@
1
+ import { DEFAULT_PAGINATION } from "../../core/src/index";
2
+ /**
3
+ * 서버에 실제로 보내는 본문 — 백엔드 `QueryBuilder/types.py` 의 `TableRequest` 모양으로 맞춘다.
4
+ *
5
+ * 기존 ERP `useTableQuery.buildParams` 와 같은 규칙이다:
6
+ * - `grouping` 이 있으면 최상위에 `groupExpansion: { path: [], offset: pageIndex*pageSize, limit: pageSize }`
7
+ * 를 싣는다 (`pageSize` = 페이지당 최상위 그룹 수). 서버는 이 값으로 최상위 그룹 노드
8
+ * (`groups.nodes`)를 돌려준다. 하위 확장(`useServerGrouping`)은 이미 `groupExpansion` 을
9
+ * 들고 오므로 그대로 둔다.
10
+ * - `groupHeaderOnly` 는 백엔드 `TableRequest` 에 없는 키라 wire 에서 뺀다 (서버는 무시했고,
11
+ * 있으면 `extra="forbid"` 검증에서 걸린다).
12
+ *
13
+ * `grouping` 이 없으면 요청 객체를 **그대로**(참조 동일) 돌려준다 — react-query 키가
14
+ * 매 렌더 바뀌지 않게 하려는 것이다.
15
+ */
16
+ export function toWireRequest(request) {
17
+ const grouping = request.grouping ?? [];
18
+ const hasGrouping = grouping.length > 0;
19
+ const hasLegacyKey = "groupHeaderOnly" in request;
20
+ if (!hasGrouping && !hasLegacyKey)
21
+ return request;
22
+ const { groupHeaderOnly: _dropped, ...rest } = request;
23
+ if (!hasGrouping)
24
+ return rest;
25
+ if (rest.groupExpansion)
26
+ return rest;
27
+ const { pageIndex, pageSize } = rest.pagination ?? DEFAULT_PAGINATION;
28
+ return {
29
+ ...rest,
30
+ groupExpansion: { path: [], offset: pageIndex * pageSize, limit: pageSize },
31
+ };
32
+ }
@@ -0,0 +1 @@
1
+ export * from "./query/src/index";
package/dist/query.js ADDED
@@ -0,0 +1,2 @@
1
+ // kokotable/query — 서버 모드
2
+ export * from "./query/src/index";
package/package.json ADDED
@@ -0,0 +1,125 @@
1
+ {
2
+ "name": "kokotable",
3
+ "version": "0.95.0",
4
+ "description": "헤드리스 테이블 코어 + MUI 렌더러 + 서버 모드 — 백엔드 QueryBuilder 와 같은 의미의 필터, 검색 상태, 확장 계약",
5
+ "keywords": [
6
+ "table",
7
+ "headless",
8
+ "mui",
9
+ "material-ui",
10
+ "react",
11
+ "tanstack-table",
12
+ "react-query",
13
+ "server-side"
14
+ ],
15
+ "license": "MIT",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/kokotu0/koko-table.git"
19
+ },
20
+ "type": "module",
21
+ "main": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "default": "./dist/index.js"
27
+ },
28
+ "./mui": {
29
+ "types": "./dist/mui.d.ts",
30
+ "default": "./dist/mui.js"
31
+ },
32
+ "./mui/virtual": {
33
+ "types": "./dist/mui-virtual.d.ts",
34
+ "default": "./dist/mui-virtual.js"
35
+ },
36
+ "./query": {
37
+ "types": "./dist/query.d.ts",
38
+ "default": "./dist/query.js"
39
+ },
40
+ "./contract/table-request.schema.json": "./contract/table-request.schema.json",
41
+ "./package.json": "./package.json"
42
+ },
43
+ "sideEffects": false,
44
+ "files": [
45
+ "dist",
46
+ "contract",
47
+ "README.md",
48
+ "LICENSE"
49
+ ],
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "koko": {
54
+ "contractVersion": "0.95.0"
55
+ },
56
+ "peerDependencies": {
57
+ "react": ">=18",
58
+ "react-dom": ">=18",
59
+ "@tanstack/react-table": "^8.21.0",
60
+ "@mui/material": "^6 || ^7",
61
+ "@mui/icons-material": "^6 || ^7",
62
+ "@emotion/react": "^11",
63
+ "@emotion/styled": "^11",
64
+ "@tanstack/react-query": "^5",
65
+ "@tanstack/react-virtual": "^3.10.0"
66
+ },
67
+ "peerDependenciesMeta": {
68
+ "@mui/material": {
69
+ "optional": true
70
+ },
71
+ "@mui/icons-material": {
72
+ "optional": true
73
+ },
74
+ "@emotion/react": {
75
+ "optional": true
76
+ },
77
+ "@emotion/styled": {
78
+ "optional": true
79
+ },
80
+ "@tanstack/react-query": {
81
+ "optional": true
82
+ },
83
+ "@tanstack/react-virtual": {
84
+ "optional": true
85
+ }
86
+ },
87
+ "workspaces": [
88
+ "packages/*"
89
+ ],
90
+ "scripts": {
91
+ "typecheck": "tsc -p tsconfig.build.json --noEmit && tsc -p packages/core/checks && tsc -p packages/mui/checks",
92
+ "test": "vitest run",
93
+ "storybook": "storybook dev -p 6006 --no-open",
94
+ "storybook:build": "storybook build -o storybook-static",
95
+ "bench": "tsx packages/core/bench/clientPipeline.bench.ts",
96
+ "contract:check": "vitest run packages/query/src/contract.test.ts",
97
+ "build": "rm -rf dist && tsc -p tsconfig.build.json",
98
+ "typecheck:tests": "tsc -p tsconfig.tests.json --noEmit",
99
+ "pack:check": "npm pack --dry-run",
100
+ "release:check": "npm run typecheck && npm run typecheck:tests && npm test && npm run build && npm run pack:check",
101
+ "live:check": "vitest run packages/query/src/live.test.ts",
102
+ "prepack": "npm run build"
103
+ },
104
+ "devDependencies": {
105
+ "@emotion/react": "^11.14.0",
106
+ "@emotion/styled": "^11.14.1",
107
+ "@mui/icons-material": "^7.3.11",
108
+ "@mui/material": "^7.3.11",
109
+ "@storybook/react-vite": "^9.1.20",
110
+ "@tanstack/react-query": "^5.102.2",
111
+ "@tanstack/react-table": "^8.21.3",
112
+ "@tanstack/react-virtual": "^3.14.10",
113
+ "@testing-library/react": "^16.3.2",
114
+ "@types/react": "^19.0.0",
115
+ "@vitejs/plugin-react": "^5.2.0",
116
+ "ajv": "^8.20.0",
117
+ "ajv-formats": "^3.0.1",
118
+ "jsdom": "^26.1.0",
119
+ "react-dom": "^19.2.8",
120
+ "storybook": "^9.1.20",
121
+ "typescript": "^5.7.2",
122
+ "vite": "^7.3.6",
123
+ "vitest": "^3.2.7"
124
+ }
125
+ }