@sheetxl/grid-react 0.7.26 → 0.7.28-beta.1

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 (90) hide show
  1. package/README.md +502 -2
  2. package/browser/cjs/index.cjs +3 -12
  3. package/browser/esm/index.mjs +5797 -1867
  4. package/licenses/dependencies.txt +143 -41
  5. package/node/esm/index.mjs +4951 -1861
  6. package/package.json +7 -6
  7. package/types/index.d.ts +2 -1503
  8. package/types/src/cell/CellLayer.d.ts +70 -0
  9. package/types/src/cell/CellRenderer.d.ts +42 -0
  10. package/types/src/cell/DefaultCellRenderer.d.ts +6 -0
  11. package/types/src/cell/GridlineLayer.d.ts +38 -0
  12. package/types/src/cell/Types.d.ts +12 -0
  13. package/types/src/cell/_CellModel.d.ts +82 -0
  14. package/types/src/cell/index.d.ts +6 -0
  15. package/types/src/editor/DefaultEditable.d.ts +121 -0
  16. package/types/src/editor/EditSession.d.ts +182 -0
  17. package/types/src/editor/EditState.d.ts +61 -0
  18. package/types/src/editor/EditorDiv.d.ts +65 -0
  19. package/types/src/editor/EditorInput.d.ts +88 -0
  20. package/types/src/editor/EditorLayer.d.ts +69 -0
  21. package/types/src/editor/EditorPlacement.d.ts +38 -0
  22. package/types/src/editor/index.d.ts +10 -0
  23. package/types/src/editor/useEditorKeymap.d.ts +74 -0
  24. package/types/src/grid/Grid.d.ts +16 -0
  25. package/types/src/grid/IGrid.d.ts +93 -0
  26. package/types/src/grid/index.d.ts +3 -0
  27. package/types/src/header/HeaderDividerAnchor.d.ts +120 -0
  28. package/types/src/header/index.d.ts +3 -0
  29. package/types/src/header/useHeaderSelectionPointer.d.ts +122 -0
  30. package/types/src/index.d.ts +13 -0
  31. package/types/src/layer/HoverTipLayer.d.ts +74 -0
  32. package/types/src/layer/Layer.d.ts +92 -0
  33. package/types/src/layer/LayerTypes.d.ts +47 -0
  34. package/types/src/layer/RangePrompt.d.ts +42 -0
  35. package/types/src/layer/Stage.d.ts +147 -0
  36. package/types/src/layer/StickyAnchor.d.ts +83 -0
  37. package/types/src/layer/StickyFloat.d.ts +65 -0
  38. package/types/src/layer/VirtualDiv.d.ts +59 -0
  39. package/types/src/layer/_Utils.d.ts +37 -0
  40. package/types/src/layer/index.d.ts +11 -0
  41. package/types/src/layer/useGridAnchor.d.ts +157 -0
  42. package/types/src/layer/useHoverIntent.d.ts +49 -0
  43. package/types/src/layer/useLayerResponder.d.ts +29 -0
  44. package/types/src/layer/usePlacement.d.ts +18 -0
  45. package/types/src/layer/useRangeHover.d.ts +35 -0
  46. package/types/src/list/CheckboxList.d.ts +63 -0
  47. package/types/src/list/List.d.ts +55 -0
  48. package/types/src/list/index.d.ts +3 -0
  49. package/types/src/metrics/Types.d.ts +23 -0
  50. package/types/src/metrics/index.d.ts +3 -0
  51. package/types/src/metrics/useGridMetrics.d.ts +67 -0
  52. package/types/src/range/DragHandle.d.ts +129 -0
  53. package/types/src/range/Draggable.d.ts +86 -0
  54. package/types/src/range/FillHandle.d.ts +54 -0
  55. package/types/src/range/RangeRect.d.ts +36 -0
  56. package/types/src/range/RangeResizer.d.ts +68 -0
  57. package/types/src/range/RangeStyle.d.ts +8 -0
  58. package/types/src/range/index.d.ts +13 -0
  59. package/types/src/selection/DefaultSelection.d.ts +59 -0
  60. package/types/src/selection/ICellAnchor.d.ts +21 -0
  61. package/types/src/selection/ISelection.d.ts +65 -0
  62. package/types/src/selection/RangesPickerLayer.d.ts +128 -0
  63. package/types/src/selection/SelectionLayer.d.ts +179 -0
  64. package/types/src/selection/SelectionStyle.d.ts +28 -0
  65. package/types/src/selection/SelectionTouchGrips.d.ts +29 -0
  66. package/types/src/selection/SelectionUtils.d.ts +2 -0
  67. package/types/src/selection/Types.d.ts +67 -0
  68. package/types/src/selection/_SelectionNavigation.d.ts +6 -0
  69. package/types/src/selection/_SelectionUtils.d.ts +7 -0
  70. package/types/src/selection/index.d.ts +12 -0
  71. package/types/src/selection/useDragCells.d.ts +218 -0
  72. package/types/src/selection/useSelectionPointer.d.ts +70 -0
  73. package/types/src/surface/GridPane.d.ts +85 -0
  74. package/types/src/surface/GridPaneProvider.d.ts +37 -0
  75. package/types/src/surface/GridSurface.d.ts +11 -0
  76. package/types/src/surface/IGridPane.d.ts +288 -0
  77. package/types/src/surface/IGridSurface.d.ts +141 -0
  78. package/types/src/surface/SurfaceStateProvider.d.ts +50 -0
  79. package/types/src/surface/_GridUtils.d.ts +37 -0
  80. package/types/src/surface/index.d.ts +7 -0
  81. package/types/src/surface/useGridPane.d.ts +31 -0
  82. package/types/src/surface/useSurfaceState.d.ts +22 -0
  83. package/types/src/svg/LineSVG.d.ts +13 -0
  84. package/types/src/svg/RectangleSVG.d.ts +114 -0
  85. package/types/src/svg/ShapeBounds.d.ts +15 -0
  86. package/types/src/svg/Types.d.ts +37 -0
  87. package/types/src/svg/index.d.ts +9 -0
  88. package/types/src/theme/GridTheme.d.ts +56 -0
  89. package/types/src/theme/index.d.ts +2 -0
  90. package/node/assets/style.css +0 -1
@@ -0,0 +1,288 @@
1
+ import { default as React } from 'react';
2
+ import { CellCoords, RangeCoords, OrientationFlags, TopLeft, Point, Rectangle, Bounds, Size, AnchorLocation, RemoveListener } from '@sheetxl/utils';
3
+ import { IGridMetrics } from '../metrics';
4
+ /**
5
+ * Describes a virtualize handle to a view section of a grid.
6
+ */
7
+ export interface IGridPane {
8
+ /**
9
+ * Sets focus to the view.
10
+ */
11
+ focus(options?: FocusOptions): void;
12
+ /**
13
+ * Set pointer capture to the view.
14
+ */
15
+ setPointerCapture(pointerId: number): void;
16
+ /**
17
+ * Release pointer capture from the view.
18
+ */
19
+ releasePointerCapture(pointerId: number): void;
20
+ /**
21
+ * The anchor for the view.
22
+ */
23
+ getAnchor(): AnchorLocation;
24
+ /**
25
+ * Allow for dimensions to be determined for various cells.
26
+ * The `IGridMetrics` is inclusive of the zoom.
27
+ */
28
+ getMetrics(): IGridMetrics;
29
+ /**
30
+ * The LIVE visible range of THIS pane — exactly the cells on screen right now. Changes as the pane
31
+ * scrolls. Same span as {@link getVisibleRows} / {@link getVisibleColumns}.
32
+ *
33
+ * @remarks
34
+ * One of three range concepts, from narrowest to widest:
35
+ * - {@link getVisibleRange} — this pane, on screen now (scroll-dependent).
36
+ * - {@link getPaneRange} — this pane's full structural coverage (scroll-independent).
37
+ * - {@link getTotalRange} — the whole grid, all panes.
38
+ */
39
+ getVisibleRange(): Readonly<RangeCoords>;
40
+ /**
41
+ * The visible (non-hidden) rows as {@link SpanSize} tracks (index + geometry), in order — so a
42
+ * caller iterates position + width in one pass; the array position is the visible ordinal.
43
+ *
44
+ * @param from Optional start index — overrides the viewport with a FRESH scan of exactly `[from, to]`
45
+ * (e.g. an overscan buffer, which extends past the viewport). Hidden runs are still skipped; the
46
+ * range is NOT clamped to the viewport. Caller keeps it within the grid.
47
+ * @param to Optional (inclusive) end index. Both `from` and `to` must be supplied to override.
48
+ */
49
+ getVisibleRows(from?: number, to?: number): readonly SpanSize[];
50
+ /**
51
+ * The visible (non-hidden) columns as {@link SpanSize} tracks (index + geometry), in order.
52
+ *
53
+ * @param from Optional start index — overrides the viewport with a custom range (see {@link getVisibleRows}).
54
+ * @param to Optional (inclusive) end index.
55
+ */
56
+ getVisibleColumns(from?: number, to?: number): readonly SpanSize[];
57
+ /**
58
+ * The geometry of ONE column by index (random access), or `null` for an out-of-grid index. Backed by
59
+ * the metrics cache — window-independent, so it also resolves off-viewport (overscan) tracks. Prefer
60
+ * {@link getVisibleColumns} when iterating; use this for the odd lookup (e.g. a merge boundary).
61
+ */
62
+ getColumnSize(index: number): SpanSize | null;
63
+ /**
64
+ * The geometry of ONE row by index (random access), or `null` for an out-of-grid index. See
65
+ * {@link getColumnSize}.
66
+ */
67
+ getRowSize(index: number): SpanSize | null;
68
+ /**
69
+ * Clip a rectangle against the viewport, culling to `null` when it falls fully outside — the
70
+ * clip/cull primitive. Pair with {@link getBoundsFromRange} for the common "range → visible bounds"
71
+ * path: `toClipBounds(getBoundsFromRange(range), insets)`.
72
+ *
73
+ * @param bounds The (view-relative) rect to clip. Defaults to the full pane bounds.
74
+ * @param insets Slack in view pixels. A negative inset extends OUTSIDE the viewport, so elements
75
+ * that visually 'flow' off the edge (e.g. a selection with an outward-growing border) are not
76
+ * culled while still partly visible.
77
+ *
78
+ * @remarks
79
+ * Returns `null` when nothing survives the clip (the rect is entirely off-screen).
80
+ */
81
+ toClipBounds(bounds?: Bounds, insets?: number | Bounds): Bounds | null;
82
+ /**
83
+ * ABSOLUTE → VIEW: map a rect from scroll-independent content space into this pane's view space
84
+ * (subtract the pane's scroll offset, then apply zoom). The inverse of {@link toAbsoluteBounds}.
85
+ *
86
+ * @remarks
87
+ * A distinct axis from {@link getBoundsFromRange} / {@link toClipBounds}, which already live in view
88
+ * space. This pair exists for content anchored in ABSOLUTE space — a floating movable (image / chart
89
+ * / shape) whose position must survive scroll & zoom. Use this to render such a movable at its current
90
+ * on-screen spot; use {@link toAbsoluteBounds} to persist a drag result back to the model. Cells never
91
+ * need it (they are range-derived, hence already view-space).
92
+ */
93
+ toPaneBounds(bounds: Bounds): Bounds;
94
+ /**
95
+ * VIEW → ABSOLUTE: map a rect from this pane's view space back into scroll-independent content space
96
+ * (undo zoom, then add the pane's scroll offset). The inverse of {@link toPaneBounds}.
97
+ *
98
+ * @remarks
99
+ * See {@link toPaneBounds}. Used to store a movable's live (view-space) drag/resize result as
100
+ * scroll-independent model bounds, so it stays anchored as the grid scrolls or zooms.
101
+ */
102
+ toAbsoluteBounds(bounds: Bounds): Bounds;
103
+ /**
104
+ * Additional inside padding.
105
+ */
106
+ getInsets(): Rectangle;
107
+ /**
108
+ * Returns the cell as a range.
109
+ *
110
+ * @remarks
111
+ * If this cell spans this will return a range later than 1.
112
+ * Note - This may return ranges for Cells if if they are not the top left.
113
+ */
114
+ getRangeFromCell(coords: CellCoords): RangeCoords;
115
+ /**
116
+ * The view-relative bounds of a range — the raw geometry primitive (never clipped, never `null`).
117
+ *
118
+ * @param range The range to measure. Defaults to the visible cell range.
119
+ * @param adjustment Optional per-edge pixel offset of the returned rect (each edge moves
120
+ * independently — this is NOT an inset, which would shrink symmetrically).
121
+ *
122
+ * @remarks
123
+ * Bounds are relative to the view (they move with scroll), NOT absolute. This resolves ANY
124
+ * range, including one entirely off-screen (e.g. an overscan/buffer cell), so callers that must
125
+ * place off-viewport content use it directly. For "geometry only if visible" (clipped to the pane,
126
+ * culled to `null` when off-screen) compose with {@link toClipBounds}:
127
+ * `toClipBounds(getBoundsFromRange(range), insets)`.
128
+ */
129
+ getBoundsFromRange(range?: RangeCoords, adjustment?: Partial<Rectangle>): Bounds;
130
+ /**
131
+ * Scroll the cell coords into view.
132
+ * If the coord does not have an index it will only scroll in a single direction.
133
+ */
134
+ scrollCellCoordsIntoView(coords: Partial<CellCoords>, options?: globalThis.ScrollIntoViewOptions | boolean): Promise<Partial<TopLeft>>;
135
+ /**
136
+ * Scroll to the specified top/left.
137
+ * @param options
138
+ */
139
+ scrollTo(options?: ScrollToOptions): void;
140
+ /**
141
+ * Indicate the allowable scroll directions.
142
+ */
143
+ getScrollOrientation(): OrientationFlags;
144
+ /**
145
+ * Returns the current scroll top/left for the view.
146
+ */
147
+ getScrollTopLeft(): TopLeft;
148
+ /**
149
+ * The pane's scroll baseline at the viewport TARGET — {@link getScrollTopLeft} plus any in-flight
150
+ * scroll (an animated glide, or an applied-but-not-yet-ticked instant target). Frame-invariant math
151
+ * (chaining PageDowns under key repeat, paging during a glide) must baseline here: the rendered
152
+ * position can lag the authoritative target by a frame or a whole animation.
153
+ */
154
+ getScrollTarget?(): TopLeft;
155
+ /**
156
+ * The frozen region's pixel offset for this pane (`{ left, top }`, view px). Like
157
+ * {@link getScrollTopLeft}, this is a pixel `TopLeft` — NOT a cell count. `{ left: 0, top: 0 }` when
158
+ * nothing is frozen on that axis.
159
+ *
160
+ * @remarks
161
+ * For the freeze STRUCTURE use {@link getAllPanes} — the `Top` / `Left` / `TopLeft` entries exist only
162
+ * when frozen — and each frozen pane's {@link getPaneRange} is exactly its frozen cell band, so
163
+ * `getPaneRange().colEnd + 1` / `.rowEnd + 1` gives the frozen column / row COUNT. The configured
164
+ * freeze count as a model value lives on `ISheetView.getFreezePanes().coords`.
165
+ */
166
+ getFreezeTopLeft(): TopLeft;
167
+ /**
168
+ * Useful for internal rendering.
169
+ *
170
+ * @remarks
171
+ * The cell layout will account for zoom factors already.
172
+ */
173
+ getZoom(): number;
174
+ /**
175
+ * Returns the range for the entire GridSurface.
176
+ */
177
+ getTotalRange(): Readonly<RangeCoords>;
178
+ /**
179
+ * The size of the surface for all grid panes.
180
+ */
181
+ getSurfaceSize(): Size;
182
+ /**
183
+ * Returns the total size of all rendered values in pixels.
184
+ */
185
+ getTotalSize(): Size;
186
+ /**
187
+ * The STRUCTURAL range of THIS pane — the full band of cells the pane is responsible for, scroll-
188
+ * independent (most of it is usually off-screen). The center/scrolling pane spans
189
+ * `[freezeLeft..columnCount-1] × [freezeTop..rowCount-1]`; a frozen pane spans its frozen band.
190
+ *
191
+ * @remarks
192
+ * NOT the visible range — see {@link getVisibleRange} for the on-screen cells, and
193
+ * {@link getTotalRange} for the whole grid across all panes.
194
+ */
195
+ getPaneRange(): RangeCoords;
196
+ /**
197
+ * The STRUCTURAL pixel rectangle of THIS pane within the surface — scroll-independent (a frozen-left
198
+ * pane sits at `x: 0`; the center pane starts at the freeze width). The pixel-space analog of
199
+ * {@link getPaneRange}.
200
+ *
201
+ * @remarks
202
+ * NOT view-relative and NOT clipped — it is the pane's own box on the surface. For a range's
203
+ * geometry use {@link getBoundsFromRange}; for the whole-surface / content sizes see
204
+ * {@link getSurfaceSize} / {@link getTotalSize}.
205
+ */
206
+ getPaneBounds(): Bounds;
207
+ /**
208
+ * Convert a CLIENT coordinate (browser-viewport pixels, e.g. a pointer event's `clientX`/`clientY`)
209
+ * into a point in this pane's view space — the same space {@link getBoundsFromRange} returns — so the
210
+ * result can be hit-tested directly against a range's bounds.
211
+ *
212
+ * @param clientX Client x, as from `PointerEvent.clientX`.
213
+ * @param clientY Client y, as from `PointerEvent.clientY`.
214
+ *
215
+ * @remarks
216
+ * The usual use is turning a DOM pointer event into grid space to find what is under the pointer
217
+ * (context menus, tooltips, hover). Passing `(0, 0)` is a useful special case: it yields the offset
218
+ * between client space and this pane's view space, so a view-space rect can be mapped back to
219
+ * on-screen (client) coordinates.
220
+ */
221
+ getPanePointFromPointer(clientX: number, clientY: number): Point | null;
222
+ /**
223
+ * Returns the coords at the offset.
224
+ *
225
+ * @param x The x offset relative to the view
226
+ * @param y The y offset relative to the view
227
+ * @param actualCell Don't return the topLeft of a merge. Default value `false`.
228
+ */
229
+ getCellFromPointer(x: number, y: number, actualCell?: boolean): CellCoords | null;
230
+ /**
231
+ * Hit-test a client (absolute) point to the pane under it.
232
+ *
233
+ * @remarks
234
+ * May return a DIFFERENT pane than this one (e.g. a frozen pane the pointer is over), or `null`
235
+ * when the point is outside every pane (off the surface). Frozen panes do not overlap the center,
236
+ * so a point in the scroll region resolves to the center pane and a point in a frozen gutter to
237
+ * that frozen pane.
238
+ */
239
+ getPaneFromPointer(clientX: number, clientY: number): IGridPane | null;
240
+ /**
241
+ * Invalidate the current view.
242
+ */
243
+ invalidate(): void;
244
+ /**
245
+ * All grid panes currently mounted, keyed by {@link AnchorLocation}.
246
+ * Callable from ANY pane, so a single pane handle can reach its siblings.
247
+ *
248
+ * @remarks
249
+ * The `Center` (scrolling) pane is always present; the `Top` / `Left` / `TopLeft` panes exist only
250
+ * when the grid has frozen rows and/or columns. Use it to reach the scrolling pane
251
+ * (`getAllPanes()[AnchorLocation.Center]`), to walk every pane (e.g. hit-test across the freeze
252
+ * split), or to detect whether the grid is frozen (more than one entry).
253
+ */
254
+ getAllPanes(): Readonly<Partial<Record<AnchorLocation, IGridPane>>>;
255
+ /**
256
+ * Add a listener for a single event type to the pane's event dispatch (e.g. a custom header
257
+ * renderer listening for `pointermove` hover). Returns a remover — hold it and call it on
258
+ * teardown; no other bookkeeping needed.
259
+ *
260
+ * @param type The native event type (`'pointermove'`, `'keydown'`, …).
261
+ * @param listener Receives the React synthetic event.
262
+ * @param listenerPane Optional variant that also receives the pane the event dispatched on.
263
+ *
264
+ * @remarks
265
+ * The listener joins the pane's z-ordered dispatch walk as an element-less responder (it has no
266
+ * layer membership). Registering while the pane's element is unmounted returns a no-op remover.
267
+ */
268
+ addReactEventListener(type: string, listener: (event: React.SyntheticEvent) => void, listenerPane?: (event: React.SyntheticEvent, pane: IGridPane) => void): RemoveListener;
269
+ /**
270
+ * Contains the div element for the pane — the pane's focusable surface (event root).
271
+ */
272
+ getElement(): HTMLElement | null;
273
+ }
274
+ /**
275
+ * The geometry of a single row/column track: its index, its leading-edge pixel `offset` (VIEW-relative
276
+ * — moves with scroll) and its pixel `size` (0 for a hidden track). The visible-ordinal is the position
277
+ * in {@link IGridPane.getVisibleColumns}/{@link IGridPane.getVisibleRows}; it is deliberately NOT stored
278
+ * here (an ordinal is only meaningful relative to a specific visible enumeration — see useBorders).
279
+ */
280
+ export interface SpanSize {
281
+ /** The row/column index this span describes. */
282
+ index: number;
283
+ /** Leading-edge pixel offset, view-relative. */
284
+ offset: number;
285
+ /** Pixel extent; 0 for a hidden track. */
286
+ size: number;
287
+ }
288
+ //# sourceMappingURL=IGridPane.d.ts.map
@@ -0,0 +1,141 @@
1
+ import { CellCoords, RangeCoords, TopLeft, FixedEdge, AnchorLocation } from '@sheetxl/utils';
2
+ import { IViewport } from '@sheetxl/utils-react';
3
+ import { IGridMetrics } from '../metrics';
4
+ import { LayerNode } from '../layer';
5
+ import { LineSVGProps } from '../svg';
6
+ import { IGridPane } from './IGridPane';
7
+ export interface GridSurfaceProps extends React.HTMLAttributes<HTMLDivElement>, React.RefAttributes<IGridSurface> {
8
+ /**
9
+ * Number of columns in the grid.
10
+ */
11
+ columnCount: number;
12
+ /**
13
+ * Number of rows in the grid.
14
+ */
15
+ rowCount: number;
16
+ /**
17
+ * The metric for calculating cell positions. The surface is metrics-only; the size-convenience
18
+ * (`getRowHeight` / `getColumnWidth`) lives on {@link Grid}.
19
+ */
20
+ metrics?: IGridMetrics | null;
21
+ /**
22
+ * The scroll viewport — a single {@link IViewport} object (position + zoom + bounds + sizes +
23
+ * ticker). Pass the SAME instance to a wrapping `ScrollPane` and they stay in sync through it.
24
+ *
25
+ * @remarks
26
+ * Use a `Viewport` for a normal grid. For per-axis sharing — a sheet header that follows
27
+ * the main grid, or split peers sharing one axis — pass an `AxisViewport` composed from the relevant
28
+ * controllers. When omitted, GridSurface creates and owns its own (standalone, non-scrolling without
29
+ * a wrapper). A passed-in viewport's lifecycle (dispose) belongs to the caller.
30
+ */
31
+ viewport?: IViewport;
32
+ /**
33
+ * Returns the cell as a range. If this cell is merged this will be reflected.
34
+ *
35
+ * @remarks
36
+ * Slightly more sophisticated than rowSpan and colSpan because it allows for queries that are not on the top/left.
37
+ */
38
+ getRangeFromCell?: (coords: CellCoords) => RangeCoords;
39
+ /**
40
+ * Will skip rendering for this row and the adjacent rows in the given direction.
41
+ */
42
+ hiddenRowsAt?: (rowIndex: number, forward?: boolean) => number;
43
+ /**
44
+ * Will skip rendering for this columns and the adjacent columns in the given direction.
45
+ */
46
+ hiddenColumnsAt?: (colIndex: number, forward?: boolean) => number;
47
+ /**
48
+ * Number of frozen left columns, or a {@link FixedEdge} whose `offset` is the frozen-region scroll
49
+ * in zoom-independent (base) px (scaled to screen px internally by the current zoom).
50
+ */
51
+ freezeLeft?: number | FixedEdge;
52
+ /**
53
+ * Number of frozen top rows, or a {@link FixedEdge} whose `offset` is the frozen-region scroll in
54
+ * zoom-independent (base) px (scaled to screen px internally by the current zoom).
55
+ */
56
+ freezeTop?: number | FixedEdge;
57
+ /**
58
+ * Allow for customization of freezeLeftDivider
59
+ */
60
+ propsFreezeLeft?: Partial<LineSVGProps>;
61
+ /**
62
+ * Allow for customization of freezeTopDivider
63
+ */
64
+ propsFreezeTop?: Partial<LineSVGProps>;
65
+ /**
66
+ * Call only once when the renders for the first time.
67
+ */
68
+ onFirstRender?: (grid: IGridSurface) => void;
69
+ /**
70
+ * The layers, as children, bottom → top. Each layer is an ordinary React node that reads its pane
71
+ * from context ({@link useGridPane}), so the children are just JSX rendered once per pane
72
+ * (`<GridSurface><Layer>…</Layer></GridSurface>`). A layer with a `zIndex` sorts within the stack.
73
+ * For the rare layer that must be BUILT from the pane, call
74
+ * {@link useGridPane} from a small wrapper component.
75
+ */
76
+ children?: LayerNode;
77
+ /**
78
+ * Wraps each pane's layers (inside its `GridPaneProvider`), once per pane. The default is the
79
+ * identity (children pass through). The seam for **per-pane** context that must sit *outside*
80
+ * the layers yet *inside* the pane — e.g. a consumer injecting a per-pane feature context (such
81
+ * as a command scope) so layers can contribute to it. Kept a render callback so `grid-react`
82
+ * stays free of any command/feature import: the pane is passed in, the consumer supplies the
83
+ * wrapper.
84
+ *
85
+ * @param pane The pane whose layers are being wrapped (one call per pane; up to 4 with freeze).
86
+ * @param children The pane's layers (already normalized + provider-wrapped).
87
+ */
88
+ wrapPane?: (pane: IGridPane, children: React.ReactNode) => React.ReactNode;
89
+ }
90
+ /**
91
+ * The imperative API of a {@link GridSurface}, exposed on its {@link IGridSurface} handle.
92
+ */
93
+ export interface IGridSurfaceAttributes {
94
+ /**
95
+ * Invalidate and re-render the grid, dropping cached pane/cell output.
96
+ *
97
+ * @remarks
98
+ * Use after a change the surface cannot observe through its props. {@link IGrid} widens this to
99
+ * accept a cell or range to invalidate only a subset.
100
+ */
101
+ invalidate: () => void;
102
+ /**
103
+ * Scroll a cell into view.
104
+ *
105
+ * @remarks
106
+ * When `coords` omits an index it scrolls only along the axis that is provided.
107
+ *
108
+ * @returns The clamped scroll position that was applied.
109
+ */
110
+ scrollCellCoordsIntoView: (coords: Partial<CellCoords>, options?: globalThis.ScrollIntoViewOptions | boolean) => Promise<Partial<TopLeft>>;
111
+ /**
112
+ * Returns the pane at the given client coordinates. A point over a frozen pane returns that frozen
113
+ * pane; otherwise the center (scrolling) pane is returned.
114
+ */
115
+ getPaneFromClient: (x: number, y: number) => IGridPane;
116
+ /**
117
+ * Returns the pane that owns the given cell.
118
+ *
119
+ * @remarks
120
+ * Prefers the last-focused pane and falls back to the center pane. Used to support goto/navigation.
121
+ */
122
+ getPaneFromCell: (coords: CellCoords) => IGridPane;
123
+ /**
124
+ * Returns the pane at the given anchor location, or `null` when that pane is not present in the
125
+ * current freeze layout. With **no argument**, returns the pane focus would land on — the
126
+ * last-focused pane, else the center (primary scrolling) pane — the pane analog of
127
+ * {@link IGridSurfaceAttributes.focus} (`focusLastPane`), so a consumer can name "the grid's
128
+ * active pane" without knowing the freeze geometry.
129
+ */
130
+ getPane: (anchor?: AnchorLocation) => IGridPane | null;
131
+ /**
132
+ * Registers a callback fired the next time the pane layout changes. Fires at most once.
133
+ */
134
+ onPaneChangeOnce: (callback: () => void) => void;
135
+ }
136
+ /**
137
+ * Type returned via ref property
138
+ */
139
+ export interface IGridSurface extends HTMLDivElement, IGridSurfaceAttributes {
140
+ }
141
+ //# sourceMappingURL=IGridSurface.d.ts.map
@@ -0,0 +1,50 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * A tiny pub/sub keyed store scoped to a single {@link GridSurface}. It is the backing for
4
+ * {@link useSurfaceState} — state that conceptually belongs to the *view* (the surface) rather than to
5
+ * any one React component instance.
6
+ *
7
+ * @remarks
8
+ * The motivating case: a layer (e.g. `Draggable`, `FillHandle`) is
9
+ * rendered **once per pane** (Center / Top / Left / TopLeft), so a single logical layer is actually
10
+ * four separate React instances. Transient drag UI (a move ghost, a fill border) lives in component
11
+ * `useState`, so only the pane that captured the pointer updates — the frozen-pane copies stay stale.
12
+ * Hoisting that value into a per-surface store lets all four instances read/write one cell (by an
13
+ * explicit key), so every pane redraws its own (independently clipped) slice. The store lives for the
14
+ * life of the surface, so a split view / second view gets its own store and never bleeds.
15
+ */
16
+ export interface SurfaceStateStore {
17
+ has(key: string): boolean;
18
+ get(key: string): unknown;
19
+ set(key: string, value: unknown): void;
20
+ subscribe(key: string, onChange: () => void): () => void;
21
+ }
22
+ export declare const createSurfaceStateStore: () => SurfaceStateStore;
23
+ export declare const SurfaceStateContext: React.Context<SurfaceStateStore | null>;
24
+ export interface SurfaceStateProviderProps {
25
+ /**
26
+ * Explicit store to provide, overriding both inheritance and lazy creation. Pass one to force a
27
+ * scope — a test, or a nested surface that wants its own transient state despite an ancestor.
28
+ * Memoize it (a fresh store every render resets the scope).
29
+ */
30
+ store?: SurfaceStateStore;
31
+ children: React.ReactNode;
32
+ }
33
+ /**
34
+ * Provides the {@link SurfaceStateStore} backing {@link useSurfaceState} to descendant panes/layers.
35
+ * It resolves the store itself, highest priority first:
36
+ *
37
+ * 1. an explicit {@link SurfaceStateProviderProps.store} prop (override);
38
+ * 2. a store **inherited** from an ancestor `SurfaceStateProvider` — so a wider parent (e.g. a
39
+ * `SheetElement` wrapping its top-left corner + both header `GridSurface`s + the main `GridSurface`)
40
+ * shares one scope across sibling surfaces, letting a layer keyed the same in a header and in the body
41
+ * read one cell;
42
+ * 3. otherwise a **lazily-created own** store (the standalone default).
43
+ *
44
+ * So a {@link GridSurface} can unconditionally mount `<SurfaceStateProvider>` and get the right thing:
45
+ * its own isolated store when standalone (or under a split view / second view), the shared one when
46
+ * nested under a wider provider. Because inheritance is automatic, the common case is a bare
47
+ * `<SurfaceStateProvider>` with no props.
48
+ */
49
+ export declare const SurfaceStateProvider: React.FC<SurfaceStateProviderProps>;
50
+ //# sourceMappingURL=SurfaceStateProvider.d.ts.map
@@ -0,0 +1,37 @@
1
+ import { RangeCoords, Bounds, TopLeft, Rectangle, SelectionTraversalUtils } from '@sheetxl/utils';
2
+ import { ViewportMetrics } from '@sheetxl/utils-react';
3
+ import { ItemSizer, IGridMetrics } from '../metrics';
4
+ /** Clamp `value` into `[min, max]` (the one shared definition — don't re-inline per module). */
5
+ export declare const clamp: (value: number, min: number, max: number) => number;
6
+ /**
7
+ * Retrieves the indices of visible headers within a specified range.
8
+ * A header is considered visible if it is not hidden according to the `hiddenAt` callback.
9
+ *
10
+ * @param hiddenAt Callback to determine hidden headers at a given index.
11
+ * @param startIndex The starting index of the range to check.
12
+ * @param stopIndex The ending index of the range to check.
13
+ * @returns An array of visible header indices within the specified range.
14
+ */
15
+ export declare const getVisibleHeaders: (hiddenAt: SelectionTraversalUtils.HiddenHeadersAt | undefined, startIndex: number, stopIndex: number) => number[];
16
+ export declare const virtualScrollToBounds: (elementBounds: Bounds, viewport: ViewportMetrics, options?: globalThis.ScrollIntoViewOptions | boolean) => TopLeft | undefined;
17
+ /**
18
+ * default implementation of hiddenAt. Uses layout and will scan zero length.
19
+ *
20
+ * Not very efficient as this just scans.
21
+ */
22
+ export declare const calcHiddenAt: (index: number, reverse: boolean | undefined, sizer: ItemSizer, limit: number) => number;
23
+ /**
24
+ * Clip `bounds` to `limitBounds` (with optional `insets`). Returns `null` when nothing survives —
25
+ * i.e. `bounds` is entirely outside `limitBounds`.
26
+ */
27
+ export declare const clipBounds: (bounds: Bounds, limitBounds: Bounds, insets?: number) => Bounds | null;
28
+ /**
29
+ * Returns the bounds for a range given a cellLayout and an optional adjustment
30
+ * The range or layout is not validated as this is expected to be a performant function
31
+ */
32
+ export declare const getBoundsFromRange: (layout: IGridMetrics, range: RangeCoords, adjustment?: Partial<Rectangle>) => Bounds;
33
+ /**
34
+ * Returns true if the x and y are bot within the bounds.
35
+ */
36
+ export declare const isPointWithinBounds: (x: number, y: number, bounds: Bounds) => boolean;
37
+ //# sourceMappingURL=_GridUtils.d.ts.map
@@ -0,0 +1,7 @@
1
+ export * from './IGridPane';
2
+ export * from './IGridSurface';
3
+ export * from './GridSurface';
4
+ export * from './useGridPane';
5
+ export * from './useSurfaceState';
6
+ export * from './SurfaceStateProvider';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,31 @@
1
+ import { IGridPane } from './IGridPane';
2
+ /**
3
+ * Hook to access the current GridPane from context
4
+ *
5
+ * @throws Error if called outside of a GridPaneProvider
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * function MyLayer() {
10
+ * const pane = useGridPane();
11
+ * const bounds = pane.getRangeBounds(myRange);
12
+ * return <div>...</div>;
13
+ * }
14
+ * ```
15
+ */
16
+ export declare function useGridPane(): IGridPane;
17
+ /**
18
+ * Hook to optionally access the current GridPane from context
19
+ * Returns null if not within a GridPaneProvider
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * function MyDiv({ pane: propPane, ...props }) {
24
+ * const contextPane = useGridPaneOptional();
25
+ * const pane = propPane ?? contextPane;
26
+ * // Use pane...
27
+ * }
28
+ * ```
29
+ */
30
+ export declare function useGridPaneOptional(): IGridPane | null;
31
+ //# sourceMappingURL=useGridPane.d.ts.map
@@ -0,0 +1,22 @@
1
+ import { Dispatch, SetStateAction } from 'react';
2
+ /**
3
+ * Like {@link React.useState}, but the cell is **keyed** and scoped to the enclosing {@link GridSurface},
4
+ * so every pane that renders this layer reads/writes the SAME cell — writing it from the pane that owns a
5
+ * drag re-renders the frozen-pane copies too (each draws its own clipped slice). Use it for transient,
6
+ * view-scoped layer UI (a move ghost, a fill border, marching ants, a drag-insert line).
7
+ *
8
+ * @param key - A stable identifier for this piece of shared state, **unique within the surface**.
9
+ * Identity is an explicit key, not call position: two mirrored panes are separate React trees (each
10
+ * gets its own fiber, and client `useId` is only a mount-order counter), so there is no positional
11
+ * identity to collapse across them. This is the same idea as a React `key`, a Redux slice, or a store
12
+ * key. For a **singleton** use a constant (`'movable-drag'`); for **multi-instance** state (e.g. one
13
+ * mover per range) compose the model's identity into the key (`` `range-move:${rangeKey}` ``) so the
14
+ * same logical instance shares across panes while distinct instances stay separate.
15
+ * @param initialValue - The initial value (or a lazy initializer), exactly like `useState`.
16
+ *
17
+ * @remarks
18
+ * Outside a {@link GridSurface} (e.g. a standalone test) it transparently falls back to a per-instance
19
+ * store, so it still behaves like ordinary local state.
20
+ */
21
+ export declare function useSurfaceState<T>(key: string, initialValue: T | (() => T)): [T, Dispatch<SetStateAction<T>>];
22
+ //# sourceMappingURL=useSurfaceState.d.ts.map
@@ -0,0 +1,13 @@
1
+ import { default as React } from 'react';
2
+ import { ShapeProps } from './Types';
3
+ export interface LineSVGProps extends React.SVGProps<SVGSVGElement>, ShapeProps {
4
+ linePoints: number[];
5
+ propsPath?: React.SVGProps<SVGPathElement>;
6
+ }
7
+ /**
8
+ * A **shape**: an SVG polyline painted within the given `bounds` (used for gridlines). Like
9
+ * {@link RectangleSVG}, it takes resolved bounds and knows nothing about ranges or the pane — a
10
+ * **layer** would place it. (Shapes take bounds and paint; layers are pane-aware.)
11
+ */
12
+ export declare const LineSVG: (props: LineSVGProps) => React.JSX.Element | null;
13
+ //# sourceMappingURL=LineSVG.d.ts.map