Replace drag-promote gesture with Ctrl+Shift+P keyboard shortcut
This commit is contained in:
parent
8e4a358aa8
commit
5085326cb1
6 changed files with 142 additions and 373 deletions
54
src/App.tsx
54
src/App.tsx
|
|
@ -18,7 +18,6 @@ import {
|
|||
type Orientation,
|
||||
type LeafNode,
|
||||
type LeafShellSpec,
|
||||
type Box,
|
||||
newLeaf,
|
||||
splitLeaf,
|
||||
closeLeaf,
|
||||
|
|
@ -36,7 +35,7 @@ import {
|
|||
updateSplitRatio,
|
||||
swapLeaves,
|
||||
findNeighborInDirection,
|
||||
promoteFromGutter,
|
||||
promoteLeaf,
|
||||
MIN_PANE_PX,
|
||||
type Direction,
|
||||
serialize,
|
||||
|
|
@ -260,6 +259,22 @@ export default function App() {
|
|||
setTree((t) => toggleBroadcastInTree(t, leafId));
|
||||
}, []);
|
||||
|
||||
// Ctrl+Shift+P: pop the active leaf out one level. The keyboard
|
||||
// replacement for the (removed) drag-past-sibling gesture. No-op with a
|
||||
// toast if the leaf is at the root or its parent shares orientation
|
||||
// with the grandparent — no perpendicular promotion available.
|
||||
const promoteActive = useCallback(
|
||||
(leafId: NodeId) => {
|
||||
const next = promoteLeaf(treeRef.current, leafId);
|
||||
if (next === null) {
|
||||
notify("Pane can't be promoted (no perpendicular split above it)");
|
||||
return;
|
||||
}
|
||||
setTree(next);
|
||||
},
|
||||
[notify],
|
||||
);
|
||||
|
||||
const setActive = useCallback((leafId: NodeId) => {
|
||||
setActiveLeafId(leafId);
|
||||
}, []);
|
||||
|
|
@ -415,12 +430,16 @@ export default function App() {
|
|||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
toggleBroadcast(activeLeafId);
|
||||
} else if (key === "p") {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
promoteActive(activeLeafId);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("keydown", onKey, true);
|
||||
return () => window.removeEventListener("keydown", onKey, true);
|
||||
}, [split, close, toggleBroadcast]);
|
||||
}, [split, close, toggleBroadcast, promoteActive]);
|
||||
|
||||
const registerPaneId = useCallback(
|
||||
(leafId: NodeId, paneId: PaneId | null) => {
|
||||
|
|
@ -586,18 +605,6 @@ export default function App() {
|
|||
setTree((t) => updateSplitRatio(t, splitId, ratio));
|
||||
}, []);
|
||||
|
||||
// ---- promote-out gesture state -----------------------------------------
|
||||
// armedPromotionBox is non-null while the user is mid-drag and past the
|
||||
// 75% threshold on a sibling pane. We render a translucent preview at
|
||||
// that position so the user knows what releasing will do.
|
||||
const [armedPromotionBox, setArmedPromotionBox] = useState<Box | null>(null);
|
||||
const onGutterArmedChange = useCallback((box: Box | null) => {
|
||||
setArmedPromotionBox(box);
|
||||
}, []);
|
||||
const onGutterPromote = useCallback((splitId: NodeId) => {
|
||||
setTree((t) => promoteFromGutter(t, splitId) ?? t);
|
||||
}, []);
|
||||
|
||||
// ---- global broadcast state (derived from tree) -------------------------
|
||||
const broadcastStats = useMemo(() => {
|
||||
let on = 0;
|
||||
|
|
@ -742,25 +749,8 @@ export default function App() {
|
|||
info={g}
|
||||
containerRef={paneWrapRef}
|
||||
onRatioChange={onGutterRatio}
|
||||
onArmedChange={onGutterArmedChange}
|
||||
onPromote={onGutterPromote}
|
||||
/>
|
||||
))}
|
||||
{armedPromotionBox && (
|
||||
<div
|
||||
className="promote-preview"
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: `${armedPromotionBox.top * 100}%`,
|
||||
left: `${armedPromotionBox.left * 100}%`,
|
||||
width: `${armedPromotionBox.width * 100}%`,
|
||||
height: `${armedPromotionBox.height * 100}%`,
|
||||
pointerEvents: "none",
|
||||
zIndex: 20,
|
||||
}}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
</OrchestrationProvider>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue