@headless-tree/core 0.0.4 → 0.0.5
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 +6 -0
- package/lib/cjs/core/create-tree.js +4 -4
- package/lib/cjs/features/drag-and-drop/feature.js +5 -5
- package/lib/cjs/features/main/types.d.ts +1 -0
- package/lib/cjs/features/selection/feature.js +2 -2
- package/lib/cjs/features/tree/feature.js +20 -3
- package/lib/cjs/features/tree/types.d.ts +5 -0
- package/lib/esm/core/create-tree.js +4 -4
- package/lib/esm/features/drag-and-drop/feature.js +5 -5
- package/lib/esm/features/main/types.d.ts +1 -0
- package/lib/esm/features/selection/feature.js +2 -2
- package/lib/esm/features/tree/feature.js +20 -3
- package/lib/esm/features/tree/types.d.ts +5 -0
- package/package.json +3 -3
- package/src/core/create-tree.ts +1 -1
- package/src/features/drag-and-drop/feature.ts +8 -8
- package/src/features/main/types.ts +1 -0
- package/src/features/selection/feature.ts +2 -2
- package/src/features/tree/feature.ts +21 -3
- package/src/features/tree/types.ts +6 -0
- package/tsconfig.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -11,10 +11,10 @@ const buildItemInstance = (features, tree, itemId) => {
|
|
|
11
11
|
return itemInstance;
|
|
12
12
|
};
|
|
13
13
|
const createTree = (initialConfig) => {
|
|
14
|
-
var _a, _b, _c, _d, _e;
|
|
14
|
+
var _a, _b, _c, _d, _e, _f;
|
|
15
15
|
const treeInstance = {};
|
|
16
16
|
const additionalFeatures = [feature_1.treeFeature, ...((_a = initialConfig.features) !== null && _a !== void 0 ? _a : [])];
|
|
17
|
-
let state = additionalFeatures.reduce((acc, feature) => { var _a, _b; return (_b = (_a = feature.getInitialState) === null || _a === void 0 ? void 0 : _a.call(feature, acc, treeInstance)) !== null && _b !== void 0 ? _b : acc; }, (_b = initialConfig.
|
|
17
|
+
let state = additionalFeatures.reduce((acc, feature) => { var _a, _b; return (_b = (_a = feature.getInitialState) === null || _a === void 0 ? void 0 : _a.call(feature, acc, treeInstance)) !== null && _b !== void 0 ? _b : acc; }, (_c = (_b = initialConfig.initialState) !== null && _b !== void 0 ? _b : initialConfig.state) !== null && _c !== void 0 ? _c : {});
|
|
18
18
|
let config = additionalFeatures.reduce((acc, feature) => { var _a, _b; return (_b = (_a = feature.getDefaultConfig) === null || _a === void 0 ? void 0 : _a.call(feature, acc, treeInstance)) !== null && _b !== void 0 ? _b : acc; }, initialConfig);
|
|
19
19
|
let treeElement;
|
|
20
20
|
const treeDataRef = { current: {} };
|
|
@@ -107,8 +107,8 @@ const createTree = (initialConfig) => {
|
|
|
107
107
|
// todo sort features
|
|
108
108
|
const features = [mainFeature, ...additionalFeatures];
|
|
109
109
|
for (const feature of features) {
|
|
110
|
-
Object.assign(treeInstance, (
|
|
111
|
-
Object.assign(hotkeyPresets, (
|
|
110
|
+
Object.assign(treeInstance, (_e = (_d = feature.createTreeInstance) === null || _d === void 0 ? void 0 : _d.call(feature, Object.assign({}, treeInstance), treeInstance)) !== null && _e !== void 0 ? _e : {});
|
|
111
|
+
Object.assign(hotkeyPresets, (_f = feature.hotkeys) !== null && _f !== void 0 ? _f : {});
|
|
112
112
|
}
|
|
113
113
|
rebuildItemMeta(mainFeature);
|
|
114
114
|
return treeInstance;
|
|
@@ -13,7 +13,7 @@ exports.dragAndDropFeature = {
|
|
|
13
13
|
} })),
|
|
14
14
|
createItemInstance: (prev, item, tree) => (Object.assign(Object.assign({}, prev), { getProps: () => {
|
|
15
15
|
var _a, _b, _c;
|
|
16
|
-
return (Object.assign(Object.assign({}, prev.getProps()), { draggable: (_c = (_b = (_a = tree.getConfig()).isItemDraggable) === null || _b === void 0 ? void 0 : _b.call(_a, item)) !== null && _c !== void 0 ? _c : true, onDragStart: (e) => {
|
|
16
|
+
return (Object.assign(Object.assign({}, prev.getProps()), { draggable: (_c = (_b = (_a = tree.getConfig()).isItemDraggable) === null || _b === void 0 ? void 0 : _b.call(_a, item)) !== null && _c !== void 0 ? _c : true, onDragStart: item.getMemoizedProp("dnd/onDragStart", () => (e) => {
|
|
17
17
|
var _a, _b, _c, _d, _e;
|
|
18
18
|
const selectedItems = tree.getSelectedItems();
|
|
19
19
|
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
@@ -33,7 +33,7 @@ exports.dragAndDropFeature = {
|
|
|
33
33
|
draggedItems: items,
|
|
34
34
|
draggingOverItem: tree.getFocusedItem(),
|
|
35
35
|
});
|
|
36
|
-
}, onDragOver: (e) => {
|
|
36
|
+
}), onDragOver: item.getMemoizedProp("dnd/onDragOver", () => (e) => {
|
|
37
37
|
var _a, _b, _c, _d, _e;
|
|
38
38
|
const target = (0, utils_1.getDropTarget)(e, item, tree);
|
|
39
39
|
const dataRef = tree.getDataRef();
|
|
@@ -51,12 +51,12 @@ exports.dragAndDropFeature = {
|
|
|
51
51
|
}
|
|
52
52
|
dataRef.current.lastDragCode = nextDragCode;
|
|
53
53
|
(_e = (_d = tree.getConfig()).setDndState) === null || _e === void 0 ? void 0 : _e.call(_d, (state) => (Object.assign(Object.assign({}, state), { dragTarget: target, draggingOverItem: item })));
|
|
54
|
-
}, onDragLeave: () => {
|
|
54
|
+
}), onDragLeave: item.getMemoizedProp("dnd/onDragLeave", () => () => {
|
|
55
55
|
var _a, _b;
|
|
56
56
|
const dataRef = tree.getDataRef();
|
|
57
57
|
dataRef.current.lastDragCode = "no-drag";
|
|
58
58
|
(_b = (_a = tree.getConfig()).setDndState) === null || _b === void 0 ? void 0 : _b.call(_a, (state) => (Object.assign(Object.assign({}, state), { draggingOverItem: undefined, dragTarget: undefined })));
|
|
59
|
-
}, onDrop: (e) => {
|
|
59
|
+
}), onDrop: item.getMemoizedProp("dnd/onDrop", () => (e) => {
|
|
60
60
|
var _a, _b, _c, _d, _e;
|
|
61
61
|
const dataRef = tree.getDataRef();
|
|
62
62
|
const target = (0, utils_1.getDropTarget)(e, item, tree);
|
|
@@ -75,7 +75,7 @@ exports.dragAndDropFeature = {
|
|
|
75
75
|
(_e = config.onDropForeignDragObject) === null || _e === void 0 ? void 0 : _e.call(config, e.dataTransfer, target);
|
|
76
76
|
}
|
|
77
77
|
// TODO rebuild tree?
|
|
78
|
-
} }));
|
|
78
|
+
}) }));
|
|
79
79
|
}, isDropTarget: () => {
|
|
80
80
|
const target = tree.getDropTarget();
|
|
81
81
|
return target ? target.item.getId() === item.getId() : false;
|
|
@@ -51,7 +51,7 @@ exports.selectionFeature = {
|
|
|
51
51
|
else {
|
|
52
52
|
item.select();
|
|
53
53
|
}
|
|
54
|
-
}, getProps: () => (Object.assign(Object.assign({}, prev.getProps()), { onClick: (e) => {
|
|
54
|
+
}, getProps: () => (Object.assign(Object.assign({}, prev.getProps()), { onClick: item.getMemoizedProp("selection/onClick", () => (e) => {
|
|
55
55
|
var _a, _b;
|
|
56
56
|
if (e.shiftKey) {
|
|
57
57
|
item.selectUpTo(e.ctrlKey || e.metaKey);
|
|
@@ -63,7 +63,7 @@ exports.selectionFeature = {
|
|
|
63
63
|
tree.setSelectedItems([item.getItemMeta().itemId]);
|
|
64
64
|
}
|
|
65
65
|
(_b = (_a = prev.getProps()).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, e);
|
|
66
|
-
} })) })),
|
|
66
|
+
}) })) })),
|
|
67
67
|
hotkeys: {
|
|
68
68
|
// setSelectedItem: {
|
|
69
69
|
// hotkey: "space",
|
|
@@ -108,7 +108,8 @@ exports.treeFeature = {
|
|
|
108
108
|
}, getId: () => item.getItemMeta().itemId, getProps: () => {
|
|
109
109
|
var _a;
|
|
110
110
|
const itemMeta = item.getItemMeta();
|
|
111
|
-
return Object.assign(Object.assign({}, (_a = prev.getProps) === null || _a === void 0 ? void 0 : _a.call(prev)), { role: "treeitem", "aria-setsize": itemMeta.setSize, "aria-posinset": itemMeta.posInSet, "aria-selected": false, "aria-label": item.getItemName(), "aria-level": itemMeta.level, tabIndex: item.isFocused() ? 0 : -1, onClick: (e) => {
|
|
111
|
+
return Object.assign(Object.assign({}, (_a = prev.getProps) === null || _a === void 0 ? void 0 : _a.call(prev)), { role: "treeitem", "aria-setsize": itemMeta.setSize, "aria-posinset": itemMeta.posInSet, "aria-selected": false, "aria-label": item.getItemName(), "aria-level": itemMeta.level, tabIndex: item.isFocused() ? 0 : -1, onClick: item.getMemoizedProp("tree/onClick", () => (e) => {
|
|
112
|
+
console.log("onClick", item.getId());
|
|
112
113
|
item.setFocused();
|
|
113
114
|
item.primaryAction();
|
|
114
115
|
if (e.ctrlKey || e.shiftKey || e.metaKey) {
|
|
@@ -123,7 +124,7 @@ exports.treeFeature = {
|
|
|
123
124
|
else {
|
|
124
125
|
item.expand();
|
|
125
126
|
}
|
|
126
|
-
} });
|
|
127
|
+
}) });
|
|
127
128
|
}, expand: () => tree.expandItem(item.getItemMeta().itemId), collapse: () => tree.collapseItem(item.getItemMeta().itemId), getItemData: () => tree.retrieveItemData(item.getItemMeta().itemId), isExpanded: () => tree.getState().expandedItems.includes(item.getItemMeta().itemId), isFocused: () => tree.getState().focusedItem === item.getItemMeta().itemId ||
|
|
128
129
|
(tree.getState().focusedItem === null && item.getItemMeta().index === 0), isFolder: () => item.getItemMeta().level === -1 ||
|
|
129
130
|
tree.getConfig().isItemFolder(item), getItemName: () => {
|
|
@@ -144,7 +145,23 @@ exports.treeFeature = {
|
|
|
144
145
|
1;
|
|
145
146
|
}, getChildren: () => tree
|
|
146
147
|
.retrieveChildrenIds(item.getItemMeta().itemId)
|
|
147
|
-
.map((id) => tree.getItemInstance(id)), getTree: () => tree, getItemAbove: () => tree.getItems()[item.getItemMeta().index - 1], getItemBelow: () => tree.getItems()[item.getItemMeta().index + 1]
|
|
148
|
+
.map((id) => tree.getItemInstance(id)), getTree: () => tree, getItemAbove: () => tree.getItems()[item.getItemMeta().index - 1], getItemBelow: () => tree.getItems()[item.getItemMeta().index + 1], getMemoizedProp: (name, create, deps) => {
|
|
149
|
+
var _a, _b, _c, _d, _e;
|
|
150
|
+
var _f, _g;
|
|
151
|
+
const data = item.getDataRef();
|
|
152
|
+
const memoizedValue = (_a = data.current.memoizedValues) === null || _a === void 0 ? void 0 : _a[name];
|
|
153
|
+
if (memoizedValue &&
|
|
154
|
+
(!deps ||
|
|
155
|
+
((_c = (_b = data.current.memoizedDeps) === null || _b === void 0 ? void 0 : _b[name]) === null || _c === void 0 ? void 0 : _c.every((d, i) => d === deps[i])))) {
|
|
156
|
+
return memoizedValue;
|
|
157
|
+
}
|
|
158
|
+
(_d = (_f = data.current).memoizedDeps) !== null && _d !== void 0 ? _d : (_f.memoizedDeps = {});
|
|
159
|
+
(_e = (_g = data.current).memoizedValues) !== null && _e !== void 0 ? _e : (_g.memoizedValues = {});
|
|
160
|
+
const value = create();
|
|
161
|
+
data.current.memoizedDeps[name] = deps;
|
|
162
|
+
data.current.memoizedValues[name] = value;
|
|
163
|
+
return value;
|
|
164
|
+
} })),
|
|
148
165
|
hotkeys: {
|
|
149
166
|
focusNextItem: {
|
|
150
167
|
hotkey: "ArrowDown",
|
|
@@ -7,6 +7,10 @@ export type ItemMeta = {
|
|
|
7
7
|
setSize: number;
|
|
8
8
|
posInSet: number;
|
|
9
9
|
};
|
|
10
|
+
export type TreeItemDataRef = {
|
|
11
|
+
memoizedValues: Record<string, any>;
|
|
12
|
+
memoizedDeps: Record<string, any[] | undefined>;
|
|
13
|
+
};
|
|
10
14
|
export type TreeFeatureDef<T> = {
|
|
11
15
|
state: {
|
|
12
16
|
expandedItems: string[];
|
|
@@ -52,6 +56,7 @@ export type TreeFeatureDef<T> = {
|
|
|
52
56
|
getTree: () => TreeInstance<T>;
|
|
53
57
|
getItemAbove: () => ItemInstance<T> | null;
|
|
54
58
|
getItemBelow: () => ItemInstance<T> | null;
|
|
59
|
+
getMemoizedProp: <X>(name: string, create: () => X, deps?: any[]) => X;
|
|
55
60
|
};
|
|
56
61
|
hotkeys: "focusNextItem" | "focusPreviousItem" | "expandOrDown" | "collapseOrUp" | "focusFirstItem" | "focusLastItem";
|
|
57
62
|
};
|
|
@@ -8,10 +8,10 @@ const buildItemInstance = (features, tree, itemId) => {
|
|
|
8
8
|
return itemInstance;
|
|
9
9
|
};
|
|
10
10
|
export const createTree = (initialConfig) => {
|
|
11
|
-
var _a, _b, _c, _d, _e;
|
|
11
|
+
var _a, _b, _c, _d, _e, _f;
|
|
12
12
|
const treeInstance = {};
|
|
13
13
|
const additionalFeatures = [treeFeature, ...((_a = initialConfig.features) !== null && _a !== void 0 ? _a : [])];
|
|
14
|
-
let state = additionalFeatures.reduce((acc, feature) => { var _a, _b; return (_b = (_a = feature.getInitialState) === null || _a === void 0 ? void 0 : _a.call(feature, acc, treeInstance)) !== null && _b !== void 0 ? _b : acc; }, (_b = initialConfig.
|
|
14
|
+
let state = additionalFeatures.reduce((acc, feature) => { var _a, _b; return (_b = (_a = feature.getInitialState) === null || _a === void 0 ? void 0 : _a.call(feature, acc, treeInstance)) !== null && _b !== void 0 ? _b : acc; }, (_c = (_b = initialConfig.initialState) !== null && _b !== void 0 ? _b : initialConfig.state) !== null && _c !== void 0 ? _c : {});
|
|
15
15
|
let config = additionalFeatures.reduce((acc, feature) => { var _a, _b; return (_b = (_a = feature.getDefaultConfig) === null || _a === void 0 ? void 0 : _a.call(feature, acc, treeInstance)) !== null && _b !== void 0 ? _b : acc; }, initialConfig);
|
|
16
16
|
let treeElement;
|
|
17
17
|
const treeDataRef = { current: {} };
|
|
@@ -104,8 +104,8 @@ export const createTree = (initialConfig) => {
|
|
|
104
104
|
// todo sort features
|
|
105
105
|
const features = [mainFeature, ...additionalFeatures];
|
|
106
106
|
for (const feature of features) {
|
|
107
|
-
Object.assign(treeInstance, (
|
|
108
|
-
Object.assign(hotkeyPresets, (
|
|
107
|
+
Object.assign(treeInstance, (_e = (_d = feature.createTreeInstance) === null || _d === void 0 ? void 0 : _d.call(feature, Object.assign({}, treeInstance), treeInstance)) !== null && _e !== void 0 ? _e : {});
|
|
108
|
+
Object.assign(hotkeyPresets, (_f = feature.hotkeys) !== null && _f !== void 0 ? _f : {});
|
|
109
109
|
}
|
|
110
110
|
rebuildItemMeta(mainFeature);
|
|
111
111
|
return treeInstance;
|
|
@@ -10,7 +10,7 @@ export const dragAndDropFeature = {
|
|
|
10
10
|
} })),
|
|
11
11
|
createItemInstance: (prev, item, tree) => (Object.assign(Object.assign({}, prev), { getProps: () => {
|
|
12
12
|
var _a, _b, _c;
|
|
13
|
-
return (Object.assign(Object.assign({}, prev.getProps()), { draggable: (_c = (_b = (_a = tree.getConfig()).isItemDraggable) === null || _b === void 0 ? void 0 : _b.call(_a, item)) !== null && _c !== void 0 ? _c : true, onDragStart: (e) => {
|
|
13
|
+
return (Object.assign(Object.assign({}, prev.getProps()), { draggable: (_c = (_b = (_a = tree.getConfig()).isItemDraggable) === null || _b === void 0 ? void 0 : _b.call(_a, item)) !== null && _c !== void 0 ? _c : true, onDragStart: item.getMemoizedProp("dnd/onDragStart", () => (e) => {
|
|
14
14
|
var _a, _b, _c, _d, _e;
|
|
15
15
|
const selectedItems = tree.getSelectedItems();
|
|
16
16
|
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
@@ -30,7 +30,7 @@ export const dragAndDropFeature = {
|
|
|
30
30
|
draggedItems: items,
|
|
31
31
|
draggingOverItem: tree.getFocusedItem(),
|
|
32
32
|
});
|
|
33
|
-
}, onDragOver: (e) => {
|
|
33
|
+
}), onDragOver: item.getMemoizedProp("dnd/onDragOver", () => (e) => {
|
|
34
34
|
var _a, _b, _c, _d, _e;
|
|
35
35
|
const target = getDropTarget(e, item, tree);
|
|
36
36
|
const dataRef = tree.getDataRef();
|
|
@@ -48,12 +48,12 @@ export const dragAndDropFeature = {
|
|
|
48
48
|
}
|
|
49
49
|
dataRef.current.lastDragCode = nextDragCode;
|
|
50
50
|
(_e = (_d = tree.getConfig()).setDndState) === null || _e === void 0 ? void 0 : _e.call(_d, (state) => (Object.assign(Object.assign({}, state), { dragTarget: target, draggingOverItem: item })));
|
|
51
|
-
}, onDragLeave: () => {
|
|
51
|
+
}), onDragLeave: item.getMemoizedProp("dnd/onDragLeave", () => () => {
|
|
52
52
|
var _a, _b;
|
|
53
53
|
const dataRef = tree.getDataRef();
|
|
54
54
|
dataRef.current.lastDragCode = "no-drag";
|
|
55
55
|
(_b = (_a = tree.getConfig()).setDndState) === null || _b === void 0 ? void 0 : _b.call(_a, (state) => (Object.assign(Object.assign({}, state), { draggingOverItem: undefined, dragTarget: undefined })));
|
|
56
|
-
}, onDrop: (e) => {
|
|
56
|
+
}), onDrop: item.getMemoizedProp("dnd/onDrop", () => (e) => {
|
|
57
57
|
var _a, _b, _c, _d, _e;
|
|
58
58
|
const dataRef = tree.getDataRef();
|
|
59
59
|
const target = getDropTarget(e, item, tree);
|
|
@@ -72,7 +72,7 @@ export const dragAndDropFeature = {
|
|
|
72
72
|
(_e = config.onDropForeignDragObject) === null || _e === void 0 ? void 0 : _e.call(config, e.dataTransfer, target);
|
|
73
73
|
}
|
|
74
74
|
// TODO rebuild tree?
|
|
75
|
-
} }));
|
|
75
|
+
}) }));
|
|
76
76
|
}, isDropTarget: () => {
|
|
77
77
|
const target = tree.getDropTarget();
|
|
78
78
|
return target ? target.item.getId() === item.getId() : false;
|
|
@@ -48,7 +48,7 @@ export const selectionFeature = {
|
|
|
48
48
|
else {
|
|
49
49
|
item.select();
|
|
50
50
|
}
|
|
51
|
-
}, getProps: () => (Object.assign(Object.assign({}, prev.getProps()), { onClick: (e) => {
|
|
51
|
+
}, getProps: () => (Object.assign(Object.assign({}, prev.getProps()), { onClick: item.getMemoizedProp("selection/onClick", () => (e) => {
|
|
52
52
|
var _a, _b;
|
|
53
53
|
if (e.shiftKey) {
|
|
54
54
|
item.selectUpTo(e.ctrlKey || e.metaKey);
|
|
@@ -60,7 +60,7 @@ export const selectionFeature = {
|
|
|
60
60
|
tree.setSelectedItems([item.getItemMeta().itemId]);
|
|
61
61
|
}
|
|
62
62
|
(_b = (_a = prev.getProps()).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, e);
|
|
63
|
-
} })) })),
|
|
63
|
+
}) })) })),
|
|
64
64
|
hotkeys: {
|
|
65
65
|
// setSelectedItem: {
|
|
66
66
|
// hotkey: "space",
|
|
@@ -105,7 +105,8 @@ export const treeFeature = {
|
|
|
105
105
|
}, getId: () => item.getItemMeta().itemId, getProps: () => {
|
|
106
106
|
var _a;
|
|
107
107
|
const itemMeta = item.getItemMeta();
|
|
108
|
-
return Object.assign(Object.assign({}, (_a = prev.getProps) === null || _a === void 0 ? void 0 : _a.call(prev)), { role: "treeitem", "aria-setsize": itemMeta.setSize, "aria-posinset": itemMeta.posInSet, "aria-selected": false, "aria-label": item.getItemName(), "aria-level": itemMeta.level, tabIndex: item.isFocused() ? 0 : -1, onClick: (e) => {
|
|
108
|
+
return Object.assign(Object.assign({}, (_a = prev.getProps) === null || _a === void 0 ? void 0 : _a.call(prev)), { role: "treeitem", "aria-setsize": itemMeta.setSize, "aria-posinset": itemMeta.posInSet, "aria-selected": false, "aria-label": item.getItemName(), "aria-level": itemMeta.level, tabIndex: item.isFocused() ? 0 : -1, onClick: item.getMemoizedProp("tree/onClick", () => (e) => {
|
|
109
|
+
console.log("onClick", item.getId());
|
|
109
110
|
item.setFocused();
|
|
110
111
|
item.primaryAction();
|
|
111
112
|
if (e.ctrlKey || e.shiftKey || e.metaKey) {
|
|
@@ -120,7 +121,7 @@ export const treeFeature = {
|
|
|
120
121
|
else {
|
|
121
122
|
item.expand();
|
|
122
123
|
}
|
|
123
|
-
} });
|
|
124
|
+
}) });
|
|
124
125
|
}, expand: () => tree.expandItem(item.getItemMeta().itemId), collapse: () => tree.collapseItem(item.getItemMeta().itemId), getItemData: () => tree.retrieveItemData(item.getItemMeta().itemId), isExpanded: () => tree.getState().expandedItems.includes(item.getItemMeta().itemId), isFocused: () => tree.getState().focusedItem === item.getItemMeta().itemId ||
|
|
125
126
|
(tree.getState().focusedItem === null && item.getItemMeta().index === 0), isFolder: () => item.getItemMeta().level === -1 ||
|
|
126
127
|
tree.getConfig().isItemFolder(item), getItemName: () => {
|
|
@@ -141,7 +142,23 @@ export const treeFeature = {
|
|
|
141
142
|
1;
|
|
142
143
|
}, getChildren: () => tree
|
|
143
144
|
.retrieveChildrenIds(item.getItemMeta().itemId)
|
|
144
|
-
.map((id) => tree.getItemInstance(id)), getTree: () => tree, getItemAbove: () => tree.getItems()[item.getItemMeta().index - 1], getItemBelow: () => tree.getItems()[item.getItemMeta().index + 1]
|
|
145
|
+
.map((id) => tree.getItemInstance(id)), getTree: () => tree, getItemAbove: () => tree.getItems()[item.getItemMeta().index - 1], getItemBelow: () => tree.getItems()[item.getItemMeta().index + 1], getMemoizedProp: (name, create, deps) => {
|
|
146
|
+
var _a, _b, _c, _d, _e;
|
|
147
|
+
var _f, _g;
|
|
148
|
+
const data = item.getDataRef();
|
|
149
|
+
const memoizedValue = (_a = data.current.memoizedValues) === null || _a === void 0 ? void 0 : _a[name];
|
|
150
|
+
if (memoizedValue &&
|
|
151
|
+
(!deps ||
|
|
152
|
+
((_c = (_b = data.current.memoizedDeps) === null || _b === void 0 ? void 0 : _b[name]) === null || _c === void 0 ? void 0 : _c.every((d, i) => d === deps[i])))) {
|
|
153
|
+
return memoizedValue;
|
|
154
|
+
}
|
|
155
|
+
(_d = (_f = data.current).memoizedDeps) !== null && _d !== void 0 ? _d : (_f.memoizedDeps = {});
|
|
156
|
+
(_e = (_g = data.current).memoizedValues) !== null && _e !== void 0 ? _e : (_g.memoizedValues = {});
|
|
157
|
+
const value = create();
|
|
158
|
+
data.current.memoizedDeps[name] = deps;
|
|
159
|
+
data.current.memoizedValues[name] = value;
|
|
160
|
+
return value;
|
|
161
|
+
} })),
|
|
145
162
|
hotkeys: {
|
|
146
163
|
focusNextItem: {
|
|
147
164
|
hotkey: "ArrowDown",
|
|
@@ -7,6 +7,10 @@ export type ItemMeta = {
|
|
|
7
7
|
setSize: number;
|
|
8
8
|
posInSet: number;
|
|
9
9
|
};
|
|
10
|
+
export type TreeItemDataRef = {
|
|
11
|
+
memoizedValues: Record<string, any>;
|
|
12
|
+
memoizedDeps: Record<string, any[] | undefined>;
|
|
13
|
+
};
|
|
10
14
|
export type TreeFeatureDef<T> = {
|
|
11
15
|
state: {
|
|
12
16
|
expandedItems: string[];
|
|
@@ -52,6 +56,7 @@ export type TreeFeatureDef<T> = {
|
|
|
52
56
|
getTree: () => TreeInstance<T>;
|
|
53
57
|
getItemAbove: () => ItemInstance<T> | null;
|
|
54
58
|
getItemBelow: () => ItemInstance<T> | null;
|
|
59
|
+
getMemoizedProp: <X>(name: string, create: () => X, deps?: any[]) => X;
|
|
55
60
|
};
|
|
56
61
|
hotkeys: "focusNextItem" | "focusPreviousItem" | "expandOrDown" | "collapseOrUp" | "focusFirstItem" | "focusLastItem";
|
|
57
62
|
};
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@headless-tree/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"main": "lib/cjs/index.js",
|
|
5
5
|
"module": "lib/esm/index.js",
|
|
6
6
|
"types": "lib/esm/index.d.ts",
|
|
7
7
|
"sideEffects": false,
|
|
8
8
|
"scripts": {
|
|
9
|
-
"build:cjs": "tsc",
|
|
10
|
-
"build:esm": "tsc
|
|
9
|
+
"build:cjs": "tsc -m commonjs --outDir lib/cjs",
|
|
10
|
+
"build:esm": "tsc",
|
|
11
11
|
"start": "tsc -w"
|
|
12
12
|
},
|
|
13
13
|
"repository": {
|
package/src/core/create-tree.ts
CHANGED
|
@@ -38,7 +38,7 @@ export const createTree = <T>(
|
|
|
38
38
|
const additionalFeatures = [treeFeature, ...(initialConfig.features ?? [])];
|
|
39
39
|
let state = additionalFeatures.reduce(
|
|
40
40
|
(acc, feature) => feature.getInitialState?.(acc, treeInstance) ?? acc,
|
|
41
|
-
initialConfig.state ?? {}
|
|
41
|
+
initialConfig.initialState ?? initialConfig.state ?? {}
|
|
42
42
|
) as TreeState<T>;
|
|
43
43
|
let config = additionalFeatures.reduce(
|
|
44
44
|
(acc, feature) => feature.getDefaultConfig?.(acc, treeInstance) ?? acc,
|
|
@@ -33,7 +33,7 @@ export const dragAndDropFeature: FeatureImplementation<
|
|
|
33
33
|
|
|
34
34
|
draggable: tree.getConfig().isItemDraggable?.(item) ?? true,
|
|
35
35
|
|
|
36
|
-
onDragStart: (e) => {
|
|
36
|
+
onDragStart: item.getMemoizedProp("dnd/onDragStart", () => (e) => {
|
|
37
37
|
const selectedItems = tree.getSelectedItems();
|
|
38
38
|
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
39
39
|
const config = tree.getConfig();
|
|
@@ -56,9 +56,9 @@ export const dragAndDropFeature: FeatureImplementation<
|
|
|
56
56
|
draggedItems: items,
|
|
57
57
|
draggingOverItem: tree.getFocusedItem(),
|
|
58
58
|
});
|
|
59
|
-
},
|
|
59
|
+
}),
|
|
60
60
|
|
|
61
|
-
onDragOver: (e) => {
|
|
61
|
+
onDragOver: item.getMemoizedProp("dnd/onDragOver", () => (e) => {
|
|
62
62
|
const target = getDropTarget(e, item, tree);
|
|
63
63
|
const dataRef = tree.getDataRef<DndDataRef>();
|
|
64
64
|
|
|
@@ -87,9 +87,9 @@ export const dragAndDropFeature: FeatureImplementation<
|
|
|
87
87
|
dragTarget: target,
|
|
88
88
|
draggingOverItem: item,
|
|
89
89
|
}));
|
|
90
|
-
},
|
|
90
|
+
}),
|
|
91
91
|
|
|
92
|
-
onDragLeave: () => {
|
|
92
|
+
onDragLeave: item.getMemoizedProp("dnd/onDragLeave", () => () => {
|
|
93
93
|
const dataRef = tree.getDataRef<DndDataRef>();
|
|
94
94
|
dataRef.current.lastDragCode = "no-drag";
|
|
95
95
|
tree.getConfig().setDndState?.((state) => ({
|
|
@@ -97,9 +97,9 @@ export const dragAndDropFeature: FeatureImplementation<
|
|
|
97
97
|
draggingOverItem: undefined,
|
|
98
98
|
dragTarget: undefined,
|
|
99
99
|
}));
|
|
100
|
-
},
|
|
100
|
+
}),
|
|
101
101
|
|
|
102
|
-
onDrop: (e) => {
|
|
102
|
+
onDrop: item.getMemoizedProp("dnd/onDrop", () => (e) => {
|
|
103
103
|
const dataRef = tree.getDataRef<DndDataRef>();
|
|
104
104
|
const target = getDropTarget(e, item, tree);
|
|
105
105
|
|
|
@@ -120,7 +120,7 @@ export const dragAndDropFeature: FeatureImplementation<
|
|
|
120
120
|
config.onDropForeignDragObject?.(e.dataTransfer, target);
|
|
121
121
|
}
|
|
122
122
|
// TODO rebuild tree?
|
|
123
|
-
},
|
|
123
|
+
}),
|
|
124
124
|
}),
|
|
125
125
|
|
|
126
126
|
isDropTarget: () => {
|
|
@@ -91,7 +91,7 @@ export const selectionFeature: FeatureImplementation<
|
|
|
91
91
|
|
|
92
92
|
getProps: () => ({
|
|
93
93
|
...prev.getProps(),
|
|
94
|
-
onClick: (e) => {
|
|
94
|
+
onClick: item.getMemoizedProp("selection/onClick", () => (e) => {
|
|
95
95
|
if (e.shiftKey) {
|
|
96
96
|
item.selectUpTo(e.ctrlKey || e.metaKey);
|
|
97
97
|
} else if (e.ctrlKey || e.metaKey) {
|
|
@@ -101,7 +101,7 @@ export const selectionFeature: FeatureImplementation<
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
prev.getProps().onClick?.(e);
|
|
104
|
-
},
|
|
104
|
+
}),
|
|
105
105
|
}),
|
|
106
106
|
}),
|
|
107
107
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FeatureImplementation, ItemInstance } from "../../types/core";
|
|
2
|
-
import { ItemMeta, TreeFeatureDef } from "./types";
|
|
2
|
+
import { ItemMeta, TreeFeatureDef, TreeItemDataRef } from "./types";
|
|
3
3
|
import { makeStateUpdater, memo, poll } from "../../utils";
|
|
4
4
|
import { MainFeatureDef } from "../main/types";
|
|
5
5
|
import { HotkeysCoreFeatureDef } from "../hotkeys-core/types";
|
|
@@ -174,7 +174,8 @@ export const treeFeature: FeatureImplementation<
|
|
|
174
174
|
"aria-label": item.getItemName(),
|
|
175
175
|
"aria-level": itemMeta.level,
|
|
176
176
|
tabIndex: item.isFocused() ? 0 : -1,
|
|
177
|
-
onClick: (e) => {
|
|
177
|
+
onClick: item.getMemoizedProp("tree/onClick", () => (e) => {
|
|
178
|
+
console.log("onClick", item.getId());
|
|
178
179
|
item.setFocused();
|
|
179
180
|
item.primaryAction();
|
|
180
181
|
|
|
@@ -191,7 +192,7 @@ export const treeFeature: FeatureImplementation<
|
|
|
191
192
|
} else {
|
|
192
193
|
item.expand();
|
|
193
194
|
}
|
|
194
|
-
},
|
|
195
|
+
}),
|
|
195
196
|
};
|
|
196
197
|
},
|
|
197
198
|
expand: () => tree.expandItem(item.getItemMeta().itemId),
|
|
@@ -235,6 +236,23 @@ export const treeFeature: FeatureImplementation<
|
|
|
235
236
|
getTree: () => tree as any,
|
|
236
237
|
getItemAbove: () => tree.getItems()[item.getItemMeta().index - 1],
|
|
237
238
|
getItemBelow: () => tree.getItems()[item.getItemMeta().index + 1],
|
|
239
|
+
getMemoizedProp: (name, create, deps) => {
|
|
240
|
+
const data = item.getDataRef<TreeItemDataRef>();
|
|
241
|
+
const memoizedValue = data.current.memoizedValues?.[name];
|
|
242
|
+
if (
|
|
243
|
+
memoizedValue &&
|
|
244
|
+
(!deps ||
|
|
245
|
+
data.current.memoizedDeps?.[name]?.every((d, i) => d === deps![i]))
|
|
246
|
+
) {
|
|
247
|
+
return memoizedValue;
|
|
248
|
+
}
|
|
249
|
+
data.current.memoizedDeps ??= {};
|
|
250
|
+
data.current.memoizedValues ??= {};
|
|
251
|
+
const value = create();
|
|
252
|
+
data.current.memoizedDeps[name] = deps;
|
|
253
|
+
data.current.memoizedValues[name] = value;
|
|
254
|
+
return value;
|
|
255
|
+
},
|
|
238
256
|
}),
|
|
239
257
|
|
|
240
258
|
hotkeys: {
|
|
@@ -9,6 +9,11 @@ export type ItemMeta = {
|
|
|
9
9
|
posInSet: number;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
export type TreeItemDataRef = {
|
|
13
|
+
memoizedValues: Record<string, any>;
|
|
14
|
+
memoizedDeps: Record<string, any[] | undefined>;
|
|
15
|
+
};
|
|
16
|
+
|
|
12
17
|
export type TreeFeatureDef<T> = {
|
|
13
18
|
state: {
|
|
14
19
|
expandedItems: string[];
|
|
@@ -59,6 +64,7 @@ export type TreeFeatureDef<T> = {
|
|
|
59
64
|
getTree: () => TreeInstance<T>;
|
|
60
65
|
getItemAbove: () => ItemInstance<T> | null;
|
|
61
66
|
getItemBelow: () => ItemInstance<T> | null;
|
|
67
|
+
getMemoizedProp: <X>(name: string, create: () => X, deps?: any[]) => X;
|
|
62
68
|
};
|
|
63
69
|
hotkeys:
|
|
64
70
|
| "focusNextItem"
|