@sheetxl/grid-react 0.8.0-beta.2 → 0.8.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +8 -7
- package/README.md +21 -8
- package/browser/esm/index.mjs +3617 -3107
- package/licenses/dependencies.txt +0 -208
- package/node/esm/index.mjs +3955 -2532
- package/package.json +9 -13
- package/types/src/cell/CellRenderer.d.ts +32 -0
- package/types/src/cell/GridlineLayer.d.ts +39 -1
- package/types/src/editor/DefaultEditable.d.ts +16 -6
- package/types/src/editor/EditSession.d.ts +28 -5
- package/types/src/editor/EditorDiv.d.ts +3 -2
- package/types/src/editor/EditorInput.d.ts +5 -2
- package/types/src/editor/EditorLayer.d.ts +9 -4
- package/types/src/editor/EditorStartLayer.d.ts +33 -0
- package/types/src/editor/index.d.ts +1 -0
- package/types/src/editor/useEditorKeymap.d.ts +7 -2
- package/types/src/grid/Grid.d.ts +1 -1
- package/types/src/grid/IGrid.d.ts +4 -4
- package/types/src/header/GridFreezeAnchor.d.ts +29 -0
- package/types/src/header/HeaderDividerAnchor.d.ts +36 -1
- package/types/src/header/HeaderFreezeAnchor.d.ts +37 -0
- package/types/src/header/_freezeSnap.d.ts +28 -0
- package/types/src/header/_useFreezeGrip.d.ts +28 -0
- package/types/src/header/index.d.ts +2 -0
- package/types/src/header/useHeaderSelectionPointer.d.ts +4 -4
- package/types/src/layer/GestureTip.d.ts +77 -0
- package/types/src/layer/GridFloatPanel.d.ts +3 -2
- package/types/src/layer/Layer.d.ts +6 -0
- package/types/src/layer/RangeFloatLayer.d.ts +145 -53
- package/types/src/layer/RangePrompt.d.ts +8 -8
- package/types/src/layer/RangeTooltip.d.ts +128 -0
- package/types/src/layer/RangeTooltipLayer.d.ts +53 -0
- package/types/src/layer/StickyAnchor.d.ts +15 -5
- package/types/src/layer/StickyPortal.d.ts +73 -0
- package/types/src/layer/TooltipProvider.d.ts +104 -0
- package/types/src/layer/_Utils.d.ts +9 -3
- package/types/src/layer/index.d.ts +6 -4
- package/types/src/layer/useGridAnchor.d.ts +45 -4
- package/types/src/layer/useHoverIntent.d.ts +35 -8
- package/types/src/list/CheckboxList.d.ts +18 -2
- package/types/src/list/ListSearch.d.ts +24 -3
- package/types/src/list/PickList.d.ts +6 -1
- package/types/src/range/DragHandle.d.ts +13 -6
- package/types/src/range/Draggable.d.ts +29 -3
- package/types/src/range/FillHandle.d.ts +11 -2
- package/types/src/range/RangeGlide.d.ts +160 -0
- package/types/src/range/RangeRect.d.ts +7 -0
- package/types/src/range/RangeResizer.d.ts +7 -1
- package/types/src/range/index.d.ts +2 -0
- package/types/src/range/useRangeGlide.d.ts +11 -0
- package/types/src/selection/RangesPickerLayer.d.ts +4 -1
- package/types/src/selection/SelectionLayer.d.ts +71 -15
- package/types/src/selection/SelectionStyle.d.ts +4 -1
- package/types/src/selection/SelectionTouchGrips.d.ts +6 -4
- package/types/src/selection/_SelectionUtils.d.ts +6 -0
- package/types/src/selection/useDragCells.d.ts +29 -9
- package/types/src/surface/GridPane.d.ts +2 -0
- package/types/src/surface/IGridPane.d.ts +15 -2
- package/types/src/surface/SurfaceStateProvider.d.ts +1 -1
- package/types/src/surface/getPrimaryPane.d.ts +13 -0
- package/types/src/surface/index.d.ts +1 -0
- package/types/src/surface/useSurfaceState.d.ts +29 -0
- package/types/src/svg/RectangleSVG.d.ts +21 -4
- package/types/src/theme/GridTheme.d.ts +1 -1
- package/browser/cjs/index.cjs +0 -3
- package/types/src/layer/HoverTipLayer.d.ts +0 -47
- package/types/src/layer/StickyFloat.d.ts +0 -68
- package/types/src/layer/useRangeHover.d.ts +0 -36
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { RangeAxis, CellCoords, RangeCoords } from '@sheetxl/utils';
|
|
2
|
-
import {
|
|
3
|
-
import { ISelection, DragCellsController } from '../selection';
|
|
2
|
+
import { ISelection, DragCellsController, DragCellsPane } from '../selection';
|
|
4
3
|
/**
|
|
5
4
|
* Options for {@link useHeaderSelectionPointer} / {@link createHeaderSelectionPointer}.
|
|
6
5
|
*/
|
|
@@ -110,7 +109,7 @@ export declare const headerRange: (a: CellCoords, b: CellCoords, axis: RangeAxis
|
|
|
110
109
|
* keeping the viewport-anchored active cell. `getOptions` is read on every event so live values (entire
|
|
111
110
|
* range, callbacks) need no controller rebuild.
|
|
112
111
|
*/
|
|
113
|
-
export declare const createHeaderSelectionPointer: (selection: ISelection | null, pane:
|
|
112
|
+
export declare const createHeaderSelectionPointer: (selection: ISelection | null, pane: DragCellsPane, getOptions: () => HeaderSelectionPointerOptions) => DragCellsController;
|
|
114
113
|
/**
|
|
115
114
|
* The header selection pointer hook: the header-axis counterpart to the body's `useSelectionPointer`.
|
|
116
115
|
* Reads the pane from context and drives the shared {@link ISelection} model, projecting every gesture
|
|
@@ -119,7 +118,8 @@ export declare const createHeaderSelectionPointer: (selection: ISelection | null
|
|
|
119
118
|
*
|
|
120
119
|
* @remarks
|
|
121
120
|
* Options are read live through a ref, so changing `entireRange` / callbacks does not rebuild the
|
|
122
|
-
* handlers — the controller is memoized on `
|
|
121
|
+
* handlers — the controller is memoized on `selection` only; the pane is read live too, so a pane rebuilt
|
|
122
|
+
* mid-drag does not end the drag (see `DragCellsPane`). The engine's auto-scroll timer is
|
|
123
123
|
* stopped on unmount.
|
|
124
124
|
*/
|
|
125
125
|
export declare const useHeaderSelectionPointer: (selection: ISelection | null, options: HeaderSelectionPointerOptions) => HeaderSelectionPointerResult;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { RangeGlide } from '../range/RangeGlide';
|
|
3
|
+
import { GridAnchor, GridPlacement, GridBoundary } from './useGridAnchor';
|
|
4
|
+
/**
|
|
5
|
+
* A gesture readout anchored to a DOM element rather than to the grid — a scrollbar thumb, which lives
|
|
6
|
+
* outside every pane. The element moves with the drag and no DOM event says so, so the readout is
|
|
7
|
+
* repositioned each time it renders: the owner re-renders it as the gesture moves (as it changes the text).
|
|
8
|
+
*/
|
|
9
|
+
export interface GestureTipElementAnchor {
|
|
10
|
+
element: Element;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* How a {@link GestureTip} travels between positions.
|
|
14
|
+
*/
|
|
15
|
+
export interface GestureTipGlide {
|
|
16
|
+
/** How long a move takes, in ms. `0` jumps. */
|
|
17
|
+
duration: number;
|
|
18
|
+
/** The CSS easing it travels on. @defaultValue 'ease-in-out' */
|
|
19
|
+
easing?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Props for {@link GestureTip}.
|
|
23
|
+
*/
|
|
24
|
+
export interface GestureTipProps {
|
|
25
|
+
/**
|
|
26
|
+
* The gesture is in flight. While it is, the tip holds the tooltip group — no hover tip opens — even
|
|
27
|
+
* when there is nothing to say (`children` empty).
|
|
28
|
+
*/
|
|
29
|
+
active: boolean;
|
|
30
|
+
/** What the readout anchors to — the in-flight range, a frame's bounds, or a dragged element. */
|
|
31
|
+
anchor: GridAnchor | GestureTipElementAnchor;
|
|
32
|
+
/** Which side + align of the anchor the readout sits on. @defaultValue `{ side: 'b', align: 'end' }` */
|
|
33
|
+
placement?: GridPlacement;
|
|
34
|
+
/** Gap (px) between the anchor and the readout. @defaultValue 8 */
|
|
35
|
+
offset?: number;
|
|
36
|
+
/** Offset (px) along the anchored edge (only `start` / `end` align). @defaultValue 0 */
|
|
37
|
+
alignOffset?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Glide to each new position instead of jumping, on CSS timing — for an anchor animated by CSS. For
|
|
40
|
+
* one drawn by a {@link RangeGlide}, pass {@link GestureTipProps.rangeGlide} instead. Where it first
|
|
41
|
+
* appears is never animated.
|
|
42
|
+
* @defaultValue none — a readout jumps with its gesture
|
|
43
|
+
*/
|
|
44
|
+
glide?: GestureTipGlide;
|
|
45
|
+
/**
|
|
46
|
+
* Travel with this glide, frame by frame: while it is in flight the readout is carried by its frame's
|
|
47
|
+
* offset from its target, so it stays on the moving range rather than waiting at the destination.
|
|
48
|
+
* The anchor must be the glide's target range. Don't combine with {@link GestureTipProps.glide}.
|
|
49
|
+
*/
|
|
50
|
+
rangeGlide?: RangeGlide | null;
|
|
51
|
+
/** Where the readout may live (a grid anchor only). @defaultValue 'data' */
|
|
52
|
+
boundary?: GridBoundary;
|
|
53
|
+
/**
|
|
54
|
+
* Whose theme the readout wears. A readout is chrome, so the app's — even over a grid in another mode.
|
|
55
|
+
* @defaultValue 'provider'
|
|
56
|
+
*/
|
|
57
|
+
themeFrom?: 'provider' | 'anchor';
|
|
58
|
+
/**
|
|
59
|
+
* The tip's identity in the tooltip group. A layer rendered once per pane passes one name so its
|
|
60
|
+
* copies count as one tip.
|
|
61
|
+
* @defaultValue this instance
|
|
62
|
+
*/
|
|
63
|
+
name?: string;
|
|
64
|
+
className?: string;
|
|
65
|
+
/** The readout. Empty draws nothing (the group is still held while {@link active}). */
|
|
66
|
+
children?: React.ReactNode;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The readout a gesture shows while it runs — a drag-select's size, a move's destination, a fill's
|
|
70
|
+
* value, a frame's size, a header's size, the row a scrollbar thumb is at. A tooltip of the gesture
|
|
71
|
+
* kind: it opens with the gesture (no dwell), holds the tooltip group so no hover tip opens beside it,
|
|
72
|
+
* closes when the gesture ends, and takes no pointer (the gesture owns it). Drawn in the group's
|
|
73
|
+
* bubble, in the tooltip band and the app's theme; on a grid anchor, `clamp`ed so it stays on screen
|
|
74
|
+
* when the anchor runs off the grid.
|
|
75
|
+
*/
|
|
76
|
+
export declare const GestureTip: React.FC<GestureTipProps>;
|
|
77
|
+
//# sourceMappingURL=GestureTip.d.ts.map
|
|
@@ -6,9 +6,10 @@ import { FloatPanelProps } from '@sheetxl/utils-react';
|
|
|
6
6
|
*
|
|
7
7
|
* @remarks
|
|
8
8
|
* The stack keeps what it does for every popup — the portal, light-dismiss, Escape, focus restore and
|
|
9
|
-
* stacking. The position comes from {@link
|
|
9
|
+
* stacking. The position comes from {@link StickyPortal}, the engine grid buttons and labels use, so the
|
|
10
10
|
* popup moves with its cell as the grid scrolls (which no DOM event reports), flips against the same
|
|
11
|
-
* boundary, and closes once its cell has scrolled out of view.
|
|
11
|
+
* boundary, and closes once its cell has scrolled out of view. It sits in the popup band, above the
|
|
12
|
+
* grid's other floats (its buttons and labels).
|
|
12
13
|
*
|
|
13
14
|
* The stack's `propsPopper` `placement` and `offsets` are read as the grid placement and offset.
|
|
14
15
|
*/
|
|
@@ -62,6 +62,12 @@ export interface LayerProps extends LayerEventProps {
|
|
|
62
62
|
zIndex?: number;
|
|
63
63
|
/** Class for the layer's boundary div (devtools identification). */
|
|
64
64
|
className?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Style for the layer's boundary div — e.g. `display: 'none'` or `opacity` to hide or fade a layer.
|
|
67
|
+
* The boundary's own placement (`position`, `inset`, `pointer-events: none`) comes from the grid;
|
|
68
|
+
* overriding it here breaks the layer's containment.
|
|
69
|
+
*/
|
|
70
|
+
style?: React.CSSProperties;
|
|
65
71
|
/**
|
|
66
72
|
* The layer's content — {@link VirtualDiv}s, `RangeRect`s, floats — hosted inside the layer's
|
|
67
73
|
* boundary div. Children stack by DOM order within the layer (law 1).
|
|
@@ -5,20 +5,21 @@ import { ICellAnchor } from '../selection/ICellAnchor';
|
|
|
5
5
|
import { LayerProps } from './Layer';
|
|
6
6
|
import { StickyState } from './StickyAnchor';
|
|
7
7
|
import { HoverTipProps } from './useHoverIntent';
|
|
8
|
-
import { GridPlacement, GridWhenOff, GridBoundary } from './useGridAnchor';
|
|
8
|
+
import { GridPlacement, GridWhenOff, GridWhenPartial, GridBoundary } from './useGridAnchor';
|
|
9
9
|
/**
|
|
10
|
-
* How
|
|
10
|
+
* How {@link RangeFloatLayer} decides WHICH range is floating.
|
|
11
11
|
*
|
|
12
|
-
* - `'hover'` — the pointer, through the
|
|
12
|
+
* - `'hover'` — the pointer, through the tooltip group's hover intent (its timing, single-open rule and
|
|
13
|
+
* keep-open-on-float); `RangeTooltipLayer` is this, with the group's bubble.
|
|
13
14
|
* - `'selection'` — the active cell of {@link RangeFloatLayerProps.selection}, with no delay: a resting
|
|
14
15
|
* affordance, not a transient tip.
|
|
15
16
|
*
|
|
16
17
|
* 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
|
|
18
|
+
* own). Omit entirely and drive {@link RangeFloatOptions.target} yourself (gesture-driven action
|
|
18
19
|
* popups — paste options, autofill options).
|
|
19
20
|
*/
|
|
20
21
|
export type RangeFloatActivation = 'hover' | 'selection';
|
|
21
|
-
/** A hit from a
|
|
22
|
+
/** A hit from a probe — the range to anchor on plus arbitrary payload. */
|
|
22
23
|
export interface RangeFloatTarget<T = unknown> {
|
|
23
24
|
/** The range the float anchors to (e.g. the cell's own range, a merge, or an enclosing table). */
|
|
24
25
|
range: RangeCoords;
|
|
@@ -30,12 +31,17 @@ export interface RangeFloatTarget<T = unknown> {
|
|
|
30
31
|
/** Payload passed to the render-prop (the message, the validation, the table, …). */
|
|
31
32
|
data: T;
|
|
32
33
|
/**
|
|
33
|
-
* Where this target's float attaches, for a
|
|
34
|
-
* Defaults to the
|
|
34
|
+
* Where this target's float attaches, for a float whose targets do not all belong on one side.
|
|
35
|
+
* Defaults to the float's {@link RangeFloatOptions.placement}.
|
|
35
36
|
*/
|
|
36
37
|
placement?: GridPlacement;
|
|
38
|
+
/**
|
|
39
|
+
* Offset (px) along the edge for this target, for a float whose offset depends on the anchor (e.g.
|
|
40
|
+
* a fraction of its width). Defaults to the float's {@link RangeFloatOptions.alignOffset}.
|
|
41
|
+
*/
|
|
42
|
+
alignOffset?: number;
|
|
37
43
|
}
|
|
38
|
-
/** The context passed to a
|
|
44
|
+
/** The context passed to a range float's render-prop. */
|
|
39
45
|
export interface RangeFloatRender<T = unknown> {
|
|
40
46
|
/** The anchored range. */
|
|
41
47
|
range: RangeCoords;
|
|
@@ -43,55 +49,52 @@ export interface RangeFloatRender<T = unknown> {
|
|
|
43
49
|
data: T;
|
|
44
50
|
/**
|
|
45
51
|
* Spread onto the floated element. Supplies `pointer-events: auto` (a layer's box never takes the
|
|
46
|
-
* pointer, so content must opt back in) and —
|
|
47
|
-
*
|
|
52
|
+
* pointer, so content must opt back in) and — for a hovered float — the enter/leave handlers that
|
|
53
|
+
* keep it open while the pointer is on it.
|
|
48
54
|
*/
|
|
49
55
|
floatProps: HoverTipProps;
|
|
50
56
|
/** The resolved sticky state (e.g. `state.scrollIntoView()`, `state.slid`). */
|
|
51
57
|
state: StickyState;
|
|
52
58
|
}
|
|
53
59
|
/**
|
|
54
|
-
*
|
|
60
|
+
* How a range float takes part in the UI around it.
|
|
61
|
+
*
|
|
62
|
+
* - `'none'` — takes no pointer at all: a label, a readout, a prompt box.
|
|
63
|
+
* - `'pointer'` — takes the pointer, and its presses, keys, clipboard, context menu and wheel stop at
|
|
64
|
+
* the float: the float is portaled out of the pane, but React events bubble the React TREE, which
|
|
65
|
+
* would carry them to the grid's own handlers. A button, a chevron, a toolbar.
|
|
66
|
+
* - `'focus'` — `'pointer'`, and the float can hold the caret: while focus is inside it stays on its
|
|
67
|
+
* target whatever the pointer does; Escape or a press anywhere outside it (a cell, a menu button, a
|
|
68
|
+
* right-click) closes it, focus returns to the grid, and {@link RangeFloatOptions.onDismiss} is told.
|
|
69
|
+
* "Outside" is judged by the React tree, so a menu the float opens in a portal of its own is inside.
|
|
70
|
+
* A card with a text field.
|
|
55
71
|
*/
|
|
56
|
-
export
|
|
57
|
-
|
|
58
|
-
|
|
72
|
+
export type RangeFloatInteractive = 'none' | 'pointer' | 'focus';
|
|
73
|
+
/**
|
|
74
|
+
* What every range float takes, however it is activated: placement, dismissal, hover timing,
|
|
75
|
+
* interactivity and the render-prop.
|
|
76
|
+
*/
|
|
77
|
+
export interface RangeFloatOptions<T = unknown> {
|
|
59
78
|
/** Style for the floated container. */
|
|
60
79
|
style?: React.CSSProperties;
|
|
61
80
|
/**
|
|
62
|
-
*
|
|
63
|
-
* @defaultValue none (controlled)
|
|
64
|
-
*/
|
|
65
|
-
activateOn?: RangeFloatActivation | readonly RangeFloatActivation[];
|
|
66
|
-
/**
|
|
67
|
-
* Identity for the hover state this layer brokers across its per-pane copies. Defaults to the
|
|
81
|
+
* Identity for the hover state brokered across the float's per-pane copies. Defaults to the host
|
|
68
82
|
* layer's z-slot, which is already unique per grid child — pass one only when a SINGLE grid child
|
|
69
|
-
* hosts more than one
|
|
83
|
+
* hosts more than one range float (they would otherwise share a cell and fight).
|
|
70
84
|
*/
|
|
71
85
|
name?: string;
|
|
72
86
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*/
|
|
77
|
-
probe?: (coords: CellCoords, pane: IGridPane) => RangeFloatTarget<T> | null;
|
|
78
|
-
/**
|
|
79
|
-
* The selection to follow for `activateOn: 'selection'`. An {@link ICellAnchor} rather than a full
|
|
80
|
-
* selection — the layer only ever reads the active cell and subscribes to it.
|
|
81
|
-
*/
|
|
82
|
-
selection?: ICellAnchor;
|
|
83
|
-
/**
|
|
84
|
-
* Controlled target: supply it (including `null`) and the layer floats exactly what you say,
|
|
85
|
-
* ignoring `activateOn` / `probe`. The escape hatch for gesture-driven popups whose lifetime is the
|
|
86
|
-
* action's, not the pointer's.
|
|
87
|
+
* Controlled target: supply it (including `null`) and the float shows exactly what you say, ignoring
|
|
88
|
+
* hover and selection. The escape hatch for gesture-driven popups whose lifetime is the action's,
|
|
89
|
+
* not the pointer's.
|
|
87
90
|
*/
|
|
88
91
|
target?: RangeFloatTarget<T> | null;
|
|
89
92
|
/**
|
|
90
|
-
* Hard close.
|
|
91
|
-
* and a later hover re-opens normally.
|
|
92
|
-
* reads as a **level**: the float stays closed while this holds and returns when it clears
|
|
93
|
-
* anchored cell is in edit mode). Ignored when {@link target} is controlled — the lifetime
|
|
94
|
-
* there, so close it by passing `null`.
|
|
93
|
+
* Hard close. For a hovered float it is **edge-triggered**: the float drops now, bypassing
|
|
94
|
+
* `closeDelay`, and a later hover re-opens normally. For the selection there is no gesture to re-arm
|
|
95
|
+
* it, so it reads as a **level**: the float stays closed while this holds and returns when it clears
|
|
96
|
+
* (e.g. the anchored cell is in edit mode). Ignored when {@link target} is controlled — the lifetime
|
|
97
|
+
* is yours there, so close it by passing `null`.
|
|
95
98
|
*/
|
|
96
99
|
dismiss?: boolean;
|
|
97
100
|
/** Which side of the range the float attaches to. @defaultValue `{ side: 't' }` */
|
|
@@ -100,24 +103,116 @@ export interface RangeFloatLayerProps<T = unknown> extends Omit<LayerProps, 'chi
|
|
|
100
103
|
offset?: number;
|
|
101
104
|
/** Offset (px) along the edge (only `start` / `end` align). @defaultValue 0 */
|
|
102
105
|
alignOffset?: number;
|
|
103
|
-
/** Dwell (ms) before a hovered float shows. @defaultValue 300 */
|
|
106
|
+
/** Dwell (ms) before a hovered float shows. @defaultValue the tooltip group's `enterDelay` (300; 0 while armed) */
|
|
104
107
|
openDelay?: number;
|
|
105
|
-
/** Grace (ms) before a hovered float hides (bridges the gap to the float). @defaultValue
|
|
108
|
+
/** Grace (ms) before a hovered float hides (bridges the gap to the float). @defaultValue the group's `leaveDelay` (400) */
|
|
106
109
|
closeDelay?: number;
|
|
110
|
+
/**
|
|
111
|
+
* A hovered float joins the grid's tooltip group (one tip at a time, closed by a press outside it or Escape).
|
|
112
|
+
* `false` for a hover-opened float that is not a tooltip — a toolbar — which must survive a tip
|
|
113
|
+
* opening beside it and a press on its own buttons.
|
|
114
|
+
* @defaultValue true
|
|
115
|
+
*/
|
|
116
|
+
group?: boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Keep a hover-opened float up although the pointer has left it — while something it opened (its
|
|
119
|
+
* dropdown) is open and has the pointer. It shows the last hovered target, and closes once released
|
|
120
|
+
* unless the pointer is back on the range or the float.
|
|
121
|
+
* @defaultValue false
|
|
122
|
+
*/
|
|
123
|
+
hold?: boolean;
|
|
107
124
|
/** What happens when the anchor leaves the data area. @defaultValue 'hide' */
|
|
108
125
|
whenOff?: GridWhenOff;
|
|
126
|
+
/** Per-axis policy while the range is partly obstructed. @defaultValue `{ side: 'flip', align: 'slide' }` */
|
|
127
|
+
whenPartial?: GridWhenPartial;
|
|
109
128
|
/** Where the float may live. @defaultValue 'data' */
|
|
110
129
|
boundary?: GridBoundary;
|
|
111
|
-
/** @defaultValue
|
|
112
|
-
zIndex?: number;
|
|
130
|
+
/** The stacking band. @defaultValue `zIndexVar('grid')` */
|
|
131
|
+
zIndex?: number | string;
|
|
132
|
+
/** How the float takes the pointer and the focus. @defaultValue 'pointer' */
|
|
133
|
+
interactive?: RangeFloatInteractive;
|
|
134
|
+
/**
|
|
135
|
+
* A `'focus'` float closed itself — Escape, or a press outside it. A controlled
|
|
136
|
+
* {@link target} should be cleared here.
|
|
137
|
+
*/
|
|
138
|
+
onDismiss?: () => void;
|
|
113
139
|
/** Render the float. **Spread `floatProps`** on the returned element. */
|
|
114
140
|
children: (info: RangeFloatRender<T>) => React.ReactNode;
|
|
115
141
|
}
|
|
116
142
|
/**
|
|
117
|
-
*
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
143
|
+
* Props for {@link VirtualRangeFloat}.
|
|
144
|
+
*/
|
|
145
|
+
export interface VirtualRangeFloatProps<T = unknown> extends RangeFloatOptions<T> {
|
|
146
|
+
/**
|
|
147
|
+
* What the pointer is over, as the HOST layer's own tap found it — `null` for nothing, omit for a
|
|
148
|
+
* float hover does not drive. Report it from the pane the pointer is in; the copies in the other
|
|
149
|
+
* panes need not repeat it (the hover is brokered across them, so the copy that owns the anchor
|
|
150
|
+
* draws).
|
|
151
|
+
*/
|
|
152
|
+
hovered?: RangeFloatTarget<T> | null;
|
|
153
|
+
/**
|
|
154
|
+
* The selection to follow: its active cell, through {@link probe}. An {@link ICellAnchor} rather than
|
|
155
|
+
* a full selection — only the active cell is read and subscribed to.
|
|
156
|
+
*/
|
|
157
|
+
selection?: ICellAnchor;
|
|
158
|
+
/** Ask whether the selection's active cell has something to float. Needed with {@link selection}. */
|
|
159
|
+
probe?: (coords: CellCoords, pane: IGridPane) => RangeFloatTarget<T> | null;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* A **range float** that is not a layer: content anchored to a range that portals out of the pane clip,
|
|
163
|
+
* placed inside a host layer. It owns **anchoring** (a {@link StickyPortal} on the range), the hover
|
|
164
|
+
* **intent** (dwell, grace, keep-open-on-float, `hold`, the tooltip group), the selection follow, and
|
|
165
|
+
* **dismissal**; the host owns its one tap and reports what the pointer is over as {@link
|
|
166
|
+
* VirtualRangeFloatProps.hovered}. So a composite layer (a table's chrome) can float its toolbar
|
|
167
|
+
* without a second layer, and {@link RangeFloatLayer} is this plus a probing tap.
|
|
168
|
+
*
|
|
169
|
+
* ```tsx
|
|
170
|
+
* <Layer onPointerMove={(e) => setHovered(probeAt(e))} onPointerLeave={() => setHovered(null)}>
|
|
171
|
+
* {outlines}
|
|
172
|
+
* <VirtualRangeFloat hovered={hovered} group={false}>
|
|
173
|
+
* {({ data, floatProps }) => <Toolbar {...floatProps} table={data} />}
|
|
174
|
+
* </VirtualRangeFloat>
|
|
175
|
+
* </Layer>
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* When hover and selection both drive it, hover is the transient override and selection the resting
|
|
179
|
+
* state: while the pointer holds a target the float shows that one, and falls back to the selection's
|
|
180
|
+
* when the pointer leaves.
|
|
181
|
+
*/
|
|
182
|
+
export declare const VirtualRangeFloat: <T>(props: VirtualRangeFloatProps<T>) => React.ReactElement | null;
|
|
183
|
+
/**
|
|
184
|
+
* Props for {@link RangeFloatLayer}.
|
|
185
|
+
*/
|
|
186
|
+
export interface RangeFloatLayerProps<T = unknown> extends Omit<LayerProps, 'children' | 'zIndex'>, RangeFloatOptions<T> {
|
|
187
|
+
/** Class for the layer. */
|
|
188
|
+
className?: string;
|
|
189
|
+
/**
|
|
190
|
+
* What makes a float appear. Omit to drive {@link RangeFloatOptions.target} yourself.
|
|
191
|
+
* @defaultValue none (controlled)
|
|
192
|
+
*/
|
|
193
|
+
activateOn?: RangeFloatActivation | readonly RangeFloatActivation[];
|
|
194
|
+
/**
|
|
195
|
+
* Ask whether a cell has something to float — the anchor range + payload, or `null` for nothing.
|
|
196
|
+
* Called with the hovered cell (`'hover'`) and with the selection's active cell (`'selection'`), so
|
|
197
|
+
* one probe serves both. Not needed when {@link RangeFloatOptions.target} is controlled.
|
|
198
|
+
*/
|
|
199
|
+
probe?: (coords: CellCoords, pane: IGridPane) => RangeFloatTarget<T> | null;
|
|
200
|
+
/**
|
|
201
|
+
* The selection to follow for `activateOn: 'selection'`. An {@link ICellAnchor} rather than a full
|
|
202
|
+
* selection — the layer only ever reads the active cell and subscribes to it.
|
|
203
|
+
*/
|
|
204
|
+
selection?: ICellAnchor;
|
|
205
|
+
/**
|
|
206
|
+
* What the pointer is over that the cells cannot tell the tap: something drawn above them, which
|
|
207
|
+
* takes the pointer first. Wins over the probed cell while it is set.
|
|
208
|
+
*/
|
|
209
|
+
hoveredOver?: RangeFloatTarget<T> | null;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* The **range float layer**: a {@link VirtualRangeFloat} as a layer of its own, whose tap probes the
|
|
213
|
+
* hovered cell. It owns the three things every such float needs — **anchoring**, **activation** (what
|
|
214
|
+
* makes it appear) and **dismissal**. What it draws is entirely the consumer's: a tooltip, a button, a
|
|
215
|
+
* toolbar, an action popup.
|
|
121
216
|
*
|
|
122
217
|
* @remarks
|
|
123
218
|
* This is the **float half** of the grid's two mechanisms. A `CellTileDiv` covers everything whose
|
|
@@ -126,7 +221,8 @@ export interface RangeFloatLayerProps<T = unknown> extends Omit<LayerProps, 'chi
|
|
|
126
221
|
* or that must leave the cell box. "Only on the active cell" is the expensive predicate: it would
|
|
127
222
|
* dirty a tile per selection move, which is exactly why it belongs here.
|
|
128
223
|
*
|
|
129
|
-
*
|
|
224
|
+
* A layer that already draws chrome for the same thing (a table's outline and handles) hosts a
|
|
225
|
+
* {@link VirtualRangeFloat} itself instead — layers do not nest.
|
|
130
226
|
*
|
|
131
227
|
* ```tsx
|
|
132
228
|
* <RangeFloatLayer activateOn="hover" probe={probeError}>
|
|
@@ -137,10 +233,6 @@ export interface RangeFloatLayerProps<T = unknown> extends Omit<LayerProps, 'chi
|
|
|
137
233
|
* {({ range, floatProps }) => <Chevron {...floatProps} onPointerDown={() => open(range)} />}
|
|
138
234
|
* </RangeFloatLayer>
|
|
139
235
|
* ```
|
|
140
|
-
*
|
|
141
|
-
* When either can activate it, hover is the transient override and selection is the resting state:
|
|
142
|
-
* while the pointer holds a target the float shows that one, and it falls back to the selection's when
|
|
143
|
-
* the pointer leaves.
|
|
144
236
|
*/
|
|
145
237
|
export declare const RangeFloatLayer: <T>(props: RangeFloatLayerProps<T>) => React.ReactElement;
|
|
146
238
|
//# sourceMappingURL=RangeFloatLayer.d.ts.map
|
|
@@ -23,20 +23,20 @@ export interface RangePromptProps {
|
|
|
23
23
|
onGoto?: (state: StickyState) => void;
|
|
24
24
|
/** Called by the small cancel (×) button. The host unmounts the layer in response. */
|
|
25
25
|
onCancel?: () => void;
|
|
26
|
-
/** @defaultValue
|
|
27
|
-
zIndex?: number;
|
|
26
|
+
/** @defaultValue `zIndexVar('grid')` */
|
|
27
|
+
zIndex?: number | string;
|
|
28
28
|
className?: string;
|
|
29
29
|
style?: React.CSSProperties;
|
|
30
30
|
/** The client prompt content (option buttons, the AI question UI, …). A node or `(state) => node`. */
|
|
31
31
|
children?: React.ReactNode | ((state: StickyState) => React.ReactNode);
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
|
-
* A **persistent prompt pinned to a range** —
|
|
35
|
-
*
|
|
36
|
-
* an AI question about the range) with a small **cancel** (×). When the range
|
|
37
|
-
* clamps to the edge and swaps to a compact **arrow + "Go to range"** pill
|
|
38
|
-
* `state.scrollIntoView()`, or your `onGoto`). Controlled: the host mounts /
|
|
39
|
-
* `onCancel`).
|
|
34
|
+
* A **persistent prompt pinned to a range** — a preset of {@link StickyPortal} (always open, `clamp`ed,
|
|
35
|
+
* with a `renderOffscreen`). While the range is in view it renders the client content (injectable option
|
|
36
|
+
* buttons — e.g. an AI question about the range) on a card with a small **cancel** (×). When the range
|
|
37
|
+
* scrolls **out of view** it clamps to the edge and swaps to a compact **arrow + "Go to range"** pill
|
|
38
|
+
* (which reveals it via `state.scrollIntoView()`, or your `onGoto`). Controlled: the host mounts /
|
|
39
|
+
* unmounts it (cancel calls `onCancel`).
|
|
40
40
|
*/
|
|
41
41
|
export declare const RangePrompt: React.FC<RangePromptProps>;
|
|
42
42
|
//# sourceMappingURL=RangePrompt.d.ts.map
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { CellCoords, RangeCoords } from '@sheetxl/utils';
|
|
3
|
+
import { LayerProps } from './Layer';
|
|
4
|
+
import { StickyState } from './StickyAnchor';
|
|
5
|
+
import { HoverTipProps } from './useHoverIntent';
|
|
6
|
+
import { GridPlacement } from './useGridAnchor';
|
|
7
|
+
/** What a tip's content is rendered from, when {@link RangeTooltipProps.content} is a function. */
|
|
8
|
+
export interface RangeTooltipContentInfo {
|
|
9
|
+
/** The anchored range. */
|
|
10
|
+
range: RangeCoords;
|
|
11
|
+
/** The resolved sticky state (e.g. `state.scrollIntoView()`, `state.placement`). */
|
|
12
|
+
state: StickyState;
|
|
13
|
+
/**
|
|
14
|
+
* Spread onto the content's root to keep the tip open while hovered. Already on the bubble when the
|
|
15
|
+
* tip draws one; only a `bubble: false` tip spreads it itself.
|
|
16
|
+
*/
|
|
17
|
+
tipProps: HoverTipProps;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Props for {@link RangeTooltip}.
|
|
21
|
+
*/
|
|
22
|
+
export interface RangeTooltipProps {
|
|
23
|
+
/** The range the tip hangs on. */
|
|
24
|
+
range: RangeCoords;
|
|
25
|
+
/** The tip: a node, or a function of the anchored range and the float's state. */
|
|
26
|
+
content: React.ReactNode | ((info: RangeTooltipContentInfo) => React.ReactNode);
|
|
27
|
+
/** Which side of the range the tip attaches to. @defaultValue `{ side: 't' }` */
|
|
28
|
+
placement?: GridPlacement;
|
|
29
|
+
/** Gap (px) between the range and the tip. @defaultValue 6 */
|
|
30
|
+
offset?: number;
|
|
31
|
+
/** Offset (px) along the edge (only `start` / `end` align). @defaultValue 0 */
|
|
32
|
+
alignOffset?: number;
|
|
33
|
+
/**
|
|
34
|
+
* The tip stays open while the pointer is on it, so its content can be clicked (a card with
|
|
35
|
+
* buttons). Otherwise it takes no pointer at all. @defaultValue false
|
|
36
|
+
*/
|
|
37
|
+
interactive?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Draw the content in the group's bubble (the host's `renderTooltip`, or the grid's plain one).
|
|
40
|
+
* `false` renders the content bare — the consumer draws its own chrome and spreads `tipProps`.
|
|
41
|
+
* @defaultValue true
|
|
42
|
+
*/
|
|
43
|
+
bubble?: boolean;
|
|
44
|
+
/** Reserved for what the tip is anchored to. A tip on a range takes none. */
|
|
45
|
+
children?: never;
|
|
46
|
+
}
|
|
47
|
+
/** A registered tip. */
|
|
48
|
+
export interface RangeTooltipEntry {
|
|
49
|
+
/** The registration's identity. */
|
|
50
|
+
id: string;
|
|
51
|
+
/** Registration order; the later of two equal ranges wins. */
|
|
52
|
+
order: number;
|
|
53
|
+
props: RangeTooltipProps;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The tips declared under one {@link RangeTooltipProvider}: what {@link RangeTooltip} registers with
|
|
57
|
+
* and {@link RangeTooltipHost} probes.
|
|
58
|
+
*/
|
|
59
|
+
export interface RangeTooltipRegistry {
|
|
60
|
+
/** Registers a tip. The returned function withdraws it. */
|
|
61
|
+
add(id: string, props: RangeTooltipProps): () => void;
|
|
62
|
+
/** Replaces a registered tip's props. */
|
|
63
|
+
set(id: string, props: RangeTooltipProps): void;
|
|
64
|
+
/** The registered tip by id, or `null`. */
|
|
65
|
+
get(id: string): RangeTooltipEntry | null;
|
|
66
|
+
/** How many tips are registered. */
|
|
67
|
+
size(): number;
|
|
68
|
+
/**
|
|
69
|
+
* The tip at a cell: the smallest registered range covering it, and the latest registered among
|
|
70
|
+
* equals. `null` when none covers it.
|
|
71
|
+
*/
|
|
72
|
+
find(coords: CellCoords): RangeTooltipEntry | null;
|
|
73
|
+
/** Called after every change. The returned function unsubscribes. */
|
|
74
|
+
subscribe(listener: () => void): () => void;
|
|
75
|
+
/** A counter that moves on every change — a snapshot for `useSyncExternalStore`. */
|
|
76
|
+
version(): number;
|
|
77
|
+
}
|
|
78
|
+
export declare const createRangeTooltipRegistry: () => RangeTooltipRegistry;
|
|
79
|
+
/** The registry the nearest {@link RangeTooltipProvider} owns, or `null` outside any. */
|
|
80
|
+
export declare const useRangeTooltipRegistry: () => RangeTooltipRegistry | null;
|
|
81
|
+
export interface RangeTooltipProviderProps {
|
|
82
|
+
/**
|
|
83
|
+
* Own a separate registry for this subtree instead of sharing the enclosing one. A provider with no
|
|
84
|
+
* enclosing one always owns a registry.
|
|
85
|
+
*/
|
|
86
|
+
isolate?: boolean;
|
|
87
|
+
children?: React.ReactNode;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Collects the {@link RangeTooltip}s declared under it for the {@link RangeTooltipHost} of the grid
|
|
91
|
+
* inside it. A grid provides one of its own, so a tip among a grid's children needs none; a tip
|
|
92
|
+
* declared elsewhere in the app needs a provider around both it and the grid.
|
|
93
|
+
*/
|
|
94
|
+
export declare const RangeTooltipProvider: React.FC<RangeTooltipProviderProps>;
|
|
95
|
+
/**
|
|
96
|
+
* A **tooltip on a range**, declared where it is wanted: hover any cell of the range and the tip opens
|
|
97
|
+
* beside it, in the tooltip group of the grid (its timing, its one-open rule, its bubble). It draws
|
|
98
|
+
* nothing itself; the grid's {@link RangeTooltipHost} draws every declared tip from one layer.
|
|
99
|
+
*
|
|
100
|
+
* ```tsx
|
|
101
|
+
* <Grid …>
|
|
102
|
+
* <RangeTooltip range={{ rowStart: 3, colStart: 2, rowEnd: 8, colEnd: 5 }} content="Q3 figures" />
|
|
103
|
+
* </Grid>
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* @remarks
|
|
107
|
+
* Reach for {@link RangeTooltipLayer} instead when the tips are derived from data (an error on
|
|
108
|
+
* whichever cells have one) rather than declared one by one. Where two declared ranges overlap, the
|
|
109
|
+
* smaller wins, and the later declared among equals. A tip's identity is its element: content may
|
|
110
|
+
* change without the open tip closing. The anchor is the `range`; `children` is reserved for an
|
|
111
|
+
* anchor that is drawn.
|
|
112
|
+
*/
|
|
113
|
+
export declare const RangeTooltip: (props: RangeTooltipProps) => null;
|
|
114
|
+
export interface RangeTooltipHostProps extends Omit<LayerProps, 'children'> {
|
|
115
|
+
className?: string;
|
|
116
|
+
/**
|
|
117
|
+
* Close the open tip and open no other while this holds, for whatever reason the host's owner has
|
|
118
|
+
* (the cell under the pointer is being edited, say).
|
|
119
|
+
*/
|
|
120
|
+
dismiss?: boolean;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The layer that draws the {@link RangeTooltip}s of the nearest {@link RangeTooltipProvider}: one tap,
|
|
124
|
+
* one probe over the registered ranges, one client of the tooltip group. A grid mounts it at the top of
|
|
125
|
+
* its stack; it draws nothing where no tip is declared.
|
|
126
|
+
*/
|
|
127
|
+
export declare const RangeTooltipHost: React.MemoExoticComponent<(props: RangeTooltipHostProps) => React.JSX.Element>;
|
|
128
|
+
//# sourceMappingURL=RangeTooltip.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { CellCoords, RangeCoords } from '@sheetxl/utils';
|
|
3
|
+
import { IGridPane } from '../surface';
|
|
4
|
+
import { StickyState } from './StickyAnchor';
|
|
5
|
+
import { HoverTipProps } from './useHoverIntent';
|
|
6
|
+
import { RangeFloatTarget, RangeFloatLayerProps } from './RangeFloatLayer';
|
|
7
|
+
/** The context passed to a {@link RangeTooltipLayerProps} render-prop. */
|
|
8
|
+
export interface RangeTooltipRender<T = unknown> {
|
|
9
|
+
/** The anchored range. */
|
|
10
|
+
range: RangeCoords;
|
|
11
|
+
/** The probe payload. */
|
|
12
|
+
data: T;
|
|
13
|
+
/**
|
|
14
|
+
* Spread onto the tip element to keep it open while hovered (`pointer-events:auto` + enter/leave).
|
|
15
|
+
* Already on the bubble when the layer draws one; only a `bubble: false` tip spreads it itself.
|
|
16
|
+
*/
|
|
17
|
+
tipProps: HoverTipProps;
|
|
18
|
+
/** The resolved sticky state (e.g. `state.scrollIntoView()`). */
|
|
19
|
+
state: StickyState;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Props for {@link RangeTooltipLayer}.
|
|
23
|
+
*/
|
|
24
|
+
export interface RangeTooltipLayerProps<T = unknown> extends Omit<RangeFloatLayerProps<T>, 'activateOn' | 'selection' | 'target' | 'probe' | 'children' | 'zIndex' | 'group' | 'hold' | 'interactive' | 'onDismiss'> {
|
|
25
|
+
/** Probe the hovered cell → a {@link RangeFloatTarget} (range + data), or `null` when nothing should show. */
|
|
26
|
+
probe: (coords: CellCoords, pane: IGridPane) => RangeFloatTarget<T> | null;
|
|
27
|
+
/**
|
|
28
|
+
* The tip stays open while the pointer is on it, so its content can be clicked (a card with
|
|
29
|
+
* buttons). Otherwise it takes no pointer at all. @defaultValue false
|
|
30
|
+
*/
|
|
31
|
+
interactive?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Draw the content in the group's bubble (the host's `renderTooltip`, or the grid's plain one).
|
|
34
|
+
* `false` renders the content bare — the consumer draws its own chrome and spreads `tipProps`.
|
|
35
|
+
* @defaultValue true
|
|
36
|
+
*/
|
|
37
|
+
bubble?: boolean;
|
|
38
|
+
/** Render the tip's content. */
|
|
39
|
+
children: (info: RangeTooltipRender<T>) => React.ReactNode;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The **tooltip kind** of range float: transient, opened by hovering a cell the probe recognizes, one
|
|
43
|
+
* at a time grid-wide. A preset of {@link RangeFloatLayer} (`activateOn: 'hover'`) whose hover intent is
|
|
44
|
+
* the tooltip group's client — so it inherits the group's timing, single-open rule, armed re-open, and
|
|
45
|
+
* closes on a press outside it or Escape — drawn in the group's bubble, under any menu.
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* Reach for `RangeFloatLayer` directly when the float is activated by the selection, driven by a
|
|
49
|
+
* gesture, or is something other than a tip. A tip is never focusable: anything that takes the caret
|
|
50
|
+
* is a persistent float.
|
|
51
|
+
*/
|
|
52
|
+
export declare const RangeTooltipLayer: <T>(props: RangeTooltipLayerProps<T>) => React.ReactElement;
|
|
53
|
+
//# sourceMappingURL=RangeTooltipLayer.d.ts.map
|