@sheetxl/grid-react 0.7.28-beta.4 → 0.8.0-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.
- package/browser/cjs/index.cjs +2 -2
- package/browser/esm/index.mjs +1245 -1143
- package/licenses/dependencies.txt +35 -1
- package/node/esm/index.mjs +1053 -969
- package/package.json +3 -3
- package/types/src/layer/HoverTipLayer.d.ts +20 -47
- package/types/src/layer/RangeFloatLayer.d.ts +141 -0
- package/types/src/layer/StickyAnchor.d.ts +2 -4
- package/types/src/layer/StickyFloat.d.ts +4 -1
- package/types/src/layer/index.d.ts +2 -1
- package/types/src/layer/useGridAnchor.d.ts +23 -6
- package/types/src/layer/useRangeHover.d.ts +5 -4
- package/types/src/list/List.d.ts +5 -5
- package/types/src/list/ListSurface.d.ts +73 -0
- package/types/src/list/index.d.ts +1 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sheetxl/grid-react",
|
|
3
3
|
"description": "Grid React - Advanced grid component for React",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.8.0-beta.1",
|
|
5
5
|
"license": "SEE LICENSE IN <LICENSE>",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@floating-ui/react-dom": "^2.1.9",
|
|
45
|
-
"@sheetxl/utils": "^0.
|
|
46
|
-
"@sheetxl/utils-react": "^0.
|
|
45
|
+
"@sheetxl/utils": "^0.8.0-beta.1",
|
|
46
|
+
"@sheetxl/utils-react": "^0.8.0-beta.1",
|
|
47
47
|
"clsx": "^2.1.1",
|
|
48
48
|
"react-merge-refs": "^3.0.2",
|
|
49
49
|
"react-use": "^17.6.1",
|
|
@@ -1,29 +1,25 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { CellCoords, RangeCoords } from '@sheetxl/utils';
|
|
3
3
|
import { IGridPane } from '../surface';
|
|
4
|
-
import { LayerProps } from './Layer';
|
|
5
4
|
import { StickyState } from './StickyAnchor';
|
|
6
5
|
import { HoverTipProps } from './useHoverIntent';
|
|
7
|
-
import {
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* one target is a no-op). Defaults to the range's coords.
|
|
15
|
-
*/
|
|
16
|
-
key?: string;
|
|
17
|
-
/** Payload passed to the render-prop (the message, the table, …). */
|
|
18
|
-
data: T;
|
|
19
|
-
}
|
|
6
|
+
import { RangeFloatTarget, RangeFloatLayerProps } from './RangeFloatLayer';
|
|
7
|
+
/**
|
|
8
|
+
* A hit returned by a {@link HoverTipLayerProps.probe} — the range to anchor on plus arbitrary payload.
|
|
9
|
+
*
|
|
10
|
+
* The hover-flavored name for a {@link RangeFloatTarget}; they are the same shape.
|
|
11
|
+
*/
|
|
12
|
+
export type HoverTarget<T = unknown> = RangeFloatTarget<T>;
|
|
20
13
|
/** The context passed to a {@link HoverTipLayerProps} render-prop. */
|
|
21
14
|
export interface HoverTipRender<T = unknown> {
|
|
22
15
|
/** The anchored range. */
|
|
23
16
|
range: RangeCoords;
|
|
24
17
|
/** The probe payload. */
|
|
25
18
|
data: T;
|
|
26
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Spread onto the tip element to keep it open while hovered (`pointer-events:auto` + enter/leave).
|
|
21
|
+
* The same object {@link RangeFloatLayer} calls `floatProps`.
|
|
22
|
+
*/
|
|
27
23
|
tipProps: HoverTipProps;
|
|
28
24
|
/** The resolved sticky state (e.g. `state.scrollIntoView()`). */
|
|
29
25
|
state: StickyState;
|
|
@@ -31,44 +27,21 @@ export interface HoverTipRender<T = unknown> {
|
|
|
31
27
|
/**
|
|
32
28
|
* Props for {@link HoverTipLayer}.
|
|
33
29
|
*/
|
|
34
|
-
export interface HoverTipLayerProps<T = unknown> extends Omit<
|
|
35
|
-
/** Class for the floated tip container. */
|
|
36
|
-
className?: string;
|
|
37
|
-
/** Style for the floated tip container. */
|
|
38
|
-
style?: React.CSSProperties;
|
|
30
|
+
export interface HoverTipLayerProps<T = unknown> extends Omit<RangeFloatLayerProps<T>, 'activateOn' | 'selection' | 'target' | 'probe' | 'children'> {
|
|
39
31
|
/** Probe the hovered cell → a {@link HoverTarget} (range + data), or `null` when nothing should show. */
|
|
40
32
|
probe: (coords: CellCoords, pane: IGridPane) => HoverTarget<T> | null;
|
|
41
|
-
/** Which side of the range the tip attaches to. @defaultValue `{ side: 't' }` */
|
|
42
|
-
placement?: GridPlacement;
|
|
43
|
-
/** Gap (px) perpendicular to the edge. @defaultValue 6 */
|
|
44
|
-
offset?: number;
|
|
45
|
-
/** Offset (px) along the edge (only `start` / `end` align). @defaultValue 0 */
|
|
46
|
-
alignOffset?: number;
|
|
47
|
-
/** Dwell (ms) before the tip shows. @defaultValue 300 */
|
|
48
|
-
openDelay?: number;
|
|
49
|
-
/** Grace (ms) before the tip hides (bridges the gap to the tip). @defaultValue 150 */
|
|
50
|
-
closeDelay?: number;
|
|
51
|
-
/** What happens when the anchor leaves the data area. @defaultValue 'hide' */
|
|
52
|
-
whenOff?: GridWhenOff;
|
|
53
|
-
/** Clip / clamp boundary. @defaultValue 'data' */
|
|
54
|
-
boundary?: GridBoundary;
|
|
55
|
-
/** @defaultValue 1250 */
|
|
56
|
-
zIndex?: number;
|
|
57
|
-
/**
|
|
58
|
-
* Edge-triggered hard dismissal: when this transitions truthy the current tip closes **immediately**
|
|
59
|
-
* (bypassing `closeDelay`) — e.g. the anchored cell entered edit mode. It does not hold the tip
|
|
60
|
-
* closed; a subsequent hover re-opens it normally.
|
|
61
|
-
*/
|
|
62
|
-
dismiss?: boolean;
|
|
63
33
|
/** Render the tip. **Spread `tipProps`** on the returned element so hovering it keeps the tip open. */
|
|
64
34
|
children: (info: HoverTipRender<T>) => React.ReactNode;
|
|
65
35
|
}
|
|
66
36
|
/**
|
|
67
|
-
* The
|
|
68
|
-
* `
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
37
|
+
* The **hover preset** of {@link RangeFloatLayer} — `activateOn: 'hover'`, with the render-prop's
|
|
38
|
+
* `floatProps` surfaced under its original name `tipProps`.
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* The engine (pointer tap, hover intent, anchoring, dismissal) lives in {@link RangeFloatLayer}; this
|
|
42
|
+
* is the ergonomic entry point for the pure-tooltip case and the shape `CellErrorLayer` uses. Reach
|
|
43
|
+
* for `RangeFloatLayer` directly when the float is activated by the selection, driven by a gesture, or
|
|
44
|
+
* is something other than a tip.
|
|
72
45
|
*/
|
|
73
46
|
export declare const HoverTipLayer: <T>(props: HoverTipLayerProps<T>) => React.ReactElement;
|
|
74
47
|
//# sourceMappingURL=HoverTipLayer.d.ts.map
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { CellCoords, RangeCoords } from '@sheetxl/utils';
|
|
3
|
+
import { IGridPane } from '../surface';
|
|
4
|
+
import { ICellAnchor } from '../selection/ICellAnchor';
|
|
5
|
+
import { LayerProps } from './Layer';
|
|
6
|
+
import { StickyState } from './StickyAnchor';
|
|
7
|
+
import { HoverTipProps } from './useHoverIntent';
|
|
8
|
+
import { GridPlacement, GridWhenOff, GridBoundary } from './useGridAnchor';
|
|
9
|
+
/**
|
|
10
|
+
* How the layer decides WHICH range is floating.
|
|
11
|
+
*
|
|
12
|
+
* - `'hover'` — the pointer, through the shared hover intent (open / close delays, keep-open-on-float).
|
|
13
|
+
* - `'selection'` — the active cell of {@link RangeFloatLayerProps.selection}, with no delay: a resting
|
|
14
|
+
* affordance, not a transient tip.
|
|
15
|
+
*
|
|
16
|
+
* Pass an array to accept EITHER (`['hover','selection']` — not an AND; each one opens the float on its
|
|
17
|
+
* own). Omit entirely and drive {@link RangeFloatLayerProps.target} yourself (gesture-driven action
|
|
18
|
+
* popups — paste options, autofill options).
|
|
19
|
+
*/
|
|
20
|
+
export type RangeFloatActivation = 'hover' | 'selection';
|
|
21
|
+
/** A hit from a {@link RangeFloatLayerProps.probe} — the range to anchor on plus arbitrary payload. */
|
|
22
|
+
export interface RangeFloatTarget<T = unknown> {
|
|
23
|
+
/** The range the float anchors to (e.g. the cell's own range, a merge, or an enclosing table). */
|
|
24
|
+
range: RangeCoords;
|
|
25
|
+
/**
|
|
26
|
+
* Stable identity for dedupe — the float re-opens only when this changes (a `pointermove` storm
|
|
27
|
+
* within one target is a no-op). Defaults to the range's coords.
|
|
28
|
+
*/
|
|
29
|
+
key?: string;
|
|
30
|
+
/** Payload passed to the render-prop (the message, the validation, the table, …). */
|
|
31
|
+
data: T;
|
|
32
|
+
}
|
|
33
|
+
/** The context passed to a {@link RangeFloatLayerProps} render-prop. */
|
|
34
|
+
export interface RangeFloatRender<T = unknown> {
|
|
35
|
+
/** The anchored range. */
|
|
36
|
+
range: RangeCoords;
|
|
37
|
+
/** The probe payload. */
|
|
38
|
+
data: T;
|
|
39
|
+
/**
|
|
40
|
+
* Spread onto the floated element. Supplies `pointer-events: auto` (a layer's box never takes the
|
|
41
|
+
* pointer, so content must opt back in) and — under `'hover'` — the enter/leave handlers that keep
|
|
42
|
+
* the float open while the pointer is on it.
|
|
43
|
+
*/
|
|
44
|
+
floatProps: HoverTipProps;
|
|
45
|
+
/** The resolved sticky state (e.g. `state.scrollIntoView()`, `state.slid`). */
|
|
46
|
+
state: StickyState;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Props for {@link RangeFloatLayer}.
|
|
50
|
+
*/
|
|
51
|
+
export interface RangeFloatLayerProps<T = unknown> extends Omit<LayerProps, 'children'> {
|
|
52
|
+
/** Class for the floated container. */
|
|
53
|
+
className?: string;
|
|
54
|
+
/** Style for the floated container. */
|
|
55
|
+
style?: React.CSSProperties;
|
|
56
|
+
/**
|
|
57
|
+
* What makes a float appear. Omit to drive {@link target} yourself.
|
|
58
|
+
* @defaultValue none (controlled)
|
|
59
|
+
*/
|
|
60
|
+
activateOn?: RangeFloatActivation | readonly RangeFloatActivation[];
|
|
61
|
+
/**
|
|
62
|
+
* Identity for the hover state this layer brokers across its per-pane copies. Defaults to the
|
|
63
|
+
* layer's z-slot, which is already unique per grid child — pass one only when a SINGLE grid child
|
|
64
|
+
* hosts more than one `RangeFloatLayer` (they would otherwise share a cell and fight).
|
|
65
|
+
*/
|
|
66
|
+
name?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Ask whether a cell has something to float — the anchor range + payload, or `null` for nothing.
|
|
69
|
+
* Called with the hovered cell (`'hover'`) and with the selection's active cell (`'selection'`), so
|
|
70
|
+
* one probe serves both. Not needed when {@link target} is controlled.
|
|
71
|
+
*/
|
|
72
|
+
probe?: (coords: CellCoords, pane: IGridPane) => RangeFloatTarget<T> | null;
|
|
73
|
+
/**
|
|
74
|
+
* The selection to follow for `activateOn: 'selection'`. An {@link ICellAnchor} rather than a full
|
|
75
|
+
* selection — the layer only ever reads the active cell and subscribes to it.
|
|
76
|
+
*/
|
|
77
|
+
selection?: ICellAnchor;
|
|
78
|
+
/**
|
|
79
|
+
* Controlled target: supply it (including `null`) and the layer floats exactly what you say,
|
|
80
|
+
* ignoring `activateOn` / `probe`. The escape hatch for gesture-driven popups whose lifetime is the
|
|
81
|
+
* action's, not the pointer's.
|
|
82
|
+
*/
|
|
83
|
+
target?: RangeFloatTarget<T> | null;
|
|
84
|
+
/**
|
|
85
|
+
* Hard close. Under `'hover'` it is **edge-triggered**: the float drops now, bypassing `closeDelay`,
|
|
86
|
+
* and a later hover re-opens normally. Under `'selection'` there is no gesture to re-arm it, so it
|
|
87
|
+
* reads as a **level**: the float stays closed while this holds and returns when it clears (e.g. the
|
|
88
|
+
* anchored cell is in edit mode). Ignored when {@link target} is controlled — the lifetime is yours
|
|
89
|
+
* there, so close it by passing `null`.
|
|
90
|
+
*/
|
|
91
|
+
dismiss?: boolean;
|
|
92
|
+
/** Which side of the range the float attaches to. @defaultValue `{ side: 't' }` */
|
|
93
|
+
placement?: GridPlacement;
|
|
94
|
+
/** Gap (px) perpendicular to the edge. @defaultValue 6 */
|
|
95
|
+
offset?: number;
|
|
96
|
+
/** Offset (px) along the edge (only `start` / `end` align). @defaultValue 0 */
|
|
97
|
+
alignOffset?: number;
|
|
98
|
+
/** Dwell (ms) before a hovered float shows. @defaultValue 300 */
|
|
99
|
+
openDelay?: number;
|
|
100
|
+
/** Grace (ms) before a hovered float hides (bridges the gap to the float). @defaultValue 150 */
|
|
101
|
+
closeDelay?: number;
|
|
102
|
+
/** What happens when the anchor leaves the data area. @defaultValue 'hide' */
|
|
103
|
+
whenOff?: GridWhenOff;
|
|
104
|
+
/** Where the float may live. @defaultValue 'data' */
|
|
105
|
+
boundary?: GridBoundary;
|
|
106
|
+
/** @defaultValue 1250 */
|
|
107
|
+
zIndex?: number;
|
|
108
|
+
/** Render the float. **Spread `floatProps`** on the returned element. */
|
|
109
|
+
children: (info: RangeFloatRender<T>) => React.ReactNode;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The **range float layer**: content anchored to a range that portals out of the pane clip. It owns
|
|
113
|
+
* the three things every such float needs — **anchoring** (a {@link StickyFloat} on the probed range),
|
|
114
|
+
* **activation** (what makes it appear) and **dismissal**. What it draws is entirely the consumer's:
|
|
115
|
+
* a tooltip, a button, a toolbar, an action popup.
|
|
116
|
+
*
|
|
117
|
+
* @remarks
|
|
118
|
+
* This is the **float half** of the grid's two mechanisms. A `CellTileDiv` covers everything whose
|
|
119
|
+
* content is a function of the cell alone — clicks and hover styling included — as a cached DOM
|
|
120
|
+
* snapshot. A float is for content that depends on transient UI state (selection, hover, open/closed)
|
|
121
|
+
* or that must leave the cell box. "Only on the active cell" is the expensive predicate: it would
|
|
122
|
+
* dirty a tile per selection move, which is exactly why it belongs here.
|
|
123
|
+
*
|
|
124
|
+
* Activation is pluggable and the rest of the layer is identical across the choices:
|
|
125
|
+
*
|
|
126
|
+
* ```tsx
|
|
127
|
+
* <RangeFloatLayer activateOn="hover" probe={probeError}>
|
|
128
|
+
* {({ data, floatProps }) => <div {...floatProps}>{data.message}</div>}
|
|
129
|
+
* </RangeFloatLayer>
|
|
130
|
+
*
|
|
131
|
+
* <RangeFloatLayer activateOn="selection" selection={selection} probe={probeList}>
|
|
132
|
+
* {({ range, floatProps }) => <Chevron {...floatProps} onPointerDown={() => open(range)} />}
|
|
133
|
+
* </RangeFloatLayer>
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* When either can activate it, hover is the transient override and selection is the resting state:
|
|
137
|
+
* while the pointer holds a target the float shows that one, and it falls back to the selection's when
|
|
138
|
+
* the pointer leaves.
|
|
139
|
+
*/
|
|
140
|
+
export declare const RangeFloatLayer: <T>(props: RangeFloatLayerProps<T>) => React.ReactElement;
|
|
141
|
+
//# sourceMappingURL=RangeFloatLayer.d.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { Bounds, Point, AnchorLocation } from '@sheetxl/utils';
|
|
3
3
|
import { IGridPane } from '../surface';
|
|
4
|
-
import { GridAnchor, GridPlacement, GridBoundary, GridWhenOff, GridSlide } from './useGridAnchor';
|
|
4
|
+
import { GridAnchor, GridAnchorReference, GridPlacement, GridBoundary, GridWhenOff, GridSlide } from './useGridAnchor';
|
|
5
5
|
/**
|
|
6
6
|
* The state a {@link StickyAnchor} publishes to its child. Carries the resolved `anchorPoint` (+ owner /
|
|
7
7
|
* clip / slide state) so the child alone decides how to render:
|
|
@@ -14,9 +14,7 @@ import { GridAnchor, GridPlacement, GridBoundary, GridWhenOff, GridSlide } from
|
|
|
14
14
|
*/
|
|
15
15
|
export interface StickyState {
|
|
16
16
|
/** Client-space Floating UI virtual reference (stable identity; reads live). */
|
|
17
|
-
reference:
|
|
18
|
-
getBoundingClientRect: () => DOMRect;
|
|
19
|
-
};
|
|
17
|
+
reference: GridAnchorReference;
|
|
20
18
|
/** Client-space boundary rect (for `flip`/`shift`/`hide` limiters). */
|
|
21
19
|
getBoundaryRect: () => DOMRect;
|
|
22
20
|
/** The placement's anchor pixel (client px). */
|
|
@@ -32,7 +32,10 @@ export interface StickyFloatProps {
|
|
|
32
32
|
placement?: GridPlacement;
|
|
33
33
|
/** What happens when the anchor leaves the data area. @defaultValue 'hide' */
|
|
34
34
|
whenOff?: GridWhenOff;
|
|
35
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Where the float may LIVE — one rect, resolved by {@link GridBoundary}: it is both the anchor's
|
|
37
|
+
* clip / clamp boundary and the rect `flip` / `shift` collide against. @defaultValue 'data'
|
|
38
|
+
*/
|
|
36
39
|
boundary?: GridBoundary;
|
|
37
40
|
/** Px overlap below which a geometried anchor reads as clipped. @defaultValue 0 */
|
|
38
41
|
minVisible?: number;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export * from './LayerTypes';
|
|
2
2
|
export * from './Layer';
|
|
3
3
|
export * from './VirtualDiv';
|
|
4
|
-
export type { GridAnchor, GridPlacement, GridWhenOff, GridBoundary, GridFloatSide, GridAlign, GridSlide } from './useGridAnchor';
|
|
4
|
+
export type { GridAnchor, GridAnchorReference, GridPlacement, GridWhenOff, GridBoundary, GridFloatSide, GridAlign, GridSlide } from './useGridAnchor';
|
|
5
5
|
export * from './StickyAnchor';
|
|
6
6
|
export * from './StickyFloat';
|
|
7
7
|
export * from './useHoverIntent';
|
|
8
8
|
export * from './useRangeHover';
|
|
9
|
+
export * from './RangeFloatLayer';
|
|
9
10
|
export * from './HoverTipLayer';
|
|
10
11
|
export * from './RangePrompt';
|
|
11
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -60,15 +60,18 @@ export type GridAnchor = {
|
|
|
60
60
|
point: Point;
|
|
61
61
|
};
|
|
62
62
|
/**
|
|
63
|
-
* The clip / clamp boundary — a **rect fed to the positioning math**, NOT a DOM parent.
|
|
64
|
-
*
|
|
63
|
+
* The clip / clamp boundary — a **rect fed to the positioning math**, NOT a DOM parent. One prop, one
|
|
64
|
+
* meaning: *where may this thing live*. It governs the anchor's clip / clamp AND (via `StickyFloat`)
|
|
65
|
+
* where `flip` / `shift` may land the float. This is how "don't slide under the headers" is expressed:
|
|
66
|
+
* clamp to the data viewport.
|
|
65
67
|
*
|
|
66
68
|
* - `'data'` — the union of the panes' cell areas (headers excluded). Default.
|
|
67
69
|
* - `'pane'` — just the resolving pane's cell area.
|
|
68
70
|
* - `'grid'` — currently the same as `'data'` (until a surface/header rect is threaded).
|
|
71
|
+
* - `'viewport'` — the browser viewport: the opt-out, for a float that may cover grid chrome.
|
|
69
72
|
* - a {@link Bounds} — an explicit **client-px** rect.
|
|
70
73
|
*/
|
|
71
|
-
export type GridBoundary = 'data' | 'pane' | 'grid' | Bounds;
|
|
74
|
+
export type GridBoundary = 'data' | 'pane' | 'grid' | 'viewport' | Bounds;
|
|
72
75
|
/** A `DOMRect`-shaped plain object (works in Floating UI and in Node tests without a DOM). */
|
|
73
76
|
export interface GridAnchorRect {
|
|
74
77
|
x: number;
|
|
@@ -106,15 +109,29 @@ export interface GridAnchorResolved {
|
|
|
106
109
|
*/
|
|
107
110
|
outOfView: boolean;
|
|
108
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* The Floating UI **virtual reference** for a grid anchor. Stable identity (so `autoUpdate` subscribes
|
|
114
|
+
* once), but both members read **live**.
|
|
115
|
+
*/
|
|
116
|
+
export interface GridAnchorReference {
|
|
117
|
+
/** The anchor's client rect, read live on every call (`autoUpdate` calls it between React renders). */
|
|
118
|
+
getBoundingClientRect: () => DOMRect;
|
|
119
|
+
/**
|
|
120
|
+
* The pane element. `autoUpdate` unwraps a virtual reference to *this* element and gates **every**
|
|
121
|
+
* DOM-side trigger on it — ancestor `scroll`, the `observeMove` layout-shift detector, element resize.
|
|
122
|
+
* Without it only the window `resize` listener survives, which is why the float used to need a 60fps
|
|
123
|
+
* `animationFrame` poll. A **getter**: the pane element only exists after mount, and resolving it
|
|
124
|
+
* lazily keeps this object's identity stable.
|
|
125
|
+
*/
|
|
126
|
+
readonly contextElement?: Element;
|
|
127
|
+
}
|
|
109
128
|
/** The hook result: stable live accessors + render-time snapshot values. */
|
|
110
129
|
export interface UseGridAnchorResult {
|
|
111
130
|
/**
|
|
112
131
|
* A Floating UI **virtual reference** with **stable identity** — its `getBoundingClientRect` reads
|
|
113
132
|
* the anchor **live** on every call (Floating UI's `autoUpdate` invokes it between React renders).
|
|
114
133
|
*/
|
|
115
|
-
reference:
|
|
116
|
-
getBoundingClientRect: () => DOMRect;
|
|
117
|
-
};
|
|
134
|
+
reference: GridAnchorReference;
|
|
118
135
|
/** Live accessor for the boundary rect (for `shift`/`flip`/`hide` limiters). */
|
|
119
136
|
getBoundaryRect: () => DOMRect;
|
|
120
137
|
/** Render-time snapshot: anchor outside the boundary. Updates each scroll frame (pane re-render). */
|
|
@@ -26,10 +26,11 @@ export interface UseRangeHoverResult {
|
|
|
26
26
|
*
|
|
27
27
|
* @remarks
|
|
28
28
|
* Registers a passive `pointermove` / `pointerleave` responder on the pane's Stage (mirrors
|
|
29
|
-
* a {@link Layer} tap); it never consumes the event. Because a grid child renders per pane, the
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* the
|
|
29
|
+
* a {@link Layer} tap); it never consumes the event. Because a grid child renders per pane, the pointer
|
|
30
|
+
* is seen by whichever pane it is over while the tip renders on the pane owning the anchor — which for
|
|
31
|
+
* a range straddling a freeze is a DIFFERENT pane. The aimed target is therefore brokered through
|
|
32
|
+
* {@link useSurfaceState}, so every pane copy runs its intent off the same signal and the owner is
|
|
33
|
+
* armed no matter where the pointer is.
|
|
33
34
|
*/
|
|
34
35
|
export declare const useRangeHover: (range: RangeCoords, options?: UseHoverIntentOptions) => UseRangeHoverResult;
|
|
35
36
|
//# sourceMappingURL=useRangeHover.d.ts.map
|
package/types/src/list/List.d.ts
CHANGED
|
@@ -40,16 +40,16 @@ export interface ListProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
40
40
|
ref?: React.Ref<IListElement>;
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
|
-
* A virtualized **list**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
43
|
+
* A virtualized **list** of arbitrary React content, built on {@link ListSurface} — which is the
|
|
44
|
+
* grid's own machinery (a `CellLayer` for the items and a `SelectionLayer` for the active-row
|
|
45
|
+
* highlight + Arrow keys) dressed as a list.
|
|
46
46
|
*
|
|
47
47
|
* @remarks
|
|
48
48
|
* The List's whole state is its {@link ListProps.selection}; it has no per-item callbacks and no notion
|
|
49
49
|
* of "checked" or "toggle". Pointer selection is the `SelectionLayer`'s job (it hit-tests the pointer),
|
|
50
50
|
* so the cells are inert, transparent content; the keyboard is the caller's via {@link ListProps.onKeyDown}.
|
|
51
|
-
*
|
|
52
|
-
*
|
|
51
|
+
* See {@link CheckboxList} for the checkbox-list specialization, and `SheetValueList` in
|
|
52
|
+
* `@sheetxl/react` for the sheet-backed one (real cells, so values format like the sheet).
|
|
53
53
|
*/
|
|
54
54
|
export declare const List: React.ForwardRefExoticComponent<Omit<ListProps, "ref"> & React.RefAttributes<IListElement>>;
|
|
55
55
|
//# sourceMappingURL=List.d.ts.map
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { CellLayerProps, CellRendererProps } from '../cell';
|
|
3
|
+
import { LayerEventProps } from '../layer';
|
|
4
|
+
import { ISelection } from '../selection';
|
|
5
|
+
/**
|
|
6
|
+
* Props for {@link ListSurface}.
|
|
7
|
+
*/
|
|
8
|
+
export interface ListSurfaceProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
9
|
+
/** Number of rows. */
|
|
10
|
+
itemCount: number;
|
|
11
|
+
/**
|
|
12
|
+
* Render one row, as a grid cell — the `CellLayer` renderer, so the row is handed its bounds, its
|
|
13
|
+
* pane (zoom) and its resolved `value`. The cell is positioned and clipped by the tiling engine.
|
|
14
|
+
*/
|
|
15
|
+
renderCell: (props: CellRendererProps) => React.ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the visible rows to render (and their `value`). Omit to render every visible row with no
|
|
18
|
+
* pre-resolved value — `renderCell` then derives its content from the row index.
|
|
19
|
+
*/
|
|
20
|
+
getVisibleCells?: CellLayerProps['getVisibleCells'];
|
|
21
|
+
/**
|
|
22
|
+
* Uniform row height in px. Also the list's natural height (`itemCount * itemHeight`) unless
|
|
23
|
+
* `style.height` overrides it. @defaultValue 24
|
|
24
|
+
*/
|
|
25
|
+
itemHeight?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Width the **column** should be, in px — the list sizes itself to this PLUS its own chrome (the
|
|
28
|
+
* vertical scrollbar's gutter), so the column actually ends up this wide.
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* The distinction matters because the natural thing to pass — a measured content width, e.g.
|
|
32
|
+
* `ICellRange.getBestFit().width` — describes the column, not the box. Setting it as the box's
|
|
33
|
+
* `width` instead silently hands the gutter's worth of pixels back, and content sized to fit
|
|
34
|
+
* exactly then does not. Omit to size from `style` and let the column take what is left.
|
|
35
|
+
*/
|
|
36
|
+
contentWidth?: number;
|
|
37
|
+
/**
|
|
38
|
+
* The selection model — the active-row highlight + Arrow-key navigation. The surface's *state*.
|
|
39
|
+
* Owned by the caller (so it can read what's selected); a private one is created when omitted.
|
|
40
|
+
*/
|
|
41
|
+
selection?: ISelection;
|
|
42
|
+
/**
|
|
43
|
+
* Event taps installed as the list's TOP layer — so they are offered keys and pointers before the
|
|
44
|
+
* built-in Arrow navigation and before the selection's own hit test. Handle Space/Enter here (the
|
|
45
|
+
* grid would otherwise consume them) and `stopPropagation` to override; anything you don't consume
|
|
46
|
+
* falls through to navigation.
|
|
47
|
+
*/
|
|
48
|
+
propsLayer?: LayerEventProps;
|
|
49
|
+
/** Take focus on mount, so the Arrow keys work without a click first. @defaultValue false */
|
|
50
|
+
autoFocus?: boolean;
|
|
51
|
+
/** Opaque content cache-bust forwarded to the `CellLayer`. */
|
|
52
|
+
cacheToken?: unknown;
|
|
53
|
+
/** Ref for the Element. */
|
|
54
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The **list chrome**: a virtualized single-column `GridSurface` wearing the grid's own layers — a
|
|
58
|
+
* `CellLayer` for the rows and a `SelectionLayer` for the active-row highlight + Arrow keys — dressed
|
|
59
|
+
* so it reads as a list rather than a grid.
|
|
60
|
+
*
|
|
61
|
+
* @remarks
|
|
62
|
+
* Not a list *component*: it renders no row content of its own, has no notion of an item, and adds no
|
|
63
|
+
* padding — {@link ListSurfaceProps.renderCell} owns the whole row box. It exists because there are
|
|
64
|
+
* two kinds of list ({@link List}, whose rows are arbitrary React, and `@sheetxl/react`'s
|
|
65
|
+
* `SheetValueList`, whose rows are real sheet cells) and they differ ONLY in that renderer. Everything
|
|
66
|
+
* they share — the viewport, the measured single column, the selection styling and its rationale, the
|
|
67
|
+
* layer order — is here, once.
|
|
68
|
+
*
|
|
69
|
+
* The single column tracks the measured content width, so a row spans the full list; scrolling is
|
|
70
|
+
* vertical only.
|
|
71
|
+
*/
|
|
72
|
+
export declare const ListSurface: React.ForwardRefExoticComponent<Omit<ListSurfaceProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
73
|
+
//# sourceMappingURL=ListSurface.d.ts.map
|