@n-uf/hypr-tiling 26.7.0
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/CHANGELOG.md +145 -0
- package/README.md +242 -0
- package/dist/chunk-ZCGZOWOY.mjs +9871 -0
- package/dist/devtools.cjs +12001 -0
- package/dist/devtools.d.mts +111 -0
- package/dist/devtools.d.ts +111 -0
- package/dist/devtools.mjs +2286 -0
- package/dist/drag-easing-5WbK3T82.d.ts +605 -0
- package/dist/drag-easing-KxPPNNZT.d.mts +605 -0
- package/dist/engine.cjs +9899 -0
- package/dist/engine.d.mts +314 -0
- package/dist/engine.d.ts +314 -0
- package/dist/engine.mjs +116 -0
- package/dist/index.cjs +9833 -0
- package/dist/index.d.mts +74 -0
- package/dist/index.d.ts +74 -0
- package/dist/index.mjs +125 -0
- package/dist/tiling-renderer-kTlSm4H4.d.mts +2185 -0
- package/dist/tiling-renderer-kTlSm4H4.d.ts +2185 -0
- package/package.json +96 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
export { G as GroupLeavesOptions, M as MULTI_SELECT_GROUP_MIN_MEMBERS, T as TILING_KEYMAP_DEFAULTS, a as TilingKeymapActionGuards, c as canGroupMultiSelection, b as chordRequiresModifier, d as collectGroups, e as collectSplitNodes, f as commandRequiredCapability, g as findLeafByDirection, h as findLeafById, i as groupLeaves, j as hasAnyModifier, k as insertLeafAdjacent, l as isCssEasing, m as isResizeAxisEnabled, n as isStructurallyValidLayout, o as keyboardActionToCommand, p as matchKeyChord, q as matchKeymapAction, r as moveLeafToRoot, s as moveLeafToSplitContainer, t as pruneMultiSelection, u as readLeafNodeIds, v as removeLeafTile, w as resolveDragEasing, x as resolveKeymap, y as resolveMaximizeToggle, z as resolveMultiSelectGroupCommand, A as resolveMultiSelectGroupHost, B as setLeafSizing, C as siblingSubtreeForLeaf, D as swapLeafTiles, E as tileOrderByLeafId, F as toggleLeafMultiSelection, H as toggleSplitAxis, I as ungroupNode, J as updateSplitRatio } from './drag-easing-KxPPNNZT.mjs';
|
|
2
|
+
import { r as TilingLeafDropZone, s as TilingDropAction, t as TilingSplitAxis, j as TilingDropIntentTuningState, u as ResolvedTilingKeymap, v as TilingKeyBinding, w as TilingKeyboardEventLike, x as TilingCommand, T as TilingLayoutNode, y as TilingDimension, z as TilingPaneSizing, A as TilingPaneSizingMode } from './tiling-renderer-kTlSm4H4.mjs';
|
|
3
|
+
export { B as BASELINE_DRAG_HOP_DURATION_MS, I as INSTANT_DRAG_DURATION_MS, C as TilingAccentHue, D as TilingKeyboardAction, E as TilingKeyboardModifierState, F as TilingMoveModeState, G as TilingPaneSwitcherState, H as accentHue } from './tiling-renderer-kTlSm4H4.mjs';
|
|
4
|
+
import 'react';
|
|
5
|
+
|
|
6
|
+
/** A pane's four directional insert edges (the drop zones excluding `"center"`). */
|
|
7
|
+
type TilingEdgeZone = Exclude<TilingLeafDropZone, "center">;
|
|
8
|
+
/** Base drop hit-zone geometry: center swap fraction, floor, and hysteresis. */
|
|
9
|
+
interface TilingDropIntentBaseConfig {
|
|
10
|
+
/**
|
|
11
|
+
* Fraction of each pane axis spanned by the center (swap) rectangle. Acts as
|
|
12
|
+
* the SYMMETRIC value: it sizes both axes unless a per-axis override
|
|
13
|
+
* (`centerRatioX` / `centerRatioY`) is supplied for that axis.
|
|
14
|
+
*/
|
|
15
|
+
centerRatio: number;
|
|
16
|
+
/** Per-axis HORIZONTAL (width) swap-zone fraction; falls back to `centerRatio`. */
|
|
17
|
+
centerRatioX?: number;
|
|
18
|
+
/** Per-axis VERTICAL (height) swap-zone fraction; falls back to `centerRatio`. */
|
|
19
|
+
centerRatioY?: number;
|
|
20
|
+
/** Floor for the center rectangle extent so tiny panes keep a usable swap zone. */
|
|
21
|
+
centerMinPx: number;
|
|
22
|
+
/** Boundary stickiness (pane-local px) used to suppress sub-pixel flicker. */
|
|
23
|
+
hysteresisPx: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The resolver's full drop-intent result for one pane hover: the resolved zone
|
|
27
|
+
* and action plus the geometry/diagnostic fields that explain how it was
|
|
28
|
+
* reached. Emitted (as {@link TilingDropIntentDebugState}) to `onDropIntentChange`.
|
|
29
|
+
*/
|
|
30
|
+
interface TilingDropIntentState {
|
|
31
|
+
/** The hovered leaf this resolution targets. */
|
|
32
|
+
leafId: string;
|
|
33
|
+
/** The resolved drop zone under the cursor. */
|
|
34
|
+
zone: TilingLeafDropZone;
|
|
35
|
+
/** The resolved drop action. */
|
|
36
|
+
action: TilingDropAction;
|
|
37
|
+
/** The nearest edge the cursor points toward (pre-fallback). */
|
|
38
|
+
dominantEdge: TilingEdgeZone;
|
|
39
|
+
/** The edge finally selected after fallbacks, or `null`. */
|
|
40
|
+
finalEdge: TilingEdgeZone | null;
|
|
41
|
+
/** Why the dominant edge was replaced by a fallback, or `null`. */
|
|
42
|
+
fallbackReason: string | null;
|
|
43
|
+
/** Why the action was blocked, or `null` when unblocked. */
|
|
44
|
+
blockedReason: string | null;
|
|
45
|
+
/** Split axes from the root to the target (containment path). */
|
|
46
|
+
axisPath: ReadonlyArray<TilingSplitAxis>;
|
|
47
|
+
/** Edge threshold fraction in effect. */
|
|
48
|
+
edgeThresholdRatio: number;
|
|
49
|
+
/** Center rectangle width (CSS px). */
|
|
50
|
+
centerRectWidthPx: number;
|
|
51
|
+
/** Center rectangle height (CSS px). */
|
|
52
|
+
centerRectHeightPx: number;
|
|
53
|
+
/** Cursor distance to the center rectangle (CSS px). */
|
|
54
|
+
centerDistancePx: number;
|
|
55
|
+
/** Cursor distance to the nearest edge (CSS px). */
|
|
56
|
+
nearestEdgeDistancePx: number;
|
|
57
|
+
/** Pane-local cursor X (CSS px). */
|
|
58
|
+
paneLocalX: number;
|
|
59
|
+
/** Pane-local cursor Y (CSS px). */
|
|
60
|
+
paneLocalY: number;
|
|
61
|
+
/** The ancestor split chosen for a split-container insert, or `null`. */
|
|
62
|
+
targetSplitId: string | null;
|
|
63
|
+
/** Which child slot of that split the insert targets, or `null`. */
|
|
64
|
+
targetSplitPlacement: "first" | "second" | null;
|
|
65
|
+
/** The edge zone selected on the chosen split, or `null`. */
|
|
66
|
+
selectedSplitZone: TilingEdgeZone | null;
|
|
67
|
+
/** Cursor distance to the selected split edge (CSS px), or `null`. */
|
|
68
|
+
selectedSplitDistancePx: number | null;
|
|
69
|
+
/** Reasons candidate splits were rejected during resolution. */
|
|
70
|
+
rejectedSplitReasons: ReadonlyArray<string>;
|
|
71
|
+
/** The tuning knobs that shaped this resolution. */
|
|
72
|
+
tuning: TilingDropIntentTuningState;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The default drop hit-zone geometry: a `0.34` center swap fraction, a `24`px
|
|
76
|
+
* center floor, and `6`px boundary hysteresis. The baseline
|
|
77
|
+
* `dropHitZoneGeometry` capability resolves to these values.
|
|
78
|
+
*/
|
|
79
|
+
declare const TILING_DROP_INTENT_CONFIG: TilingDropIntentBaseConfig;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The resolved hover target the FSM tracks. Structurally a `TilingDropIntentState`
|
|
83
|
+
* (the resolver output the renderer already produces), so the renderer can store
|
|
84
|
+
* the full resolved intent verbatim and the candidate-tree derivation / commit
|
|
85
|
+
* both read the SAME object the preview render reads — no second resolution path.
|
|
86
|
+
*/
|
|
87
|
+
type DragResolvedTarget = TilingDropIntentState;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Public keyboard-binding registry (HT-API-COMMAND-KEYBOARD-SURFACE, half B).
|
|
91
|
+
*
|
|
92
|
+
* The chord→command registration surface — the Hyprland `bind` analog. Distinct
|
|
93
|
+
* from the fixed `TilingKeymap` chord overrides (which only RE-CHORD the built-in
|
|
94
|
+
* action set): a binding maps an ARBITRARY chord to an ARBITRARY `TilingCommand`,
|
|
95
|
+
* so a consumer can wire any shortcut to any tiler action (including programmatic
|
|
96
|
+
* commands like swap / split-ratio).
|
|
97
|
+
*
|
|
98
|
+
* Pure + DOM-less. The renderer's keydown resolves a command in this order:
|
|
99
|
+
* consumer bindings (first match wins, so they augment / override defaults) →
|
|
100
|
+
* default keymap bindings (unless `replaceDefaults`) → the jump-to-pane Alt+1..9
|
|
101
|
+
* family (kept in the keymap path since the digit is dynamic) → capability gate.
|
|
102
|
+
*
|
|
103
|
+
* Cross-ref: `_agent/command-keyboard-api-design.md` §3; `commands.ts`
|
|
104
|
+
* (`keyboardActionToCommand` + `isCommandEnabled`); `pane-switching.ts`
|
|
105
|
+
* (`matchKeyChord` + `matchKeymapAction`).
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The command of the FIRST binding whose chord matches `event` (exact modifier
|
|
110
|
+
* match on the physical `event.code`), or `null` when none match. First-match
|
|
111
|
+
* semantics make binding order significant: an earlier binding wins a chord
|
|
112
|
+
* collision. Capability gating is applied by the caller (`isCommandEnabled`),
|
|
113
|
+
* not here — this is pure chord resolution.
|
|
114
|
+
*/
|
|
115
|
+
declare function matchKeyBinding(event: TilingKeyboardEventLike, bindings: ReadonlyArray<TilingKeyBinding>): TilingCommand | null;
|
|
116
|
+
/**
|
|
117
|
+
* The default chord→command bindings derived from a resolved keymap — the
|
|
118
|
+
* built-in action set expressed as the binding registry (so a consumer can
|
|
119
|
+
* introspect / extend it). The jump-to-pane Alt+1..9 family is intentionally
|
|
120
|
+
* EXCLUDED: its digit is dynamic, so it stays in the `matchKeymapAction` path
|
|
121
|
+
* rather than being enumerated as nine static bindings.
|
|
122
|
+
*/
|
|
123
|
+
declare function defaultKeyBindings(keymap: ResolvedTilingKeymap): ReadonlyArray<TilingKeyBinding>;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* MRU focus history — the pure model behind the "focus current-or-last" toggle
|
|
127
|
+
* (HT-NAV-MRU-FOCUS-TOGGLE; Hyprland `focuscurrentorlast` analog).
|
|
128
|
+
*
|
|
129
|
+
* hypr-tiling cycles a fixed reading-order ring (`resolveCycledPaneId`) with no
|
|
130
|
+
* memory of WHICH pane was focused before the current one. This module adds a
|
|
131
|
+
* most-recently-used stack so a consumer (or the `focus-current-or-last`
|
|
132
|
+
* command) can jump back to the previously-focused pane and toggle between the
|
|
133
|
+
* two — independent of tree order.
|
|
134
|
+
*
|
|
135
|
+
* Pure + DOM-less (the renderer holds the `FocusHistory` in a ref and pushes on
|
|
136
|
+
* every focus change); unit-tested in the `node` jest environment.
|
|
137
|
+
*
|
|
138
|
+
* Cross-ref: `_agent/command-keyboard-api-design.md` §4;
|
|
139
|
+
* `_agent/comparative-analysis/parity-report.md` §5 #8 (MRU focus-toggle gap);
|
|
140
|
+
* `_agent/programme-debt/D-a11y-navigation.md` (HT-NAV-MRU-FOCUS-TOGGLE).
|
|
141
|
+
*/
|
|
142
|
+
/**
|
|
143
|
+
* An ordered most-recently-used focus list. `entries` is oldest-first /
|
|
144
|
+
* MOST-RECENT-LAST; the final entry is the currently-focused pane once it has
|
|
145
|
+
* been pushed. Each leaf id appears at most once (a re-focus moves it to the
|
|
146
|
+
* end rather than duplicating).
|
|
147
|
+
*/
|
|
148
|
+
interface FocusHistory {
|
|
149
|
+
/** Leaf ids in MRU order: oldest-first, most-recently-focused last. */
|
|
150
|
+
readonly entries: ReadonlyArray<string>;
|
|
151
|
+
}
|
|
152
|
+
/** Default cap on retained history entries (older entries are dropped from the front). */
|
|
153
|
+
declare const FOCUS_HISTORY_DEFAULT_LIMIT: number;
|
|
154
|
+
/** An empty focus history (no panes focused yet). */
|
|
155
|
+
declare const EMPTY_FOCUS_HISTORY: FocusHistory;
|
|
156
|
+
/**
|
|
157
|
+
* Push `leafId` as the most-recent focus. If it already appears it is MOVED to
|
|
158
|
+
* the end (de-dupe, not duplicate), so the history stays a clean MRU ordering.
|
|
159
|
+
* The list is capped to `limit` by dropping the oldest (front) entries. A
|
|
160
|
+
* `limit <= 0` clamps to `1` (the current focus is always retained).
|
|
161
|
+
*/
|
|
162
|
+
declare function pushFocusHistory(history: FocusHistory, leafId: string, limit?: number): FocusHistory;
|
|
163
|
+
/**
|
|
164
|
+
* Resolve the "current-or-last" target: the most-recent entry that is NOT
|
|
165
|
+
* `currentLeafId` (the previously-focused distinct pane). Returns `null` when
|
|
166
|
+
* there is no such pane (empty history, or only the current pane is recorded).
|
|
167
|
+
*
|
|
168
|
+
* `currentLeafId == null` returns the most-recent entry outright (no current
|
|
169
|
+
* focus to skip). Because focusing the returned pane pushes it to most-recent,
|
|
170
|
+
* repeated toggles bounce between the two panes naturally.
|
|
171
|
+
*/
|
|
172
|
+
declare function resolveFocusCurrentOrLast(history: FocusHistory, currentLeafId: string | null): string | null;
|
|
173
|
+
/**
|
|
174
|
+
* Drop history entries whose leaf id is no longer present in the live tree
|
|
175
|
+
* (`validLeafIds`), preserving MRU order. Called after a layout change so a
|
|
176
|
+
* removed pane is never returned by `resolveFocusCurrentOrLast`.
|
|
177
|
+
*/
|
|
178
|
+
declare function pruneFocusHistory(history: FocusHistory, validLeafIds: ReadonlyArray<string>): FocusHistory;
|
|
179
|
+
|
|
180
|
+
/** Resolve the sizing mode for a single dimension; undefined defaults to flexible. */
|
|
181
|
+
declare function resolveSizingMode(sizing: TilingPaneSizing | undefined, dimension: TilingDimension): TilingPaneSizingMode;
|
|
182
|
+
/** True when the node is content-sized (static) in the given dimension. */
|
|
183
|
+
declare function isStaticInDimension(node: TilingLayoutNode, dimension: TilingDimension): boolean;
|
|
184
|
+
/**
|
|
185
|
+
* True when the node is static ALONG the split's main axis → it is content-sized
|
|
186
|
+
* along that axis, excluded from the split's ratio, and removes the divider on
|
|
187
|
+
* that boundary.
|
|
188
|
+
*/
|
|
189
|
+
declare function isStaticAlongSplitAxis(node: TilingLayoutNode, axis: TilingSplitAxis): boolean;
|
|
190
|
+
/**
|
|
191
|
+
* True when the node is static on the split's CROSS axis → it content-sizes on
|
|
192
|
+
* the cross axis (no stretch) but still participates in the split-axis ratio.
|
|
193
|
+
*/
|
|
194
|
+
declare function isStaticOnCrossAxis(node: TilingLayoutNode, axis: TilingSplitAxis): boolean;
|
|
195
|
+
/**
|
|
196
|
+
* True when the layout tree contains ANY node declared static in either
|
|
197
|
+
* dimension — a generic whole-tree predicate. NOTE: this is no longer the drag
|
|
198
|
+
* gate. The drag/rearrange gate is now PER-SUBTREE (`drop-validity.ts`
|
|
199
|
+
* `collectStaticGatedLeafIds`) and the footprint geometry is static-aware
|
|
200
|
+
* (`leaf-geometry.ts`), so a pinned static pane no longer freezes the whole tree
|
|
201
|
+
* (HT-SIZING-STATIC-DRAG-GATING). Retained as a reusable predicate.
|
|
202
|
+
*/
|
|
203
|
+
declare function layoutContainsStaticPane(node: TilingLayoutNode): boolean;
|
|
204
|
+
/** Inputs deciding whether a split boundary renders a draggable resize divider. */
|
|
205
|
+
interface SplitBoundaryStaticFlags {
|
|
206
|
+
/** Whether divider resize is enabled for this boundary. */
|
|
207
|
+
resizeEnabled: boolean;
|
|
208
|
+
/** Whether the first child is static along the split axis. */
|
|
209
|
+
firstStaticAlongAxis: boolean;
|
|
210
|
+
/** Whether the second child is static along the split axis. */
|
|
211
|
+
secondStaticAlongAxis: boolean;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* A resize divider is placed ONLY between two boundaries that are both flexible
|
|
215
|
+
* along the split axis. If resize is disabled, or either adjacent child is
|
|
216
|
+
* static along the split axis, no draggable handle is rendered there.
|
|
217
|
+
*/
|
|
218
|
+
declare function shouldRenderSplitDivider({ resizeEnabled, firstStaticAlongAxis, secondStaticAlongAxis, }: SplitBoundaryStaticFlags): boolean;
|
|
219
|
+
/** One child's ratio + static-along-axis flag, input to ratio renormalization. */
|
|
220
|
+
interface FlexibleRatioChild {
|
|
221
|
+
/** The child's declared split-axis ratio. */
|
|
222
|
+
ratio: number;
|
|
223
|
+
/** Whether the child is static along the split axis (weight 0 in distribution). */
|
|
224
|
+
staticAlongAxis: boolean;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Renormalize split-axis ratios over the FLEXIBLE children only. Static children
|
|
228
|
+
* receive weight 0 (content-sized, excluded from distribution); flexible children
|
|
229
|
+
* share `1.0` proportionally to their declared ratios. When the flexible ratios
|
|
230
|
+
* sum to zero (or there are no positive ratios), flexible children split evenly.
|
|
231
|
+
*/
|
|
232
|
+
declare function renormalizeFlexibleRatios(children: ReadonlyArray<FlexibleRatioChild>): number[];
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Custom-rendered drag cursor (interaction tier "c"). A single `position: fixed`
|
|
236
|
+
* sibling of the cursor-following ghost (`DragPaneOverlay`) that REPLACES the OS
|
|
237
|
+
* cursor during an active live drag, transform-pinned to the pointer in the same
|
|
238
|
+
* coalesced rAF/render path as the ghost so it never lags the hardware cursor.
|
|
239
|
+
*
|
|
240
|
+
* This module is the PURE, DOM-less core: it maps the drag FSM's resolved target
|
|
241
|
+
* (`DragResolvedTarget` = the resolver's `TilingDropIntentState`) plus the drop
|
|
242
|
+
* validity onto a small SEMANTIC presentation descriptor — the OPERATION the
|
|
243
|
+
* release would perform (grab / insert / swap) or its rejection (invalid) — NOT
|
|
244
|
+
* an edge direction. The found slot itself already shows where the pane lands;
|
|
245
|
+
* the cursor only confirms what kind of drop is under the pointer. The renderer's
|
|
246
|
+
* `DragCursorOverlay` consumes these outputs and owns the actual SVG/Tailwind +
|
|
247
|
+
* reduced-motion transitions.
|
|
248
|
+
*/
|
|
249
|
+
/**
|
|
250
|
+
* The semantic cursor states, driven by the drag FSM + resolver operation type +
|
|
251
|
+
* validity (NOT by edge direction):
|
|
252
|
+
* - `grab` — dragging with no committable target (ghost free-following) OR
|
|
253
|
+
* hovering the drag source itself; neutral "carrying" look.
|
|
254
|
+
* - `insert` — a committable edge-insert slot is resolved; a "drop/place here"
|
|
255
|
+
* target affordance in the valid accent color. No direction — the found slot
|
|
256
|
+
* already shows where the pane lands.
|
|
257
|
+
* - `swap` — a committable center/swap target is resolved; a distinct exchange
|
|
258
|
+
* indicator in the valid accent color (swap is a different operation).
|
|
259
|
+
* - `invalid` — the hovered target is rejected (`blockedReason` set); a
|
|
260
|
+
* `not-allowed`-style indicator in the warning color.
|
|
261
|
+
*/
|
|
262
|
+
type DragCursorKind = "grab" | "insert" | "swap" | "invalid";
|
|
263
|
+
/** Color tone the cursor adopts, derived from drop validity. */
|
|
264
|
+
type DragCursorTone = "neutral" | "valid" | "invalid";
|
|
265
|
+
/** The semantic presentation of the custom drag cursor: its state plus its tone. */
|
|
266
|
+
interface DragCursorPresentation {
|
|
267
|
+
/** The semantic operation/validity state the cursor conveys (drives the glyph). */
|
|
268
|
+
kind: DragCursorKind;
|
|
269
|
+
/** Validity tone the cursor adopts (drives the color). */
|
|
270
|
+
tone: DragCursorTone;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Derive the custom cursor's semantic presentation from the FSM-resolved target +
|
|
274
|
+
* the drag source. Pure (no DOM, no time) so the operation+validity → kind
|
|
275
|
+
* mapping is unit-testable. Precedence mirrors the commit gate
|
|
276
|
+
* (`isCommittableTarget`) so the cursor's "valid" look is shown for EXACTLY the
|
|
277
|
+
* targets a release would commit:
|
|
278
|
+
* - no target / self-target → `grab` (neutral).
|
|
279
|
+
* - committable `swap` (center) → `swap` (valid).
|
|
280
|
+
* - committable `edge-insert` (a resolved, valid edge) → `insert` (valid).
|
|
281
|
+
* - otherwise, a rejected hovered target (`blockedReason` set) → `invalid`.
|
|
282
|
+
* - any remaining non-committable, non-blocked hover → `grab` (neutral).
|
|
283
|
+
*/
|
|
284
|
+
declare function resolveDragCursorPresentation(resolvedTarget: DragResolvedTarget | null, sourceLeafId: string): DragCursorPresentation;
|
|
285
|
+
/** A pointer point in viewport (client) coordinates. */
|
|
286
|
+
interface DragCursorPoint {
|
|
287
|
+
/** Client X (CSS px). */
|
|
288
|
+
x: number;
|
|
289
|
+
/** Client Y (CSS px). */
|
|
290
|
+
y: number;
|
|
291
|
+
}
|
|
292
|
+
/** Viewport edge bounds (client coords) used to clamp the pinned cursor point. */
|
|
293
|
+
interface DragCursorViewportBounds {
|
|
294
|
+
/** Left edge (client X). */
|
|
295
|
+
left: number;
|
|
296
|
+
/** Top edge (client Y). */
|
|
297
|
+
top: number;
|
|
298
|
+
/** Right edge (client X). */
|
|
299
|
+
right: number;
|
|
300
|
+
/** Bottom edge (client Y). */
|
|
301
|
+
bottom: number;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Clamp the pinned pointer point so the custom cursor element stays fully within
|
|
305
|
+
* the viewport at the edges — the analog of the ghost overlay's off-viewport
|
|
306
|
+
* clamp. `marginPx` reserves room for the cursor element's own extent (so the
|
|
307
|
+
* badge at the right/bottom edge is not clipped). When the bounds are narrower
|
|
308
|
+
* than `2 * marginPx` on an axis (degenerate / tiny viewport), the point snaps
|
|
309
|
+
* to that axis's midpoint rather than inverting. Pure so the clamp is testable
|
|
310
|
+
* without a DOM.
|
|
311
|
+
*/
|
|
312
|
+
declare function clampCursorPointToViewport(point: DragCursorPoint, bounds: DragCursorViewportBounds, marginPx: number): DragCursorPoint;
|
|
313
|
+
|
|
314
|
+
export { type DragCursorKind, type DragCursorPoint, type DragCursorPresentation, type DragCursorTone, type DragCursorViewportBounds, type DragResolvedTarget, EMPTY_FOCUS_HISTORY, FOCUS_HISTORY_DEFAULT_LIMIT, type FlexibleRatioChild, type FocusHistory, type SplitBoundaryStaticFlags, TILING_DROP_INTENT_CONFIG, TilingDimension, type TilingDropIntentBaseConfig, type TilingDropIntentState, type TilingEdgeZone, TilingKeyboardEventLike, clampCursorPointToViewport, defaultKeyBindings, isStaticAlongSplitAxis, isStaticInDimension, isStaticOnCrossAxis, layoutContainsStaticPane, matchKeyBinding, pruneFocusHistory, pushFocusHistory, renormalizeFlexibleRatios, resolveDragCursorPresentation, resolveFocusCurrentOrLast, resolveSizingMode, shouldRenderSplitDivider };
|
package/dist/engine.d.ts
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
export { G as GroupLeavesOptions, M as MULTI_SELECT_GROUP_MIN_MEMBERS, T as TILING_KEYMAP_DEFAULTS, a as TilingKeymapActionGuards, c as canGroupMultiSelection, b as chordRequiresModifier, d as collectGroups, e as collectSplitNodes, f as commandRequiredCapability, g as findLeafByDirection, h as findLeafById, i as groupLeaves, j as hasAnyModifier, k as insertLeafAdjacent, l as isCssEasing, m as isResizeAxisEnabled, n as isStructurallyValidLayout, o as keyboardActionToCommand, p as matchKeyChord, q as matchKeymapAction, r as moveLeafToRoot, s as moveLeafToSplitContainer, t as pruneMultiSelection, u as readLeafNodeIds, v as removeLeafTile, w as resolveDragEasing, x as resolveKeymap, y as resolveMaximizeToggle, z as resolveMultiSelectGroupCommand, A as resolveMultiSelectGroupHost, B as setLeafSizing, C as siblingSubtreeForLeaf, D as swapLeafTiles, E as tileOrderByLeafId, F as toggleLeafMultiSelection, H as toggleSplitAxis, I as ungroupNode, J as updateSplitRatio } from './drag-easing-5WbK3T82.js';
|
|
2
|
+
import { r as TilingLeafDropZone, s as TilingDropAction, t as TilingSplitAxis, j as TilingDropIntentTuningState, u as ResolvedTilingKeymap, v as TilingKeyBinding, w as TilingKeyboardEventLike, x as TilingCommand, T as TilingLayoutNode, y as TilingDimension, z as TilingPaneSizing, A as TilingPaneSizingMode } from './tiling-renderer-kTlSm4H4.js';
|
|
3
|
+
export { B as BASELINE_DRAG_HOP_DURATION_MS, I as INSTANT_DRAG_DURATION_MS, C as TilingAccentHue, D as TilingKeyboardAction, E as TilingKeyboardModifierState, F as TilingMoveModeState, G as TilingPaneSwitcherState, H as accentHue } from './tiling-renderer-kTlSm4H4.js';
|
|
4
|
+
import 'react';
|
|
5
|
+
|
|
6
|
+
/** A pane's four directional insert edges (the drop zones excluding `"center"`). */
|
|
7
|
+
type TilingEdgeZone = Exclude<TilingLeafDropZone, "center">;
|
|
8
|
+
/** Base drop hit-zone geometry: center swap fraction, floor, and hysteresis. */
|
|
9
|
+
interface TilingDropIntentBaseConfig {
|
|
10
|
+
/**
|
|
11
|
+
* Fraction of each pane axis spanned by the center (swap) rectangle. Acts as
|
|
12
|
+
* the SYMMETRIC value: it sizes both axes unless a per-axis override
|
|
13
|
+
* (`centerRatioX` / `centerRatioY`) is supplied for that axis.
|
|
14
|
+
*/
|
|
15
|
+
centerRatio: number;
|
|
16
|
+
/** Per-axis HORIZONTAL (width) swap-zone fraction; falls back to `centerRatio`. */
|
|
17
|
+
centerRatioX?: number;
|
|
18
|
+
/** Per-axis VERTICAL (height) swap-zone fraction; falls back to `centerRatio`. */
|
|
19
|
+
centerRatioY?: number;
|
|
20
|
+
/** Floor for the center rectangle extent so tiny panes keep a usable swap zone. */
|
|
21
|
+
centerMinPx: number;
|
|
22
|
+
/** Boundary stickiness (pane-local px) used to suppress sub-pixel flicker. */
|
|
23
|
+
hysteresisPx: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The resolver's full drop-intent result for one pane hover: the resolved zone
|
|
27
|
+
* and action plus the geometry/diagnostic fields that explain how it was
|
|
28
|
+
* reached. Emitted (as {@link TilingDropIntentDebugState}) to `onDropIntentChange`.
|
|
29
|
+
*/
|
|
30
|
+
interface TilingDropIntentState {
|
|
31
|
+
/** The hovered leaf this resolution targets. */
|
|
32
|
+
leafId: string;
|
|
33
|
+
/** The resolved drop zone under the cursor. */
|
|
34
|
+
zone: TilingLeafDropZone;
|
|
35
|
+
/** The resolved drop action. */
|
|
36
|
+
action: TilingDropAction;
|
|
37
|
+
/** The nearest edge the cursor points toward (pre-fallback). */
|
|
38
|
+
dominantEdge: TilingEdgeZone;
|
|
39
|
+
/** The edge finally selected after fallbacks, or `null`. */
|
|
40
|
+
finalEdge: TilingEdgeZone | null;
|
|
41
|
+
/** Why the dominant edge was replaced by a fallback, or `null`. */
|
|
42
|
+
fallbackReason: string | null;
|
|
43
|
+
/** Why the action was blocked, or `null` when unblocked. */
|
|
44
|
+
blockedReason: string | null;
|
|
45
|
+
/** Split axes from the root to the target (containment path). */
|
|
46
|
+
axisPath: ReadonlyArray<TilingSplitAxis>;
|
|
47
|
+
/** Edge threshold fraction in effect. */
|
|
48
|
+
edgeThresholdRatio: number;
|
|
49
|
+
/** Center rectangle width (CSS px). */
|
|
50
|
+
centerRectWidthPx: number;
|
|
51
|
+
/** Center rectangle height (CSS px). */
|
|
52
|
+
centerRectHeightPx: number;
|
|
53
|
+
/** Cursor distance to the center rectangle (CSS px). */
|
|
54
|
+
centerDistancePx: number;
|
|
55
|
+
/** Cursor distance to the nearest edge (CSS px). */
|
|
56
|
+
nearestEdgeDistancePx: number;
|
|
57
|
+
/** Pane-local cursor X (CSS px). */
|
|
58
|
+
paneLocalX: number;
|
|
59
|
+
/** Pane-local cursor Y (CSS px). */
|
|
60
|
+
paneLocalY: number;
|
|
61
|
+
/** The ancestor split chosen for a split-container insert, or `null`. */
|
|
62
|
+
targetSplitId: string | null;
|
|
63
|
+
/** Which child slot of that split the insert targets, or `null`. */
|
|
64
|
+
targetSplitPlacement: "first" | "second" | null;
|
|
65
|
+
/** The edge zone selected on the chosen split, or `null`. */
|
|
66
|
+
selectedSplitZone: TilingEdgeZone | null;
|
|
67
|
+
/** Cursor distance to the selected split edge (CSS px), or `null`. */
|
|
68
|
+
selectedSplitDistancePx: number | null;
|
|
69
|
+
/** Reasons candidate splits were rejected during resolution. */
|
|
70
|
+
rejectedSplitReasons: ReadonlyArray<string>;
|
|
71
|
+
/** The tuning knobs that shaped this resolution. */
|
|
72
|
+
tuning: TilingDropIntentTuningState;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The default drop hit-zone geometry: a `0.34` center swap fraction, a `24`px
|
|
76
|
+
* center floor, and `6`px boundary hysteresis. The baseline
|
|
77
|
+
* `dropHitZoneGeometry` capability resolves to these values.
|
|
78
|
+
*/
|
|
79
|
+
declare const TILING_DROP_INTENT_CONFIG: TilingDropIntentBaseConfig;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The resolved hover target the FSM tracks. Structurally a `TilingDropIntentState`
|
|
83
|
+
* (the resolver output the renderer already produces), so the renderer can store
|
|
84
|
+
* the full resolved intent verbatim and the candidate-tree derivation / commit
|
|
85
|
+
* both read the SAME object the preview render reads — no second resolution path.
|
|
86
|
+
*/
|
|
87
|
+
type DragResolvedTarget = TilingDropIntentState;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Public keyboard-binding registry (HT-API-COMMAND-KEYBOARD-SURFACE, half B).
|
|
91
|
+
*
|
|
92
|
+
* The chord→command registration surface — the Hyprland `bind` analog. Distinct
|
|
93
|
+
* from the fixed `TilingKeymap` chord overrides (which only RE-CHORD the built-in
|
|
94
|
+
* action set): a binding maps an ARBITRARY chord to an ARBITRARY `TilingCommand`,
|
|
95
|
+
* so a consumer can wire any shortcut to any tiler action (including programmatic
|
|
96
|
+
* commands like swap / split-ratio).
|
|
97
|
+
*
|
|
98
|
+
* Pure + DOM-less. The renderer's keydown resolves a command in this order:
|
|
99
|
+
* consumer bindings (first match wins, so they augment / override defaults) →
|
|
100
|
+
* default keymap bindings (unless `replaceDefaults`) → the jump-to-pane Alt+1..9
|
|
101
|
+
* family (kept in the keymap path since the digit is dynamic) → capability gate.
|
|
102
|
+
*
|
|
103
|
+
* Cross-ref: `_agent/command-keyboard-api-design.md` §3; `commands.ts`
|
|
104
|
+
* (`keyboardActionToCommand` + `isCommandEnabled`); `pane-switching.ts`
|
|
105
|
+
* (`matchKeyChord` + `matchKeymapAction`).
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The command of the FIRST binding whose chord matches `event` (exact modifier
|
|
110
|
+
* match on the physical `event.code`), or `null` when none match. First-match
|
|
111
|
+
* semantics make binding order significant: an earlier binding wins a chord
|
|
112
|
+
* collision. Capability gating is applied by the caller (`isCommandEnabled`),
|
|
113
|
+
* not here — this is pure chord resolution.
|
|
114
|
+
*/
|
|
115
|
+
declare function matchKeyBinding(event: TilingKeyboardEventLike, bindings: ReadonlyArray<TilingKeyBinding>): TilingCommand | null;
|
|
116
|
+
/**
|
|
117
|
+
* The default chord→command bindings derived from a resolved keymap — the
|
|
118
|
+
* built-in action set expressed as the binding registry (so a consumer can
|
|
119
|
+
* introspect / extend it). The jump-to-pane Alt+1..9 family is intentionally
|
|
120
|
+
* EXCLUDED: its digit is dynamic, so it stays in the `matchKeymapAction` path
|
|
121
|
+
* rather than being enumerated as nine static bindings.
|
|
122
|
+
*/
|
|
123
|
+
declare function defaultKeyBindings(keymap: ResolvedTilingKeymap): ReadonlyArray<TilingKeyBinding>;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* MRU focus history — the pure model behind the "focus current-or-last" toggle
|
|
127
|
+
* (HT-NAV-MRU-FOCUS-TOGGLE; Hyprland `focuscurrentorlast` analog).
|
|
128
|
+
*
|
|
129
|
+
* hypr-tiling cycles a fixed reading-order ring (`resolveCycledPaneId`) with no
|
|
130
|
+
* memory of WHICH pane was focused before the current one. This module adds a
|
|
131
|
+
* most-recently-used stack so a consumer (or the `focus-current-or-last`
|
|
132
|
+
* command) can jump back to the previously-focused pane and toggle between the
|
|
133
|
+
* two — independent of tree order.
|
|
134
|
+
*
|
|
135
|
+
* Pure + DOM-less (the renderer holds the `FocusHistory` in a ref and pushes on
|
|
136
|
+
* every focus change); unit-tested in the `node` jest environment.
|
|
137
|
+
*
|
|
138
|
+
* Cross-ref: `_agent/command-keyboard-api-design.md` §4;
|
|
139
|
+
* `_agent/comparative-analysis/parity-report.md` §5 #8 (MRU focus-toggle gap);
|
|
140
|
+
* `_agent/programme-debt/D-a11y-navigation.md` (HT-NAV-MRU-FOCUS-TOGGLE).
|
|
141
|
+
*/
|
|
142
|
+
/**
|
|
143
|
+
* An ordered most-recently-used focus list. `entries` is oldest-first /
|
|
144
|
+
* MOST-RECENT-LAST; the final entry is the currently-focused pane once it has
|
|
145
|
+
* been pushed. Each leaf id appears at most once (a re-focus moves it to the
|
|
146
|
+
* end rather than duplicating).
|
|
147
|
+
*/
|
|
148
|
+
interface FocusHistory {
|
|
149
|
+
/** Leaf ids in MRU order: oldest-first, most-recently-focused last. */
|
|
150
|
+
readonly entries: ReadonlyArray<string>;
|
|
151
|
+
}
|
|
152
|
+
/** Default cap on retained history entries (older entries are dropped from the front). */
|
|
153
|
+
declare const FOCUS_HISTORY_DEFAULT_LIMIT: number;
|
|
154
|
+
/** An empty focus history (no panes focused yet). */
|
|
155
|
+
declare const EMPTY_FOCUS_HISTORY: FocusHistory;
|
|
156
|
+
/**
|
|
157
|
+
* Push `leafId` as the most-recent focus. If it already appears it is MOVED to
|
|
158
|
+
* the end (de-dupe, not duplicate), so the history stays a clean MRU ordering.
|
|
159
|
+
* The list is capped to `limit` by dropping the oldest (front) entries. A
|
|
160
|
+
* `limit <= 0` clamps to `1` (the current focus is always retained).
|
|
161
|
+
*/
|
|
162
|
+
declare function pushFocusHistory(history: FocusHistory, leafId: string, limit?: number): FocusHistory;
|
|
163
|
+
/**
|
|
164
|
+
* Resolve the "current-or-last" target: the most-recent entry that is NOT
|
|
165
|
+
* `currentLeafId` (the previously-focused distinct pane). Returns `null` when
|
|
166
|
+
* there is no such pane (empty history, or only the current pane is recorded).
|
|
167
|
+
*
|
|
168
|
+
* `currentLeafId == null` returns the most-recent entry outright (no current
|
|
169
|
+
* focus to skip). Because focusing the returned pane pushes it to most-recent,
|
|
170
|
+
* repeated toggles bounce between the two panes naturally.
|
|
171
|
+
*/
|
|
172
|
+
declare function resolveFocusCurrentOrLast(history: FocusHistory, currentLeafId: string | null): string | null;
|
|
173
|
+
/**
|
|
174
|
+
* Drop history entries whose leaf id is no longer present in the live tree
|
|
175
|
+
* (`validLeafIds`), preserving MRU order. Called after a layout change so a
|
|
176
|
+
* removed pane is never returned by `resolveFocusCurrentOrLast`.
|
|
177
|
+
*/
|
|
178
|
+
declare function pruneFocusHistory(history: FocusHistory, validLeafIds: ReadonlyArray<string>): FocusHistory;
|
|
179
|
+
|
|
180
|
+
/** Resolve the sizing mode for a single dimension; undefined defaults to flexible. */
|
|
181
|
+
declare function resolveSizingMode(sizing: TilingPaneSizing | undefined, dimension: TilingDimension): TilingPaneSizingMode;
|
|
182
|
+
/** True when the node is content-sized (static) in the given dimension. */
|
|
183
|
+
declare function isStaticInDimension(node: TilingLayoutNode, dimension: TilingDimension): boolean;
|
|
184
|
+
/**
|
|
185
|
+
* True when the node is static ALONG the split's main axis → it is content-sized
|
|
186
|
+
* along that axis, excluded from the split's ratio, and removes the divider on
|
|
187
|
+
* that boundary.
|
|
188
|
+
*/
|
|
189
|
+
declare function isStaticAlongSplitAxis(node: TilingLayoutNode, axis: TilingSplitAxis): boolean;
|
|
190
|
+
/**
|
|
191
|
+
* True when the node is static on the split's CROSS axis → it content-sizes on
|
|
192
|
+
* the cross axis (no stretch) but still participates in the split-axis ratio.
|
|
193
|
+
*/
|
|
194
|
+
declare function isStaticOnCrossAxis(node: TilingLayoutNode, axis: TilingSplitAxis): boolean;
|
|
195
|
+
/**
|
|
196
|
+
* True when the layout tree contains ANY node declared static in either
|
|
197
|
+
* dimension — a generic whole-tree predicate. NOTE: this is no longer the drag
|
|
198
|
+
* gate. The drag/rearrange gate is now PER-SUBTREE (`drop-validity.ts`
|
|
199
|
+
* `collectStaticGatedLeafIds`) and the footprint geometry is static-aware
|
|
200
|
+
* (`leaf-geometry.ts`), so a pinned static pane no longer freezes the whole tree
|
|
201
|
+
* (HT-SIZING-STATIC-DRAG-GATING). Retained as a reusable predicate.
|
|
202
|
+
*/
|
|
203
|
+
declare function layoutContainsStaticPane(node: TilingLayoutNode): boolean;
|
|
204
|
+
/** Inputs deciding whether a split boundary renders a draggable resize divider. */
|
|
205
|
+
interface SplitBoundaryStaticFlags {
|
|
206
|
+
/** Whether divider resize is enabled for this boundary. */
|
|
207
|
+
resizeEnabled: boolean;
|
|
208
|
+
/** Whether the first child is static along the split axis. */
|
|
209
|
+
firstStaticAlongAxis: boolean;
|
|
210
|
+
/** Whether the second child is static along the split axis. */
|
|
211
|
+
secondStaticAlongAxis: boolean;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* A resize divider is placed ONLY between two boundaries that are both flexible
|
|
215
|
+
* along the split axis. If resize is disabled, or either adjacent child is
|
|
216
|
+
* static along the split axis, no draggable handle is rendered there.
|
|
217
|
+
*/
|
|
218
|
+
declare function shouldRenderSplitDivider({ resizeEnabled, firstStaticAlongAxis, secondStaticAlongAxis, }: SplitBoundaryStaticFlags): boolean;
|
|
219
|
+
/** One child's ratio + static-along-axis flag, input to ratio renormalization. */
|
|
220
|
+
interface FlexibleRatioChild {
|
|
221
|
+
/** The child's declared split-axis ratio. */
|
|
222
|
+
ratio: number;
|
|
223
|
+
/** Whether the child is static along the split axis (weight 0 in distribution). */
|
|
224
|
+
staticAlongAxis: boolean;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Renormalize split-axis ratios over the FLEXIBLE children only. Static children
|
|
228
|
+
* receive weight 0 (content-sized, excluded from distribution); flexible children
|
|
229
|
+
* share `1.0` proportionally to their declared ratios. When the flexible ratios
|
|
230
|
+
* sum to zero (or there are no positive ratios), flexible children split evenly.
|
|
231
|
+
*/
|
|
232
|
+
declare function renormalizeFlexibleRatios(children: ReadonlyArray<FlexibleRatioChild>): number[];
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Custom-rendered drag cursor (interaction tier "c"). A single `position: fixed`
|
|
236
|
+
* sibling of the cursor-following ghost (`DragPaneOverlay`) that REPLACES the OS
|
|
237
|
+
* cursor during an active live drag, transform-pinned to the pointer in the same
|
|
238
|
+
* coalesced rAF/render path as the ghost so it never lags the hardware cursor.
|
|
239
|
+
*
|
|
240
|
+
* This module is the PURE, DOM-less core: it maps the drag FSM's resolved target
|
|
241
|
+
* (`DragResolvedTarget` = the resolver's `TilingDropIntentState`) plus the drop
|
|
242
|
+
* validity onto a small SEMANTIC presentation descriptor — the OPERATION the
|
|
243
|
+
* release would perform (grab / insert / swap) or its rejection (invalid) — NOT
|
|
244
|
+
* an edge direction. The found slot itself already shows where the pane lands;
|
|
245
|
+
* the cursor only confirms what kind of drop is under the pointer. The renderer's
|
|
246
|
+
* `DragCursorOverlay` consumes these outputs and owns the actual SVG/Tailwind +
|
|
247
|
+
* reduced-motion transitions.
|
|
248
|
+
*/
|
|
249
|
+
/**
|
|
250
|
+
* The semantic cursor states, driven by the drag FSM + resolver operation type +
|
|
251
|
+
* validity (NOT by edge direction):
|
|
252
|
+
* - `grab` — dragging with no committable target (ghost free-following) OR
|
|
253
|
+
* hovering the drag source itself; neutral "carrying" look.
|
|
254
|
+
* - `insert` — a committable edge-insert slot is resolved; a "drop/place here"
|
|
255
|
+
* target affordance in the valid accent color. No direction — the found slot
|
|
256
|
+
* already shows where the pane lands.
|
|
257
|
+
* - `swap` — a committable center/swap target is resolved; a distinct exchange
|
|
258
|
+
* indicator in the valid accent color (swap is a different operation).
|
|
259
|
+
* - `invalid` — the hovered target is rejected (`blockedReason` set); a
|
|
260
|
+
* `not-allowed`-style indicator in the warning color.
|
|
261
|
+
*/
|
|
262
|
+
type DragCursorKind = "grab" | "insert" | "swap" | "invalid";
|
|
263
|
+
/** Color tone the cursor adopts, derived from drop validity. */
|
|
264
|
+
type DragCursorTone = "neutral" | "valid" | "invalid";
|
|
265
|
+
/** The semantic presentation of the custom drag cursor: its state plus its tone. */
|
|
266
|
+
interface DragCursorPresentation {
|
|
267
|
+
/** The semantic operation/validity state the cursor conveys (drives the glyph). */
|
|
268
|
+
kind: DragCursorKind;
|
|
269
|
+
/** Validity tone the cursor adopts (drives the color). */
|
|
270
|
+
tone: DragCursorTone;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Derive the custom cursor's semantic presentation from the FSM-resolved target +
|
|
274
|
+
* the drag source. Pure (no DOM, no time) so the operation+validity → kind
|
|
275
|
+
* mapping is unit-testable. Precedence mirrors the commit gate
|
|
276
|
+
* (`isCommittableTarget`) so the cursor's "valid" look is shown for EXACTLY the
|
|
277
|
+
* targets a release would commit:
|
|
278
|
+
* - no target / self-target → `grab` (neutral).
|
|
279
|
+
* - committable `swap` (center) → `swap` (valid).
|
|
280
|
+
* - committable `edge-insert` (a resolved, valid edge) → `insert` (valid).
|
|
281
|
+
* - otherwise, a rejected hovered target (`blockedReason` set) → `invalid`.
|
|
282
|
+
* - any remaining non-committable, non-blocked hover → `grab` (neutral).
|
|
283
|
+
*/
|
|
284
|
+
declare function resolveDragCursorPresentation(resolvedTarget: DragResolvedTarget | null, sourceLeafId: string): DragCursorPresentation;
|
|
285
|
+
/** A pointer point in viewport (client) coordinates. */
|
|
286
|
+
interface DragCursorPoint {
|
|
287
|
+
/** Client X (CSS px). */
|
|
288
|
+
x: number;
|
|
289
|
+
/** Client Y (CSS px). */
|
|
290
|
+
y: number;
|
|
291
|
+
}
|
|
292
|
+
/** Viewport edge bounds (client coords) used to clamp the pinned cursor point. */
|
|
293
|
+
interface DragCursorViewportBounds {
|
|
294
|
+
/** Left edge (client X). */
|
|
295
|
+
left: number;
|
|
296
|
+
/** Top edge (client Y). */
|
|
297
|
+
top: number;
|
|
298
|
+
/** Right edge (client X). */
|
|
299
|
+
right: number;
|
|
300
|
+
/** Bottom edge (client Y). */
|
|
301
|
+
bottom: number;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Clamp the pinned pointer point so the custom cursor element stays fully within
|
|
305
|
+
* the viewport at the edges — the analog of the ghost overlay's off-viewport
|
|
306
|
+
* clamp. `marginPx` reserves room for the cursor element's own extent (so the
|
|
307
|
+
* badge at the right/bottom edge is not clipped). When the bounds are narrower
|
|
308
|
+
* than `2 * marginPx` on an axis (degenerate / tiny viewport), the point snaps
|
|
309
|
+
* to that axis's midpoint rather than inverting. Pure so the clamp is testable
|
|
310
|
+
* without a DOM.
|
|
311
|
+
*/
|
|
312
|
+
declare function clampCursorPointToViewport(point: DragCursorPoint, bounds: DragCursorViewportBounds, marginPx: number): DragCursorPoint;
|
|
313
|
+
|
|
314
|
+
export { type DragCursorKind, type DragCursorPoint, type DragCursorPresentation, type DragCursorTone, type DragCursorViewportBounds, type DragResolvedTarget, EMPTY_FOCUS_HISTORY, FOCUS_HISTORY_DEFAULT_LIMIT, type FlexibleRatioChild, type FocusHistory, type SplitBoundaryStaticFlags, TILING_DROP_INTENT_CONFIG, TilingDimension, type TilingDropIntentBaseConfig, type TilingDropIntentState, type TilingEdgeZone, TilingKeyboardEventLike, clampCursorPointToViewport, defaultKeyBindings, isStaticAlongSplitAxis, isStaticInDimension, isStaticOnCrossAxis, layoutContainsStaticPane, matchKeyBinding, pruneFocusHistory, pushFocusHistory, renormalizeFlexibleRatios, resolveDragCursorPresentation, resolveFocusCurrentOrLast, resolveSizingMode, shouldRenderSplitDivider };
|