@bendyline/squisq-grid-react 2.11.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/NOTICE.md +16 -0
- package/README.md +23 -0
- package/THIRD_PARTY_LICENSES.txt +8 -0
- package/dist/index.d.ts +376 -0
- package/dist/index.js +1778 -0
- package/dist/styles/index.css +341 -0
- package/dist/styles/index.d.ts +1 -0
- package/package.json +71 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bendyline LLC
|
|
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/NOTICE.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Third-Party Notices for @bendyline/squisq-grid-react
|
|
2
|
+
|
|
3
|
+
This notice applies to the `@bendyline/squisq-grid-react` npm package.
|
|
4
|
+
Squisq-authored code is licensed under the MIT license in `LICENSE`.
|
|
5
|
+
Third-party components remain under their respective license terms.
|
|
6
|
+
|
|
7
|
+
## Runtime and peer dependencies
|
|
8
|
+
|
|
9
|
+
| Package | Version | License | Repository |
|
|
10
|
+
| ----------------------- | -------------------- | ------- | ----------------------------------- |
|
|
11
|
+
| @tanstack/react-virtual | 3.14.10 | MIT | https://github.com/TanStack/virtual |
|
|
12
|
+
| react _(peer)_ | ^18.0.0 \|\| ^19.0.0 | MIT | https://github.com/facebook/react |
|
|
13
|
+
| react-dom _(peer)_ | ^18.0.0 \|\| ^19.0.0 | MIT | https://github.com/facebook/react |
|
|
14
|
+
|
|
15
|
+
Copyright and complete license texts for these dependencies are included in
|
|
16
|
+
their respective npm distributions and source repositories.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# @bendyline/squisq-grid-react
|
|
2
|
+
|
|
3
|
+
Virtualized data grid for squisq data sidecars: an in-house columnar store
|
|
4
|
+
behind a Web Worker (`TableStoreClient`, implementing core's
|
|
5
|
+
`TableQueryProvider`), plus a TanStack-Virtual React renderer (`DataGrid`)
|
|
6
|
+
with spreadsheet-style sort/filter/selection/clipboard and journaled cell
|
|
7
|
+
editing.
|
|
8
|
+
|
|
9
|
+
The Tiptap mount lives in `@bendyline/squisq-editor-react` (the data-card
|
|
10
|
+
widget lazy-imports this package); the grid itself has no editor
|
|
11
|
+
dependencies and works in any React 18/19 host.
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { DataGrid, TableStoreClient, EditJournal } from '@bendyline/squisq-grid-react';
|
|
15
|
+
import '@bendyline/squisq-grid-react/styles';
|
|
16
|
+
|
|
17
|
+
const provider = new TableStoreClient({ headers, cells });
|
|
18
|
+
<DataGrid provider={provider} journal={new EditJournal()} view={{ sort: [], filter: [] }} />;
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Theming: every color resolves through `--squisq-grid-*` CSS custom
|
|
22
|
+
properties with literal fallbacks; hosts re-bind them to their own palette
|
|
23
|
+
(editor-react aliases them onto its chrome tokens).
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
THIRD-PARTY LICENSES FOR @bendyline/squisq-grid-react
|
|
2
|
+
|
|
3
|
+
Generated from the actual esbuild input graph. Package-local license, copying,
|
|
4
|
+
and notice files are reproduced verbatim. When an npm tarball omits its
|
|
5
|
+
repository license, the pinned upstream copy is vendored and identified below.
|
|
6
|
+
|
|
7
|
+
COMPONENTS
|
|
8
|
+
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import { TableCellValue, TableColumnKind, TableQueryProvider, TableSchema, TableViewState, TableViewResult, TableRowsPage, TableCellEdit, TableEditResult, TableDistinctResult } from '@bendyline/squisq/table';
|
|
2
|
+
import { ReactElement } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Columnar ingestion: a format-neutral cell grid → typed columns the worker
|
|
6
|
+
* kernel operates on. grid-react never parses files itself — the editor
|
|
7
|
+
* adapter feeds an `IngestTable` built from the lazy formats readers (CSV
|
|
8
|
+
* strings with a typing pass; XLSX typed `XlsxCell.value`s).
|
|
9
|
+
*
|
|
10
|
+
* Layout per column kind:
|
|
11
|
+
* - `number` → `Float64Array data` + `Uint8Array valid` (an explicit blank
|
|
12
|
+
* mask — NaN-as-sentinel is rejected because a coercion bug could
|
|
13
|
+
* legitimately produce NaN, and masks make blank semantics testable)
|
|
14
|
+
* - `string`/`date` → DICTIONARY-encoded: `Int32Array codes` (−1 = blank) +
|
|
15
|
+
* `string[] dict`. Chosen because (1) the code array is transferable, so
|
|
16
|
+
* the bulk of the bytes move to the worker rather than being cloned;
|
|
17
|
+
* (2) locale-aware sort is one `rank` array over unique values instead of
|
|
18
|
+
* per-row collation; (3) `contains` lowercasing happens once per dict
|
|
19
|
+
* entry. High-cardinality columns degrade gracefully (dict length = row
|
|
20
|
+
* count — no worse than `string[]`).
|
|
21
|
+
* - `boolean` → `Uint8Array data` + `Uint8Array valid`
|
|
22
|
+
*
|
|
23
|
+
* Column typing follows the SHARED rule in `@bendyline/squisq/table`
|
|
24
|
+
* (`isNumericCellText`: all non-blank cells numeric, no leading-zero
|
|
25
|
+
* strings) so kernel results stay parity-testable against
|
|
26
|
+
* `applyTableViewState`.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/** A format-neutral cell: `null` = blank. */
|
|
30
|
+
type IngestCell = TableCellValue;
|
|
31
|
+
interface IngestColumnHint {
|
|
32
|
+
/** Force a column kind (XLSX adapters know; CSV lets inference decide). */
|
|
33
|
+
kind?: TableColumnKind;
|
|
34
|
+
}
|
|
35
|
+
interface IngestTable {
|
|
36
|
+
headers: string[];
|
|
37
|
+
/** Row-major cells; ragged rows are padded with blanks. */
|
|
38
|
+
cells: IngestCell[][];
|
|
39
|
+
/** Optional per-column hints, index-aligned with `headers`. */
|
|
40
|
+
hints?: (IngestColumnHint | undefined)[];
|
|
41
|
+
}
|
|
42
|
+
interface NumberColumn {
|
|
43
|
+
kind: 'number';
|
|
44
|
+
name: string;
|
|
45
|
+
data: Float64Array;
|
|
46
|
+
valid: Uint8Array;
|
|
47
|
+
}
|
|
48
|
+
interface DictColumn {
|
|
49
|
+
kind: 'string' | 'date';
|
|
50
|
+
name: string;
|
|
51
|
+
/** Dictionary code per row; −1 = blank. */
|
|
52
|
+
codes: Int32Array;
|
|
53
|
+
dict: string[];
|
|
54
|
+
}
|
|
55
|
+
interface BooleanColumn {
|
|
56
|
+
kind: 'boolean';
|
|
57
|
+
name: string;
|
|
58
|
+
data: Uint8Array;
|
|
59
|
+
valid: Uint8Array;
|
|
60
|
+
}
|
|
61
|
+
type StoreColumn = NumberColumn | DictColumn | BooleanColumn;
|
|
62
|
+
interface ColumnarTable {
|
|
63
|
+
columns: StoreColumn[];
|
|
64
|
+
rowCount: number;
|
|
65
|
+
}
|
|
66
|
+
/** Build typed columns from a neutral cell grid. */
|
|
67
|
+
declare function buildColumnarTable(table: IngestTable): ColumnarTable;
|
|
68
|
+
/** Read one cell back out of typed columns (`null` = blank). */
|
|
69
|
+
declare function columnCellValue(column: StoreColumn, row: number): TableCellValue;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The table kernel — sort/filter/window/edit over transferred typed columns.
|
|
73
|
+
*
|
|
74
|
+
* SHIPPING CONSTRAINT: this function's SOURCE is the worker. It is embedded
|
|
75
|
+
* via `tableKernel.toString()` into a Blob URL (`buildKernelSource`), the
|
|
76
|
+
* same zero-asset pattern as the teleprompter's PCM worklet — editor
|
|
77
|
+
* packages ship no runtime asset files, and URL-based workers would force
|
|
78
|
+
* bundler configuration onto every host. Therefore:
|
|
79
|
+
*
|
|
80
|
+
* - the function must reference NOTHING from module scope (all helpers are
|
|
81
|
+
* nested; only web-worker globals like `Intl` are used);
|
|
82
|
+
* - tsup must never minify this package (mangled `toString()` output);
|
|
83
|
+
* both properties are pinned by tests in `kernel.test.ts`.
|
|
84
|
+
*
|
|
85
|
+
* Semantics mirror `applyTableViewState` in `@bendyline/squisq/table`
|
|
86
|
+
* (numeric compare on number columns, collator-ranked dictionary compare on
|
|
87
|
+
* text, blanks last regardless of direction, stable sort with source-index
|
|
88
|
+
* tie-break, filter-then-sort) — parity is a tested property, not an
|
|
89
|
+
* aspiration. Type/collation rules are COPIED here by necessity (zero
|
|
90
|
+
* imports); the parity suite is what keeps the copies honest.
|
|
91
|
+
*
|
|
92
|
+
* Edits mutate columns in place and NEVER re-permute: a row teleporting out
|
|
93
|
+
* from under the caret mid-entry is hostile. `applyEdits` reports
|
|
94
|
+
* `staleView` when an edited cell touched an active sort/filter column so
|
|
95
|
+
* the UI can offer an explicit refresh.
|
|
96
|
+
*/
|
|
97
|
+
interface KernelColumnPayload {
|
|
98
|
+
name: string;
|
|
99
|
+
kind: 'number' | 'string' | 'date' | 'boolean';
|
|
100
|
+
/** number/boolean: values; string/date: dictionary codes (−1 = blank). */
|
|
101
|
+
data: Float64Array | Int32Array | Uint8Array;
|
|
102
|
+
valid?: Uint8Array;
|
|
103
|
+
dict?: string[];
|
|
104
|
+
}
|
|
105
|
+
interface KernelSortTerm {
|
|
106
|
+
col: number;
|
|
107
|
+
dir: 'asc' | 'desc';
|
|
108
|
+
}
|
|
109
|
+
interface KernelFilterClause {
|
|
110
|
+
col: number;
|
|
111
|
+
op: '=' | '!=' | '>' | '<' | '>=' | '<=' | '~' | '!~' | '^~' | '$~';
|
|
112
|
+
value: string;
|
|
113
|
+
/** Case-sensitive text matching (the grammar's `*` modifier). */
|
|
114
|
+
caseSensitive?: boolean;
|
|
115
|
+
}
|
|
116
|
+
interface KernelCellEdit {
|
|
117
|
+
rowId: number;
|
|
118
|
+
col: number;
|
|
119
|
+
value: number | string | boolean | null;
|
|
120
|
+
}
|
|
121
|
+
type KernelRequest = {
|
|
122
|
+
type: 'init';
|
|
123
|
+
seq: number;
|
|
124
|
+
columns: KernelColumnPayload[];
|
|
125
|
+
rowCount: number;
|
|
126
|
+
} | {
|
|
127
|
+
type: 'setView';
|
|
128
|
+
seq: number;
|
|
129
|
+
sort: KernelSortTerm[];
|
|
130
|
+
filter: KernelFilterClause[];
|
|
131
|
+
} | {
|
|
132
|
+
type: 'rows';
|
|
133
|
+
seq: number;
|
|
134
|
+
start: number;
|
|
135
|
+
count: number;
|
|
136
|
+
} | {
|
|
137
|
+
type: 'applyEdits';
|
|
138
|
+
seq: number;
|
|
139
|
+
edits: KernelCellEdit[];
|
|
140
|
+
} | {
|
|
141
|
+
type: 'distinct';
|
|
142
|
+
seq: number;
|
|
143
|
+
col: number;
|
|
144
|
+
limit: number;
|
|
145
|
+
} | {
|
|
146
|
+
type: 'dispose';
|
|
147
|
+
};
|
|
148
|
+
type KernelCell = number | string | boolean | null;
|
|
149
|
+
type KernelResponse = {
|
|
150
|
+
type: 'ready';
|
|
151
|
+
seq: number;
|
|
152
|
+
} | {
|
|
153
|
+
type: 'viewResult';
|
|
154
|
+
seq: number;
|
|
155
|
+
viewRowCount: number;
|
|
156
|
+
} | {
|
|
157
|
+
type: 'rowsResult';
|
|
158
|
+
seq: number;
|
|
159
|
+
start: number;
|
|
160
|
+
rowIds: number[];
|
|
161
|
+
cells: KernelCell[][];
|
|
162
|
+
} | {
|
|
163
|
+
type: 'editResult';
|
|
164
|
+
seq: number;
|
|
165
|
+
staleView: boolean;
|
|
166
|
+
} | {
|
|
167
|
+
type: 'distinctResult';
|
|
168
|
+
seq: number;
|
|
169
|
+
values: string[];
|
|
170
|
+
totalDistinct: number;
|
|
171
|
+
hasBlank: boolean;
|
|
172
|
+
} | {
|
|
173
|
+
type: 'error';
|
|
174
|
+
seq: number;
|
|
175
|
+
message: string;
|
|
176
|
+
};
|
|
177
|
+
/** The structural slice of a worker global scope the kernel needs. */
|
|
178
|
+
interface KernelScope {
|
|
179
|
+
onmessage: ((event: {
|
|
180
|
+
data: KernelRequest;
|
|
181
|
+
}) => void) | null;
|
|
182
|
+
postMessage(message: KernelResponse): void;
|
|
183
|
+
}
|
|
184
|
+
declare function tableKernel(scope: KernelScope): void;
|
|
185
|
+
/** The worker source: the kernel applied to the worker's own global scope. */
|
|
186
|
+
declare function buildKernelSource(): string;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* TableStoreClient — the in-house columnar store behind the
|
|
190
|
+
* `TableQueryProvider` contract. Compute (filter/sort/window/edit) runs in
|
|
191
|
+
* the kernel; the kernel runs in a Blob-URL Web Worker when available and
|
|
192
|
+
* falls back to an in-process host otherwise (SSR, tests — the fallback is
|
|
193
|
+
* also the protocol-parity proof, since both paths execute the SAME
|
|
194
|
+
* `tableKernel` source).
|
|
195
|
+
*
|
|
196
|
+
* Transfer note: typed-array halves of the columns are TRANSFERRED to the
|
|
197
|
+
* worker (zero-copy); dictionaries are structured-cloned. After `init` the
|
|
198
|
+
* client's own column buffers are detached — the client keeps only the
|
|
199
|
+
* schema; the ingest source stays with the adapter (it owns save).
|
|
200
|
+
*/
|
|
201
|
+
|
|
202
|
+
interface KernelHost {
|
|
203
|
+
post(message: KernelRequest, transfer?: Transferable[]): void;
|
|
204
|
+
onResponse: (message: KernelResponse) => void;
|
|
205
|
+
terminate(): void;
|
|
206
|
+
}
|
|
207
|
+
/** In-process host: drives `tableKernel` directly (SSR/tests/parity). */
|
|
208
|
+
declare class LocalKernelHost implements KernelHost {
|
|
209
|
+
onResponse: (message: KernelResponse) => void;
|
|
210
|
+
private readonly scope;
|
|
211
|
+
constructor();
|
|
212
|
+
post(message: KernelRequest): void;
|
|
213
|
+
terminate(): void;
|
|
214
|
+
}
|
|
215
|
+
interface TableStoreClientOptions {
|
|
216
|
+
/** Force the in-process host (tests, SSR probes). */
|
|
217
|
+
forceLocal?: boolean;
|
|
218
|
+
}
|
|
219
|
+
declare class TableStoreClient implements TableQueryProvider {
|
|
220
|
+
private readonly host;
|
|
221
|
+
private readonly schema;
|
|
222
|
+
private seq;
|
|
223
|
+
private viewRowCount;
|
|
224
|
+
private readonly pending;
|
|
225
|
+
private ready;
|
|
226
|
+
constructor(table: IngestTable, options?: TableStoreClientOptions);
|
|
227
|
+
private request;
|
|
228
|
+
describe(): Promise<TableSchema>;
|
|
229
|
+
setView(view: TableViewState): Promise<TableViewResult>;
|
|
230
|
+
rows(start: number, count: number): Promise<TableRowsPage>;
|
|
231
|
+
applyEdits(edits: TableCellEdit[]): Promise<TableEditResult>;
|
|
232
|
+
distinct(col: number, limit: number): Promise<TableDistinctResult>;
|
|
233
|
+
/** Row count under the current view (post-filter). */
|
|
234
|
+
get currentViewRowCount(): number;
|
|
235
|
+
dispose(): void;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* EditJournal — unsaved cell edits, keyed by immutable source row id.
|
|
240
|
+
*
|
|
241
|
+
* Lives on the MAIN thread beside the store client. Row identity is the
|
|
242
|
+
* source row index assigned at ingest, so an entry is unambiguous under any
|
|
243
|
+
* sort/filter permutation and unaffected by edits changing sort keys —
|
|
244
|
+
* identity was never derived from values.
|
|
245
|
+
*
|
|
246
|
+
* Batches are the undo unit (one commit = one batch). The journal is
|
|
247
|
+
* additionally cached module-level by `(cacheKey)` — conventionally
|
|
248
|
+
* `${path}@${mediaRevision}` — so a widget unmount/remount (ProseMirror
|
|
249
|
+
* re-decoration) does not lose unsaved edits; a revision bump (save or
|
|
250
|
+
* re-upload) naturally misses the cache and starts clean.
|
|
251
|
+
*/
|
|
252
|
+
|
|
253
|
+
interface JournalEntry {
|
|
254
|
+
rowId: number;
|
|
255
|
+
col: number;
|
|
256
|
+
prev: TableCellValue;
|
|
257
|
+
next: TableCellValue;
|
|
258
|
+
}
|
|
259
|
+
declare class EditJournal {
|
|
260
|
+
/** Latest value per cell, keyed `rowId:col`. */
|
|
261
|
+
private readonly latest;
|
|
262
|
+
private readonly undoStack;
|
|
263
|
+
private readonly redoStack;
|
|
264
|
+
get dirtyCount(): number;
|
|
265
|
+
get canUndo(): boolean;
|
|
266
|
+
get canRedo(): boolean;
|
|
267
|
+
isDirty(rowId: number, col: number): boolean;
|
|
268
|
+
/** Record one committed batch of edits. Clears the redo stack. */
|
|
269
|
+
commit(entries: JournalEntry[]): void;
|
|
270
|
+
/** Pop the latest batch; returns the INVERSE edits to apply to the store. */
|
|
271
|
+
undo(): TableCellEdit[];
|
|
272
|
+
/** Re-apply the most recently undone batch. */
|
|
273
|
+
redo(): TableCellEdit[];
|
|
274
|
+
/** Net outstanding edits (what a Save must persist). */
|
|
275
|
+
entries(): JournalEntry[];
|
|
276
|
+
clear(): void;
|
|
277
|
+
private applyLatest;
|
|
278
|
+
private rebuildLatest;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Get (or create) the journal for a cache key. Any entry for the same path
|
|
282
|
+
* at a DIFFERENT revision is discarded — a revision bump means the bytes
|
|
283
|
+
* changed underneath the edits.
|
|
284
|
+
*/
|
|
285
|
+
declare function journalFor(path: string, revision: number): EditJournal;
|
|
286
|
+
declare function discardJournal(path: string): void;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* DataGrid — the virtualized grid over a `TableQueryProvider`.
|
|
290
|
+
*
|
|
291
|
+
* Rendering model: TanStack Virtual drives ROW virtualization only (at the
|
|
292
|
+
* ~20-column design target, column virtualization buys nothing and costs
|
|
293
|
+
* sticky-header/selection complexity); columns are a CSS grid template from
|
|
294
|
+
* the width map. The grid owns a bounded scroll container
|
|
295
|
+
* (`overscroll-behavior: contain`) — it never scrolls the document.
|
|
296
|
+
*
|
|
297
|
+
* Interaction contract (kept in sync with the plan spec):
|
|
298
|
+
* - selection: rectangular `{anchor, focus}` in view coordinates; roving
|
|
299
|
+
* tabIndex on the focused cell (real focus — the cell editor needs it);
|
|
300
|
+
* - keyboard: arrows move, Shift extends, Ctrl/Cmd jumps to data edges,
|
|
301
|
+
* PageUp/Down by viewport, Home/End row-wise, Ctrl/Cmd+Home/End
|
|
302
|
+
* grid-wise, Enter commits+moves down, Tab commits+moves right, F2 or
|
|
303
|
+
* typing opens the editor, Escape cancels, Ctrl/Cmd+A selects all,
|
|
304
|
+
* Ctrl/Cmd+Z / +Shift+Z drive the edit journal;
|
|
305
|
+
* - clipboard: `copy` writes TSV (`text/plain`) + `<table>` (`text/html`)
|
|
306
|
+
* from the selection prefetch cache (capped; truncation is announced);
|
|
307
|
+
* - edits: committed per cell through `provider.applyEdits` + the journal;
|
|
308
|
+
* the view is NEVER auto re-sorted after an edit — `staleView` drives an
|
|
309
|
+
* explicit refresh affordance instead;
|
|
310
|
+
* - sort headers cycle asc → desc → none; Shift+click appends a term.
|
|
311
|
+
*
|
|
312
|
+
* Theming: every color resolves through `--squisq-grid-*` tokens with
|
|
313
|
+
* literal fallbacks (see styles/grid.css) so the grid works standalone;
|
|
314
|
+
* editor-react aliases the tokens onto its chrome palette.
|
|
315
|
+
*/
|
|
316
|
+
|
|
317
|
+
interface DataGridProps {
|
|
318
|
+
provider: TableQueryProvider;
|
|
319
|
+
/** Present = editable; the journal records batches for undo + save. */
|
|
320
|
+
journal?: EditJournal;
|
|
321
|
+
view: TableViewState;
|
|
322
|
+
onViewChange?: (view: TableViewState) => void;
|
|
323
|
+
/** False = view state is session-only ("not saved to document" hint). */
|
|
324
|
+
viewPersisted?: boolean;
|
|
325
|
+
onSave?: () => void | Promise<void>;
|
|
326
|
+
saving?: boolean;
|
|
327
|
+
height?: number;
|
|
328
|
+
/** Reason editing is unavailable (e.g. parquet sidecars). */
|
|
329
|
+
readOnlyReason?: string;
|
|
330
|
+
/**
|
|
331
|
+
* Per-cell lock predicate (source row id + column). A locked cell renders
|
|
332
|
+
* with a lock affordance and refuses edits while its neighbors stay
|
|
333
|
+
* editable — how XLSX keeps formula/date cells safe from value patching.
|
|
334
|
+
*/
|
|
335
|
+
isCellLocked?: (rowId: number, col: number) => boolean;
|
|
336
|
+
/** Tooltip/announcement for locked cells. */
|
|
337
|
+
lockedReason?: string;
|
|
338
|
+
/**
|
|
339
|
+
* Formula editing, when the host has a calculation engine. A cell whose
|
|
340
|
+
* `getFormula` returns text edits as `=formula`; any committed draft
|
|
341
|
+
* starting with `=` routes through `commitFormula`, whose returned
|
|
342
|
+
* `updates` (the edited cell plus recalculated dependents) are applied to
|
|
343
|
+
* the provider and the visible cache.
|
|
344
|
+
*/
|
|
345
|
+
formulaSupport?: FormulaSupport;
|
|
346
|
+
/**
|
|
347
|
+
* Notified after each committed VALUE edit. A host mirroring edits into a
|
|
348
|
+
* calculation engine may RETURN the recalculated dependent updates, which
|
|
349
|
+
* the grid applies to the provider and the visible cache — this is what
|
|
350
|
+
* makes formula cells recalc live when a plain value changes.
|
|
351
|
+
*/
|
|
352
|
+
onCellEdited?: (edit: TableCellEdit) => void | TableCellEdit[] | Promise<void | TableCellEdit[]>;
|
|
353
|
+
/** Unsaved formula edits (kept outside the value journal) for the save bar. */
|
|
354
|
+
extraDirtyCount?: number;
|
|
355
|
+
/**
|
|
356
|
+
* Discard handler for those formula edits (runs beside journal discard).
|
|
357
|
+
* The host reverts its engine + provider; the grid then refetches.
|
|
358
|
+
*/
|
|
359
|
+
onDiscardExtra?: () => void | Promise<void>;
|
|
360
|
+
className?: string;
|
|
361
|
+
}
|
|
362
|
+
interface FormulaCommitResult {
|
|
363
|
+
ok: boolean;
|
|
364
|
+
/** User-facing message when `ok` is false (parse error, budget, …). */
|
|
365
|
+
error?: string;
|
|
366
|
+
/** Value updates to apply: the edited cell + recalculated dependents. */
|
|
367
|
+
updates?: TableCellEdit[];
|
|
368
|
+
}
|
|
369
|
+
interface FormulaSupport {
|
|
370
|
+
/** Formula source (no `=`) for a cell, or undefined for plain values. */
|
|
371
|
+
getFormula(rowId: number, col: number): string | undefined;
|
|
372
|
+
commitFormula(rowId: number, col: number, formula: string): Promise<FormulaCommitResult>;
|
|
373
|
+
}
|
|
374
|
+
declare function DataGrid({ provider, journal, view, onViewChange, viewPersisted, onSave, saving, height, readOnlyReason, isCellLocked, lockedReason, formulaSupport, onCellEdited, extraDirtyCount, onDiscardExtra, className, }: DataGridProps): ReactElement;
|
|
375
|
+
|
|
376
|
+
export { type ColumnarTable, DataGrid, type DataGridProps, EditJournal, type FormulaCommitResult, type FormulaSupport, type IngestCell, type IngestColumnHint, type IngestTable, type JournalEntry, type KernelCellEdit, type KernelColumnPayload, type KernelRequest, type KernelResponse, type KernelScope, LocalKernelHost, type StoreColumn, TableStoreClient, type TableStoreClientOptions, buildColumnarTable, buildKernelSource, columnCellValue, discardJournal, journalFor, tableKernel };
|