@edux-design/tree-select 0.1.0 → 0.1.2
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/README.md +27 -0
- package/dist/index.d.mts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +181 -27
- package/dist/index.mjs +182 -28
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -134,18 +134,42 @@ Allows multi-select drag using CMD/CTRL or SHIFT. Selection is restricted to adj
|
|
|
134
134
|
### `isEditable` (boolean, default `false`)
|
|
135
135
|
Enables inline label editing and add-item controls.
|
|
136
136
|
|
|
137
|
+
### `allowDelete` (boolean, default `false`)
|
|
138
|
+
Shows a delete action for each item and removes the node (plus descendants).
|
|
139
|
+
|
|
137
140
|
### `useChevron` (boolean, default `false`)
|
|
138
141
|
Uses a chevron control for expand/collapse instead of the checkbox toggle.
|
|
139
142
|
|
|
143
|
+
### `defaultExpanded` (`"all"` | number | string[] | Set<string | number>)
|
|
144
|
+
Defines the initial expansion state. Use `"all"` to expand every node with children, a number to expand up to that level (1 expands top-level nodes), or an array/set of ids to expand specific items.
|
|
145
|
+
|
|
146
|
+
### `expanded` (`"all"` | number | string[] | Set<string | number>)
|
|
147
|
+
Controlled expansion state. When provided, the tree expansion is driven by this value.
|
|
148
|
+
|
|
149
|
+
### `onExpandedChange` (function)
|
|
150
|
+
Called with a `Set` of expanded ids when the user toggles expansion in controlled mode.
|
|
151
|
+
|
|
140
152
|
### `maxDepth` (number)
|
|
141
153
|
Limits how deep new items can be added. For example, `maxDepth={3}` allows at most 3 levels.
|
|
142
154
|
|
|
143
155
|
### `addChildTooltip` (string)
|
|
144
156
|
Tooltip copy for the add-child button.
|
|
145
157
|
|
|
158
|
+
### `addChildTooltipByLevel` (string[])
|
|
159
|
+
Tooltip copy for add-child, keyed by depth. Overrides `addChildTooltip` when provided.
|
|
160
|
+
|
|
146
161
|
### `addSiblingTooltip` (string)
|
|
147
162
|
Tooltip copy for the add-sibling button.
|
|
148
163
|
|
|
164
|
+
### `addSiblingTooltipByLevel` (string[])
|
|
165
|
+
Tooltip copy for add-sibling, keyed by depth. Overrides `addSiblingTooltip` when provided.
|
|
166
|
+
|
|
167
|
+
### `deleteTooltip` (string)
|
|
168
|
+
Tooltip copy for the delete button.
|
|
169
|
+
|
|
170
|
+
### `deleteTooltipByLevel` (string[])
|
|
171
|
+
Tooltip copy for delete, keyed by depth. Overrides `deleteTooltip` when provided.
|
|
172
|
+
|
|
149
173
|
---
|
|
150
174
|
|
|
151
175
|
## Behaviour details
|
|
@@ -154,6 +178,9 @@ Tooltip copy for the add-sibling button.
|
|
|
154
178
|
- Leaf nodes do not render a checkbox/chevron toggle.
|
|
155
179
|
- Expansion only controls visibility of children.
|
|
156
180
|
- When `useChevron` is `false`, the toggle uses the Checkbox plus/indeterminate states.
|
|
181
|
+
- `defaultExpanded` only seeds the initial state; use `expanded` for controlled expansion.
|
|
182
|
+
- When `expanded` is provided, `onExpandedChange` is called with the next set of expanded ids.
|
|
183
|
+
- Deleting a node removes the entire subtree and clears any selected/expanded state for those ids.
|
|
157
184
|
- Drag-and-drop supports reordering within a level and moving items between levels.
|
|
158
185
|
- Drag handle alignment is set so child handles align under the parent toggle.
|
|
159
186
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
|
|
3
|
-
declare function TreeSelect({ data, onDataChange, allowDragAndDrop, allowMultiDrag, isEditable, useChevron, maxDepth, addChildTooltip, addSiblingTooltip, }: {
|
|
3
|
+
declare function TreeSelect({ data, onDataChange, allowDragAndDrop, allowMultiDrag, isEditable, allowDelete, useChevron, maxDepth, addChildTooltip, addSiblingTooltip, deleteTooltip, addChildTooltipByLevel, addSiblingTooltipByLevel, deleteTooltipByLevel, defaultExpanded, expanded, onExpandedChange, }: {
|
|
4
4
|
data: any;
|
|
5
5
|
onDataChange: any;
|
|
6
6
|
allowDragAndDrop?: boolean;
|
|
7
7
|
allowMultiDrag?: boolean;
|
|
8
8
|
isEditable?: boolean;
|
|
9
|
+
allowDelete?: boolean;
|
|
9
10
|
useChevron?: boolean;
|
|
10
11
|
maxDepth: any;
|
|
11
12
|
addChildTooltip: any;
|
|
12
13
|
addSiblingTooltip: any;
|
|
14
|
+
deleteTooltip: any;
|
|
15
|
+
addChildTooltipByLevel: any;
|
|
16
|
+
addSiblingTooltipByLevel: any;
|
|
17
|
+
deleteTooltipByLevel: any;
|
|
18
|
+
defaultExpanded: any;
|
|
19
|
+
expanded: any;
|
|
20
|
+
onExpandedChange: any;
|
|
13
21
|
}): react_jsx_runtime.JSX.Element;
|
|
14
22
|
|
|
15
23
|
export { TreeSelect };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
|
|
3
|
-
declare function TreeSelect({ data, onDataChange, allowDragAndDrop, allowMultiDrag, isEditable, useChevron, maxDepth, addChildTooltip, addSiblingTooltip, }: {
|
|
3
|
+
declare function TreeSelect({ data, onDataChange, allowDragAndDrop, allowMultiDrag, isEditable, allowDelete, useChevron, maxDepth, addChildTooltip, addSiblingTooltip, deleteTooltip, addChildTooltipByLevel, addSiblingTooltipByLevel, deleteTooltipByLevel, defaultExpanded, expanded, onExpandedChange, }: {
|
|
4
4
|
data: any;
|
|
5
5
|
onDataChange: any;
|
|
6
6
|
allowDragAndDrop?: boolean;
|
|
7
7
|
allowMultiDrag?: boolean;
|
|
8
8
|
isEditable?: boolean;
|
|
9
|
+
allowDelete?: boolean;
|
|
9
10
|
useChevron?: boolean;
|
|
10
11
|
maxDepth: any;
|
|
11
12
|
addChildTooltip: any;
|
|
12
13
|
addSiblingTooltip: any;
|
|
14
|
+
deleteTooltip: any;
|
|
15
|
+
addChildTooltipByLevel: any;
|
|
16
|
+
addSiblingTooltipByLevel: any;
|
|
17
|
+
deleteTooltipByLevel: any;
|
|
18
|
+
defaultExpanded: any;
|
|
19
|
+
expanded: any;
|
|
20
|
+
onExpandedChange: any;
|
|
13
21
|
}): react_jsx_runtime.JSX.Element;
|
|
14
22
|
|
|
15
23
|
export { TreeSelect };
|
package/dist/index.js
CHANGED
|
@@ -5764,13 +5764,17 @@ var TreeRow = ({
|
|
|
5764
5764
|
onAddChild,
|
|
5765
5765
|
onAddSibling,
|
|
5766
5766
|
addChildTooltip,
|
|
5767
|
-
addSiblingTooltip
|
|
5767
|
+
addSiblingTooltip,
|
|
5768
|
+
canDelete,
|
|
5769
|
+
onDelete,
|
|
5770
|
+
deleteTooltip
|
|
5768
5771
|
}) => {
|
|
5769
5772
|
const toggleLabel = isExpanded ? "Collapse item" : "Expand item";
|
|
5770
5773
|
const label = item.node.label ?? item.node.id;
|
|
5771
5774
|
const showToggle = item.hasChildren;
|
|
5772
5775
|
const rowBackground = isDragging ? "rgba(0, 0, 0, 0.04)" : isSelected ? "rgba(15, 98, 254, 0.08)" : void 0;
|
|
5773
5776
|
const rowPaddingLeft = depth * INDENT_WIDTH + 8 + (isDraggable ? 0 : HANDLE_WIDTH + 8);
|
|
5777
|
+
const showActions = canAddChild || canAddSibling || canDelete;
|
|
5774
5778
|
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
5775
5779
|
"div",
|
|
5776
5780
|
{
|
|
@@ -5883,7 +5887,7 @@ var TreeRow = ({
|
|
|
5883
5887
|
children: label
|
|
5884
5888
|
}
|
|
5885
5889
|
),
|
|
5886
|
-
|
|
5890
|
+
showActions ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
5887
5891
|
"div",
|
|
5888
5892
|
{
|
|
5889
5893
|
onClick: (event) => event.stopPropagation(),
|
|
@@ -5914,6 +5918,19 @@ var TreeRow = ({
|
|
|
5914
5918
|
}
|
|
5915
5919
|
) }),
|
|
5916
5920
|
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent2, { children: addSiblingTooltip ?? "Add sibling" })
|
|
5921
|
+
] }) : null,
|
|
5922
|
+
canDelete ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip2, { children: [
|
|
5923
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
5924
|
+
IconButton,
|
|
5925
|
+
{
|
|
5926
|
+
size: "small",
|
|
5927
|
+
isBare: true,
|
|
5928
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_icons.Close, { "aria-hidden": "true" }),
|
|
5929
|
+
"aria-label": "Delete item",
|
|
5930
|
+
onClick: () => onDelete == null ? void 0 : onDelete(item.id)
|
|
5931
|
+
}
|
|
5932
|
+
) }),
|
|
5933
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent2, { children: deleteTooltip ?? "Delete item" })
|
|
5917
5934
|
] }) : null
|
|
5918
5935
|
]
|
|
5919
5936
|
}
|
|
@@ -5949,7 +5966,10 @@ var TreeSortableRow = ({
|
|
|
5949
5966
|
onAddChild,
|
|
5950
5967
|
onAddSibling,
|
|
5951
5968
|
addChildTooltip,
|
|
5952
|
-
addSiblingTooltip
|
|
5969
|
+
addSiblingTooltip,
|
|
5970
|
+
canDelete,
|
|
5971
|
+
onDelete,
|
|
5972
|
+
deleteTooltip
|
|
5953
5973
|
}) => {
|
|
5954
5974
|
const {
|
|
5955
5975
|
attributes,
|
|
@@ -6007,7 +6027,10 @@ var TreeSortableRow = ({
|
|
|
6007
6027
|
onAddChild,
|
|
6008
6028
|
onAddSibling,
|
|
6009
6029
|
addChildTooltip,
|
|
6010
|
-
addSiblingTooltip
|
|
6030
|
+
addSiblingTooltip,
|
|
6031
|
+
canDelete,
|
|
6032
|
+
onDelete,
|
|
6033
|
+
deleteTooltip
|
|
6011
6034
|
}
|
|
6012
6035
|
);
|
|
6013
6036
|
};
|
|
@@ -6190,6 +6213,53 @@ var addSiblingNode = (nodes, targetId, newNode) => {
|
|
|
6190
6213
|
});
|
|
6191
6214
|
return { nextNodes, inserted };
|
|
6192
6215
|
};
|
|
6216
|
+
var collectNodeIds = (node, ids = /* @__PURE__ */ new Set()) => {
|
|
6217
|
+
if (!node) return ids;
|
|
6218
|
+
ids.add(normaliseId(node.id));
|
|
6219
|
+
if (hasChildren(node)) {
|
|
6220
|
+
node.children.forEach((child) => collectNodeIds(child, ids));
|
|
6221
|
+
}
|
|
6222
|
+
return ids;
|
|
6223
|
+
};
|
|
6224
|
+
var collectExpandableIds = (nodes, ids = /* @__PURE__ */ new Set()) => {
|
|
6225
|
+
nodes.forEach((node) => {
|
|
6226
|
+
if (!hasChildren(node)) return;
|
|
6227
|
+
const nodeId = normaliseId(node.id);
|
|
6228
|
+
ids.add(nodeId);
|
|
6229
|
+
collectExpandableIds(node.children, ids);
|
|
6230
|
+
});
|
|
6231
|
+
return ids;
|
|
6232
|
+
};
|
|
6233
|
+
var collectExpandedIdsByLevel = (nodes, level, depth = 0, ids = /* @__PURE__ */ new Set()) => {
|
|
6234
|
+
if (level <= 0) return ids;
|
|
6235
|
+
nodes.forEach((node) => {
|
|
6236
|
+
if (!hasChildren(node)) return;
|
|
6237
|
+
if (depth < level) {
|
|
6238
|
+
ids.add(normaliseId(node.id));
|
|
6239
|
+
}
|
|
6240
|
+
if (depth + 1 < level) {
|
|
6241
|
+
collectExpandedIdsByLevel(node.children, level, depth + 1, ids);
|
|
6242
|
+
}
|
|
6243
|
+
});
|
|
6244
|
+
return ids;
|
|
6245
|
+
};
|
|
6246
|
+
var getExpandedIds = (nodes, expanded) => {
|
|
6247
|
+
if (!expanded) return /* @__PURE__ */ new Set();
|
|
6248
|
+
if (expanded === true || expanded === "all") {
|
|
6249
|
+
return collectExpandableIds(nodes);
|
|
6250
|
+
}
|
|
6251
|
+
if (typeof expanded === "number" && Number.isFinite(expanded)) {
|
|
6252
|
+
const level = Math.max(Math.floor(expanded), 0);
|
|
6253
|
+
return collectExpandedIdsByLevel(nodes, level);
|
|
6254
|
+
}
|
|
6255
|
+
if (expanded instanceof Set) {
|
|
6256
|
+
return new Set(Array.from(expanded, normaliseId));
|
|
6257
|
+
}
|
|
6258
|
+
if (Array.isArray(expanded)) {
|
|
6259
|
+
return new Set(expanded.map(normaliseId));
|
|
6260
|
+
}
|
|
6261
|
+
return /* @__PURE__ */ new Set();
|
|
6262
|
+
};
|
|
6193
6263
|
|
|
6194
6264
|
// src/elements/treeSelectDrag.js
|
|
6195
6265
|
var clamp2 = (value, min2, max2) => Math.min(Math.max(value, min2), max2);
|
|
@@ -6322,13 +6392,24 @@ function TreeSelect({
|
|
|
6322
6392
|
allowDragAndDrop = false,
|
|
6323
6393
|
allowMultiDrag = false,
|
|
6324
6394
|
isEditable = false,
|
|
6395
|
+
allowDelete = false,
|
|
6325
6396
|
useChevron = false,
|
|
6326
6397
|
maxDepth,
|
|
6327
6398
|
addChildTooltip,
|
|
6328
|
-
addSiblingTooltip
|
|
6399
|
+
addSiblingTooltip,
|
|
6400
|
+
deleteTooltip,
|
|
6401
|
+
addChildTooltipByLevel,
|
|
6402
|
+
addSiblingTooltipByLevel,
|
|
6403
|
+
deleteTooltipByLevel,
|
|
6404
|
+
defaultExpanded,
|
|
6405
|
+
expanded,
|
|
6406
|
+
onExpandedChange
|
|
6329
6407
|
}) {
|
|
6330
6408
|
var _a, _b;
|
|
6331
|
-
const [
|
|
6409
|
+
const [uncontrolledExpandedIds, setExpandedIds] = (0, import_react11.useState)(
|
|
6410
|
+
() => getExpandedIds(data ?? [], defaultExpanded)
|
|
6411
|
+
);
|
|
6412
|
+
const isExpandedControlled = expanded !== void 0;
|
|
6332
6413
|
const [activeId, setActiveId] = (0, import_react11.useState)(null);
|
|
6333
6414
|
const [overId, setOverId] = (0, import_react11.useState)(null);
|
|
6334
6415
|
const [horizontalOffset, setHorizontalOffset] = (0, import_react11.useState)(0);
|
|
@@ -6338,6 +6419,11 @@ function TreeSelect({
|
|
|
6338
6419
|
const [draftLabel, setDraftLabel] = (0, import_react11.useState)("");
|
|
6339
6420
|
const idCounterRef = (0, import_react11.useRef)(0);
|
|
6340
6421
|
const treeData = data ?? [];
|
|
6422
|
+
const controlledExpandedIds = (0, import_react11.useMemo)(
|
|
6423
|
+
() => getExpandedIds(treeData, expanded),
|
|
6424
|
+
[expanded, treeData]
|
|
6425
|
+
);
|
|
6426
|
+
const expandedIds = isExpandedControlled ? controlledExpandedIds : uncontrolledExpandedIds;
|
|
6341
6427
|
const listRef = (0, import_react11.useRef)(null);
|
|
6342
6428
|
const rowRefs = (0, import_react11.useRef)(/* @__PURE__ */ new Map());
|
|
6343
6429
|
const visibleItems = (0, import_react11.useMemo)(
|
|
@@ -6359,17 +6445,27 @@ function TreeSelect({
|
|
|
6359
6445
|
const sensors = (0, import_core2.useSensors)(
|
|
6360
6446
|
(0, import_core2.useSensor)(import_core2.PointerSensor, { activationConstraint: { distance: 4 } })
|
|
6361
6447
|
);
|
|
6448
|
+
const updateExpandedIds = (0, import_react11.useCallback)(
|
|
6449
|
+
(updater) => {
|
|
6450
|
+
if (isExpandedControlled) {
|
|
6451
|
+
const next = updater(new Set(expandedIds));
|
|
6452
|
+
onExpandedChange == null ? void 0 : onExpandedChange(next);
|
|
6453
|
+
return;
|
|
6454
|
+
}
|
|
6455
|
+
setExpandedIds((prev) => updater(new Set(prev)));
|
|
6456
|
+
},
|
|
6457
|
+
[expandedIds, isExpandedControlled, onExpandedChange]
|
|
6458
|
+
);
|
|
6362
6459
|
const toggleExpanded = (0, import_react11.useCallback)((id) => {
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
next.delete(id);
|
|
6460
|
+
updateExpandedIds((prev) => {
|
|
6461
|
+
if (prev.has(id)) {
|
|
6462
|
+
prev.delete(id);
|
|
6367
6463
|
} else {
|
|
6368
|
-
|
|
6464
|
+
prev.add(id);
|
|
6369
6465
|
}
|
|
6370
|
-
return
|
|
6466
|
+
return prev;
|
|
6371
6467
|
});
|
|
6372
|
-
}, []);
|
|
6468
|
+
}, [updateExpandedIds]);
|
|
6373
6469
|
const handleRowClick = (0, import_react11.useCallback)(
|
|
6374
6470
|
(event, id) => {
|
|
6375
6471
|
var _a2, _b2;
|
|
@@ -6497,10 +6593,9 @@ function TreeSelect({
|
|
|
6497
6593
|
});
|
|
6498
6594
|
onDataChange == null ? void 0 : onDataChange(nextTree);
|
|
6499
6595
|
if (parentId && projectedDepth > 0) {
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
return next;
|
|
6596
|
+
updateExpandedIds((prev) => {
|
|
6597
|
+
prev.add(parentId);
|
|
6598
|
+
return prev;
|
|
6504
6599
|
});
|
|
6505
6600
|
}
|
|
6506
6601
|
setActiveId(null);
|
|
@@ -6514,7 +6609,9 @@ function TreeSelect({
|
|
|
6514
6609
|
onDataChange,
|
|
6515
6610
|
overId,
|
|
6516
6611
|
treeData,
|
|
6517
|
-
|
|
6612
|
+
updateExpandedIds,
|
|
6613
|
+
visibleItems,
|
|
6614
|
+
maxDepth
|
|
6518
6615
|
]);
|
|
6519
6616
|
const handleDragCancel = (0, import_react11.useCallback)(() => {
|
|
6520
6617
|
setActiveId(null);
|
|
@@ -6533,13 +6630,12 @@ function TreeSelect({
|
|
|
6533
6630
|
const newNode = createNewNode();
|
|
6534
6631
|
const nextTree = addChildNode(treeData, parentId, newNode);
|
|
6535
6632
|
onDataChange == null ? void 0 : onDataChange(nextTree);
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
return next;
|
|
6633
|
+
updateExpandedIds((prev) => {
|
|
6634
|
+
prev.add(parentId);
|
|
6635
|
+
return prev;
|
|
6540
6636
|
});
|
|
6541
6637
|
},
|
|
6542
|
-
[createNewNode, onDataChange, treeData]
|
|
6638
|
+
[createNewNode, onDataChange, treeData, updateExpandedIds]
|
|
6543
6639
|
);
|
|
6544
6640
|
const handleAddSibling = (0, import_react11.useCallback)(
|
|
6545
6641
|
(targetId) => {
|
|
@@ -6550,6 +6646,34 @@ function TreeSelect({
|
|
|
6550
6646
|
},
|
|
6551
6647
|
[createNewNode, onDataChange, treeData]
|
|
6552
6648
|
);
|
|
6649
|
+
const resolveTooltipByLevel = (0, import_react11.useCallback)((levels, depth, fallback) => {
|
|
6650
|
+
if (!Array.isArray(levels)) return fallback;
|
|
6651
|
+
if (depth < 0 || depth >= levels.length) return fallback;
|
|
6652
|
+
return levels[depth] ?? fallback;
|
|
6653
|
+
}, []);
|
|
6654
|
+
const handleDelete = (0, import_react11.useCallback)(
|
|
6655
|
+
(targetId) => {
|
|
6656
|
+
const { nextNodes, removed } = removeNode(treeData, targetId);
|
|
6657
|
+
if (!removed) return;
|
|
6658
|
+
const removedIds = collectNodeIds(removed);
|
|
6659
|
+
onDataChange == null ? void 0 : onDataChange(nextNodes);
|
|
6660
|
+
updateExpandedIds((prev) => {
|
|
6661
|
+
removedIds.forEach((id) => prev.delete(id));
|
|
6662
|
+
return prev;
|
|
6663
|
+
});
|
|
6664
|
+
setSelectedIds((prev) => {
|
|
6665
|
+
if (!prev.size) return prev;
|
|
6666
|
+
const next = new Set(prev);
|
|
6667
|
+
removedIds.forEach((id) => next.delete(id));
|
|
6668
|
+
return next;
|
|
6669
|
+
});
|
|
6670
|
+
setLastSelectedId(
|
|
6671
|
+
(prev) => prev && removedIds.has(prev) ? null : prev
|
|
6672
|
+
);
|
|
6673
|
+
setEditingId((prev) => prev && removedIds.has(prev) ? null : prev);
|
|
6674
|
+
},
|
|
6675
|
+
[onDataChange, treeData, updateExpandedIds]
|
|
6676
|
+
);
|
|
6553
6677
|
const startEdit = (0, import_react11.useCallback)(
|
|
6554
6678
|
(id) => {
|
|
6555
6679
|
var _a2, _b2, _c, _d;
|
|
@@ -6641,8 +6765,23 @@ function TreeSelect({
|
|
|
6641
6765
|
canAddSibling: isEditable && (maxDepthLimit === null || item.depth <= maxDepthLimit),
|
|
6642
6766
|
onAddChild: handleAddChild,
|
|
6643
6767
|
onAddSibling: handleAddSibling,
|
|
6644
|
-
addChildTooltip
|
|
6645
|
-
|
|
6768
|
+
addChildTooltip: resolveTooltipByLevel(
|
|
6769
|
+
addChildTooltipByLevel,
|
|
6770
|
+
item.depth,
|
|
6771
|
+
addChildTooltip
|
|
6772
|
+
),
|
|
6773
|
+
addSiblingTooltip: resolveTooltipByLevel(
|
|
6774
|
+
addSiblingTooltipByLevel,
|
|
6775
|
+
item.depth,
|
|
6776
|
+
addSiblingTooltip
|
|
6777
|
+
),
|
|
6778
|
+
canDelete: isEditable && allowDelete,
|
|
6779
|
+
onDelete: handleDelete,
|
|
6780
|
+
deleteTooltip: resolveTooltipByLevel(
|
|
6781
|
+
deleteTooltipByLevel,
|
|
6782
|
+
item.depth,
|
|
6783
|
+
deleteTooltip
|
|
6784
|
+
)
|
|
6646
6785
|
},
|
|
6647
6786
|
item.id
|
|
6648
6787
|
))
|
|
@@ -6685,8 +6824,23 @@ function TreeSelect({
|
|
|
6685
6824
|
canAddSibling: isEditable && (maxDepthLimit === null || item.depth <= maxDepthLimit),
|
|
6686
6825
|
onAddChild: handleAddChild,
|
|
6687
6826
|
onAddSibling: handleAddSibling,
|
|
6688
|
-
addChildTooltip
|
|
6689
|
-
|
|
6827
|
+
addChildTooltip: resolveTooltipByLevel(
|
|
6828
|
+
addChildTooltipByLevel,
|
|
6829
|
+
item.depth,
|
|
6830
|
+
addChildTooltip
|
|
6831
|
+
),
|
|
6832
|
+
addSiblingTooltip: resolveTooltipByLevel(
|
|
6833
|
+
addSiblingTooltipByLevel,
|
|
6834
|
+
item.depth,
|
|
6835
|
+
addSiblingTooltip
|
|
6836
|
+
),
|
|
6837
|
+
canDelete: isEditable && allowDelete,
|
|
6838
|
+
onDelete: handleDelete,
|
|
6839
|
+
deleteTooltip: resolveTooltipByLevel(
|
|
6840
|
+
deleteTooltipByLevel,
|
|
6841
|
+
item.depth,
|
|
6842
|
+
deleteTooltip
|
|
6843
|
+
)
|
|
6690
6844
|
},
|
|
6691
6845
|
item.id
|
|
6692
6846
|
)) }) }) });
|
package/dist/index.mjs
CHANGED
|
@@ -5708,7 +5708,7 @@ function ButtonGroupItem(_props) {
|
|
|
5708
5708
|
ButtonGroupItem.displayName = "ButtonGroupItem";
|
|
5709
5709
|
|
|
5710
5710
|
// src/elements/TreeRow.jsx
|
|
5711
|
-
import { Chevron, Draghandle, List, Plus } from "@edux-design/icons";
|
|
5711
|
+
import { Chevron, Close, Draghandle, List, Plus } from "@edux-design/icons";
|
|
5712
5712
|
|
|
5713
5713
|
// src/elements/treeSelectConstants.js
|
|
5714
5714
|
var HANDLE_WIDTH = 28;
|
|
@@ -5744,13 +5744,17 @@ var TreeRow = ({
|
|
|
5744
5744
|
onAddChild,
|
|
5745
5745
|
onAddSibling,
|
|
5746
5746
|
addChildTooltip,
|
|
5747
|
-
addSiblingTooltip
|
|
5747
|
+
addSiblingTooltip,
|
|
5748
|
+
canDelete,
|
|
5749
|
+
onDelete,
|
|
5750
|
+
deleteTooltip
|
|
5748
5751
|
}) => {
|
|
5749
5752
|
const toggleLabel = isExpanded ? "Collapse item" : "Expand item";
|
|
5750
5753
|
const label = item.node.label ?? item.node.id;
|
|
5751
5754
|
const showToggle = item.hasChildren;
|
|
5752
5755
|
const rowBackground = isDragging ? "rgba(0, 0, 0, 0.04)" : isSelected ? "rgba(15, 98, 254, 0.08)" : void 0;
|
|
5753
5756
|
const rowPaddingLeft = depth * INDENT_WIDTH + 8 + (isDraggable ? 0 : HANDLE_WIDTH + 8);
|
|
5757
|
+
const showActions = canAddChild || canAddSibling || canDelete;
|
|
5754
5758
|
return /* @__PURE__ */ jsxs3(
|
|
5755
5759
|
"div",
|
|
5756
5760
|
{
|
|
@@ -5863,7 +5867,7 @@ var TreeRow = ({
|
|
|
5863
5867
|
children: label
|
|
5864
5868
|
}
|
|
5865
5869
|
),
|
|
5866
|
-
|
|
5870
|
+
showActions ? /* @__PURE__ */ jsxs3(
|
|
5867
5871
|
"div",
|
|
5868
5872
|
{
|
|
5869
5873
|
onClick: (event) => event.stopPropagation(),
|
|
@@ -5894,6 +5898,19 @@ var TreeRow = ({
|
|
|
5894
5898
|
}
|
|
5895
5899
|
) }),
|
|
5896
5900
|
/* @__PURE__ */ jsx11(TooltipContent2, { children: addSiblingTooltip ?? "Add sibling" })
|
|
5901
|
+
] }) : null,
|
|
5902
|
+
canDelete ? /* @__PURE__ */ jsxs3(Tooltip2, { children: [
|
|
5903
|
+
/* @__PURE__ */ jsx11(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsx11(
|
|
5904
|
+
IconButton,
|
|
5905
|
+
{
|
|
5906
|
+
size: "small",
|
|
5907
|
+
isBare: true,
|
|
5908
|
+
icon: /* @__PURE__ */ jsx11(Close, { "aria-hidden": "true" }),
|
|
5909
|
+
"aria-label": "Delete item",
|
|
5910
|
+
onClick: () => onDelete == null ? void 0 : onDelete(item.id)
|
|
5911
|
+
}
|
|
5912
|
+
) }),
|
|
5913
|
+
/* @__PURE__ */ jsx11(TooltipContent2, { children: deleteTooltip ?? "Delete item" })
|
|
5897
5914
|
] }) : null
|
|
5898
5915
|
]
|
|
5899
5916
|
}
|
|
@@ -5929,7 +5946,10 @@ var TreeSortableRow = ({
|
|
|
5929
5946
|
onAddChild,
|
|
5930
5947
|
onAddSibling,
|
|
5931
5948
|
addChildTooltip,
|
|
5932
|
-
addSiblingTooltip
|
|
5949
|
+
addSiblingTooltip,
|
|
5950
|
+
canDelete,
|
|
5951
|
+
onDelete,
|
|
5952
|
+
deleteTooltip
|
|
5933
5953
|
}) => {
|
|
5934
5954
|
const {
|
|
5935
5955
|
attributes,
|
|
@@ -5987,7 +6007,10 @@ var TreeSortableRow = ({
|
|
|
5987
6007
|
onAddChild,
|
|
5988
6008
|
onAddSibling,
|
|
5989
6009
|
addChildTooltip,
|
|
5990
|
-
addSiblingTooltip
|
|
6010
|
+
addSiblingTooltip,
|
|
6011
|
+
canDelete,
|
|
6012
|
+
onDelete,
|
|
6013
|
+
deleteTooltip
|
|
5991
6014
|
}
|
|
5992
6015
|
);
|
|
5993
6016
|
};
|
|
@@ -6170,6 +6193,53 @@ var addSiblingNode = (nodes, targetId, newNode) => {
|
|
|
6170
6193
|
});
|
|
6171
6194
|
return { nextNodes, inserted };
|
|
6172
6195
|
};
|
|
6196
|
+
var collectNodeIds = (node, ids = /* @__PURE__ */ new Set()) => {
|
|
6197
|
+
if (!node) return ids;
|
|
6198
|
+
ids.add(normaliseId(node.id));
|
|
6199
|
+
if (hasChildren(node)) {
|
|
6200
|
+
node.children.forEach((child) => collectNodeIds(child, ids));
|
|
6201
|
+
}
|
|
6202
|
+
return ids;
|
|
6203
|
+
};
|
|
6204
|
+
var collectExpandableIds = (nodes, ids = /* @__PURE__ */ new Set()) => {
|
|
6205
|
+
nodes.forEach((node) => {
|
|
6206
|
+
if (!hasChildren(node)) return;
|
|
6207
|
+
const nodeId = normaliseId(node.id);
|
|
6208
|
+
ids.add(nodeId);
|
|
6209
|
+
collectExpandableIds(node.children, ids);
|
|
6210
|
+
});
|
|
6211
|
+
return ids;
|
|
6212
|
+
};
|
|
6213
|
+
var collectExpandedIdsByLevel = (nodes, level, depth = 0, ids = /* @__PURE__ */ new Set()) => {
|
|
6214
|
+
if (level <= 0) return ids;
|
|
6215
|
+
nodes.forEach((node) => {
|
|
6216
|
+
if (!hasChildren(node)) return;
|
|
6217
|
+
if (depth < level) {
|
|
6218
|
+
ids.add(normaliseId(node.id));
|
|
6219
|
+
}
|
|
6220
|
+
if (depth + 1 < level) {
|
|
6221
|
+
collectExpandedIdsByLevel(node.children, level, depth + 1, ids);
|
|
6222
|
+
}
|
|
6223
|
+
});
|
|
6224
|
+
return ids;
|
|
6225
|
+
};
|
|
6226
|
+
var getExpandedIds = (nodes, expanded) => {
|
|
6227
|
+
if (!expanded) return /* @__PURE__ */ new Set();
|
|
6228
|
+
if (expanded === true || expanded === "all") {
|
|
6229
|
+
return collectExpandableIds(nodes);
|
|
6230
|
+
}
|
|
6231
|
+
if (typeof expanded === "number" && Number.isFinite(expanded)) {
|
|
6232
|
+
const level = Math.max(Math.floor(expanded), 0);
|
|
6233
|
+
return collectExpandedIdsByLevel(nodes, level);
|
|
6234
|
+
}
|
|
6235
|
+
if (expanded instanceof Set) {
|
|
6236
|
+
return new Set(Array.from(expanded, normaliseId));
|
|
6237
|
+
}
|
|
6238
|
+
if (Array.isArray(expanded)) {
|
|
6239
|
+
return new Set(expanded.map(normaliseId));
|
|
6240
|
+
}
|
|
6241
|
+
return /* @__PURE__ */ new Set();
|
|
6242
|
+
};
|
|
6173
6243
|
|
|
6174
6244
|
// src/elements/treeSelectDrag.js
|
|
6175
6245
|
var clamp2 = (value, min2, max2) => Math.min(Math.max(value, min2), max2);
|
|
@@ -6302,13 +6372,24 @@ function TreeSelect({
|
|
|
6302
6372
|
allowDragAndDrop = false,
|
|
6303
6373
|
allowMultiDrag = false,
|
|
6304
6374
|
isEditable = false,
|
|
6375
|
+
allowDelete = false,
|
|
6305
6376
|
useChevron = false,
|
|
6306
6377
|
maxDepth,
|
|
6307
6378
|
addChildTooltip,
|
|
6308
|
-
addSiblingTooltip
|
|
6379
|
+
addSiblingTooltip,
|
|
6380
|
+
deleteTooltip,
|
|
6381
|
+
addChildTooltipByLevel,
|
|
6382
|
+
addSiblingTooltipByLevel,
|
|
6383
|
+
deleteTooltipByLevel,
|
|
6384
|
+
defaultExpanded,
|
|
6385
|
+
expanded,
|
|
6386
|
+
onExpandedChange
|
|
6309
6387
|
}) {
|
|
6310
6388
|
var _a, _b;
|
|
6311
|
-
const [
|
|
6389
|
+
const [uncontrolledExpandedIds, setExpandedIds] = useState11(
|
|
6390
|
+
() => getExpandedIds(data ?? [], defaultExpanded)
|
|
6391
|
+
);
|
|
6392
|
+
const isExpandedControlled = expanded !== void 0;
|
|
6312
6393
|
const [activeId, setActiveId] = useState11(null);
|
|
6313
6394
|
const [overId, setOverId] = useState11(null);
|
|
6314
6395
|
const [horizontalOffset, setHorizontalOffset] = useState11(0);
|
|
@@ -6318,6 +6399,11 @@ function TreeSelect({
|
|
|
6318
6399
|
const [draftLabel, setDraftLabel] = useState11("");
|
|
6319
6400
|
const idCounterRef = useRef10(0);
|
|
6320
6401
|
const treeData = data ?? [];
|
|
6402
|
+
const controlledExpandedIds = useMemo8(
|
|
6403
|
+
() => getExpandedIds(treeData, expanded),
|
|
6404
|
+
[expanded, treeData]
|
|
6405
|
+
);
|
|
6406
|
+
const expandedIds = isExpandedControlled ? controlledExpandedIds : uncontrolledExpandedIds;
|
|
6321
6407
|
const listRef = useRef10(null);
|
|
6322
6408
|
const rowRefs = useRef10(/* @__PURE__ */ new Map());
|
|
6323
6409
|
const visibleItems = useMemo8(
|
|
@@ -6339,17 +6425,27 @@ function TreeSelect({
|
|
|
6339
6425
|
const sensors = useSensors(
|
|
6340
6426
|
useSensor(PointerSensor, { activationConstraint: { distance: 4 } })
|
|
6341
6427
|
);
|
|
6428
|
+
const updateExpandedIds = useCallback8(
|
|
6429
|
+
(updater) => {
|
|
6430
|
+
if (isExpandedControlled) {
|
|
6431
|
+
const next = updater(new Set(expandedIds));
|
|
6432
|
+
onExpandedChange == null ? void 0 : onExpandedChange(next);
|
|
6433
|
+
return;
|
|
6434
|
+
}
|
|
6435
|
+
setExpandedIds((prev) => updater(new Set(prev)));
|
|
6436
|
+
},
|
|
6437
|
+
[expandedIds, isExpandedControlled, onExpandedChange]
|
|
6438
|
+
);
|
|
6342
6439
|
const toggleExpanded = useCallback8((id) => {
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
next.delete(id);
|
|
6440
|
+
updateExpandedIds((prev) => {
|
|
6441
|
+
if (prev.has(id)) {
|
|
6442
|
+
prev.delete(id);
|
|
6347
6443
|
} else {
|
|
6348
|
-
|
|
6444
|
+
prev.add(id);
|
|
6349
6445
|
}
|
|
6350
|
-
return
|
|
6446
|
+
return prev;
|
|
6351
6447
|
});
|
|
6352
|
-
}, []);
|
|
6448
|
+
}, [updateExpandedIds]);
|
|
6353
6449
|
const handleRowClick = useCallback8(
|
|
6354
6450
|
(event, id) => {
|
|
6355
6451
|
var _a2, _b2;
|
|
@@ -6477,10 +6573,9 @@ function TreeSelect({
|
|
|
6477
6573
|
});
|
|
6478
6574
|
onDataChange == null ? void 0 : onDataChange(nextTree);
|
|
6479
6575
|
if (parentId && projectedDepth > 0) {
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
return next;
|
|
6576
|
+
updateExpandedIds((prev) => {
|
|
6577
|
+
prev.add(parentId);
|
|
6578
|
+
return prev;
|
|
6484
6579
|
});
|
|
6485
6580
|
}
|
|
6486
6581
|
setActiveId(null);
|
|
@@ -6494,7 +6589,9 @@ function TreeSelect({
|
|
|
6494
6589
|
onDataChange,
|
|
6495
6590
|
overId,
|
|
6496
6591
|
treeData,
|
|
6497
|
-
|
|
6592
|
+
updateExpandedIds,
|
|
6593
|
+
visibleItems,
|
|
6594
|
+
maxDepth
|
|
6498
6595
|
]);
|
|
6499
6596
|
const handleDragCancel = useCallback8(() => {
|
|
6500
6597
|
setActiveId(null);
|
|
@@ -6513,13 +6610,12 @@ function TreeSelect({
|
|
|
6513
6610
|
const newNode = createNewNode();
|
|
6514
6611
|
const nextTree = addChildNode(treeData, parentId, newNode);
|
|
6515
6612
|
onDataChange == null ? void 0 : onDataChange(nextTree);
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
return next;
|
|
6613
|
+
updateExpandedIds((prev) => {
|
|
6614
|
+
prev.add(parentId);
|
|
6615
|
+
return prev;
|
|
6520
6616
|
});
|
|
6521
6617
|
},
|
|
6522
|
-
[createNewNode, onDataChange, treeData]
|
|
6618
|
+
[createNewNode, onDataChange, treeData, updateExpandedIds]
|
|
6523
6619
|
);
|
|
6524
6620
|
const handleAddSibling = useCallback8(
|
|
6525
6621
|
(targetId) => {
|
|
@@ -6530,6 +6626,34 @@ function TreeSelect({
|
|
|
6530
6626
|
},
|
|
6531
6627
|
[createNewNode, onDataChange, treeData]
|
|
6532
6628
|
);
|
|
6629
|
+
const resolveTooltipByLevel = useCallback8((levels, depth, fallback) => {
|
|
6630
|
+
if (!Array.isArray(levels)) return fallback;
|
|
6631
|
+
if (depth < 0 || depth >= levels.length) return fallback;
|
|
6632
|
+
return levels[depth] ?? fallback;
|
|
6633
|
+
}, []);
|
|
6634
|
+
const handleDelete = useCallback8(
|
|
6635
|
+
(targetId) => {
|
|
6636
|
+
const { nextNodes, removed } = removeNode(treeData, targetId);
|
|
6637
|
+
if (!removed) return;
|
|
6638
|
+
const removedIds = collectNodeIds(removed);
|
|
6639
|
+
onDataChange == null ? void 0 : onDataChange(nextNodes);
|
|
6640
|
+
updateExpandedIds((prev) => {
|
|
6641
|
+
removedIds.forEach((id) => prev.delete(id));
|
|
6642
|
+
return prev;
|
|
6643
|
+
});
|
|
6644
|
+
setSelectedIds((prev) => {
|
|
6645
|
+
if (!prev.size) return prev;
|
|
6646
|
+
const next = new Set(prev);
|
|
6647
|
+
removedIds.forEach((id) => next.delete(id));
|
|
6648
|
+
return next;
|
|
6649
|
+
});
|
|
6650
|
+
setLastSelectedId(
|
|
6651
|
+
(prev) => prev && removedIds.has(prev) ? null : prev
|
|
6652
|
+
);
|
|
6653
|
+
setEditingId((prev) => prev && removedIds.has(prev) ? null : prev);
|
|
6654
|
+
},
|
|
6655
|
+
[onDataChange, treeData, updateExpandedIds]
|
|
6656
|
+
);
|
|
6533
6657
|
const startEdit = useCallback8(
|
|
6534
6658
|
(id) => {
|
|
6535
6659
|
var _a2, _b2, _c, _d;
|
|
@@ -6621,8 +6745,23 @@ function TreeSelect({
|
|
|
6621
6745
|
canAddSibling: isEditable && (maxDepthLimit === null || item.depth <= maxDepthLimit),
|
|
6622
6746
|
onAddChild: handleAddChild,
|
|
6623
6747
|
onAddSibling: handleAddSibling,
|
|
6624
|
-
addChildTooltip
|
|
6625
|
-
|
|
6748
|
+
addChildTooltip: resolveTooltipByLevel(
|
|
6749
|
+
addChildTooltipByLevel,
|
|
6750
|
+
item.depth,
|
|
6751
|
+
addChildTooltip
|
|
6752
|
+
),
|
|
6753
|
+
addSiblingTooltip: resolveTooltipByLevel(
|
|
6754
|
+
addSiblingTooltipByLevel,
|
|
6755
|
+
item.depth,
|
|
6756
|
+
addSiblingTooltip
|
|
6757
|
+
),
|
|
6758
|
+
canDelete: isEditable && allowDelete,
|
|
6759
|
+
onDelete: handleDelete,
|
|
6760
|
+
deleteTooltip: resolveTooltipByLevel(
|
|
6761
|
+
deleteTooltipByLevel,
|
|
6762
|
+
item.depth,
|
|
6763
|
+
deleteTooltip
|
|
6764
|
+
)
|
|
6626
6765
|
},
|
|
6627
6766
|
item.id
|
|
6628
6767
|
))
|
|
@@ -6665,8 +6804,23 @@ function TreeSelect({
|
|
|
6665
6804
|
canAddSibling: isEditable && (maxDepthLimit === null || item.depth <= maxDepthLimit),
|
|
6666
6805
|
onAddChild: handleAddChild,
|
|
6667
6806
|
onAddSibling: handleAddSibling,
|
|
6668
|
-
addChildTooltip
|
|
6669
|
-
|
|
6807
|
+
addChildTooltip: resolveTooltipByLevel(
|
|
6808
|
+
addChildTooltipByLevel,
|
|
6809
|
+
item.depth,
|
|
6810
|
+
addChildTooltip
|
|
6811
|
+
),
|
|
6812
|
+
addSiblingTooltip: resolveTooltipByLevel(
|
|
6813
|
+
addSiblingTooltipByLevel,
|
|
6814
|
+
item.depth,
|
|
6815
|
+
addSiblingTooltip
|
|
6816
|
+
),
|
|
6817
|
+
canDelete: isEditable && allowDelete,
|
|
6818
|
+
onDelete: handleDelete,
|
|
6819
|
+
deleteTooltip: resolveTooltipByLevel(
|
|
6820
|
+
deleteTooltipByLevel,
|
|
6821
|
+
item.depth,
|
|
6822
|
+
deleteTooltip
|
|
6823
|
+
)
|
|
6670
6824
|
},
|
|
6671
6825
|
item.id
|
|
6672
6826
|
)) }) }) });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@edux-design/tree-select",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css"
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
20
|
"lint": "eslint . --max-warnings 0",
|
|
21
|
-
"build": "tsup src/index.js --format esm,cjs --dts",
|
|
22
|
-
"dev": "tsup src/index.js --watch --format esm,cjs --dts",
|
|
21
|
+
"build": "tsup src/index.js --format esm,cjs --dts --external react,react-dom",
|
|
22
|
+
"dev": "tsup src/index.js --watch --format esm,cjs --dts --external react,react-dom",
|
|
23
23
|
"check-types": "tsc --noEmit"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|