@headless-tree/core 0.0.0-20260108010329 → 0.0.0-20260108162121

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 CHANGED
@@ -1,6 +1,12 @@
1
1
  # @headless-tree/core
2
2
 
3
- ## 0.0.0-20260108010329
3
+ ## 0.0.0-20260108162121
4
+
5
+ ### Patch Changes
6
+
7
+ - 4397d8c: Added `draggedItemOverwritesSelection` as config option to the Drag Feature. Setting it to false will disable the current default behavior, where dragging an unselected item will overwrite the selection to just the dragged item.
8
+
9
+ ## 1.6.2
4
10
 
5
11
  ### Patch Changes
6
12
 
package/dist/index.d.mts CHANGED
@@ -70,6 +70,9 @@ type DragAndDropFeatureDef<T> = {
70
70
  openOnDropDelay?: number;
71
71
  /** If true, `item.getProps()` will not include drag event handlers. Use `item.getDragHandleProps()` on the handler element. */
72
72
  seperateDragHandle?: boolean;
73
+ /** If true, the item that is dragged is not selected, the selected items will be overwritten to just the dragged item.
74
+ * Defaults to true */
75
+ draggedItemOverwritesSelection?: boolean;
73
76
  };
74
77
  treeInstance: {
75
78
  getDragTarget: () => DragTarget<T> | null;
package/dist/index.d.ts CHANGED
@@ -70,6 +70,9 @@ type DragAndDropFeatureDef<T> = {
70
70
  openOnDropDelay?: number;
71
71
  /** If true, `item.getProps()` will not include drag event handlers. Use `item.getDragHandleProps()` on the handler element. */
72
72
  seperateDragHandle?: boolean;
73
+ /** If true, the item that is dragged is not selected, the selected items will be overwritten to just the dragged item.
74
+ * Defaults to true */
75
+ draggedItemOverwritesSelection?: boolean;
73
76
  };
74
77
  treeInstance: {
75
78
  getDragTarget: () => DragTarget<T> | null;
package/dist/index.js CHANGED
@@ -1527,7 +1527,8 @@ var dragAndDropFeature = {
1527
1527
  canDragForeignDragObjectOver: defaultConfig.canDropForeignDragObject !== defaultCanDropForeignDragObject ? (dataTransfer) => dataTransfer.effectAllowed !== "none" : () => false,
1528
1528
  setDndState: makeStateUpdater("dnd", tree),
1529
1529
  canReorder: true,
1530
- openOnDropDelay: 800
1530
+ openOnDropDelay: 800,
1531
+ draggedItemOverwritesSelection: true
1531
1532
  }, defaultConfig),
1532
1533
  stateHandlerNames: {
1533
1534
  dnd: "setDndState"
@@ -1697,10 +1698,12 @@ var dragAndDropFeature = {
1697
1698
  draggable: true,
1698
1699
  onDragStart: (e) => {
1699
1700
  var _a, _b, _c, _d;
1701
+ const { draggedItemOverwritesSelection } = tree.getConfig();
1700
1702
  const selectedItems = tree.getSelectedItems ? tree.getSelectedItems() : [tree.getFocusedItem()];
1701
- const items = selectedItems.includes(item) ? selectedItems : [item];
1703
+ const overwriteSelection = !selectedItems.includes(item) && draggedItemOverwritesSelection;
1704
+ const items = overwriteSelection ? [item] : selectedItems;
1702
1705
  const config = tree.getConfig();
1703
- if (!selectedItems.includes(item)) {
1706
+ if (overwriteSelection) {
1704
1707
  (_a = tree.setSelectedItems) == null ? void 0 : _a.call(tree, [item.getItemMeta().itemId]);
1705
1708
  }
1706
1709
  if (!((_c = (_b = config.canDrag) == null ? void 0 : _b.call(config, items)) != null ? _c : true)) {
package/dist/index.mjs CHANGED
@@ -1483,7 +1483,8 @@ var dragAndDropFeature = {
1483
1483
  canDragForeignDragObjectOver: defaultConfig.canDropForeignDragObject !== defaultCanDropForeignDragObject ? (dataTransfer) => dataTransfer.effectAllowed !== "none" : () => false,
1484
1484
  setDndState: makeStateUpdater("dnd", tree),
1485
1485
  canReorder: true,
1486
- openOnDropDelay: 800
1486
+ openOnDropDelay: 800,
1487
+ draggedItemOverwritesSelection: true
1487
1488
  }, defaultConfig),
1488
1489
  stateHandlerNames: {
1489
1490
  dnd: "setDndState"
@@ -1653,10 +1654,12 @@ var dragAndDropFeature = {
1653
1654
  draggable: true,
1654
1655
  onDragStart: (e) => {
1655
1656
  var _a, _b, _c, _d;
1657
+ const { draggedItemOverwritesSelection } = tree.getConfig();
1656
1658
  const selectedItems = tree.getSelectedItems ? tree.getSelectedItems() : [tree.getFocusedItem()];
1657
- const items = selectedItems.includes(item) ? selectedItems : [item];
1659
+ const overwriteSelection = !selectedItems.includes(item) && draggedItemOverwritesSelection;
1660
+ const items = overwriteSelection ? [item] : selectedItems;
1658
1661
  const config = tree.getConfig();
1659
- if (!selectedItems.includes(item)) {
1662
+ if (overwriteSelection) {
1660
1663
  (_a = tree.setSelectedItems) == null ? void 0 : _a.call(tree, [item.getItemMeta().itemId]);
1661
1664
  }
1662
1665
  if (!((_c = (_b = config.canDrag) == null ? void 0 : _b.call(config, items)) != null ? _c : true)) {
package/package.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "checkbox",
14
14
  "hook"
15
15
  ],
16
- "version": "0.0.0-20260108010329",
16
+ "version": "0.0.0-20260108162121",
17
17
  "main": "dist/index.d.ts",
18
18
  "module": "dist/index.mjs",
19
19
  "types": "dist/index.d.mts",
@@ -787,5 +787,99 @@ describe("core-feature/drag-and-drop", () => {
787
787
  expect(canDrop).toBeCalledTimes(3);
788
788
  });
789
789
  });
790
+
791
+ describe("draggedItemOverwritesSelection", () => {
792
+ it("overwrites selection when dragging unselected item with draggedItemOverwritesSelection=true", () => {
793
+ tree.do.selectItem("x111");
794
+ tree.do.ctrlSelectItem("x112");
795
+ tree.do.ctrlSelectItem("x113");
796
+
797
+ expect(tree.instance.getItemInstance("x111").isSelected()).toBe(true);
798
+ expect(tree.instance.getItemInstance("x112").isSelected()).toBe(true);
799
+ expect(tree.instance.getItemInstance("x113").isSelected()).toBe(true);
800
+ expect(tree.instance.getItemInstance("x114").isSelected()).toBe(false);
801
+
802
+ tree.do.startDrag("x114");
803
+
804
+ expect(tree.instance.getItemInstance("x111").isSelected()).toBe(false);
805
+ expect(tree.instance.getItemInstance("x112").isSelected()).toBe(false);
806
+ expect(tree.instance.getItemInstance("x113").isSelected()).toBe(false);
807
+ expect(tree.instance.getItemInstance("x114").isSelected()).toBe(true);
808
+ });
809
+
810
+ it("preserves selection when dragging unselected item with draggedItemOverwritesSelection=false", async () => {
811
+ const testTree = await tree
812
+ .with({ draggedItemOverwritesSelection: false })
813
+ .createTestCaseTree();
814
+
815
+ testTree.do.selectItem("x111");
816
+ testTree.do.ctrlSelectItem("x112");
817
+ testTree.do.ctrlSelectItem("x113");
818
+
819
+ expect(testTree.item("x111").isSelected()).toBe(true);
820
+ expect(testTree.item("x112").isSelected()).toBe(true);
821
+ expect(testTree.item("x113").isSelected()).toBe(true);
822
+ expect(testTree.item("x114").isSelected()).toBe(false);
823
+ testTree.do.startDrag("x114");
824
+
825
+ expect(testTree.item("x111").isSelected()).toBe(true);
826
+ expect(testTree.item("x112").isSelected()).toBe(true);
827
+ expect(testTree.item("x113").isSelected()).toBe(true);
828
+ expect(testTree.item("x114").isSelected()).toBe(false);
829
+ });
830
+
831
+ it("does not overwrite selection when dragging selected item with draggedItemOverwritesSelection=true", () => {
832
+ tree.do.selectItem("x111");
833
+ tree.do.ctrlSelectItem("x112");
834
+ tree.do.ctrlSelectItem("x113");
835
+
836
+ expect(tree.item("x111").isSelected()).toBe(true);
837
+ expect(tree.item("x112").isSelected()).toBe(true);
838
+ expect(tree.item("x113").isSelected()).toBe(true);
839
+
840
+ tree.do.startDrag("x111");
841
+
842
+ expect(tree.item("x111").isSelected()).toBe(true);
843
+ expect(tree.item("x112").isSelected()).toBe(true);
844
+ expect(tree.item("x113").isSelected()).toBe(true);
845
+ });
846
+
847
+ it("does not overwrite selection when dragging selected item with draggedItemOverwritesSelection=false", async () => {
848
+ const testTree = await tree
849
+ .with({ draggedItemOverwritesSelection: false })
850
+ .createTestCaseTree();
851
+
852
+ testTree.do.selectItem("x111");
853
+ testTree.do.ctrlSelectItem("x112");
854
+ testTree.do.ctrlSelectItem("x113");
855
+
856
+ expect(testTree.item("x111").isSelected()).toBe(true);
857
+ expect(testTree.item("x112").isSelected()).toBe(true);
858
+ expect(testTree.item("x113").isSelected()).toBe(true);
859
+
860
+ testTree.do.startDrag("x111");
861
+
862
+ expect(testTree.item("x111").isSelected()).toBe(true);
863
+ expect(testTree.item("x112").isSelected()).toBe(true);
864
+ expect(testTree.item("x113").isSelected()).toBe(true);
865
+ });
866
+
867
+ it("drags all selected items when draggedItemOverwritesSelection=false", async () => {
868
+ const testTree = await tree
869
+ .with({ draggedItemOverwritesSelection: false })
870
+ .createTestCaseTree();
871
+
872
+ testTree.do.selectItem("x111");
873
+ testTree.do.ctrlSelectItem("x112");
874
+ testTree.do.ctrlSelectItem("x113");
875
+
876
+ testTree.do.startDrag("x111");
877
+ testTree.do.dragOverAndDrop("x21");
878
+
879
+ testTree.expect.dropped(["x111", "x112", "x113"], {
880
+ item: testTree.item("x21"),
881
+ });
882
+ });
883
+ });
790
884
  });
791
885
  });
@@ -57,6 +57,7 @@ export const dragAndDropFeature: FeatureImplementation = {
57
57
  setDndState: makeStateUpdater("dnd", tree),
58
58
  canReorder: true,
59
59
  openOnDropDelay: 800,
60
+ draggedItemOverwritesSelection: true,
60
61
  ...defaultConfig,
61
62
  }),
62
63
 
@@ -280,13 +281,16 @@ export const dragAndDropFeature: FeatureImplementation = {
280
281
  draggable: true,
281
282
 
282
283
  onDragStart: (e: DragEvent) => {
284
+ const { draggedItemOverwritesSelection } = tree.getConfig();
283
285
  const selectedItems = tree.getSelectedItems
284
286
  ? tree.getSelectedItems()
285
287
  : [tree.getFocusedItem()];
286
- const items = selectedItems.includes(item) ? selectedItems : [item];
288
+ const overwriteSelection =
289
+ !selectedItems.includes(item) && draggedItemOverwritesSelection;
290
+ const items = overwriteSelection ? [item] : selectedItems;
287
291
  const config = tree.getConfig();
288
292
 
289
- if (!selectedItems.includes(item)) {
293
+ if (overwriteSelection) {
290
294
  tree.setSelectedItems?.([item.getItemMeta().itemId]);
291
295
  }
292
296
 
@@ -100,6 +100,10 @@ export type DragAndDropFeatureDef<T> = {
100
100
 
101
101
  /** If true, `item.getProps()` will not include drag event handlers. Use `item.getDragHandleProps()` on the handler element. */
102
102
  seperateDragHandle?: boolean;
103
+
104
+ /** If true, the item that is dragged is not selected, the selected items will be overwritten to just the dragged item.
105
+ * Defaults to true */
106
+ draggedItemOverwritesSelection?: boolean;
103
107
  };
104
108
  treeInstance: {
105
109
  getDragTarget: () => DragTarget<T> | null;