@lv-x-software-house/x_view 1.1.9-dev.3 → 1.1.9-dev.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.
Files changed (3) hide show
  1. package/dist/index.js +163 -120
  2. package/dist/index.mjs +163 -120
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -186,8 +186,8 @@ function ContextMenu({
186
186
  return !isVisible;
187
187
  }).map((link) => {
188
188
  const isSource = String(link.source) === String(data.nodeData.id);
189
- const targetNodeId = isSource ? link.target : link.source;
190
- const targetNode = nodeMap.get(String(targetNodeId));
189
+ const targetNodeId2 = isSource ? link.target : link.source;
190
+ const targetNode = nodeMap.get(String(targetNodeId2));
191
191
  return { link, targetNode, direction: isSource ? "outgoing" : "incoming" };
192
192
  }).filter((c) => {
193
193
  var _a2;
@@ -1812,16 +1812,16 @@ var userActionHandlers = {
1812
1812
  linksToExpand.forEach((link) => {
1813
1813
  var _a;
1814
1814
  const isSource = String(link.source) === String(sourceNode.id);
1815
- const targetNodeId = isSource ? link.target : link.source;
1815
+ const targetNodeId2 = isSource ? link.target : link.source;
1816
1816
  const linkAlreadyInSceneData = sceneDataRef.current.links.some((l) => String(l.id) === String(link.id));
1817
1817
  if (!linkAlreadyInSceneData) {
1818
1818
  sceneDataRef.current.links.push(link);
1819
1819
  }
1820
- if (!nodeObjects[String(targetNodeId)]) {
1820
+ if (!nodeObjects[String(targetNodeId2)]) {
1821
1821
  const allParentNodes = Object.values(graphDataRef.current).flatMap((fileData) => fileData.nodes);
1822
- const nodeData = allParentNodes.find((n) => String(n.id) === String(targetNodeId));
1822
+ const nodeData = allParentNodes.find((n) => String(n.id) === String(targetNodeId2));
1823
1823
  if (!nodeData) {
1824
- console.warn(`Dados do Node com ID ${targetNodeId} n\xE3o encontrados no cache.`);
1824
+ console.warn(`Dados do Node com ID ${targetNodeId2} n\xE3o encontrados no cache.`);
1825
1825
  return;
1826
1826
  }
1827
1827
  if (!sceneDataRef.current.nodes.some((n) => String(n.id) === String(nodeData.id))) {
@@ -1838,7 +1838,7 @@ var userActionHandlers = {
1838
1838
  if (targetMesh.userData.labelObject) {
1839
1839
  graphGroup.add(targetMesh.userData.labelObject);
1840
1840
  }
1841
- nodeObjects[String(targetNodeId)] = targetMesh;
1841
+ nodeObjects[String(targetNodeId2)] = targetMesh;
1842
1842
  clickableNodes.push(targetMesh);
1843
1843
  const posTween = new import_tween.Tween(targetMesh.position).to(endPosition, 1200).easing(import_tween.Easing.Quadratic.Out);
1844
1844
  tweenGroup.add(posTween);
@@ -4874,31 +4874,50 @@ function AncestryPickerModal({
4874
4874
  }
4875
4875
 
4876
4876
  // src/components/CreateAncestryPanel.jsx
4877
- var findNodePath = (tree, targetNodeId, currentPath = []) => {
4877
+ var findNodePath = (tree, targetNodeId2, currentPath = []) => {
4878
4878
  var _a;
4879
4879
  if (!tree) return null;
4880
4880
  const currentNodeId = tree.is_section ? tree.section_id : String((_a = tree.node) == null ? void 0 : _a.id);
4881
- if (String(currentNodeId) === String(targetNodeId)) {
4881
+ if (String(currentNodeId) === String(targetNodeId2)) {
4882
4882
  return { node: tree, path: currentPath };
4883
4883
  }
4884
4884
  if (tree.children) {
4885
4885
  for (let i = 0; i < tree.children.length; i++) {
4886
- const res = findNodePath(tree.children[i], targetNodeId, [...currentPath, i]);
4886
+ const res = findNodePath(tree.children[i], targetNodeId2, [...currentPath, i]);
4887
4887
  if (res) return res;
4888
4888
  }
4889
4889
  }
4890
4890
  return null;
4891
4891
  };
4892
- var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, onMoveNode, selectedParentId, level = 0, isLast = false, path = [], isEditable }) => {
4892
+ var NodeItem = ({ nodeData, onSelectParent, onViewSelect, highlightedPathIds = [], targetRenderNodeId, onRemoveNode, onEditRelationship, onMoveNode, selectedParentId, level = 0, isLast = false, path = [], isEditable }) => {
4893
4893
  var _a, _b;
4894
4894
  const itemId = nodeData.is_section ? nodeData.id : (_a = nodeData.node) == null ? void 0 : _a.id;
4895
4895
  const itemName = nodeData.is_section ? nodeData.name : (_b = nodeData.node) == null ? void 0 : _b.name;
4896
4896
  const [isDragOver, setIsDragOver] = (0, import_react10.useState)(false);
4897
- const isSelected = String(selectedParentId) === String(itemId);
4897
+ const isSelectedParent = String(selectedParentId) === String(itemId);
4898
+ const isTargetViewNode = String(targetRenderNodeId) === String(itemId);
4899
+ const isHighlightedPath = highlightedPathIds.includes(String(itemId));
4898
4900
  const hasChildren = nodeData.children && nodeData.children.length > 0;
4899
- const itemBgClass = nodeData.is_section ? isSelected ? "bg-indigo-500/30 ring-2 ring-indigo-400" : "bg-indigo-900/20 border border-indigo-500/30 hover:bg-indigo-900/40" : isSelected ? "bg-cyan-500/20 ring-2 ring-cyan-400" : "bg-slate-900/50 hover:bg-slate-800/80";
4900
- const textColorClass = nodeData.is_section ? isSelected ? "text-indigo-200 font-bold" : "text-indigo-300" : isSelected ? "text-cyan-200 font-semibold" : "text-slate-200";
4901
- const cursorClass = isEditable ? "cursor-grab active:cursor-grabbing" : "cursor-default";
4901
+ let itemBgClass = "bg-slate-900/50 hover:bg-slate-800/80";
4902
+ let textColorClass = "text-slate-200";
4903
+ if (nodeData.is_section) {
4904
+ itemBgClass = isSelectedParent ? "bg-indigo-500/30 ring-2 ring-indigo-400" : "bg-indigo-900/20 border border-indigo-500/30 hover:bg-indigo-900/40";
4905
+ textColorClass = isSelectedParent ? "text-indigo-200 font-bold" : "text-indigo-300";
4906
+ } else {
4907
+ if (isSelectedParent) {
4908
+ itemBgClass = "bg-purple-500/30 ring-2 ring-purple-400";
4909
+ textColorClass = "text-purple-200 font-semibold";
4910
+ } else if (isTargetViewNode) {
4911
+ itemBgClass = "bg-fuchsia-600/40 ring-2 ring-fuchsia-400 shadow-[0_0_15px_rgba(217,70,239,0.3)]";
4912
+ textColorClass = "text-white font-bold";
4913
+ } else if (isHighlightedPath) {
4914
+ itemBgClass = "bg-fuchsia-900/30 border border-fuchsia-500/40";
4915
+ textColorClass = "text-fuchsia-200 font-semibold";
4916
+ } else {
4917
+ textColorClass = "text-slate-200";
4918
+ }
4919
+ }
4920
+ const cursorClass = isEditable ? "cursor-grab active:cursor-grabbing" : "cursor-pointer";
4902
4921
  const handleDragStart = (e) => {
4903
4922
  if (!isEditable) {
4904
4923
  e.preventDefault();
@@ -4928,23 +4947,9 @@ var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, on
4928
4947
  if (!isEditable) return;
4929
4948
  const sourceId = e.dataTransfer.getData("nodeId");
4930
4949
  if (sourceId === String(itemId)) return;
4931
- if (onMoveNode) {
4932
- onMoveNode(sourceId, itemId);
4933
- }
4950
+ if (onMoveNode) onMoveNode(sourceId, itemId);
4934
4951
  };
4935
- return /* @__PURE__ */ import_react10.default.createElement("div", { className: "relative" }, level > 0 && /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement(
4936
- "span",
4937
- {
4938
- className: `absolute -left-4 top-0 w-px bg-cyan-600/60 ${isLast ? "h-[1.125rem]" : "h-full"}`,
4939
- "aria-hidden": "true"
4940
- }
4941
- ), /* @__PURE__ */ import_react10.default.createElement(
4942
- "span",
4943
- {
4944
- className: `absolute -left-4 top-[1.125rem] h-px w-4 bg-cyan-600/60`,
4945
- "aria-hidden": "true"
4946
- }
4947
- )), /* @__PURE__ */ import_react10.default.createElement(
4952
+ return /* @__PURE__ */ import_react10.default.createElement("div", { className: "relative" }, level > 0 && /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement("span", { className: `absolute -left-4 top-0 w-px ${isHighlightedPath ? "bg-fuchsia-500 shadow-[0_0_8px_rgba(217,70,239,0.8)]" : "bg-cyan-600/60"} ${isLast ? "h-[1.125rem]" : "h-full"}`, "aria-hidden": "true" }), /* @__PURE__ */ import_react10.default.createElement("span", { className: `absolute -left-4 top-[1.125rem] h-px w-4 ${isHighlightedPath ? "bg-fuchsia-500 shadow-[0_0_8px_rgba(217,70,239,0.8)]" : "bg-cyan-600/60"}`, "aria-hidden": "true" })), /* @__PURE__ */ import_react10.default.createElement(
4948
4953
  "div",
4949
4954
  {
4950
4955
  draggable: isEditable,
@@ -4952,63 +4957,35 @@ var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, on
4952
4957
  onDragOver: handleDragOver,
4953
4958
  onDragLeave: handleDragLeave,
4954
4959
  onDrop: handleDrop,
4955
- onClick: () => {
4960
+ onClick: (e) => {
4961
+ e.stopPropagation();
4956
4962
  if (isEditable) {
4957
4963
  onSelectParent(itemId);
4964
+ } else if (onViewSelect) {
4965
+ onViewSelect(itemId);
4958
4966
  }
4959
4967
  },
4960
4968
  className: `flex items-center justify-between gap-2 px-3 h-9 rounded-md transition-all duration-150 border
4961
4969
  ${isDragOver ? "border-dashed border-yellow-400 bg-yellow-400/10" : "border-transparent"}
4962
4970
  ${itemBgClass} ${cursorClass}`
4963
4971
  },
4964
- /* @__PURE__ */ import_react10.default.createElement("span", { className: `truncate flex items-center ${textColorClass}` }, level === 0 && !nodeData.is_section && /* @__PURE__ */ import_react10.default.createElement(
4965
- "svg",
4966
- {
4967
- xmlns: "http://www.w3.org/2000/svg",
4968
- width: "16",
4969
- height: "16",
4970
- viewBox: "0 0 24 24",
4971
- fill: "none",
4972
- stroke: "currentColor",
4973
- strokeWidth: "2",
4974
- strokeLinecap: "round",
4975
- strokeLinejoin: "round",
4976
- className: "lucide lucide-blend-icon lucide-blend mr-1.5 inline-block"
4977
- },
4978
- /* @__PURE__ */ import_react10.default.createElement("circle", { cx: "9", cy: "9", r: "7" }),
4979
- /* @__PURE__ */ import_react10.default.createElement("circle", { cx: "15", cy: "15", r: "7" })
4980
- ), nodeData.is_section && /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiFolder, { className: "mr-2" }), itemName),
4981
- level > 0 && isEditable && /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-1 animate-in fade-in duration-200" }, !nodeData.is_section && /* @__PURE__ */ import_react10.default.createElement(
4982
- "button",
4983
- {
4984
- onClick: (e) => {
4985
- e.stopPropagation();
4986
- onEditRelationship(path, nodeData.relationship || {});
4987
- },
4988
- className: "w-6 h-6 grid place-content-center rounded-full hover:bg-cyan-500/20 text-cyan-400 transition-colors flex-shrink-0",
4989
- title: "Editar detalhes da rela\xE7\xE3o",
4990
- style: { cursor: "pointer" }
4991
- },
4992
- /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiEdit2, { size: 12 })
4993
- ), /* @__PURE__ */ import_react10.default.createElement(
4994
- "button",
4995
- {
4996
- onClick: (e) => {
4997
- e.stopPropagation();
4998
- onRemoveNode(path);
4999
- },
5000
- className: "w-6 h-6 grid place-content-center rounded-full hover:bg-red-500/20 text-red-400 text-lg transition-colors flex-shrink-0",
5001
- title: "Remover Node da ancestralidade",
5002
- style: { cursor: "pointer" }
5003
- },
5004
- "\xD7"
5005
- ))
4972
+ /* @__PURE__ */ import_react10.default.createElement("span", { className: `truncate flex items-center ${textColorClass}` }, level === 0 && !nodeData.is_section && /* @__PURE__ */ import_react10.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "mr-1.5 inline-block" }, /* @__PURE__ */ import_react10.default.createElement("circle", { cx: "9", cy: "9", r: "7" }), /* @__PURE__ */ import_react10.default.createElement("circle", { cx: "15", cy: "15", r: "7" })), nodeData.is_section && /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiFolder, { className: "mr-2" }), itemName),
4973
+ level > 0 && isEditable && /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-1 animate-in fade-in duration-200" }, !nodeData.is_section && /* @__PURE__ */ import_react10.default.createElement("button", { onClick: (e) => {
4974
+ e.stopPropagation();
4975
+ onEditRelationship(path, nodeData.relationship || {});
4976
+ }, className: "w-6 h-6 grid place-content-center rounded-full hover:bg-cyan-500/20 text-cyan-400 transition-colors flex-shrink-0", title: "Editar detalhes da rela\xE7\xE3o" }, /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiEdit2, { size: 12 })), /* @__PURE__ */ import_react10.default.createElement("button", { onClick: (e) => {
4977
+ e.stopPropagation();
4978
+ onRemoveNode(path);
4979
+ }, className: "w-6 h-6 grid place-content-center rounded-full hover:bg-red-500/20 text-red-400 text-lg transition-colors flex-shrink-0", title: "Remover Node" }, "\xD7"))
5006
4980
  ), hasChildren && /* @__PURE__ */ import_react10.default.createElement("div", { className: "mt-2 space-y-2 pl-8" }, nodeData.children.map((child, index) => /* @__PURE__ */ import_react10.default.createElement(
5007
4981
  NodeItem,
5008
4982
  {
5009
4983
  key: `${child.is_section ? child.id : child.node.id}-${index}`,
5010
4984
  nodeData: child,
5011
4985
  onSelectParent,
4986
+ onViewSelect,
4987
+ highlightedPathIds,
4988
+ targetRenderNodeId,
5012
4989
  onRemoveNode,
5013
4990
  onEditRelationship,
5014
4991
  onMoveNode,
@@ -5023,11 +5000,8 @@ var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, on
5023
5000
  function CreateAncestryPanel({
5024
5001
  ancestryMode,
5025
5002
  setAncestryMode,
5026
- // <--- Nova prop necessária para as novas funções manipuladoras
5027
5003
  onSelectParent,
5028
- // Mantido para compatibilidade, mas as novas funções usam setAncestryMode
5029
5004
  onRemoveNode,
5030
- // Mantido para compatibilidade
5031
5005
  onSave,
5032
5006
  onClose,
5033
5007
  onEditRelationship,
@@ -5038,14 +5012,12 @@ function CreateAncestryPanel({
5038
5012
  onUpdateTree,
5039
5013
  onAncestrySectionChange,
5040
5014
  onToggleAddNodes,
5041
- // Mantido para compatibilidade
5042
5015
  onRenderFullAncestry,
5043
5016
  onHighlightNode,
5044
5017
  onClearAncestryVisuals,
5045
5018
  onUploadFile,
5046
5019
  onOpenImageViewer,
5047
5020
  onRenderAbstractionTree
5048
- // <--- Nova prop recebida
5049
5021
  }) {
5050
5022
  const {
5051
5023
  tree: rootTree,
@@ -5062,6 +5034,20 @@ function CreateAncestryPanel({
5062
5034
  const [customProps, setCustomProps] = (0, import_react10.useState)([]);
5063
5035
  const propsEndRef = (0, import_react10.useRef)(null);
5064
5036
  const [branchStack, setBranchStack] = (0, import_react10.useState)([]);
5037
+ const [targetRenderNodeId, setTargetRenderNodeId] = (0, import_react10.useState)(null);
5038
+ const highlightedPathIds = (0, import_react10.useMemo)(() => {
5039
+ var _a, _b;
5040
+ if (!targetRenderNodeId || !ancestryMode.abstraction_tree) return [];
5041
+ const found = findNodePath(ancestryMode.abstraction_tree, targetRenderNodeId);
5042
+ if (!found) return [];
5043
+ let current = ancestryMode.abstraction_tree;
5044
+ const ids = [current.is_section ? current.section_id : String((_a = current.node) == null ? void 0 : _a.id)];
5045
+ for (let i of found.path) {
5046
+ current = current.children[i];
5047
+ ids.push(current.is_section ? current.section_id : String((_b = current.node) == null ? void 0 : _b.id));
5048
+ }
5049
+ return ids;
5050
+ }, [targetRenderNodeId, ancestryMode.abstraction_tree]);
5065
5051
  const [targetScrollSectionId, setTargetScrollSectionId] = (0, import_react10.useState)(null);
5066
5052
  const [internalHighlightedNodeId, setInternalHighlightedNodeId] = (0, import_react10.useState)(null);
5067
5053
  const [ancestryName, setAncestryName] = (0, import_react10.useState)(initialName);
@@ -5085,6 +5071,9 @@ function CreateAncestryPanel({
5085
5071
  setAncestryMode((prev) => isAbstraction ? { ...prev, selectedAbstractionParentId: nodeId } : { ...prev, selectedParentId: nodeId });
5086
5072
  };
5087
5073
  const handleToggleAddMode = (isAbstraction = false) => {
5074
+ if (isAbstraction && !ancestryMode.isAddingAbstractionNodes) {
5075
+ setTargetRenderNodeId(null);
5076
+ }
5088
5077
  setAncestryMode((prev) => isAbstraction ? { ...prev, isAddingAbstractionNodes: !prev.isAddingAbstractionNodes } : { ...prev, isAddingNodes: !prev.isAddingNodes });
5089
5078
  };
5090
5079
  const handleRemoveNode = (0, import_react10.useCallback)((pathToRemove, isAbstraction = false) => {
@@ -6220,44 +6209,77 @@ function CreateAncestryPanel({
6220
6209
  path: [],
6221
6210
  isEditable: isAddingNodes
6222
6211
  }
6223
- ), (!activeTree || activeTree.children.length === 0) && !isAddingNodes && /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center py-4 text-xs text-slate-500 italic" }, "A estrutura est\xE1 vazia. Clique no l\xE1pis acima para adicionar nodes."))), branchStack.length === 0 && ancestryMode.abstraction_tree && /* @__PURE__ */ import_react10.default.createElement("div", { className: `mt-6 rounded-lg border transition-all duration-300 overflow-hidden ${ancestryMode.isAddingAbstractionNodes ? "border-purple-500/40 bg-slate-900/60 ring-1 ring-purple-500/20" : "border-white/10 bg-slate-800/60"}` }, /* @__PURE__ */ import_react10.default.createElement("div", { className: `flex items-center justify-between px-3 py-2 border-b ${ancestryMode.isAddingAbstractionNodes ? "bg-purple-900/20 border-purple-500/20" : "bg-white/5 border-white/5"}` }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react10.default.createElement("span", { className: `text-xs font-semibold uppercase tracking-wider ${ancestryMode.isAddingAbstractionNodes ? "text-purple-300" : "text-slate-400"}` }, "Estrutura de Abstra\xE7\xE3o"), ancestryMode.isAddingAbstractionNodes && /* @__PURE__ */ import_react10.default.createElement("span", { className: "text-[10px] bg-purple-500/20 text-purple-300 px-1.5 py-0.5 rounded animate-pulse" }, "Editando")), /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react10.default.createElement(
6224
- "button",
6225
- {
6226
- type: "button",
6227
- onClick: () => {
6228
- const tempPayload = {
6229
- ancestry_id: currentAncestryId || "temp_rendering",
6230
- abstraction_tree: ancestryMode.abstraction_tree
6231
- };
6232
- if (onRenderAbstractionTree) onRenderAbstractionTree(tempPayload);
6233
- },
6234
- className: "p-1.5 rounded-md bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600 transition-colors",
6235
- title: "Renderizar Verticalmente no Cen\xE1rio"
6236
- },
6237
- /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiLayers, { size: 14 })
6238
- ), /* @__PURE__ */ import_react10.default.createElement(
6239
- "button",
6212
+ ), (!activeTree || activeTree.children.length === 0) && !isAddingNodes && /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center py-4 text-xs text-slate-500 italic" }, "A estrutura est\xE1 vazia. Clique no l\xE1pis acima para adicionar nodes."))), branchStack.length === 0 && ancestryMode.abstraction_tree && /* @__PURE__ */ import_react10.default.createElement(
6213
+ "div",
6240
6214
  {
6241
- onClick: () => handleToggleAddMode(true),
6242
- className: `p-1.5 rounded-md transition-colors ${ancestryMode.isAddingAbstractionNodes ? "bg-purple-500 text-white shadow-lg shadow-purple-500/30" : "bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600"}`,
6243
- title: "Editar estrutura da abstra\xE7\xE3o"
6215
+ className: `mt-6 rounded-lg border transition-all duration-300 overflow-hidden ${ancestryMode.isAddingAbstractionNodes ? "border-purple-500/40 bg-slate-900/60 ring-1 ring-purple-500/20" : "border-white/10 bg-slate-800/60"}`,
6216
+ onClick: () => setTargetRenderNodeId(null)
6244
6217
  },
6245
- ancestryMode.isAddingAbstractionNodes ? /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiCheck, { size: 14 }) : /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiEdit2, { size: 14 })
6246
- ))), /* @__PURE__ */ import_react10.default.createElement("div", { className: "p-4 space-y-2" }, ancestryMode.isAddingAbstractionNodes && /* @__PURE__ */ import_react10.default.createElement("div", { className: "mb-3 p-2 rounded bg-purple-900/20 border border-purple-500/20 text-xs text-purple-200 flex items-start gap-2" }, /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiMousePointer, { className: "mt-0.5 flex-shrink-0" }), /* @__PURE__ */ import_react10.default.createElement("span", null, "Clique nos nodes do cen\xE1rio para adicion\xE1-los. Arraste e solte para organizar a hierarquia.")), /* @__PURE__ */ import_react10.default.createElement(
6247
- NodeItem,
6248
- {
6249
- nodeData: ancestryMode.abstraction_tree,
6250
- onSelectParent: (id) => handleSelectAncestryParent(id, true),
6251
- onRemoveNode: (path) => handleRemoveNode(path, true),
6252
- onEditRelationship,
6253
- onMoveNode: (s, t) => handleMoveNode(s, t, true),
6254
- selectedParentId: ancestryMode.selectedAbstractionParentId,
6255
- level: 0,
6256
- isLast: true,
6257
- path: [],
6258
- isEditable: ancestryMode.isAddingAbstractionNodes
6259
- }
6260
- ))), branchStack.length === 0 && /* @__PURE__ */ import_react10.default.createElement("div", { className: "mt-3 flex items-center justify-end px-1" }, /* @__PURE__ */ import_react10.default.createElement("label", { className: "flex items-center gap-2 cursor-pointer group select-none" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${isPrivate ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, isPrivate && /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiCheck, { size: 12, className: "text-white" })), /* @__PURE__ */ import_react10.default.createElement(
6218
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: `flex items-center justify-between px-3 py-2 border-b ${ancestryMode.isAddingAbstractionNodes ? "bg-purple-900/20 border-purple-500/20" : "bg-white/5 border-white/5"}` }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react10.default.createElement("span", { className: `text-xs font-semibold uppercase tracking-wider ${ancestryMode.isAddingAbstractionNodes ? "text-purple-300" : "text-slate-400"}` }, "Estrutura de Abstra\xE7\xE3o"), ancestryMode.isAddingAbstractionNodes && /* @__PURE__ */ import_react10.default.createElement("span", { className: "text-[10px] bg-purple-500/20 text-purple-300 px-1.5 py-0.5 rounded animate-pulse" }, "Editando")), /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-2" }, targetRenderNodeId && !ancestryMode.isAddingAbstractionNodes && /* @__PURE__ */ import_react10.default.createElement(
6219
+ "button",
6220
+ {
6221
+ type: "button",
6222
+ onClick: (e) => {
6223
+ e.stopPropagation();
6224
+ const tempPayload = {
6225
+ ancestry_id: currentAncestryId || "temp_rendering",
6226
+ abstraction_tree: ancestryMode.abstraction_tree
6227
+ };
6228
+ if (onRenderAbstractionTree) onRenderAbstractionTree(tempPayload, targetRenderNodeId);
6229
+ },
6230
+ className: "px-2 py-1.5 rounded-md bg-fuchsia-600 text-white hover:bg-fuchsia-500 transition-colors flex items-center gap-1 shadow-lg animate-in fade-in zoom-in",
6231
+ title: "Renderizar cen\xE1rio at\xE9 o caminho selecionado"
6232
+ },
6233
+ /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiLayers, { size: 13 }),
6234
+ /* @__PURE__ */ import_react10.default.createElement("span", { className: "text-[10px] font-bold uppercase tracking-wider" }, "Caminho")
6235
+ ), /* @__PURE__ */ import_react10.default.createElement(
6236
+ "button",
6237
+ {
6238
+ type: "button",
6239
+ onClick: (e) => {
6240
+ e.stopPropagation();
6241
+ const tempPayload = {
6242
+ ancestry_id: currentAncestryId || "temp_rendering",
6243
+ abstraction_tree: ancestryMode.abstraction_tree
6244
+ };
6245
+ if (onRenderAbstractionTree) onRenderAbstractionTree(tempPayload);
6246
+ },
6247
+ className: "p-1.5 rounded-md bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600 transition-colors",
6248
+ title: "Renderizar Verticalmente Completo"
6249
+ },
6250
+ /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiLayers, { size: 14 })
6251
+ ), /* @__PURE__ */ import_react10.default.createElement(
6252
+ "button",
6253
+ {
6254
+ type: "button",
6255
+ onClick: (e) => {
6256
+ e.stopPropagation();
6257
+ handleToggleAddMode(true);
6258
+ },
6259
+ className: `p-1.5 rounded-md transition-colors ${ancestryMode.isAddingAbstractionNodes ? "bg-purple-500 text-white shadow-lg shadow-purple-500/30" : "bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600"}`,
6260
+ title: "Editar estrutura da abstra\xE7\xE3o"
6261
+ },
6262
+ ancestryMode.isAddingAbstractionNodes ? /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiCheck, { size: 14 }) : /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiEdit2, { size: 14 })
6263
+ ))),
6264
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: "p-4 space-y-2" }, ancestryMode.isAddingAbstractionNodes && /* @__PURE__ */ import_react10.default.createElement("div", { className: "mb-3 p-2 rounded bg-purple-900/20 border border-purple-500/20 text-xs text-purple-200 flex items-start gap-2" }, /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiMousePointer, { className: "mt-0.5 flex-shrink-0" }), /* @__PURE__ */ import_react10.default.createElement("span", null, "Clique nos nodes do cen\xE1rio para adicion\xE1-los. Arraste e solte para organizar a hierarquia.")), /* @__PURE__ */ import_react10.default.createElement(
6265
+ NodeItem,
6266
+ {
6267
+ nodeData: ancestryMode.abstraction_tree,
6268
+ onSelectParent: (id) => handleSelectAncestryParent(id, true),
6269
+ onViewSelect: setTargetRenderNodeId,
6270
+ highlightedPathIds,
6271
+ targetRenderNodeId,
6272
+ onRemoveNode: (path) => handleRemoveNode(path, true),
6273
+ onEditRelationship,
6274
+ onMoveNode: (s, t) => handleMoveNode(s, t, true),
6275
+ selectedParentId: ancestryMode.selectedAbstractionParentId,
6276
+ level: 0,
6277
+ isLast: true,
6278
+ path: [],
6279
+ isEditable: ancestryMode.isAddingAbstractionNodes
6280
+ }
6281
+ ))
6282
+ ), branchStack.length === 0 && /* @__PURE__ */ import_react10.default.createElement("div", { className: "mt-3 flex items-center justify-end px-1" }, /* @__PURE__ */ import_react10.default.createElement("label", { className: "flex items-center gap-2 cursor-pointer group select-none" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${isPrivate ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, isPrivate && /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiCheck, { size: 12, className: "text-white" })), /* @__PURE__ */ import_react10.default.createElement(
6261
6283
  "input",
6262
6284
  {
6263
6285
  type: "checkbox",
@@ -8775,16 +8797,16 @@ var getAllNodeIdsFromTree = (treeNode) => {
8775
8797
  traverse(treeNode);
8776
8798
  return Array.from(ids);
8777
8799
  };
8778
- var findNodePath2 = (tree, targetNodeId, currentPath = []) => {
8800
+ var findNodePath2 = (tree, targetNodeId2, currentPath = []) => {
8779
8801
  var _a;
8780
8802
  if (!tree) return null;
8781
8803
  const currentNodeId = tree.is_section ? tree.section_id : String((_a = tree.node) == null ? void 0 : _a.id);
8782
- if (String(currentNodeId) === String(targetNodeId)) {
8804
+ if (String(currentNodeId) === String(targetNodeId2)) {
8783
8805
  return { node: tree, path: currentPath };
8784
8806
  }
8785
8807
  if (tree.children) {
8786
8808
  for (let i = 0; i < tree.children.length; i++) {
8787
- const res = findNodePath2(tree.children[i], targetNodeId, [...currentPath, i]);
8809
+ const res = findNodePath2(tree.children[i], targetNodeId2, [...currentPath, i]);
8788
8810
  if (res) return res;
8789
8811
  }
8790
8812
  }
@@ -10858,8 +10880,29 @@ function XViewScene({
10858
10880
  if (!ancestryObject || !ancestryObject.abstraction_tree) return;
10859
10881
  const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
10860
10882
  const allParentNodes = Object.values(parentDataRef.current).flatMap((f) => f.nodes);
10861
- const fullTree = buildFullAncestryTree(ancestryObject.abstraction_tree, allParentNodes, ancestryDataRef.current);
10883
+ let fullTree = buildFullAncestryTree(ancestryObject.abstraction_tree, allParentNodes, ancestryDataRef.current);
10862
10884
  if (!fullTree || !fullTree.node) return;
10885
+ if (targetNodeId) {
10886
+ const pruneTreeToPath = (treeNode, targetId) => {
10887
+ var _a2;
10888
+ if (!treeNode) return null;
10889
+ const currentId = treeNode.is_section ? treeNode.section_id : String((_a2 = treeNode.node) == null ? void 0 : _a2.id);
10890
+ if (String(currentId) === String(targetId)) {
10891
+ return { ...treeNode, children: [] };
10892
+ }
10893
+ if (treeNode.children && treeNode.children.length > 0) {
10894
+ for (let child of treeNode.children) {
10895
+ const prunedChild = pruneTreeToPath(child, targetId);
10896
+ if (prunedChild) {
10897
+ return { ...treeNode, children: [prunedChild] };
10898
+ }
10899
+ }
10900
+ }
10901
+ return null;
10902
+ };
10903
+ const pruned = pruneTreeToPath(fullTree, targetNodeId);
10904
+ if (pruned) fullTree = pruned;
10905
+ }
10863
10906
  const absId = ancestryObject.ancestry_id + "_abs";
10864
10907
  handleClearAncestryVisuals(absId);
10865
10908
  const colorHex = 9133302;
@@ -11871,7 +11914,7 @@ function XViewScene({
11871
11914
  onClearAncestryVisuals: handleClearAncestryVisuals,
11872
11915
  onUploadFile: upload_file_action,
11873
11916
  onOpenImageViewer: handleOpenImageViewer,
11874
- onRenderAbstractionTree: (data) => handleRenderAbstractionTree(data)
11917
+ onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
11875
11918
  }
11876
11919
  ),
11877
11920
  editingAncestryRel.visible && /* @__PURE__ */ import_react23.default.createElement(
package/dist/index.mjs CHANGED
@@ -142,8 +142,8 @@ function ContextMenu({
142
142
  return !isVisible;
143
143
  }).map((link) => {
144
144
  const isSource = String(link.source) === String(data.nodeData.id);
145
- const targetNodeId = isSource ? link.target : link.source;
146
- const targetNode = nodeMap.get(String(targetNodeId));
145
+ const targetNodeId2 = isSource ? link.target : link.source;
146
+ const targetNode = nodeMap.get(String(targetNodeId2));
147
147
  return { link, targetNode, direction: isSource ? "outgoing" : "incoming" };
148
148
  }).filter((c) => {
149
149
  var _a2;
@@ -1768,16 +1768,16 @@ var userActionHandlers = {
1768
1768
  linksToExpand.forEach((link) => {
1769
1769
  var _a;
1770
1770
  const isSource = String(link.source) === String(sourceNode.id);
1771
- const targetNodeId = isSource ? link.target : link.source;
1771
+ const targetNodeId2 = isSource ? link.target : link.source;
1772
1772
  const linkAlreadyInSceneData = sceneDataRef.current.links.some((l) => String(l.id) === String(link.id));
1773
1773
  if (!linkAlreadyInSceneData) {
1774
1774
  sceneDataRef.current.links.push(link);
1775
1775
  }
1776
- if (!nodeObjects[String(targetNodeId)]) {
1776
+ if (!nodeObjects[String(targetNodeId2)]) {
1777
1777
  const allParentNodes = Object.values(graphDataRef.current).flatMap((fileData) => fileData.nodes);
1778
- const nodeData = allParentNodes.find((n) => String(n.id) === String(targetNodeId));
1778
+ const nodeData = allParentNodes.find((n) => String(n.id) === String(targetNodeId2));
1779
1779
  if (!nodeData) {
1780
- console.warn(`Dados do Node com ID ${targetNodeId} n\xE3o encontrados no cache.`);
1780
+ console.warn(`Dados do Node com ID ${targetNodeId2} n\xE3o encontrados no cache.`);
1781
1781
  return;
1782
1782
  }
1783
1783
  if (!sceneDataRef.current.nodes.some((n) => String(n.id) === String(nodeData.id))) {
@@ -1794,7 +1794,7 @@ var userActionHandlers = {
1794
1794
  if (targetMesh.userData.labelObject) {
1795
1795
  graphGroup.add(targetMesh.userData.labelObject);
1796
1796
  }
1797
- nodeObjects[String(targetNodeId)] = targetMesh;
1797
+ nodeObjects[String(targetNodeId2)] = targetMesh;
1798
1798
  clickableNodes.push(targetMesh);
1799
1799
  const posTween = new Tween(targetMesh.position).to(endPosition, 1200).easing(Easing.Quadratic.Out);
1800
1800
  tweenGroup.add(posTween);
@@ -4855,31 +4855,50 @@ function AncestryPickerModal({
4855
4855
  }
4856
4856
 
4857
4857
  // src/components/CreateAncestryPanel.jsx
4858
- var findNodePath = (tree, targetNodeId, currentPath = []) => {
4858
+ var findNodePath = (tree, targetNodeId2, currentPath = []) => {
4859
4859
  var _a;
4860
4860
  if (!tree) return null;
4861
4861
  const currentNodeId = tree.is_section ? tree.section_id : String((_a = tree.node) == null ? void 0 : _a.id);
4862
- if (String(currentNodeId) === String(targetNodeId)) {
4862
+ if (String(currentNodeId) === String(targetNodeId2)) {
4863
4863
  return { node: tree, path: currentPath };
4864
4864
  }
4865
4865
  if (tree.children) {
4866
4866
  for (let i = 0; i < tree.children.length; i++) {
4867
- const res = findNodePath(tree.children[i], targetNodeId, [...currentPath, i]);
4867
+ const res = findNodePath(tree.children[i], targetNodeId2, [...currentPath, i]);
4868
4868
  if (res) return res;
4869
4869
  }
4870
4870
  }
4871
4871
  return null;
4872
4872
  };
4873
- var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, onMoveNode, selectedParentId, level = 0, isLast = false, path = [], isEditable }) => {
4873
+ var NodeItem = ({ nodeData, onSelectParent, onViewSelect, highlightedPathIds = [], targetRenderNodeId, onRemoveNode, onEditRelationship, onMoveNode, selectedParentId, level = 0, isLast = false, path = [], isEditable }) => {
4874
4874
  var _a, _b;
4875
4875
  const itemId = nodeData.is_section ? nodeData.id : (_a = nodeData.node) == null ? void 0 : _a.id;
4876
4876
  const itemName = nodeData.is_section ? nodeData.name : (_b = nodeData.node) == null ? void 0 : _b.name;
4877
4877
  const [isDragOver, setIsDragOver] = useState10(false);
4878
- const isSelected = String(selectedParentId) === String(itemId);
4878
+ const isSelectedParent = String(selectedParentId) === String(itemId);
4879
+ const isTargetViewNode = String(targetRenderNodeId) === String(itemId);
4880
+ const isHighlightedPath = highlightedPathIds.includes(String(itemId));
4879
4881
  const hasChildren = nodeData.children && nodeData.children.length > 0;
4880
- const itemBgClass = nodeData.is_section ? isSelected ? "bg-indigo-500/30 ring-2 ring-indigo-400" : "bg-indigo-900/20 border border-indigo-500/30 hover:bg-indigo-900/40" : isSelected ? "bg-cyan-500/20 ring-2 ring-cyan-400" : "bg-slate-900/50 hover:bg-slate-800/80";
4881
- const textColorClass = nodeData.is_section ? isSelected ? "text-indigo-200 font-bold" : "text-indigo-300" : isSelected ? "text-cyan-200 font-semibold" : "text-slate-200";
4882
- const cursorClass = isEditable ? "cursor-grab active:cursor-grabbing" : "cursor-default";
4882
+ let itemBgClass = "bg-slate-900/50 hover:bg-slate-800/80";
4883
+ let textColorClass = "text-slate-200";
4884
+ if (nodeData.is_section) {
4885
+ itemBgClass = isSelectedParent ? "bg-indigo-500/30 ring-2 ring-indigo-400" : "bg-indigo-900/20 border border-indigo-500/30 hover:bg-indigo-900/40";
4886
+ textColorClass = isSelectedParent ? "text-indigo-200 font-bold" : "text-indigo-300";
4887
+ } else {
4888
+ if (isSelectedParent) {
4889
+ itemBgClass = "bg-purple-500/30 ring-2 ring-purple-400";
4890
+ textColorClass = "text-purple-200 font-semibold";
4891
+ } else if (isTargetViewNode) {
4892
+ itemBgClass = "bg-fuchsia-600/40 ring-2 ring-fuchsia-400 shadow-[0_0_15px_rgba(217,70,239,0.3)]";
4893
+ textColorClass = "text-white font-bold";
4894
+ } else if (isHighlightedPath) {
4895
+ itemBgClass = "bg-fuchsia-900/30 border border-fuchsia-500/40";
4896
+ textColorClass = "text-fuchsia-200 font-semibold";
4897
+ } else {
4898
+ textColorClass = "text-slate-200";
4899
+ }
4900
+ }
4901
+ const cursorClass = isEditable ? "cursor-grab active:cursor-grabbing" : "cursor-pointer";
4883
4902
  const handleDragStart = (e) => {
4884
4903
  if (!isEditable) {
4885
4904
  e.preventDefault();
@@ -4909,23 +4928,9 @@ var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, on
4909
4928
  if (!isEditable) return;
4910
4929
  const sourceId = e.dataTransfer.getData("nodeId");
4911
4930
  if (sourceId === String(itemId)) return;
4912
- if (onMoveNode) {
4913
- onMoveNode(sourceId, itemId);
4914
- }
4931
+ if (onMoveNode) onMoveNode(sourceId, itemId);
4915
4932
  };
4916
- return /* @__PURE__ */ React10.createElement("div", { className: "relative" }, level > 0 && /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(
4917
- "span",
4918
- {
4919
- className: `absolute -left-4 top-0 w-px bg-cyan-600/60 ${isLast ? "h-[1.125rem]" : "h-full"}`,
4920
- "aria-hidden": "true"
4921
- }
4922
- ), /* @__PURE__ */ React10.createElement(
4923
- "span",
4924
- {
4925
- className: `absolute -left-4 top-[1.125rem] h-px w-4 bg-cyan-600/60`,
4926
- "aria-hidden": "true"
4927
- }
4928
- )), /* @__PURE__ */ React10.createElement(
4933
+ return /* @__PURE__ */ React10.createElement("div", { className: "relative" }, level > 0 && /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement("span", { className: `absolute -left-4 top-0 w-px ${isHighlightedPath ? "bg-fuchsia-500 shadow-[0_0_8px_rgba(217,70,239,0.8)]" : "bg-cyan-600/60"} ${isLast ? "h-[1.125rem]" : "h-full"}`, "aria-hidden": "true" }), /* @__PURE__ */ React10.createElement("span", { className: `absolute -left-4 top-[1.125rem] h-px w-4 ${isHighlightedPath ? "bg-fuchsia-500 shadow-[0_0_8px_rgba(217,70,239,0.8)]" : "bg-cyan-600/60"}`, "aria-hidden": "true" })), /* @__PURE__ */ React10.createElement(
4929
4934
  "div",
4930
4935
  {
4931
4936
  draggable: isEditable,
@@ -4933,63 +4938,35 @@ var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, on
4933
4938
  onDragOver: handleDragOver,
4934
4939
  onDragLeave: handleDragLeave,
4935
4940
  onDrop: handleDrop,
4936
- onClick: () => {
4941
+ onClick: (e) => {
4942
+ e.stopPropagation();
4937
4943
  if (isEditable) {
4938
4944
  onSelectParent(itemId);
4945
+ } else if (onViewSelect) {
4946
+ onViewSelect(itemId);
4939
4947
  }
4940
4948
  },
4941
4949
  className: `flex items-center justify-between gap-2 px-3 h-9 rounded-md transition-all duration-150 border
4942
4950
  ${isDragOver ? "border-dashed border-yellow-400 bg-yellow-400/10" : "border-transparent"}
4943
4951
  ${itemBgClass} ${cursorClass}`
4944
4952
  },
4945
- /* @__PURE__ */ React10.createElement("span", { className: `truncate flex items-center ${textColorClass}` }, level === 0 && !nodeData.is_section && /* @__PURE__ */ React10.createElement(
4946
- "svg",
4947
- {
4948
- xmlns: "http://www.w3.org/2000/svg",
4949
- width: "16",
4950
- height: "16",
4951
- viewBox: "0 0 24 24",
4952
- fill: "none",
4953
- stroke: "currentColor",
4954
- strokeWidth: "2",
4955
- strokeLinecap: "round",
4956
- strokeLinejoin: "round",
4957
- className: "lucide lucide-blend-icon lucide-blend mr-1.5 inline-block"
4958
- },
4959
- /* @__PURE__ */ React10.createElement("circle", { cx: "9", cy: "9", r: "7" }),
4960
- /* @__PURE__ */ React10.createElement("circle", { cx: "15", cy: "15", r: "7" })
4961
- ), nodeData.is_section && /* @__PURE__ */ React10.createElement(FiFolder, { className: "mr-2" }), itemName),
4962
- level > 0 && isEditable && /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-1 animate-in fade-in duration-200" }, !nodeData.is_section && /* @__PURE__ */ React10.createElement(
4963
- "button",
4964
- {
4965
- onClick: (e) => {
4966
- e.stopPropagation();
4967
- onEditRelationship(path, nodeData.relationship || {});
4968
- },
4969
- className: "w-6 h-6 grid place-content-center rounded-full hover:bg-cyan-500/20 text-cyan-400 transition-colors flex-shrink-0",
4970
- title: "Editar detalhes da rela\xE7\xE3o",
4971
- style: { cursor: "pointer" }
4972
- },
4973
- /* @__PURE__ */ React10.createElement(FiEdit23, { size: 12 })
4974
- ), /* @__PURE__ */ React10.createElement(
4975
- "button",
4976
- {
4977
- onClick: (e) => {
4978
- e.stopPropagation();
4979
- onRemoveNode(path);
4980
- },
4981
- className: "w-6 h-6 grid place-content-center rounded-full hover:bg-red-500/20 text-red-400 text-lg transition-colors flex-shrink-0",
4982
- title: "Remover Node da ancestralidade",
4983
- style: { cursor: "pointer" }
4984
- },
4985
- "\xD7"
4986
- ))
4953
+ /* @__PURE__ */ React10.createElement("span", { className: `truncate flex items-center ${textColorClass}` }, level === 0 && !nodeData.is_section && /* @__PURE__ */ React10.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "mr-1.5 inline-block" }, /* @__PURE__ */ React10.createElement("circle", { cx: "9", cy: "9", r: "7" }), /* @__PURE__ */ React10.createElement("circle", { cx: "15", cy: "15", r: "7" })), nodeData.is_section && /* @__PURE__ */ React10.createElement(FiFolder, { className: "mr-2" }), itemName),
4954
+ level > 0 && isEditable && /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-1 animate-in fade-in duration-200" }, !nodeData.is_section && /* @__PURE__ */ React10.createElement("button", { onClick: (e) => {
4955
+ e.stopPropagation();
4956
+ onEditRelationship(path, nodeData.relationship || {});
4957
+ }, className: "w-6 h-6 grid place-content-center rounded-full hover:bg-cyan-500/20 text-cyan-400 transition-colors flex-shrink-0", title: "Editar detalhes da rela\xE7\xE3o" }, /* @__PURE__ */ React10.createElement(FiEdit23, { size: 12 })), /* @__PURE__ */ React10.createElement("button", { onClick: (e) => {
4958
+ e.stopPropagation();
4959
+ onRemoveNode(path);
4960
+ }, className: "w-6 h-6 grid place-content-center rounded-full hover:bg-red-500/20 text-red-400 text-lg transition-colors flex-shrink-0", title: "Remover Node" }, "\xD7"))
4987
4961
  ), hasChildren && /* @__PURE__ */ React10.createElement("div", { className: "mt-2 space-y-2 pl-8" }, nodeData.children.map((child, index) => /* @__PURE__ */ React10.createElement(
4988
4962
  NodeItem,
4989
4963
  {
4990
4964
  key: `${child.is_section ? child.id : child.node.id}-${index}`,
4991
4965
  nodeData: child,
4992
4966
  onSelectParent,
4967
+ onViewSelect,
4968
+ highlightedPathIds,
4969
+ targetRenderNodeId,
4993
4970
  onRemoveNode,
4994
4971
  onEditRelationship,
4995
4972
  onMoveNode,
@@ -5004,11 +4981,8 @@ var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, on
5004
4981
  function CreateAncestryPanel({
5005
4982
  ancestryMode,
5006
4983
  setAncestryMode,
5007
- // <--- Nova prop necessária para as novas funções manipuladoras
5008
4984
  onSelectParent,
5009
- // Mantido para compatibilidade, mas as novas funções usam setAncestryMode
5010
4985
  onRemoveNode,
5011
- // Mantido para compatibilidade
5012
4986
  onSave,
5013
4987
  onClose,
5014
4988
  onEditRelationship,
@@ -5019,14 +4993,12 @@ function CreateAncestryPanel({
5019
4993
  onUpdateTree,
5020
4994
  onAncestrySectionChange,
5021
4995
  onToggleAddNodes,
5022
- // Mantido para compatibilidade
5023
4996
  onRenderFullAncestry,
5024
4997
  onHighlightNode,
5025
4998
  onClearAncestryVisuals,
5026
4999
  onUploadFile,
5027
5000
  onOpenImageViewer,
5028
5001
  onRenderAbstractionTree
5029
- // <--- Nova prop recebida
5030
5002
  }) {
5031
5003
  const {
5032
5004
  tree: rootTree,
@@ -5043,6 +5015,20 @@ function CreateAncestryPanel({
5043
5015
  const [customProps, setCustomProps] = useState10([]);
5044
5016
  const propsEndRef = useRef8(null);
5045
5017
  const [branchStack, setBranchStack] = useState10([]);
5018
+ const [targetRenderNodeId, setTargetRenderNodeId] = useState10(null);
5019
+ const highlightedPathIds = useMemo8(() => {
5020
+ var _a, _b;
5021
+ if (!targetRenderNodeId || !ancestryMode.abstraction_tree) return [];
5022
+ const found = findNodePath(ancestryMode.abstraction_tree, targetRenderNodeId);
5023
+ if (!found) return [];
5024
+ let current = ancestryMode.abstraction_tree;
5025
+ const ids = [current.is_section ? current.section_id : String((_a = current.node) == null ? void 0 : _a.id)];
5026
+ for (let i of found.path) {
5027
+ current = current.children[i];
5028
+ ids.push(current.is_section ? current.section_id : String((_b = current.node) == null ? void 0 : _b.id));
5029
+ }
5030
+ return ids;
5031
+ }, [targetRenderNodeId, ancestryMode.abstraction_tree]);
5046
5032
  const [targetScrollSectionId, setTargetScrollSectionId] = useState10(null);
5047
5033
  const [internalHighlightedNodeId, setInternalHighlightedNodeId] = useState10(null);
5048
5034
  const [ancestryName, setAncestryName] = useState10(initialName);
@@ -5066,6 +5052,9 @@ function CreateAncestryPanel({
5066
5052
  setAncestryMode((prev) => isAbstraction ? { ...prev, selectedAbstractionParentId: nodeId } : { ...prev, selectedParentId: nodeId });
5067
5053
  };
5068
5054
  const handleToggleAddMode = (isAbstraction = false) => {
5055
+ if (isAbstraction && !ancestryMode.isAddingAbstractionNodes) {
5056
+ setTargetRenderNodeId(null);
5057
+ }
5069
5058
  setAncestryMode((prev) => isAbstraction ? { ...prev, isAddingAbstractionNodes: !prev.isAddingAbstractionNodes } : { ...prev, isAddingNodes: !prev.isAddingNodes });
5070
5059
  };
5071
5060
  const handleRemoveNode = useCallback((pathToRemove, isAbstraction = false) => {
@@ -6201,44 +6190,77 @@ function CreateAncestryPanel({
6201
6190
  path: [],
6202
6191
  isEditable: isAddingNodes
6203
6192
  }
6204
- ), (!activeTree || activeTree.children.length === 0) && !isAddingNodes && /* @__PURE__ */ React10.createElement("div", { className: "text-center py-4 text-xs text-slate-500 italic" }, "A estrutura est\xE1 vazia. Clique no l\xE1pis acima para adicionar nodes."))), branchStack.length === 0 && ancestryMode.abstraction_tree && /* @__PURE__ */ React10.createElement("div", { className: `mt-6 rounded-lg border transition-all duration-300 overflow-hidden ${ancestryMode.isAddingAbstractionNodes ? "border-purple-500/40 bg-slate-900/60 ring-1 ring-purple-500/20" : "border-white/10 bg-slate-800/60"}` }, /* @__PURE__ */ React10.createElement("div", { className: `flex items-center justify-between px-3 py-2 border-b ${ancestryMode.isAddingAbstractionNodes ? "bg-purple-900/20 border-purple-500/20" : "bg-white/5 border-white/5"}` }, /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React10.createElement("span", { className: `text-xs font-semibold uppercase tracking-wider ${ancestryMode.isAddingAbstractionNodes ? "text-purple-300" : "text-slate-400"}` }, "Estrutura de Abstra\xE7\xE3o"), ancestryMode.isAddingAbstractionNodes && /* @__PURE__ */ React10.createElement("span", { className: "text-[10px] bg-purple-500/20 text-purple-300 px-1.5 py-0.5 rounded animate-pulse" }, "Editando")), /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React10.createElement(
6205
- "button",
6206
- {
6207
- type: "button",
6208
- onClick: () => {
6209
- const tempPayload = {
6210
- ancestry_id: currentAncestryId || "temp_rendering",
6211
- abstraction_tree: ancestryMode.abstraction_tree
6212
- };
6213
- if (onRenderAbstractionTree) onRenderAbstractionTree(tempPayload);
6214
- },
6215
- className: "p-1.5 rounded-md bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600 transition-colors",
6216
- title: "Renderizar Verticalmente no Cen\xE1rio"
6217
- },
6218
- /* @__PURE__ */ React10.createElement(FiLayers5, { size: 14 })
6219
- ), /* @__PURE__ */ React10.createElement(
6220
- "button",
6193
+ ), (!activeTree || activeTree.children.length === 0) && !isAddingNodes && /* @__PURE__ */ React10.createElement("div", { className: "text-center py-4 text-xs text-slate-500 italic" }, "A estrutura est\xE1 vazia. Clique no l\xE1pis acima para adicionar nodes."))), branchStack.length === 0 && ancestryMode.abstraction_tree && /* @__PURE__ */ React10.createElement(
6194
+ "div",
6221
6195
  {
6222
- onClick: () => handleToggleAddMode(true),
6223
- className: `p-1.5 rounded-md transition-colors ${ancestryMode.isAddingAbstractionNodes ? "bg-purple-500 text-white shadow-lg shadow-purple-500/30" : "bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600"}`,
6224
- title: "Editar estrutura da abstra\xE7\xE3o"
6196
+ className: `mt-6 rounded-lg border transition-all duration-300 overflow-hidden ${ancestryMode.isAddingAbstractionNodes ? "border-purple-500/40 bg-slate-900/60 ring-1 ring-purple-500/20" : "border-white/10 bg-slate-800/60"}`,
6197
+ onClick: () => setTargetRenderNodeId(null)
6225
6198
  },
6226
- ancestryMode.isAddingAbstractionNodes ? /* @__PURE__ */ React10.createElement(FiCheck4, { size: 14 }) : /* @__PURE__ */ React10.createElement(FiEdit23, { size: 14 })
6227
- ))), /* @__PURE__ */ React10.createElement("div", { className: "p-4 space-y-2" }, ancestryMode.isAddingAbstractionNodes && /* @__PURE__ */ React10.createElement("div", { className: "mb-3 p-2 rounded bg-purple-900/20 border border-purple-500/20 text-xs text-purple-200 flex items-start gap-2" }, /* @__PURE__ */ React10.createElement(FiMousePointer, { className: "mt-0.5 flex-shrink-0" }), /* @__PURE__ */ React10.createElement("span", null, "Clique nos nodes do cen\xE1rio para adicion\xE1-los. Arraste e solte para organizar a hierarquia.")), /* @__PURE__ */ React10.createElement(
6228
- NodeItem,
6229
- {
6230
- nodeData: ancestryMode.abstraction_tree,
6231
- onSelectParent: (id) => handleSelectAncestryParent(id, true),
6232
- onRemoveNode: (path) => handleRemoveNode(path, true),
6233
- onEditRelationship,
6234
- onMoveNode: (s, t) => handleMoveNode(s, t, true),
6235
- selectedParentId: ancestryMode.selectedAbstractionParentId,
6236
- level: 0,
6237
- isLast: true,
6238
- path: [],
6239
- isEditable: ancestryMode.isAddingAbstractionNodes
6240
- }
6241
- ))), branchStack.length === 0 && /* @__PURE__ */ React10.createElement("div", { className: "mt-3 flex items-center justify-end px-1" }, /* @__PURE__ */ React10.createElement("label", { className: "flex items-center gap-2 cursor-pointer group select-none" }, /* @__PURE__ */ React10.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${isPrivate ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, isPrivate && /* @__PURE__ */ React10.createElement(FiCheck4, { size: 12, className: "text-white" })), /* @__PURE__ */ React10.createElement(
6199
+ /* @__PURE__ */ React10.createElement("div", { className: `flex items-center justify-between px-3 py-2 border-b ${ancestryMode.isAddingAbstractionNodes ? "bg-purple-900/20 border-purple-500/20" : "bg-white/5 border-white/5"}` }, /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React10.createElement("span", { className: `text-xs font-semibold uppercase tracking-wider ${ancestryMode.isAddingAbstractionNodes ? "text-purple-300" : "text-slate-400"}` }, "Estrutura de Abstra\xE7\xE3o"), ancestryMode.isAddingAbstractionNodes && /* @__PURE__ */ React10.createElement("span", { className: "text-[10px] bg-purple-500/20 text-purple-300 px-1.5 py-0.5 rounded animate-pulse" }, "Editando")), /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-2" }, targetRenderNodeId && !ancestryMode.isAddingAbstractionNodes && /* @__PURE__ */ React10.createElement(
6200
+ "button",
6201
+ {
6202
+ type: "button",
6203
+ onClick: (e) => {
6204
+ e.stopPropagation();
6205
+ const tempPayload = {
6206
+ ancestry_id: currentAncestryId || "temp_rendering",
6207
+ abstraction_tree: ancestryMode.abstraction_tree
6208
+ };
6209
+ if (onRenderAbstractionTree) onRenderAbstractionTree(tempPayload, targetRenderNodeId);
6210
+ },
6211
+ className: "px-2 py-1.5 rounded-md bg-fuchsia-600 text-white hover:bg-fuchsia-500 transition-colors flex items-center gap-1 shadow-lg animate-in fade-in zoom-in",
6212
+ title: "Renderizar cen\xE1rio at\xE9 o caminho selecionado"
6213
+ },
6214
+ /* @__PURE__ */ React10.createElement(FiLayers5, { size: 13 }),
6215
+ /* @__PURE__ */ React10.createElement("span", { className: "text-[10px] font-bold uppercase tracking-wider" }, "Caminho")
6216
+ ), /* @__PURE__ */ React10.createElement(
6217
+ "button",
6218
+ {
6219
+ type: "button",
6220
+ onClick: (e) => {
6221
+ e.stopPropagation();
6222
+ const tempPayload = {
6223
+ ancestry_id: currentAncestryId || "temp_rendering",
6224
+ abstraction_tree: ancestryMode.abstraction_tree
6225
+ };
6226
+ if (onRenderAbstractionTree) onRenderAbstractionTree(tempPayload);
6227
+ },
6228
+ className: "p-1.5 rounded-md bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600 transition-colors",
6229
+ title: "Renderizar Verticalmente Completo"
6230
+ },
6231
+ /* @__PURE__ */ React10.createElement(FiLayers5, { size: 14 })
6232
+ ), /* @__PURE__ */ React10.createElement(
6233
+ "button",
6234
+ {
6235
+ type: "button",
6236
+ onClick: (e) => {
6237
+ e.stopPropagation();
6238
+ handleToggleAddMode(true);
6239
+ },
6240
+ className: `p-1.5 rounded-md transition-colors ${ancestryMode.isAddingAbstractionNodes ? "bg-purple-500 text-white shadow-lg shadow-purple-500/30" : "bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600"}`,
6241
+ title: "Editar estrutura da abstra\xE7\xE3o"
6242
+ },
6243
+ ancestryMode.isAddingAbstractionNodes ? /* @__PURE__ */ React10.createElement(FiCheck4, { size: 14 }) : /* @__PURE__ */ React10.createElement(FiEdit23, { size: 14 })
6244
+ ))),
6245
+ /* @__PURE__ */ React10.createElement("div", { className: "p-4 space-y-2" }, ancestryMode.isAddingAbstractionNodes && /* @__PURE__ */ React10.createElement("div", { className: "mb-3 p-2 rounded bg-purple-900/20 border border-purple-500/20 text-xs text-purple-200 flex items-start gap-2" }, /* @__PURE__ */ React10.createElement(FiMousePointer, { className: "mt-0.5 flex-shrink-0" }), /* @__PURE__ */ React10.createElement("span", null, "Clique nos nodes do cen\xE1rio para adicion\xE1-los. Arraste e solte para organizar a hierarquia.")), /* @__PURE__ */ React10.createElement(
6246
+ NodeItem,
6247
+ {
6248
+ nodeData: ancestryMode.abstraction_tree,
6249
+ onSelectParent: (id) => handleSelectAncestryParent(id, true),
6250
+ onViewSelect: setTargetRenderNodeId,
6251
+ highlightedPathIds,
6252
+ targetRenderNodeId,
6253
+ onRemoveNode: (path) => handleRemoveNode(path, true),
6254
+ onEditRelationship,
6255
+ onMoveNode: (s, t) => handleMoveNode(s, t, true),
6256
+ selectedParentId: ancestryMode.selectedAbstractionParentId,
6257
+ level: 0,
6258
+ isLast: true,
6259
+ path: [],
6260
+ isEditable: ancestryMode.isAddingAbstractionNodes
6261
+ }
6262
+ ))
6263
+ ), branchStack.length === 0 && /* @__PURE__ */ React10.createElement("div", { className: "mt-3 flex items-center justify-end px-1" }, /* @__PURE__ */ React10.createElement("label", { className: "flex items-center gap-2 cursor-pointer group select-none" }, /* @__PURE__ */ React10.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${isPrivate ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, isPrivate && /* @__PURE__ */ React10.createElement(FiCheck4, { size: 12, className: "text-white" })), /* @__PURE__ */ React10.createElement(
6242
6264
  "input",
6243
6265
  {
6244
6266
  type: "checkbox",
@@ -8769,16 +8791,16 @@ var getAllNodeIdsFromTree = (treeNode) => {
8769
8791
  traverse(treeNode);
8770
8792
  return Array.from(ids);
8771
8793
  };
8772
- var findNodePath2 = (tree, targetNodeId, currentPath = []) => {
8794
+ var findNodePath2 = (tree, targetNodeId2, currentPath = []) => {
8773
8795
  var _a;
8774
8796
  if (!tree) return null;
8775
8797
  const currentNodeId = tree.is_section ? tree.section_id : String((_a = tree.node) == null ? void 0 : _a.id);
8776
- if (String(currentNodeId) === String(targetNodeId)) {
8798
+ if (String(currentNodeId) === String(targetNodeId2)) {
8777
8799
  return { node: tree, path: currentPath };
8778
8800
  }
8779
8801
  if (tree.children) {
8780
8802
  for (let i = 0; i < tree.children.length; i++) {
8781
- const res = findNodePath2(tree.children[i], targetNodeId, [...currentPath, i]);
8803
+ const res = findNodePath2(tree.children[i], targetNodeId2, [...currentPath, i]);
8782
8804
  if (res) return res;
8783
8805
  }
8784
8806
  }
@@ -10852,8 +10874,29 @@ function XViewScene({
10852
10874
  if (!ancestryObject || !ancestryObject.abstraction_tree) return;
10853
10875
  const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
10854
10876
  const allParentNodes = Object.values(parentDataRef.current).flatMap((f) => f.nodes);
10855
- const fullTree = buildFullAncestryTree(ancestryObject.abstraction_tree, allParentNodes, ancestryDataRef.current);
10877
+ let fullTree = buildFullAncestryTree(ancestryObject.abstraction_tree, allParentNodes, ancestryDataRef.current);
10856
10878
  if (!fullTree || !fullTree.node) return;
10879
+ if (targetNodeId) {
10880
+ const pruneTreeToPath = (treeNode, targetId) => {
10881
+ var _a2;
10882
+ if (!treeNode) return null;
10883
+ const currentId = treeNode.is_section ? treeNode.section_id : String((_a2 = treeNode.node) == null ? void 0 : _a2.id);
10884
+ if (String(currentId) === String(targetId)) {
10885
+ return { ...treeNode, children: [] };
10886
+ }
10887
+ if (treeNode.children && treeNode.children.length > 0) {
10888
+ for (let child of treeNode.children) {
10889
+ const prunedChild = pruneTreeToPath(child, targetId);
10890
+ if (prunedChild) {
10891
+ return { ...treeNode, children: [prunedChild] };
10892
+ }
10893
+ }
10894
+ }
10895
+ return null;
10896
+ };
10897
+ const pruned = pruneTreeToPath(fullTree, targetNodeId);
10898
+ if (pruned) fullTree = pruned;
10899
+ }
10857
10900
  const absId = ancestryObject.ancestry_id + "_abs";
10858
10901
  handleClearAncestryVisuals(absId);
10859
10902
  const colorHex = 9133302;
@@ -11865,7 +11908,7 @@ function XViewScene({
11865
11908
  onClearAncestryVisuals: handleClearAncestryVisuals,
11866
11909
  onUploadFile: upload_file_action,
11867
11910
  onOpenImageViewer: handleOpenImageViewer,
11868
- onRenderAbstractionTree: (data) => handleRenderAbstractionTree(data)
11911
+ onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
11869
11912
  }
11870
11913
  ),
11871
11914
  editingAncestryRel.visible && /* @__PURE__ */ React23.createElement(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lv-x-software-house/x_view",
3
- "version": "1.1.9-dev.3",
3
+ "version": "1.1.9-dev.5",
4
4
  "description": "Pacote privado contendo os componentes e lógica de renderização 3D do X View.",
5
5
  "author": "iv.x - Engenharia de Software - ivxsoftwarehouse@gmail.com",
6
6
  "license": "UNLICENSED",