@sheetxl/grid-react 0.7.21 → 0.7.23-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/README.md +502 -2
- package/browser/cjs/index.cjs +3 -12
- package/browser/esm/index.mjs +5797 -1867
- package/licenses/dependencies.txt +143 -41
- package/node/esm/index.mjs +4951 -1861
- package/package.json +7 -6
- package/types/index.d.ts +2 -1497
- package/types/src/cell/CellLayer.d.ts +70 -0
- package/types/src/cell/CellLayer.d.ts.map +1 -0
- package/types/src/cell/CellRenderer.d.ts +42 -0
- package/types/src/cell/CellRenderer.d.ts.map +1 -0
- package/types/src/cell/DefaultCellRenderer.d.ts +6 -0
- package/types/src/cell/DefaultCellRenderer.d.ts.map +1 -0
- package/types/src/cell/GridlineLayer.d.ts +38 -0
- package/types/src/cell/GridlineLayer.d.ts.map +1 -0
- package/types/src/cell/Types.d.ts +12 -0
- package/types/src/cell/Types.d.ts.map +1 -0
- package/types/src/cell/_CellModel.d.ts +82 -0
- package/types/src/cell/_CellModel.d.ts.map +1 -0
- package/types/src/cell/index.d.ts +6 -0
- package/types/src/cell/index.d.ts.map +1 -0
- package/types/src/editor/DefaultEditable.d.ts +121 -0
- package/types/src/editor/DefaultEditable.d.ts.map +1 -0
- package/types/src/editor/EditSession.d.ts +182 -0
- package/types/src/editor/EditSession.d.ts.map +1 -0
- package/types/src/editor/EditState.d.ts +61 -0
- package/types/src/editor/EditState.d.ts.map +1 -0
- package/types/src/editor/EditorDiv.d.ts +65 -0
- package/types/src/editor/EditorDiv.d.ts.map +1 -0
- package/types/src/editor/EditorInput.d.ts +88 -0
- package/types/src/editor/EditorInput.d.ts.map +1 -0
- package/types/src/editor/EditorLayer.d.ts +69 -0
- package/types/src/editor/EditorLayer.d.ts.map +1 -0
- package/types/src/editor/EditorPlacement.d.ts +38 -0
- package/types/src/editor/EditorPlacement.d.ts.map +1 -0
- package/types/src/editor/index.d.ts +10 -0
- package/types/src/editor/index.d.ts.map +1 -0
- package/types/src/editor/useEditorKeymap.d.ts +74 -0
- package/types/src/editor/useEditorKeymap.d.ts.map +1 -0
- package/types/src/grid/Grid.d.ts +16 -0
- package/types/src/grid/Grid.d.ts.map +1 -0
- package/types/src/grid/IGrid.d.ts +93 -0
- package/types/src/grid/IGrid.d.ts.map +1 -0
- package/types/src/grid/index.d.ts +3 -0
- package/types/src/grid/index.d.ts.map +1 -0
- package/types/src/header/HeaderDividerAnchor.d.ts +120 -0
- package/types/src/header/HeaderDividerAnchor.d.ts.map +1 -0
- package/types/src/header/index.d.ts +3 -0
- package/types/src/header/index.d.ts.map +1 -0
- package/types/src/header/useHeaderSelectionPointer.d.ts +122 -0
- package/types/src/header/useHeaderSelectionPointer.d.ts.map +1 -0
- package/types/src/index.d.ts +13 -0
- package/types/src/index.d.ts.map +1 -0
- package/types/src/layer/HoverTipLayer.d.ts +74 -0
- package/types/src/layer/HoverTipLayer.d.ts.map +1 -0
- package/types/src/layer/Layer.d.ts +92 -0
- package/types/src/layer/Layer.d.ts.map +1 -0
- package/types/src/layer/LayerTypes.d.ts +47 -0
- package/types/src/layer/LayerTypes.d.ts.map +1 -0
- package/types/src/layer/RangePrompt.d.ts +42 -0
- package/types/src/layer/RangePrompt.d.ts.map +1 -0
- package/types/src/layer/Stage.d.ts +147 -0
- package/types/src/layer/Stage.d.ts.map +1 -0
- package/types/src/layer/StickyAnchor.d.ts +83 -0
- package/types/src/layer/StickyAnchor.d.ts.map +1 -0
- package/types/src/layer/StickyFloat.d.ts +65 -0
- package/types/src/layer/StickyFloat.d.ts.map +1 -0
- package/types/src/layer/VirtualDiv.d.ts +59 -0
- package/types/src/layer/VirtualDiv.d.ts.map +1 -0
- package/types/src/layer/_Utils.d.ts +37 -0
- package/types/src/layer/_Utils.d.ts.map +1 -0
- package/types/src/layer/index.d.ts +11 -0
- package/types/src/layer/index.d.ts.map +1 -0
- package/types/src/layer/useGridAnchor.d.ts +157 -0
- package/types/src/layer/useGridAnchor.d.ts.map +1 -0
- package/types/src/layer/useHoverIntent.d.ts +49 -0
- package/types/src/layer/useHoverIntent.d.ts.map +1 -0
- package/types/src/layer/useLayerResponder.d.ts +29 -0
- package/types/src/layer/useLayerResponder.d.ts.map +1 -0
- package/types/src/layer/usePlacement.d.ts +18 -0
- package/types/src/layer/usePlacement.d.ts.map +1 -0
- package/types/src/layer/useRangeHover.d.ts +35 -0
- package/types/src/layer/useRangeHover.d.ts.map +1 -0
- package/types/src/list/CheckboxList.d.ts +63 -0
- package/types/src/list/CheckboxList.d.ts.map +1 -0
- package/types/src/list/List.d.ts +55 -0
- package/types/src/list/List.d.ts.map +1 -0
- package/types/src/list/index.d.ts +3 -0
- package/types/src/list/index.d.ts.map +1 -0
- package/types/src/metrics/Types.d.ts +23 -0
- package/types/src/metrics/Types.d.ts.map +1 -0
- package/types/src/metrics/index.d.ts +3 -0
- package/types/src/metrics/index.d.ts.map +1 -0
- package/types/src/metrics/useGridMetrics.d.ts +67 -0
- package/types/src/metrics/useGridMetrics.d.ts.map +1 -0
- package/types/src/range/DragHandle.d.ts +129 -0
- package/types/src/range/DragHandle.d.ts.map +1 -0
- package/types/src/range/Draggable.d.ts +86 -0
- package/types/src/range/Draggable.d.ts.map +1 -0
- package/types/src/range/FillHandle.d.ts +54 -0
- package/types/src/range/FillHandle.d.ts.map +1 -0
- package/types/src/range/RangeRect.d.ts +36 -0
- package/types/src/range/RangeRect.d.ts.map +1 -0
- package/types/src/range/RangeResizer.d.ts +68 -0
- package/types/src/range/RangeResizer.d.ts.map +1 -0
- package/types/src/range/RangeStyle.d.ts +8 -0
- package/types/src/range/RangeStyle.d.ts.map +1 -0
- package/types/src/range/index.d.ts +13 -0
- package/types/src/range/index.d.ts.map +1 -0
- package/types/src/selection/DefaultSelection.d.ts +59 -0
- package/types/src/selection/DefaultSelection.d.ts.map +1 -0
- package/types/src/selection/ICellAnchor.d.ts +21 -0
- package/types/src/selection/ICellAnchor.d.ts.map +1 -0
- package/types/src/selection/ISelection.d.ts +65 -0
- package/types/src/selection/ISelection.d.ts.map +1 -0
- package/types/src/selection/RangesPickerLayer.d.ts +128 -0
- package/types/src/selection/RangesPickerLayer.d.ts.map +1 -0
- package/types/src/selection/SelectionLayer.d.ts +179 -0
- package/types/src/selection/SelectionLayer.d.ts.map +1 -0
- package/types/src/selection/SelectionStyle.d.ts +28 -0
- package/types/src/selection/SelectionStyle.d.ts.map +1 -0
- package/types/src/selection/SelectionTouchGrips.d.ts +29 -0
- package/types/src/selection/SelectionTouchGrips.d.ts.map +1 -0
- package/types/src/selection/SelectionUtils.d.ts +2 -0
- package/types/src/selection/SelectionUtils.d.ts.map +1 -0
- package/types/src/selection/Types.d.ts +67 -0
- package/types/src/selection/Types.d.ts.map +1 -0
- package/types/src/selection/_SelectionNavigation.d.ts +6 -0
- package/types/src/selection/_SelectionNavigation.d.ts.map +1 -0
- package/types/src/selection/_SelectionUtils.d.ts +7 -0
- package/types/src/selection/_SelectionUtils.d.ts.map +1 -0
- package/types/src/selection/index.d.ts +12 -0
- package/types/src/selection/index.d.ts.map +1 -0
- package/types/src/selection/useDragCells.d.ts +218 -0
- package/types/src/selection/useDragCells.d.ts.map +1 -0
- package/types/src/selection/useSelectionPointer.d.ts +70 -0
- package/types/src/selection/useSelectionPointer.d.ts.map +1 -0
- package/types/src/surface/GridPane.d.ts +85 -0
- package/types/src/surface/GridPane.d.ts.map +1 -0
- package/types/src/surface/GridPaneProvider.d.ts +37 -0
- package/types/src/surface/GridPaneProvider.d.ts.map +1 -0
- package/types/src/surface/GridSurface.d.ts +11 -0
- package/types/src/surface/GridSurface.d.ts.map +1 -0
- package/types/src/surface/IGridPane.d.ts +288 -0
- package/types/src/surface/IGridPane.d.ts.map +1 -0
- package/types/src/surface/IGridSurface.d.ts +141 -0
- package/types/src/surface/IGridSurface.d.ts.map +1 -0
- package/types/src/surface/SurfaceStateProvider.d.ts +50 -0
- package/types/src/surface/SurfaceStateProvider.d.ts.map +1 -0
- package/types/src/surface/_GridUtils.d.ts +37 -0
- package/types/src/surface/_GridUtils.d.ts.map +1 -0
- package/types/src/surface/index.d.ts +7 -0
- package/types/src/surface/index.d.ts.map +1 -0
- package/types/src/surface/useGridPane.d.ts +31 -0
- package/types/src/surface/useGridPane.d.ts.map +1 -0
- package/types/src/surface/useSurfaceState.d.ts +22 -0
- package/types/src/surface/useSurfaceState.d.ts.map +1 -0
- package/types/src/svg/LineSVG.d.ts +13 -0
- package/types/src/svg/LineSVG.d.ts.map +1 -0
- package/types/src/svg/RectangleSVG.d.ts +114 -0
- package/types/src/svg/RectangleSVG.d.ts.map +1 -0
- package/types/src/svg/ShapeBounds.d.ts +15 -0
- package/types/src/svg/ShapeBounds.d.ts.map +1 -0
- package/types/src/svg/Types.d.ts +37 -0
- package/types/src/svg/Types.d.ts.map +1 -0
- package/types/src/svg/index.d.ts +9 -0
- package/types/src/svg/index.d.ts.map +1 -0
- package/types/src/theme/GridTheme.d.ts +56 -0
- package/types/src/theme/GridTheme.d.ts.map +1 -0
- package/types/src/theme/index.d.ts +2 -0
- package/types/src/theme/index.d.ts.map +1 -0
- package/node/assets/style.css +0 -1
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { CellCoords, RangeCoords } from '@sheetxl/utils';
|
|
3
|
+
import { LayerProps, GridPlacement } from '../layer';
|
|
4
|
+
import { VisualSVGProps } from '../svg';
|
|
5
|
+
import { ISelection } from './ISelection';
|
|
6
|
+
import { SelectionNavigation } from './Types';
|
|
7
|
+
import { SelectionRangeStyle } from './SelectionStyle';
|
|
8
|
+
/**
|
|
9
|
+
* The in-flight selection gesture passed to {@link SelectionLayerProps.renderTip}:
|
|
10
|
+
* - `select` — a drag-select growing the active range (Excel's live R×C);
|
|
11
|
+
* - `move` — the built-in move grip (border drag); `to` is the in-flight destination;
|
|
12
|
+
* - `fill` — the fill handle; `destination` is the in-flight fill range.
|
|
13
|
+
*/
|
|
14
|
+
export type SelectionGesture = {
|
|
15
|
+
kind: 'select';
|
|
16
|
+
range: RangeCoords;
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'move';
|
|
19
|
+
from: RangeCoords;
|
|
20
|
+
to: RangeCoords;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'fill';
|
|
23
|
+
template: RangeCoords;
|
|
24
|
+
destination: RangeCoords;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Props for {@link SelectionLayer}.
|
|
28
|
+
*/
|
|
29
|
+
export interface SelectionLayerProps extends LayerProps {
|
|
30
|
+
/**
|
|
31
|
+
* The writable selection model this layer owns.
|
|
32
|
+
*/
|
|
33
|
+
selection: ISelection;
|
|
34
|
+
/**
|
|
35
|
+
* The content (used-range) bounds the `…End` keys (End / Ctrl+End) jump to. Supply it from a tier that
|
|
36
|
+
* knows the used range (the sheet layer) so those keys land on the last cell *with content*; omit it
|
|
37
|
+
* and they fall back to the grid edge (correct for the dumb {@link DefaultSelection} tier, which has no
|
|
38
|
+
* used range). It stays a plain bounds getter here — the layer never learns it's a sheet.
|
|
39
|
+
*/
|
|
40
|
+
getContentBounds?: () => RangeCoords;
|
|
41
|
+
/**
|
|
42
|
+
* The bounding REGION enclosing a cell — a table's data range from a tier that knows tables (the sheet
|
|
43
|
+
* layer), else `null` (the bare sheet). Drives Tab/Enter wrapping inside a table and the row/column
|
|
44
|
+
* span of Ctrl/Shift+Space. Omit it (the dumb {@link DefaultSelection} tier) and there is no enclosing
|
|
45
|
+
* region: Tab is a plain move and Ctrl/Shift+Space select the whole grid. The layer never learns it's a
|
|
46
|
+
* sheet — just a `cell → bounds | null` getter; any escalation lives in the provider.
|
|
47
|
+
*/
|
|
48
|
+
getRegionBounds?: (cell: CellCoords) => RangeCoords | null;
|
|
49
|
+
/**
|
|
50
|
+
* The scroll executor for keyboard selection. Supply it from a tier that OWNS scrolling — e.g. the
|
|
51
|
+
* sheet layer, which routes to `sheet.scrollTo` so the UI and scripting scroll through one path. When
|
|
52
|
+
* supplied, the layer delegates every keyboard scroll here and lets the model own the arrow-`navigate`
|
|
53
|
+
* scroll (it already scrolls to the moved edge) so the two don't compete. When omitted, the layer
|
|
54
|
+
* scrolls its own pane (correct for a standalone grid, whose {@link DefaultSelection} has no sheet).
|
|
55
|
+
*/
|
|
56
|
+
scrollIntoView?: (cell: Partial<CellCoords>) => void;
|
|
57
|
+
/** The single-range look. Merged (slot-by-slot) over {@link DEFAULT_SINGLE_STYLE}. */
|
|
58
|
+
singleStyle?: SelectionRangeStyle;
|
|
59
|
+
/** The multi-range look. Merged (slot-by-slot) over {@link DEFAULT_MULTI_STYLE}. */
|
|
60
|
+
multiStyle?: SelectionRangeStyle;
|
|
61
|
+
/** The active-cell border within a **multi**-range selection. Merged over {@link DEFAULT_ANCHOR_STYLE}. */
|
|
62
|
+
multiAnchorStyle?: VisualSVGProps;
|
|
63
|
+
/**
|
|
64
|
+
* A border drawn on the active cell within a **single**-range selection. Off by default (Excel draws
|
|
65
|
+
* none — the selection rectangle is the only outline). Set it to mark the anchor when the fill covers
|
|
66
|
+
* the whole row (see {@link SelectionLayerProps.anchorHole}) — e.g. a list's focus ring. An `inset`
|
|
67
|
+
* border stays within the row, so it never clips at the viewport edge.
|
|
68
|
+
*/
|
|
69
|
+
singleAnchorStyle?: VisualSVGProps;
|
|
70
|
+
/** The Ctrl/Cmd-drag remove rubber-band. Merged (slot-by-slot) over {@link DEFAULT_REMOVE_PREVIEW_STYLE}. */
|
|
71
|
+
removePreviewStyle?: SelectionRangeStyle;
|
|
72
|
+
/**
|
|
73
|
+
* Stacked layers (fill, move, …) rendered when a single range is selected.
|
|
74
|
+
*/
|
|
75
|
+
singleLayer?: React.ReactNode;
|
|
76
|
+
/**
|
|
77
|
+
* Stacked layers rendered when multiple ranges are selected.
|
|
78
|
+
*/
|
|
79
|
+
multiLayer?: React.ReactNode;
|
|
80
|
+
/**
|
|
81
|
+
* Disable the built-in move grip on a single range (drag the border to move it, Excel-style).
|
|
82
|
+
*
|
|
83
|
+
* @defaultValue false
|
|
84
|
+
*/
|
|
85
|
+
enabledMove?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Called when the single range is moved by its border — `from` is the original range, `to` the new
|
|
88
|
+
* one. The selection follows automatically; use this for the data side-effect (cut-move).
|
|
89
|
+
*/
|
|
90
|
+
onMove?: (from: RangeCoords, to: RangeCoords, e: React.PointerEvent) => void;
|
|
91
|
+
/** The move drag started (before any translation) — `from` is the range being moved. */
|
|
92
|
+
onMoveStart?: (from: RangeCoords, e: React.PointerEvent) => void;
|
|
93
|
+
/**
|
|
94
|
+
* Live during the move drag — `to` is the in-flight translated range. `e` carries the current
|
|
95
|
+
* modifiers (Ctrl = copy, Shift = insert), so a consumer can reflect the mode (cursor/description).
|
|
96
|
+
*/
|
|
97
|
+
onMoveUpdate?: (from: RangeCoords, to: RangeCoords, e: React.PointerEvent) => void;
|
|
98
|
+
/**
|
|
99
|
+
* The move drag ended (fires on release regardless of whether the range actually moved) — for teardown
|
|
100
|
+
* of anything {@link SelectionLayerProps.onMoveStart}/`onMoveUpdate` set (e.g. clearing a drag mode).
|
|
101
|
+
*/
|
|
102
|
+
onMoveEnd?: () => void;
|
|
103
|
+
/**
|
|
104
|
+
* Enable the built-in fill handle on a single range (the Excel fill square at the bottom-right
|
|
105
|
+
* corner; drag to fill). Opt-in (unlike the always-on move grip) because it adds a visible handle.
|
|
106
|
+
*
|
|
107
|
+
* @defaultValue false
|
|
108
|
+
*/
|
|
109
|
+
enableFill?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Called when the single range is filled via the handle — `template` is the source range, `destination`
|
|
112
|
+
* the filled range (which includes the template). The selection extends to `destination` automatically;
|
|
113
|
+
* use this for the data side-effect (the actual fill).
|
|
114
|
+
*/
|
|
115
|
+
onFill?: (template: RangeCoords, destination: RangeCoords, e: React.PointerEvent) => void;
|
|
116
|
+
/**
|
|
117
|
+
* Adjust the raw fill destination before it drives the preview + fill callbacks — e.g. snap the fill
|
|
118
|
+
* edge to a merged-cell boundary so the dashed preview and the committed fill agree and never land on
|
|
119
|
+
* an illegal interval. Given the template and the pointer-derived destination, return the destination
|
|
120
|
+
* to use. Omit for no snapping.
|
|
121
|
+
*/
|
|
122
|
+
snapFillDestination?: (template: RangeCoords, destination: RangeCoords) => RangeCoords;
|
|
123
|
+
/** The fill drag started — `template` is the source range. */
|
|
124
|
+
onFillStart?: (template: RangeCoords, e: React.PointerEvent) => void;
|
|
125
|
+
/**
|
|
126
|
+
* Live during the fill drag — `destination` is the in-flight fill range (incl. the template). Use it
|
|
127
|
+
* to preview what will be filled (e.g. a value tooltip). The fill axis is `template` vs `destination`.
|
|
128
|
+
*/
|
|
129
|
+
onFillPreview?: (template: RangeCoords, destination: RangeCoords, e: React.PointerEvent) => void;
|
|
130
|
+
/**
|
|
131
|
+
* The fill drag ended (fires on release regardless of whether a fill was drawn) — for teardown of
|
|
132
|
+
* anything {@link SelectionLayerProps.onFillPreview} set (e.g. closing the preview tooltip).
|
|
133
|
+
*/
|
|
134
|
+
onFillEnd?: () => void;
|
|
135
|
+
/**
|
|
136
|
+
* Fired when a selection pointer interaction ends (click/drag settled) — "act on the just-selected
|
|
137
|
+
* range" (e.g. the format painter applies the copied format to the new selection). See
|
|
138
|
+
* {@link SelectionPointerOptions.onSelectionEnd}.
|
|
139
|
+
*/
|
|
140
|
+
onSelectionEnd?: (e: React.PointerEvent) => void;
|
|
141
|
+
/**
|
|
142
|
+
* Render a transient tip during a gesture — a drag-select ({@link SelectionGesture} `select`, live
|
|
143
|
+
* R×C), a move (`move`, the destination address), or a fill (`fill`, the preview). Return a falsy node
|
|
144
|
+
* for no tip (e.g. skip a 1×1 drag-select). The tip floats on the in-flight range (non-interactive).
|
|
145
|
+
*/
|
|
146
|
+
renderTip?: (gesture: SelectionGesture) => React.ReactNode;
|
|
147
|
+
/** Placement of the gesture tip relative to the in-flight range. @defaultValue `{ side: 'b', align: 'end' }` */
|
|
148
|
+
tipPlacement?: GridPlacement;
|
|
149
|
+
/**
|
|
150
|
+
* Disable the layer's **built-in keyboard** routing (arrows → {@link ISelection.navigate}, Tab/Enter
|
|
151
|
+
* → {@link ISelection.traverse}) so an external command system owns the keyboard instead — without it,
|
|
152
|
+
* both would fire the same navigation. Pointer routing is unaffected.
|
|
153
|
+
*
|
|
154
|
+
* @defaultValue false
|
|
155
|
+
*/
|
|
156
|
+
disableKeyboard?: boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Cut the active (anchor) cell out of the fill — the Excel "current cell" cutout. For a selection that
|
|
159
|
+
* is just the 1×1 active cell the cutout covers the *entire* range, so the fill vanishes; set `false`
|
|
160
|
+
* to fill the whole selected row (then mark the anchor with {@link SelectionLayerProps.singleAnchorStyle},
|
|
161
|
+
* since the anchor is still the live Space/scroll target).
|
|
162
|
+
*
|
|
163
|
+
* @defaultValue true
|
|
164
|
+
*/
|
|
165
|
+
anchorHole?: boolean;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* The selection layer: renders the selection (single-range "rich" treatment vs multi-range), routes
|
|
169
|
+
* pointer + keyboard to the model, owns the {@link SelectionRangeStyle} theme, and mounts the
|
|
170
|
+
* single/multi handle slots bound to the active range. The only piece that knows about
|
|
171
|
+
* {@link ISelection}; the handle layers stay dumb, controlled RangeHandles.
|
|
172
|
+
*
|
|
173
|
+
* @remarks
|
|
174
|
+
* Slot children are cloned with `range` = the active range injected and their `onDragEnd` wrapped so
|
|
175
|
+
* the committed range updates the selection (the child's own `onDragEnd`, e.g. a data fill, still
|
|
176
|
+
* runs after). Handles inherit the active style via {@link SelectionStyleContext}.
|
|
177
|
+
*/
|
|
178
|
+
export declare const SelectionLayer: React.ForwardRefExoticComponent<SelectionLayerProps & React.RefAttributes<SelectionNavigation>>;
|
|
179
|
+
//# sourceMappingURL=SelectionLayer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectionLayer.d.ts","sourceRoot":"","sources":["../../../../src/selection/SelectionLayer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { VisualSVGProps } from '../svg';
|
|
2
|
+
/**
|
|
3
|
+
* The style of one selection range: a stack of up to three rectangles — a `fill`, a `border` outline,
|
|
4
|
+
* and an optional `inner` accent ring (the white inner edge of the Excel-style two-tone border). Each
|
|
5
|
+
* slot is a {@link VisualSVGProps} (a single rectangle's visual override; geometry/hole are supplied by
|
|
6
|
+
* the layer); a `null` or omitted slot draws no rectangle. Per-mode overrides merge slot-by-slot over
|
|
7
|
+
* the `DEFAULT_*_STYLE`.
|
|
8
|
+
*/
|
|
9
|
+
export interface SelectionRangeStyle {
|
|
10
|
+
/** The interior fill (the active cell is cut out via the layer-supplied `hole`). */
|
|
11
|
+
fill?: VisualSVGProps | null;
|
|
12
|
+
/** The main outline. */
|
|
13
|
+
border?: VisualSVGProps | null;
|
|
14
|
+
/** The inner accent ring, inset inside the border. Omit for a single-tone outline. */
|
|
15
|
+
inner?: VisualSVGProps | null;
|
|
16
|
+
}
|
|
17
|
+
/** The rich single-range style: tinted fill, thick outline, inner ring (the two-tone border). */
|
|
18
|
+
export declare const DEFAULT_SINGLE_STYLE: SelectionRangeStyle;
|
|
19
|
+
/** The quieter multi-range style: lighter fill, thin outline, thin inner ring. */
|
|
20
|
+
export declare const DEFAULT_MULTI_STYLE: SelectionRangeStyle;
|
|
21
|
+
/**
|
|
22
|
+
* The active-cell border drawn over a multi-range selection (the anchor cell within the rich range).
|
|
23
|
+
* Inset so it sits just inside the cell, leaving a gap to the range's outer border.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEFAULT_ANCHOR_STYLE: VisualSVGProps;
|
|
26
|
+
/** The transient rubber-band shown while Ctrl/Cmd-dragging to remove an area (fill + border stack). */
|
|
27
|
+
export declare const DEFAULT_REMOVE_PREVIEW_STYLE: SelectionRangeStyle;
|
|
28
|
+
//# sourceMappingURL=SelectionStyle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectionStyle.d.ts","sourceRoot":"","sources":["../../../../src/selection/SelectionStyle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,oFAAoF;IACpF,IAAI,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,wBAAwB;IACxB,MAAM,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,sFAAsF;IACtF,KAAK,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CAC/B;AAqBD,iGAAiG;AACjG,eAAO,MAAM,oBAAoB,EAAE,mBAIlC,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,mBAAmB,EAAE,mBAIjC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,cAIlC,CAAC;AAEF,uGAAuG;AACvG,eAAO,MAAM,4BAA4B,EAAE,mBAG1C,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { ISelection } from './ISelection';
|
|
3
|
+
/**
|
|
4
|
+
* Props for {@link SelectionTouchGrips}.
|
|
5
|
+
*/
|
|
6
|
+
export interface SelectionTouchGripsProps {
|
|
7
|
+
/** The selection the touch handles read (for placement) and extend (via `modify`). */
|
|
8
|
+
selection: ISelection;
|
|
9
|
+
/** The ring color (the fill is the surface/"window" color). @defaultValue the theme primary. */
|
|
10
|
+
color?: string;
|
|
11
|
+
/** Handle diameter (px). Touch-sized. @defaultValue 22 */
|
|
12
|
+
size?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Touch selection handles: round grips at the active range's corners (or edges, for a whole row/column)
|
|
16
|
+
* that drag to **extend the selection** via {@link ISelection.modify}, reusing the exact range math the
|
|
17
|
+
* mouse path uses. See {@link computeGrips} for the per-selection grip layout.
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* Each grip is a {@link StickyAnchor} rendered through a **portal** (via the fullscreen-aware root) so it
|
|
21
|
+
* escapes the pane clip. StickyAnchor's owner/clip gating means exactly ONE pane renders each grip, and
|
|
22
|
+
* anchoring to a cell makes the grip vanish the moment that cell scrolls off — no slide-to-edge.
|
|
23
|
+
*
|
|
24
|
+
* The drag runs on **window** pointer listeners owned by this (always-mounted) component — not
|
|
25
|
+
* pointer-capture on the grip element — so the gesture survives the grip hiding mid-drag (the grips fade
|
|
26
|
+
* to `opacity: 0` while dragging so the finger isn't dragging a dot it can't see past).
|
|
27
|
+
*/
|
|
28
|
+
export declare const SelectionTouchGrips: React.FC<SelectionTouchGripsProps>;
|
|
29
|
+
//# sourceMappingURL=SelectionTouchGrips.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectionTouchGrips.d.ts","sourceRoot":"","sources":["../../../../src/selection/SelectionTouchGrips.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAK/C;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,sFAAsF;IACtF,SAAS,EAAE,UAAU,CAAC;IACtB,gGAAgG;IAChG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA+DD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAiElE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectionUtils.d.ts","sourceRoot":"","sources":["../../../../src/selection/SelectionUtils.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,qBAAqB,MAAM,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { CellCoords, RangeCoords } from '@sheetxl/utils';
|
|
2
|
+
import { IKeyStroke } from '@sheetxl/utils-react';
|
|
3
|
+
import { IGridPane } from '../surface';
|
|
4
|
+
import { ISelection } from './ISelection';
|
|
5
|
+
/**
|
|
6
|
+
* One navigation binding: its **default** keystroke(s) + the method to run. The single source for a
|
|
7
|
+
* selection navigation capability — keystroke handling (the layer's `onKeyDown`), the imperative
|
|
8
|
+
* handle (`invoke`), and the command catalog (which derives its shortcut + adds chrome) all read it.
|
|
9
|
+
*/
|
|
10
|
+
export interface NavBinding {
|
|
11
|
+
/**
|
|
12
|
+
* The default keystroke(s). The command catalog seeds its (re-mappable) shortcut from this. Omitted
|
|
13
|
+
* for a command-only binding (invokable by name, no default chord) — every chord maps to exactly ONE
|
|
14
|
+
* binding, so a method whose natural chord is already taken ships without one.
|
|
15
|
+
*/
|
|
16
|
+
shortcut?: IKeyStroke | IKeyStroke[];
|
|
17
|
+
/** The behavior — a composition of {@link ISelection} (model) + {@link IGridPane} (view). */
|
|
18
|
+
run: () => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The selection navigation capability owned by `SelectionLayer`.
|
|
22
|
+
*/
|
|
23
|
+
export interface SelectionNavigation {
|
|
24
|
+
/** Run a binding by name (the command front-end). Returns `false` if the name is unknown. */
|
|
25
|
+
invoke(name: string): boolean;
|
|
26
|
+
/** Match a keyboard event to a binding and run it (the layer's keyboard front-end). */
|
|
27
|
+
handleKey(event: React.KeyboardEvent): boolean;
|
|
28
|
+
/** Whether a binding name exists. */
|
|
29
|
+
supports(name: string): boolean;
|
|
30
|
+
/** The full binding map — `name → { shortcut, run }` (the command catalog seeds shortcuts from it). */
|
|
31
|
+
getBindings(): ReadonlyMap<string, NavBinding>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Options for {@link createSelectionNavigation} — the live getters a navigation capability is built
|
|
35
|
+
* over. `getSelection` / `getPane` are read on *every* action so the capability stays valid across
|
|
36
|
+
* re-renders and scroll (never captured once). The bounds getters inject sheet-tier knowledge; the
|
|
37
|
+
* dumb {@link DefaultSelection} tier omits them and everything falls back to the grid edge.
|
|
38
|
+
*/
|
|
39
|
+
export interface SelectionNavigationOptions {
|
|
40
|
+
/** The writable selection model, read live. */
|
|
41
|
+
getSelection: () => ISelection;
|
|
42
|
+
/** The grid view (metrics + scroll), read live so bindings stay correct across scroll. */
|
|
43
|
+
getPane: () => IGridPane;
|
|
44
|
+
/**
|
|
45
|
+
* The content (used-range) bounds the `…End` keys (End / Ctrl+End) jump to. A **sheet-global**
|
|
46
|
+
* property — the used range — so it is deliberately **cell-independent**: Ctrl+End lands on the same
|
|
47
|
+
* used-range corner wherever the cursor sits. (Contrast {@link getRegionBounds}, a *positional*
|
|
48
|
+
* query — that difference is why one takes a `cell` and this one does not; it is not an oversight.)
|
|
49
|
+
* Omit it (the dumb tier, which has no sheet ⇒ no used range) ⇒ the grid edge.
|
|
50
|
+
*/
|
|
51
|
+
getContentBounds?: () => RangeCoords;
|
|
52
|
+
/**
|
|
53
|
+
* The scroll executor for keyboard selection. Supply it from a tier that OWNS scrolling (the sheet
|
|
54
|
+
* layer → `sheet.scrollTo`) so UI and scripting scroll through one path; the model then owns the
|
|
55
|
+
* arrow-`navigate` scroll and the two don't compete. Omit it and the layer scrolls its own pane.
|
|
56
|
+
*/
|
|
57
|
+
getScrollIntoView?: () => ((cell: Partial<CellCoords>) => void) | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* The bounding REGION enclosing a cell — a table's data range, or `null` on the bare sheet. A
|
|
60
|
+
* **positional** query (hence the `cell`, unlike the sheet-global {@link getContentBounds}): drives
|
|
61
|
+
* Tab/Enter wrapping inside a table and the row/column span of Ctrl/Shift+Space. Omit it (the dumb
|
|
62
|
+
* tier) ⇒ no enclosing region (Tab moves, Ctrl/Shift+Space select the whole grid). Any escalation
|
|
63
|
+
* (data → table → sheet) is the provider's job, not the consumer's.
|
|
64
|
+
*/
|
|
65
|
+
getRegionBounds?: (cell: CellCoords) => RangeCoords | null;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=Types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Types.d.ts","sourceRoot":"","sources":["../../../../src/selection/Types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,UAAU,GAAG,UAAU,EAAE,CAAC;IACrC,6FAA6F;IAC7F,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,6FAA6F;IAC7F,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,uFAAuF;IACvF,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,aAAa,GAAG,OAAO,CAAC;IAC/C,qCAAqC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,uGAAuG;IACvG,WAAW,IAAI,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CAChD;AAED;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IACzC,+CAA+C;IAC/C,YAAY,EAAE,MAAM,UAAU,CAAC;IAC/B,0FAA0F;IAC1F,OAAO,EAAE,MAAM,SAAS,CAAC;IACzB;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,WAAW,CAAC;IACrC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC5E;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,WAAW,GAAG,IAAI,CAAC;CAC5D"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SelectionNavigation, SelectionNavigationOptions } from './Types';
|
|
2
|
+
/**
|
|
3
|
+
* Build the navigation capability over the live getters in {@link SelectionNavigationOptions}.
|
|
4
|
+
*/
|
|
5
|
+
export declare function createSelectionNavigation(options: SelectionNavigationOptions): SelectionNavigation;
|
|
6
|
+
//# sourceMappingURL=_SelectionNavigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_SelectionNavigation.d.ts","sourceRoot":"","sources":["../../../../src/selection/_SelectionNavigation.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,0BAA0B,EAAmB,MAAM,SAAS,CAAC;AAerG;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,0BAA0B,GAAG,mBAAmB,CAgQlG"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SelectionRangeStyle } from './SelectionStyle';
|
|
2
|
+
/**
|
|
3
|
+
* Merge a {@link SelectionRangeStyle} override over a base, slot-by-slot (each rectangle merges
|
|
4
|
+
* independently).
|
|
5
|
+
*/
|
|
6
|
+
export declare const mergeSelectionStyle: (base: SelectionRangeStyle, over?: SelectionRangeStyle) => SelectionRangeStyle;
|
|
7
|
+
//# sourceMappingURL=_SelectionUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_SelectionUtils.d.ts","sourceRoot":"","sources":["../../../../src/selection/_SelectionUtils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAe3D;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC9B,MAAM,mBAAmB,EACzB,OAAO,mBAAmB,KACzB,mBAOF,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './Types';
|
|
2
|
+
export * from './SelectionUtils';
|
|
3
|
+
export * from './ICellAnchor';
|
|
4
|
+
export * from './ISelection';
|
|
5
|
+
export * from './DefaultSelection';
|
|
6
|
+
export * from './SelectionStyle';
|
|
7
|
+
export * from './useDragCells';
|
|
8
|
+
export * from './useSelectionPointer';
|
|
9
|
+
export * from './SelectionTouchGrips';
|
|
10
|
+
export * from './SelectionLayer';
|
|
11
|
+
export * from './RangesPickerLayer';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/selection/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AAExB,cAAc,kBAAkB,CAAC;AAEjC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { CellCoords } from '@sheetxl/utils';
|
|
2
|
+
import { IGridPane } from '../surface';
|
|
3
|
+
/**
|
|
4
|
+
* Repeat interval (ms) for the held-still auto-scroll. While a drag is parked past the viewport edge no
|
|
5
|
+
* pointer-move events fire, so the engine re-applies the drag at the last pointer position on this
|
|
6
|
+
* cadence; each tick scrolls one cell, which shifts the cell under the (fixed) point, continuing the drag.
|
|
7
|
+
*/
|
|
8
|
+
export declare const AUTO_SCROLL_INTERVAL_MS = 60;
|
|
9
|
+
/**
|
|
10
|
+
* How close (client px) the pointer must get to a pane edge — on the INSIDE of the viewport, or past it —
|
|
11
|
+
* to engage the auto-scroll. Edge detection is by pointer POSITION, not by the resolved cell, because a
|
|
12
|
+
* TOUCH drag can never resolve a cell past the last visible one: a finger is pinned to the physical grid
|
|
13
|
+
* edge and can't roam into the empty space beyond the content the way a mouse cursor can. This band is
|
|
14
|
+
* sized so a fingertip at the edge falls inside it.
|
|
15
|
+
*/
|
|
16
|
+
export declare const EDGE_AUTO_SCROLL_MARGIN_PX = 24;
|
|
17
|
+
/**
|
|
18
|
+
* The default {@link DragCellsSession.edgeScroll} for a body / picker drag: step the pane's viewport ONE
|
|
19
|
+
* cell toward whichever edge(s) the pointer sits within {@link EDGE_AUTO_SCROLL_MARGIN_PX} of (or past),
|
|
20
|
+
* on both axes. Returns whether an edge is still scrollable — so the held-still auto-scroll keeps ticking.
|
|
21
|
+
*
|
|
22
|
+
* @remarks
|
|
23
|
+
* Position/direction-based rather than "scroll the dragged cell into view": the latter only advances when
|
|
24
|
+
* the resolved cell is off-screen (reachable by a mouse roaming past the content, never by a finger). A
|
|
25
|
+
* fixed one-cell step per tick advances the viewport regardless, and the engine then extends to the cell
|
|
26
|
+
* newly revealed under the pointer. The step routes through the CENTER pane (a frozen pane can't move its
|
|
27
|
+
* frozen axis).
|
|
28
|
+
*
|
|
29
|
+
* @param axes restricts which axes may scroll — a whole-row/column touch grip extends only one axis, so
|
|
30
|
+
* it passes e.g. `{ x: true, y: false }`. Omitted axes default to enabled (both).
|
|
31
|
+
*/
|
|
32
|
+
export declare const edgeScrollPane: (pane: IGridPane, point: {
|
|
33
|
+
x: number;
|
|
34
|
+
y: number;
|
|
35
|
+
}, axes?: {
|
|
36
|
+
x?: boolean;
|
|
37
|
+
y?: boolean;
|
|
38
|
+
}) => boolean;
|
|
39
|
+
/**
|
|
40
|
+
* The in-flight gesture returned by {@link DragCellsOptions.onStart}. It carries the *policy* — how a
|
|
41
|
+
* given cell-drag mutates the model — while the engine owns the *mechanics* (pointer capture, `lastCell`
|
|
42
|
+
* de-dup, the held-still auto-scroll timer, and the public `dragMode` signal).
|
|
43
|
+
*
|
|
44
|
+
* @remarks
|
|
45
|
+
* `onStart` has already SEEDED the model for the down cell (and taken ownership of the down event —
|
|
46
|
+
* `stopPropagation` / `preventDefault` per its own policy); the session's callbacks then drive the drag:
|
|
47
|
+
* `drag` on each new cell, `edgeScroll` for the held-still edge auto-scroll, `end` on release, `cancel`
|
|
48
|
+
* on an OS-cancelled abort.
|
|
49
|
+
*/
|
|
50
|
+
export interface DragCellsSession {
|
|
51
|
+
/**
|
|
52
|
+
* Apply the in-flight update for a newly-entered `cell` — called once per DISTINCT cell during the
|
|
53
|
+
* drag (the engine de-dups moves within the same cell). Not called for the down cell (already seeded).
|
|
54
|
+
* `e` is the triggering pointer event when the move came from a real pointer (read live modifiers off
|
|
55
|
+
* it — e.g. a move-drag's Ctrl=copy / Shift=insert); it is ABSENT on a held-still auto-scroll tick
|
|
56
|
+
* (no pointer event fires while the pointer is parked past the edge), so treat it as optional.
|
|
57
|
+
*/
|
|
58
|
+
drag: (cell: CellCoords, e?: React.PointerEvent) => void;
|
|
59
|
+
/**
|
|
60
|
+
* The auto-scroll step: given the pointer's client `point`, scroll the viewport ONE cell toward any edge
|
|
61
|
+
* the pointer is at (see {@link edgeScrollPane}), and return whether an edge is still engaged so the
|
|
62
|
+
* held-still timer keeps ticking. Called every tick (not gated on a distinct cell) — the drag EXTEND is
|
|
63
|
+
* separate (the engine's per-cell `drag`), so the two concerns don't fight: this steps the viewport, and
|
|
64
|
+
* the engine then extends to the cell newly under the pointer.
|
|
65
|
+
*
|
|
66
|
+
* Position/direction-based on purpose — a cell-based "is the dragged cell off-screen?" test can't fire
|
|
67
|
+
* on TOUCH (a finger can't leave the content). The header supplies a single-axis, sheet-routed version
|
|
68
|
+
* (its controlled viewport can't scroll itself); a body / picker drag uses the default.
|
|
69
|
+
* @defaultValue {@link edgeScrollPane} of the engine's pane (both axes).
|
|
70
|
+
*/
|
|
71
|
+
edgeScroll?: (point: {
|
|
72
|
+
x: number;
|
|
73
|
+
y: number;
|
|
74
|
+
}) => boolean;
|
|
75
|
+
/** Finalize on pointer-up (e.g. a remove-drag's `deselect`, an `onSelectionEnd`, a refocus). */
|
|
76
|
+
end?: (e: React.PointerEvent) => void;
|
|
77
|
+
/**
|
|
78
|
+
* Abort cleanup for a CANCELLED gesture — the OS/browser seized the pointer (`pointercancel`: a touch
|
|
79
|
+
* became a system pan/zoom, a pen left range, a window blurred), OR the user pressed **Escape**
|
|
80
|
+
* (Windows-style drag abort). The engine always runs the mechanical teardown (stop the auto-scroll
|
|
81
|
+
* timer, disarm the touch swallow, release capture); this hook is for the policy's own rollback —
|
|
82
|
+
* restore the pre-drag selection, clear a rubber-band / preview — WITHOUT committing, since a cancel is
|
|
83
|
+
* an abort, not a release. {@link DragCellsSession.end} never runs on a cancel. The event is absent on
|
|
84
|
+
* an Escape abort (no pointer event drives it).
|
|
85
|
+
*/
|
|
86
|
+
cancel?: (e?: React.PointerEvent) => void;
|
|
87
|
+
/**
|
|
88
|
+
* Take pointer capture and track the drag. `false` = a click-only gesture (e.g. a header right-click
|
|
89
|
+
* that positions the selection for the context menu): no capture, moves are ignored, but {@link end}
|
|
90
|
+
* still runs on the next pointer-up. @defaultValue true
|
|
91
|
+
*/
|
|
92
|
+
capture?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* `stopPropagation` the move / up events while this drag is in flight, so a layer below never also acts
|
|
95
|
+
* on them. The down event is owned by `onStart` itself. @defaultValue true
|
|
96
|
+
*/
|
|
97
|
+
captureEvents?: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* A public label for the gesture, surfaced as {@link DragCellsResult.dragMode} between down and up (a
|
|
100
|
+
* layer shows a transient tip — e.g. live R×C — off it). Flips only on start / end, not per move.
|
|
101
|
+
*/
|
|
102
|
+
dragMode?: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Options for {@link useDragCells} / {@link createDragCells}.
|
|
106
|
+
*/
|
|
107
|
+
export interface DragCellsOptions {
|
|
108
|
+
/**
|
|
109
|
+
* Begin a gesture at the `cell` under the pointer. SEED the model, take ownership of the down event
|
|
110
|
+
* (`stopPropagation` / `preventDefault` as the policy needs), and return a {@link DragCellsSession} to
|
|
111
|
+
* drive the drag — or `null` to not start one (a non-primary button, an intercepted right-click, …).
|
|
112
|
+
* The engine captures the pointer only for a returned session (unless {@link DragCellsSession.capture}
|
|
113
|
+
* is `false`).
|
|
114
|
+
*/
|
|
115
|
+
onStart: (cell: CellCoords, e: React.PointerEvent) => DragCellsSession | null;
|
|
116
|
+
}
|
|
117
|
+
/** The spreadable handlers + the public `dragMode`, produced by {@link useDragCells}. */
|
|
118
|
+
export interface DragCellsResult {
|
|
119
|
+
onPointerDown: (e: React.PointerEvent) => void;
|
|
120
|
+
onPointerMove: (e: React.PointerEvent) => void;
|
|
121
|
+
onPointerUp: (e: React.PointerEvent) => void;
|
|
122
|
+
/**
|
|
123
|
+
* Abort the in-flight drag. Wire it onto the tap only if the host routes `pointercancel` — the engine
|
|
124
|
+
* ALSO listens natively on the captured element (a `pointercancel` fires there whether or not the host
|
|
125
|
+
* dispatches it), so this is a safe idempotent extra, not a requirement.
|
|
126
|
+
*/
|
|
127
|
+
onPointerCancel: (e: React.PointerEvent) => void;
|
|
128
|
+
/**
|
|
129
|
+
* What the in-flight drag is doing — the active session's {@link DragCellsSession.dragMode}, or `null`
|
|
130
|
+
* between drags. Flips only on down / up so a layer can show a transient tip without re-rendering on
|
|
131
|
+
* every pointer move.
|
|
132
|
+
*/
|
|
133
|
+
dragMode: string | null;
|
|
134
|
+
}
|
|
135
|
+
/** The headless controller behind {@link useDragCells}. */
|
|
136
|
+
export interface DragCellsController {
|
|
137
|
+
onPointerDown: (e: React.PointerEvent) => void;
|
|
138
|
+
onPointerMove: (e: React.PointerEvent) => void;
|
|
139
|
+
onPointerUp: (e: React.PointerEvent) => void;
|
|
140
|
+
/** Abort the in-flight drag (see {@link DragCellsResult.onPointerCancel}). */
|
|
141
|
+
onPointerCancel: (e: React.PointerEvent) => void;
|
|
142
|
+
/** Stop the auto-scroll timer + disarm touch. Call on unmount (the hook wires this). */
|
|
143
|
+
dispose: () => void;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The **shared cell-drag engine** — the axis-agnostic mechanics every pointer selection needs: pointer
|
|
147
|
+
* capture, per-cell de-dup, the held-still auto-scroll timer, and the public `dragMode` signal. It holds
|
|
148
|
+
* NO range math: an {@link DragCellsOptions.onStart} adapter supplies the policy as a
|
|
149
|
+
* {@link DragCellsSession}. Used by the body selection, the header selection, and the range picker's draw
|
|
150
|
+
* — each a thin adapter over this one engine (so all three get identical auto-scroll for free).
|
|
151
|
+
*
|
|
152
|
+
* @remarks
|
|
153
|
+
* This is the **tap driver**: the consumer spreads `onPointerDown` / `onPointerMove` / `onPointerUp`
|
|
154
|
+
* (and, if the host routes it, `onPointerCancel`) onto a Stage tap; the engine captures the pointer on
|
|
155
|
+
* that tap's element so move / up keep firing when the drag leaves the viewport. The handle / grip
|
|
156
|
+
* flavors, whose element repositions or unmounts mid-drag, use {@link createWindowDragCells} instead —
|
|
157
|
+
* same session, `window`-tracked.
|
|
158
|
+
*
|
|
159
|
+
* A plain (non-hook) factory so a headless controller (e.g. the header's `createHeaderSelectionPointer`,
|
|
160
|
+
* unit-tested with a fake pane) can build on it directly. The React hook is {@link useDragCells}.
|
|
161
|
+
* `onStart` is captured at creation; a caller that needs live values reads them through a ref inside its
|
|
162
|
+
* `onStart` closure (as the hook does).
|
|
163
|
+
*
|
|
164
|
+
* @param onDragModeChange Notified when the active session's `dragMode` changes (a hook turns this into
|
|
165
|
+
* React state); omit for a headless controller that doesn't surface it.
|
|
166
|
+
*/
|
|
167
|
+
export declare const createDragCells: (pane: IGridPane, onStart: (cell: CellCoords, e: React.PointerEvent) => DragCellsSession | null, onDragModeChange?: (mode: string | null) => void) => DragCellsController;
|
|
168
|
+
/** The headless controller behind {@link useWindowDragCells}. */
|
|
169
|
+
export interface WindowDragCellsController {
|
|
170
|
+
/**
|
|
171
|
+
* Begin a `window`-driven gesture from a pointer-down on the source element. `cursorEl` is captured
|
|
172
|
+
* (pointer-capture) purely so the browser paints ITS cursor for the whole drag — the gesture tracks on
|
|
173
|
+
* `window` regardless, surviving the element repositioning / unmounting. Defaults to `e.currentTarget`.
|
|
174
|
+
*/
|
|
175
|
+
start: (e: React.PointerEvent, cursorEl?: Element | null) => void;
|
|
176
|
+
/** Stop any in-flight gesture (drop the `window` listeners + timer + touch swallow). Call on unmount. */
|
|
177
|
+
dispose: () => void;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The **window-driven** cell-drag engine — same {@link DragCellsSession} policy and shared mechanics as
|
|
181
|
+
* {@link createDragCells}, but the gesture tracks on `window` listeners instead of a Stage tap's element
|
|
182
|
+
* capture. Use it when the element that starts the drag repositions or unmounts mid-gesture: a fill /
|
|
183
|
+
* resize handle culled under an edge auto-scroll, a move grip whose source range scrolls off in ghost
|
|
184
|
+
* mode. Element capture on such an element would silently drop the drag; `window` tracking is immune.
|
|
185
|
+
*
|
|
186
|
+
* @remarks
|
|
187
|
+
* The source element is still pointer-captured (for its CURSOR only — see {@link WindowDragCellsController.start});
|
|
188
|
+
* the actual move / up / cancel are `window` listeners, so a re-render or unmount of the handle never
|
|
189
|
+
* interrupts the gesture. Consumers supply `onStart` policy exactly as for the tap engine, and get the
|
|
190
|
+
* same held-still auto-scroll, touch arming, per-cell de-dup, and abort-on-cancel.
|
|
191
|
+
*/
|
|
192
|
+
export declare function createWindowDragCells(pane: IGridPane, onStart: (cell: CellCoords, e: React.PointerEvent) => DragCellsSession | null, onDragModeChange?: (mode: string | null) => void,
|
|
193
|
+
/** Override cell resolution (a touch grip resolves against the pane the finger is over). */
|
|
194
|
+
resolveCell?: (clientX: number, clientY: number) => CellCoords | null): WindowDragCellsController;
|
|
195
|
+
/**
|
|
196
|
+
* The React hook over {@link createDragCells}: reads the pane from context, owns the `dragMode` state,
|
|
197
|
+
* and stops the auto-scroll timer on unmount. `onStart` is read live through a ref, so a consumer's
|
|
198
|
+
* closure over changing values (selection, options) needs no handler rebuild.
|
|
199
|
+
*/
|
|
200
|
+
export declare const useDragCells: (onStart: (cell: CellCoords, e: React.PointerEvent) => DragCellsSession | null) => DragCellsResult;
|
|
201
|
+
/** Handlers + transient `dragMode` produced by {@link useWindowDragCells}. */
|
|
202
|
+
export interface WindowDragCellsResult {
|
|
203
|
+
/**
|
|
204
|
+
* Begin a window-driven gesture. Spread as the source element's `onPointerDown`. Pass a `cursorEl` (the
|
|
205
|
+
* element whose cursor should paint for the drag) when the pointer-down may be dispatched with a
|
|
206
|
+
* `currentTarget` other than that element (e.g. a grip below an interactive child).
|
|
207
|
+
*/
|
|
208
|
+
start: (e: React.PointerEvent, cursorEl?: Element | null) => void;
|
|
209
|
+
/** The active session's `dragMode`, or `null` between drags (flips only on start / end). */
|
|
210
|
+
dragMode: string | null;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* The React hook over {@link createWindowDragCells}: reads the pane from context, owns the `dragMode`
|
|
214
|
+
* state, and disposes the gesture on unmount. For handle / grip flavors (fill, resize, move, touch grips)
|
|
215
|
+
* whose element repositions or unmounts mid-drag. `onStart` is read live through a ref.
|
|
216
|
+
*/
|
|
217
|
+
export declare const useWindowDragCells: (onStart: (cell: CellCoords, e: React.PointerEvent) => DragCellsSession | null) => WindowDragCellsResult;
|
|
218
|
+
//# sourceMappingURL=useDragCells.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDragCells.d.ts","sourceRoot":"","sources":["../../../../src/selection/useDragCells.ts"],"names":[],"mappings":"AAEA,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE7E,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAKzD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,SAAS,EACf,OAAO;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/B,OAAM;IAAE,CAAC,CAAC,EAAE,OAAO,CAAC;IAAC,CAAC,CAAC,EAAE,OAAO,CAAA;CAAyB,KACxD,OA6BF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,IAAI,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;IACzD;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;IAC1D,gGAAgG;IAChG,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;IACtC;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;IAC1C;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,gBAAgB,GAAG,IAAI,CAAC;CAC/E;AAED,yFAAyF;AACzF,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;IAC/C,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;IAC/C,WAAW,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;IAC7C;;;;OAIG;IACH,eAAe,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;IACjD;;;;OAIG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,2DAA2D;AAC3D,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;IAC/C,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;IAC/C,WAAW,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;IAC7C,8EAA8E;IAC9E,eAAe,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;IACjD,wFAAwF;IACxF,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AA4ID;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,eAAe,GAC1B,MAAM,SAAS,EACf,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,gBAAgB,GAAG,IAAI,EAC7E,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,KAC/C,mBAyGF,CAAC;AAEF,iEAAiE;AACjE,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,KAAK,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;IAClE,yGAAyG;IACzG,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,gBAAgB,GAAG,IAAI,EAC7E,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI;AAChD,4FAA4F;AAC5F,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,UAAU,GAAG,IAAI,GACpE,yBAAyB,CAgE3B;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,GACvB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,gBAAgB,GAAG,IAAI,KAC5E,eAoBF,CAAC;AAEF,8EAA8E;AAC9E,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,KAAK,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;IAClE,4FAA4F;IAC5F,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC7B,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,gBAAgB,GAAG,IAAI,KAC5E,qBAcF,CAAC"}
|