@headless-tree/core 0.0.15 → 1.0.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @headless-tree/core
2
2
 
3
+ ## 1.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 9e5027b: The propMemoization feature now memoizes all prop-generation related functions, including searchinput and renameinput related props
8
+
3
9
  ## 0.0.15
4
10
 
5
11
  ### Patch Changes
@@ -29,7 +29,7 @@ exports.dragAndDropFeature = {
29
29
  const target = tree.getDragTarget();
30
30
  const indent = ((_a = target === null || target === void 0 ? void 0 : target.item.getItemMeta().level) !== null && _a !== void 0 ? _a : 0) + 1;
31
31
  const treeBb = (_b = tree.getElement()) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
32
- if (!target || !treeBb || !("childIndex" in target))
32
+ if (!target || !treeBb || !(0, utils_1.isOrderedDragTarget)(target))
33
33
  return null;
34
34
  const leftOffset = target.dragLineLevel * ((_c = tree.getConfig().indent) !== null && _c !== void 0 ? _c : 1);
35
35
  const targetItem = tree.getItems()[target.dragLineIndex];
@@ -157,7 +157,7 @@ exports.dragAndDropFeature = {
157
157
  isDragTargetAbove: ({ tree, item }) => {
158
158
  const target = tree.getDragTarget();
159
159
  if (!target ||
160
- !("childIndex" in target) ||
160
+ !(0, utils_1.isOrderedDragTarget)(target) ||
161
161
  target.item !== item.getParent())
162
162
  return false;
163
163
  return target.childIndex === item.getItemMeta().posInSet;
@@ -165,7 +165,7 @@ exports.dragAndDropFeature = {
165
165
  isDragTargetBelow: ({ tree, item }) => {
166
166
  const target = tree.getDragTarget();
167
167
  if (!target ||
168
- !("childIndex" in target) ||
168
+ !(0, utils_1.isOrderedDragTarget)(target) ||
169
169
  target.item !== item.getParent())
170
170
  return false;
171
171
  return target.childIndex - 1 === item.getItemMeta().posInSet;
@@ -5,6 +5,13 @@ export declare enum ItemDropCategory {
5
5
  ExpandedFolder = 1,
6
6
  LastInGroup = 2
7
7
  }
8
+ export declare const isOrderedDragTarget: <T>(dragTarget: DragTarget<T>) => dragTarget is {
9
+ item: ItemInstance<T>;
10
+ childIndex: number;
11
+ insertionIndex: number;
12
+ dragLineIndex: number;
13
+ dragLineLevel: number;
14
+ };
8
15
  export declare const canDrop: (dataTransfer: DataTransfer | null, target: DragTarget<any>, tree: TreeInstance<any>) => boolean;
9
16
  export declare const getItemDropCategory: (item: ItemInstance<any>) => ItemDropCategory;
10
17
  export declare const getInsertionIndex: <T>(children: ItemInstance<T>[], childIndex: number, draggedItems: ItemInstance<T>[] | undefined) => number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getDragTarget = exports.getReparentTarget = exports.getDragCode = exports.getInsertionIndex = exports.getItemDropCategory = exports.canDrop = exports.ItemDropCategory = void 0;
3
+ exports.getDragTarget = exports.getReparentTarget = exports.getDragCode = exports.getInsertionIndex = exports.getItemDropCategory = exports.canDrop = exports.isOrderedDragTarget = exports.ItemDropCategory = void 0;
4
4
  var ItemDropCategory;
5
5
  (function (ItemDropCategory) {
6
6
  ItemDropCategory[ItemDropCategory["Item"] = 0] = "Item";
@@ -14,6 +14,8 @@ var PlacementType;
14
14
  PlacementType[PlacementType["MakeChild"] = 2] = "MakeChild";
15
15
  PlacementType[PlacementType["Reparent"] = 3] = "Reparent";
16
16
  })(PlacementType || (PlacementType = {}));
17
+ const isOrderedDragTarget = (dragTarget) => "childIndex" in dragTarget;
18
+ exports.isOrderedDragTarget = isOrderedDragTarget;
17
19
  const canDrop = (dataTransfer, target, tree) => {
18
20
  var _a, _b, _c;
19
21
  const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems;
@@ -18,8 +18,7 @@ const getNextDragTarget = (tree, isUp, dragTarget) => {
18
18
  const direction = isUp ? 0 : 1;
19
19
  const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems;
20
20
  // currently hovering between items
21
- if ("childIndex" in dragTarget) {
22
- // TODO move check in reusable function
21
+ if ((0, utils_1.isOrderedDragTarget)(dragTarget)) {
23
22
  const parent = dragTarget.item.getParent();
24
23
  const targetedItem = tree.getItems()[dragTarget.dragLineIndex - 1]; // item above dragline
25
24
  const targetCategory = targetedItem
@@ -77,7 +76,7 @@ const getNextValidDragTarget = (tree, isUp, previousTarget) => {
77
76
  };
78
77
  const updateScroll = (tree) => {
79
78
  const state = tree.getState().dnd;
80
- if (!(state === null || state === void 0 ? void 0 : state.dragTarget) || "childIndex" in state.dragTarget)
79
+ if (!(state === null || state === void 0 ? void 0 : state.dragTarget) || (0, utils_1.isOrderedDragTarget)(state.dragTarget))
81
80
  return;
82
81
  state.dragTarget.item.scrollTo({ block: "nearest", inline: "nearest" });
83
82
  };
@@ -118,7 +117,7 @@ const moveDragPosition = (tree, isUp) => {
118
117
  dragTarget,
119
118
  });
120
119
  tree.applySubStateUpdate("assistiveDndState", types_1.AssistiveDndState.Dragging);
121
- if (!("childIndex" in dragTarget)) {
120
+ if (!(0, utils_1.isOrderedDragTarget)(dragTarget)) {
122
121
  dragTarget.item.setFocused();
123
122
  }
124
123
  updateScroll(tree);
@@ -1,16 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.propMemoizationFeature = void 0;
4
- const memoize = (props, dataRef) => {
5
- var _a;
6
- (_a = dataRef.memoizedProps) !== null && _a !== void 0 ? _a : (dataRef.memoizedProps = {});
4
+ const memoize = (props, memoizedProps) => {
7
5
  for (const key in props) {
8
6
  if (typeof props[key] === "function") {
9
- if (key in dataRef.memoizedProps) {
10
- props[key] = dataRef.memoizedProps[key];
7
+ if (memoizedProps && key in memoizedProps) {
8
+ props[key] = memoizedProps[key];
11
9
  }
12
10
  else {
13
- dataRef.memoizedProps[key] = props[key];
11
+ memoizedProps[key] = props[key];
14
12
  }
15
13
  }
16
14
  }
@@ -31,18 +29,42 @@ exports.propMemoizationFeature = {
31
29
  ],
32
30
  treeInstance: {
33
31
  getContainerProps: ({ tree, prev }, treeLabel) => {
34
- var _a;
32
+ var _a, _b, _c;
33
+ var _d, _e;
35
34
  const dataRef = tree.getDataRef();
36
35
  const props = (_a = prev === null || prev === void 0 ? void 0 : prev(treeLabel)) !== null && _a !== void 0 ? _a : {};
37
- return memoize(props, dataRef.current);
36
+ (_b = (_d = dataRef.current).memo) !== null && _b !== void 0 ? _b : (_d.memo = {});
37
+ (_c = (_e = dataRef.current.memo).tree) !== null && _c !== void 0 ? _c : (_e.tree = {});
38
+ return memoize(props, dataRef.current.memo.tree);
39
+ },
40
+ getSearchInputElementProps: ({ tree, prev }) => {
41
+ var _a, _b, _c;
42
+ var _d, _e;
43
+ const dataRef = tree.getDataRef();
44
+ const props = (_a = prev === null || prev === void 0 ? void 0 : prev()) !== null && _a !== void 0 ? _a : {};
45
+ (_b = (_d = dataRef.current).memo) !== null && _b !== void 0 ? _b : (_d.memo = {});
46
+ (_c = (_e = dataRef.current.memo).search) !== null && _c !== void 0 ? _c : (_e.search = {});
47
+ return memoize(props, dataRef.current.memo.search);
38
48
  },
39
49
  },
40
50
  itemInstance: {
41
51
  getProps: ({ item, prev }) => {
42
- var _a;
52
+ var _a, _b, _c;
53
+ var _d, _e;
54
+ const dataRef = item.getDataRef();
55
+ const props = (_a = prev === null || prev === void 0 ? void 0 : prev()) !== null && _a !== void 0 ? _a : {};
56
+ (_b = (_d = dataRef.current).memo) !== null && _b !== void 0 ? _b : (_d.memo = {});
57
+ (_c = (_e = dataRef.current.memo).item) !== null && _c !== void 0 ? _c : (_e.item = {});
58
+ return memoize(props, dataRef.current.memo.item);
59
+ },
60
+ getRenameInputProps: ({ item, prev }) => {
61
+ var _a, _b, _c;
62
+ var _d, _e;
43
63
  const dataRef = item.getDataRef();
44
64
  const props = (_a = prev === null || prev === void 0 ? void 0 : prev()) !== null && _a !== void 0 ? _a : {};
45
- return memoize(props, dataRef.current);
65
+ (_b = (_d = dataRef.current).memo) !== null && _b !== void 0 ? _b : (_d.memo = {});
66
+ (_c = (_e = dataRef.current.memo).rename) !== null && _c !== void 0 ? _c : (_e.rename = {});
67
+ return memoize(props, dataRef.current.memo.rename);
46
68
  },
47
69
  },
48
70
  };
@@ -1,5 +1,10 @@
1
1
  export interface PropMemoizationDataRef {
2
- memoizedProps?: Record<string, any>;
2
+ memo?: {
3
+ tree?: Record<string, any>;
4
+ item?: Record<string, any>;
5
+ search?: Record<string, any>;
6
+ rename?: Record<string, any>;
7
+ };
3
8
  }
4
9
  export type PropMemoizationFeatureDef = {
5
10
  state: {};
@@ -50,7 +50,6 @@ exports.treeFeature = {
50
50
  }
51
51
  return flatItems;
52
52
  },
53
- // TODO memo
54
53
  getFocusedItem: ({ tree }) => {
55
54
  var _a, _b;
56
55
  return ((_b = tree.getItemInstance((_a = tree.getState().focusedItem) !== null && _a !== void 0 ? _a : "")) !== null && _b !== void 0 ? _b : tree.getItems()[0]);
@@ -80,7 +79,6 @@ exports.treeFeature = {
80
79
  focusedElement.focus();
81
80
  }));
82
81
  },
83
- // TODO add label parameter
84
82
  getContainerProps: ({ prev, tree }, treeLabel) => (Object.assign(Object.assign({}, prev === null || prev === void 0 ? void 0 : prev()), { role: "tree", "aria-label": treeLabel !== null && treeLabel !== void 0 ? treeLabel : "", ref: tree.registerElement })),
85
83
  // relevant for hotkeys of this feature
86
84
  isSearchOpen: () => false,
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { canDrop, getDragCode, getDragTarget } from "./utils";
10
+ import { canDrop, getDragCode, getDragTarget, isOrderedDragTarget, } from "./utils";
11
11
  import { makeStateUpdater } from "../../utils";
12
12
  export const dragAndDropFeature = {
13
13
  key: "drag-and-drop",
@@ -26,7 +26,7 @@ export const dragAndDropFeature = {
26
26
  const target = tree.getDragTarget();
27
27
  const indent = ((_a = target === null || target === void 0 ? void 0 : target.item.getItemMeta().level) !== null && _a !== void 0 ? _a : 0) + 1;
28
28
  const treeBb = (_b = tree.getElement()) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
29
- if (!target || !treeBb || !("childIndex" in target))
29
+ if (!target || !treeBb || !isOrderedDragTarget(target))
30
30
  return null;
31
31
  const leftOffset = target.dragLineLevel * ((_c = tree.getConfig().indent) !== null && _c !== void 0 ? _c : 1);
32
32
  const targetItem = tree.getItems()[target.dragLineIndex];
@@ -154,7 +154,7 @@ export const dragAndDropFeature = {
154
154
  isDragTargetAbove: ({ tree, item }) => {
155
155
  const target = tree.getDragTarget();
156
156
  if (!target ||
157
- !("childIndex" in target) ||
157
+ !isOrderedDragTarget(target) ||
158
158
  target.item !== item.getParent())
159
159
  return false;
160
160
  return target.childIndex === item.getItemMeta().posInSet;
@@ -162,7 +162,7 @@ export const dragAndDropFeature = {
162
162
  isDragTargetBelow: ({ tree, item }) => {
163
163
  const target = tree.getDragTarget();
164
164
  if (!target ||
165
- !("childIndex" in target) ||
165
+ !isOrderedDragTarget(target) ||
166
166
  target.item !== item.getParent())
167
167
  return false;
168
168
  return target.childIndex - 1 === item.getItemMeta().posInSet;
@@ -5,6 +5,13 @@ export declare enum ItemDropCategory {
5
5
  ExpandedFolder = 1,
6
6
  LastInGroup = 2
7
7
  }
8
+ export declare const isOrderedDragTarget: <T>(dragTarget: DragTarget<T>) => dragTarget is {
9
+ item: ItemInstance<T>;
10
+ childIndex: number;
11
+ insertionIndex: number;
12
+ dragLineIndex: number;
13
+ dragLineLevel: number;
14
+ };
8
15
  export declare const canDrop: (dataTransfer: DataTransfer | null, target: DragTarget<any>, tree: TreeInstance<any>) => boolean;
9
16
  export declare const getItemDropCategory: (item: ItemInstance<any>) => ItemDropCategory;
10
17
  export declare const getInsertionIndex: <T>(children: ItemInstance<T>[], childIndex: number, draggedItems: ItemInstance<T>[] | undefined) => number;
@@ -11,6 +11,7 @@ var PlacementType;
11
11
  PlacementType[PlacementType["MakeChild"] = 2] = "MakeChild";
12
12
  PlacementType[PlacementType["Reparent"] = 3] = "Reparent";
13
13
  })(PlacementType || (PlacementType = {}));
14
+ export const isOrderedDragTarget = (dragTarget) => "childIndex" in dragTarget;
14
15
  export const canDrop = (dataTransfer, target, tree) => {
15
16
  var _a, _b, _c;
16
17
  const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems;
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { ItemDropCategory, canDrop, getInsertionIndex, getItemDropCategory, getReparentTarget, } from "../drag-and-drop/utils";
10
+ import { ItemDropCategory, canDrop, getInsertionIndex, getItemDropCategory, getReparentTarget, isOrderedDragTarget, } from "../drag-and-drop/utils";
11
11
  import { makeStateUpdater } from "../../utils";
12
12
  import { AssistiveDndState } from "./types";
13
13
  const getNextDragTarget = (tree, isUp, dragTarget) => {
@@ -15,8 +15,7 @@ const getNextDragTarget = (tree, isUp, dragTarget) => {
15
15
  const direction = isUp ? 0 : 1;
16
16
  const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems;
17
17
  // currently hovering between items
18
- if ("childIndex" in dragTarget) {
19
- // TODO move check in reusable function
18
+ if (isOrderedDragTarget(dragTarget)) {
20
19
  const parent = dragTarget.item.getParent();
21
20
  const targetedItem = tree.getItems()[dragTarget.dragLineIndex - 1]; // item above dragline
22
21
  const targetCategory = targetedItem
@@ -74,7 +73,7 @@ const getNextValidDragTarget = (tree, isUp, previousTarget) => {
74
73
  };
75
74
  const updateScroll = (tree) => {
76
75
  const state = tree.getState().dnd;
77
- if (!(state === null || state === void 0 ? void 0 : state.dragTarget) || "childIndex" in state.dragTarget)
76
+ if (!(state === null || state === void 0 ? void 0 : state.dragTarget) || isOrderedDragTarget(state.dragTarget))
78
77
  return;
79
78
  state.dragTarget.item.scrollTo({ block: "nearest", inline: "nearest" });
80
79
  };
@@ -115,7 +114,7 @@ const moveDragPosition = (tree, isUp) => {
115
114
  dragTarget,
116
115
  });
117
116
  tree.applySubStateUpdate("assistiveDndState", AssistiveDndState.Dragging);
118
- if (!("childIndex" in dragTarget)) {
117
+ if (!isOrderedDragTarget(dragTarget)) {
119
118
  dragTarget.item.setFocused();
120
119
  }
121
120
  updateScroll(tree);
@@ -1,13 +1,11 @@
1
- const memoize = (props, dataRef) => {
2
- var _a;
3
- (_a = dataRef.memoizedProps) !== null && _a !== void 0 ? _a : (dataRef.memoizedProps = {});
1
+ const memoize = (props, memoizedProps) => {
4
2
  for (const key in props) {
5
3
  if (typeof props[key] === "function") {
6
- if (key in dataRef.memoizedProps) {
7
- props[key] = dataRef.memoizedProps[key];
4
+ if (memoizedProps && key in memoizedProps) {
5
+ props[key] = memoizedProps[key];
8
6
  }
9
7
  else {
10
- dataRef.memoizedProps[key] = props[key];
8
+ memoizedProps[key] = props[key];
11
9
  }
12
10
  }
13
11
  }
@@ -28,18 +26,42 @@ export const propMemoizationFeature = {
28
26
  ],
29
27
  treeInstance: {
30
28
  getContainerProps: ({ tree, prev }, treeLabel) => {
31
- var _a;
29
+ var _a, _b, _c;
30
+ var _d, _e;
32
31
  const dataRef = tree.getDataRef();
33
32
  const props = (_a = prev === null || prev === void 0 ? void 0 : prev(treeLabel)) !== null && _a !== void 0 ? _a : {};
34
- return memoize(props, dataRef.current);
33
+ (_b = (_d = dataRef.current).memo) !== null && _b !== void 0 ? _b : (_d.memo = {});
34
+ (_c = (_e = dataRef.current.memo).tree) !== null && _c !== void 0 ? _c : (_e.tree = {});
35
+ return memoize(props, dataRef.current.memo.tree);
36
+ },
37
+ getSearchInputElementProps: ({ tree, prev }) => {
38
+ var _a, _b, _c;
39
+ var _d, _e;
40
+ const dataRef = tree.getDataRef();
41
+ const props = (_a = prev === null || prev === void 0 ? void 0 : prev()) !== null && _a !== void 0 ? _a : {};
42
+ (_b = (_d = dataRef.current).memo) !== null && _b !== void 0 ? _b : (_d.memo = {});
43
+ (_c = (_e = dataRef.current.memo).search) !== null && _c !== void 0 ? _c : (_e.search = {});
44
+ return memoize(props, dataRef.current.memo.search);
35
45
  },
36
46
  },
37
47
  itemInstance: {
38
48
  getProps: ({ item, prev }) => {
39
- var _a;
49
+ var _a, _b, _c;
50
+ var _d, _e;
51
+ const dataRef = item.getDataRef();
52
+ const props = (_a = prev === null || prev === void 0 ? void 0 : prev()) !== null && _a !== void 0 ? _a : {};
53
+ (_b = (_d = dataRef.current).memo) !== null && _b !== void 0 ? _b : (_d.memo = {});
54
+ (_c = (_e = dataRef.current.memo).item) !== null && _c !== void 0 ? _c : (_e.item = {});
55
+ return memoize(props, dataRef.current.memo.item);
56
+ },
57
+ getRenameInputProps: ({ item, prev }) => {
58
+ var _a, _b, _c;
59
+ var _d, _e;
40
60
  const dataRef = item.getDataRef();
41
61
  const props = (_a = prev === null || prev === void 0 ? void 0 : prev()) !== null && _a !== void 0 ? _a : {};
42
- return memoize(props, dataRef.current);
62
+ (_b = (_d = dataRef.current).memo) !== null && _b !== void 0 ? _b : (_d.memo = {});
63
+ (_c = (_e = dataRef.current.memo).rename) !== null && _c !== void 0 ? _c : (_e.rename = {});
64
+ return memoize(props, dataRef.current.memo.rename);
43
65
  },
44
66
  },
45
67
  };
@@ -1,5 +1,10 @@
1
1
  export interface PropMemoizationDataRef {
2
- memoizedProps?: Record<string, any>;
2
+ memo?: {
3
+ tree?: Record<string, any>;
4
+ item?: Record<string, any>;
5
+ search?: Record<string, any>;
6
+ rename?: Record<string, any>;
7
+ };
3
8
  }
4
9
  export type PropMemoizationFeatureDef = {
5
10
  state: {};
@@ -47,7 +47,6 @@ export const treeFeature = {
47
47
  }
48
48
  return flatItems;
49
49
  },
50
- // TODO memo
51
50
  getFocusedItem: ({ tree }) => {
52
51
  var _a, _b;
53
52
  return ((_b = tree.getItemInstance((_a = tree.getState().focusedItem) !== null && _a !== void 0 ? _a : "")) !== null && _b !== void 0 ? _b : tree.getItems()[0]);
@@ -77,7 +76,6 @@ export const treeFeature = {
77
76
  focusedElement.focus();
78
77
  }));
79
78
  },
80
- // TODO add label parameter
81
79
  getContainerProps: ({ prev, tree }, treeLabel) => (Object.assign(Object.assign({}, prev === null || prev === void 0 ? void 0 : prev()), { role: "tree", "aria-label": treeLabel !== null && treeLabel !== void 0 ? treeLabel : "", ref: tree.registerElement })),
82
80
  // relevant for hotkeys of this feature
83
81
  isSearchOpen: () => false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@headless-tree/core",
3
- "version": "0.0.15",
3
+ "version": "1.0.0",
4
4
  "type": "module",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/esm/index.js",
@@ -1,6 +1,11 @@
1
1
  import { FeatureImplementation } from "../../types/core";
2
2
  import { DndDataRef, DragLineData } from "./types";
3
- import { canDrop, getDragCode, getDragTarget } from "./utils";
3
+ import {
4
+ canDrop,
5
+ getDragCode,
6
+ getDragTarget,
7
+ isOrderedDragTarget,
8
+ } from "./utils";
4
9
  import { makeStateUpdater } from "../../utils";
5
10
 
6
11
  export const dragAndDropFeature: FeatureImplementation = {
@@ -30,7 +35,7 @@ export const dragAndDropFeature: FeatureImplementation = {
30
35
 
31
36
  const treeBb = tree.getElement()?.getBoundingClientRect();
32
37
 
33
- if (!target || !treeBb || !("childIndex" in target)) return null;
38
+ if (!target || !treeBb || !isOrderedDragTarget(target)) return null;
34
39
 
35
40
  const leftOffset = target.dragLineLevel * (tree.getConfig().indent ?? 1);
36
41
  const targetItem = tree.getItems()[target.dragLineIndex];
@@ -212,7 +217,7 @@ export const dragAndDropFeature: FeatureImplementation = {
212
217
 
213
218
  if (
214
219
  !target ||
215
- !("childIndex" in target) ||
220
+ !isOrderedDragTarget(target) ||
216
221
  target.item !== item.getParent()
217
222
  )
218
223
  return false;
@@ -224,7 +229,7 @@ export const dragAndDropFeature: FeatureImplementation = {
224
229
 
225
230
  if (
226
231
  !target ||
227
- !("childIndex" in target) ||
232
+ !isOrderedDragTarget(target) ||
228
233
  target.item !== item.getParent()
229
234
  )
230
235
  return false;
@@ -26,6 +26,9 @@ type TargetPlacement =
26
26
  reparentLevel: number;
27
27
  };
28
28
 
29
+ export const isOrderedDragTarget = <T>(dragTarget: DragTarget<T>) =>
30
+ "childIndex" in dragTarget;
31
+
29
32
  export const canDrop = (
30
33
  dataTransfer: DataTransfer | null,
31
34
  target: DragTarget<any>,
@@ -10,6 +10,7 @@ import {
10
10
  getInsertionIndex,
11
11
  getItemDropCategory,
12
12
  getReparentTarget,
13
+ isOrderedDragTarget,
13
14
  } from "../drag-and-drop/utils";
14
15
  import { makeStateUpdater } from "../../utils";
15
16
  import { AssistiveDndState, KDndDataRef } from "./types";
@@ -23,8 +24,7 @@ const getNextDragTarget = <T>(
23
24
  const draggedItems = tree.getState().dnd?.draggedItems;
24
25
 
25
26
  // currently hovering between items
26
- if ("childIndex" in dragTarget) {
27
- // TODO move check in reusable function
27
+ if (isOrderedDragTarget(dragTarget)) {
28
28
  const parent = dragTarget.item.getParent();
29
29
  const targetedItem = tree.getItems()[dragTarget.dragLineIndex - 1]; // item above dragline
30
30
 
@@ -107,7 +107,7 @@ const getNextValidDragTarget = <T>(
107
107
 
108
108
  const updateScroll = <T>(tree: TreeInstance<T>) => {
109
109
  const state = tree.getState().dnd;
110
- if (!state?.dragTarget || "childIndex" in state.dragTarget) return;
110
+ if (!state?.dragTarget || isOrderedDragTarget(state.dragTarget)) return;
111
111
  state.dragTarget.item.scrollTo({ block: "nearest", inline: "nearest" });
112
112
  };
113
113
 
@@ -152,7 +152,7 @@ const moveDragPosition = <T>(tree: TreeInstance<T>, isUp: boolean) => {
152
152
  dragTarget,
153
153
  });
154
154
  tree.applySubStateUpdate("assistiveDndState", AssistiveDndState.Dragging);
155
- if (!("childIndex" in dragTarget)) {
155
+ if (!isOrderedDragTarget(dragTarget)) {
156
156
  dragTarget.item.setFocused();
157
157
  }
158
158
  updateScroll(tree);
@@ -6,6 +6,7 @@ import { propMemoizationFeature } from "../prop-memoization/feature";
6
6
  import { keyboardDragAndDropFeature } from "./feature";
7
7
  import { dragAndDropFeature } from "../drag-and-drop/feature";
8
8
  import { AssistiveDndState } from "./types";
9
+ import { isOrderedDragTarget } from "../drag-and-drop/utils";
9
10
 
10
11
  const isItem = (item: unknown): item is ItemInstance<any> =>
11
12
  !!item && typeof item === "object" && "getId" in item;
@@ -318,7 +319,7 @@ describe("core-feature/keyboard-drag-and-drop", () => {
318
319
  describe("drag restrictions", () => {
319
320
  const expectChildIndex = (index: number) => {
320
321
  const state = tree.instance.getState().dnd?.dragTarget;
321
- if (!state || !("childIndex" in state))
322
+ if (!state || !isOrderedDragTarget(state))
322
323
  throw new Error("No childIndex");
323
324
  expect(state.childIndex).toEqual(index);
324
325
  };
@@ -3,15 +3,14 @@ import { PropMemoizationDataRef } from "./types";
3
3
 
4
4
  const memoize = (
5
5
  props: Record<string, any>,
6
- dataRef: PropMemoizationDataRef,
6
+ memoizedProps: Record<string, any>,
7
7
  ) => {
8
- dataRef.memoizedProps ??= {};
9
8
  for (const key in props) {
10
9
  if (typeof props[key] === "function") {
11
- if (key in dataRef.memoizedProps) {
12
- props[key] = dataRef.memoizedProps[key];
10
+ if (memoizedProps && key in memoizedProps) {
11
+ props[key] = memoizedProps[key];
13
12
  } else {
14
- dataRef.memoizedProps[key] = props[key];
13
+ memoizedProps[key] = props[key];
15
14
  }
16
15
  }
17
16
  }
@@ -37,7 +36,17 @@ export const propMemoizationFeature: FeatureImplementation = {
37
36
  getContainerProps: ({ tree, prev }, treeLabel) => {
38
37
  const dataRef = tree.getDataRef<PropMemoizationDataRef>();
39
38
  const props = prev?.(treeLabel) ?? {};
40
- return memoize(props, dataRef.current);
39
+ dataRef.current.memo ??= {};
40
+ dataRef.current.memo.tree ??= {};
41
+ return memoize(props, dataRef.current.memo.tree);
42
+ },
43
+
44
+ getSearchInputElementProps: ({ tree, prev }) => {
45
+ const dataRef = tree.getDataRef<PropMemoizationDataRef>();
46
+ const props = prev?.() ?? {};
47
+ dataRef.current.memo ??= {};
48
+ dataRef.current.memo.search ??= {};
49
+ return memoize(props, dataRef.current.memo.search);
41
50
  },
42
51
  },
43
52
 
@@ -45,7 +54,17 @@ export const propMemoizationFeature: FeatureImplementation = {
45
54
  getProps: ({ item, prev }) => {
46
55
  const dataRef = item.getDataRef<PropMemoizationDataRef>();
47
56
  const props = prev?.() ?? {};
48
- return memoize(props, dataRef.current);
57
+ dataRef.current.memo ??= {};
58
+ dataRef.current.memo.item ??= {};
59
+ return memoize(props, dataRef.current.memo.item);
60
+ },
61
+
62
+ getRenameInputProps: ({ item, prev }) => {
63
+ const dataRef = item.getDataRef<PropMemoizationDataRef>();
64
+ const props = prev?.() ?? {};
65
+ dataRef.current.memo ??= {};
66
+ dataRef.current.memo.rename ??= {};
67
+ return memoize(props, dataRef.current.memo.rename);
49
68
  },
50
69
  },
51
70
  };
@@ -1,5 +1,10 @@
1
1
  export interface PropMemoizationDataRef {
2
- memoizedProps?: Record<string, any>;
2
+ memo?: {
3
+ tree?: Record<string, any>;
4
+ item?: Record<string, any>;
5
+ search?: Record<string, any>;
6
+ rename?: Record<string, any>;
7
+ };
3
8
  }
4
9
 
5
10
  export type PropMemoizationFeatureDef = {
@@ -63,7 +63,6 @@ export const treeFeature: FeatureImplementation<any> = {
63
63
  return flatItems;
64
64
  },
65
65
 
66
- // TODO memo
67
66
  getFocusedItem: ({ tree }) => {
68
67
  return (
69
68
  tree.getItemInstance(tree.getState().focusedItem ?? "") ??
@@ -95,7 +94,6 @@ export const treeFeature: FeatureImplementation<any> = {
95
94
  });
96
95
  },
97
96
 
98
- // TODO add label parameter
99
97
  getContainerProps: ({ prev, tree }, treeLabel) => ({
100
98
  ...prev?.(),
101
99
  role: "tree",