@edux-design/tree-select 0.2.3 → 0.2.4

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 CHANGED
@@ -123,7 +123,22 @@ export function ChevronExample() {
123
123
  Tree data to render. This component is controlled; updates are emitted through `onDataChange`.
124
124
 
125
125
  ### `onDataChange` (function)
126
- Called with the updated tree when edits, add actions, or drag-and-drop reordering occur.
126
+ Called with `(nextTree, meta?)` when edits, add actions, deletes, or drag-and-drop reordering occur.
127
+
128
+ ```ts
129
+ type TreeSelectChangeMeta = {
130
+ reason: "drag" | "edit" | "add-child" | "add-sibling" | "delete";
131
+ activeId?: string | null;
132
+ draggedRootIds?: string[];
133
+ draggedIds?: string[];
134
+ sourceParentId?: string | null;
135
+ targetParentId?: string | null;
136
+ targetSiblingIndex?: number | null;
137
+ projectedDepth?: number | null;
138
+ };
139
+ ```
140
+
141
+ For drag-and-drop, `meta.draggedRootIds` identifies the exact root nodes that moved, which removes ambiguity when multiple reorder outcomes can produce the same final tree shape.
127
142
 
128
143
  ### `onLabelChange` (function)
129
144
  Called with `(id, nextLabel)` when a label edit is committed. When provided, label edits do not emit `onDataChange`.
package/dist/index.js CHANGED
@@ -845,6 +845,12 @@ function TreeSelect({
845
845
  },
846
846
  [expandedIds, isExpandedControlled, onExpandedChange]
847
847
  );
848
+ const emitDataChange = (0, import_react3.useCallback)(
849
+ (nextTree, meta) => {
850
+ onDataChange == null ? void 0 : onDataChange(nextTree, meta);
851
+ },
852
+ [onDataChange]
853
+ );
848
854
  const toggleExpanded = (0, import_react3.useCallback)((id) => {
849
855
  updateExpandedIds((prev) => {
850
856
  if (prev.has(id)) {
@@ -954,6 +960,7 @@ function TreeSelect({
954
960
  }
955
961
  }, []);
956
962
  const handleDragEnd = (0, import_react3.useCallback)(() => {
963
+ var _a2;
957
964
  const projection = getDropProjection({
958
965
  items: visibleItems,
959
966
  activeId,
@@ -969,6 +976,7 @@ function TreeSelect({
969
976
  return;
970
977
  }
971
978
  const { parentId, siblingIndex, projectedDepth } = projection;
979
+ const sourceParentId = ((_a2 = itemById.get(draggedRootIds[0] ?? activeId)) == null ? void 0 : _a2.parentId) ?? null;
972
980
  const { nextNodes, removedNodes } = removeNodes(treeData, draggedRootIds);
973
981
  if (!removedNodes.length) {
974
982
  setActiveId(null);
@@ -980,7 +988,16 @@ function TreeSelect({
980
988
  removedNodes.forEach((node, index) => {
981
989
  nextTree = insertNode(nextTree, parentId, siblingIndex + index, node);
982
990
  });
983
- onDataChange == null ? void 0 : onDataChange(nextTree);
991
+ emitDataChange(nextTree, {
992
+ reason: "drag",
993
+ activeId,
994
+ draggedRootIds,
995
+ draggedIds: Array.from(draggedIds),
996
+ sourceParentId,
997
+ targetParentId: parentId ?? null,
998
+ targetSiblingIndex: siblingIndex,
999
+ projectedDepth
1000
+ });
984
1001
  if (parentId && projectedDepth > 0) {
985
1002
  updateExpandedIds((prev) => {
986
1003
  prev.add(parentId);
@@ -994,8 +1011,9 @@ function TreeSelect({
994
1011
  activeId,
995
1012
  draggedIds,
996
1013
  draggedRootIds,
1014
+ emitDataChange,
997
1015
  horizontalOffset,
998
- onDataChange,
1016
+ itemById,
999
1017
  overId,
1000
1018
  treeData,
1001
1019
  updateExpandedIds,
@@ -1018,29 +1036,40 @@ function TreeSelect({
1018
1036
  (parentId) => {
1019
1037
  const newNode = createNewNode();
1020
1038
  const nextTree = addChildNode(treeData, parentId, newNode);
1021
- onDataChange == null ? void 0 : onDataChange(nextTree);
1039
+ emitDataChange(nextTree, {
1040
+ reason: "add-child",
1041
+ activeId: newNode.id,
1042
+ targetParentId: parentId
1043
+ });
1022
1044
  updateExpandedIds((prev) => {
1023
1045
  prev.add(parentId);
1024
1046
  return prev;
1025
1047
  });
1026
1048
  },
1027
- [createNewNode, onDataChange, treeData, updateExpandedIds]
1049
+ [createNewNode, emitDataChange, treeData, updateExpandedIds]
1028
1050
  );
1029
1051
  const handleAddSibling = (0, import_react3.useCallback)(
1030
1052
  (targetId) => {
1031
1053
  const newNode = createNewNode();
1032
1054
  const { nextNodes, inserted } = addSiblingNode(treeData, targetId, newNode);
1033
1055
  if (!inserted) return;
1034
- onDataChange == null ? void 0 : onDataChange(nextNodes);
1056
+ emitDataChange(nextNodes, {
1057
+ reason: "add-sibling",
1058
+ activeId: newNode.id
1059
+ });
1035
1060
  },
1036
- [createNewNode, onDataChange, treeData]
1061
+ [createNewNode, emitDataChange, treeData]
1037
1062
  );
1038
1063
  const handleDelete = (0, import_react3.useCallback)(
1039
1064
  (targetId) => {
1040
1065
  const { nextNodes, removed } = removeNode(treeData, targetId);
1041
1066
  if (!removed) return;
1042
1067
  const removedIds = collectNodeIds(removed);
1043
- onDataChange == null ? void 0 : onDataChange(nextNodes);
1068
+ emitDataChange(nextNodes, {
1069
+ reason: "delete",
1070
+ activeId: targetId,
1071
+ draggedIds: Array.from(removedIds)
1072
+ });
1044
1073
  updateExpandedIds((prev) => {
1045
1074
  removedIds.forEach((id) => prev.delete(id));
1046
1075
  return prev;
@@ -1056,7 +1085,7 @@ function TreeSelect({
1056
1085
  );
1057
1086
  setEditingId((prev) => prev && removedIds.has(prev) ? null : prev);
1058
1087
  },
1059
- [onDataChange, treeData, updateExpandedIds]
1088
+ [emitDataChange, treeData, updateExpandedIds]
1060
1089
  );
1061
1090
  const startEdit = (0, import_react3.useCallback)(
1062
1091
  (id) => {
@@ -1080,9 +1109,12 @@ function TreeSelect({
1080
1109
  return;
1081
1110
  }
1082
1111
  const nextTree = updateNodeLabel(treeData, editingId, nextLabel);
1083
- onDataChange == null ? void 0 : onDataChange(nextTree);
1112
+ emitDataChange(nextTree, {
1113
+ reason: "edit",
1114
+ activeId: editingId
1115
+ });
1084
1116
  setEditingId(null);
1085
- }, [draftLabel, editingId, onDataChange, onLabelChange, treeData]);
1117
+ }, [draftLabel, editingId, emitDataChange, onLabelChange, treeData]);
1086
1118
  const cancelEdit = (0, import_react3.useCallback)(() => {
1087
1119
  setEditingId(null);
1088
1120
  }, []);
package/dist/index.mjs CHANGED
@@ -828,6 +828,12 @@ function TreeSelect({
828
828
  },
829
829
  [expandedIds, isExpandedControlled, onExpandedChange]
830
830
  );
831
+ const emitDataChange = useCallback2(
832
+ (nextTree, meta) => {
833
+ onDataChange == null ? void 0 : onDataChange(nextTree, meta);
834
+ },
835
+ [onDataChange]
836
+ );
831
837
  const toggleExpanded = useCallback2((id) => {
832
838
  updateExpandedIds((prev) => {
833
839
  if (prev.has(id)) {
@@ -937,6 +943,7 @@ function TreeSelect({
937
943
  }
938
944
  }, []);
939
945
  const handleDragEnd = useCallback2(() => {
946
+ var _a2;
940
947
  const projection = getDropProjection({
941
948
  items: visibleItems,
942
949
  activeId,
@@ -952,6 +959,7 @@ function TreeSelect({
952
959
  return;
953
960
  }
954
961
  const { parentId, siblingIndex, projectedDepth } = projection;
962
+ const sourceParentId = ((_a2 = itemById.get(draggedRootIds[0] ?? activeId)) == null ? void 0 : _a2.parentId) ?? null;
955
963
  const { nextNodes, removedNodes } = removeNodes(treeData, draggedRootIds);
956
964
  if (!removedNodes.length) {
957
965
  setActiveId(null);
@@ -963,7 +971,16 @@ function TreeSelect({
963
971
  removedNodes.forEach((node, index) => {
964
972
  nextTree = insertNode(nextTree, parentId, siblingIndex + index, node);
965
973
  });
966
- onDataChange == null ? void 0 : onDataChange(nextTree);
974
+ emitDataChange(nextTree, {
975
+ reason: "drag",
976
+ activeId,
977
+ draggedRootIds,
978
+ draggedIds: Array.from(draggedIds),
979
+ sourceParentId,
980
+ targetParentId: parentId ?? null,
981
+ targetSiblingIndex: siblingIndex,
982
+ projectedDepth
983
+ });
967
984
  if (parentId && projectedDepth > 0) {
968
985
  updateExpandedIds((prev) => {
969
986
  prev.add(parentId);
@@ -977,8 +994,9 @@ function TreeSelect({
977
994
  activeId,
978
995
  draggedIds,
979
996
  draggedRootIds,
997
+ emitDataChange,
980
998
  horizontalOffset,
981
- onDataChange,
999
+ itemById,
982
1000
  overId,
983
1001
  treeData,
984
1002
  updateExpandedIds,
@@ -1001,29 +1019,40 @@ function TreeSelect({
1001
1019
  (parentId) => {
1002
1020
  const newNode = createNewNode();
1003
1021
  const nextTree = addChildNode(treeData, parentId, newNode);
1004
- onDataChange == null ? void 0 : onDataChange(nextTree);
1022
+ emitDataChange(nextTree, {
1023
+ reason: "add-child",
1024
+ activeId: newNode.id,
1025
+ targetParentId: parentId
1026
+ });
1005
1027
  updateExpandedIds((prev) => {
1006
1028
  prev.add(parentId);
1007
1029
  return prev;
1008
1030
  });
1009
1031
  },
1010
- [createNewNode, onDataChange, treeData, updateExpandedIds]
1032
+ [createNewNode, emitDataChange, treeData, updateExpandedIds]
1011
1033
  );
1012
1034
  const handleAddSibling = useCallback2(
1013
1035
  (targetId) => {
1014
1036
  const newNode = createNewNode();
1015
1037
  const { nextNodes, inserted } = addSiblingNode(treeData, targetId, newNode);
1016
1038
  if (!inserted) return;
1017
- onDataChange == null ? void 0 : onDataChange(nextNodes);
1039
+ emitDataChange(nextNodes, {
1040
+ reason: "add-sibling",
1041
+ activeId: newNode.id
1042
+ });
1018
1043
  },
1019
- [createNewNode, onDataChange, treeData]
1044
+ [createNewNode, emitDataChange, treeData]
1020
1045
  );
1021
1046
  const handleDelete = useCallback2(
1022
1047
  (targetId) => {
1023
1048
  const { nextNodes, removed } = removeNode(treeData, targetId);
1024
1049
  if (!removed) return;
1025
1050
  const removedIds = collectNodeIds(removed);
1026
- onDataChange == null ? void 0 : onDataChange(nextNodes);
1051
+ emitDataChange(nextNodes, {
1052
+ reason: "delete",
1053
+ activeId: targetId,
1054
+ draggedIds: Array.from(removedIds)
1055
+ });
1027
1056
  updateExpandedIds((prev) => {
1028
1057
  removedIds.forEach((id) => prev.delete(id));
1029
1058
  return prev;
@@ -1039,7 +1068,7 @@ function TreeSelect({
1039
1068
  );
1040
1069
  setEditingId((prev) => prev && removedIds.has(prev) ? null : prev);
1041
1070
  },
1042
- [onDataChange, treeData, updateExpandedIds]
1071
+ [emitDataChange, treeData, updateExpandedIds]
1043
1072
  );
1044
1073
  const startEdit = useCallback2(
1045
1074
  (id) => {
@@ -1063,9 +1092,12 @@ function TreeSelect({
1063
1092
  return;
1064
1093
  }
1065
1094
  const nextTree = updateNodeLabel(treeData, editingId, nextLabel);
1066
- onDataChange == null ? void 0 : onDataChange(nextTree);
1095
+ emitDataChange(nextTree, {
1096
+ reason: "edit",
1097
+ activeId: editingId
1098
+ });
1067
1099
  setEditingId(null);
1068
- }, [draftLabel, editingId, onDataChange, onLabelChange, treeData]);
1100
+ }, [draftLabel, editingId, emitDataChange, onLabelChange, treeData]);
1069
1101
  const cancelEdit = useCallback2(() => {
1070
1102
  setEditingId(null);
1071
1103
  }, []);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edux-design/tree-select",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "**/*.css"