@kermodes/grid 0.0.0-stage → 0.3.13-dev.68.g32b767a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/ColumnHeaderGroup.d.ts +8 -0
  2. package/dist/ContextMenu.d.ts +15 -0
  3. package/dist/EventHandlerResult.d.ts +16 -0
  4. package/dist/FilterBar.d.ts +32 -0
  5. package/dist/Grid.d.ts +458 -0
  6. package/dist/GridAxisRange.d.ts +9 -0
  7. package/dist/GridMetricCalculator.d.ts +509 -0
  8. package/dist/GridMetrics.d.ts +125 -0
  9. package/dist/GridModel.d.ts +96 -0
  10. package/dist/GridMouseHandler.d.ts +29 -0
  11. package/dist/GridRange.d.ts +268 -0
  12. package/dist/GridRenderer.d.ts +159 -0
  13. package/dist/GridRendererTypes.d.ts +25 -0
  14. package/dist/GridSelectionUtils.d.ts +97 -0
  15. package/dist/GridStyles.d.ts +2 -0
  16. package/dist/GridTheme.d.ts +96 -0
  17. package/dist/GridUtils.d.ts +457 -0
  18. package/dist/KeyHandler.d.ts +33 -0
  19. package/dist/RangedSelection.d.ts +118 -0
  20. package/dist/Selection.d.ts +218 -0
  21. package/dist/TableViewer.d.ts +16 -0
  22. package/dist/TableViewerGrid.d.ts +16 -0
  23. package/dist/TextCellRenderer.d.ts +8 -0
  24. package/dist/ThemeContext.d.ts +5 -0
  25. package/dist/ValuePopover.d.ts +23 -0
  26. package/dist/ViewportGridModel.d.ts +92 -0
  27. package/dist/cellValue.d.ts +11 -0
  28. package/dist/copy.d.ts +29 -0
  29. package/dist/cover.d.ts +16 -0
  30. package/dist/errors/AssertionError.d.ts +4 -0
  31. package/dist/errors/assertIsDefined.d.ts +2 -0
  32. package/dist/errors/index.d.ts +2 -0
  33. package/dist/fastMemoize.d.ts +50 -0
  34. package/dist/index.d.ts +32 -0
  35. package/dist/index.js +7909 -0
  36. package/dist/key-handlers/SelectionKeyHandler.d.ts +11 -0
  37. package/dist/key-handlers/index.d.ts +1 -0
  38. package/dist/menuItems.d.ts +53 -0
  39. package/dist/mouse-handlers/GridColumnMoveMouseHandler.d.ts +50 -0
  40. package/dist/mouse-handlers/GridColumnSeparatorMouseHandler.d.ts +27 -0
  41. package/dist/mouse-handlers/GridHorizontalScrollBarMouseHandler.d.ts +24 -0
  42. package/dist/mouse-handlers/GridScrollBarCornerMouseHandler.d.ts +14 -0
  43. package/dist/mouse-handlers/GridSelectionMouseHandler.d.ts +19 -0
  44. package/dist/mouse-handlers/GridSeparatorMouseHandler.d.ts +61 -0
  45. package/dist/mouse-handlers/GridVerticalScrollBarMouseHandler.d.ts +24 -0
  46. package/dist/mouse-handlers/index.d.ts +8 -0
  47. package/dist/sorting.d.ts +19 -0
  48. package/dist/utils.d.ts +15 -0
  49. package/package.json +28 -3
  50. package/README.md +0 -3
@@ -0,0 +1,118 @@
1
+ import GridRange, { type GridRangeIndex, type SELECTION_DIRECTION } from './GridRange';
2
+ import type { VisibleIndex } from './GridMetrics';
3
+ import { type BoundedAxisRange } from './GridAxisRange';
4
+ import type { CommitGestureOptions, GestureExtendOptions, GetModel, Selection, TickRangeSelection } from './Selection';
5
+ /**
6
+ * Immutable `Selection` for standard (row-indexed) grids. Each entry in
7
+ * `ranges` describes a rectangle of cells; consumers iterate/consolidate
8
+ * as needed.
9
+ */
10
+ export declare class RangedSelection implements Selection, TickRangeSelection {
11
+ /** Committed selection rectangles; may be empty for a cleared selection. */
12
+ readonly ranges: readonly GridRange[];
13
+ /**
14
+ * Deferred lookup for the current `GridModel`. Passed as a closure
15
+ * (not a direct reference) so this Selection always reads the model
16
+ * currently on `Grid.props.model` — surviving prop swaps without
17
+ * holding a stale reference.
18
+ */
19
+ private readonly getModel;
20
+ /** Anchor row for shift-click / keyboard extend; null when no anchor is set. */
21
+ private readonly gestureStartRow;
22
+ /** Anchor column for shift-click / keyboard extend; null when no anchor is set. */
23
+ private readonly gestureStartColumn;
24
+ /** Focus row; null when no cursor is set. */
25
+ readonly cursorRow: VisibleIndex | null;
26
+ /** Focus column; null when no cursor is set. */
27
+ readonly cursorColumn: VisibleIndex | null;
28
+ /** Last shift/drag endpoint row; null when unset. */
29
+ readonly selectionEndRow: VisibleIndex | null;
30
+ /** Last shift/drag endpoint column; null when unset. */
31
+ readonly selectionEndColumn: VisibleIndex | null;
32
+ static empty(getModel: GetModel): RangedSelection;
33
+ constructor(
34
+ /** Committed selection rectangles; may be empty for a cleared selection. */
35
+ ranges: readonly GridRange[],
36
+ /**
37
+ * Deferred lookup for the current `GridModel`. Passed as a closure
38
+ * (not a direct reference) so this Selection always reads the model
39
+ * currently on `Grid.props.model` — surviving prop swaps without
40
+ * holding a stale reference.
41
+ */
42
+ getModel: GetModel,
43
+ /** Anchor row for shift-click / keyboard extend; null when no anchor is set. */
44
+ gestureStartRow?: GridRangeIndex,
45
+ /** Anchor column for shift-click / keyboard extend; null when no anchor is set. */
46
+ gestureStartColumn?: GridRangeIndex,
47
+ /** Focus row; null when no cursor is set. */
48
+ cursorRow?: VisibleIndex | null,
49
+ /** Focus column; null when no cursor is set. */
50
+ cursorColumn?: VisibleIndex | null,
51
+ /** Last shift/drag endpoint row; null when unset. */
52
+ selectionEndRow?: VisibleIndex | null,
53
+ /** Last shift/drag endpoint column; null when unset. */
54
+ selectionEndColumn?: VisibleIndex | null);
55
+ /**
56
+ * Returns a copy with the given fields overridden. Unspecified fields
57
+ * carry through from `this`, so mutations that only touch ranges /
58
+ * anchor keep cursor + endpoint intact without extra bookkeeping at
59
+ * every call site.
60
+ */
61
+ private copyWith;
62
+ isEmpty(): boolean;
63
+ isCellSelected(column: VisibleIndex, row: VisibleIndex): boolean;
64
+ isRowSelected(row: VisibleIndex): boolean;
65
+ isColumnSelected(column: VisibleIndex): boolean;
66
+ /**
67
+ * Checks if all ranges are within the bounds of the grid model.
68
+ * @returns True if all ranges are within bounds, false otherwise.
69
+ */
70
+ isInBounds(): boolean;
71
+ toRanges(): readonly GridRange[];
72
+ getColumnTickRanges(): readonly BoundedAxisRange[];
73
+ getRowTickRanges(): readonly BoundedAxisRange[];
74
+ private cachedColumnTickRanges;
75
+ private cachedRowTickRanges;
76
+ withCommittedRanges(ranges: readonly GridRange[], anchor?: {
77
+ row: GridRangeIndex;
78
+ column: GridRangeIndex;
79
+ }): RangedSelection;
80
+ /**
81
+ * Sets the gesture anchor (extend-from position for shift-click and
82
+ * keyboard extend) to the given cell. Passing `null` for both clears it.
83
+ */
84
+ private withGestureAnchor;
85
+ /**
86
+ * The current `{row, column}` of the gesture anchor, or `null` if none is set.
87
+ */
88
+ private getGestureAnchor;
89
+ selectAll(): RangedSelection;
90
+ getNextCursorInDirection(current: {
91
+ row: GridRangeIndex;
92
+ column: GridRangeIndex;
93
+ }, direction: SELECTION_DIRECTION): {
94
+ row: GridRangeIndex;
95
+ column: GridRangeIndex;
96
+ } | null;
97
+ private getCursorLandingCell;
98
+ withCursor(row: VisibleIndex | null, column: VisibleIndex | null): RangedSelection;
99
+ withSelectionEnd(row: VisibleIndex | null, column: VisibleIndex | null): RangedSelection;
100
+ withGestureExtend(cursor: {
101
+ row: GridRangeIndex;
102
+ column: GridRangeIndex;
103
+ }, opts: GestureExtendOptions): RangedSelection;
104
+ commitGesture(lastCommitted: Selection, opts: CommitGestureOptions): RangedSelection;
105
+ clear(): RangedSelection;
106
+ trimmed(): RangedSelection;
107
+ truncate(maxRows: number): RangedSelection;
108
+ }
109
+ export declare function isRangedSelection(selection: Selection): selection is RangedSelection;
110
+ export declare function assertIsRangedSelection(selection: Selection): asserts selection is RangedSelection;
111
+ /**
112
+ * Returns `selection.toRanges()` when `selection` is a `RangedSelection`,
113
+ * otherwise `EMPTY_ARRAY`. Handy for consumers that only care about the
114
+ * range-form projection of a selection (e.g. legacy `selectedRanges`
115
+ * callbacks) and want a stable empty array for keyed / null selections.
116
+ */
117
+ export declare function selectionToRanges(selection: Selection | null | undefined): readonly GridRange[];
118
+ export default RangedSelection;
@@ -0,0 +1,218 @@
1
+ import type GridRange from './GridRange';
2
+ import type { GridRangeIndex, SELECTION_DIRECTION } from './GridRange';
3
+ import type GridModel from './GridModel';
4
+ import type { VisibleIndex } from './GridMetrics';
5
+ import type { BoundedAxisRange } from './GridAxisRange';
6
+ /** Provides current model data to Selection instances without holding a stale reference. */
7
+ export type GetModel = () => GridModel;
8
+ /**
9
+ * Immutable value object representing the current selection state of the grid.
10
+ * Mutations return new instances; Grid stores the result in React state.
11
+ *
12
+ * Composed from five sub-interfaces:
13
+ * - `SelectionQueries` — read-only inspection.
14
+ * - `SelectionTransforms` — immutable transforms with no external dependencies.
15
+ * - `ProgrammaticSelection` — programmatic write path (`Grid.setSelectedRanges`).
16
+ * - `MouseSelection` — mouse-driven gestures (click, shift-click, drag).
17
+ * - `KeyboardSelection` — keyboard-driven queries (Tab/Enter advance, cursor
18
+ * landing after commit).
19
+ */
20
+ export interface Selection extends SelectionQueries, SelectionTransforms, ProgrammaticSelection, MouseSelection, KeyboardSelection {
21
+ }
22
+ /** Read-only inspection of a `Selection`. Every method is side-effect-free. */
23
+ export interface SelectionQueries {
24
+ /** True when the selection contains no cells and no in-progress gesture. */
25
+ isEmpty: () => boolean;
26
+ /** True when `(column, row)` is part of the selection. */
27
+ isCellSelected: (column: VisibleIndex, row: VisibleIndex) => boolean;
28
+ /** True when the entire row is part of the selection. */
29
+ isRowSelected: (row: VisibleIndex) => boolean;
30
+ /** True when the entire column is part of the selection. */
31
+ isColumnSelected: (column: VisibleIndex) => boolean;
32
+ /** The focus cell's row, or `null` when there is no cursor set. */
33
+ readonly cursorRow: VisibleIndex | null;
34
+ /** The focus cell's column, or `null` when there is no cursor set. */
35
+ readonly cursorColumn: VisibleIndex | null;
36
+ /** Row of the last shift/drag endpoint, or `null` when unset. */
37
+ readonly selectionEndRow: VisibleIndex | null;
38
+ /** Column of the last shift/drag endpoint, or `null` when unset. */
39
+ readonly selectionEndColumn: VisibleIndex | null;
40
+ }
41
+ /**
42
+ * Optional capability implemented by selections that can project onto
43
+ * scrollbar tick marks. Ranges are returned sorted by start and merged so
44
+ * consumers can iterate directly without re-normalizing per frame.
45
+ */
46
+ export interface TickRangeSelection {
47
+ /**
48
+ * Sorted, non-overlapping column `[start, end]` pairs for scrollbar tick
49
+ * rendering.
50
+ */
51
+ getColumnTickRanges: () => readonly BoundedAxisRange[];
52
+ /**
53
+ * Sorted, non-overlapping row `[start, end]` pairs for scrollbar tick
54
+ * rendering.
55
+ */
56
+ getRowTickRanges: () => readonly BoundedAxisRange[];
57
+ }
58
+ export declare function isTickRangeSelection(selection: Selection): selection is Selection & TickRangeSelection;
59
+ /**
60
+ * Immutable transformations of a `Selection` that need no external context.
61
+ * Each method returns a new `Selection`; the receiver is never modified.
62
+ */
63
+ export interface SelectionTransforms {
64
+ /** A fresh empty selection with no committed state, overlay, or anchor. */
65
+ clear: () => Selection;
66
+ /**
67
+ * A new selection keeping only the last committed range (for
68
+ * `RangedSelection`) or clearing committed keys (for `KeyedSelection`).
69
+ * Called by `Grid.trimSelectedRanges` immediately before shift-based
70
+ * extend so the anchor is preserved.
71
+ */
72
+ trimmed: () => Selection;
73
+ /** A new selection covering the entire grid. */
74
+ selectAll: () => Selection;
75
+ /** A new selection containing at most `maxRows` rows. */
76
+ truncate: (maxRows: number) => Selection;
77
+ }
78
+ /**
79
+ * Programmatic write path: install a caller-supplied set of ranges as the
80
+ * committed selection. Used by `Grid.setSelectedRanges`, `setFocusRow`, and
81
+ * `moveCursorInDirection`. Distinct from gesture-driven writes, which are
82
+ * being reworked in the `MouseSelection` / `KeyboardSelection` interfaces.
83
+ */
84
+ export interface ProgrammaticSelection {
85
+ /**
86
+ * Replaces the committed selection with the given ranges and clears any
87
+ * transient overlay state. When `anchor` is provided, sets the gesture
88
+ * anchor (extend-from position for shift-click and keyboard extend) to
89
+ * the given cell; otherwise clears it.
90
+ */
91
+ withCommittedRanges: (ranges: readonly GridRange[], anchor?: {
92
+ row: GridRangeIndex;
93
+ column: GridRangeIndex;
94
+ }) => Selection;
95
+ }
96
+ /**
97
+ * Modifier-key-derived mode for a mouse gesture:
98
+ * - `replace` — plain click: clear the current selection and install a
99
+ * single cell at the cursor.
100
+ * - `add` — ctrl/meta click: keep the current selection and add a single
101
+ * cell at the cursor.
102
+ * - `extend` — shift click / drag: trim to the last range and extend it
103
+ * from the gesture anchor to the cursor.
104
+ * - `maximize` — ctrl+shift click: keep all ranges, grow the last range
105
+ * to include the cursor.
106
+ */
107
+ export type GestureMode = 'replace' | 'add' | 'extend' | 'maximize';
108
+ /** Options for `MouseSelection.withGestureExtend`. */
109
+ export type GestureExtendOptions = {
110
+ /** How the current selection should be combined with the incoming cursor. */
111
+ mode: GestureMode;
112
+ /** Full-row selection mode (theme `autoSelectRow`). */
113
+ autoSelectRow: boolean;
114
+ /** Full-column selection mode (theme `autoSelectColumn`). */
115
+ autoSelectColumn: boolean;
116
+ };
117
+ /** Options for `MouseSelection.commitGesture`. */
118
+ export type CommitGestureOptions = {
119
+ /**
120
+ * When true, a single-row commit that repeats the previous single-row
121
+ * selection is treated as a deselect. Matches the `autoSelectRow` theme
122
+ * flag semantic.
123
+ */
124
+ autoSelectRow: boolean;
125
+ /**
126
+ * Post-commit cursor position. When `settled` is non-empty and this
127
+ * cursor falls outside it, `commitGesture` substitutes a landing cell
128
+ * from the pre-commit selection. When `settled` is empty, this cursor
129
+ * is preserved on the returned selection (matches Escape semantics).
130
+ * Omit for no-op commits that shouldn't touch cursor.
131
+ */
132
+ cursor?: {
133
+ row: GridRangeIndex;
134
+ column: GridRangeIndex;
135
+ };
136
+ /**
137
+ * When true (default), a commit whose settled ranges match the previous
138
+ * single-row / single-cell committed selection is treated as a deselect.
139
+ * This is the mouse click-to-deselect affordance. Keyboard callers pass
140
+ * `false` so arrowing onto an already-selected cell just moves the cursor
141
+ * instead of clearing the selection.
142
+ */
143
+ allowDeselect?: boolean;
144
+ /**
145
+ * When true (default), the commit finalizes the gesture: deselect check,
146
+ * hole-punch on overlap, and range consolidation all run. Pass `false`
147
+ * from mouse-down so those steps defer to mouse-up; between them the
148
+ * drag can grow the last range without eagerly fragmenting the prior
149
+ * selection.
150
+ */
151
+ settle?: boolean;
152
+ };
153
+ /**
154
+ * Mouse-driven selection updates. Both `withGestureExtend` and
155
+ * `commitGesture` are called by `Grid`'s mouse handlers.
156
+ *
157
+ * A gesture starts on mouse-down, may extend across drag frames, and settles
158
+ * on mouse-up. Each drag frame calls `withGestureExtend` to update the
159
+ * transient overlay; `commitGesture` folds the overlay into the committed
160
+ * selection.
161
+ */
162
+ export interface MouseSelection {
163
+ /**
164
+ * Applies a mouse gesture that moves the selection to `cursor` per `opts`.
165
+ * `mode` chooses replace / add / extend / maximize semantics based on the
166
+ * modifier keys the caller observed.
167
+ *
168
+ * Returns a transient overlay-updated selection. Caller controls when to
169
+ * `commitGesture` — mouse handlers commit on mouse-up only; a plain click
170
+ * commits immediately.
171
+ */
172
+ withGestureExtend: (cursor: {
173
+ row: GridRangeIndex;
174
+ column: GridRangeIndex;
175
+ }, opts: GestureExtendOptions) => Selection;
176
+ /**
177
+ * Settles the current transient overlay into the committed selection.
178
+ * Handles consolidation, deselect-on-reclick, and subtract logic. Returns
179
+ * identity (`this`) when there is nothing to commit.
180
+ *
181
+ * `lastCommitted` is the selection state as it was BEFORE the current
182
+ * gesture began. Grid pins this in state at gesture-start so the
183
+ * deselect-on-reclick comparison stays stable across drag frames.
184
+ */
185
+ commitGesture: (lastCommitted: Selection, opts: CommitGestureOptions) => Selection;
186
+ }
187
+ /**
188
+ * Keyboard-driven selection queries. Grid's key handlers use these to advance
189
+ * the cursor within the current selection (Tab/Enter) and to place the cursor
190
+ * after a commit or programmatic install.
191
+ */
192
+ export interface KeyboardSelection {
193
+ /**
194
+ * Returns the next cursor cell in `direction` starting from `current`.
195
+ * When the selection is empty or has exactly one cell, walks the whole
196
+ * grid (wrapping at edges) so a lone Tab still moves the cursor.
197
+ * Otherwise cycles through the currently selected ranges.
198
+ */
199
+ getNextCursorInDirection: (current: {
200
+ row: GridRangeIndex;
201
+ column: GridRangeIndex;
202
+ }, direction: SELECTION_DIRECTION) => {
203
+ row: GridRangeIndex;
204
+ column: GridRangeIndex;
205
+ } | null;
206
+ /**
207
+ * A new selection with the cursor set to `(column, row)`. Passing `null`
208
+ * for both clears the cursor. Non-cursor state (ranges, keys, anchor,
209
+ * selection endpoint) is preserved.
210
+ */
211
+ withCursor: (row: VisibleIndex | null, column: VisibleIndex | null) => Selection;
212
+ /**
213
+ * A new selection with the shift/drag endpoint set to `(column, row)`.
214
+ * Passing `null` for both clears the endpoint. Non-endpoint state
215
+ * (ranges, keys, anchor, cursor) is preserved.
216
+ */
217
+ withSelectionEnd: (row: VisibleIndex | null, column: VisibleIndex | null) => Selection;
218
+ }
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { type GridTheme } from './GridTheme';
3
+ import { type ViewerChannel } from '@kermodes/client';
4
+ export type TableViewerProps = {
5
+ channel: ViewerChannel;
6
+ theme: GridTheme;
7
+ maxGridHeight?: number;
8
+ follow?: boolean;
9
+ };
10
+ /**
11
+ * The table viewer (architecture.md §15.3): the canvas grid over a viewport of
12
+ * an engine table, with header sort, quick filters, copy, change highlighting,
13
+ * and a status line. Talks to the engine only through `channel`.
14
+ */
15
+ export declare function TableViewer({ channel, theme, maxGridHeight, follow, }: TableViewerProps): React.ReactElement;
16
+ export default TableViewer;
@@ -0,0 +1,16 @@
1
+ import GridMetricCalculator, { type GridMetricState } from './GridMetricCalculator';
2
+ import { type ModelIndex, type VisibleIndex } from './GridMetrics';
3
+ import GridRenderer from './GridRenderer';
4
+ import { type GridRenderState } from './GridRendererTypes';
5
+ /** Column widths leave room in the header for the sort indicator, so sorting never resizes */
6
+ export declare class TableViewerMetricCalculator extends GridMetricCalculator {
7
+ calculateColumnHeaderWidth(modelColumn: ModelIndex, state: GridMetricState, maxColumnWidth: number): number;
8
+ }
9
+ /** Draws the sort in the headers and flashes over changed or copied cells */
10
+ export declare class TableViewerRenderer extends GridRenderer {
11
+ drawColumnHeaderAtIndex(context: CanvasRenderingContext2D, state: GridRenderState, index: VisibleIndex, bounds: {
12
+ minX: number;
13
+ maxX: number;
14
+ }): void;
15
+ drawCellBackgrounds(context: CanvasRenderingContext2D, state: GridRenderState): void;
16
+ }
@@ -0,0 +1,8 @@
1
+ import { type VisibleIndex } from './GridMetrics';
2
+ import { type GridRenderState } from './GridRendererTypes';
3
+ declare class TextCellRenderer {
4
+ drawCellContent(context: CanvasRenderingContext2D, state: GridRenderState, column: VisibleIndex, row: VisibleIndex): void;
5
+ private cachedTruncateToWidth;
6
+ getCachedTruncatedString: (context: CanvasRenderingContext2D, text: string, width: number, fontWidthLower?: number, fontWidthUpper?: number, truncationChar?: string) => string;
7
+ }
8
+ export default TextCellRenderer;
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import { type GridTheme as GridThemeType } from './GridTheme';
3
+ export type ThemeContextValue = Partial<GridThemeType>;
4
+ export declare const ThemeContext: React.Context<ThemeContextValue>;
5
+ export default ThemeContext;
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { type ShownValue } from './cellValue';
3
+ /** Where a cell is, relative to the positioned parent the popover is drawn in */
4
+ export type CellRect = {
5
+ x: number;
6
+ y: number;
7
+ width: number;
8
+ height: number;
9
+ };
10
+ export type ValuePopoverProps = {
11
+ cell: CellRect;
12
+ column: string;
13
+ type: string;
14
+ value: ShownValue;
15
+ onCopy: (text: string) => void;
16
+ onClose: () => void;
17
+ };
18
+ /**
19
+ * A cell's whole value under it (above it where there is no room below): JSON pretty-printed,
20
+ * selectable, with Copy. Escape or a click elsewhere closes it.
21
+ */
22
+ export declare function ValuePopover({ cell, column, type, value, onCopy, onClose, }: ValuePopoverProps): React.ReactElement;
23
+ export default ValuePopover;
@@ -0,0 +1,92 @@
1
+ import { type Table } from 'apache-arrow';
2
+ import GridModel from './GridModel';
3
+ import { type ModelIndex } from './GridMetrics';
4
+ import { type GridColor, type GridTheme, type NullableGridColor } from './GridTheme';
5
+ import { type SortKey, type ViewportColumn } from '@kermodes/client';
6
+ /** How long a changed or copied cell stays highlighted */
7
+ export declare const FLASH_DURATION_MS = 600;
8
+ export declare function isNumericType(type: string): boolean;
9
+ /** Format one non-null cell value of a column of `type` */
10
+ export declare function formatValue(type: string, value: unknown): string;
11
+ /** A pushed window of rows: their keys and a reader of their values */
12
+ export type RowWindow = {
13
+ keys: ArrayLike<bigint>;
14
+ value: (column: number, index: number) => unknown;
15
+ };
16
+ /**
17
+ * The cells of `next` whose value differs from the same row (by key) in `previous`.
18
+ * Rows that are new to `next` are not changes, however they got there (scrolled
19
+ * into view, filtered in), and neither are rows that only moved.
20
+ * @returns Pairs of row index in `next` and column
21
+ */
22
+ export declare function changedCells(previous: RowWindow, next: RowWindow, columnCount: number): Array<[index: number, column: number]>;
23
+ /**
24
+ * A grid model over a window of a larger table: the column list, the table's
25
+ * total row count, and the rows at positions `start..start + window.numRows`
26
+ * decoded from Arrow, with the key of each row. Rows outside the window read
27
+ * as empty (still loading). Also holds what the header shows (the sort) and
28
+ * which cells are flashing.
29
+ */
30
+ export declare class ViewportGridModel extends GridModel {
31
+ private viewColumns;
32
+ private totalRowCount;
33
+ private windowStart;
34
+ private windowRowCount;
35
+ private vectors;
36
+ private keys;
37
+ private keyIndex;
38
+ private textCache;
39
+ private sort;
40
+ private flashes;
41
+ private listeners;
42
+ constructor(columns?: readonly ViewportColumn[], rowCount?: number);
43
+ get rowCount(): number;
44
+ get columnCount(): number;
45
+ get columns(): readonly ViewportColumn[];
46
+ /** First row position held in the window */
47
+ get start(): number;
48
+ /** Call `listener` after every change; returns the function that stops it */
49
+ subscribe(listener: () => void): () => void;
50
+ private notify;
51
+ /** Replace the column list. Drops the window, whose columns no longer match. */
52
+ setColumns(columns: readonly ViewportColumn[]): void;
53
+ /** Set the total row count of the table */
54
+ setRowCount(rowCount: number): void;
55
+ /**
56
+ * Replace the window with the rows of `table`, which start at row position
57
+ * `start`, hold the columns in `columns` order, and have the given keys.
58
+ * Cells whose value changed since the last window, for the same key, flash.
59
+ */
60
+ setWindow(start: number, table: Table, keys: BigUint64Array, now?: number): void;
61
+ private rowWindow;
62
+ private clearWindow;
63
+ /** Set the sort the header shows */
64
+ setSort(sort: readonly SortKey[]): void;
65
+ get sortKeys(): readonly SortKey[];
66
+ /** The sort key on `column` and its 1-based priority, or null when unsorted */
67
+ sortForColumn(column: ModelIndex): {
68
+ descending: boolean;
69
+ priority: number;
70
+ } | null;
71
+ /** Whether the row at `row` has arrived */
72
+ isRowLoaded(row: ModelIndex): boolean;
73
+ /** The raw value at a cell: undefined when the row has not arrived, null for a null */
74
+ valueAt(column: ModelIndex, row: ModelIndex): unknown;
75
+ /** Start a flash on one cell, eg. to show it was copied */
76
+ flashCell(column: ModelIndex, row: ModelIndex, now?: number): void;
77
+ /** Whether any cell is still flashing at `now` */
78
+ hasFlashes(now?: number): boolean;
79
+ /**
80
+ * Call `draw` for each flashing cell in the window with how far its flash has
81
+ * faded, from 0 (just started) to 1 (gone).
82
+ */
83
+ forEachFlash(now: number, draw: (column: ModelIndex, row: ModelIndex, progress: number) => void): void;
84
+ private pruneFlashes;
85
+ textForColumnHeader(column: ModelIndex): string;
86
+ textForCell(column: ModelIndex, row: ModelIndex): string;
87
+ textAlignForCell(column: ModelIndex): CanvasTextAlign;
88
+ /** Numbers by sign and dates in their theme colours, after Deephaven's grid */
89
+ colorForCell(column: ModelIndex, row: ModelIndex, theme: GridTheme): GridColor;
90
+ backgroundColorForCell(column: ModelIndex, row: ModelIndex, theme: GridTheme): NullableGridColor;
91
+ }
92
+ export default ViewportGridModel;
@@ -0,0 +1,11 @@
1
+ /** A cell's whole value as the value popover shows it */
2
+ export type ShownValue = {
3
+ text: string;
4
+ isJson: boolean;
5
+ };
6
+ /**
7
+ * `value` in full: text holding a JSON object or array pretty-printed with two-space indents,
8
+ * anything else as copying it would give (numbers unrounded, dates in full). A null is the
9
+ * word null, so an empty popover never means "no value".
10
+ */
11
+ export declare function shownValue(type: string, value: unknown): ShownValue;
package/dist/copy.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ import GridRange from './GridRange';
2
+ import { type VisibleIndex } from './GridMetrics';
3
+ import { type ViewportColumn } from '@kermodes/client';
4
+ /** The most rows one copy takes; bigger selections copy their first rows */
5
+ export declare const COPY_ROW_LIMIT = 100000;
6
+ /** A cell's value as copied: displayed text, numbers raw (no thousands separators), nulls empty */
7
+ export declare function copyValue(type: string, value: unknown): string;
8
+ /** One field of tab-separated text, quoted when it holds a tab, line break, or quote */
9
+ export declare function tsvField(text: string): string;
10
+ export declare function toTsv(rows: readonly (readonly string[])[]): string;
11
+ /** Which cells a copy of the selected ranges takes */
12
+ export type CopyPlan = {
13
+ rows: number[];
14
+ columns: VisibleIndex[];
15
+ isCapped: boolean;
16
+ selectedRowCount: number;
17
+ contains: (column: VisibleIndex, row: number) => boolean;
18
+ };
19
+ export declare function planCopy(ranges: readonly GridRange[], columnCount: number, rowCount: number, limit?: number): CopyPlan;
20
+ /**
21
+ * The tab-separated text of a copy: one line per row of the plan, optionally
22
+ * after a line of column names.
23
+ */
24
+ export declare function copyText(plan: CopyPlan, columns: readonly ViewportColumn[], modelColumnOf: (column: VisibleIndex) => number, valueAt: (modelColumn: number, row: number) => unknown, includeHeader: boolean): string;
25
+ /**
26
+ * Put `text` on the clipboard. Notebook front ends can run outputs in frames
27
+ * that deny the clipboard API, so fall back to copying from a hidden textarea.
28
+ */
29
+ export declare function writeClipboard(text: string): Promise<void>;
@@ -0,0 +1,16 @@
1
+ import { type ViewerState } from '@kermodes/client';
2
+ /**
3
+ * What covers a viewer's rows when they are not current (docs/theme.md, "Live data states"):
4
+ * a failure in their place, skeleton rows before the first arrive, or the rows dimmed under a
5
+ * spinner while something brings them up to date. Current rows are covered by nothing.
6
+ */
7
+ export type Cover = {
8
+ kind: 'failed';
9
+ message: string;
10
+ } | {
11
+ kind: 'skeleton';
12
+ } | {
13
+ kind: 'busy';
14
+ label: string;
15
+ } | null;
16
+ export declare function viewerCover(state: Pick<ViewerState, 'status' | 'error' | 'retrying'>, hasRows: boolean, isUpdating: boolean): Cover;
@@ -0,0 +1,4 @@
1
+ export declare class AssertionError extends Error {
2
+ isAssertionFailed: boolean;
3
+ }
4
+ export default AssertionError;
@@ -0,0 +1,2 @@
1
+ export declare function assertIsDefined<T>(val: T): asserts val is NonNullable<T>;
2
+ export default assertIsDefined;
@@ -0,0 +1,2 @@
1
+ export { default as assertIsDefined } from './assertIsDefined';
2
+ export { default as AssertionError } from './AssertionError';
@@ -0,0 +1,50 @@
1
+ /**
2
+ * A minimal memoizer for the hot per cell render paths.
3
+ *
4
+ * `memoizeClear` wraps memoizee, which routes every call through a
5
+ * configurable argument resolver, a nested lookup structure and an LRU queue
6
+ * that has to be reordered on each hit. That is a reasonable trade for
7
+ * occasional calls, but a function invoked once per visible cell of every
8
+ * frame pays it tens of thousands of times a second: profiling a grid scroll
9
+ * found more time spent inside memoizee than in the truncation and
10
+ * tokenization it was caching.
11
+ *
12
+ * This keeps a tree of `Map`s with one level per argument, keyed on the
13
+ * argument values themselves. The arguments are deliberately not combined
14
+ * into a single string key: cell text can be tens of thousands of characters,
15
+ * and a freshly built key would have to be copied, hashed and retained on
16
+ * every call. Keying on the original string lets the engine reuse the hash it
17
+ * caches on that string, so a lookup stays cheap however long the text is.
18
+ * `Map` compares with SameValueZero, so primitives match by value and objects,
19
+ * functions and symbols by identity.
20
+ *
21
+ * There is no eviction queue to maintain because the entire cache is dropped
22
+ * once it fills, which is the behaviour `memoizeClear` already settled on to
23
+ * avoid LRU thrashing.
24
+ *
25
+ * The returned function does not forward `this`, so the memoized function must
26
+ * not depend on it.
27
+ */
28
+ /**
29
+ * Longest string V8 hashes by content (`String::kMaxHashCalcLength`). Longer
30
+ * strings are hashed by their length alone, so long cells that only differ
31
+ * near the end, such as a long text with a row number appended, all share a
32
+ * bucket and every lookup compares them character by character. Callers that
33
+ * can receive strings this long should key on only the part they read.
34
+ */
35
+ export declare const MAX_HASHED_STRING_LENGTH = 16383;
36
+ /**
37
+ * Entries for a cache that is hit once per visible cell. If a single frame
38
+ * draws more distinct cells than the cache holds, it clears partway through
39
+ * every frame and never serves a hit. A maximized grid with minimum width
40
+ * columns shows about 7,500 cells on a 4K display and 13,500 on a 5K display
41
+ * at 100% scaling, so this leaves room for larger displays too.
42
+ */
43
+ export declare const CELL_CACHE_SIZE = 50000;
44
+ /**
45
+ * @param fn The function to memoize. Must not depend on `this`
46
+ * @param max Number of entries to hold before clearing the whole cache
47
+ * @returns The memoized function
48
+ */
49
+ export declare function fastMemoize<A extends unknown[], R>(fn: (...args: A) => R, max: number): (...args: A) => R;
50
+ export default fastMemoize;
@@ -0,0 +1,32 @@
1
+ export { default as Grid } from './Grid';
2
+ export * from './Grid';
3
+ export * from './GridMetricCalculator';
4
+ export * from './GridMetrics';
5
+ export { default as GridModel } from './GridModel';
6
+ export { default as GridMouseHandler } from './GridMouseHandler';
7
+ export * from './GridMouseHandler';
8
+ export { default as KeyHandler } from './KeyHandler';
9
+ export * from './KeyHandler';
10
+ export * from './EventHandlerResult';
11
+ export * from './GridRange';
12
+ export * from './GridAxisRange';
13
+ export * from './GridRenderer';
14
+ export * from './GridRendererTypes';
15
+ export * from './GridTheme';
16
+ export * from './GridUtils';
17
+ export * from './Selection';
18
+ export * from './GridSelectionUtils';
19
+ export { RangedSelection, isRangedSelection, assertIsRangedSelection, selectionToRanges, } from './RangedSelection';
20
+ export * from './ThemeContext';
21
+ export * from './ColumnHeaderGroup';
22
+ export * from './key-handlers';
23
+ export * from './mouse-handlers';
24
+ export * from './errors';
25
+ export { injectGridStyles } from './GridStyles';
26
+ export * from './ViewportGridModel';
27
+ export { TableViewer, type TableViewerProps } from './TableViewer';
28
+ export { TableViewerMetricCalculator, TableViewerRenderer } from './TableViewerGrid';
29
+ export * from './FilterBar';
30
+ export * from './sorting';
31
+ export * from './copy';
32
+ export * from './cellValue';