@lv-x-software-house/x_view 1.1.9-dev.1 → 1.1.9-dev.10

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 +362 -152
  2. package/dist/index.mjs +367 -155
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2698,7 +2698,10 @@ var IGNORED_KEYS = [
2698
2698
  "isAddingNodes",
2699
2699
  "ancestryDescriptionSections",
2700
2700
  "direction",
2701
- "is_private"
2701
+ "is_private",
2702
+ "abstraction_tree",
2703
+ "selectedAbstractionParentId",
2704
+ "isAddingAbstractionNodes"
2702
2705
  ];
2703
2706
  function extractCustomPropsFromNode(node) {
2704
2707
  const customPropTypes = node._customPropTypes || {};
@@ -4464,6 +4467,65 @@ function DescriptionDisplay({
4464
4467
  // src/components/DescriptionReadModePanel.jsx
4465
4468
  var import_react7 = __toESM(require("react"));
4466
4469
  var import_fi6 = require("react-icons/fi");
4470
+ var findNodePath = (tree, targetNodeId, currentPath = []) => {
4471
+ var _a;
4472
+ if (!tree) return null;
4473
+ const currentNodeId = tree.is_section ? tree.section_id : String((_a = tree.node) == null ? void 0 : _a.id);
4474
+ if (String(currentNodeId) === String(targetNodeId)) {
4475
+ return { node: tree, path: currentPath };
4476
+ }
4477
+ if (tree.children) {
4478
+ for (let i = 0; i < tree.children.length; i++) {
4479
+ const res = findNodePath(tree.children[i], targetNodeId, [...currentPath, i]);
4480
+ if (res) return res;
4481
+ }
4482
+ }
4483
+ return null;
4484
+ };
4485
+ var ReadOnlyNodeItem = ({ nodeData, onViewSelect, highlightedPathIds = [], targetRenderNodeId, level = 0, isLast = false }) => {
4486
+ var _a, _b;
4487
+ const itemId = nodeData.is_section ? nodeData.id : (_a = nodeData.node) == null ? void 0 : _a.id;
4488
+ const itemName = nodeData.is_section ? nodeData.name : (_b = nodeData.node) == null ? void 0 : _b.name;
4489
+ const isTargetViewNode = String(targetRenderNodeId) === String(itemId);
4490
+ const isHighlightedPath = highlightedPathIds.includes(String(itemId));
4491
+ const hasChildren = nodeData.children && nodeData.children.length > 0;
4492
+ let itemBgClass = "bg-slate-900/50 hover:bg-slate-800/80";
4493
+ let textColorClass = "text-slate-200";
4494
+ if (nodeData.is_section) {
4495
+ itemBgClass = "bg-purple-900/20 border border-purple-500/30 hover:bg-purple-900/40";
4496
+ textColorClass = "text-purple-300";
4497
+ } else {
4498
+ if (isTargetViewNode) {
4499
+ itemBgClass = "bg-fuchsia-600/40 ring-2 ring-fuchsia-400 shadow-[0_0_15px_rgba(217,70,239,0.3)]";
4500
+ textColorClass = "text-white font-bold";
4501
+ } else if (isHighlightedPath) {
4502
+ itemBgClass = "bg-fuchsia-900/30 border border-fuchsia-500/40";
4503
+ textColorClass = "text-fuchsia-200 font-semibold";
4504
+ }
4505
+ }
4506
+ return /* @__PURE__ */ import_react7.default.createElement("div", { className: "relative" }, level > 0 && /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.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_react7.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_react7.default.createElement(
4507
+ "div",
4508
+ {
4509
+ onClick: (e) => {
4510
+ e.stopPropagation();
4511
+ if (onViewSelect) onViewSelect(itemId);
4512
+ },
4513
+ className: `flex items-center justify-between gap-2 px-3 h-9 rounded-md transition-all duration-150 border border-transparent cursor-pointer ${itemBgClass}`
4514
+ },
4515
+ /* @__PURE__ */ import_react7.default.createElement("span", { className: `truncate flex items-center ${textColorClass}` }, level === 0 && !nodeData.is_section && /* @__PURE__ */ import_react7.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_react7.default.createElement("circle", { cx: "9", cy: "9", r: "7" }), /* @__PURE__ */ import_react7.default.createElement("circle", { cx: "15", cy: "15", r: "7" })), nodeData.is_section && /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiFolder, { className: "mr-2" }), itemName)
4516
+ ), hasChildren && /* @__PURE__ */ import_react7.default.createElement("div", { className: "mt-2 space-y-2 pl-8" }, nodeData.children.map((child, index) => /* @__PURE__ */ import_react7.default.createElement(
4517
+ ReadOnlyNodeItem,
4518
+ {
4519
+ key: `${child.is_section ? child.id : child.node.id}-${index}`,
4520
+ nodeData: child,
4521
+ onViewSelect,
4522
+ highlightedPathIds,
4523
+ targetRenderNodeId,
4524
+ level: level + 1,
4525
+ isLast: index === nodeData.children.length - 1
4526
+ }
4527
+ ))));
4528
+ };
4467
4529
  function DescriptionReadModePanel({
4468
4530
  title,
4469
4531
  description,
@@ -4485,14 +4547,40 @@ function DescriptionReadModePanel({
4485
4547
  backNavigationInfo,
4486
4548
  customProperties = [],
4487
4549
  onImageClick,
4488
- userRole
4489
- // <--- NOVA PROP: Recebendo a role do usuário
4550
+ userRole,
4551
+ // --- NOVAS PROPS PARA ABSTRAÇÃO ---
4552
+ abstractionTree = null,
4553
+ onRenderAbstractionTree = null
4490
4554
  }) {
4491
4555
  const [showProperties, setShowProperties] = (0, import_react7.useState)(false);
4556
+ const [showAbstraction, setShowAbstraction] = (0, import_react7.useState)(false);
4557
+ const [targetRenderNodeId, setTargetRenderNodeId] = (0, import_react7.useState)(null);
4492
4558
  const swallow = (e) => e.stopPropagation();
4493
4559
  const hasCustomProps = customProperties && customProperties.length > 0;
4560
+ const hasAbstraction = Boolean(abstractionTree && (abstractionTree.node || abstractionTree.children && abstractionTree.children.length > 0));
4494
4561
  const ability = (0, import_react7.useMemo)(() => defineAbilityFor(userRole), [userRole]);
4495
4562
  const canEditAncestry = ability.can("update", "Ancestry");
4563
+ const highlightedPathIds = (0, import_react7.useMemo)(() => {
4564
+ var _a, _b;
4565
+ if (!targetRenderNodeId || !abstractionTree) return [];
4566
+ const found = findNodePath(abstractionTree, targetRenderNodeId);
4567
+ if (!found) return [];
4568
+ let current = abstractionTree;
4569
+ const ids = [current.is_section ? current.section_id : String((_a = current.node) == null ? void 0 : _a.id)];
4570
+ for (let i of found.path) {
4571
+ current = current.children[i];
4572
+ ids.push(current.is_section ? current.section_id : String((_b = current.node) == null ? void 0 : _b.id));
4573
+ }
4574
+ return ids;
4575
+ }, [targetRenderNodeId, abstractionTree]);
4576
+ const handleToggleProperties = () => {
4577
+ setShowProperties(!showProperties);
4578
+ if (!showProperties) setShowAbstraction(false);
4579
+ };
4580
+ const handleToggleAbstraction = () => {
4581
+ setShowAbstraction(!showAbstraction);
4582
+ if (!showAbstraction) setShowProperties(false);
4583
+ };
4496
4584
  const leftAction = (0, import_react7.useMemo)(() => {
4497
4585
  if (activeNodeBranches == null ? void 0 : activeNodeBranches.left) {
4498
4586
  return {
@@ -4537,21 +4625,38 @@ function DescriptionReadModePanel({
4537
4625
  /* @__PURE__ */ import_react7.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4 border-b border-white/10 shrink-0 bg-slate-950/50 backdrop-blur-md z-20" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-3 overflow-hidden" }, /* @__PURE__ */ import_react7.default.createElement(
4538
4626
  "button",
4539
4627
  {
4540
- onClick: onBack,
4628
+ onClick: () => {
4629
+ if (showAbstraction) {
4630
+ setShowAbstraction(false);
4631
+ } else if (showProperties) {
4632
+ setShowProperties(false);
4633
+ } else if (onBack) {
4634
+ onBack();
4635
+ }
4636
+ },
4541
4637
  className: "w-8 h-8 flex-shrink-0 grid place-content-center rounded-lg border border-white/10 bg-white/5 hover:bg-white/10 transition-colors text-slate-300",
4542
4638
  title: "Voltar"
4543
4639
  },
4544
4640
  /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiArrowLeft, { size: 16 })
4545
- ), /* @__PURE__ */ import_react7.default.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ import_react7.default.createElement("p", { className: "text-xs/relaxed text-slate-400 uppercase tracking-wider font-semibold" }, showProperties ? "Propriedades Adicionais" : "Modo de Leitura"), /* @__PURE__ */ import_react7.default.createElement("h2", { className: "text-lg sm:text-xl font-semibold tracking-tight text-white truncate", title }, title || "Sem T\xEDtulo"))), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-2 flex-shrink-0" }, hasCustomProps && /* @__PURE__ */ import_react7.default.createElement(
4641
+ ), /* @__PURE__ */ import_react7.default.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ import_react7.default.createElement("p", { className: "text-xs/relaxed text-slate-400 uppercase tracking-wider font-semibold" }, showAbstraction ? "Tree de Abstra\xE7\xE3o" : showProperties ? "Propriedades Adicionais" : "Modo de Leitura"), /* @__PURE__ */ import_react7.default.createElement("h2", { className: "text-lg sm:text-xl font-semibold tracking-tight text-white truncate", title }, title || "Sem T\xEDtulo"))), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-2 flex-shrink-0" }, hasCustomProps && /* @__PURE__ */ import_react7.default.createElement(
4546
4642
  "button",
4547
4643
  {
4548
- onClick: () => setShowProperties(!showProperties),
4644
+ onClick: handleToggleProperties,
4549
4645
  className: `relative w-9 h-9 grid place-content-center rounded-lg border transition-colors
4550
4646
  ${showProperties ? "border-cyan-500/50 bg-cyan-500/10 text-cyan-300" : "border-white/15 bg-transparent hover:bg-white/5 text-slate-300 hover:text-white"}`,
4551
4647
  title: showProperties ? "Ver Descri\xE7\xE3o" : "Ver Propriedades Adicionais"
4552
4648
  },
4553
4649
  showProperties ? /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiAlignLeft, { size: 16 }) : /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiList, { size: 16 }),
4554
- !showProperties && /* @__PURE__ */ import_react7.default.createElement("span", { className: "absolute top-1.5 right-1.5 block h-2 w-2 rounded-full bg-cyan-400 ring-2 ring-slate-900 animate-pulse" })
4650
+ !showProperties && !showAbstraction && /* @__PURE__ */ import_react7.default.createElement("span", { className: "absolute top-1.5 right-1.5 block h-2 w-2 rounded-full bg-cyan-400 ring-2 ring-slate-900 animate-pulse" })
4651
+ ), hasAbstraction && /* @__PURE__ */ import_react7.default.createElement(
4652
+ "button",
4653
+ {
4654
+ onClick: handleToggleAbstraction,
4655
+ className: `relative w-9 h-9 grid place-content-center rounded-lg border transition-colors
4656
+ ${showAbstraction ? "border-purple-500/50 bg-purple-500/10 text-purple-300" : "border-white/15 bg-transparent hover:bg-white/5 text-slate-300 hover:text-white"}`,
4657
+ title: showAbstraction ? "Voltar \xE0 Descri\xE7\xE3o" : "Ver Tree de Abstra\xE7\xE3o"
4658
+ },
4659
+ /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiGitBranch, { size: 16 })
4555
4660
  ), onRenderFullAncestry && /* @__PURE__ */ import_react7.default.createElement(
4556
4661
  "button",
4557
4662
  {
@@ -4565,7 +4670,7 @@ function DescriptionReadModePanel({
4565
4670
  {
4566
4671
  onClick: onEdit,
4567
4672
  className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-slate-300 hover:text-white",
4568
- title: "Editar Descri\xE7\xE3o"
4673
+ title: "Editar Descri\xE7\xE3o / Estrutura"
4569
4674
  },
4570
4675
  /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiEdit2, { size: 16 })
4571
4676
  ), /* @__PURE__ */ import_react7.default.createElement(
@@ -4577,7 +4682,40 @@ function DescriptionReadModePanel({
4577
4682
  },
4578
4683
  "\xD7"
4579
4684
  ))),
4580
- /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 bg-slate-900/20 relative z-10" }, showProperties ? /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-4 animate-in fade-in slide-in-from-bottom-2 duration-300" }, customProperties.map((prop) => /* @__PURE__ */ import_react7.default.createElement(
4685
+ /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 bg-slate-900/20 relative z-10", onClick: () => setTargetRenderNodeId(null) }, showAbstraction ? /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-4 animate-in fade-in slide-in-from-bottom-2 duration-300", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-4" }, /* @__PURE__ */ import_react7.default.createElement("h3", { className: "text-sm font-semibold text-purple-300 uppercase tracking-wider" }, "Explorar Hierarquia"), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex flex-wrap gap-2" }, targetRenderNodeId && onRenderAbstractionTree && /* @__PURE__ */ import_react7.default.createElement(
4686
+ "button",
4687
+ {
4688
+ onClick: (e) => {
4689
+ e.stopPropagation();
4690
+ onRenderAbstractionTree(targetRenderNodeId);
4691
+ },
4692
+ className: "px-3 py-1.5 rounded-md bg-fuchsia-600 text-white hover:bg-fuchsia-500 transition-colors flex items-center gap-1.5 text-xs font-bold shadow-lg animate-in zoom-in-95 duration-200",
4693
+ title: "Renderiza no 3D apenas o caminho at\xE9 o Node selecionado"
4694
+ },
4695
+ /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiLayers, { size: 14 }),
4696
+ " Renderizar Caminho"
4697
+ ), onRenderAbstractionTree && /* @__PURE__ */ import_react7.default.createElement(
4698
+ "button",
4699
+ {
4700
+ onClick: (e) => {
4701
+ e.stopPropagation();
4702
+ setTargetRenderNodeId(null);
4703
+ onRenderAbstractionTree(null);
4704
+ },
4705
+ className: "px-3 py-1.5 rounded-md bg-slate-700 border border-white/10 text-slate-200 hover:bg-slate-600 hover:text-white transition-colors flex items-center gap-1.5 text-xs font-semibold",
4706
+ title: "Renderiza a Abstraction Tree inteira verticalmente"
4707
+ },
4708
+ /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiLayers, { size: 14 }),
4709
+ " Renderizar Completa"
4710
+ ))), /* @__PURE__ */ import_react7.default.createElement("div", { className: "bg-slate-900/60 border border-white/10 rounded-lg p-4" }, /* @__PURE__ */ import_react7.default.createElement(
4711
+ ReadOnlyNodeItem,
4712
+ {
4713
+ nodeData: abstractionTree,
4714
+ onViewSelect: setTargetRenderNodeId,
4715
+ highlightedPathIds,
4716
+ targetRenderNodeId
4717
+ }
4718
+ ))) : showProperties ? /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-4 animate-in fade-in slide-in-from-bottom-2 duration-300" }, customProperties.map((prop) => /* @__PURE__ */ import_react7.default.createElement(
4581
4719
  CustomPropertyDisplay,
4582
4720
  {
4583
4721
  key: prop.id,
@@ -4606,7 +4744,7 @@ function DescriptionReadModePanel({
4606
4744
  onImageClick
4607
4745
  }
4608
4746
  )),
4609
- leftAction && /* @__PURE__ */ import_react7.default.createElement(
4747
+ leftAction && !showAbstraction && !showProperties && /* @__PURE__ */ import_react7.default.createElement(
4610
4748
  "button",
4611
4749
  {
4612
4750
  onClick: leftAction.onClick,
@@ -4618,7 +4756,7 @@ function DescriptionReadModePanel({
4618
4756
  ${leftAction.type === "branch" ? "bg-indigo-500/20 text-indigo-300 group-hover/btn:text-white group-hover/btn:bg-indigo-500" : "bg-rose-500/20 text-rose-300 group-hover/btn:text-white group-hover/btn:bg-rose-500"}
4619
4757
  ` }, leftAction.type === "branch" ? /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiChevronLeft, { size: 20 }) : /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiCornerUpLeft, { size: 20 }))
4620
4758
  ),
4621
- rightAction && /* @__PURE__ */ import_react7.default.createElement(
4759
+ rightAction && !showAbstraction && !showProperties && /* @__PURE__ */ import_react7.default.createElement(
4622
4760
  "button",
4623
4761
  {
4624
4762
  onClick: rightAction.onClick,
@@ -4871,7 +5009,7 @@ function AncestryPickerModal({
4871
5009
  }
4872
5010
 
4873
5011
  // src/components/CreateAncestryPanel.jsx
4874
- var findNodePath = (tree, targetNodeId, currentPath = []) => {
5012
+ var findNodePath2 = (tree, targetNodeId, currentPath = []) => {
4875
5013
  var _a;
4876
5014
  if (!tree) return null;
4877
5015
  const currentNodeId = tree.is_section ? tree.section_id : String((_a = tree.node) == null ? void 0 : _a.id);
@@ -4880,22 +5018,41 @@ var findNodePath = (tree, targetNodeId, currentPath = []) => {
4880
5018
  }
4881
5019
  if (tree.children) {
4882
5020
  for (let i = 0; i < tree.children.length; i++) {
4883
- const res = findNodePath(tree.children[i], targetNodeId, [...currentPath, i]);
5021
+ const res = findNodePath2(tree.children[i], targetNodeId, [...currentPath, i]);
4884
5022
  if (res) return res;
4885
5023
  }
4886
5024
  }
4887
5025
  return null;
4888
5026
  };
4889
- var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, onMoveNode, selectedParentId, level = 0, isLast = false, path = [], isEditable }) => {
5027
+ var NodeItem = ({ nodeData, onSelectParent, onViewSelect, highlightedPathIds = [], targetRenderNodeId, onRemoveNode, onEditRelationship, onMoveNode, selectedParentId, level = 0, isLast = false, path = [], isEditable }) => {
4890
5028
  var _a, _b;
4891
5029
  const itemId = nodeData.is_section ? nodeData.id : (_a = nodeData.node) == null ? void 0 : _a.id;
4892
5030
  const itemName = nodeData.is_section ? nodeData.name : (_b = nodeData.node) == null ? void 0 : _b.name;
4893
5031
  const [isDragOver, setIsDragOver] = (0, import_react10.useState)(false);
4894
- const isSelected = String(selectedParentId) === String(itemId);
5032
+ const isSelectedParent = String(selectedParentId) === String(itemId);
5033
+ const isTargetViewNode = String(targetRenderNodeId) === String(itemId);
5034
+ const isHighlightedPath = highlightedPathIds.includes(String(itemId));
4895
5035
  const hasChildren = nodeData.children && nodeData.children.length > 0;
4896
- 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";
4897
- const textColorClass = nodeData.is_section ? isSelected ? "text-indigo-200 font-bold" : "text-indigo-300" : isSelected ? "text-cyan-200 font-semibold" : "text-slate-200";
4898
- const cursorClass = isEditable ? "cursor-grab active:cursor-grabbing" : "cursor-default";
5036
+ let itemBgClass = "bg-slate-900/50 hover:bg-slate-800/80";
5037
+ let textColorClass = "text-slate-200";
5038
+ if (nodeData.is_section) {
5039
+ 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";
5040
+ textColorClass = isSelectedParent ? "text-indigo-200 font-bold" : "text-indigo-300";
5041
+ } else {
5042
+ if (isSelectedParent) {
5043
+ itemBgClass = "bg-purple-500/30 ring-2 ring-purple-400";
5044
+ textColorClass = "text-purple-200 font-semibold";
5045
+ } else if (isTargetViewNode) {
5046
+ itemBgClass = "bg-fuchsia-600/40 ring-2 ring-fuchsia-400 shadow-[0_0_15px_rgba(217,70,239,0.3)]";
5047
+ textColorClass = "text-white font-bold";
5048
+ } else if (isHighlightedPath) {
5049
+ itemBgClass = "bg-fuchsia-900/30 border border-fuchsia-500/40";
5050
+ textColorClass = "text-fuchsia-200 font-semibold";
5051
+ } else {
5052
+ textColorClass = "text-slate-200";
5053
+ }
5054
+ }
5055
+ const cursorClass = isEditable ? "cursor-grab active:cursor-grabbing" : "cursor-pointer";
4899
5056
  const handleDragStart = (e) => {
4900
5057
  if (!isEditable) {
4901
5058
  e.preventDefault();
@@ -4925,23 +5082,9 @@ var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, on
4925
5082
  if (!isEditable) return;
4926
5083
  const sourceId = e.dataTransfer.getData("nodeId");
4927
5084
  if (sourceId === String(itemId)) return;
4928
- if (onMoveNode) {
4929
- onMoveNode(sourceId, itemId);
4930
- }
5085
+ if (onMoveNode) onMoveNode(sourceId, itemId);
4931
5086
  };
4932
- 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(
4933
- "span",
4934
- {
4935
- className: `absolute -left-4 top-0 w-px bg-cyan-600/60 ${isLast ? "h-[1.125rem]" : "h-full"}`,
4936
- "aria-hidden": "true"
4937
- }
4938
- ), /* @__PURE__ */ import_react10.default.createElement(
4939
- "span",
4940
- {
4941
- className: `absolute -left-4 top-[1.125rem] h-px w-4 bg-cyan-600/60`,
4942
- "aria-hidden": "true"
4943
- }
4944
- )), /* @__PURE__ */ import_react10.default.createElement(
5087
+ 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(
4945
5088
  "div",
4946
5089
  {
4947
5090
  draggable: isEditable,
@@ -4949,63 +5092,35 @@ var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, on
4949
5092
  onDragOver: handleDragOver,
4950
5093
  onDragLeave: handleDragLeave,
4951
5094
  onDrop: handleDrop,
4952
- onClick: () => {
5095
+ onClick: (e) => {
5096
+ e.stopPropagation();
4953
5097
  if (isEditable) {
4954
5098
  onSelectParent(itemId);
5099
+ } else if (onViewSelect) {
5100
+ onViewSelect(itemId);
4955
5101
  }
4956
5102
  },
4957
5103
  className: `flex items-center justify-between gap-2 px-3 h-9 rounded-md transition-all duration-150 border
4958
5104
  ${isDragOver ? "border-dashed border-yellow-400 bg-yellow-400/10" : "border-transparent"}
4959
5105
  ${itemBgClass} ${cursorClass}`
4960
5106
  },
4961
- /* @__PURE__ */ import_react10.default.createElement("span", { className: `truncate flex items-center ${textColorClass}` }, level === 0 && !nodeData.is_section && /* @__PURE__ */ import_react10.default.createElement(
4962
- "svg",
4963
- {
4964
- xmlns: "http://www.w3.org/2000/svg",
4965
- width: "16",
4966
- height: "16",
4967
- viewBox: "0 0 24 24",
4968
- fill: "none",
4969
- stroke: "currentColor",
4970
- strokeWidth: "2",
4971
- strokeLinecap: "round",
4972
- strokeLinejoin: "round",
4973
- className: "lucide lucide-blend-icon lucide-blend mr-1.5 inline-block"
4974
- },
4975
- /* @__PURE__ */ import_react10.default.createElement("circle", { cx: "9", cy: "9", r: "7" }),
4976
- /* @__PURE__ */ import_react10.default.createElement("circle", { cx: "15", cy: "15", r: "7" })
4977
- ), nodeData.is_section && /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiFolder, { className: "mr-2" }), itemName),
4978
- 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(
4979
- "button",
4980
- {
4981
- onClick: (e) => {
4982
- e.stopPropagation();
4983
- onEditRelationship(path, nodeData.relationship || {});
4984
- },
4985
- className: "w-6 h-6 grid place-content-center rounded-full hover:bg-cyan-500/20 text-cyan-400 transition-colors flex-shrink-0",
4986
- title: "Editar detalhes da rela\xE7\xE3o",
4987
- style: { cursor: "pointer" }
4988
- },
4989
- /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiEdit2, { size: 12 })
4990
- ), /* @__PURE__ */ import_react10.default.createElement(
4991
- "button",
4992
- {
4993
- onClick: (e) => {
4994
- e.stopPropagation();
4995
- onRemoveNode(path);
4996
- },
4997
- 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",
4998
- title: "Remover Node da ancestralidade",
4999
- style: { cursor: "pointer" }
5000
- },
5001
- "\xD7"
5002
- ))
5107
+ /* @__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),
5108
+ 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) => {
5109
+ e.stopPropagation();
5110
+ onEditRelationship(path, nodeData.relationship || {});
5111
+ }, 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) => {
5112
+ e.stopPropagation();
5113
+ onRemoveNode(path);
5114
+ }, 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"))
5003
5115
  ), 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(
5004
5116
  NodeItem,
5005
5117
  {
5006
5118
  key: `${child.is_section ? child.id : child.node.id}-${index}`,
5007
5119
  nodeData: child,
5008
5120
  onSelectParent,
5121
+ onViewSelect,
5122
+ highlightedPathIds,
5123
+ targetRenderNodeId,
5009
5124
  onRemoveNode,
5010
5125
  onEditRelationship,
5011
5126
  onMoveNode,
@@ -5020,11 +5135,8 @@ var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, on
5020
5135
  function CreateAncestryPanel({
5021
5136
  ancestryMode,
5022
5137
  setAncestryMode,
5023
- // <--- Nova prop necessária para as novas funções manipuladoras
5024
5138
  onSelectParent,
5025
- // Mantido para compatibilidade, mas as novas funções usam setAncestryMode
5026
5139
  onRemoveNode,
5027
- // Mantido para compatibilidade
5028
5140
  onSave,
5029
5141
  onClose,
5030
5142
  onEditRelationship,
@@ -5035,14 +5147,12 @@ function CreateAncestryPanel({
5035
5147
  onUpdateTree,
5036
5148
  onAncestrySectionChange,
5037
5149
  onToggleAddNodes,
5038
- // Mantido para compatibilidade
5039
5150
  onRenderFullAncestry,
5040
5151
  onHighlightNode,
5041
5152
  onClearAncestryVisuals,
5042
5153
  onUploadFile,
5043
5154
  onOpenImageViewer,
5044
5155
  onRenderAbstractionTree
5045
- // <--- Nova prop recebida
5046
5156
  }) {
5047
5157
  const {
5048
5158
  tree: rootTree,
@@ -5059,6 +5169,20 @@ function CreateAncestryPanel({
5059
5169
  const [customProps, setCustomProps] = (0, import_react10.useState)([]);
5060
5170
  const propsEndRef = (0, import_react10.useRef)(null);
5061
5171
  const [branchStack, setBranchStack] = (0, import_react10.useState)([]);
5172
+ const [targetRenderNodeId, setTargetRenderNodeId] = (0, import_react10.useState)(null);
5173
+ const highlightedPathIds = (0, import_react10.useMemo)(() => {
5174
+ var _a, _b;
5175
+ if (!targetRenderNodeId || !ancestryMode.abstraction_tree) return [];
5176
+ const found = findNodePath2(ancestryMode.abstraction_tree, targetRenderNodeId);
5177
+ if (!found) return [];
5178
+ let current = ancestryMode.abstraction_tree;
5179
+ const ids = [current.is_section ? current.section_id : String((_a = current.node) == null ? void 0 : _a.id)];
5180
+ for (let i of found.path) {
5181
+ current = current.children[i];
5182
+ ids.push(current.is_section ? current.section_id : String((_b = current.node) == null ? void 0 : _b.id));
5183
+ }
5184
+ return ids;
5185
+ }, [targetRenderNodeId, ancestryMode.abstraction_tree]);
5062
5186
  const [targetScrollSectionId, setTargetScrollSectionId] = (0, import_react10.useState)(null);
5063
5187
  const [internalHighlightedNodeId, setInternalHighlightedNodeId] = (0, import_react10.useState)(null);
5064
5188
  const [ancestryName, setAncestryName] = (0, import_react10.useState)(initialName);
@@ -5082,6 +5206,9 @@ function CreateAncestryPanel({
5082
5206
  setAncestryMode((prev) => isAbstraction ? { ...prev, selectedAbstractionParentId: nodeId } : { ...prev, selectedParentId: nodeId });
5083
5207
  };
5084
5208
  const handleToggleAddMode = (isAbstraction = false) => {
5209
+ if (isAbstraction && !ancestryMode.isAddingAbstractionNodes) {
5210
+ setTargetRenderNodeId(null);
5211
+ }
5085
5212
  setAncestryMode((prev) => isAbstraction ? { ...prev, isAddingAbstractionNodes: !prev.isAddingAbstractionNodes } : { ...prev, isAddingNodes: !prev.isAddingNodes });
5086
5213
  };
5087
5214
  const handleRemoveNode = (0, import_react10.useCallback)((pathToRemove, isAbstraction = false) => {
@@ -5113,7 +5240,7 @@ function CreateAncestryPanel({
5113
5240
  if (!isAbstraction && branchStack.length > 0) {
5114
5241
  let ptr = rootTreeClone;
5115
5242
  for (const step of branchStack) {
5116
- const found = findNodePath(ptr, step.nodeId);
5243
+ const found = findNodePath2(ptr, step.nodeId);
5117
5244
  if (found && found.node.parallel_branches) {
5118
5245
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5119
5246
  if (branch) ptr = branch.tree;
@@ -5163,14 +5290,15 @@ function CreateAncestryPanel({
5163
5290
  }
5164
5291
  }
5165
5292
  };
5166
- const takeSnapshot = (tree, name, desc, sections, customProps2, isPrivateVal) => {
5293
+ const takeSnapshot = (tree, name, desc, sections, customProps2, isPrivateVal, abstractionTree = null) => {
5167
5294
  return {
5168
5295
  tree: JSON.stringify(tree),
5169
5296
  name,
5170
5297
  description: desc || "",
5171
5298
  sections: JSON.stringify(sections || []),
5172
5299
  customProps: JSON.stringify(customProps2 || []),
5173
- isPrivate: isPrivateVal
5300
+ isPrivate: isPrivateVal,
5301
+ abstractionTree: JSON.stringify(abstractionTree)
5174
5302
  };
5175
5303
  };
5176
5304
  const getCurrentContext = () => {
@@ -5189,7 +5317,7 @@ function CreateAncestryPanel({
5189
5317
  let currentBranch = null;
5190
5318
  let currentDirection = null;
5191
5319
  for (const step of branchStack) {
5192
- const found = findNodePath(currentTreePtr, step.nodeId);
5320
+ const found = findNodePath2(currentTreePtr, step.nodeId);
5193
5321
  if (!found || !found.node.parallel_branches) return null;
5194
5322
  currentBranch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5195
5323
  if (!currentBranch) return null;
@@ -5271,7 +5399,7 @@ function CreateAncestryPanel({
5271
5399
  let ptr = ancestryMode.tree;
5272
5400
  let foundBranch = null;
5273
5401
  for (const step of branchStack) {
5274
- const found = findNodePath(ptr, step.nodeId);
5402
+ const found = findNodePath2(ptr, step.nodeId);
5275
5403
  if (found && found.node.parallel_branches) {
5276
5404
  foundBranch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5277
5405
  if (foundBranch) ptr = foundBranch.tree;
@@ -5304,7 +5432,8 @@ function CreateAncestryPanel({
5304
5432
  ancestryMode.ancestryDescription,
5305
5433
  ancestryMode.ancestryDescriptionSections,
5306
5434
  extractedProps,
5307
- ancestryMode.is_private
5435
+ ancestryMode.is_private,
5436
+ ancestryMode.abstraction_tree
5308
5437
  ));
5309
5438
  } else if (ctx) {
5310
5439
  setLastSavedSnapshot(takeSnapshot(
@@ -5313,7 +5442,8 @@ function CreateAncestryPanel({
5313
5442
  ctx.description,
5314
5443
  ctx.sections,
5315
5444
  extractedProps,
5316
- isPrivate
5445
+ isPrivate,
5446
+ ancestryMode.abstraction_tree
5317
5447
  ));
5318
5448
  }
5319
5449
  }, [branchStack, ancestryMode]);
@@ -5328,7 +5458,7 @@ function CreateAncestryPanel({
5328
5458
  let ptr = rootTreeClone;
5329
5459
  let targetBranch = null;
5330
5460
  for (const step of branchStack) {
5331
- const found = findNodePath(ptr, step.nodeId);
5461
+ const found = findNodePath2(ptr, step.nodeId);
5332
5462
  if (found && found.node.parallel_branches) {
5333
5463
  targetBranch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5334
5464
  if (targetBranch) ptr = targetBranch.tree;
@@ -5356,7 +5486,7 @@ function CreateAncestryPanel({
5356
5486
  rootTreeClone,
5357
5487
  rootExtras
5358
5488
  );
5359
- setLastSavedSnapshot(takeSnapshot(rootTreeClone, ancestryName, description, processedSections, [], isPrivate));
5489
+ setLastSavedSnapshot(takeSnapshot(rootTreeClone, ancestryName, description, processedSections, [], isPrivate, ancestryMode.abstraction_tree));
5360
5490
  if (onRenderFullAncestry) {
5361
5491
  const fullTreePayload = {
5362
5492
  ancestry_id: ancestryMode.currentAncestryId || "temp_root",
@@ -5386,14 +5516,14 @@ function CreateAncestryPanel({
5386
5516
  let ptr = rootTreeClone;
5387
5517
  for (let i = 0; i < branchStack.length - 1; i++) {
5388
5518
  const step = branchStack[i];
5389
- const found = findNodePath(ptr, step.nodeId);
5519
+ const found = findNodePath2(ptr, step.nodeId);
5390
5520
  if (found && found.node.parallel_branches) {
5391
5521
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5392
5522
  if (branch) ptr = branch.tree;
5393
5523
  }
5394
5524
  }
5395
5525
  const currentStep = branchStack[branchStack.length - 1];
5396
- const foundParentPath = findNodePath(ptr, currentStep.nodeId);
5526
+ const foundParentPath = findNodePath2(ptr, currentStep.nodeId);
5397
5527
  if (foundParentPath && foundParentPath.node && foundParentPath.node.parallel_branches) {
5398
5528
  const branchIndex = foundParentPath.node.parallel_branches.findIndex((b) => b.id === currentStep.branchId);
5399
5529
  if (branchIndex !== -1) {
@@ -5417,7 +5547,8 @@ function CreateAncestryPanel({
5417
5547
  ancestryMode.ancestryDescription,
5418
5548
  ancestryMode.ancestryDescriptionSections,
5419
5549
  currentRootProps,
5420
- isPrivate
5550
+ isPrivate,
5551
+ ancestryMode.abstraction_tree
5421
5552
  ));
5422
5553
  if (onClearAncestryVisuals) {
5423
5554
  onClearAncestryVisuals(currentStep.branchId);
@@ -5436,7 +5567,7 @@ function CreateAncestryPanel({
5436
5567
  const actions = { left: null, right: null };
5437
5568
  const isInBranch = branchStack.length > 0;
5438
5569
  if (internalHighlightedNodeId) {
5439
- const found = findNodePath(activeTree, internalHighlightedNodeId);
5570
+ const found = findNodePath2(activeTree, internalHighlightedNodeId);
5440
5571
  if (found && found.node) {
5441
5572
  const branches = found.node.parallel_branches || [];
5442
5573
  const leftBranch = branches.find((b) => (b.direction || "right") === "left");
@@ -5488,7 +5619,7 @@ function CreateAncestryPanel({
5488
5619
  if (branchStack.length > 0) {
5489
5620
  let ptr = rootTreeClone;
5490
5621
  for (const step of branchStack) {
5491
- const found = findNodePath(ptr, step.nodeId);
5622
+ const found = findNodePath2(ptr, step.nodeId);
5492
5623
  if (found && found.node.parallel_branches) {
5493
5624
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5494
5625
  if (branch) ptr = branch.tree;
@@ -5606,6 +5737,11 @@ function CreateAncestryPanel({
5606
5737
  const sectionsChanged = JSON.stringify(existingSections) !== lastSavedSnapshot.sections;
5607
5738
  const propsChanged = JSON.stringify(customProps) !== lastSavedSnapshot.customProps;
5608
5739
  const privateChanged = isPrivate !== lastSavedSnapshot.isPrivate;
5740
+ let abstractionTreeChanged = false;
5741
+ if (branchStack.length === 0) {
5742
+ const currentAbsTreeStr = JSON.stringify(ancestryMode.abstraction_tree);
5743
+ abstractionTreeChanged = currentAbsTreeStr !== lastSavedSnapshot.abstractionTree;
5744
+ }
5609
5745
  return treeChanged || nameChanged || descChanged || sectionsChanged || propsChanged || privateChanged;
5610
5746
  }, [
5611
5747
  ancestryName,
@@ -5615,6 +5751,7 @@ function CreateAncestryPanel({
5615
5751
  branchStack,
5616
5752
  lastSavedSnapshot,
5617
5753
  ancestryMode.tree,
5754
+ ancestryMode.abstraction_tree,
5618
5755
  customProps,
5619
5756
  isPrivate
5620
5757
  ]);
@@ -5628,7 +5765,7 @@ function CreateAncestryPanel({
5628
5765
  let parentTreePtr = rootTree;
5629
5766
  let parentBranch = null;
5630
5767
  for (const step of parentStack) {
5631
- const found = findNodePath(parentTreePtr, step.nodeId);
5768
+ const found = findNodePath2(parentTreePtr, step.nodeId);
5632
5769
  if (found && found.node.parallel_branches) {
5633
5770
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5634
5771
  if (branch) {
@@ -5706,7 +5843,7 @@ function CreateAncestryPanel({
5706
5843
  const rootTreeClone = JSON.parse(JSON.stringify(ancestryMode.tree));
5707
5844
  let ptr = rootTreeClone;
5708
5845
  for (const step of branchStack) {
5709
- const foundParent = findNodePath(ptr, step.nodeId);
5846
+ const foundParent = findNodePath2(ptr, step.nodeId);
5710
5847
  if (foundParent && foundParent.node && foundParent.node.parallel_branches) {
5711
5848
  const existingBranch = foundParent.node.parallel_branches.find((b) => b.id === step.branchId);
5712
5849
  if (existingBranch) {
@@ -5714,7 +5851,7 @@ function CreateAncestryPanel({
5714
5851
  }
5715
5852
  }
5716
5853
  }
5717
- const found = findNodePath(ptr, nodeId);
5854
+ const found = findNodePath2(ptr, nodeId);
5718
5855
  if (!found) {
5719
5856
  console.error("Node alvo n\xE3o encontrado no contexto atual.");
5720
5857
  return;
@@ -5827,7 +5964,7 @@ function CreateAncestryPanel({
5827
5964
  let ptr = updatedRootTree;
5828
5965
  let targetBranch = null;
5829
5966
  for (const step of branchStack) {
5830
- const found = findNodePath(ptr, step.nodeId);
5967
+ const found = findNodePath2(ptr, step.nodeId);
5831
5968
  if (found && found.node.parallel_branches) {
5832
5969
  targetBranch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5833
5970
  if (targetBranch) ptr = targetBranch.tree;
@@ -5857,7 +5994,8 @@ function CreateAncestryPanel({
5857
5994
  currentInputDesc,
5858
5995
  processedSections,
5859
5996
  customProps,
5860
- isPrivate
5997
+ isPrivate,
5998
+ ancestryMode.abstraction_tree
5861
5999
  ));
5862
6000
  if (onRenderFullAncestry) {
5863
6001
  const rotation = branchStack.reduce((acc, step) => {
@@ -5916,7 +6054,8 @@ function CreateAncestryPanel({
5916
6054
  currentInputDesc,
5917
6055
  processedSections,
5918
6056
  customProps,
5919
- isPrivate
6057
+ isPrivate,
6058
+ ancestryMode.abstraction_tree
5920
6059
  ));
5921
6060
  if (!keepOpen) onClose();
5922
6061
  } finally {
@@ -5969,7 +6108,9 @@ function CreateAncestryPanel({
5969
6108
  const node = findNode(activeTree, selectedParentId);
5970
6109
  return node ? node.name : "Nenhum";
5971
6110
  };
5972
- const hasChildren = activeTree && activeTree.children && activeTree.children.length > 0;
6111
+ const hasMainChildren = activeTree && activeTree.children && activeTree.children.length > 0;
6112
+ const hasAbstractionChildren = branchStack.length === 0 && ancestryMode.abstraction_tree && ancestryMode.abstraction_tree.children && ancestryMode.abstraction_tree.children.length > 0;
6113
+ const canSave = hasMainChildren || hasAbstractionChildren;
5973
6114
  const handleSectionChangeWrapper = (sectionId) => {
5974
6115
  const ctx = getCurrentContext();
5975
6116
  const currentDesc = ctx ? ctx.description : description;
@@ -6172,7 +6313,7 @@ function CreateAncestryPanel({
6172
6313
  unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type),
6173
6314
  onUploadFile
6174
6315
  }
6175
- )), /* @__PURE__ */ import_react10.default.createElement("div", { ref: propsEndRef }))), /* @__PURE__ */ import_react10.default.createElement("div", { className: `rounded-lg border transition-all duration-300 overflow-hidden ${isAddingNodes ? "border-cyan-500/40 bg-slate-900/60 ring-1 ring-cyan-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 ${isAddingNodes ? "bg-cyan-900/20 border-cyan-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 ${isAddingNodes ? "text-cyan-300" : "text-slate-400"}` }, "Estrutura ", branchStack.length > 0 && "(Aba)"), isAddingNodes && /* @__PURE__ */ import_react10.default.createElement("span", { className: "text-[10px] bg-cyan-500/20 text-cyan-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(
6316
+ )), /* @__PURE__ */ import_react10.default.createElement("div", { ref: propsEndRef }))), /* @__PURE__ */ import_react10.default.createElement("div", { className: `rounded-lg border transition-all duration-300 overflow-hidden ${isAddingNodes ? "border-cyan-500/40 bg-slate-900/60 ring-1 ring-cyan-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 ${isAddingNodes ? "bg-cyan-900/20 border-cyan-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 ${isAddingNodes ? "text-cyan-300" : "text-slate-400"}` }, "TREE DE ANCESTRALIDADE ", branchStack.length > 0 && "(Aba)"), isAddingNodes && /* @__PURE__ */ import_react10.default.createElement("span", { className: "text-[10px] bg-cyan-500/20 text-cyan-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(
6176
6317
  "button",
6177
6318
  {
6178
6319
  type: "button",
@@ -6203,44 +6344,77 @@ function CreateAncestryPanel({
6203
6344
  path: [],
6204
6345
  isEditable: isAddingNodes
6205
6346
  }
6206
- ), (!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(
6207
- "button",
6208
- {
6209
- type: "button",
6210
- onClick: () => {
6211
- const tempPayload = {
6212
- ancestry_id: currentAncestryId || "temp_rendering",
6213
- abstraction_tree: ancestryMode.abstraction_tree
6214
- };
6215
- if (onRenderAbstractionTree) onRenderAbstractionTree(tempPayload);
6216
- },
6217
- className: "p-1.5 rounded-md bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600 transition-colors",
6218
- title: "Renderizar Verticalmente no Cen\xE1rio"
6219
- },
6220
- /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiLayers, { size: 14 })
6221
- ), /* @__PURE__ */ import_react10.default.createElement(
6222
- "button",
6347
+ ), (!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(
6348
+ "div",
6223
6349
  {
6224
- onClick: () => handleToggleAddMode(true),
6225
- 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"}`,
6226
- title: "Editar estrutura da abstra\xE7\xE3o"
6350
+ 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"}`,
6351
+ onClick: () => setTargetRenderNodeId(null)
6227
6352
  },
6228
- ancestryMode.isAddingAbstractionNodes ? /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiCheck, { size: 14 }) : /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiEdit2, { size: 14 })
6229
- ))), /* @__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(
6230
- NodeItem,
6231
- {
6232
- nodeData: ancestryMode.abstraction_tree,
6233
- onSelectParent: (id) => handleSelectAncestryParent(id, true),
6234
- onRemoveNode: (path) => handleRemoveNode(path, true),
6235
- onEditRelationship,
6236
- onMoveNode: (s, t) => handleMoveNode(s, t, true),
6237
- selectedParentId: ancestryMode.selectedAbstractionParentId,
6238
- level: 0,
6239
- isLast: true,
6240
- path: [],
6241
- isEditable: ancestryMode.isAddingAbstractionNodes
6242
- }
6243
- ))), 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(
6353
+ /* @__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"}` }, "Tree 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(
6354
+ "button",
6355
+ {
6356
+ type: "button",
6357
+ onClick: (e) => {
6358
+ e.stopPropagation();
6359
+ const tempPayload = {
6360
+ ancestry_id: currentAncestryId || "temp_rendering",
6361
+ abstraction_tree: ancestryMode.abstraction_tree
6362
+ };
6363
+ if (onRenderAbstractionTree) onRenderAbstractionTree(tempPayload, targetRenderNodeId);
6364
+ },
6365
+ 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",
6366
+ title: "Renderizar cen\xE1rio at\xE9 o caminho selecionado"
6367
+ },
6368
+ /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiLayers, { size: 13 }),
6369
+ /* @__PURE__ */ import_react10.default.createElement("span", { className: "text-[10px] font-bold uppercase tracking-wider" }, "Renderizar")
6370
+ ), /* @__PURE__ */ import_react10.default.createElement(
6371
+ "button",
6372
+ {
6373
+ type: "button",
6374
+ onClick: (e) => {
6375
+ e.stopPropagation();
6376
+ const tempPayload = {
6377
+ ancestry_id: currentAncestryId || "temp_rendering",
6378
+ abstraction_tree: ancestryMode.abstraction_tree
6379
+ };
6380
+ if (onRenderAbstractionTree) onRenderAbstractionTree(tempPayload);
6381
+ },
6382
+ className: "p-1.5 rounded-md bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600 transition-colors",
6383
+ title: "Renderizar Verticalmente Completo"
6384
+ },
6385
+ /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiLayers, { size: 14 })
6386
+ ), /* @__PURE__ */ import_react10.default.createElement(
6387
+ "button",
6388
+ {
6389
+ type: "button",
6390
+ onClick: (e) => {
6391
+ e.stopPropagation();
6392
+ handleToggleAddMode(true);
6393
+ },
6394
+ 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"}`,
6395
+ title: "Editar estrutura da abstra\xE7\xE3o"
6396
+ },
6397
+ ancestryMode.isAddingAbstractionNodes ? /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiCheck, { size: 14 }) : /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiEdit2, { size: 14 })
6398
+ ))),
6399
+ /* @__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(
6400
+ NodeItem,
6401
+ {
6402
+ nodeData: ancestryMode.abstraction_tree,
6403
+ onSelectParent: (id) => handleSelectAncestryParent(id, true),
6404
+ onViewSelect: setTargetRenderNodeId,
6405
+ highlightedPathIds,
6406
+ targetRenderNodeId,
6407
+ onRemoveNode: (path) => handleRemoveNode(path, true),
6408
+ onEditRelationship,
6409
+ onMoveNode: (s, t) => handleMoveNode(s, t, true),
6410
+ selectedParentId: ancestryMode.selectedAbstractionParentId,
6411
+ level: 0,
6412
+ isLast: true,
6413
+ path: [],
6414
+ isEditable: ancestryMode.isAddingAbstractionNodes
6415
+ }
6416
+ ))
6417
+ ), 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(
6244
6418
  "input",
6245
6419
  {
6246
6420
  type: "checkbox",
@@ -6248,7 +6422,7 @@ function CreateAncestryPanel({
6248
6422
  onChange: (e) => setIsPrivate(e.target.checked),
6249
6423
  className: "hidden"
6250
6424
  }
6251
- ), /* @__PURE__ */ import_react10.default.createElement("span", { className: `text-xs flex items-center gap-1 transition-colors ${isPrivate ? "text-indigo-300" : "text-slate-400 group-hover:text-slate-300"}` }, /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiLock, { size: 10 }), " N\xE3o Export\xE1vel"))))), /* @__PURE__ */ import_react10.default.createElement("div", { className: "px-6 pt-2 pb-5 flex-shrink-0" }, hasChildren && /* @__PURE__ */ import_react10.default.createElement(
6425
+ ), /* @__PURE__ */ import_react10.default.createElement("span", { className: `text-xs flex items-center gap-1 transition-colors ${isPrivate ? "text-indigo-300" : "text-slate-400 group-hover:text-slate-300"}` }, /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiLock, { size: 10 }), " N\xE3o Export\xE1vel"))))), /* @__PURE__ */ import_react10.default.createElement("div", { className: "px-6 pt-2 pb-5 flex-shrink-0" }, canSave && /* @__PURE__ */ import_react10.default.createElement(
6252
6426
  "button",
6253
6427
  {
6254
6428
  onClick: () => handleLocalSave(false),
@@ -8758,7 +8932,7 @@ var getAllNodeIdsFromTree = (treeNode) => {
8758
8932
  traverse(treeNode);
8759
8933
  return Array.from(ids);
8760
8934
  };
8761
- var findNodePath2 = (tree, targetNodeId, currentPath = []) => {
8935
+ var findNodePath3 = (tree, targetNodeId, currentPath = []) => {
8762
8936
  var _a;
8763
8937
  if (!tree) return null;
8764
8938
  const currentNodeId = tree.is_section ? tree.section_id : String((_a = tree.node) == null ? void 0 : _a.id);
@@ -8767,7 +8941,7 @@ var findNodePath2 = (tree, targetNodeId, currentPath = []) => {
8767
8941
  }
8768
8942
  if (tree.children) {
8769
8943
  for (let i = 0; i < tree.children.length; i++) {
8770
- const res = findNodePath2(tree.children[i], targetNodeId, [...currentPath, i]);
8944
+ const res = findNodePath3(tree.children[i], targetNodeId, [...currentPath, i]);
8771
8945
  if (res) return res;
8772
8946
  }
8773
8947
  }
@@ -10836,13 +11010,34 @@ function XViewScene({
10836
11010
  },
10837
11011
  [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, readingMode.isActive, ancestryMode.isActive]
10838
11012
  );
10839
- const handleRenderAbstractionTree = (0, import_react23.useCallback)((ancestryObject) => {
11013
+ const handleRenderAbstractionTree = (0, import_react23.useCallback)((ancestryObject, targetNodeId = null) => {
10840
11014
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
10841
11015
  if (!ancestryObject || !ancestryObject.abstraction_tree) return;
10842
11016
  const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
10843
11017
  const allParentNodes = Object.values(parentDataRef.current).flatMap((f) => f.nodes);
10844
- const fullTree = buildFullAncestryTree(ancestryObject.abstraction_tree, allParentNodes, ancestryDataRef.current);
11018
+ let fullTree = buildFullAncestryTree(ancestryObject.abstraction_tree, allParentNodes, ancestryDataRef.current);
10845
11019
  if (!fullTree || !fullTree.node) return;
11020
+ if (targetNodeId) {
11021
+ const pruneTreeToPath = (treeNode, targetId) => {
11022
+ var _a2;
11023
+ if (!treeNode) return null;
11024
+ const currentId = treeNode.is_section ? treeNode.section_id : String((_a2 = treeNode.node) == null ? void 0 : _a2.id);
11025
+ if (String(currentId) === String(targetId)) {
11026
+ return { ...treeNode, children: [] };
11027
+ }
11028
+ if (treeNode.children && treeNode.children.length > 0) {
11029
+ for (let child of treeNode.children) {
11030
+ const prunedChild = pruneTreeToPath(child, targetId);
11031
+ if (prunedChild) {
11032
+ return { ...treeNode, children: [prunedChild] };
11033
+ }
11034
+ }
11035
+ }
11036
+ return null;
11037
+ };
11038
+ const pruned = pruneTreeToPath(fullTree, targetNodeId);
11039
+ if (pruned) fullTree = pruned;
11040
+ }
10846
11041
  const absId = ancestryObject.ancestry_id + "_abs";
10847
11042
  handleClearAncestryVisuals(absId);
10848
11043
  const colorHex = 9133302;
@@ -10884,13 +11079,13 @@ function XViewScene({
10884
11079
  if (action === "open") {
10885
11080
  let currentPtr = fullTree;
10886
11081
  for (const step of branchStack) {
10887
- const found = findNodePath2(currentPtr, step.nodeId);
11082
+ const found = findNodePath3(currentPtr, step.nodeId);
10888
11083
  if (found && found.node.parallel_branches) {
10889
11084
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
10890
11085
  if (branch) currentPtr = branch.tree;
10891
11086
  }
10892
11087
  }
10893
- const foundTarget = findNodePath2(currentPtr, nodeId);
11088
+ const foundTarget = findNodePath3(currentPtr, nodeId);
10894
11089
  if (foundTarget && foundTarget.node && foundTarget.node.parallel_branches && foundTarget.node.parallel_branches.length > 0) {
10895
11090
  const branchToOpen = foundTarget.node.parallel_branches.find((b) => (b.direction || "right") === direction);
10896
11091
  if (!branchToOpen) return;
@@ -10957,7 +11152,7 @@ function XViewScene({
10957
11152
  if (newStack.length > 0) {
10958
11153
  let ptr = fullTree;
10959
11154
  for (const step of newStack) {
10960
- const found = findNodePath2(ptr, step.nodeId);
11155
+ const found = findNodePath3(ptr, step.nodeId);
10961
11156
  if (found && found.node.parallel_branches) {
10962
11157
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
10963
11158
  if (branch) {
@@ -11098,7 +11293,7 @@ function XViewScene({
11098
11293
  let currentMeta = ancestry;
11099
11294
  let currentDirection = null;
11100
11295
  for (const step of branchStack) {
11101
- const found = findNodePath2(currentPtr, step.nodeId);
11296
+ const found = findNodePath3(currentPtr, step.nodeId);
11102
11297
  if (found && found.node.parallel_branches) {
11103
11298
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
11104
11299
  if (branch) {
@@ -11118,6 +11313,18 @@ function XViewScene({
11118
11313
  // <--- ADICIONADO
11119
11314
  };
11120
11315
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
11316
+ const readModeAbstractionTree = (0, import_react23.useMemo)(() => {
11317
+ if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
11318
+ return null;
11319
+ }
11320
+ const allNodes = Object.values(parentDataRef.current || {}).flatMap((f) => f.nodes || []);
11321
+ const allAncestries = ancestryDataRef.current || [];
11322
+ return buildFullAncestryTree(
11323
+ readingMode.ancestry.abstraction_tree,
11324
+ allNodes,
11325
+ allAncestries
11326
+ );
11327
+ }, [readingMode.isActive, readingMode.ancestry, buildFullAncestryTree, sceneVersion]);
11121
11328
  const handleStartReadingAncestry = (0, import_react23.useCallback)(
11122
11329
  async (ancestryObject) => {
11123
11330
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
@@ -11158,7 +11365,7 @@ function XViewScene({
11158
11365
  );
11159
11366
  let currentPtr = fullTree;
11160
11367
  for (const step of branchStack) {
11161
- const found = findNodePath2(currentPtr, step.nodeId);
11368
+ const found = findNodePath3(currentPtr, step.nodeId);
11162
11369
  if (found && found.node && found.node.parallel_branches) {
11163
11370
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
11164
11371
  if (branch) {
@@ -11826,7 +12033,9 @@ function XViewScene({
11826
12033
  activeNodeBranches,
11827
12034
  backNavigationInfo,
11828
12035
  onImageClick: (url, name) => handleOpenImageViewer([{ name: name || "Imagem", value: url }], 0),
11829
- userRole: userPermissionRole
12036
+ userRole: userPermissionRole,
12037
+ abstractionTree: readModeAbstractionTree,
12038
+ onRenderAbstractionTree: (targetId) => handleRenderAbstractionTree(readingMode.ancestry, targetId)
11830
12039
  }
11831
12040
  )
11832
12041
  ),
@@ -11834,6 +12043,7 @@ function XViewScene({
11834
12043
  CreateAncestryPanel,
11835
12044
  {
11836
12045
  ancestryMode,
12046
+ setAncestryMode,
11837
12047
  onSelectParent: handleSelectAncestryParent,
11838
12048
  onRemoveNode: handleRemoveFromAncestry,
11839
12049
  onSave: handleSaveAncestry,
@@ -11853,7 +12063,7 @@ function XViewScene({
11853
12063
  onClearAncestryVisuals: handleClearAncestryVisuals,
11854
12064
  onUploadFile: upload_file_action,
11855
12065
  onOpenImageViewer: handleOpenImageViewer,
11856
- onRenderAbstractionTree: (data) => handleRenderAbstractionTree(data)
12066
+ onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
11857
12067
  }
11858
12068
  ),
11859
12069
  editingAncestryRel.visible && /* @__PURE__ */ import_react23.default.createElement(