Skip to content

Commit 297b575

Browse files
committed
feat: improve selectUpTo anchor item (#176)
1 parent 7158afe commit 297b575

File tree

3 files changed

+21
-2
lines changed

3 files changed

+21
-2
lines changed

.changeset/slimy-years-cross.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@headless-tree/core": minor
3+
---
4+
5+
The anchor for shift-selecting (`item.selectUpTo()`) is now the last item that was clicked while not holding shift, or alternatively the focused item if that didn't exist. The previous behavior was always using the focused item as anchor, which doesn't match common multi-select behaviors in similar applications (#176)

packages/core/src/features/selection/feature.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { FeatureImplementation } from "../../types/core";
22
import { makeStateUpdater } from "../../utils";
3+
import type { SelectionDataRef } from "./types";
34

45
export const selectionFeature: FeatureImplementation = {
56
key: "selection",
@@ -50,8 +51,12 @@ export const selectionFeature: FeatureImplementation = {
5051

5152
selectUpTo: ({ tree, item }, ctrl: boolean) => {
5253
const indexA = item.getItemMeta().index;
53-
// TODO dont use focused item as anchor, but last primary-clicked item
54-
const indexB = tree.getFocusedItem().getItemMeta().index;
54+
const { selectUpToAnchorId } =
55+
tree.getDataRef<SelectionDataRef>().current;
56+
const itemB = selectUpToAnchorId
57+
? tree.getItemInstance(selectUpToAnchorId)
58+
: tree.getFocusedItem();
59+
const indexB = itemB.getItemMeta().index;
5560
const [a, b] = indexA < indexB ? [indexA, indexB] : [indexB, indexA];
5661
const newSelectedItems = tree
5762
.getItems()
@@ -90,6 +95,11 @@ export const selectionFeature: FeatureImplementation = {
9095
tree.setSelectedItems([item.getItemMeta().itemId]);
9196
}
9297

98+
if (!e.shiftKey) {
99+
tree.getDataRef<SelectionDataRef>().current.selectUpToAnchorId =
100+
item.getId();
101+
}
102+
93103
prev?.()?.onClick?.(e);
94104
},
95105
}),

packages/core/src/features/selection/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { ItemInstance, SetStateFn } from "../../types/core";
22

3+
export interface SelectionDataRef {
4+
selectUpToAnchorId?: string | null;
5+
}
6+
37
export type SelectionFeatureDef<T> = {
48
state: {
59
selectedItems: string[];

0 commit comments

Comments
 (0)