@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,96 @@
1
+ import type { IColumnHeaderGroup } from './ColumnHeaderGroup';
2
+ import { type ModelIndex } from './GridMetrics';
3
+ import { type GridColor, type GridTheme, type NullableGridColor } from './GridTheme';
4
+ /**
5
+ * Model for a Grid
6
+ * All of these methods should return very quickly, as they will be called many times in the render cycle.
7
+ * If data needs to be loaded asynchronously, return something immediately, then redraw the grid when it arrives.
8
+ */
9
+ declare abstract class GridModel {
10
+ /** Count of rows in the grid */
11
+ abstract get rowCount(): number;
12
+ /** Count of columns in the grid */
13
+ abstract get columnCount(): number;
14
+ /** Count of rows that are frozen (or 'floating') at the top */
15
+ get floatingTopRowCount(): number;
16
+ /** Count of rows that are frozen at the bottom */
17
+ get floatingBottomRowCount(): number;
18
+ /** Count of columns that are frozen (or 'floating') at the left */
19
+ get floatingLeftColumnCount(): number;
20
+ /** Count of columns that are frozen (or 'floating') at the right */
21
+ get floatingRightColumnCount(): number;
22
+ /**
23
+ * How many columns header levels are in the grid
24
+ * Used for column grouping where columns at depth 0 are the base columns
25
+ *
26
+ * A grid with 1-level grouping would have a columnHeaderDepth of 2
27
+ * and column headers at depths 0 and 1
28
+ */
29
+ get columnHeaderMaxDepth(): number;
30
+ /**
31
+ * Get the text for the specified cell
32
+ * @param column Column to get the text for
33
+ * @param row Row to get the text for
34
+ * @returns Text for the specified cell
35
+ */
36
+ abstract textForCell(column: ModelIndex, row: ModelIndex): string;
37
+ /**
38
+ * Get the character to replace text when truncated for a specific cell.
39
+ * Leave undefined to show text truncated with ellipsis
40
+ * @param column Column to get the truncation character for
41
+ * @param row Row to get the truncation character for
42
+ * @returns Truncation character for the specified cell
43
+ */
44
+ truncationCharForCell(column: ModelIndex, row: ModelIndex): string | undefined;
45
+ /**
46
+ * Get the text alignment for the specified cell
47
+ * @param column Column to get the alignment for
48
+ * @param row Row to get the alignment for
49
+ * @returns Text alignment for the specified cell
50
+ */
51
+ textAlignForCell(column: ModelIndex, row: ModelIndex): CanvasTextAlign;
52
+ /**
53
+ * Get the color for the text in the specified cell
54
+ * @param column Column to get the color for
55
+ * @param row Row to get the color for
56
+ * @param theme Theme applied to the grid
57
+ * @returns Color for the text in the cell
58
+ */
59
+ colorForCell(column: ModelIndex, row: ModelIndex, theme: GridTheme): GridColor;
60
+ /**
61
+ * Get the background color for the cell
62
+ * @param column Column to get the background color for
63
+ * @param row Row to get the background color for
64
+ * @param theme Theme applied to the grid
65
+ * @returns Background color for the cell
66
+ */
67
+ backgroundColorForCell(column: ModelIndex, row: ModelIndex, theme: GridTheme): NullableGridColor;
68
+ /**
69
+ * Text for the column header
70
+ * @param column Column to get the header for
71
+ * @param depth Depth to get the header text for. 0 is base columns
72
+ * @returns Text to put in the column header
73
+ */
74
+ abstract textForColumnHeader(column: ModelIndex, depth?: number): string | undefined;
75
+ /** Color for column header
76
+ * @param column Column to get the color for
77
+ * @param depth Header depth to get the color for
78
+ * @returns Color for the header at the depth or null
79
+ */
80
+ colorForColumnHeader(column: ModelIndex, depth?: number): string | null;
81
+ /**
82
+ * Text for the row header
83
+ * @param row Row to get the header for
84
+ * @returns Text to put in the row header
85
+ */
86
+ textForRowHeader(row: ModelIndex): string;
87
+ /**
88
+ * Text for the row footer
89
+ * @param row Row to get the footer for
90
+ * @returns Text to put in the row footer
91
+ */
92
+ textForRowFooter(row: ModelIndex): string;
93
+ getColumnHeaderGroup(modelIndex: ModelIndex, depth: number): IColumnHeaderGroup | undefined;
94
+ getColumnHeaderParentGroup(modelIndex: ModelIndex, depth: number): IColumnHeaderGroup | undefined;
95
+ }
96
+ export default GridModel;
@@ -0,0 +1,29 @@
1
+ import { type EventHandlerResult } from './EventHandlerResult';
2
+ import type Grid from './Grid';
3
+ import { type GridPoint } from './GridUtils';
4
+ /**
5
+ * Some events we listen to are a native mouse event, and others are wrapped with React's SyntheticEvent.
6
+ * The GridMouseHandler shouldn't care though - the properties it accesses should be common on both types of events.
7
+ */
8
+ export type GridMouseEvent = MouseEvent | React.MouseEvent;
9
+ export type GridWheelEvent = WheelEvent | React.WheelEvent;
10
+ export type GridMouseHandlerFunctionName = 'onDown' | 'onMove' | 'onDrag' | 'onLeave' | 'onClick' | 'onContextMenu' | 'onDoubleClick' | 'onUp' | 'onWheel';
11
+ /**
12
+ * Define a region in the grid that interacts with the mouse on a grid.
13
+ * Return true from any of the events to indicate they're consumed, and stopPropagation/preventDefault will be called.
14
+ */
15
+ export declare class GridMouseHandler {
16
+ order: number;
17
+ constructor(order?: number);
18
+ cursor: string | null;
19
+ onDown(gridPoint: GridPoint, grid: Grid, event: GridMouseEvent): EventHandlerResult;
20
+ onMove(gridPoint: GridPoint, grid: Grid, event: GridMouseEvent): EventHandlerResult;
21
+ onDrag(gridPoint: GridPoint, grid: Grid, event: GridMouseEvent): EventHandlerResult;
22
+ onLeave(gridPoint: GridPoint, grid: Grid, event: GridMouseEvent): EventHandlerResult;
23
+ onClick(gridPoint: GridPoint, grid: Grid, event: GridMouseEvent): EventHandlerResult;
24
+ onContextMenu(gridPoint: GridPoint, grid: Grid, event: GridMouseEvent): EventHandlerResult;
25
+ onDoubleClick(gridPoint: GridPoint, grid: Grid, event: GridMouseEvent): EventHandlerResult;
26
+ onUp(gridPoint: GridPoint, grid: Grid, event: GridMouseEvent): EventHandlerResult;
27
+ onWheel(gridPoint: GridPoint, grid: Grid, event: GridMouseEvent): EventHandlerResult;
28
+ }
29
+ export default GridMouseHandler;
@@ -0,0 +1,268 @@
1
+ export type GridRangeIndex = number | null;
2
+ export type RequiredGridRangeIndex = number;
3
+ type LeftIndex = GridRangeIndex;
4
+ type RightIndex = GridRangeIndex;
5
+ type TopIndex = GridRangeIndex;
6
+ type BottomIndex = GridRangeIndex;
7
+ export type GridCell = {
8
+ column: RequiredGridRangeIndex;
9
+ row: RequiredGridRangeIndex;
10
+ };
11
+ export interface BoundedGridRange extends GridRange {
12
+ startColumn: RequiredGridRangeIndex;
13
+ startRow: RequiredGridRangeIndex;
14
+ endColumn: RequiredGridRangeIndex;
15
+ endRow: RequiredGridRangeIndex;
16
+ }
17
+ export declare enum SELECTION_DIRECTION {
18
+ DOWN = "DOWN",
19
+ UP = "UP",
20
+ LEFT = "LEFT",
21
+ RIGHT = "RIGHT"
22
+ }
23
+ export declare class GridRange {
24
+ startColumn: GridRangeIndex;
25
+ startRow: GridRangeIndex;
26
+ endColumn: GridRangeIndex;
27
+ endRow: GridRangeIndex;
28
+ static SELECTION_DIRECTION: typeof SELECTION_DIRECTION;
29
+ /**
30
+ * Returns a normalized array of indexes ensuring left <= right and top <= bottom
31
+ * @param startColumn Start column index
32
+ * @param startRow Start row index
33
+ * @param endColumn End column index
34
+ * @param endRow End row index
35
+ * @returns Array containing normalized indexes [left, top, right, bottom]
36
+ */
37
+ static normalize(startColumn: GridRangeIndex, startRow: GridRangeIndex, endColumn: GridRangeIndex, endRow: GridRangeIndex): [LeftIndex, TopIndex, RightIndex, BottomIndex];
38
+ /**
39
+ * Makes a GridRange ensuring startColumn <= endColumn, startRow <= endRow
40
+ * @param startColumn Start column index
41
+ * @param startRow Start row index
42
+ * @param endColumn End column index
43
+ * @param endRow End row index
44
+ * @returns Normalized GridRange
45
+ */
46
+ static makeNormalized(startColumn: GridRangeIndex, startRow: GridRangeIndex, endColumn: GridRangeIndex, endRow: GridRangeIndex): GridRange;
47
+ /**
48
+ * Creates a GridRange representing a single cell
49
+ * @param column Column index
50
+ * @param row Row index
51
+ * @returns GridRange representing the cell
52
+ */
53
+ static makeCell(column: GridRangeIndex, row: GridRangeIndex): GridRange;
54
+ /**
55
+ * Creates a GridRange representing an infinite length column
56
+ * @param column Column index
57
+ * @returns GridRange representing the column
58
+ */
59
+ static makeColumn(column: GridRangeIndex): GridRange;
60
+ /**
61
+ * Creates a GridRange representing an infinite length row
62
+ * @param row Row index
63
+ * @returns GridRange representing the row
64
+ */
65
+ static makeRow(row: GridRangeIndex): GridRange;
66
+ /**
67
+ * Returns the minimum value between 2 range indexes or null if at least 1 is null
68
+ * @param index1 First grid range index
69
+ * @param index2 Second grid range index
70
+ * @returns Minimum index or null if either index is null
71
+ */
72
+ static minOrNull(index1: GridRangeIndex, index2: GridRangeIndex): number | null;
73
+ /**
74
+ * Returns the maximum value between 2 range indexes or null if at least 1 is null
75
+ * @param index1 First grid range index
76
+ * @param index2 Second grid range index
77
+ * @returns Maximum index or null if either index is null
78
+ */
79
+ static maxOrNull(index1: GridRangeIndex, index2: GridRangeIndex): number | null;
80
+ /**
81
+ * Consolidate the passed in ranges to the minimum set, merging overlapping ranges.
82
+ * @param ranges The ranges to consolidate
83
+ * @returns Consolidated ranges
84
+ */
85
+ static consolidate(ranges: readonly GridRange[]): GridRange[];
86
+ /**
87
+ * Checks if the 1-D ranges between 2 index pairs overlap or are continuous.
88
+ * For example ranges [0, 1] and [2, 3] are continuous and will return true.
89
+ * [0, 1] and [1, 3] overlap and return true.
90
+ * [0, 1] and [3, 4] do not overlap and have a gap so this will return false.
91
+ * @param start1 Start of 1st range
92
+ * @param end1 End of 1st range
93
+ * @param start2 Start of 2nd range
94
+ * @param end2 End of 2nd range
95
+ * @returns True if the ranges overlap or touch, else false
96
+ */
97
+ static isAxisRangeTouching(start1: GridRangeIndex, end1: GridRangeIndex, start2: GridRangeIndex, end2: GridRangeIndex): boolean;
98
+ /**
99
+ * Checks if 2 arrays of ranges are the same ranges
100
+ * @param ranges1 First array of ranges
101
+ * @param ranges2 Second array of ranges
102
+ * @returns True if the arrays contain the same ranges in the same order
103
+ */
104
+ static rangeArraysEqual(ranges1: readonly GridRange[], ranges2: readonly GridRange[]): boolean;
105
+ /**
106
+ * Get the intersection (overlapping area) of two ranges
107
+ * @param range One range to check for the intersection
108
+ * @param otherRange The other range to check for the intersection
109
+ * @returns Intersection of the two ranges. If they do not intersect, returns `null`.
110
+ */
111
+ static intersection(range: GridRange, otherRange: GridRange): GridRange | null;
112
+ /**
113
+ * Subtracts 1 range from another
114
+ * @param range The range to be subtracted from
115
+ * @param subtractRange The range to subtract from within this range
116
+ * @returns The ranges needed to represent the remaining
117
+ */
118
+ static subtractFromRange(range: GridRange, subtractRange: GridRange): GridRange[];
119
+ /**
120
+ * Subtract a range from multiple ranges
121
+ * @param ranges The ranges to be subtracted from
122
+ * @param subtractRange The range to subtract from within these ranges
123
+ * @returns The ranges needed to represent the remaining
124
+ */
125
+ static subtractFromRanges(ranges: readonly GridRange[], subtractRange: GridRange): GridRange[];
126
+ /**
127
+ * Subtract multiple ranges from multiple ranges
128
+ * @param ranges The ranges to be subtracted from
129
+ * @param subtractRanges The ranges to subtract from within these ranges
130
+ * @returns The ranges needed to represent the remaining
131
+ */
132
+ static subtractRangesFromRanges(ranges: readonly GridRange[], subtractRanges: readonly GridRange[]): GridRange[];
133
+ /**
134
+ * Test if a given range is bounded (all values are non-null)
135
+ * @param range The range to test
136
+ * @returns True if this range is bounded, false otherwise
137
+ */
138
+ static isBounded(range: GridRange): range is BoundedGridRange;
139
+ /**
140
+ * Converts any GridRange passed in that is a full row or column selection to be bound
141
+ * to the `columnCount` and `rowCount` passed in
142
+ *
143
+ * @param range The range to get the bounded range of
144
+ * @param columnCount The number of columns
145
+ * @param rowCount The number of rows
146
+ * @returns The passed in GridRange with any null values filled in
147
+ */
148
+ static boundedRange(range: GridRange, columnCount: number, rowCount: number): BoundedGridRange;
149
+ /**
150
+ * Converts the GridRanges passed in to be bound to the `columnCount` and `rowCount` passed in
151
+ *
152
+ * @param ranges The ranges to get the bounded ranges of
153
+ * @param columnCount The number of columns
154
+ * @param rowCount The number of rows
155
+ * @returns The passed in GridRange with any null values filled in
156
+ */
157
+ static boundedRanges(ranges: readonly GridRange[], columnCount: number, rowCount: number): BoundedGridRange[];
158
+ /**
159
+ * Offsets a GridRange by the specified amount in the x and y directions
160
+ *
161
+ * @param range The range to offset
162
+ * @param columnOffset The number of columns to offset
163
+ * @param rowOffset The number of rows to offset
164
+ * @returns The new grid range offset from the original
165
+ */
166
+ static offset(range: GridRange, columnOffset: number, rowOffset: number): GridRange;
167
+ /**
168
+ * Get the next cell given the selected ranges and the current cell
169
+ * @param ranges The selected bounded ranges within the grid
170
+ * @param column The cursor column, or null if none focused
171
+ * @param row The cursor row, or null if none focused
172
+ * @param direction The direction in which to select next
173
+ * @returns The next cell to focus, or null if there should be no more focus
174
+ */
175
+ static nextCell(ranges: readonly GridRange[], column?: GridRangeIndex, row?: GridRangeIndex, direction?: SELECTION_DIRECTION): GridCell | null;
176
+ /**
177
+ * Count the number of cells in the provided grid ranges
178
+ * @param ranges The ranges to count the rows of
179
+ * @returns The number of cells in the ranges, or `NaN` if any of the ranges were unbounded
180
+ */
181
+ static cellCount(ranges: readonly GridRange[]): number;
182
+ /**
183
+ * Count the number of rows in the provided grid ranges
184
+ * @param ranges The ranges to count the rows of
185
+ * @returns The number of rows in the ranges, or `NaN` if any of the ranges were unbounded
186
+ */
187
+ static rowCount(ranges: readonly GridRange[]): number;
188
+ /**
189
+ * Count the number of columns in the provided grid ranges
190
+ * @param ranges The ranges to count the columns of
191
+ * @returns The number of columns in the ranges, or `NaN` if any of the ranges were unbounded
192
+ */
193
+ static columnCount(ranges: readonly GridRange[]): number;
194
+ /**
195
+ * Check if the provided ranges contain the provided cell
196
+ * @param ranges The ranges to check
197
+ * @param column The column index
198
+ * @param row The row index
199
+ * @returns True if the cell is within the provided ranges, false otherwise.
200
+ */
201
+ static containsCell(ranges: readonly GridRange[], column: GridRangeIndex, row: GridRangeIndex): boolean;
202
+ /**
203
+ * Iterate through each cell in the provided ranges
204
+ * @param ranges The ranges to iterate through
205
+ * @param callback The callback to execute. `index` is the index within that range
206
+ * @param direction The direction to iterate in
207
+ */
208
+ static forEachCell(ranges: readonly GridRange[], callback: (column: number, row: number, index: number) => void, direction?: SELECTION_DIRECTION): void;
209
+ constructor(startColumn: GridRangeIndex, startRow: GridRangeIndex, endColumn: GridRangeIndex, endRow: GridRangeIndex);
210
+ /**
211
+ * Checks if the provided range is equivalent to this range (same start and end column/row indexes)
212
+ * @param other Grid range to check against
213
+ * @returns True if the ranges cover the same area
214
+ */
215
+ equals(other: GridRange): boolean;
216
+ /**
217
+ * Checks if this GridRange contains another range
218
+ * @param other The range to check
219
+ * @returns True if this GridRange completely contains `other`
220
+ * */
221
+ contains(other: GridRange): boolean;
222
+ /**
223
+ * Check if the provided cell is in this range
224
+ * @param column The column to check
225
+ * @param row The row to check
226
+ * @returns True if this cell is within this range
227
+ */
228
+ containsCell(column: GridRangeIndex, row: GridRangeIndex): boolean;
229
+ /**
230
+ * Check if the provided range touches (or overlaps) this GridRange
231
+ * Effectively checks if the 2 ranges could be represented by 1 continuous range
232
+ * @param other The range to check
233
+ * @returns True if this GridRange touches `other`
234
+ * */
235
+ touches(other: GridRange): boolean;
236
+ /**
237
+ * Subtracts a range from this range
238
+ * @param other The range to deselect from within this range
239
+ * @returns The ranges needed to represent the remaining
240
+ */
241
+ subtract(other: GridRange): GridRange[];
242
+ /**
243
+ * Get the first cell in this range. Throws if this range is unbounded.
244
+ *
245
+ * @param direction The direction to get the starting cell in. Defaults to DOWN
246
+ * @returns The first cell in this range in the direction specified
247
+ */
248
+ startCell(direction?: SELECTION_DIRECTION): GridCell;
249
+ /**
250
+ * Get the next cell in the direction specified. Throws if this range is unbounded.
251
+ * If already at the bounds of the range in that direction, wrap to the next column or row
252
+ * If at the end of the entire range, return null
253
+ * If outside of the range, returns the next cell closest within this range.
254
+ *
255
+ * @param column The cursor column
256
+ * @param row The cursor row
257
+ * @param direction The direction to go in
258
+ * @returns The next cell in the direction specified, or `null` if at the end of the range
259
+ */
260
+ nextCell(column: GridRangeIndex, row: GridRangeIndex, direction: SELECTION_DIRECTION): GridCell | null;
261
+ /**
262
+ * Iterate through each cell in the range
263
+ * @param callback Callback to execute. `index` is the index within this range
264
+ * @param direction The direction to iterate in
265
+ */
266
+ forEach(callback: (column: number, row: number, index: number) => void, direction?: SELECTION_DIRECTION): void;
267
+ }
268
+ export default GridRange;
@@ -0,0 +1,159 @@
1
+ import { type GridColorWay, type NullableGridColor } from './GridTheme';
2
+ import { type Coordinate, type VisibleIndex } from './GridMetrics';
3
+ import { type BoundedAxisRange } from './GridAxisRange';
4
+ import { type GridRenderState } from './GridRendererTypes';
5
+ import TextCellRenderer from './TextCellRenderer';
6
+ /**
7
+ * A GridRenderer handles rendering the different parts of the grid
8
+ * This default rendering just renders a basic grid. Extend this class and implement
9
+ * your own methods to customize drawing of the grid (eg. Draw icons or special features)
10
+ */
11
+ export declare class GridRenderer {
12
+ static DEFAULT_EDGE_RADIUS: number;
13
+ protected textCellRenderer: TextCellRenderer;
14
+ /**
15
+ * Truncate a string to the specified length and add ellipses if necessary
16
+ * @param str The string to truncate
17
+ * @param len The length to truncate the string to. If longer than the actual string, just returns the string
18
+ * @returns The truncated string
19
+ */
20
+ static truncate(str: string, len: number): string;
21
+ /**
22
+ * Uses binary search to truncate a string to fit in the provided width
23
+ * @param context The drawing context to measure the text in
24
+ * @param str The string to get the maximum length it can draw
25
+ * @param width The width to truncate it to
26
+ * @param start The low boundary to start the search
27
+ * @param end The high boundary to start the search
28
+ * @param truncationChar This char will be repeated as the display string if the string is truncated instead of just adding an ellipsis
29
+ * @returns The truncated string
30
+ */
31
+ static binaryTruncateToWidth(context: CanvasRenderingContext2D, str: string, width: number, start?: number, end?: number, truncationChar?: string): string;
32
+ /**
33
+ * The most characters of a string that can be drawn within a width, based on
34
+ * the estimated width of the narrowest character. `truncateToWidth` never
35
+ * reads past this many characters.
36
+ * @param width The width to truncate within
37
+ * @param fontWidthLower The estimated width of the narrowest character
38
+ * @returns The maximum number of characters that can fit
39
+ */
40
+ static getMaxTruncatedLength(width: number, fontWidthLower?: number): number;
41
+ /**
42
+ * Truncate a string (if necessary) to fit in the specified width.
43
+ * First uses the estimated font width to calculate a lower/upper bound
44
+ * Then uses binary search within those bounds to find the exact max length
45
+ * @param context The drawing context
46
+ * @param str The string to calculate max length for
47
+ * @param width The width to truncate within
48
+ * @param fontWidth The estimated width of each character
49
+ * @param truncationChar This char will be repeated as the display string if the string is truncated instead of just adding an ellipsis
50
+ * @returns The truncated string that fits within the width provided
51
+ */
52
+ static truncateToWidth(context: CanvasRenderingContext2D, str: string, width: number, fontWidthLower?: number, fontWidthUpper?: number, truncationChar?: string): string;
53
+ /** Split a space separated list of row background colors, cached for the last value */
54
+ static getCachedBackgroundColors: import("memoize-one").MemoizedFn<(backgroundColors: GridColorWay) => string[]>;
55
+ /**
56
+ * Draw the grid canvas with the state provided
57
+ * @param state The state of the grid
58
+ */
59
+ drawCanvas(state: GridRenderState): void;
60
+ configureContext(context: CanvasRenderingContext2D, state: GridRenderState): void;
61
+ drawBackground(context: CanvasRenderingContext2D, state: GridRenderState): void;
62
+ drawGrid(context: CanvasRenderingContext2D, state: GridRenderState): void;
63
+ drawFloatingRows(context: CanvasRenderingContext2D, state: GridRenderState): void;
64
+ drawFloatingColumns(context: CanvasRenderingContext2D, state: GridRenderState): void;
65
+ drawFloatingBorders(context: CanvasRenderingContext2D, state: GridRenderState): void;
66
+ drawGridBackground(context: CanvasRenderingContext2D, state: GridRenderState, drawHover?: boolean): void;
67
+ drawRowStripes(context: CanvasRenderingContext2D, state: GridRenderState): void;
68
+ drawRowStripesForRows(context: CanvasRenderingContext2D, state: GridRenderState, rows: readonly VisibleIndex[], rowBackgroundColors: GridColorWay, minX?: number, maxX?: number): void;
69
+ drawMouseColumnHover(context: CanvasRenderingContext2D, state: GridRenderState): void;
70
+ drawMouseRowHover(context: CanvasRenderingContext2D, state: GridRenderState): void;
71
+ drawFloatingMouseRowHover(context: CanvasRenderingContext2D, state: GridRenderState): void;
72
+ /** Tints the whole row of the cursor cell, so a clicked cell's row stands out */
73
+ drawCursorRow(context: CanvasRenderingContext2D, state: GridRenderState): void;
74
+ drawMouseRowHoverForRow(context: CanvasRenderingContext2D, state: GridRenderState, row: VisibleIndex): void;
75
+ drawGridLines(context: CanvasRenderingContext2D, state: GridRenderState): void;
76
+ drawGridLinesForItems(context: CanvasRenderingContext2D, state: GridRenderState, columns: readonly VisibleIndex[], rows: readonly VisibleIndex[], columnColor: NullableGridColor, rowColor: NullableGridColor): void;
77
+ drawGridLinesForColumns(context: CanvasRenderingContext2D, state: GridRenderState, columns: readonly VisibleIndex[]): void;
78
+ drawGridLinesForRows(context: CanvasRenderingContext2D, state: GridRenderState, rows: readonly VisibleIndex[]): void;
79
+ drawCellBackgrounds(context: CanvasRenderingContext2D, state: GridRenderState): void;
80
+ drawCellBackgroundsForItems(context: CanvasRenderingContext2D, state: GridRenderState, columns: readonly VisibleIndex[], rows: readonly VisibleIndex[]): void;
81
+ drawCellBackground(context: CanvasRenderingContext2D, state: GridRenderState, column: VisibleIndex, row: VisibleIndex): void;
82
+ drawCellContents(context: CanvasRenderingContext2D, state: GridRenderState): void;
83
+ drawColumnCellContents(context: CanvasRenderingContext2D, state: GridRenderState, column: VisibleIndex): void;
84
+ drawCellContent(context: CanvasRenderingContext2D, state: GridRenderState, column: VisibleIndex, row: VisibleIndex): void;
85
+ drawHeaders(context: CanvasRenderingContext2D, state: GridRenderState): void;
86
+ /**
87
+ * The row between the headers and the cells that holds the filter inputs: a header-coloured
88
+ * band divided like the columns below it, so each input reads as a cell of the grid.
89
+ */
90
+ drawFilterBar(context: CanvasRenderingContext2D, state: GridRenderState): void;
91
+ drawFooters(context: CanvasRenderingContext2D, state: GridRenderState): void;
92
+ drawColumnHeaders(context: CanvasRenderingContext2D, state: GridRenderState): void;
93
+ drawColumnHeadersForRange(context: CanvasRenderingContext2D, state: GridRenderState, range: BoundedAxisRange, bounds: {
94
+ minX: number;
95
+ maxX: number;
96
+ }): void;
97
+ drawColumnHeadersAtDepth(context: CanvasRenderingContext2D, state: GridRenderState, range: BoundedAxisRange, bounds: {
98
+ minX: number;
99
+ maxX: number;
100
+ }, depth: number): void;
101
+ /**
102
+ * Draws the column header for the given visible index
103
+ * @param context Canvas context
104
+ * @param state Grid render state
105
+ * @param index Visible index of the column header to draw
106
+ * @param bounds The horizontal bounds the header can be drawn in
107
+ */
108
+ drawColumnHeaderAtIndex(context: CanvasRenderingContext2D, state: GridRenderState, index: VisibleIndex, bounds: {
109
+ minX: number;
110
+ maxX: number;
111
+ }): void;
112
+ drawColumnHeader(context: CanvasRenderingContext2D, state: GridRenderState, columnText: string, columnX: Coordinate, columnWidth: number, style?: {
113
+ backgroundColor?: string;
114
+ textColor?: string;
115
+ separatorColor?: string;
116
+ textInsetRight?: number;
117
+ }, bounds?: {
118
+ minX?: number;
119
+ maxX?: number;
120
+ }): void;
121
+ drawRowHeaders(context: CanvasRenderingContext2D, state: GridRenderState): void;
122
+ drawRowHeader(context: CanvasRenderingContext2D, state: GridRenderState, row: VisibleIndex, rowY: Coordinate, rowHeight: number): void;
123
+ drawRowFooters(context: CanvasRenderingContext2D, state: GridRenderState): void;
124
+ drawSelectedRanges(context: CanvasRenderingContext2D, state: GridRenderState, viewport?: {
125
+ left?: VisibleIndex;
126
+ top?: VisibleIndex;
127
+ right?: VisibleIndex;
128
+ bottom?: VisibleIndex;
129
+ minX?: Coordinate;
130
+ minY?: Coordinate;
131
+ maxX?: Coordinate;
132
+ maxY?: Coordinate;
133
+ }): void;
134
+ drawActiveCell(context: CanvasRenderingContext2D, state: GridRenderState, column: VisibleIndex, row: VisibleIndex): void;
135
+ /**
136
+ * Draws an outline around the in-flight ctrl+click / ctrl+shift+click drag
137
+ * rectangle. Uses `selection.cursor` (mouse-down anchor) and
138
+ * `selection.selectionEnd` (current drag position) for the bounds. For row
139
+ * selection themes only the top and bottom horizontal strokes are drawn
140
+ * (row-boundary preview); for column selection only left/right; for cell
141
+ * selection all four sides.
142
+ */
143
+ drawGestureDragOutline(context: CanvasRenderingContext2D, state: GridRenderState): void;
144
+ /**
145
+ * Draws a rounded rectangle using the current state of the canvas.
146
+ *
147
+ * @param context The canvas context
148
+ * @param x coordinate of the left side
149
+ * @param y coordinate of the top side
150
+ * @param w width of the rectangle
151
+ * @param h height of the rectangle
152
+ * @param r corner radius of the rectangle
153
+ */
154
+ drawRoundedRect(context: CanvasRenderingContext2D, x: Coordinate, y: Coordinate, w: number, h: number, r?: number): void;
155
+ drawDraggingColumn(context: CanvasRenderingContext2D, state: GridRenderState): void;
156
+ drawScrollBars(context: CanvasRenderingContext2D, state: GridRenderState): void;
157
+ getCachedHeaderWidth: (context: CanvasRenderingContext2D, text: string) => number;
158
+ }
159
+ export default GridRenderer;
@@ -0,0 +1,25 @@
1
+ import { type Coordinate } from './GridMetrics';
2
+ import type GridMetrics from './GridMetrics';
3
+ import type GridModel from './GridModel';
4
+ import { type GridTheme } from './GridTheme';
5
+ import { type GridSeparator } from './mouse-handlers/GridSeparatorMouseHandler';
6
+ import { type DraggingColumn } from './mouse-handlers/GridColumnMoveMouseHandler';
7
+ import type { GestureMode, Selection } from './Selection';
8
+ export declare const DEFAULT_FONT_WIDTH = 10;
9
+ export type GridRenderState = {
10
+ width: number;
11
+ height: number;
12
+ context: CanvasRenderingContext2D;
13
+ theme: GridTheme;
14
+ model: GridModel;
15
+ metrics: GridMetrics;
16
+ mouseX: Coordinate | null;
17
+ mouseY: Coordinate | null;
18
+ selection: Selection;
19
+ draggingColumn: DraggingColumn | null;
20
+ draggingColumnSeparator: GridSeparator | null;
21
+ isDraggingHorizontalScrollBar: boolean;
22
+ isDraggingVerticalScrollBar: boolean;
23
+ isDragging: boolean;
24
+ gestureMode: GestureMode | null;
25
+ };
@@ -0,0 +1,97 @@
1
+ import GridRange, { type GridRangeIndex, type SELECTION_DIRECTION } from './GridRange';
2
+ import type { CommitGestureOptions, GestureExtendOptions, GestureMode, Selection } from './Selection';
3
+ /**
4
+ * Maps modifier-key state on a mouse event to the appropriate `GestureMode`.
5
+ * The four modifier combinations partition the gesture space:
6
+ * - shift + ctrl/meta → `maximize`
7
+ * - shift alone → `extend`
8
+ * - ctrl/meta alone → `add`
9
+ * - no modifiers → `replace`
10
+ */
11
+ export declare function gestureModeFromModifiers(modifiers: {
12
+ isShiftKey: boolean;
13
+ isModifierKey: boolean;
14
+ }): GestureMode;
15
+ /**
16
+ * Shape describing how a mouse gesture should mutate the selection's ranges.
17
+ * Consumed by each `Selection` implementation's `withGestureExtend` to install
18
+ * the transient overlay.
19
+ */
20
+ export type GestureExtendResult = {
21
+ /** The new range list to install as the transient overlay. */
22
+ newRanges: readonly GridRange[];
23
+ /**
24
+ * True when the caller should drop any previously-committed selection state
25
+ * (relevant to `KeyedSelection.selectedKeys`; ignored by `RangedSelection`).
26
+ */
27
+ isReplacing: boolean;
28
+ /**
29
+ * True when the caller should trim to the last committed range before
30
+ * installing the new ranges. Applies to `extend` mode.
31
+ */
32
+ trimBefore: boolean;
33
+ /**
34
+ * True when the caller should reset the gesture anchor to `cursor` after
35
+ * installing. False preserves the existing anchor.
36
+ */
37
+ resetAnchor: boolean;
38
+ };
39
+ /**
40
+ * Compute the geometry for a mouse gesture. Given the current active ranges,
41
+ * gesture anchor, cursor position, and mode, returns the new overlay ranges
42
+ * plus the flags describing how the caller should install them.
43
+ *
44
+ * This is the shared arithmetic used by both `RangedSelection` and
45
+ * `KeyedSelection` for their `withGestureExtend` implementations.
46
+ */
47
+ export declare function computeGestureExtend(activeRanges: readonly GridRange[], anchor: {
48
+ row: GridRangeIndex;
49
+ column: GridRangeIndex;
50
+ } | null, cursor: {
51
+ row: GridRangeIndex;
52
+ column: GridRangeIndex;
53
+ }, opts: GestureExtendOptions): GestureExtendResult;
54
+ /**
55
+ * Returns the next cursor cell in `direction` walking through `ranges`.
56
+ * Falls back to walking the full grid when the ranges are empty or contain
57
+ * exactly one cell — matches Tab/Enter behavior for single-cell selections.
58
+ * Shared by `RangedSelection` and `KeyedSelection` implementations of
59
+ * `getNextCursorInDirection`.
60
+ */
61
+ export declare function nextCursorInRanges(ranges: readonly GridRange[], current: {
62
+ row: GridRangeIndex;
63
+ column: GridRangeIndex;
64
+ }, direction: SELECTION_DIRECTION, bounds: {
65
+ columnCount: number;
66
+ rowCount: number;
67
+ }): {
68
+ row: GridRangeIndex;
69
+ column: GridRangeIndex;
70
+ } | null;
71
+ /**
72
+ * Returns the first cell of `ranges` bounded to `[columnCount, rowCount]`.
73
+ * Shared by `RangedSelection` and `KeyedSelection` implementations of
74
+ * `getCursorLandingCell`.
75
+ */
76
+ export declare function cursorLandingCellForRanges(ranges: readonly GridRange[], bounds: {
77
+ columnCount: number;
78
+ rowCount: number;
79
+ }): {
80
+ row: GridRangeIndex;
81
+ column: GridRangeIndex;
82
+ } | null;
83
+ /**
84
+ * Returns `settled` with the post-commit cursor placed. Uses `opts.cursor`
85
+ * as the target; substitutes `landing` when the target falls outside a
86
+ * non-empty settled selection; preserves the target when settled is empty
87
+ * (matches Escape's "cursor survives clear" semantics).
88
+ *
89
+ * Callers pass `landing` precomputed from the pre-commit selection so this
90
+ * helper doesn't need to reach back into the caller's overlay state.
91
+ * Returns `settled` unchanged when the cursor is already correct so
92
+ * mouseUp no-ops preserve reference equality.
93
+ */
94
+ export declare function withCommittedCursor<S extends Selection>(settled: S, landing: {
95
+ row: GridRangeIndex;
96
+ column: GridRangeIndex;
97
+ } | null, opts: CommitGestureOptions): S;