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,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
|
+
}
|
package/dist/query.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./query/src/index";
|
package/dist/query.js
ADDED
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
|
+
}
|