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,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { MenuItem, Pagination, Stack, TextField, Typography } from "@mui/material";
3
+ import { toPaginationSource } from "../../../core/src/index";
4
+ import { useKokoTableConfig } from "../provider/KokoTableProvider";
5
+ /**
6
+ * 페이지네이션 구역.
7
+ *
8
+ * `PaginationSource` 만 요구하므로 테이블 인스턴스가 없어도 붙는다 —
9
+ * 카드 화면에서는 `paginationSource(search, data)` 를 넘긴다.
10
+ */
11
+ export function PaginationArea({ source, pageSizeOptions: pageSizeOptionsProp, showTotal = true, }) {
12
+ const { defaults } = useKokoTableConfig();
13
+ const pageSizeOptions = pageSizeOptionsProp ?? defaults.pageSizeOptions;
14
+ const pagination = toPaginationSource(source);
15
+ const { pageIndex, pageSize, total, pageCount } = pagination.getPagination();
16
+ // 선택지에 없는 크기(프리셋 복원 등)도 드롭다운에 보여야 사용자가 현재 값을 안다
17
+ const sizes = pageSizeOptions.includes(pageSize)
18
+ ? pageSizeOptions
19
+ : [...pageSizeOptions, pageSize].sort((a, b) => a - b);
20
+ const from = total === 0 ? 0 : pageIndex * pageSize + 1;
21
+ const to = Math.min((pageIndex + 1) * pageSize, total);
22
+ return (_jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", spacing: 2, sx: { py: 1, flexWrap: "wrap", gap: 1 }, children: [showTotal && (_jsx(Typography, { variant: "body2", color: "text.secondary", children: total === 0 ? "0건" : `${from.toLocaleString("ko-KR")}–${to.toLocaleString("ko-KR")} / ${total.toLocaleString("ko-KR")}건` })), _jsxs(Stack, { direction: "row", alignItems: "center", spacing: 2, children: [_jsx(TextField, { select: true, size: "small", variant: "standard", value: pageSize, onChange: (event) => pagination.setPageSize(Number(event.target.value)), sx: { width: 90 }, slotProps: { htmlInput: { "aria-label": "페이지당 행 수" } }, children: sizes.map((size) => (_jsxs(MenuItem, { value: size, children: [size, "\uD589"] }, size))) }), _jsx(Pagination, { size: "small", shape: "rounded", count: Math.max(pageCount, 1), page: pageIndex + 1, onChange: (_event, page) => pagination.setPageIndex(page - 1), disabled: pageCount <= 1 })] })] }));
23
+ }
@@ -0,0 +1,18 @@
1
+ import type { PivotResult } from "../../../core/src/index";
2
+ export interface PivotTableProps {
3
+ result: PivotResult;
4
+ /** 보여줄 값 키. 미지정이면 첫 번째 하나만 (여러 개면 셀이 빽빽해진다) */
5
+ valueKey?: string;
6
+ formatValue?: (value: unknown) => string;
7
+ /** 총계 열 표시 */
8
+ showTotal?: boolean;
9
+ maxHeight?: number | string;
10
+ }
11
+ /**
12
+ * 피벗 결과 표.
13
+ *
14
+ * 행 축은 트리라 접고 펼 수 있고, 열 축은 중첩 헤더로 그린다.
15
+ * 두 축이 동등하므로 전환은 `transposePivot(spec)` 으로 데이터 쪽에서 처리한다 —
16
+ * 이 컴포넌트는 축의 의미를 모른다.
17
+ */
18
+ export declare function PivotTable({ result, valueKey, formatValue, showTotal, maxHeight, }: PivotTableProps): import("react").JSX.Element;
@@ -0,0 +1,100 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Fragment, useMemo, useState } from "react";
3
+ import { Alert, Box, IconButton, Stack, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography, } from "@mui/material";
4
+ import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
5
+ import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight";
6
+ const defaultFormat = (value) => {
7
+ if (value === null || value === undefined)
8
+ return "";
9
+ if (typeof value === "number") {
10
+ return Number.isInteger(value) ? value.toLocaleString("ko-KR") : value.toFixed(2);
11
+ }
12
+ return String(value);
13
+ };
14
+ /** 헤더 레벨별로 노드를 모은다 — 중첩 헤더를 행으로 펼치기 위해 */
15
+ function headerLevels(nodes) {
16
+ const levels = [];
17
+ const walk = (list, depth) => {
18
+ if (list.length === 0)
19
+ return;
20
+ if (!levels[depth])
21
+ levels[depth] = [];
22
+ levels[depth].push(...list);
23
+ for (const node of list)
24
+ if (node.children)
25
+ walk(node.children, depth + 1);
26
+ };
27
+ walk(nodes, 0);
28
+ return levels;
29
+ }
30
+ /** 이 노드가 차지하는 leaf 열 수 */
31
+ function leafSpan(node) {
32
+ if (!node.children || node.children.length === 0)
33
+ return 1;
34
+ return node.children.reduce((sum, child) => sum + leafSpan(child), 0);
35
+ }
36
+ function collectRowKeys(rows) {
37
+ const keys = [];
38
+ const walk = (list) => {
39
+ for (const row of list) {
40
+ keys.push(row.key);
41
+ if (row.children)
42
+ walk(row.children);
43
+ }
44
+ };
45
+ walk(rows);
46
+ return keys;
47
+ }
48
+ /**
49
+ * 피벗 결과 표.
50
+ *
51
+ * 행 축은 트리라 접고 펼 수 있고, 열 축은 중첩 헤더로 그린다.
52
+ * 두 축이 동등하므로 전환은 `transposePivot(spec)` 으로 데이터 쪽에서 처리한다 —
53
+ * 이 컴포넌트는 축의 의미를 모른다.
54
+ */
55
+ export function PivotTable({ result, valueKey, formatValue = defaultFormat, showTotal = true, maxHeight, }) {
56
+ const key = valueKey ?? result.valueKeys[0];
57
+ const levels = useMemo(() => headerLevels(result.columns), [result.columns]);
58
+ const [collapsed, setCollapsed] = useState(new Set());
59
+ const allKeys = useMemo(() => collectRowKeys(result.rows), [result.rows]);
60
+ void allKeys;
61
+ /**
62
+ * 열 합계. 코어가 `PivotResult.colTotals`(leaf 키 → 값 키 → 집계값) 를 주면 그것을 쓴다 —
63
+ * AVG/COUNT_DISTINCT 는 행 합계를 더해서 만들 수 없다. 아직 없으면 SUM 에서만 맞는
64
+ * 예전 방식(행 값 합산)으로 되돌아간다.
65
+ */
66
+ const colTotals = result.colTotals;
67
+ if (!key)
68
+ return _jsx(Alert, { severity: "warning", children: "\uD45C\uC2DC\uD560 \uC9D1\uACC4 \uAC12\uC774 \uC5C6\uC2B5\uB2C8\uB2E4" });
69
+ const toggle = (rowKey) => setCollapsed((prev) => {
70
+ const next = new Set(prev);
71
+ if (next.has(rowKey))
72
+ next.delete(rowKey);
73
+ else
74
+ next.add(rowKey);
75
+ return next;
76
+ });
77
+ const renderRows = (rows) => rows.map((row) => {
78
+ const isCollapsed = collapsed.has(row.key);
79
+ const hasChildren = !!row.children && row.children.length > 0;
80
+ return (_jsxs(Fragment, { children: [_jsxs(TableRow, { hover: true, children: [_jsx(TableCell, { sx: {
81
+ pl: 1 + row.depth * 2,
82
+ whiteSpace: "nowrap",
83
+ position: "sticky", left: 0, zIndex: 1,
84
+ backgroundColor: "background.paper",
85
+ fontWeight: hasChildren ? 600 : 400,
86
+ }, children: _jsxs(Stack, { direction: "row", alignItems: "center", spacing: 0.5, children: [hasChildren ? (_jsx(IconButton, { size: "small", "aria-label": isCollapsed ? "펼치기" : "접기", onClick: () => toggle(row.key), children: isCollapsed ? _jsx(KeyboardArrowRightIcon, { fontSize: "small" }) : _jsx(KeyboardArrowDownIcon, { fontSize: "small" }) })) : (_jsx(Box, { sx: { width: 30 } })), _jsx("span", { children: row.label })] }) }), result.leafKeys.map((leafKey) => (_jsx(TableCell, { align: "right", sx: { whiteSpace: "nowrap" }, children: formatValue(row.cells[leafKey]?.[key]) }, leafKey))), showTotal && (_jsx(TableCell, { align: "right", sx: { fontWeight: 600, whiteSpace: "nowrap" }, children: formatValue(row.total[key]) }))] }), hasChildren && !isCollapsed && renderRows(row.children)] }, row.key));
87
+ });
88
+ return (_jsxs(Stack, { spacing: 1, children: [result.droppedColumns > 0 && (_jsxs(Alert, { severity: "info", sx: { py: 0 }, children: ["\uC5F4\uC774 \uB9CE\uC544 ", result.droppedColumns, "\uAC1C\uB97C \uC81C\uC678\uD588\uC2B5\uB2C8\uB2E4 \u2014 \uC0C1\uD55C\uC744 \uC62C\uB9AC\uAC70\uB098 \uC870\uAC74\uC744 \uC881\uD600 \uC8FC\uC138\uC694"] })), _jsx(TableContainer, { sx: { maxHeight, border: "1px solid", borderColor: "divider", borderRadius: 1 }, children: _jsxs(Table, { stickyHeader: true, size: "small", children: [_jsx(TableHead, { children: levels.map((level, depth) => (_jsxs(TableRow, { children: [depth === 0 && (_jsx(TableCell, { rowSpan: levels.length, sx: {
89
+ position: "sticky", left: 0, zIndex: 3,
90
+ backgroundColor: "background.paper", fontWeight: 600,
91
+ } })), level.map((node) => (_jsx(TableCell, { align: "center", colSpan: leafSpan(node), sx: { fontWeight: 600, whiteSpace: "nowrap", backgroundColor: "background.paper" }, children: node.label }, node.key))), depth === 0 && showTotal && (_jsx(TableCell, { rowSpan: levels.length, align: "right", sx: { fontWeight: 700, backgroundColor: "background.paper", whiteSpace: "nowrap" }, children: "\uD569\uACC4" }))] }, depth))) }), _jsx(TableBody, { children: result.rows.length === 0 ? (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: result.leafKeys.length + (showTotal ? 2 : 1), sx: { py: 6, textAlign: "center" }, children: _jsx(Typography, { variant: "body2", color: "text.secondary", children: "\uD45C\uC2DC\uD560 \uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4" }) }) })) : (_jsxs(_Fragment, { children: [renderRows(result.rows), showTotal && (_jsxs(TableRow, { sx: { backgroundColor: "action.hover" }, children: [_jsx(TableCell, { sx: { fontWeight: 700, position: "sticky", left: 0, zIndex: 1, backgroundColor: "inherit" }, children: "\uD569\uACC4" }), result.leafKeys.map((leafKey) => {
92
+ const columnTotal = colTotals
93
+ ? colTotals[leafKey]?.[key]
94
+ : result.rows.reduce((sum, row) => {
95
+ const value = row.cells[leafKey]?.[key];
96
+ return typeof value === "number" ? sum + value : sum;
97
+ }, 0);
98
+ return (_jsx(TableCell, { align: "right", sx: { fontWeight: 700 }, children: formatValue(columnTotal) }, leafKey));
99
+ }), _jsx(TableCell, { align: "right", sx: { fontWeight: 700 }, children: formatValue(result.grandTotal[key]) })] }))] })) })] }) })] }));
100
+ }
@@ -0,0 +1,184 @@
1
+ import { type ComponentType, type ReactNode } from "react";
2
+ import type { Cell, Column, Row, RowData, Table } from "@tanstack/react-table";
3
+ import type { AggregateResult, CellRenderProps as CoreCellRenderProps, ColumnDataType, ColumnMeta, FilterRender, FilterVariant, GroupTreeNode } from "../../../core/src/index";
4
+ import type { HeaderCellProps } from "../content/HeaderCell";
5
+ import type { ColumnMenuProps } from "../content/ColumnMenu";
6
+ import type { TableErrorFallbackProps } from "../content/TableErrorFallback";
7
+ import type { EditCellProps } from "../content/EditCell";
8
+ import type { AggregateChipProps } from "../grouping/AggregateChip";
9
+ import type { Density } from "../content/density";
10
+ import type { GroupRowLayout, GroupedColumnMode } from "../content/TableContent";
11
+ import { type KokoTableLabels, type KokoTableLabelsInput } from "./labels";
12
+ import { applyPatch, toRegistry, type AggregationDef, type CellRendererDef, type ExportFormatterDef, type Registry } from "../registry";
13
+ import type { HeaderDef } from "../headers/types";
14
+ import { type ColumnMenuItemDef, type ColumnMenuPatch } from "../menus/columnMenu";
15
+ import { type RowMenuItemDef, type RowMenuPatch } from "../menus/rowMenu";
16
+ export interface EmptyStateProps {
17
+ message: ReactNode;
18
+ table: Table<any>;
19
+ columnCount: number;
20
+ }
21
+ export interface LoadingSkeletonProps {
22
+ rows: number;
23
+ columns: Array<Column<any, unknown>>;
24
+ columnCount: number;
25
+ size: "small" | "medium";
26
+ }
27
+ /** 그룹 행 전체를 교체할 때 받는 것. `<TableRow>` 하나를 돌려줘야 한다 */
28
+ export interface GroupRowRenderContext<T extends RowData = any> {
29
+ node: GroupTreeNode<T>;
30
+ depth: number;
31
+ /** 지금 그려지는 순서의 리프 컬럼 (열 가상화·그룹 컬럼 재배치 반영) */
32
+ columns: Array<Column<T, unknown>>;
33
+ aggregates: AggregateResult;
34
+ toggle: () => void;
35
+ expanded: boolean;
36
+ table: Table<T>;
37
+ columnCount: number;
38
+ /** 이 depth 의 그룹 기준 컬럼 (없으면 숨김·제거된 것) */
39
+ groupColumn?: Column<T, unknown>;
40
+ /** 기본 규칙으로 해석한 그룹값 라벨 */
41
+ groupValue: ReactNode;
42
+ /** 기본 행 props — `data-index`·ref·onClick·sx. 그대로 펼치면 가상화·키보드가 유지된다 */
43
+ rowProps: Record<string, unknown>;
44
+ }
45
+ export interface DetailPanelRowContext<T extends RowData = any> {
46
+ row: Row<T>;
47
+ table: Table<T>;
48
+ columnCount: number;
49
+ /** `renderDetailPanel(row, table)` 결과 */
50
+ content: ReactNode;
51
+ }
52
+ export interface KokoTableComponents {
53
+ HeaderCell: ComponentType<HeaderCellProps<any>>;
54
+ ColumnMenu: ComponentType<ColumnMenuProps<any>>;
55
+ EmptyState: ComponentType<EmptyStateProps>;
56
+ ErrorFallback: ComponentType<TableErrorFallbackProps>;
57
+ /** `<tr>` 들을 돌려준다 — `<tbody>` 안에 놓인다 */
58
+ LoadingSkeleton: ComponentType<LoadingSkeletonProps>;
59
+ AggregateChip: ComponentType<AggregateChipProps>;
60
+ /** 그룹 행 전체 교체 */
61
+ GroupRow: (ctx: GroupRowRenderContext<any>) => ReactNode;
62
+ /** 펼친 행 아래 상세 패널 행 전체 교체 */
63
+ DetailPanelRow: (ctx: DetailPanelRowContext<any>) => ReactNode;
64
+ EditCell: ComponentType<EditCellProps<any>>;
65
+ }
66
+ /** Provider 셀 렌더러가 받는 것 — 코어 `CellRenderProps` 에 인스턴스를 더한 것 */
67
+ export interface CellRendererProps<T extends RowData = any> extends CoreCellRenderProps<T> {
68
+ cell: Cell<T, unknown>;
69
+ column: Column<T, unknown>;
70
+ table: Table<T>;
71
+ meta?: ColumnMeta;
72
+ /** `link` 렌더러에만 — `meta.link.to()` 결과 */
73
+ href?: string;
74
+ }
75
+ export type CellRendererKey = ColumnDataType | "link" | "chip" | "placeholder";
76
+ export type CellRenderer<T extends RowData = any> = (props: CellRendererProps<T>) => ReactNode;
77
+ export type KokoCellRenderers = Partial<Record<CellRendererKey, CellRenderer>>;
78
+ export type KokoFilterInputs = Partial<Record<FilterVariant, FilterRender<any>>>;
79
+ export interface KokoTableDefaults {
80
+ density?: Density;
81
+ pageSizeOptions: number[];
82
+ skeletonRows: number;
83
+ groupRowLayout: GroupRowLayout;
84
+ groupedColumnMode: GroupedColumnMode;
85
+ enableColumnMenu: boolean;
86
+ stickyHeader: boolean;
87
+ maxHeight?: number | string;
88
+ /** 검색 입력 debounce(ms) — 값만 내려준다. 실제 적용은 검색 훅·입력 컴포넌트 몫 */
89
+ debounceMs: number;
90
+ }
91
+ export declare const DEFAULT_TABLE_DEFAULTS: KokoTableDefaults;
92
+ /** 필터 kind 의 표시 부분 — 의미(predicate·serialize)는 core 의 kind 가, 편집기·칩은 여기가 맡는다 */
93
+ export interface FilterKindUi {
94
+ editor?: FilterRender<any>;
95
+ chip?: (value: unknown, operator: string) => ReactNode;
96
+ }
97
+ export type KokoFilterKinds = Record<string, FilterKindUi>;
98
+ /** 해석된 메뉴 레지스트리 — `ColumnMenu`/`TableContent` 가 항목을 여기서 꺼낸다 */
99
+ export interface KokoTableMenus {
100
+ column: Registry<ColumnMenuItemDef<any>>;
101
+ row: Registry<RowMenuItemDef<any>>;
102
+ }
103
+ export interface KokoTableMenusInput {
104
+ column?: ColumnMenuPatch<any>;
105
+ row?: RowMenuPatch<any>;
106
+ }
107
+ /** 셀 렌더러 · 집계 · export 포맷터 레지스트리 — 항목 타입은 각 담당 파일이 채운다 */
108
+ export interface KokoTableRegistries {
109
+ cells: Registry<CellRendererDef>;
110
+ aggregations: Registry<AggregationDef>;
111
+ exportFormatters: Registry<ExportFormatterDef>;
112
+ }
113
+ /** 컬럼 메뉴 "필터 열기" — 있을 때만 항목이 보인다 */
114
+ export type OpenFilterHandler = (column: Column<any, unknown>, table: Table<any>) => void;
115
+ /** 해석된 설정 — 라벨·기본값·레지스트리는 항상 채워져 있고, 컴포넌트·렌더러는 덮어쓴 것만 있다 */
116
+ export interface KokoTableConfig {
117
+ components: Partial<KokoTableComponents>;
118
+ /** dataType 별 셀 렌더러 맵 (기존 통로). 배열/레지스트리로 준 정의는 `registries.cells` 에 있다 */
119
+ cellRenderers: KokoCellRenderers;
120
+ filterInputs: KokoFilterInputs;
121
+ labels: KokoTableLabels;
122
+ defaults: KokoTableDefaults;
123
+ menus: KokoTableMenus;
124
+ /** Provider 헤더 정의 — 안쪽 Provider 것이 앞에 온다 (`when` 이 참인 첫 정의가 이긴다) */
125
+ headers: Array<HeaderDef<any>>;
126
+ filterKinds: KokoFilterKinds;
127
+ registries: KokoTableRegistries;
128
+ onOpenFilter?: OpenFilterHandler;
129
+ }
130
+ export interface KokoTableConfigInput {
131
+ components?: Partial<KokoTableComponents>;
132
+ /** dataType 맵(기존) 또는 `CellRendererDef[]`/레지스트리(설계 4절) — 둘 다 받는다 */
133
+ cellRenderers?: KokoCellRenderers | CellRendererDef[] | Registry<CellRendererDef>;
134
+ filterInputs?: KokoFilterInputs;
135
+ labels?: KokoTableLabelsInput;
136
+ defaults?: Partial<KokoTableDefaults>;
137
+ /** 컬럼·행 컨텍스트 메뉴 add · remove · replace · order */
138
+ menus?: KokoTableMenusInput;
139
+ headers?: Array<HeaderDef<any>>;
140
+ filterKinds?: KokoFilterKinds;
141
+ aggregations?: AggregationDef[] | Registry<AggregationDef>;
142
+ exportFormatters?: ExportFormatterDef[] | Registry<ExportFormatterDef>;
143
+ onOpenFilter?: OpenFilterHandler;
144
+ }
145
+ export declare const DEFAULT_KOKO_TABLE_CONFIG: KokoTableConfig;
146
+ /**
147
+ * 부모 설정 위에 입력을 병합한다 — 항목별 얕은 병합(지정한 키만 바뀐다).
148
+ * 메뉴 패치는 부모 레지스트리에서 `with()` 로 파생(안쪽이 바깥 위에 쌓인다), 헤더는 안쪽 정의가 앞에 온다.
149
+ */
150
+ export declare function mergeKokoTableConfig(base: KokoTableConfig, input?: KokoTableConfigInput): KokoTableConfig;
151
+ export interface KokoTableProviderProps extends KokoTableConfigInput {
152
+ children?: ReactNode;
153
+ }
154
+ /**
155
+ * 덮어쓰기 계층의 입구 — 단일 진입점 (설계 5절).
156
+ *
157
+ * 우선순위는 **컬럼 단위 선언 → Provider → 기본값** 이다:
158
+ * - 필터 입력: `filter.render` → `filterInputs[variant]` / `filterKinds[kind].editor` → variant 기본 컴포넌트
159
+ * - 셀: 컬럼 `cell`(코어 포맷터 포함) 결과를 `cellRenderers[dataType]` 이 받아 감싼다 → `chip`/`link`/`placeholder`
160
+ * - 헤더: `meta.header`(id 또는 `defineHeader`) → `headers[]` 중 `when` 이 참인 첫 정의 → 기본 헤더
161
+ * - 메뉴: `menus.column` / `menus.row` 패치가 내장 세트 위에 쌓인다 → `TableContent columnMenuItems`/`rowMenuItems` 가 마지막
162
+ * - 문구: `labels` (연산자·UI·집계) — 다국어 통로
163
+ * - 기본값: `TableContent`/`PaginationArea` 의 미지정 prop 이 `defaults` 를 본다
164
+ *
165
+ * 중첩하면 안쪽 Provider 가 바깥 설정 위에 병합된다 — 화면 하나만 영어로 바꾸는 식이 된다.
166
+ */
167
+ export declare function KokoTableProvider({ children, ...input }: KokoTableProviderProps): import("react").JSX.Element;
168
+ /** 가장 가까운 Provider 의 해석된 설정. Provider 가 없으면 기본값 */
169
+ export declare function useKokoTableConfig(): KokoTableConfig;
170
+ /** 정의 배열·레지스트리·undefined 를 레지스트리로 — 소비자가 자기 확장점에 같은 규칙을 쓸 때 */
171
+ export { toRegistry, applyPatch };
172
+ /**
173
+ * `props ?? defaults` — `TableContent`/`PaginationArea` 가 미지정 prop 을 Provider 기본값으로 채울 때 쓴다.
174
+ * 명시한 prop(undefined 가 아닌 것)은 그대로다.
175
+ */
176
+ export declare function resolveTableProps<P extends {
177
+ density?: Density;
178
+ skeletonRows?: number;
179
+ groupRowLayout?: GroupRowLayout;
180
+ groupedColumnMode?: GroupedColumnMode;
181
+ enableColumnMenu?: boolean;
182
+ stickyHeader?: boolean;
183
+ maxHeight?: number | string;
184
+ }>(props: P, defaults: KokoTableDefaults): P;
@@ -0,0 +1,118 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext, useMemo } from "react";
3
+ import { DEFAULT_LABELS, mergeLabels } from "./labels";
4
+ import { applyPatch, createRegistry, isRegistry, toRegistry, } from "../registry";
5
+ import { columnMenuRegistry } from "../menus/columnMenu";
6
+ import { rowMenuRegistry } from "../menus/rowMenu";
7
+ export const DEFAULT_TABLE_DEFAULTS = {
8
+ pageSizeOptions: [15, 30, 50, 100],
9
+ skeletonRows: 5,
10
+ groupRowLayout: "columns",
11
+ groupedColumnMode: "reorder",
12
+ enableColumnMenu: true,
13
+ stickyHeader: true,
14
+ debounceMs: 300,
15
+ };
16
+ export const DEFAULT_KOKO_TABLE_CONFIG = {
17
+ components: {},
18
+ cellRenderers: {},
19
+ filterInputs: {},
20
+ labels: DEFAULT_LABELS,
21
+ defaults: DEFAULT_TABLE_DEFAULTS,
22
+ menus: { column: columnMenuRegistry, row: rowMenuRegistry },
23
+ headers: [],
24
+ filterKinds: {},
25
+ registries: {
26
+ cells: createRegistry(),
27
+ aggregations: createRegistry(),
28
+ exportFormatters: createRegistry(),
29
+ },
30
+ };
31
+ function isCellRendererMap(value) {
32
+ return !!value && !Array.isArray(value) && !isRegistry(value);
33
+ }
34
+ /** 배열이면 부모 레지스트리에 add, 레지스트리면 그것으로 교체 */
35
+ function mergeRegistry(base, input) {
36
+ if (!input)
37
+ return base;
38
+ if (isRegistry(input))
39
+ return input;
40
+ return base.with({ add: input });
41
+ }
42
+ /**
43
+ * 부모 설정 위에 입력을 병합한다 — 항목별 얕은 병합(지정한 키만 바뀐다).
44
+ * 메뉴 패치는 부모 레지스트리에서 `with()` 로 파생(안쪽이 바깥 위에 쌓인다), 헤더는 안쪽 정의가 앞에 온다.
45
+ */
46
+ export function mergeKokoTableConfig(base, input) {
47
+ if (!input)
48
+ return base;
49
+ const cellMap = isCellRendererMap(input.cellRenderers) ? input.cellRenderers : undefined;
50
+ const cellDefs = isCellRendererMap(input.cellRenderers) ? undefined : input.cellRenderers;
51
+ return {
52
+ components: { ...base.components, ...input.components },
53
+ cellRenderers: { ...base.cellRenderers, ...cellMap },
54
+ filterInputs: { ...base.filterInputs, ...input.filterInputs },
55
+ labels: mergeLabels(base.labels, input.labels),
56
+ defaults: { ...base.defaults, ...input.defaults },
57
+ menus: {
58
+ column: input.menus?.column ? base.menus.column.with(input.menus.column) : base.menus.column,
59
+ row: input.menus?.row ? base.menus.row.with(input.menus.row) : base.menus.row,
60
+ },
61
+ headers: input.headers ? [...input.headers, ...base.headers] : base.headers,
62
+ filterKinds: { ...base.filterKinds, ...input.filterKinds },
63
+ registries: {
64
+ cells: mergeRegistry(base.registries.cells, cellDefs),
65
+ aggregations: mergeRegistry(base.registries.aggregations, input.aggregations),
66
+ exportFormatters: mergeRegistry(base.registries.exportFormatters, input.exportFormatters),
67
+ },
68
+ onOpenFilter: input.onOpenFilter ?? base.onOpenFilter,
69
+ };
70
+ }
71
+ const KokoTableContext = createContext(DEFAULT_KOKO_TABLE_CONFIG);
72
+ /**
73
+ * 덮어쓰기 계층의 입구 — 단일 진입점 (설계 5절).
74
+ *
75
+ * 우선순위는 **컬럼 단위 선언 → Provider → 기본값** 이다:
76
+ * - 필터 입력: `filter.render` → `filterInputs[variant]` / `filterKinds[kind].editor` → variant 기본 컴포넌트
77
+ * - 셀: 컬럼 `cell`(코어 포맷터 포함) 결과를 `cellRenderers[dataType]` 이 받아 감싼다 → `chip`/`link`/`placeholder`
78
+ * - 헤더: `meta.header`(id 또는 `defineHeader`) → `headers[]` 중 `when` 이 참인 첫 정의 → 기본 헤더
79
+ * - 메뉴: `menus.column` / `menus.row` 패치가 내장 세트 위에 쌓인다 → `TableContent columnMenuItems`/`rowMenuItems` 가 마지막
80
+ * - 문구: `labels` (연산자·UI·집계) — 다국어 통로
81
+ * - 기본값: `TableContent`/`PaginationArea` 의 미지정 prop 이 `defaults` 를 본다
82
+ *
83
+ * 중첩하면 안쪽 Provider 가 바깥 설정 위에 병합된다 — 화면 하나만 영어로 바꾸는 식이 된다.
84
+ */
85
+ export function KokoTableProvider({ children, ...input }) {
86
+ const parent = useContext(KokoTableContext);
87
+ const { components, cellRenderers, filterInputs, labels, defaults, menus, headers, filterKinds, aggregations, exportFormatters, onOpenFilter, } = input;
88
+ const value = useMemo(() => mergeKokoTableConfig(parent, {
89
+ components, cellRenderers, filterInputs, labels, defaults, menus, headers, filterKinds, aggregations,
90
+ exportFormatters, onOpenFilter,
91
+ }), [
92
+ parent, components, cellRenderers, filterInputs, labels, defaults, menus, headers, filterKinds, aggregations,
93
+ exportFormatters, onOpenFilter,
94
+ ]);
95
+ return _jsx(KokoTableContext.Provider, { value: value, children: children });
96
+ }
97
+ /** 가장 가까운 Provider 의 해석된 설정. Provider 가 없으면 기본값 */
98
+ export function useKokoTableConfig() {
99
+ return useContext(KokoTableContext);
100
+ }
101
+ /** 정의 배열·레지스트리·undefined 를 레지스트리로 — 소비자가 자기 확장점에 같은 규칙을 쓸 때 */
102
+ export { toRegistry, applyPatch };
103
+ /**
104
+ * `props ?? defaults` — `TableContent`/`PaginationArea` 가 미지정 prop 을 Provider 기본값으로 채울 때 쓴다.
105
+ * 명시한 prop(undefined 가 아닌 것)은 그대로다.
106
+ */
107
+ export function resolveTableProps(props, defaults) {
108
+ return {
109
+ ...props,
110
+ density: props.density ?? defaults.density,
111
+ skeletonRows: props.skeletonRows ?? defaults.skeletonRows,
112
+ groupRowLayout: props.groupRowLayout ?? defaults.groupRowLayout,
113
+ groupedColumnMode: props.groupedColumnMode ?? defaults.groupedColumnMode,
114
+ enableColumnMenu: props.enableColumnMenu ?? defaults.enableColumnMenu,
115
+ stickyHeader: props.stickyHeader ?? defaults.stickyHeader,
116
+ maxHeight: props.maxHeight ?? defaults.maxHeight,
117
+ };
118
+ }
@@ -0,0 +1,85 @@
1
+ import type { AggFnKey, FilterOperator } from "../../../core/src/index";
2
+ /**
3
+ * 연산자 한국어 라벨 — 없는 것은 키를 그대로 보여준다.
4
+ * `KokoTableProvider({ labels: { operators } })` 로 덮어쓴다 (다국어 통로).
5
+ */
6
+ export declare const OPERATOR_LABELS: Partial<Record<FilterOperator, string>>;
7
+ /**
8
+ * UI 문구. 문자열이거나, 값이 끼는 문구는 함수다.
9
+ * 렌더러 패키지 안의 모든 고정 문구는 여기서 나온다 — 소비자는 Provider 로 일부만 바꾼다.
10
+ */
11
+ export interface KokoUiLabels {
12
+ search: string;
13
+ reset: string;
14
+ filterTitle: string;
15
+ detailConditions: string;
16
+ /** 연산자 버튼 툴팁 — `filterMode("포함")` */
17
+ filterMode: (operatorLabel: string) => string;
18
+ changeFilterMode: string;
19
+ empty: string;
20
+ loading: string;
21
+ retry: string;
22
+ loadFailed: string;
23
+ badRequest: string;
24
+ resetFilters: string;
25
+ /** 서버 그룹핑 "더 보기" */
26
+ loadMore: (loaded: number, total?: number) => string;
27
+ /** 그룹 트리에는 있는데 행 모델에 없을 때 */
28
+ missingRows: string;
29
+ expand: string;
30
+ collapse: string;
31
+ expandAll: string;
32
+ collapseAll: string;
33
+ selectAll: string;
34
+ selectRow: string;
35
+ expandGroup: string;
36
+ collapseGroup: string;
37
+ /** "2단계까지 펼치기 (지역)" */
38
+ expandToDepth: (depth: number, columnName: string) => string;
39
+ expandChildren: string;
40
+ /** 헤더 정렬 툴팁 */
41
+ sortHint: string;
42
+ /** 컬럼 메뉴 버튼 aria — 컬럼 id 뒤에 붙는다 */
43
+ columnMenu: string;
44
+ resizeHandle: (columnId: string) => string;
45
+ sortAsc: string;
46
+ sortDesc: string;
47
+ clearSort: string;
48
+ pinLeft: string;
49
+ pinRight: string;
50
+ unpin: string;
51
+ moveLeft: string;
52
+ moveRight: string;
53
+ hide: string;
54
+ groupBy: string;
55
+ ungroup: string;
56
+ resetColumnSize: string;
57
+ /** 컬럼 메뉴 "필터 열기" (`onOpenFilter` 가 있을 때) */
58
+ openFilter: string;
59
+ /** 컬럼 메뉴 "헤더 복사" */
60
+ copyHeader: string;
61
+ /** 헤더 메뉴 "집계" 항목·상세 설정 버튼 */
62
+ aggregation: string;
63
+ aggregationSettings: string;
64
+ /** 행 메뉴 "행 복사" */
65
+ copyRow: string;
66
+ }
67
+ export declare const DEFAULT_UI_LABELS: KokoUiLabels;
68
+ /** 해석된 라벨 — Provider 가 기본값과 병합해 내려준다 */
69
+ export interface KokoTableLabels {
70
+ operators: Partial<Record<FilterOperator, string>>;
71
+ aggregations: Record<AggFnKey, string>;
72
+ aggregationsShort: Record<AggFnKey, string>;
73
+ ui: KokoUiLabels;
74
+ }
75
+ /** Provider 에 넘기는 부분 덮어쓰기 */
76
+ export interface KokoTableLabelsInput {
77
+ operators?: Partial<Record<FilterOperator, string>>;
78
+ aggregations?: Partial<Record<AggFnKey, string>>;
79
+ aggregationsShort?: Partial<Record<AggFnKey, string>>;
80
+ ui?: Partial<KokoUiLabels>;
81
+ }
82
+ export declare const DEFAULT_LABELS: KokoTableLabels;
83
+ export declare function mergeLabels(base: KokoTableLabels, input?: KokoTableLabelsInput): KokoTableLabels;
84
+ /** 연산자 라벨 — `labels` 를 주면 그것을, 없으면 기본 한국어 표를 본다 */
85
+ export declare function operatorLabel(operator: FilterOperator, labels?: Partial<Record<FilterOperator, string>>): string;
@@ -0,0 +1,104 @@
1
+ import { AGG_LABELS, AGG_SHORT_LABELS } from "../../../core/src/index";
2
+ /**
3
+ * 연산자 한국어 라벨 — 없는 것은 키를 그대로 보여준다.
4
+ * `KokoTableProvider({ labels: { operators } })` 로 덮어쓴다 (다국어 통로).
5
+ */
6
+ export const OPERATOR_LABELS = {
7
+ fuzzy: "포함(공백무시)",
8
+ contains: "포함",
9
+ notContains: "미포함",
10
+ equals: "같음",
11
+ notEquals: "다름",
12
+ startsWith: "시작",
13
+ endsWith: "끝",
14
+ empty: "비어 있음",
15
+ notEmpty: "비어 있지 않음",
16
+ isEmpty: "비어 있음",
17
+ between: "범위(초과·미만)",
18
+ betweenInclusive: "범위",
19
+ outsideRange: "범위 밖",
20
+ lessThan: "미만",
21
+ lessThanOrEqualTo: "이하",
22
+ greaterThan: "초과",
23
+ greaterThanOrEqualTo: "이상",
24
+ inPeriod: "기간",
25
+ inArray: "포함",
26
+ notInArray: "제외",
27
+ in: "포함",
28
+ notIn: "제외",
29
+ hasAny: "하나라도",
30
+ hasAll: "모두",
31
+ hasChild: "자식 있음",
32
+ hasNotChild: "자식 없음",
33
+ linearContains: "수량 포함",
34
+ linearExists: "존재",
35
+ linearExact: "정확히",
36
+ scheduleContains: "그 날 포함",
37
+ scheduleOverlaps: "기간 겹침",
38
+ };
39
+ export const DEFAULT_UI_LABELS = {
40
+ search: "검색",
41
+ reset: "초기화",
42
+ filterTitle: "검색 조건",
43
+ detailConditions: "상세 조건",
44
+ filterMode: (label) => `필터 방식: ${label}`,
45
+ changeFilterMode: "필터 방식 변경",
46
+ empty: "표시할 데이터가 없습니다",
47
+ loading: "불러오는 중…",
48
+ retry: "다시 시도",
49
+ loadFailed: "조회에 실패했습니다",
50
+ badRequest: "필터를 해석할 수 없습니다",
51
+ resetFilters: "필터 초기화",
52
+ loadMore: (loaded, total) => (total != null ? `더 보기 (${loaded} / ${total})` : `더 보기 (${loaded})`),
53
+ missingRows: "행을 테이블에 전달하지 못했습니다 — useDataTable 에 그룹핑의 rows 를 넘겨 주세요",
54
+ expand: "펼치기",
55
+ collapse: "접기",
56
+ expandAll: "모두 펼치기",
57
+ collapseAll: "모두 접기",
58
+ selectAll: "전체 선택",
59
+ selectRow: "행 선택",
60
+ expandGroup: "이 그룹 펼치기",
61
+ collapseGroup: "이 그룹 접기",
62
+ expandToDepth: (depth, columnName) => `${depth}단계까지 펼치기 (${columnName})`,
63
+ expandChildren: "하위 펼치기",
64
+ sortHint: "클릭: 정렬 · Shift+클릭: 정렬 추가",
65
+ columnMenu: "컬럼 메뉴",
66
+ resizeHandle: (columnId) => `${columnId} 너비 조절`,
67
+ sortAsc: "오름차순 정렬",
68
+ sortDesc: "내림차순 정렬",
69
+ clearSort: "정렬 해제",
70
+ pinLeft: "왼쪽 고정",
71
+ pinRight: "오른쪽 고정",
72
+ unpin: "고정 해제",
73
+ moveLeft: "왼쪽으로 이동",
74
+ moveRight: "오른쪽으로 이동",
75
+ hide: "숨기기",
76
+ groupBy: "그룹 기준에 추가",
77
+ ungroup: "그룹 기준에서 제거",
78
+ resetColumnSize: "컬럼 너비 초기화",
79
+ openFilter: "필터 열기",
80
+ copyHeader: "헤더 복사",
81
+ aggregation: "집계",
82
+ aggregationSettings: "집계 설정",
83
+ copyRow: "행 복사",
84
+ };
85
+ export const DEFAULT_LABELS = {
86
+ operators: OPERATOR_LABELS,
87
+ aggregations: AGG_LABELS,
88
+ aggregationsShort: AGG_SHORT_LABELS,
89
+ ui: DEFAULT_UI_LABELS,
90
+ };
91
+ export function mergeLabels(base, input) {
92
+ if (!input)
93
+ return base;
94
+ return {
95
+ operators: { ...base.operators, ...input.operators },
96
+ aggregations: { ...base.aggregations, ...input.aggregations },
97
+ aggregationsShort: { ...base.aggregationsShort, ...input.aggregationsShort },
98
+ ui: { ...base.ui, ...input.ui },
99
+ };
100
+ }
101
+ /** 연산자 라벨 — `labels` 를 주면 그것을, 없으면 기본 한국어 표를 본다 */
102
+ export function operatorLabel(operator, labels) {
103
+ return (labels ?? OPERATOR_LABELS)[operator] ?? operator;
104
+ }