@sheetxl/grid-react 0.8.0-beta.19 → 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/README.md +1 -1
- package/browser/esm/index.mjs +1568 -1350
- package/node/esm/index.mjs +1885 -1666
- package/package.json +3 -3
- package/types/src/layer/GestureTip.d.ts +10 -2
- package/types/src/range/DragHandle.d.ts +8 -4
- package/types/src/range/FillHandle.d.ts +6 -0
- 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 +25 -0
- package/types/src/selection/SelectionTouchGrips.d.ts +6 -0
- package/types/src/surface/useSurfaceState.d.ts +10 -0
- package/types/src/svg/RectangleSVG.d.ts +21 -4
- package/types/src/svg/_Glide.d.ts +0 -9
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.8.0-beta.
|
|
4
|
+
"version": "0.8.0-beta.20",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"table"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@sheetxl/utils": "^0.8.0-beta.
|
|
44
|
-
"@sheetxl/utils-react": "^0.8.0-beta.
|
|
43
|
+
"@sheetxl/utils": "^0.8.0-beta.20",
|
|
44
|
+
"@sheetxl/utils-react": "^0.8.0-beta.20",
|
|
45
45
|
"clsx": "^2.1.1",
|
|
46
46
|
"react-merge-refs": "^3.0.2"
|
|
47
47
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
+
import { RangeGlide } from '../range/RangeGlide';
|
|
2
3
|
import { GridAnchor, GridPlacement, GridBoundary } from './useGridAnchor';
|
|
3
4
|
/**
|
|
4
5
|
* A gesture readout anchored to a DOM element rather than to the grid — a scrollbar thumb, which lives
|
|
@@ -35,11 +36,18 @@ export interface GestureTipProps {
|
|
|
35
36
|
/** Offset (px) along the anchored edge (only `start` / `end` align). @defaultValue 0 */
|
|
36
37
|
alignOffset?: number;
|
|
37
38
|
/**
|
|
38
|
-
* Glide to each new position instead of jumping
|
|
39
|
-
*
|
|
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.
|
|
40
42
|
* @defaultValue none — a readout jumps with its gesture
|
|
41
43
|
*/
|
|
42
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;
|
|
43
51
|
/** Where the readout may live (a grid anchor only). @defaultValue 'data' */
|
|
44
52
|
boundary?: GridBoundary;
|
|
45
53
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CellCoords, RangeCoords } from '@sheetxl/utils';
|
|
2
|
+
import { RangeGlide } from './RangeGlide';
|
|
2
3
|
/** Which corner (`tl`/`tr`/`bl`/`br`) or edge-midpoint (`t`/`b`/`l`/`r`) of the range to sit on. */
|
|
3
4
|
export type HandleAnchor = 'tl' | 'tr' | 'bl' | 'br' | 't' | 'b' | 'l' | 'r';
|
|
4
5
|
/**
|
|
@@ -24,6 +25,8 @@ export interface DragHandleRenderProps {
|
|
|
24
25
|
handleProps: {
|
|
25
26
|
/** The handle's identifying class(es) — `drag-handle` plus whatever the flavor tagged it with. */
|
|
26
27
|
className?: string;
|
|
28
|
+
/** The handle element, which a glide moves frame by frame. Any element type takes it. */
|
|
29
|
+
ref: (element: HTMLElement | null) => void;
|
|
27
30
|
onPointerDown: (e: React.PointerEvent) => void;
|
|
28
31
|
onDoubleClick?: (e: React.MouseEvent) => void;
|
|
29
32
|
onPointerEnter?: (e: React.PointerEvent) => void;
|
|
@@ -88,11 +91,12 @@ export interface DragHandleProps {
|
|
|
88
91
|
*/
|
|
89
92
|
hoverStyle?: React.CSSProperties;
|
|
90
93
|
/**
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
+
* Ride this glide's frames while it is in flight — the same clock as a {@link RangeRect} given the
|
|
95
|
+
* same glide, so the handle stays on the outline's corner. The glide must be heading to `range`. A
|
|
96
|
+
* handle pinned to the view ({@link DragHandleProps.clampToView}) hides until the glide lands: its
|
|
97
|
+
* pinned edge has no place along the way.
|
|
94
98
|
*/
|
|
95
|
-
|
|
99
|
+
glide?: RangeGlide | null;
|
|
96
100
|
/**
|
|
97
101
|
* Pin the handle centre INSIDE the pane's viewport instead of letting it sit at the range's true
|
|
98
102
|
* anchored corner. When that corner is far off-grid — e.g. a whole-row / whole-column fill selection
|
|
@@ -2,6 +2,7 @@ import { default as React } from 'react';
|
|
|
2
2
|
import { CellCoords, RangeCoords } from '@sheetxl/utils';
|
|
3
3
|
import { VisualSVGProps } from '../svg';
|
|
4
4
|
import { DragHandleRenderProps } from './DragHandle';
|
|
5
|
+
import { RangeGlide } from './RangeGlide';
|
|
5
6
|
/**
|
|
6
7
|
* Props for {@link FillHandle}. Follows the shared **RangeHandle** contract: a controlled `range`
|
|
7
8
|
* (the fill template/source) in, the fill **destination** range out via `onDrag*`. The destination
|
|
@@ -61,6 +62,11 @@ export interface FillHandleProps extends VisualSVGProps {
|
|
|
61
62
|
* Replaces the default dot. Use it for a custom fill mark (e.g. the Excel fill square).
|
|
62
63
|
*/
|
|
63
64
|
renderHandle?: (props: DragHandleRenderProps) => React.ReactNode;
|
|
65
|
+
/**
|
|
66
|
+
* The glide the template's outline is drawn with, so the handle rides its corner frame by frame
|
|
67
|
+
* instead of arriving first. See {@link DragHandleProps.glide}.
|
|
68
|
+
*/
|
|
69
|
+
glide?: RangeGlide | null;
|
|
64
70
|
}
|
|
65
71
|
/**
|
|
66
72
|
* The destination range when filling `template` toward `to`. Excel-style single axis: extend along
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Bounds, RangeCoords, TopLeft } from '@sheetxl/utils';
|
|
2
|
+
import { IGridPane } from '../surface';
|
|
3
|
+
/**
|
|
4
|
+
* What a {@link RangeGlide} travels to: a range, plus the cell cut out of its fill (a selection's
|
|
5
|
+
* active cell), which travels on the same clock.
|
|
6
|
+
*/
|
|
7
|
+
export interface RangeGlideTarget {
|
|
8
|
+
range: RangeCoords;
|
|
9
|
+
hole?: RangeCoords;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* One frame of a glide: the rectangle to draw and its hole, in a pane's VIEW space (the space
|
|
13
|
+
* `IGridPane.getBoundsFromRange` returns).
|
|
14
|
+
*/
|
|
15
|
+
export interface RangeGlideFrame {
|
|
16
|
+
outer: Bounds;
|
|
17
|
+
hole?: Bounds;
|
|
18
|
+
/**
|
|
19
|
+
* Where `outer` is heading: the target's box, clamped as `outer` is. Whatever is anchored to the
|
|
20
|
+
* target travels by `outer`'s offset from it.
|
|
21
|
+
*/
|
|
22
|
+
to: Bounds;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The geometry a glide resolves through: one pane's view. A glide keeps no pixels of its own - the
|
|
26
|
+
* target is a range and the start point is absolute (content) space - so every pane that draws it
|
|
27
|
+
* asks through its own view, and a scroll mid-glide moves the frame with the cells.
|
|
28
|
+
*/
|
|
29
|
+
export interface RangeGlideView {
|
|
30
|
+
/** A range's box in view space. */
|
|
31
|
+
boundsOf(range: RangeCoords): Bounds;
|
|
32
|
+
/** Absolute (content) space → view space. */
|
|
33
|
+
toView(bounds: Bounds): Bounds;
|
|
34
|
+
/** View space → absolute (content) space. */
|
|
35
|
+
toAbsolute(bounds: Bounds): Bounds;
|
|
36
|
+
/** The view's visible box (view space). */
|
|
37
|
+
getViewport(): Bounds;
|
|
38
|
+
/** Where the view is scrolling to; a change mid-glide that the glide did not start with stops it. */
|
|
39
|
+
getScrollTarget(): TopLeft;
|
|
40
|
+
/** Device pixel ratio, for keeping a moving box's size steady. */
|
|
41
|
+
getDevicePixelRatio(): number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Timing of a {@link RangeGlide}.
|
|
45
|
+
*/
|
|
46
|
+
export interface RangeGlideOptions {
|
|
47
|
+
/** How long a glide takes, in ms. `0` never glides. @defaultValue 60 */
|
|
48
|
+
duration?: number;
|
|
49
|
+
/**
|
|
50
|
+
* How far into the glide its first frame is drawn, in ms. The clock starts on the first animation
|
|
51
|
+
* frame, not when the target changes: the change usually lands inside the work it causes (a render
|
|
52
|
+
* of everything that reads the selection), and a clock running through that work would spend the
|
|
53
|
+
* glide where nothing paints and show it as a jump. @defaultValue one 60Hz frame
|
|
54
|
+
*/
|
|
55
|
+
frameLead?: number;
|
|
56
|
+
/**
|
|
57
|
+
* How long a glide takes when it starts from inside another one - a held arrow key, a drag. Shorter,
|
|
58
|
+
* so a stream of retargets keeps up instead of trailing. @defaultValue 60% of `duration`
|
|
59
|
+
*/
|
|
60
|
+
retargetDuration?: number;
|
|
61
|
+
/** Progress (0..1) → eased progress (0..1). @defaultValue ease-out quad */
|
|
62
|
+
easing?: (t: number) => number;
|
|
63
|
+
/** The clock. @defaultValue `performance.now` */
|
|
64
|
+
now?: () => number;
|
|
65
|
+
/** Schedule the next frame. @defaultValue `requestAnimationFrame` */
|
|
66
|
+
requestFrame?: (callback: () => void) => number;
|
|
67
|
+
/** Cancel a scheduled frame. @defaultValue `cancelAnimationFrame` */
|
|
68
|
+
cancelFrame?: (handle: number) => void;
|
|
69
|
+
/** Whether motion is reduced (no glides). @defaultValue the `prefers-reduced-motion` media query */
|
|
70
|
+
isReducedMotion?: () => boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Interpolate `from` → `to` at eased progress `e`, edge by edge. Edges shared by both ends are
|
|
74
|
+
* returned unchanged; with one `e` for a box and its hole, a hole inside its box at both ends stays
|
|
75
|
+
* inside it throughout.
|
|
76
|
+
*/
|
|
77
|
+
export declare const lerpGlideBounds: (from: Bounds, to: Bounds, e: number, dpr: number) => Bounds;
|
|
78
|
+
/**
|
|
79
|
+
* How far a frame is from where it is heading, at the edge something hangs off — the offset that
|
|
80
|
+
* carries a thing anchored to the target (a handle on its corner, a tip off its side) along with the
|
|
81
|
+
* frame. `side` and `align` name the edge as a grid placement does: `side` the edge, `align` the point
|
|
82
|
+
* along it.
|
|
83
|
+
*/
|
|
84
|
+
export declare const glideOffset: (frame: RangeGlideFrame, side: "t" | "b" | "l" | "r", align?: "start" | "center" | "end") => {
|
|
85
|
+
dx: number;
|
|
86
|
+
dy: number;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* The {@link RangeGlideView} of a grid pane.
|
|
90
|
+
*/
|
|
91
|
+
export declare const paneGlideView: (pane: IGridPane) => RangeGlideView;
|
|
92
|
+
/**
|
|
93
|
+
* A glide between ranges on one clock: the animation of a selection moving, growing or shrinking from
|
|
94
|
+
* one range to the next. Everything that travels with the range - its outline, its fill and hole, its
|
|
95
|
+
* handles, its tip - reads the same frame, so they move in lockstep.
|
|
96
|
+
*
|
|
97
|
+
* @remarks
|
|
98
|
+
* A glide holds ranges and one start point, not pixels: the target is a range and the start is in
|
|
99
|
+
* absolute (content) space, and each frame is resolved through the view that asks for it. So a glide
|
|
100
|
+
* is shared by every pane of a surface (one per frozen pane, each drawing its own clipped slice), and
|
|
101
|
+
* a scroll mid-glide carries the frame with the cells instead of dragging it. A scroll the glide did
|
|
102
|
+
* not start with - the user's wheel - ends it.
|
|
103
|
+
*
|
|
104
|
+
* It renders nothing. Readers {@link subscribe} and pull {@link frame} for their view on each tick;
|
|
105
|
+
* `frame` is `null` when settled, which means: draw the target as rendered.
|
|
106
|
+
*/
|
|
107
|
+
export declare class RangeGlide {
|
|
108
|
+
private readonly _duration;
|
|
109
|
+
private readonly _frameLead;
|
|
110
|
+
private readonly _retargetDuration;
|
|
111
|
+
private readonly _easing;
|
|
112
|
+
private readonly _now;
|
|
113
|
+
private readonly _requestFrame;
|
|
114
|
+
private readonly _cancelFrame;
|
|
115
|
+
private readonly _isReducedMotion;
|
|
116
|
+
private _target;
|
|
117
|
+
/** Where the glide started, in absolute space; `null` when settled. */
|
|
118
|
+
private _from;
|
|
119
|
+
private _start;
|
|
120
|
+
private _length;
|
|
121
|
+
/** Eased progress of the glide in flight. */
|
|
122
|
+
private _progress;
|
|
123
|
+
/** The view the glide started in, watched for a scroll it did not start with. */
|
|
124
|
+
private _view;
|
|
125
|
+
private _scrollBase;
|
|
126
|
+
private _handle;
|
|
127
|
+
private readonly _listeners;
|
|
128
|
+
constructor(options?: RangeGlideOptions);
|
|
129
|
+
/** The range the glide is heading to (or rests at). */
|
|
130
|
+
getTarget(): RangeGlideTarget | null;
|
|
131
|
+
/** A glide is in flight. */
|
|
132
|
+
isGliding(): boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Head to `target`. The same target again does nothing, so every pane drawing one selection can
|
|
135
|
+
* call this on each render and only the first change counts. With `animate` the glide starts from
|
|
136
|
+
* what is drawn now - mid-flight, from the frame in flight; otherwise it jumps.
|
|
137
|
+
*
|
|
138
|
+
* @param view The view of the caller, used to capture the start point and watch for a user scroll.
|
|
139
|
+
* @returns Whether the target changed.
|
|
140
|
+
*/
|
|
141
|
+
retarget(target: RangeGlideTarget, view: RangeGlideView, animate: boolean): boolean;
|
|
142
|
+
/** Jump to the target now. */
|
|
143
|
+
finish(): void;
|
|
144
|
+
/**
|
|
145
|
+
* The frame to draw in `view` now, or `null` when settled (draw the target as rendered). A glide
|
|
146
|
+
* whose start is nowhere near the view - a jump to the far end of the data - draws no frame.
|
|
147
|
+
*/
|
|
148
|
+
frame(view: RangeGlideView): RangeGlideFrame | null;
|
|
149
|
+
/** Listen for frames (each tick, and on start and settle). Returns the unsubscribe. */
|
|
150
|
+
subscribe(listener: () => void): () => void;
|
|
151
|
+
/**
|
|
152
|
+
* What is drawn now, in absolute space: the frame in flight, else the target at rest. Unclamped, so
|
|
153
|
+
* it is the same whichever pane asks - a frozen pane the range is not in included.
|
|
154
|
+
*/
|
|
155
|
+
private _shownAbsolute;
|
|
156
|
+
private readonly _tick;
|
|
157
|
+
private _settle;
|
|
158
|
+
private _notify;
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=RangeGlide.d.ts.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { RangeCoords } from '@sheetxl/utils';
|
|
2
2
|
import { VirtualDivProps } from '../layer';
|
|
3
3
|
import { VisualSVGProps } from '../svg';
|
|
4
|
+
import { RangeGlide } from './RangeGlide';
|
|
4
5
|
/**
|
|
5
6
|
* Props for {@link RangeRect}: a thin range→bounds wrapper that places the {@link RectangleSVG}
|
|
6
7
|
* **shape** at a grid range — it resolves the range to bounds via the pane, culls off-screen,
|
|
@@ -23,6 +24,12 @@ export interface RangeRectProps extends Omit<VirtualDivProps, 'fill'>, Omit<Visu
|
|
|
23
24
|
* concern {@link RectangleSVG} can't express (it has no pane and does no culling).
|
|
24
25
|
*/
|
|
25
26
|
clipInsets?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Draw the frames of this glide while it is in flight; at rest, `range` and `hole` as given. The glide
|
|
29
|
+
* must be heading to `range` (and to `hole`, when there is one) - the caller retargets it. Every
|
|
30
|
+
* rectangle reading one glide moves on one clock.
|
|
31
|
+
*/
|
|
32
|
+
glide?: RangeGlide | null;
|
|
26
33
|
}
|
|
27
34
|
/**
|
|
28
35
|
* Places one device-aligned {@link RectangleSVG} at a grid range. Resolves the range to bounds via
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { RangeCoords } from '@sheetxl/utils';
|
|
2
2
|
import { VisualSVGProps } from '../svg';
|
|
3
3
|
import { HandleAnchor, DragHandleRenderProps } from './DragHandle';
|
|
4
|
+
import { RangeGlide } from './RangeGlide';
|
|
4
5
|
/** The four corner handles (chart series / formula precedent rectangles use these). */
|
|
5
6
|
export declare const RESIZE_ANCHORS_4: readonly HandleAnchor[];
|
|
6
7
|
/** Corners + edge midpoints. */
|
|
@@ -9,7 +10,7 @@ export declare const RESIZE_ANCHORS_8: readonly HandleAnchor[];
|
|
|
9
10
|
* Props for {@link RangeResizer}. Follows the shared **RangeHandle** contract: a controlled
|
|
10
11
|
* `range` in, the resized range out via `onDrag*`. Extends {@link VisualSVGProps} (like
|
|
11
12
|
* {@link RangeRectProps}) so the outline's paint props — `stroke`, `fill`, `strokeWidth`,
|
|
12
|
-
* `animatedStroke`,
|
|
13
|
+
* `animatedStroke`, … — are passed directly; the handles inherit
|
|
13
14
|
* {@link DEFAULT_HANDLE_STYLE} for whatever you don't set. The grip color follows `stroke`.
|
|
14
15
|
*/
|
|
15
16
|
export interface RangeResizerProps extends VisualSVGProps {
|
|
@@ -51,6 +52,11 @@ export interface RangeResizerProps extends VisualSVGProps {
|
|
|
51
52
|
renderHandle?: (props: DragHandleRenderProps) => React.ReactNode;
|
|
52
53
|
/** Keep the current focus across a handle drag (forwarded to {@link DragHandle.preserveFocus}). */
|
|
53
54
|
preserveFocus?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Draw the outline and its grips from this glide's frames while it is in flight, on one clock. The
|
|
57
|
+
* glide must be heading to `range`.
|
|
58
|
+
*/
|
|
59
|
+
glide?: RangeGlide | null;
|
|
54
60
|
}
|
|
55
61
|
/**
|
|
56
62
|
* A draggable, resizable rectangle: an outlined range with {@link DragHandle} grips on the requested
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* (`useWindowDragCells`) for their gesture mechanics — capture, de-dup, edge auto-scroll, touch, cancel.
|
|
6
6
|
*/
|
|
7
7
|
export * from './RangeStyle';
|
|
8
|
+
export * from './RangeGlide';
|
|
9
|
+
export * from './useRangeGlide';
|
|
8
10
|
export * from './RangeRect';
|
|
9
11
|
export * from './RangeInsertBar';
|
|
10
12
|
export * from './DragHandle';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { RangeGlide, RangeGlideOptions } from './RangeGlide';
|
|
2
|
+
/**
|
|
3
|
+
* The {@link RangeGlide} shared by every pane of the surface under `key` - one clock for one logical
|
|
4
|
+
* range (a selection), so each pane's copy, and everything that travels with the range, reads the same
|
|
5
|
+
* frame. Never re-renders: readers subscribe to the glide itself.
|
|
6
|
+
*
|
|
7
|
+
* @param key Unique within the surface. `null` returns `null` (no glide).
|
|
8
|
+
* @param options Timing, read when the glide is first created under `key`.
|
|
9
|
+
*/
|
|
10
|
+
export declare const useRangeGlide: (key: string | null, options?: RangeGlideOptions) => RangeGlide | null;
|
|
11
|
+
//# sourceMappingURL=useRangeGlide.d.ts.map
|
|
@@ -55,7 +55,10 @@ export interface RangesPickerLayerProps extends LayerProps {
|
|
|
55
55
|
* {@link RESIZE_ANCHORS_8} for corners + edge midpoints.
|
|
56
56
|
*/
|
|
57
57
|
anchors?: readonly HandleAnchor[];
|
|
58
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Enable the move grip (drag the border to relocate a range, keeping its size). The moved range glides
|
|
60
|
+
* from cell to cell, its corner grips with it. @defaultValue false
|
|
61
|
+
*/
|
|
59
62
|
enabledMove?: boolean;
|
|
60
63
|
/**
|
|
61
64
|
* Don't claim the grid-wide **draw** gesture — the pointer-drag over empty grid that re-scopes the
|
|
@@ -57,6 +57,21 @@ export interface MoveDrop {
|
|
|
57
57
|
*/
|
|
58
58
|
refused?: boolean;
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* How a selection glides from one range to the next — see {@link SelectionLayerProps.animate}.
|
|
62
|
+
*/
|
|
63
|
+
export interface SelectionAnimateOptions {
|
|
64
|
+
/**
|
|
65
|
+
* Names the selection's glide within the surface. Every pane drawing ONE selection must share it, and
|
|
66
|
+
* two selections drawn on one surface must not, so a host that swaps the model underneath (a sheet
|
|
67
|
+
* switch) puts the model's identity in it: a new key starts at rest rather than gliding in from the
|
|
68
|
+
* last model's range.
|
|
69
|
+
* @defaultValue 'selection'
|
|
70
|
+
*/
|
|
71
|
+
key?: string;
|
|
72
|
+
/** How long a glide takes, in ms. @defaultValue 60 */
|
|
73
|
+
duration?: number;
|
|
74
|
+
}
|
|
60
75
|
/**
|
|
61
76
|
* Props for {@link SelectionLayer}.
|
|
62
77
|
*/
|
|
@@ -292,6 +307,16 @@ export interface SelectionLayerProps extends LayerProps {
|
|
|
292
307
|
* @defaultValue true
|
|
293
308
|
*/
|
|
294
309
|
anchorHole?: boolean;
|
|
310
|
+
/**
|
|
311
|
+
* Glide the single-range selection from one range to the next — moving, growing and shrinking edge by
|
|
312
|
+
* edge, its active-cell cutout on the same clock — instead of jumping. Edges that don't change stay
|
|
313
|
+
* put, a scroll during a glide carries it with the cells, and a scroll the user starts ends it. A
|
|
314
|
+
* multi-range selection, and the selection a move or fill commits, jump. Off under
|
|
315
|
+
* `prefers-reduced-motion`.
|
|
316
|
+
*
|
|
317
|
+
* @defaultValue false
|
|
318
|
+
*/
|
|
319
|
+
animate?: boolean | SelectionAnimateOptions;
|
|
295
320
|
}
|
|
296
321
|
/**
|
|
297
322
|
* The selection layer: renders the selection (single-range "rich" treatment vs multi-range), routes
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
+
import { RangeGlide } from '../range';
|
|
2
3
|
import { ISelection } from './ISelection';
|
|
3
4
|
/**
|
|
4
5
|
* Props for {@link SelectionTouchGrips}.
|
|
@@ -6,6 +7,11 @@ import { ISelection } from './ISelection';
|
|
|
6
7
|
export interface SelectionTouchGripsProps {
|
|
7
8
|
/** The selection the touch handles read (for placement) and extend (via `modify`). */
|
|
8
9
|
selection: ISelection;
|
|
10
|
+
/**
|
|
11
|
+
* The glide the selection is drawn with (the `SelectionLayer`'s, by its `animate` key), so the grips
|
|
12
|
+
* ride its frames on the outline's corners instead of arriving first.
|
|
13
|
+
*/
|
|
14
|
+
glide?: RangeGlide | null;
|
|
9
15
|
}
|
|
10
16
|
/**
|
|
11
17
|
* Touch selection handles: round grips at the active range's corners (or edges, for a whole row/column)
|
|
@@ -28,6 +28,16 @@ export declare function useSurfaceState<T>(key: string, initialValue: T | (() =>
|
|
|
28
28
|
* @param initialValue The value an updater function receives while the cell has never been written.
|
|
29
29
|
*/
|
|
30
30
|
export declare function useSurfaceStateSetter<T>(key: string, initialValue: T): Dispatch<SetStateAction<T>>;
|
|
31
|
+
/**
|
|
32
|
+
* A stable OBJECT shared by every pane of the surface under `key` — created on first use, then the same
|
|
33
|
+
* instance for every caller. Unlike {@link useSurfaceState} it never re-renders: the object is the
|
|
34
|
+
* channel (a clock, an animator, an imperative store with its own `subscribe`), not a value to render.
|
|
35
|
+
*
|
|
36
|
+
* @param key The cell's key, unique within the surface — the same rule as `useSurfaceState`. `null`
|
|
37
|
+
* opts out and returns `null`, so a caller can make the object conditional without breaking hook order.
|
|
38
|
+
* @param create Builds the object the first time the key is asked for.
|
|
39
|
+
*/
|
|
40
|
+
export declare function useSurfaceObject<T extends object>(key: string | null, create: () => T): T | null;
|
|
31
41
|
/**
|
|
32
42
|
* Read one {@link useSurfaceState} cell from a given store — for the component that OWNS the store and so
|
|
33
43
|
* sits above its {@link SurfaceStateProvider} (it passes the store to the provider and reads it here).
|
|
@@ -76,10 +76,6 @@ export interface VisualSVGProps {
|
|
|
76
76
|
* defaults; pass {@link AnimatedStrokeProps} to tune the dash/speed.
|
|
77
77
|
*/
|
|
78
78
|
animatedStroke?: boolean | AnimatedStrokeProps;
|
|
79
|
-
/**
|
|
80
|
-
* Transition the path `d` so the shape glides when its bounds change (move-drag).
|
|
81
|
-
*/
|
|
82
|
-
animatedTransition?: boolean;
|
|
83
79
|
/** Class on the root `<svg>`. */
|
|
84
80
|
className?: string;
|
|
85
81
|
/**
|
|
@@ -89,12 +85,33 @@ export interface VisualSVGProps {
|
|
|
89
85
|
*/
|
|
90
86
|
style?: Omit<React.CSSProperties, PaintCSSKey>;
|
|
91
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Bounds that change faster than React renders - an animation - for {@link RectangleSVGProps.frameSource}.
|
|
90
|
+
*/
|
|
91
|
+
export interface RectangleFrameSource {
|
|
92
|
+
/**
|
|
93
|
+
* The bounds (and hole) to draw now, in the same space as {@link RectangleSVGProps.bounds}; `null`
|
|
94
|
+
* draws the rendered `bounds`.
|
|
95
|
+
*/
|
|
96
|
+
getFrame(): {
|
|
97
|
+
bounds: Bounds;
|
|
98
|
+
hole?: Bounds;
|
|
99
|
+
} | null;
|
|
100
|
+
/** Called when the frame changes. Returns the unsubscribe. */
|
|
101
|
+
subscribe(onFrame: () => void): () => void;
|
|
102
|
+
}
|
|
92
103
|
export interface RectangleSVGProps extends VisualSVGProps, ShapeProps {
|
|
93
104
|
/**
|
|
94
105
|
* RAW bounds of an evenodd cut-out of the FILL (e.g. the active cell inside a
|
|
95
106
|
* selection). Area-snapped (`snapDeviceEdge`), not stroke-snapped. Ignored for the stroke.
|
|
96
107
|
*/
|
|
97
108
|
hole?: Bounds;
|
|
109
|
+
/**
|
|
110
|
+
* Draw each frame of an animation from here instead of re-rendering: the paths are rewritten in
|
|
111
|
+
* place, snapped exactly as a render would snap them, and a `null` frame puts back the rendered
|
|
112
|
+
* `bounds`.
|
|
113
|
+
*/
|
|
114
|
+
frameSource?: RectangleFrameSource;
|
|
98
115
|
/**
|
|
99
116
|
* Escape hatch: props spread onto the root `<svg>` element (raw attributes, event handlers). Rare —
|
|
100
117
|
* the wrapper is `pointerEvents: 'none'` by default and overlays seldom need it. Prefer the dedicated
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* How a moving range outline glides between cells. What travels with it — its corner handles, its
|
|
3
|
-
* gesture tip — rides the same timing, or it reads as trailing.
|
|
4
|
-
*/
|
|
5
|
-
export declare const RANGE_GLIDE: {
|
|
6
|
-
readonly duration: 60;
|
|
7
|
-
readonly easing: "ease-in-out";
|
|
8
|
-
};
|
|
9
|
-
//# sourceMappingURL=_Glide.d.ts.map
|