@ishibashi0112/spreadsheet-grid 0.1.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 +228 -0
- package/dist/ActiveCellOverlay.d.ts +14 -0
- package/dist/CellEditorLayer.d.ts +18 -0
- package/dist/SelectionOverlay.d.ts +14 -0
- package/dist/SpreadsheetGrid.d.ts +3 -0
- package/dist/hooks/useColumnAutosizeRunner.d.ts +16 -0
- package/dist/hooks/useColumnChooserController.d.ts +18 -0
- package/dist/hooks/useColumnHeaderDragController.d.ts +24 -0
- package/dist/hooks/useColumnMenuController.d.ts +23 -0
- package/dist/hooks/useColumnSelectOptionsCollector.d.ts +18 -0
- package/dist/hooks/useFilterPopoverController.d.ts +30 -0
- package/dist/hooks/useGridBarContext.d.ts +17 -0
- package/dist/hooks/useGridClipboardController.d.ts +22 -0
- package/dist/hooks/useGridEditController.d.ts +23 -0
- package/dist/hooks/useGridKeyboardInteractions.d.ts +21 -0
- package/dist/hooks/useGridPointerInteractions.d.ts +46 -0
- package/dist/hooks/useGridViewportSync.d.ts +21 -0
- package/dist/hooks/useServerSideRowModel.d.ts +16 -0
- package/dist/hooks/useSortManagementController.d.ts +18 -0
- package/dist/index.cjs +8 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5024 -0
- package/dist/logic/columnAutosize.d.ts +18 -0
- package/dist/logic/cx.d.ts +1 -0
- package/dist/logic/domGuards.d.ts +7 -0
- package/dist/logic/filtering.d.ts +12 -0
- package/dist/logic/geometry.d.ts +72 -0
- package/dist/logic/rowHeightStore.d.ts +13 -0
- package/dist/logic/selectOptions.d.ts +9 -0
- package/dist/logic/serverSideBlocks.d.ts +2 -0
- package/dist/logic/serverSideCache.d.ts +13 -0
- package/dist/logic/serverSideQuery.d.ts +7 -0
- package/dist/logic/sorting.d.ts +11 -0
- package/dist/logic/verticalGeometry.d.ts +50 -0
- package/dist/model/gridActions.d.ts +87 -0
- package/dist/model/gridReducer.d.ts +4 -0
- package/dist/model/gridSelectors.d.ts +40 -0
- package/dist/model/gridTypes.d.ts +267 -0
- package/dist/style.css +2 -0
- package/dist/utils/clipboard.d.ts +25 -0
- package/dist/utils/excelColumnName.d.ts +1 -0
- package/dist/utils/permissions.d.ts +4 -0
- package/dist/utils/scheduler.d.ts +1 -0
- package/dist/view/ColumnChooserPanel.d.ts +23 -0
- package/dist/view/ColumnFilterPopover.d.ts +40 -0
- package/dist/view/ColumnMenuPopover.d.ts +25 -0
- package/dist/view/DefaultGridBottomBar.d.ts +6 -0
- package/dist/view/DefaultGridTopBar.d.ts +6 -0
- package/dist/view/GridBodyLayer.d.ts +43 -0
- package/dist/view/GridHeaderRow.d.ts +41 -0
- package/dist/view/SortManagementPanel.d.ts +24 -0
- package/dist/view/gridBarHelpers.d.ts +12 -0
- package/package.json +89 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yuki Sakakibara
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# @ishibashi0112/spreadsheet-grid
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@ishibashi0112/spreadsheet-grid)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
|
|
6
|
+
A high-performance, virtualized spreadsheet / data grid for **React 19**, written in TypeScript.
|
|
7
|
+
|
|
8
|
+
高性能な仮想化スプレッドシート/データグリッド(**React 19**・TypeScript 製)。
|
|
9
|
+
|
|
10
|
+
**English** | [日本語](#日本語)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- Scroll-space virtualization that handles up to ~1,000,000 rows.
|
|
17
|
+
- Three-pane pinned columns (left / center / right) via sticky positioning.
|
|
18
|
+
- Sorting, per-column filters (`text` / `number` / `date` / `select` / `set` / `custom`), and a global filter.
|
|
19
|
+
- In-cell editing and clipboard copy / paste, with range selection and keyboard navigation.
|
|
20
|
+
- Optional auto-height rows for wrapped, variable-height content.
|
|
21
|
+
- Both **client-side** (`rows`) and **server-side** (`dataSource`, SSRM) row models.
|
|
22
|
+
- Themeable with CSS custom properties (`--ssg-*`) and a low-priority `@layer ssg-base`, so your own CSS or Tailwind utilities override the defaults without specificity battles. `className` / `classNames` slots are also provided.
|
|
23
|
+
- TypeScript-first, fully controlled API.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npm install @ishibashi0112/spreadsheet-grid
|
|
29
|
+
# pnpm add @ishibashi0112/spreadsheet-grid
|
|
30
|
+
# yarn add @ishibashi0112/spreadsheet-grid
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Requires **react** and **react-dom** `>= 19` as peer dependencies (install them in your app if you have not already). `@tanstack/react-virtual` is a regular dependency and is installed automatically.
|
|
34
|
+
|
|
35
|
+
## Styles
|
|
36
|
+
|
|
37
|
+
The grid ships its CSS as a separate file. Import it once (for example, in your app entry):
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import '@ishibashi0112/spreadsheet-grid/style.css'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The base styles live in `@layer ssg-base`, so any unlayered CSS or Tailwind utilities you write will win over the defaults.
|
|
44
|
+
|
|
45
|
+
## Quick start
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import { useState } from 'react'
|
|
49
|
+
import { SpreadsheetGrid, type GridColumn } from '@ishibashi0112/spreadsheet-grid'
|
|
50
|
+
import '@ishibashi0112/spreadsheet-grid/style.css'
|
|
51
|
+
|
|
52
|
+
type Row = { id: number; name: string; qty: number }
|
|
53
|
+
|
|
54
|
+
const columns: GridColumn<Row>[] = [
|
|
55
|
+
{ key: 'name', title: 'Name', width: 200, editable: true, filterType: 'text' },
|
|
56
|
+
{ key: 'qty', title: 'Qty', width: 120, editable: true, filterType: 'number' },
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
export function Example() {
|
|
60
|
+
const [rows, setRows] = useState<Row[]>([
|
|
61
|
+
{ id: 1, name: 'Apple', qty: 3 },
|
|
62
|
+
{ id: 2, name: 'Banana', qty: 5 },
|
|
63
|
+
])
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<SpreadsheetGrid
|
|
67
|
+
rows={rows}
|
|
68
|
+
columns={columns}
|
|
69
|
+
onRowsChange={setRows}
|
|
70
|
+
rowKeyGetter={(row) => row.id}
|
|
71
|
+
/>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`rows` and `onRowsChange` make the grid a controlled component. A column needs at least `key` and `width`.
|
|
77
|
+
|
|
78
|
+
## Server-side mode (SSRM)
|
|
79
|
+
|
|
80
|
+
Pass a `dataSource` instead of `rows` to switch to server-side mode. The grid keeps the full scroll height for the total row count and fetches only the blocks near the viewport:
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
<SpreadsheetGrid
|
|
84
|
+
columns={columns}
|
|
85
|
+
dataSource={{
|
|
86
|
+
async getRows({ startIndex, endIndex, query, signal }) {
|
|
87
|
+
// Apply `query` (filters / sort) on the server and return only [startIndex, endIndex).
|
|
88
|
+
const { rows, totalRowCount } = await fetchPage({ startIndex, endIndex, query, signal })
|
|
89
|
+
return { rows, totalRowCount }
|
|
90
|
+
},
|
|
91
|
+
}}
|
|
92
|
+
/>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Sorting, column filters, and the global filter stay enabled and are forwarded to the server through `query`. See the [API reference](./src/components/spreadsheet-grid/API_REFERENCE.md) for the full `getRows` contract, the filter wire format, and `serverSideRefreshToken`.
|
|
96
|
+
|
|
97
|
+
## Styling & theming
|
|
98
|
+
|
|
99
|
+
- Override the CSS variables on `.ssg-root` (or scope them via the `className` prop):
|
|
100
|
+
|
|
101
|
+
```css
|
|
102
|
+
.ssg-root {
|
|
103
|
+
--ssg-accent: #16a34a;
|
|
104
|
+
--ssg-radius: 4px;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
- Use the `classNames` prop for per-part class slots, `cellClassName` per column, and `getRowClassName` per row. Because the defaults are in `@layer ssg-base`, your overrides apply without `!important`.
|
|
109
|
+
|
|
110
|
+
## API reference
|
|
111
|
+
|
|
112
|
+
The full prop and type reference lives in [`src/components/spreadsheet-grid/API_REFERENCE.md`](./src/components/spreadsheet-grid/API_REFERENCE.md).
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
[MIT](./LICENSE) © 2026 Yuki Sakakibara
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 日本語
|
|
121
|
+
|
|
122
|
+
[English](#ishibashi0112spreadsheet-grid)
|
|
123
|
+
|
|
124
|
+
**React 19** 製の高性能な仮想化スプレッドシート/データグリッドです。TypeScript で書かれています。
|
|
125
|
+
|
|
126
|
+
### 特徴
|
|
127
|
+
|
|
128
|
+
- スクロール空間の仮想化により最大 100 万行規模に対応。
|
|
129
|
+
- `position: sticky` による 3 ペイン固定列(左 / 中央 / 右)。
|
|
130
|
+
- ソート、列ごとのフィルター(`text` / `number` / `date` / `select` / `set` / `custom`)、グローバルフィルター。
|
|
131
|
+
- セル内編集とクリップボードのコピー/貼り付け、範囲選択、キーボード操作。
|
|
132
|
+
- 折り返し・可変行高に対応する auto-height 行(任意)。
|
|
133
|
+
- **クライアントサイド**(`rows`)と**サーバーサイド**(`dataSource`、SSRM)の両行モデル。
|
|
134
|
+
- CSS カスタムプロパティ(`--ssg-*`)と優先度の低い `@layer ssg-base` によるテーマ設定。利用側の通常 CSS や Tailwind ユーティリティが特異度の競合なしに既定を上書きできます。`className` / `classNames` スロットも用意。
|
|
135
|
+
- TypeScript ファースト、完全 controlled な API。
|
|
136
|
+
|
|
137
|
+
### インストール
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
npm install @ishibashi0112/spreadsheet-grid
|
|
141
|
+
# pnpm add @ishibashi0112/spreadsheet-grid
|
|
142
|
+
# yarn add @ishibashi0112/spreadsheet-grid
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
peer 依存として **react** / **react-dom** `>= 19` が必要です(未導入なら利用側で入れてください)。`@tanstack/react-virtual` は通常依存として自動的に入ります。
|
|
146
|
+
|
|
147
|
+
### スタイル
|
|
148
|
+
|
|
149
|
+
CSS は別ファイルとして同梱されます。アプリのエントリ等で 1 度だけ import してください:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
import '@ishibashi0112/spreadsheet-grid/style.css'
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
基底スタイルは `@layer ssg-base` にあるため、利用側が書く未レイヤーの CSS や Tailwind ユーティリティが既定に必ず勝ちます。
|
|
156
|
+
|
|
157
|
+
### クイックスタート
|
|
158
|
+
|
|
159
|
+
```tsx
|
|
160
|
+
import { useState } from 'react'
|
|
161
|
+
import { SpreadsheetGrid, type GridColumn } from '@ishibashi0112/spreadsheet-grid'
|
|
162
|
+
import '@ishibashi0112/spreadsheet-grid/style.css'
|
|
163
|
+
|
|
164
|
+
type Row = { id: number; name: string; qty: number }
|
|
165
|
+
|
|
166
|
+
const columns: GridColumn<Row>[] = [
|
|
167
|
+
{ key: 'name', title: '名前', width: 200, editable: true, filterType: 'text' },
|
|
168
|
+
{ key: 'qty', title: '数量', width: 120, editable: true, filterType: 'number' },
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
export function Example() {
|
|
172
|
+
const [rows, setRows] = useState<Row[]>([
|
|
173
|
+
{ id: 1, name: 'りんご', qty: 3 },
|
|
174
|
+
{ id: 2, name: 'バナナ', qty: 5 },
|
|
175
|
+
])
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
<SpreadsheetGrid
|
|
179
|
+
rows={rows}
|
|
180
|
+
columns={columns}
|
|
181
|
+
onRowsChange={setRows}
|
|
182
|
+
rowKeyGetter={(row) => row.id}
|
|
183
|
+
/>
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`rows` と `onRowsChange` でグリッドは controlled になります。列には最低限 `key` と `width` が必要です。
|
|
189
|
+
|
|
190
|
+
### サーバーサイドモード(SSRM)
|
|
191
|
+
|
|
192
|
+
`rows` の代わりに `dataSource` を渡すとサーバーサイドモードになります。総行数ぶんのスクロール高さを保ったまま、可視窓に近いブロックだけを取得します:
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
<SpreadsheetGrid
|
|
196
|
+
columns={columns}
|
|
197
|
+
dataSource={{
|
|
198
|
+
async getRows({ startIndex, endIndex, query, signal }) {
|
|
199
|
+
// query(フィルター/ソート)をサーバで適用し、[startIndex, endIndex) のみ返す。
|
|
200
|
+
const { rows, totalRowCount } = await fetchPage({ startIndex, endIndex, query, signal })
|
|
201
|
+
return { rows, totalRowCount }
|
|
202
|
+
},
|
|
203
|
+
}}
|
|
204
|
+
/>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
ソート・列フィルター・グローバルフィルターは有効なまま `query` 経由でサーバへ送られます。`getRows` の契約、フィルターの wire format、`serverSideRefreshToken` の詳細は [API リファレンス](./src/components/spreadsheet-grid/API_REFERENCE.md) を参照してください。
|
|
208
|
+
|
|
209
|
+
### スタイリング / テーマ
|
|
210
|
+
|
|
211
|
+
- `.ssg-root` 上で CSS 変数を上書きします(`className` prop でスコープも可能):
|
|
212
|
+
|
|
213
|
+
```css
|
|
214
|
+
.ssg-root {
|
|
215
|
+
--ssg-accent: #16a34a;
|
|
216
|
+
--ssg-radius: 4px;
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
- パーツ別の class は `classNames` prop、列単位は `cellClassName`、行単位は `getRowClassName` で付与できます。既定は `@layer ssg-base` にあるため、上書きに `!important` は不要です。
|
|
221
|
+
|
|
222
|
+
### API リファレンス
|
|
223
|
+
|
|
224
|
+
prop と型の完全なリファレンスは [`src/components/spreadsheet-grid/API_REFERENCE.md`](./src/components/spreadsheet-grid/API_REFERENCE.md) にあります。
|
|
225
|
+
|
|
226
|
+
### ライセンス
|
|
227
|
+
|
|
228
|
+
[MIT](./LICENSE) © 2026 Yuki Sakakibara
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type ActiveCellOverlayRect = {
|
|
2
|
+
left: number;
|
|
3
|
+
top: number;
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
};
|
|
7
|
+
type ActiveCellOverlayProps = {
|
|
8
|
+
rect: ActiveCellOverlayRect | null;
|
|
9
|
+
headerHeight: number;
|
|
10
|
+
leadingWidth: number;
|
|
11
|
+
baseOffset?: number;
|
|
12
|
+
};
|
|
13
|
+
export declare function ActiveCellOverlay({ rect, headerHeight, leadingWidth, baseOffset, }: ActiveCellOverlayProps): import("react").JSX.Element | null;
|
|
14
|
+
export default ActiveCellOverlay;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type EditorCommitDirection = 'down' | 'right' | 'left';
|
|
2
|
+
type CellEditorRect = {
|
|
3
|
+
left: number;
|
|
4
|
+
top: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
};
|
|
8
|
+
type CellEditorLayerProps = {
|
|
9
|
+
rect: CellEditorRect | null;
|
|
10
|
+
headerHeight: number;
|
|
11
|
+
leadingWidth: number;
|
|
12
|
+
baseOffset?: number;
|
|
13
|
+
initialValue: string;
|
|
14
|
+
onCommit: (value: string, direction?: EditorCommitDirection) => void;
|
|
15
|
+
onCancel: () => void;
|
|
16
|
+
};
|
|
17
|
+
export declare function CellEditorLayer({ rect, headerHeight, leadingWidth, baseOffset, initialValue, onCommit, onCancel, }: CellEditorLayerProps): import("react").JSX.Element | null;
|
|
18
|
+
export default CellEditorLayer;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type SelectionOverlayRect = {
|
|
2
|
+
left: number;
|
|
3
|
+
top: number;
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
};
|
|
7
|
+
type SelectionOverlayProps = {
|
|
8
|
+
rect: SelectionOverlayRect | null;
|
|
9
|
+
headerHeight: number;
|
|
10
|
+
leadingWidth: number;
|
|
11
|
+
baseOffset?: number;
|
|
12
|
+
};
|
|
13
|
+
export declare function SelectionOverlay({ rect, headerHeight, leadingWidth, baseOffset, }: SelectionOverlayProps): import("react").JSX.Element | null;
|
|
14
|
+
export default SelectionOverlay;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import './styles.css';
|
|
2
|
+
import type { SpreadsheetGridProps } from './model/gridTypes';
|
|
3
|
+
export declare function SpreadsheetGrid<T extends object>({ rows, dataSource, serverSideRefreshToken, columns, onRowsChange, onColumnsChange, rowKeyGetter, createRow, createOverflowColumn, rowHeight, autoHeight, estimateRowHeight, headerHeight, rowHeaderWidth, readOnly, canEditCell, enableRangeSelection, enableGlobalFilter, enableColumnFilter, enableSorting, enableRowHover, enableColumnHeaderHover, enableColumnMenu, noMatchingRowsText, noRowsText, renderTopBar, renderBottomBar, className, classNames, getRowClassName, }: SpreadsheetGridProps<T>): import("react").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { gridActions } from '../model/gridActions';
|
|
2
|
+
import type { GridColumn, RowModel } from '../model/gridTypes';
|
|
3
|
+
type ReadonlyRef<V> = {
|
|
4
|
+
readonly current: V;
|
|
5
|
+
};
|
|
6
|
+
type UseColumnAutosizeRunnerArgs<T> = {
|
|
7
|
+
rowModelRef: ReadonlyRef<RowModel<T>>;
|
|
8
|
+
gridRootRef: ReadonlyRef<HTMLElement | null>;
|
|
9
|
+
columnWidthsRef: ReadonlyRef<Record<string, number>>;
|
|
10
|
+
dispatch: (action: ReturnType<typeof gridActions.syncColumnWidths>) => void;
|
|
11
|
+
};
|
|
12
|
+
export declare const useColumnAutosizeRunner: <T>({ rowModelRef, gridRootRef, columnWidthsRef, dispatch, }: UseColumnAutosizeRunnerArgs<T>) => {
|
|
13
|
+
isAutosizing: boolean;
|
|
14
|
+
runAutosize: (columns: GridColumn<T>[]) => Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
export default useColumnAutosizeRunner;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
export type ColumnChooserLayout = {
|
|
3
|
+
top: number;
|
|
4
|
+
left: number;
|
|
5
|
+
width: number;
|
|
6
|
+
};
|
|
7
|
+
type UseColumnChooserControllerArgs = {
|
|
8
|
+
enableColumnMenu: boolean;
|
|
9
|
+
gridRootRef: RefObject<HTMLDivElement | null>;
|
|
10
|
+
};
|
|
11
|
+
export declare const useColumnChooserController: ({ enableColumnMenu, gridRootRef, }: UseColumnChooserControllerArgs) => {
|
|
12
|
+
isColumnChooserOpen: boolean;
|
|
13
|
+
columnChooserLayout: ColumnChooserLayout | null;
|
|
14
|
+
columnChooserRef: RefObject<HTMLDivElement | null>;
|
|
15
|
+
openColumnChooser: () => void;
|
|
16
|
+
closeColumnChooser: () => void;
|
|
17
|
+
};
|
|
18
|
+
export default useColumnChooserController;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type PointerEvent, type RefObject } from 'react';
|
|
2
|
+
import type { GridColumn, GridColumnPinned } from '../model/gridTypes';
|
|
3
|
+
import { type GridPaneLayout } from '../logic/geometry';
|
|
4
|
+
type ApplyColumnOrderAndPin = (orderedKeys: string[], pinOverride?: Map<string, GridColumnPinned | undefined>) => void;
|
|
5
|
+
type UseColumnHeaderDragControllerArgs<T> = {
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
columns: GridColumn<T>[];
|
|
8
|
+
paneLayout: GridPaneLayout<T>;
|
|
9
|
+
leftPaneScrollRef: RefObject<HTMLDivElement | null>;
|
|
10
|
+
rightPaneScrollRef: RefObject<HTMLDivElement | null>;
|
|
11
|
+
bodyScrollRef: RefObject<HTMLDivElement | null>;
|
|
12
|
+
scrollContainerRef: RefObject<HTMLDivElement | null>;
|
|
13
|
+
leftLeadingWidth: number;
|
|
14
|
+
centerLeadingWidth: number;
|
|
15
|
+
rightLeadingWidth: number;
|
|
16
|
+
applyColumnOrderAndPin: ApplyColumnOrderAndPin;
|
|
17
|
+
};
|
|
18
|
+
export declare const useColumnHeaderDragController: <T>(args: UseColumnHeaderDragControllerArgs<T>) => {
|
|
19
|
+
onColumnDragHandlePointerDown: (column: GridColumn<T>, event: PointerEvent<HTMLElement>) => void;
|
|
20
|
+
leftIndicatorRef: RefObject<HTMLDivElement | null>;
|
|
21
|
+
centerIndicatorRef: RefObject<HTMLDivElement | null>;
|
|
22
|
+
rightIndicatorRef: RefObject<HTMLDivElement | null>;
|
|
23
|
+
};
|
|
24
|
+
export default useColumnHeaderDragController;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type MouseEvent, type PointerEvent, type RefObject } from 'react';
|
|
2
|
+
import type { GridColumn } from '../model/gridTypes';
|
|
3
|
+
export type ColumnMenuLayout = {
|
|
4
|
+
top: number;
|
|
5
|
+
left: number;
|
|
6
|
+
width: number;
|
|
7
|
+
};
|
|
8
|
+
type UseColumnMenuControllerArgs<T> = {
|
|
9
|
+
visibleColumns: GridColumn<T>[];
|
|
10
|
+
enableColumnMenu: boolean;
|
|
11
|
+
gridRootRef: RefObject<HTMLDivElement | null>;
|
|
12
|
+
};
|
|
13
|
+
export declare const useColumnMenuController: <T>({ visibleColumns, enableColumnMenu, gridRootRef, }: UseColumnMenuControllerArgs<T>) => {
|
|
14
|
+
columnMenuLayout: ColumnMenuLayout | null;
|
|
15
|
+
columnMenuRef: RefObject<HTMLDivElement | null>;
|
|
16
|
+
isColumnMenuOpen: boolean;
|
|
17
|
+
openedMenuColumnKey: string | null;
|
|
18
|
+
openedMenuColumn: GridColumn<T> | null;
|
|
19
|
+
openColumnMenuFromButton: (column: GridColumn<T>, event: PointerEvent<HTMLButtonElement>) => void;
|
|
20
|
+
openColumnMenuFromContextMenu: (column: GridColumn<T>, event: MouseEvent<HTMLDivElement>) => void;
|
|
21
|
+
closeColumnMenu: () => void;
|
|
22
|
+
};
|
|
23
|
+
export default useColumnMenuController;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { GridColumn } from '../model/gridTypes';
|
|
2
|
+
import { type SelectOptionEntry } from '../logic/selectOptions';
|
|
3
|
+
export declare const ASYNC_SELECT_COLLECT_ROW_THRESHOLD = 50000;
|
|
4
|
+
export type ColumnSelectOptionsStatus = 'idle' | 'collecting' | 'ready';
|
|
5
|
+
export type ColumnSelectOptionsResult = {
|
|
6
|
+
status: ColumnSelectOptionsStatus;
|
|
7
|
+
options: SelectOptionEntry[];
|
|
8
|
+
allValues: ReadonlySet<string>;
|
|
9
|
+
progress: number;
|
|
10
|
+
};
|
|
11
|
+
type RawValueAccessor = (index: number) => unknown;
|
|
12
|
+
type UseColumnSelectOptionsCollectorArgs<T> = {
|
|
13
|
+
column: GridColumn<T> | null;
|
|
14
|
+
rowCount: number;
|
|
15
|
+
getRawValueAt: RawValueAccessor;
|
|
16
|
+
};
|
|
17
|
+
export declare const useColumnSelectOptionsCollector: <T>({ column, rowCount, getRawValueAt, }: UseColumnSelectOptionsCollectorArgs<T>) => ColumnSelectOptionsResult;
|
|
18
|
+
export default useColumnSelectOptionsCollector;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type PointerEvent, type RefObject } from 'react';
|
|
2
|
+
import type { ColumnFilterValue, GridColumn } from '../model/gridTypes';
|
|
3
|
+
type HeaderFilterPopoverState = {
|
|
4
|
+
columnKey: string;
|
|
5
|
+
draftValue: string;
|
|
6
|
+
};
|
|
7
|
+
export type FilterPopoverLayout = {
|
|
8
|
+
top: number;
|
|
9
|
+
left: number;
|
|
10
|
+
width: number;
|
|
11
|
+
};
|
|
12
|
+
type UseFilterPopoverControllerArgs<T> = {
|
|
13
|
+
visibleColumns: GridColumn<T>[];
|
|
14
|
+
columnFilterValues: Record<string, ColumnFilterValue>;
|
|
15
|
+
enableColumnFilter: boolean;
|
|
16
|
+
gridRootRef: RefObject<HTMLDivElement | null>;
|
|
17
|
+
};
|
|
18
|
+
export declare const useFilterPopoverController: <T>({ visibleColumns, columnFilterValues, enableColumnFilter, gridRootRef, }: UseFilterPopoverControllerArgs<T>) => {
|
|
19
|
+
filterPopoverState: HeaderFilterPopoverState | null;
|
|
20
|
+
filterPopoverLayout: FilterPopoverLayout | null;
|
|
21
|
+
filterPopoverRef: RefObject<HTMLDivElement | null>;
|
|
22
|
+
filterTextInputRef: RefObject<HTMLInputElement | null>;
|
|
23
|
+
filterSelectRef: RefObject<HTMLSelectElement | null>;
|
|
24
|
+
isFilterPopoverOpen: boolean;
|
|
25
|
+
openedFilterColumn: GridColumn<T> | null;
|
|
26
|
+
openColumnFilterPopover: (column: GridColumn<T>, event: PointerEvent<HTMLButtonElement>) => void;
|
|
27
|
+
closeColumnFilterPopover: () => void;
|
|
28
|
+
updateFilterPopoverDraft: (value: string) => void;
|
|
29
|
+
};
|
|
30
|
+
export default useFilterPopoverController;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { GridColumn, GridUiState, SpreadsheetGridSlotContext } from '../model/gridTypes';
|
|
2
|
+
type GridSlotContextBase<T> = Omit<SpreadsheetGridSlotContext<T>, 'setGlobalFilterText' | 'derivedSummary' | 'filteredRows'>;
|
|
3
|
+
type UseGridBarContextArgs<T> = {
|
|
4
|
+
rows: T[];
|
|
5
|
+
viewRowCount: number;
|
|
6
|
+
getFilteredRows: () => T[];
|
|
7
|
+
columns: GridColumn<T>[];
|
|
8
|
+
visibleColumns: GridColumn<T>[];
|
|
9
|
+
uiState: GridUiState;
|
|
10
|
+
setGlobalFilterText: (value: string) => void;
|
|
11
|
+
};
|
|
12
|
+
export declare const useGridBarContext: <T>({ rows, viewRowCount, getFilteredRows, columns, visibleColumns, uiState, setGlobalFilterText, }: UseGridBarContextArgs<T>) => {
|
|
13
|
+
slotContextBase: GridSlotContextBase<T>;
|
|
14
|
+
derivedSummary: import("..").SpreadsheetGridDerivedSummary;
|
|
15
|
+
slotContext: SpreadsheetGridSlotContext<T>;
|
|
16
|
+
};
|
|
17
|
+
export default useGridBarContext;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Dispatch } from 'react';
|
|
2
|
+
import { type GridUiAction } from '../model/gridActions';
|
|
3
|
+
import type { GridColumn, SpreadsheetGridProps, GridUiState, RowModel } from '../model/gridTypes';
|
|
4
|
+
type UseGridClipboardControllerArgs<T extends object> = {
|
|
5
|
+
rows: T[];
|
|
6
|
+
rowModel: RowModel<T>;
|
|
7
|
+
visibleColumns: GridColumn<T>[];
|
|
8
|
+
uiState: GridUiState;
|
|
9
|
+
readOnly: boolean;
|
|
10
|
+
canEditCell: SpreadsheetGridProps<T>['canEditCell'];
|
|
11
|
+
createRow?: () => T;
|
|
12
|
+
createOverflowColumn?: (columnIndex: number) => GridColumn<T>;
|
|
13
|
+
onRowsChange?: (nextRows: T[]) => void;
|
|
14
|
+
onColumnsChange?: (nextColumns: GridColumn<T>[]) => void;
|
|
15
|
+
dispatch: Dispatch<GridUiAction>;
|
|
16
|
+
};
|
|
17
|
+
export declare const useGridClipboardController: <T extends object>({ rows, rowModel, visibleColumns, uiState, readOnly, canEditCell, createRow, createOverflowColumn, onRowsChange, onColumnsChange, dispatch, }: UseGridClipboardControllerArgs<T>) => {
|
|
18
|
+
isWholeGridSelected: boolean;
|
|
19
|
+
handleCopy: () => Promise<void>;
|
|
20
|
+
handlePaste: (event: React.ClipboardEvent<HTMLDivElement>) => void;
|
|
21
|
+
};
|
|
22
|
+
export default useGridClipboardController;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type Dispatch, type RefObject } from 'react';
|
|
2
|
+
import { type GridUiAction } from '../model/gridActions';
|
|
3
|
+
import type { CellCoord, GridColumn, GridUiState, RowModel } from '../model/gridTypes';
|
|
4
|
+
import type { EditorCommitDirection } from '../CellEditorLayer';
|
|
5
|
+
type UseGridEditControllerArgs<T extends object> = {
|
|
6
|
+
uiState: GridUiState;
|
|
7
|
+
rows: T[];
|
|
8
|
+
visibleColumns: GridColumn<T>[];
|
|
9
|
+
rowModel: RowModel<T>;
|
|
10
|
+
setEditorInitialValue: (value: string) => void;
|
|
11
|
+
onRowsChange?: (nextRows: T[]) => void;
|
|
12
|
+
dispatch: Dispatch<GridUiAction>;
|
|
13
|
+
getMovedCell: (baseCell: CellCoord, deltaRow: number, deltaCol: number) => CellCoord;
|
|
14
|
+
gridRootRef: RefObject<HTMLDivElement | null>;
|
|
15
|
+
editorActionGuardRef: RefObject<boolean>;
|
|
16
|
+
};
|
|
17
|
+
export declare const useGridEditController: <T extends object>({ uiState, rows, visibleColumns, rowModel, setEditorInitialValue, onRowsChange, dispatch, getMovedCell, gridRootRef, editorActionGuardRef, }: UseGridEditControllerArgs<T>) => {
|
|
18
|
+
activateSingleCell: (cell: CellCoord) => void;
|
|
19
|
+
startEditWithValue: (cell: CellCoord, initialValue: string) => void;
|
|
20
|
+
commitEdit: (committedValue: string, direction?: EditorCommitDirection) => void;
|
|
21
|
+
cancelEdit: () => void;
|
|
22
|
+
};
|
|
23
|
+
export default useGridEditController;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Dispatch, type KeyboardEvent } from 'react';
|
|
2
|
+
import { type GridUiAction } from '../model/gridActions';
|
|
3
|
+
import type { CellCoord, GridColumn, GridUiState, RowModel, SpreadsheetGridProps } from '../model/gridTypes';
|
|
4
|
+
type UseGridKeyboardInteractionsArgs<T> = {
|
|
5
|
+
uiState: GridUiState;
|
|
6
|
+
rowModel: RowModel<T>;
|
|
7
|
+
visibleColumns: GridColumn<T>[];
|
|
8
|
+
readOnly: boolean;
|
|
9
|
+
canEditCell: SpreadsheetGridProps<T>['canEditCell'];
|
|
10
|
+
setEditorInitialValue: (value: string) => void;
|
|
11
|
+
dispatch: Dispatch<GridUiAction>;
|
|
12
|
+
handleCopy: () => Promise<void>;
|
|
13
|
+
handleCellDoubleClick: (cell: CellCoord) => void;
|
|
14
|
+
isWholeGridSelected: boolean;
|
|
15
|
+
selectEntireGrid: () => void;
|
|
16
|
+
};
|
|
17
|
+
export declare const useGridKeyboardInteractions: <T>({ uiState, rowModel, visibleColumns, readOnly, canEditCell, setEditorInitialValue, dispatch, handleCopy, handleCellDoubleClick, isWholeGridSelected, selectEntireGrid, }: UseGridKeyboardInteractionsArgs<T>) => {
|
|
18
|
+
getMovedCell: (baseCell: CellCoord, deltaRow: number, deltaCol: number) => CellCoord;
|
|
19
|
+
handleKeyDown: (event: KeyboardEvent<HTMLDivElement>) => Promise<void>;
|
|
20
|
+
};
|
|
21
|
+
export default useGridKeyboardInteractions;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Dispatch, type PointerEvent, type RefObject } from 'react';
|
|
2
|
+
import { type GridUiAction } from '../model/gridActions';
|
|
3
|
+
import type { CellCoord, GridColumn, GridUiState } from '../model/gridTypes';
|
|
4
|
+
import { type GridPaneLayout } from '../logic/geometry';
|
|
5
|
+
import type { RowMetrics } from '../logic/verticalGeometry';
|
|
6
|
+
type UseGridPointerInteractionsArgs<T> = {
|
|
7
|
+
gridRootRef: RefObject<HTMLDivElement | null>;
|
|
8
|
+
bodyScrollRef: RefObject<HTMLDivElement | null>;
|
|
9
|
+
scrollContainerRef: RefObject<HTMLDivElement | null>;
|
|
10
|
+
leftPaneScrollRef: RefObject<HTMLDivElement | null>;
|
|
11
|
+
rightPaneScrollRef: RefObject<HTMLDivElement | null>;
|
|
12
|
+
pointerClientRef: RefObject<{
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
} | null>;
|
|
16
|
+
autoScrollFrameRef: RefObject<number | null>;
|
|
17
|
+
uiState: GridUiState;
|
|
18
|
+
dispatch: Dispatch<GridUiAction>;
|
|
19
|
+
enableRangeSelection: boolean;
|
|
20
|
+
enableSorting: boolean;
|
|
21
|
+
orderedColumns: GridColumn<T>[];
|
|
22
|
+
filteredRowsLength: number;
|
|
23
|
+
visibleColumnsLength: number;
|
|
24
|
+
paneLayout: GridPaneLayout<T>;
|
|
25
|
+
leftLeadingWidth: number;
|
|
26
|
+
centerLeadingWidth: number;
|
|
27
|
+
rightLeadingWidth: number;
|
|
28
|
+
headerHeight: number;
|
|
29
|
+
rowMetrics: RowMetrics;
|
|
30
|
+
verticalScaleFactor: number;
|
|
31
|
+
setHoveredRowIndex: (value: number | null) => void;
|
|
32
|
+
setHoveredColumnIndex: (value: number | null) => void;
|
|
33
|
+
enableRowHover: boolean;
|
|
34
|
+
enableColumnHeaderHover: boolean;
|
|
35
|
+
};
|
|
36
|
+
export declare const useGridPointerInteractions: <T>({ gridRootRef, bodyScrollRef, scrollContainerRef, leftPaneScrollRef, rightPaneScrollRef, pointerClientRef, autoScrollFrameRef, uiState, dispatch, enableRangeSelection, enableSorting, orderedColumns, filteredRowsLength, visibleColumnsLength, paneLayout, leftLeadingWidth, centerLeadingWidth, rightLeadingWidth, headerHeight, rowMetrics, verticalScaleFactor, setHoveredRowIndex, setHoveredColumnIndex, enableRowHover, enableColumnHeaderHover, }: UseGridPointerInteractionsArgs<T>) => {
|
|
37
|
+
updateSelectionFromPointer: (clientX: number, clientY: number) => void;
|
|
38
|
+
handleCellPointerDown: (cell: CellCoord, event: PointerEvent<HTMLDivElement>) => void;
|
|
39
|
+
handleCellPointerEnter: (cell: CellCoord, event: PointerEvent<HTMLDivElement>) => void;
|
|
40
|
+
handleNativeDragStart: (event: React.DragEvent<HTMLDivElement>) => void;
|
|
41
|
+
handleRowHeaderPointerDown: (rowIndex: number, event: PointerEvent<HTMLDivElement>) => void;
|
|
42
|
+
handleRowHeaderPointerEnter: (rowIndex: number, event: PointerEvent<HTMLDivElement>) => void;
|
|
43
|
+
handleColumnHeaderPointerDown: (colIndex: number, event: PointerEvent<HTMLDivElement>) => void;
|
|
44
|
+
handleColumnHeaderPointerEnter: (colIndex: number, event: PointerEvent<HTMLDivElement>) => void;
|
|
45
|
+
};
|
|
46
|
+
export default useGridPointerInteractions;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import type { ActiveCellOverlayRect } from '../ActiveCellOverlay';
|
|
3
|
+
import type { ColumnMeasurement } from '../logic/geometry';
|
|
4
|
+
type VirtualizerLike = {
|
|
5
|
+
measure: () => void;
|
|
6
|
+
};
|
|
7
|
+
type UseGridViewportSyncArgs<T> = {
|
|
8
|
+
scrollRef: RefObject<HTMLDivElement | null>;
|
|
9
|
+
columnVirtualizer: VirtualizerLike;
|
|
10
|
+
columnMeasurements: ColumnMeasurement<T>[];
|
|
11
|
+
totalScrollWidth: number;
|
|
12
|
+
physicalBodyHeight: number;
|
|
13
|
+
headerHeight: number;
|
|
14
|
+
leftPaneWidth: number;
|
|
15
|
+
rightPaneWidth: number;
|
|
16
|
+
centerLeadingWidth: number;
|
|
17
|
+
activeCellRect: ActiveCellOverlayRect | null;
|
|
18
|
+
verticalScaleFactor: number;
|
|
19
|
+
};
|
|
20
|
+
export declare const useGridViewportSync: <T>({ scrollRef, columnVirtualizer, columnMeasurements, totalScrollWidth, physicalBodyHeight, headerHeight, leftPaneWidth, rightPaneWidth, centerLeadingWidth, activeCellRect, verticalScaleFactor, }: UseGridViewportSyncArgs<T>) => void;
|
|
21
|
+
export default useGridViewportSync;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GridRowKey, RowModel, ServerSideDataSource, ServerSideQuery } from '../model/gridTypes';
|
|
2
|
+
export type UseServerSideRowModelParams<T> = {
|
|
3
|
+
dataSource?: ServerSideDataSource<T>;
|
|
4
|
+
rowKeyGetter: (row: T, index: number) => GridRowKey;
|
|
5
|
+
query: ServerSideQuery;
|
|
6
|
+
queryKey: string;
|
|
7
|
+
refreshToken?: number;
|
|
8
|
+
debounceMs?: number;
|
|
9
|
+
};
|
|
10
|
+
export type UseServerSideRowModelResult<T> = {
|
|
11
|
+
rowModel: RowModel<T>;
|
|
12
|
+
rowCount: number;
|
|
13
|
+
isRowLoaded: (viewIndex: number) => boolean;
|
|
14
|
+
requestRange: (startIndex: number, endIndex: number) => void;
|
|
15
|
+
};
|
|
16
|
+
export declare function useServerSideRowModel<T>(params: UseServerSideRowModelParams<T>): UseServerSideRowModelResult<T>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
export type SortManagementLayout = {
|
|
3
|
+
top: number;
|
|
4
|
+
left: number;
|
|
5
|
+
width: number;
|
|
6
|
+
};
|
|
7
|
+
type UseSortManagementControllerArgs = {
|
|
8
|
+
enableSorting: boolean;
|
|
9
|
+
gridRootRef: RefObject<HTMLDivElement | null>;
|
|
10
|
+
};
|
|
11
|
+
export declare const useSortManagementController: ({ enableSorting, gridRootRef, }: UseSortManagementControllerArgs) => {
|
|
12
|
+
isSortManagerOpen: boolean;
|
|
13
|
+
sortManagerLayout: SortManagementLayout | null;
|
|
14
|
+
sortManagerRef: RefObject<HTMLDivElement | null>;
|
|
15
|
+
openSortManager: () => void;
|
|
16
|
+
closeSortManager: () => void;
|
|
17
|
+
};
|
|
18
|
+
export default useSortManagementController;
|