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.
- package/LICENSE +21 -0
- package/README.md +320 -0
- package/contract/table-request.schema.json +424 -0
- package/dist/core/src/adapters/sources.d.ts +59 -0
- package/dist/core/src/adapters/sources.js +235 -0
- package/dist/core/src/client/aggregate.d.ts +94 -0
- package/dist/core/src/client/aggregate.js +222 -0
- package/dist/core/src/client/groupRows.d.ts +40 -0
- package/dist/core/src/client/groupRows.js +145 -0
- package/dist/core/src/client/runClientQuery.d.ts +67 -0
- package/dist/core/src/client/runClientQuery.js +157 -0
- package/dist/core/src/columns/ColumnBuilder.d.ts +121 -0
- package/dist/core/src/columns/ColumnBuilder.js +273 -0
- package/dist/core/src/columns/cascade.d.ts +24 -0
- package/dist/core/src/columns/cascade.js +93 -0
- package/dist/core/src/columns/deriveOperators.d.ts +38 -0
- package/dist/core/src/columns/deriveOperators.js +94 -0
- package/dist/core/src/columns/expandSorting.d.ts +19 -0
- package/dist/core/src/columns/expandSorting.js +52 -0
- package/dist/core/src/columns/helper.d.ts +196 -0
- package/dist/core/src/columns/helper.js +250 -0
- package/dist/core/src/columns/labels.d.ts +12 -0
- package/dist/core/src/columns/labels.js +21 -0
- package/dist/core/src/contract.d.ts +12 -0
- package/dist/core/src/contract.js +12 -0
- package/dist/core/src/contracts/aiColumnMeta.d.ts +102 -0
- package/dist/core/src/contracts/aiColumnMeta.js +197 -0
- package/dist/core/src/contracts/describeColumns.d.ts +48 -0
- package/dist/core/src/contracts/describeColumns.js +40 -0
- package/dist/core/src/contracts/exportData.d.ts +150 -0
- package/dist/core/src/contracts/exportData.js +228 -0
- package/dist/core/src/contracts/index.d.ts +6 -0
- package/dist/core/src/contracts/index.js +12 -0
- package/dist/core/src/contracts/legacyUrl.d.ts +47 -0
- package/dist/core/src/contracts/legacyUrl.js +156 -0
- package/dist/core/src/contracts/preset.d.ts +104 -0
- package/dist/core/src/contracts/preset.js +141 -0
- package/dist/core/src/contracts/presetStore.d.ts +81 -0
- package/dist/core/src/contracts/presetStore.js +146 -0
- package/dist/core/src/contracts/usePresets.d.ts +51 -0
- package/dist/core/src/contracts/usePresets.js +170 -0
- package/dist/core/src/defaults.d.ts +7 -0
- package/dist/core/src/defaults.js +9 -0
- package/dist/core/src/filters/codec.d.ts +20 -0
- package/dist/core/src/filters/codec.js +61 -0
- package/dist/core/src/filters/date.d.ts +30 -0
- package/dist/core/src/filters/date.js +179 -0
- package/dist/core/src/filters/describe.d.ts +45 -0
- package/dist/core/src/filters/describe.js +189 -0
- package/dist/core/src/filters/kind.d.ts +52 -0
- package/dist/core/src/filters/kind.js +110 -0
- package/dist/core/src/filters/kinds/_list.d.ts +13 -0
- package/dist/core/src/filters/kinds/_list.js +42 -0
- package/dist/core/src/filters/kinds/boolean.d.ts +3 -0
- package/dist/core/src/filters/kinds/boolean.js +21 -0
- package/dist/core/src/filters/kinds/cascade.d.ts +6 -0
- package/dist/core/src/filters/kinds/cascade.js +16 -0
- package/dist/core/src/filters/kinds/commonCode.d.ts +3 -0
- package/dist/core/src/filters/kinds/commonCode.js +13 -0
- package/dist/core/src/filters/kinds/date.d.ts +9 -0
- package/dist/core/src/filters/kinds/date.js +32 -0
- package/dist/core/src/filters/kinds/enum.d.ts +4 -0
- package/dist/core/src/filters/kinds/enum.js +13 -0
- package/dist/core/src/filters/kinds/index.d.ts +49 -0
- package/dist/core/src/filters/kinds/index.js +39 -0
- package/dist/core/src/filters/kinds/linear.d.ts +5 -0
- package/dist/core/src/filters/kinds/linear.js +16 -0
- package/dist/core/src/filters/kinds/number.d.ts +5 -0
- package/dist/core/src/filters/kinds/number.js +19 -0
- package/dist/core/src/filters/kinds/period.d.ts +4 -0
- package/dist/core/src/filters/kinds/period.js +17 -0
- package/dist/core/src/filters/kinds/relation.d.ts +5 -0
- package/dist/core/src/filters/kinds/relation.js +17 -0
- package/dist/core/src/filters/kinds/schedule.d.ts +5 -0
- package/dist/core/src/filters/kinds/schedule.js +16 -0
- package/dist/core/src/filters/kinds/text.d.ts +4 -0
- package/dist/core/src/filters/kinds/text.js +18 -0
- package/dist/core/src/filters/linear.d.ts +33 -0
- package/dist/core/src/filters/linear.js +65 -0
- package/dist/core/src/filters/list.d.ts +32 -0
- package/dist/core/src/filters/list.js +87 -0
- package/dist/core/src/filters/number.d.ts +17 -0
- package/dist/core/src/filters/number.js +82 -0
- package/dist/core/src/filters/registry.d.ts +23 -0
- package/dist/core/src/filters/registry.js +121 -0
- package/dist/core/src/filters/relation.d.ts +26 -0
- package/dist/core/src/filters/relation.js +75 -0
- package/dist/core/src/filters/schedule.d.ts +21 -0
- package/dist/core/src/filters/schedule.js +60 -0
- package/dist/core/src/filters/text.d.ts +44 -0
- package/dist/core/src/filters/text.js +127 -0
- package/dist/core/src/hooks/index.d.ts +6 -0
- package/dist/core/src/hooks/index.js +6 -0
- package/dist/core/src/hooks/useDataTable.d.ts +13 -0
- package/dist/core/src/hooks/useDataTable.js +109 -0
- package/dist/core/src/hooks/useGrouping.d.ts +33 -0
- package/dist/core/src/hooks/useGrouping.js +57 -0
- package/dist/core/src/hooks/useSearchHistory.d.ts +20 -0
- package/dist/core/src/hooks/useSearchHistory.js +52 -0
- package/dist/core/src/hooks/useTableData.d.ts +25 -0
- package/dist/core/src/hooks/useTableData.js +49 -0
- package/dist/core/src/hooks/useTableFromDefinition.d.ts +47 -0
- package/dist/core/src/hooks/useTableFromDefinition.js +174 -0
- package/dist/core/src/hooks/useTableSearch.d.ts +10 -0
- package/dist/core/src/hooks/useTableSearch.js +434 -0
- package/dist/core/src/hooks/useUrlSync.d.ts +64 -0
- package/dist/core/src/hooks/useUrlSync.js +145 -0
- package/dist/core/src/index.d.ts +38 -0
- package/dist/core/src/index.js +43 -0
- package/dist/core/src/pivot/runClientPivot.d.ts +101 -0
- package/dist/core/src/pivot/runClientPivot.js +230 -0
- package/dist/core/src/pivot/transforms.d.ts +19 -0
- package/dist/core/src/pivot/transforms.js +105 -0
- package/dist/core/src/registry.d.ts +46 -0
- package/dist/core/src/registry.js +67 -0
- package/dist/core/src/types/column.d.ts +213 -0
- package/dist/core/src/types/column.js +1 -0
- package/dist/core/src/types/data.d.ts +63 -0
- package/dist/core/src/types/data.js +1 -0
- package/dist/core/src/types/definition.d.ts +239 -0
- package/dist/core/src/types/definition.js +59 -0
- package/dist/core/src/types/filter.d.ts +94 -0
- package/dist/core/src/types/filter.js +1 -0
- package/dist/core/src/types/filterKind.d.ts +204 -0
- package/dist/core/src/types/filterKind.js +1 -0
- package/dist/core/src/types/grouping.d.ts +80 -0
- package/dist/core/src/types/grouping.js +4 -0
- package/dist/core/src/types/index.d.ts +8 -0
- package/dist/core/src/types/index.js +8 -0
- package/dist/core/src/types/operators.d.ts +64 -0
- package/dist/core/src/types/operators.js +108 -0
- package/dist/core/src/types/request.d.ts +114 -0
- package/dist/core/src/types/request.js +1 -0
- package/dist/core/src/types/search.d.ts +112 -0
- package/dist/core/src/types/search.js +1 -0
- package/dist/core/src/types/sources.d.ts +84 -0
- package/dist/core/src/types/sources.js +1 -0
- package/dist/core/src/types/table.d.ts +40 -0
- package/dist/core/src/types/table.js +1 -0
- package/dist/core/src/utils/compare.d.ts +13 -0
- package/dist/core/src/utils/compare.js +53 -0
- package/dist/core/src/utils/dateText.d.ts +12 -0
- package/dist/core/src/utils/dateText.js +30 -0
- package/dist/core/src/utils/getValue.d.ts +9 -0
- package/dist/core/src/utils/getValue.js +32 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/mui/src/TableLayout.d.ts +75 -0
- package/dist/mui/src/TableLayout.js +162 -0
- package/dist/mui/src/TableScreen.d.ts +70 -0
- package/dist/mui/src/TableScreen.js +174 -0
- package/dist/mui/src/addons/FilterModal.d.ts +45 -0
- package/dist/mui/src/addons/FilterModal.js +39 -0
- package/dist/mui/src/addons/FilterStatusModal.d.ts +40 -0
- package/dist/mui/src/addons/FilterStatusModal.js +68 -0
- package/dist/mui/src/addons/PresetBar.d.ts +56 -0
- package/dist/mui/src/addons/PresetBar.js +145 -0
- package/dist/mui/src/addons/ShareDropdown.d.ts +35 -0
- package/dist/mui/src/addons/ShareDropdown.js +41 -0
- package/dist/mui/src/addons/searchStore.d.ts +44 -0
- package/dist/mui/src/addons/searchStore.js +112 -0
- package/dist/mui/src/addons/searchSummary.d.ts +106 -0
- package/dist/mui/src/addons/searchSummary.js +109 -0
- package/dist/mui/src/columns/displayColumns.d.ts +100 -0
- package/dist/mui/src/columns/displayColumns.js +174 -0
- package/dist/mui/src/content/CardContent.d.ts +24 -0
- package/dist/mui/src/content/CardContent.js +25 -0
- package/dist/mui/src/content/ColumnMenu.d.ts +43 -0
- package/dist/mui/src/content/ColumnMenu.js +40 -0
- package/dist/mui/src/content/ColumnVisibilityMenu.d.ts +14 -0
- package/dist/mui/src/content/ColumnVisibilityMenu.js +37 -0
- package/dist/mui/src/content/EditCell.d.ts +19 -0
- package/dist/mui/src/content/EditCell.js +61 -0
- package/dist/mui/src/content/HeaderCell.d.ts +59 -0
- package/dist/mui/src/content/HeaderCell.js +88 -0
- package/dist/mui/src/content/SelectionActionBar.d.ts +17 -0
- package/dist/mui/src/content/SelectionActionBar.js +19 -0
- package/dist/mui/src/content/SortControl.d.ts +17 -0
- package/dist/mui/src/content/SortControl.js +45 -0
- package/dist/mui/src/content/TableContent.d.ts +191 -0
- package/dist/mui/src/content/TableContent.js +525 -0
- package/dist/mui/src/content/TableErrorFallback.d.ts +24 -0
- package/dist/mui/src/content/TableErrorFallback.js +29 -0
- package/dist/mui/src/content/cellError.d.ts +13 -0
- package/dist/mui/src/content/cellError.js +20 -0
- package/dist/mui/src/content/cellRenderers.d.ts +71 -0
- package/dist/mui/src/content/cellRenderers.js +127 -0
- package/dist/mui/src/content/cellValue.d.ts +27 -0
- package/dist/mui/src/content/cellValue.js +82 -0
- package/dist/mui/src/content/columnOrder.d.ts +7 -0
- package/dist/mui/src/content/columnOrder.js +48 -0
- package/dist/mui/src/content/density.d.ts +13 -0
- package/dist/mui/src/content/density.js +12 -0
- package/dist/mui/src/content/menuItems.d.ts +118 -0
- package/dist/mui/src/content/menuItems.js +128 -0
- package/dist/mui/src/content/pinning.d.ts +17 -0
- package/dist/mui/src/content/pinning.js +65 -0
- package/dist/mui/src/exporters/index.d.ts +1 -0
- package/dist/mui/src/exporters/index.js +1 -0
- package/dist/mui/src/exporters/useExportFormatters.d.ts +13 -0
- package/dist/mui/src/exporters/useExportFormatters.js +17 -0
- package/dist/mui/src/filter/FilterArea.d.ts +40 -0
- package/dist/mui/src/filter/FilterArea.js +37 -0
- package/dist/mui/src/filter/FilterInput.d.ts +14 -0
- package/dist/mui/src/filter/FilterInput.js +18 -0
- package/dist/mui/src/filter/inputs/DateFilterInput.d.ts +14 -0
- package/dist/mui/src/filter/inputs/DateFilterInput.js +112 -0
- package/dist/mui/src/filter/inputs/LinearFilterInput.d.ts +10 -0
- package/dist/mui/src/filter/inputs/LinearFilterInput.js +35 -0
- package/dist/mui/src/filter/inputs/NumberFilterInput.d.ts +12 -0
- package/dist/mui/src/filter/inputs/NumberFilterInput.js +111 -0
- package/dist/mui/src/filter/inputs/OperatorMenu.d.ts +14 -0
- package/dist/mui/src/filter/inputs/OperatorMenu.js +25 -0
- package/dist/mui/src/filter/inputs/RelationFilterInput.d.ts +11 -0
- package/dist/mui/src/filter/inputs/RelationFilterInput.js +67 -0
- package/dist/mui/src/filter/inputs/ScheduleFilterInput.d.ts +8 -0
- package/dist/mui/src/filter/inputs/ScheduleFilterInput.js +17 -0
- package/dist/mui/src/filter/inputs/SelectFilterInput.d.ts +16 -0
- package/dist/mui/src/filter/inputs/SelectFilterInput.js +57 -0
- package/dist/mui/src/filter/inputs/TextFilterInput.d.ts +13 -0
- package/dist/mui/src/filter/inputs/TextFilterInput.js +55 -0
- package/dist/mui/src/filter/kinds.d.ts +58 -0
- package/dist/mui/src/filter/kinds.js +103 -0
- package/dist/mui/src/grouping/AggregateChip.d.ts +55 -0
- package/dist/mui/src/grouping/AggregateChip.js +128 -0
- package/dist/mui/src/grouping/AggregationChips.d.ts +49 -0
- package/dist/mui/src/grouping/AggregationChips.js +80 -0
- package/dist/mui/src/grouping/AggregationSettingsButton.d.ts +14 -0
- package/dist/mui/src/grouping/AggregationSettingsButton.js +19 -0
- package/dist/mui/src/grouping/GroupingBar.d.ts +59 -0
- package/dist/mui/src/grouping/GroupingBar.js +267 -0
- package/dist/mui/src/grouping/StepExpandButton.d.ts +12 -0
- package/dist/mui/src/grouping/StepExpandButton.js +18 -0
- package/dist/mui/src/grouping/groupRow.d.ts +68 -0
- package/dist/mui/src/grouping/groupRow.js +129 -0
- package/dist/mui/src/headers/defaultHeader.d.ts +28 -0
- package/dist/mui/src/headers/defaultHeader.js +90 -0
- package/dist/mui/src/headers/defineHeader.d.ts +21 -0
- package/dist/mui/src/headers/defineHeader.js +68 -0
- package/dist/mui/src/headers/index.d.ts +5 -0
- package/dist/mui/src/headers/index.js +3 -0
- package/dist/mui/src/headers/meta.d.ts +18 -0
- package/dist/mui/src/headers/meta.js +11 -0
- package/dist/mui/src/headers/types.d.ts +84 -0
- package/dist/mui/src/headers/types.js +1 -0
- package/dist/mui/src/index.d.ts +110 -0
- package/dist/mui/src/index.js +79 -0
- package/dist/mui/src/layout/ResizeHandle.d.ts +30 -0
- package/dist/mui/src/layout/ResizeHandle.js +66 -0
- package/dist/mui/src/menus/columnMenu.d.ts +45 -0
- package/dist/mui/src/menus/columnMenu.js +144 -0
- package/dist/mui/src/menus/copy.d.ts +5 -0
- package/dist/mui/src/menus/copy.js +25 -0
- package/dist/mui/src/menus/index.d.ts +6 -0
- package/dist/mui/src/menus/index.js +4 -0
- package/dist/mui/src/menus/resolve.d.ts +15 -0
- package/dist/mui/src/menus/resolve.js +60 -0
- package/dist/mui/src/menus/rowMenu.d.ts +46 -0
- package/dist/mui/src/menus/rowMenu.js +76 -0
- package/dist/mui/src/pagination/PaginationArea.d.ts +16 -0
- package/dist/mui/src/pagination/PaginationArea.js +23 -0
- package/dist/mui/src/pivot/PivotTable.d.ts +18 -0
- package/dist/mui/src/pivot/PivotTable.js +100 -0
- package/dist/mui/src/provider/KokoTableProvider.d.ts +184 -0
- package/dist/mui/src/provider/KokoTableProvider.js +118 -0
- package/dist/mui/src/provider/labels.d.ts +85 -0
- package/dist/mui/src/provider/labels.js +104 -0
- package/dist/mui/src/registry.d.ts +30 -0
- package/dist/mui/src/registry.js +5 -0
- package/dist/mui/src/toolbar/GlobalFilterField.d.ts +36 -0
- package/dist/mui/src/toolbar/GlobalFilterField.js +78 -0
- package/dist/mui/src/virtual/VirtualTableContent.d.ts +41 -0
- package/dist/mui/src/virtual/VirtualTableContent.js +58 -0
- package/dist/mui/src/virtual/VirtualTableScreen.d.ts +13 -0
- package/dist/mui/src/virtual/VirtualTableScreen.js +23 -0
- package/dist/mui/src/virtual.d.ts +4 -0
- package/dist/mui/src/virtual.js +4 -0
- package/dist/mui/src/virtualColumns/VirtualColumnCard.d.ts +26 -0
- package/dist/mui/src/virtualColumns/VirtualColumnCard.js +29 -0
- package/dist/mui/src/virtualColumns/VirtualColumnDialog.d.ts +27 -0
- package/dist/mui/src/virtualColumns/VirtualColumnDialog.js +154 -0
- package/dist/mui/src/virtualColumns/VirtualColumnSection.d.ts +31 -0
- package/dist/mui/src/virtualColumns/VirtualColumnSection.js +55 -0
- package/dist/mui/src/virtualColumns/expression.d.ts +68 -0
- package/dist/mui/src/virtualColumns/expression.js +489 -0
- package/dist/mui/src/virtualColumns/useVirtualColumns.d.ts +67 -0
- package/dist/mui/src/virtualColumns/useVirtualColumns.js +111 -0
- package/dist/mui/src/virtualColumns/virtualColumnDefs.d.ts +29 -0
- package/dist/mui/src/virtualColumns/virtualColumnDefs.js +51 -0
- package/dist/mui-virtual.d.ts +1 -0
- package/dist/mui-virtual.js +2 -0
- package/dist/mui.d.ts +1 -0
- package/dist/mui.js +2 -0
- package/dist/query/src/index.d.ts +6 -0
- package/dist/query/src/index.js +7 -0
- package/dist/query/src/serverPivot.d.ts +42 -0
- package/dist/query/src/serverPivot.js +153 -0
- package/dist/query/src/useServerGrouping.d.ts +52 -0
- package/dist/query/src/useServerGrouping.js +186 -0
- package/dist/query/src/useServerTable.d.ts +20 -0
- package/dist/query/src/useServerTable.js +106 -0
- package/dist/query/src/useServerTableData.d.ts +48 -0
- package/dist/query/src/useServerTableData.js +64 -0
- package/dist/query/src/wire.d.ts +16 -0
- package/dist/query/src/wire.js +32 -0
- package/dist/query.d.ts +1 -0
- package/dist/query.js +2 -0
- package/package.json +125 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useCallback, useMemo, useState } from "react";
|
|
2
|
+
import { pathKey } from "../types/grouping";
|
|
3
|
+
import { allGroupPaths, flattenGroups, groupDepth, groupRows, pathsToDepth, } from "../client/groupRows";
|
|
4
|
+
/**
|
|
5
|
+
* 클라이언트 그룹핑 — 이미 필터·정렬이 끝난 행을 트리로 묶는다.
|
|
6
|
+
*
|
|
7
|
+
* 서버 그룹핑(`groupExpansion` — 최상위 `path: []` / 경로 확장)과 결과 모양을 맞춰 두었기
|
|
8
|
+
* 때문에, 나중에 서버 모드를 붙여도 렌더러는 그대로 쓸 수 있다.
|
|
9
|
+
*/
|
|
10
|
+
export function useGrouping(options) {
|
|
11
|
+
const { rows, columns, grouping, aggregation, aggregations, labelOf, initialExpanded = false, includeLeaves = true, } = options;
|
|
12
|
+
const enabled = grouping.length > 0;
|
|
13
|
+
const tree = useMemo(() => (enabled ? groupRows(rows, { grouping, columns, aggregation, aggregations, labelOf }) : []), [enabled, rows, grouping, columns, aggregation, aggregations, labelOf]);
|
|
14
|
+
const maxDepth = useMemo(() => groupDepth(tree), [tree]);
|
|
15
|
+
// 초기 펼침은 트리가 처음 생길 때 한 번만 반영한다 — 매 렌더 계산하면
|
|
16
|
+
// 사용자가 접은 그룹이 데이터 갱신마다 다시 펼쳐진다.
|
|
17
|
+
const [expandedKeys, setExpandedKeys] = useState(null);
|
|
18
|
+
const resolvedExpanded = useMemo(() => {
|
|
19
|
+
if (expandedKeys !== null)
|
|
20
|
+
return expandedKeys;
|
|
21
|
+
return initialExpanded ? new Set(allGroupPaths(tree)) : new Set();
|
|
22
|
+
}, [expandedKeys, initialExpanded, tree]);
|
|
23
|
+
const currentDepth = useMemo(() => {
|
|
24
|
+
if (resolvedExpanded.size === 0)
|
|
25
|
+
return 0;
|
|
26
|
+
for (let depth = maxDepth; depth >= 1; depth -= 1) {
|
|
27
|
+
const needed = pathsToDepth(tree, depth);
|
|
28
|
+
if (needed.every((key) => resolvedExpanded.has(key)))
|
|
29
|
+
return depth;
|
|
30
|
+
}
|
|
31
|
+
return 0;
|
|
32
|
+
}, [resolvedExpanded, tree, maxDepth]);
|
|
33
|
+
const toggle = useCallback((path) => {
|
|
34
|
+
const key = pathKey(path);
|
|
35
|
+
setExpandedKeys((prev) => {
|
|
36
|
+
const next = new Set(prev ?? []);
|
|
37
|
+
if (next.has(key))
|
|
38
|
+
next.delete(key);
|
|
39
|
+
else
|
|
40
|
+
next.add(key);
|
|
41
|
+
return next;
|
|
42
|
+
});
|
|
43
|
+
}, []);
|
|
44
|
+
const expandToDepth = useCallback((depth) => setExpandedKeys(new Set(pathsToDepth(tree, depth))), [tree]);
|
|
45
|
+
const expand = useMemo(() => ({
|
|
46
|
+
isExpanded: (path) => resolvedExpanded.has(pathKey(path)),
|
|
47
|
+
toggle,
|
|
48
|
+
expandAll: () => setExpandedKeys(new Set(allGroupPaths(tree))),
|
|
49
|
+
collapseAll: () => setExpandedKeys(new Set()),
|
|
50
|
+
expandToDepth,
|
|
51
|
+
depth: currentDepth,
|
|
52
|
+
maxDepth,
|
|
53
|
+
canExpand: maxDepth > 0,
|
|
54
|
+
}), [resolvedExpanded, toggle, tree, expandToDepth, currentDepth, maxDepth]);
|
|
55
|
+
const items = useMemo(() => (enabled ? flattenGroups(tree, { expanded: resolvedExpanded, includeLeaves }) : []), [enabled, tree, resolvedExpanded, includeLeaves]);
|
|
56
|
+
return { tree, items, expand, enabled };
|
|
57
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { RowData } from "@tanstack/react-table";
|
|
2
|
+
import type { TableSearch } from "../types/search";
|
|
3
|
+
export interface SearchHistory {
|
|
4
|
+
back: () => void;
|
|
5
|
+
forward: () => void;
|
|
6
|
+
canGoBack: boolean;
|
|
7
|
+
canGoForward: boolean;
|
|
8
|
+
size: number;
|
|
9
|
+
}
|
|
10
|
+
export interface UseSearchHistoryOptions {
|
|
11
|
+
/** 보관할 최대 항목 수 */
|
|
12
|
+
limit?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 검색 조건 히스토리 애드온 — 적용된 조건(`params`)만 기록한다.
|
|
16
|
+
*
|
|
17
|
+
* 뒤로/앞으로 이동해서 생긴 변경은 기록하지 않는다. 기록하면 되돌아간 지점이
|
|
18
|
+
* 다시 스택 맨 위로 쌓여 앞으로 가기가 영영 살아나지 않는다.
|
|
19
|
+
*/
|
|
20
|
+
export declare function useSearchHistory<T extends RowData>(search: TableSearch<T>, options?: UseSearchHistoryOptions): SearchHistory;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
const sameState = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
3
|
+
/**
|
|
4
|
+
* 검색 조건 히스토리 애드온 — 적용된 조건(`params`)만 기록한다.
|
|
5
|
+
*
|
|
6
|
+
* 뒤로/앞으로 이동해서 생긴 변경은 기록하지 않는다. 기록하면 되돌아간 지점이
|
|
7
|
+
* 다시 스택 맨 위로 쌓여 앞으로 가기가 영영 살아나지 않는다.
|
|
8
|
+
*/
|
|
9
|
+
export function useSearchHistory(search, options = {}) {
|
|
10
|
+
const { limit = 50 } = options;
|
|
11
|
+
const stackRef = useRef([search.params]);
|
|
12
|
+
const indexRef = useRef(0);
|
|
13
|
+
const navigatingRef = useRef(false);
|
|
14
|
+
const [version, setVersion] = useState(0);
|
|
15
|
+
const searchRef = useRef(search);
|
|
16
|
+
searchRef.current = search;
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (navigatingRef.current) {
|
|
19
|
+
navigatingRef.current = false;
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const current = stackRef.current[indexRef.current];
|
|
23
|
+
if (current && sameState(current, search.params))
|
|
24
|
+
return;
|
|
25
|
+
// 새 조건은 현재 위치 뒤를 잘라내고 쌓는다 (브라우저 히스토리와 같은 규약)
|
|
26
|
+
const next = [...stackRef.current.slice(0, indexRef.current + 1), search.params];
|
|
27
|
+
const trimmed = next.length > limit ? next.slice(next.length - limit) : next;
|
|
28
|
+
stackRef.current = trimmed;
|
|
29
|
+
indexRef.current = trimmed.length - 1;
|
|
30
|
+
setVersion((v) => v + 1);
|
|
31
|
+
}, [search.params, limit]);
|
|
32
|
+
const go = useCallback((delta) => {
|
|
33
|
+
const target = indexRef.current + delta;
|
|
34
|
+
const state = stackRef.current[target];
|
|
35
|
+
if (!state)
|
|
36
|
+
return;
|
|
37
|
+
indexRef.current = target;
|
|
38
|
+
navigatingRef.current = true;
|
|
39
|
+
searchRef.current.setParams(state);
|
|
40
|
+
setVersion((v) => v + 1);
|
|
41
|
+
}, []);
|
|
42
|
+
const back = useCallback(() => go(-1), [go]);
|
|
43
|
+
const forward = useCallback(() => go(1), [go]);
|
|
44
|
+
void version; // 스택은 ref 에 있으므로 리렌더 트리거용으로만 쓴다
|
|
45
|
+
return {
|
|
46
|
+
back,
|
|
47
|
+
forward,
|
|
48
|
+
canGoBack: indexRef.current > 0,
|
|
49
|
+
canGoForward: indexRef.current < stackRef.current.length - 1,
|
|
50
|
+
size: stackRef.current.length,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { RowData } from "@tanstack/react-table";
|
|
2
|
+
import type { TableColumnDefs } from "../types/column";
|
|
3
|
+
import type { TableData, TableDataOptions, TableMode } from "../types/data";
|
|
4
|
+
import { type ClientQueryOptions } from "../client/runClientQuery";
|
|
5
|
+
export interface UseTableDataOptions<T extends RowData> extends TableDataOptions<T>, ClientQueryOptions<T> {
|
|
6
|
+
/** 클라이언트 모드 필터링에 쓸 컬럼 정의 */
|
|
7
|
+
columns: TableColumnDefs<T>;
|
|
8
|
+
}
|
|
9
|
+
/** `mode` 미지정 시의 판정 — 기존 `useTableQuery` 규칙과 같다 */
|
|
10
|
+
export declare function resolveMode<T extends RowData>(options: TableDataOptions<T>): TableMode;
|
|
11
|
+
/**
|
|
12
|
+
* 2층 — 데이터. **테이블 인스턴스를 만들지 않는다.**
|
|
13
|
+
*
|
|
14
|
+
* 지금은 클라이언트 모드만 구현돼 있다. 서버 모드는 요청 캐싱·취소가 필요해
|
|
15
|
+
* `kokotable/query`(react-query 어댑터)로 분리하며, 코어는 의존성 0 을 유지한다.
|
|
16
|
+
*
|
|
17
|
+
* 파이프라인은 두 단계로 메모이즈한다. `request` 는 페이지만 넘겨도 새 객체가 되므로
|
|
18
|
+
* 통째로 의존하면 페이지 이동마다 필터·정렬(50k 행이면 수십 ms)을 다시 돌린다.
|
|
19
|
+
* 필터·전역검색·정렬에 관여하는 필드만 1단계의 의존성으로 두고, 2단계는 슬라이스만 한다.
|
|
20
|
+
* (`useTableSearch` 는 페이지 이동 시 `columnFilters`/`sorting` 의 참조를 유지한다.)
|
|
21
|
+
*
|
|
22
|
+
* `now` 는 `inPeriod` 의 기준 시각이다. 서버는 서버 시각(KST)으로 계산하므로
|
|
23
|
+
* 브라우저 시간대가 다르면 경계가 어긋날 수 있다 — 맞춰야 하면 주입한다.
|
|
24
|
+
*/
|
|
25
|
+
export declare function useTableData<T extends RowData>(options: UseTableDataOptions<T>): TableData<T>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { filterAndSortRows, paginateRows, } from "../client/runClientQuery";
|
|
3
|
+
/** `mode` 미지정 시의 판정 — 기존 `useTableQuery` 규칙과 같다 */
|
|
4
|
+
export function resolveMode(options) {
|
|
5
|
+
if (options.mode)
|
|
6
|
+
return options.mode;
|
|
7
|
+
return options.queryFn ? "server" : "client";
|
|
8
|
+
}
|
|
9
|
+
const noop = () => { };
|
|
10
|
+
const EMPTY_ROWS = [];
|
|
11
|
+
/**
|
|
12
|
+
* 2층 — 데이터. **테이블 인스턴스를 만들지 않는다.**
|
|
13
|
+
*
|
|
14
|
+
* 지금은 클라이언트 모드만 구현돼 있다. 서버 모드는 요청 캐싱·취소가 필요해
|
|
15
|
+
* `kokotable/query`(react-query 어댑터)로 분리하며, 코어는 의존성 0 을 유지한다.
|
|
16
|
+
*
|
|
17
|
+
* 파이프라인은 두 단계로 메모이즈한다. `request` 는 페이지만 넘겨도 새 객체가 되므로
|
|
18
|
+
* 통째로 의존하면 페이지 이동마다 필터·정렬(50k 행이면 수십 ms)을 다시 돌린다.
|
|
19
|
+
* 필터·전역검색·정렬에 관여하는 필드만 1단계의 의존성으로 두고, 2단계는 슬라이스만 한다.
|
|
20
|
+
* (`useTableSearch` 는 페이지 이동 시 `columnFilters`/`sorting` 의 참조를 유지한다.)
|
|
21
|
+
*
|
|
22
|
+
* `now` 는 `inPeriod` 의 기준 시각이다. 서버는 서버 시각(KST)으로 계산하므로
|
|
23
|
+
* 브라우저 시간대가 다르면 경계가 어긋날 수 있다 — 맞춰야 하면 주입한다.
|
|
24
|
+
*/
|
|
25
|
+
export function useTableData(options) {
|
|
26
|
+
const { columns, request, data, now, globalFilterFields } = options;
|
|
27
|
+
const mode = resolveMode(options);
|
|
28
|
+
const { columnFilters, columnFilterFns, globalFilter, sorting, pagination } = request;
|
|
29
|
+
// 훅 호출은 조건 없이 — 모드 판정보다 먼저 실행돼야 순서가 흔들리지 않는다
|
|
30
|
+
const filtered = useMemo(() => filterAndSortRows(data ?? EMPTY_ROWS, columns, { columnFilters, columnFilterFns, globalFilter, sorting }, { now, globalFilterFields }), [data, columns, columnFilters, columnFilterFns, globalFilter, sorting, now, globalFilterFields]);
|
|
31
|
+
const rows = useMemo(() => paginateRows(filtered, pagination), [filtered, pagination]);
|
|
32
|
+
const value = useMemo(() => ({
|
|
33
|
+
rows,
|
|
34
|
+
total: filtered.length,
|
|
35
|
+
meta: { total_count: filtered.length },
|
|
36
|
+
groups: null,
|
|
37
|
+
isLoading: false,
|
|
38
|
+
isInitialLoading: false,
|
|
39
|
+
isError: false,
|
|
40
|
+
error: undefined,
|
|
41
|
+
refetch: noop,
|
|
42
|
+
mode: "client",
|
|
43
|
+
}), [rows, filtered]);
|
|
44
|
+
if (mode === "server") {
|
|
45
|
+
throw new Error("[koko-table] 서버 모드는 코어에 없습니다 (코어는 의존성 0 을 유지한다). " +
|
|
46
|
+
'kokotable/query 의 useServerTableData 를 쓰거나 mode: "client" 로 두세요.');
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { RowData, TableOptions } from "@tanstack/react-table";
|
|
2
|
+
import type { TableColumnDefs } from "../types/column";
|
|
3
|
+
import type { TableData } from "../types/data";
|
|
4
|
+
import type { DataTable } from "../types/table";
|
|
5
|
+
import type { TableSearch } from "../types/search";
|
|
6
|
+
import type { TableBundle, TableDefinition } from "../types/definition";
|
|
7
|
+
import { type UrlSync } from "./useUrlSync";
|
|
8
|
+
import { type SearchHistory } from "./useSearchHistory";
|
|
9
|
+
export interface DefinitionSearch<T extends RowData> {
|
|
10
|
+
search: TableSearch<T>;
|
|
11
|
+
urlSync?: UrlSync;
|
|
12
|
+
history?: SearchHistory;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 1층 + 애드온 — 정의에서 검색 상태·URL 동기화·이력을 만든다.
|
|
16
|
+
* 클라이언트(`useTableFromDefinition`)와 서버(`useServerTable`) 조립이 공유하는 부분이다.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useDefinitionSearch<T extends RowData>(definition: TableDefinition<T>): DefinitionSearch<T>;
|
|
19
|
+
/**
|
|
20
|
+
* `features` → TanStack 옵션. `definition.tableOptions` 가 위에 덮이고 `getRowId` 는 정의가 우선한다.
|
|
21
|
+
*/
|
|
22
|
+
export declare function definitionTableOptions<T extends RowData>(definition: TableDefinition<T>): Partial<TableOptions<T>>;
|
|
23
|
+
export interface UseDefinitionTableOptions<T extends RowData> {
|
|
24
|
+
definition: TableDefinition<T>;
|
|
25
|
+
search: TableSearch<T>;
|
|
26
|
+
data: TableData<T>;
|
|
27
|
+
}
|
|
28
|
+
export interface DefinitionTable<T extends RowData> {
|
|
29
|
+
table: DataTable<T>;
|
|
30
|
+
tableColumns: TableColumnDefs<T>;
|
|
31
|
+
setTableColumns: (columns: TableColumnDefs<T> | null) => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 3층 — 정의의 `features`/`getRowId`/`tableOptions` 로 TanStack 인스턴스를 만든다.
|
|
35
|
+
*
|
|
36
|
+
* 표시 전용 열(선택·확장·번호·액션)과 가상 컬럼은 렌더러 패키지가 만든다(코어는 MUI 를 모른다).
|
|
37
|
+
* 그래서 컬럼 목록을 **등록하는 자리**(`setTableColumns`)를 둔다 — `TableScreen` 이 마운트 시
|
|
38
|
+
* `withDisplayColumns(...)` 결과를 넣고, 직접 조립하는 화면은 원하는 목록을 넣는다.
|
|
39
|
+
*/
|
|
40
|
+
export declare function useDefinitionTable<T extends RowData>(options: UseDefinitionTableOptions<T>): DefinitionTable<T>;
|
|
41
|
+
/**
|
|
42
|
+
* 클라이언트 모드 조립 — `useTableSearch` → `useTableData` → `useGrouping` → `useDataTable` + URL 동기화.
|
|
43
|
+
*
|
|
44
|
+
* 서버 모드 정의는 `kokotable/query` 의 `useServerTable(definition)` 으로 조립한다 (코어는 의존성 0).
|
|
45
|
+
* 반환값은 의존성이 바뀔 때만 새 객체다.
|
|
46
|
+
*/
|
|
47
|
+
export declare function useTableFromDefinition<T extends RowData>(definition: TableDefinition<T>): TableBundle<T>;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { useCallback, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { resolveDefinitionMode } from "../types/definition";
|
|
3
|
+
import { runClientQuery } from "../client/runClientQuery";
|
|
4
|
+
import { PAGE_SIZE_ALL } from "../defaults";
|
|
5
|
+
import { useTableSearch } from "./useTableSearch";
|
|
6
|
+
import { useTableData } from "./useTableData";
|
|
7
|
+
import { useDataTable } from "./useDataTable";
|
|
8
|
+
import { useGrouping } from "./useGrouping";
|
|
9
|
+
import { readUrlSearchState, useUrlSync } from "./useUrlSync";
|
|
10
|
+
import { useSearchHistory } from "./useSearchHistory";
|
|
11
|
+
/** 비어 있는 그룹 배열의 고정 참조 — 렌더마다 새 배열이면 그룹 트리 메모가 매번 무효화된다 */
|
|
12
|
+
const EMPTY_GROUPING = [];
|
|
13
|
+
/**
|
|
14
|
+
* 정의의 검색 초기값 — `initial` 위에 `grouping.initial/aggregation` 을 깔고,
|
|
15
|
+
* URL 동기화가 켜져 있으면 주소창의 값이 마지막에 덮는다 (공유 링크가 기본값을 이긴다).
|
|
16
|
+
*/
|
|
17
|
+
function resolveInitialSearch(definition) {
|
|
18
|
+
let initial = definition.initial;
|
|
19
|
+
const grouping = definition.grouping;
|
|
20
|
+
if (grouping?.initial && initial?.grouping === undefined) {
|
|
21
|
+
initial = { ...initial, grouping: [...grouping.initial] };
|
|
22
|
+
}
|
|
23
|
+
if (grouping?.aggregation && initial?.aggregation === undefined) {
|
|
24
|
+
initial = { ...initial, aggregation: grouping.aggregation };
|
|
25
|
+
}
|
|
26
|
+
if (definition.urlSync) {
|
|
27
|
+
const options = typeof definition.urlSync === "object" ? definition.urlSync : {};
|
|
28
|
+
const fromUrl = readUrlSearchState({ ...options, columns: definition.columns });
|
|
29
|
+
if (fromUrl)
|
|
30
|
+
initial = { ...initial, ...fromUrl };
|
|
31
|
+
}
|
|
32
|
+
return initial;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 1층 + 애드온 — 정의에서 검색 상태·URL 동기화·이력을 만든다.
|
|
36
|
+
* 클라이언트(`useTableFromDefinition`)와 서버(`useServerTable`) 조립이 공유하는 부분이다.
|
|
37
|
+
*/
|
|
38
|
+
export function useDefinitionSearch(definition) {
|
|
39
|
+
// 초기값은 마운트 시 한 번만 계산한다 — URL 읽기가 렌더마다 돌면 popstate 복원과 경쟁한다
|
|
40
|
+
const initialRef = useRef(null);
|
|
41
|
+
if (initialRef.current === null)
|
|
42
|
+
initialRef.current = { value: resolveInitialSearch(definition) };
|
|
43
|
+
const searchOptions = {
|
|
44
|
+
columns: definition.columns,
|
|
45
|
+
initial: initialRef.current.value,
|
|
46
|
+
initialOperators: definition.initialOperators,
|
|
47
|
+
};
|
|
48
|
+
// `TableSearchOptions.debounceMs` 는 1층이 지원할 때만 의미가 있다 — 없으면 무시된다
|
|
49
|
+
if (definition.debounceMs !== undefined)
|
|
50
|
+
searchOptions.debounceMs = definition.debounceMs;
|
|
51
|
+
const search = useTableSearch(searchOptions);
|
|
52
|
+
const urlOptions = definition.urlSync
|
|
53
|
+
? (typeof definition.urlSync === "object" ? definition.urlSync : {})
|
|
54
|
+
: undefined;
|
|
55
|
+
const urlSync = useUrlSync(search, {
|
|
56
|
+
enabled: !!urlOptions,
|
|
57
|
+
paramKey: urlOptions?.paramKey,
|
|
58
|
+
legacyParamKeys: urlOptions?.legacyParamKeys,
|
|
59
|
+
});
|
|
60
|
+
const historyLimit = typeof definition.history === "object" ? definition.history.limit : undefined;
|
|
61
|
+
const history = useSearchHistory(search, { limit: historyLimit });
|
|
62
|
+
return useMemo(() => ({
|
|
63
|
+
search,
|
|
64
|
+
urlSync: urlOptions ? urlSync : undefined,
|
|
65
|
+
history: definition.history ? history : undefined,
|
|
66
|
+
}), [search, urlSync, history, !!urlOptions, !!definition.history]);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* `features` → TanStack 옵션. `definition.tableOptions` 가 위에 덮이고 `getRowId` 는 정의가 우선한다.
|
|
70
|
+
*/
|
|
71
|
+
export function definitionTableOptions(definition) {
|
|
72
|
+
const features = definition.features ?? {};
|
|
73
|
+
const options = {};
|
|
74
|
+
if (features.selection) {
|
|
75
|
+
const selection = typeof features.selection === "object" ? features.selection : {};
|
|
76
|
+
options.enableRowSelection = selection.canSelect ?? true;
|
|
77
|
+
if (selection.multi === false)
|
|
78
|
+
options.enableMultiRowSelection = false;
|
|
79
|
+
}
|
|
80
|
+
if (features.expand && typeof features.expand === "object" && features.expand.canExpand) {
|
|
81
|
+
options.getRowCanExpand = features.expand.canExpand;
|
|
82
|
+
}
|
|
83
|
+
const merged = { ...options, ...definition.tableOptions };
|
|
84
|
+
if (definition.getRowId)
|
|
85
|
+
merged.getRowId = definition.getRowId;
|
|
86
|
+
return merged;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 3층 — 정의의 `features`/`getRowId`/`tableOptions` 로 TanStack 인스턴스를 만든다.
|
|
90
|
+
*
|
|
91
|
+
* 표시 전용 열(선택·확장·번호·액션)과 가상 컬럼은 렌더러 패키지가 만든다(코어는 MUI 를 모른다).
|
|
92
|
+
* 그래서 컬럼 목록을 **등록하는 자리**(`setTableColumns`)를 둔다 — `TableScreen` 이 마운트 시
|
|
93
|
+
* `withDisplayColumns(...)` 결과를 넣고, 직접 조립하는 화면은 원하는 목록을 넣는다.
|
|
94
|
+
*/
|
|
95
|
+
export function useDefinitionTable(options) {
|
|
96
|
+
const { definition, search, data } = options;
|
|
97
|
+
const [registered, setRegistered] = useState(null);
|
|
98
|
+
const tableColumns = registered ?? definition.columns;
|
|
99
|
+
const setTableColumns = useCallback((columns) => {
|
|
100
|
+
setRegistered((prev) => (prev === columns ? prev : columns));
|
|
101
|
+
}, []);
|
|
102
|
+
const tableOptions = useMemo(() => definitionTableOptions(definition), [definition]);
|
|
103
|
+
const table = useDataTable({
|
|
104
|
+
columns: tableColumns,
|
|
105
|
+
search,
|
|
106
|
+
data,
|
|
107
|
+
fieldErrors: definition.fieldErrors,
|
|
108
|
+
tableOptions,
|
|
109
|
+
});
|
|
110
|
+
return useMemo(() => ({ table, tableColumns, setTableColumns }), [table, tableColumns, setTableColumns]);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* 클라이언트 모드 조립 — `useTableSearch` → `useTableData` → `useGrouping` → `useDataTable` + URL 동기화.
|
|
114
|
+
*
|
|
115
|
+
* 서버 모드 정의는 `kokotable/query` 의 `useServerTable(definition)` 으로 조립한다 (코어는 의존성 0).
|
|
116
|
+
* 반환값은 의존성이 바뀔 때만 새 객체다.
|
|
117
|
+
*/
|
|
118
|
+
export function useTableFromDefinition(definition) {
|
|
119
|
+
const mode = resolveDefinitionMode(definition);
|
|
120
|
+
if (mode === "server") {
|
|
121
|
+
throw new Error(`[koko-table] useTableFromDefinition("${definition.key}"): 서버 모드 정의는 ` +
|
|
122
|
+
"kokotable/query 의 useServerTable(definition) 으로 조립하세요.");
|
|
123
|
+
}
|
|
124
|
+
const { search, urlSync, history } = useDefinitionSearch(definition);
|
|
125
|
+
const data = useTableData({
|
|
126
|
+
columns: definition.columns,
|
|
127
|
+
request: search.request,
|
|
128
|
+
data: definition.data,
|
|
129
|
+
mode: "client",
|
|
130
|
+
now: definition.now,
|
|
131
|
+
globalFilterFields: definition.globalFilterFields,
|
|
132
|
+
});
|
|
133
|
+
const groupingEnabled = !!definition.grouping?.enabled;
|
|
134
|
+
const groupingColumns = groupingEnabled ? (search.params.grouping ?? EMPTY_GROUPING) : EMPTY_GROUPING;
|
|
135
|
+
const group = useGrouping({
|
|
136
|
+
rows: data.rows,
|
|
137
|
+
columns: definition.columns,
|
|
138
|
+
grouping: groupingColumns,
|
|
139
|
+
// 요청에 실리는 것과 같은 명세 — 서버 모드와 집계 기준이 같아진다
|
|
140
|
+
aggregation: search.request.aggregation,
|
|
141
|
+
initialExpanded: definition.grouping?.initialExpanded,
|
|
142
|
+
});
|
|
143
|
+
const { table, tableColumns, setTableColumns } = useDefinitionTable({ definition, search, data });
|
|
144
|
+
const fetchAllRows = useCallback(async () => {
|
|
145
|
+
const { filtered } = runClientQuery(definition.data ?? [], definition.columns, { ...search.request, pagination: { pageIndex: 0, pageSize: PAGE_SIZE_ALL } }, { now: definition.now, globalFilterFields: definition.globalFilterFields });
|
|
146
|
+
return filtered;
|
|
147
|
+
}, [definition.data, definition.columns, definition.now, definition.globalFilterFields, search.request]);
|
|
148
|
+
const grouping = useMemo(() => {
|
|
149
|
+
if (!groupingEnabled)
|
|
150
|
+
return undefined;
|
|
151
|
+
return {
|
|
152
|
+
enabled: group.enabled,
|
|
153
|
+
grouping: groupingColumns,
|
|
154
|
+
setGrouping: search.setGrouping,
|
|
155
|
+
items: group.items,
|
|
156
|
+
expand: group.expand,
|
|
157
|
+
rows: data.rows,
|
|
158
|
+
};
|
|
159
|
+
}, [groupingEnabled, group.enabled, group.items, group.expand, groupingColumns, search.setGrouping, data.rows]);
|
|
160
|
+
return useMemo(() => ({
|
|
161
|
+
definition,
|
|
162
|
+
mode: "client",
|
|
163
|
+
search,
|
|
164
|
+
data,
|
|
165
|
+
table,
|
|
166
|
+
grouping,
|
|
167
|
+
urlSync,
|
|
168
|
+
history,
|
|
169
|
+
request: search.request,
|
|
170
|
+
tableColumns,
|
|
171
|
+
setTableColumns,
|
|
172
|
+
fetchAllRows,
|
|
173
|
+
}), [definition, search, data, table, grouping, urlSync, history, tableColumns, setTableColumns, fetchAllRows]);
|
|
174
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RowData } from "@tanstack/react-table";
|
|
2
|
+
import type { TableSearch, TableSearchOptions } from "../types/search";
|
|
3
|
+
/**
|
|
4
|
+
* 1층 — 검색 상태. **테이블 인스턴스를 만들지 않는다.**
|
|
5
|
+
*
|
|
6
|
+
* 반환값이 `FilterSource` 를 만족하므로 필터 패널이 테이블 없이 바로 붙는다.
|
|
7
|
+
* 페이지네이션 UI 는 총 건수가 필요하므로 `paginationSource(search, data)` 로
|
|
8
|
+
* 2층과 합쳐 넘긴다.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useTableSearch<T extends RowData>(options: TableSearchOptions<T>): TableSearch<T>;
|