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

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 +376 -154
  2. package/dist/index.mjs +381 -157
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -122,6 +122,7 @@ function ContextMenu({
122
122
  onRenderAncestry,
123
123
  onEditAncestry,
124
124
  onDeleteAncestry,
125
+ onFocusNode,
125
126
  onClose
126
127
  }) {
127
128
  var _a, _b;
@@ -271,7 +272,10 @@ function ContextMenu({
271
272
  const canCreateVersion = ability.can("create", "Versioning");
272
273
  const canReadVersion = ability.can("read", "Versioning");
273
274
  const shouldShowVersioningBtn = canCreateVersion || canReadVersion && hasVersions;
274
- return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ import_react.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex flex-col gap-1" }, ability.can("create", "Connection") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Conectar")), ability.can("create", "Node") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar Ancestralidade" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M10 20.5c.5-.5.8-1.2.8-2s-.3-1.5-.8-2c-.5-.5-1.2-.8-2-.8s-1.5.3-2 .8c-.5.5-.8 1.2-.8 2s.3 1.5.8 2c.5.5 1.2.8 2 .8s1.5-.3 2-.8Z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 3.5c.5.5.8 1.2.8 2s-.3 1.5-.8 2c-.5-.5-1.2-.8-2 .8s1.5.3-2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("line", { x1: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ import_react.default.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), ability.can("dismiss", "Node") && /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onDismissNode == null ? void 0 : onDismissNode(data.nodeData), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Dismiss")), /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onDismissOtherNodes == null ? void 0 : onDismissOtherNodes(data.nodeData), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Dismiss other nodes"))), ability.can("delete", "Node") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onDeleteNode == null ? void 0 : onDeleteNode(data.nodeData), className: deleteButtonClass, title: "Excluir Node" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Excluir Node"))));
275
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ import_react.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => {
276
+ onFocusNode == null ? void 0 : onFocusNode(data.nodeData);
277
+ onClose();
278
+ }, className: baseButtonClass, title: "Focar na c\xE2mera" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "3" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Focar neste Node")), ability.can("create", "Connection") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Conectar")), ability.can("create", "Node") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar Ancestralidade" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M10 20.5c.5-.5.8-1.2.8-2s-.3-1.5-.8-2c-.5-.5-1.2-.8-2-.8s-1.5.3-2 .8c-.5.5-.8 1.2-.8 2s.3 1.5.8 2c.5.5 1.2.8 2 .8s1.5-.3 2-.8Z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 3.5c.5.5.8 1.2.8 2s-.3 1.5-.8 2c-.5-.5-1.2-.8-2 .8s1.5.3-2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("line", { x1: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ import_react.default.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), ability.can("dismiss", "Node") && /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onDismissNode == null ? void 0 : onDismissNode(data.nodeData), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Dismiss")), /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onDismissOtherNodes == null ? void 0 : onDismissOtherNodes(data.nodeData), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Dismiss other nodes"))), ability.can("delete", "Node") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onDeleteNode == null ? void 0 : onDeleteNode(data.nodeData), className: deleteButtonClass, title: "Excluir Node" }, /* @__PURE__ */ import_react.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" }, /* @__PURE__ */ import_react.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Excluir Node"))));
275
279
  };
276
280
  const renderVersionSubMenuView = () => {
277
281
  const group = versionSubMenu;
@@ -2698,7 +2702,10 @@ var IGNORED_KEYS = [
2698
2702
  "isAddingNodes",
2699
2703
  "ancestryDescriptionSections",
2700
2704
  "direction",
2701
- "is_private"
2705
+ "is_private",
2706
+ "abstraction_tree",
2707
+ "selectedAbstractionParentId",
2708
+ "isAddingAbstractionNodes"
2702
2709
  ];
2703
2710
  function extractCustomPropsFromNode(node) {
2704
2711
  const customPropTypes = node._customPropTypes || {};
@@ -4464,6 +4471,65 @@ function DescriptionDisplay({
4464
4471
  // src/components/DescriptionReadModePanel.jsx
4465
4472
  var import_react7 = __toESM(require("react"));
4466
4473
  var import_fi6 = require("react-icons/fi");
4474
+ var findNodePath = (tree, targetNodeId, currentPath = []) => {
4475
+ var _a;
4476
+ if (!tree) return null;
4477
+ const currentNodeId = tree.is_section ? tree.section_id : String((_a = tree.node) == null ? void 0 : _a.id);
4478
+ if (String(currentNodeId) === String(targetNodeId)) {
4479
+ return { node: tree, path: currentPath };
4480
+ }
4481
+ if (tree.children) {
4482
+ for (let i = 0; i < tree.children.length; i++) {
4483
+ const res = findNodePath(tree.children[i], targetNodeId, [...currentPath, i]);
4484
+ if (res) return res;
4485
+ }
4486
+ }
4487
+ return null;
4488
+ };
4489
+ var ReadOnlyNodeItem = ({ nodeData, onViewSelect, highlightedPathIds = [], targetRenderNodeId, level = 0, isLast = false }) => {
4490
+ var _a, _b;
4491
+ const itemId = nodeData.is_section ? nodeData.id : (_a = nodeData.node) == null ? void 0 : _a.id;
4492
+ const itemName = nodeData.is_section ? nodeData.name : (_b = nodeData.node) == null ? void 0 : _b.name;
4493
+ const isTargetViewNode = String(targetRenderNodeId) === String(itemId);
4494
+ const isHighlightedPath = highlightedPathIds.includes(String(itemId));
4495
+ const hasChildren = nodeData.children && nodeData.children.length > 0;
4496
+ let itemBgClass = "bg-slate-900/50 hover:bg-slate-800/80";
4497
+ let textColorClass = "text-slate-200";
4498
+ if (nodeData.is_section) {
4499
+ itemBgClass = "bg-purple-900/20 border border-purple-500/30 hover:bg-purple-900/40";
4500
+ textColorClass = "text-purple-300";
4501
+ } else {
4502
+ if (isTargetViewNode) {
4503
+ itemBgClass = "bg-fuchsia-600/40 ring-2 ring-fuchsia-400 shadow-[0_0_15px_rgba(217,70,239,0.3)]";
4504
+ textColorClass = "text-white font-bold";
4505
+ } else if (isHighlightedPath) {
4506
+ itemBgClass = "bg-fuchsia-900/30 border border-fuchsia-500/40";
4507
+ textColorClass = "text-fuchsia-200 font-semibold";
4508
+ }
4509
+ }
4510
+ 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(
4511
+ "div",
4512
+ {
4513
+ onClick: (e) => {
4514
+ e.stopPropagation();
4515
+ if (onViewSelect) onViewSelect(itemId);
4516
+ },
4517
+ className: `flex items-center justify-between gap-2 px-3 h-9 rounded-md transition-all duration-150 border border-transparent cursor-pointer ${itemBgClass}`
4518
+ },
4519
+ /* @__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)
4520
+ ), 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(
4521
+ ReadOnlyNodeItem,
4522
+ {
4523
+ key: `${child.is_section ? child.id : child.node.id}-${index}`,
4524
+ nodeData: child,
4525
+ onViewSelect,
4526
+ highlightedPathIds,
4527
+ targetRenderNodeId,
4528
+ level: level + 1,
4529
+ isLast: index === nodeData.children.length - 1
4530
+ }
4531
+ ))));
4532
+ };
4467
4533
  function DescriptionReadModePanel({
4468
4534
  title,
4469
4535
  description,
@@ -4485,14 +4551,40 @@ function DescriptionReadModePanel({
4485
4551
  backNavigationInfo,
4486
4552
  customProperties = [],
4487
4553
  onImageClick,
4488
- userRole
4489
- // <--- NOVA PROP: Recebendo a role do usuário
4554
+ userRole,
4555
+ // --- NOVAS PROPS PARA ABSTRAÇÃO ---
4556
+ abstractionTree = null,
4557
+ onRenderAbstractionTree = null
4490
4558
  }) {
4491
4559
  const [showProperties, setShowProperties] = (0, import_react7.useState)(false);
4560
+ const [showAbstraction, setShowAbstraction] = (0, import_react7.useState)(false);
4561
+ const [targetRenderNodeId, setTargetRenderNodeId] = (0, import_react7.useState)(null);
4492
4562
  const swallow = (e) => e.stopPropagation();
4493
4563
  const hasCustomProps = customProperties && customProperties.length > 0;
4564
+ const hasAbstraction = Boolean(abstractionTree && (abstractionTree.node || abstractionTree.children && abstractionTree.children.length > 0));
4494
4565
  const ability = (0, import_react7.useMemo)(() => defineAbilityFor(userRole), [userRole]);
4495
4566
  const canEditAncestry = ability.can("update", "Ancestry");
4567
+ const highlightedPathIds = (0, import_react7.useMemo)(() => {
4568
+ var _a, _b;
4569
+ if (!targetRenderNodeId || !abstractionTree) return [];
4570
+ const found = findNodePath(abstractionTree, targetRenderNodeId);
4571
+ if (!found) return [];
4572
+ let current = abstractionTree;
4573
+ const ids = [current.is_section ? current.section_id : String((_a = current.node) == null ? void 0 : _a.id)];
4574
+ for (let i of found.path) {
4575
+ current = current.children[i];
4576
+ ids.push(current.is_section ? current.section_id : String((_b = current.node) == null ? void 0 : _b.id));
4577
+ }
4578
+ return ids;
4579
+ }, [targetRenderNodeId, abstractionTree]);
4580
+ const handleToggleProperties = () => {
4581
+ setShowProperties(!showProperties);
4582
+ if (!showProperties) setShowAbstraction(false);
4583
+ };
4584
+ const handleToggleAbstraction = () => {
4585
+ setShowAbstraction(!showAbstraction);
4586
+ if (!showAbstraction) setShowProperties(false);
4587
+ };
4496
4588
  const leftAction = (0, import_react7.useMemo)(() => {
4497
4589
  if (activeNodeBranches == null ? void 0 : activeNodeBranches.left) {
4498
4590
  return {
@@ -4537,21 +4629,38 @@ function DescriptionReadModePanel({
4537
4629
  /* @__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
4630
  "button",
4539
4631
  {
4540
- onClick: onBack,
4632
+ onClick: () => {
4633
+ if (showAbstraction) {
4634
+ setShowAbstraction(false);
4635
+ } else if (showProperties) {
4636
+ setShowProperties(false);
4637
+ } else if (onBack) {
4638
+ onBack();
4639
+ }
4640
+ },
4541
4641
  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
4642
  title: "Voltar"
4543
4643
  },
4544
4644
  /* @__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(
4645
+ ), /* @__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
4646
  "button",
4547
4647
  {
4548
- onClick: () => setShowProperties(!showProperties),
4648
+ onClick: handleToggleProperties,
4549
4649
  className: `relative w-9 h-9 grid place-content-center rounded-lg border transition-colors
4550
4650
  ${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
4651
  title: showProperties ? "Ver Descri\xE7\xE3o" : "Ver Propriedades Adicionais"
4552
4652
  },
4553
4653
  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" })
4654
+ !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" })
4655
+ ), hasAbstraction && /* @__PURE__ */ import_react7.default.createElement(
4656
+ "button",
4657
+ {
4658
+ onClick: handleToggleAbstraction,
4659
+ className: `relative w-9 h-9 grid place-content-center rounded-lg border transition-colors
4660
+ ${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"}`,
4661
+ title: showAbstraction ? "Voltar \xE0 Descri\xE7\xE3o" : "Ver Tree de Abstra\xE7\xE3o"
4662
+ },
4663
+ /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiGitBranch, { size: 16 })
4555
4664
  ), onRenderFullAncestry && /* @__PURE__ */ import_react7.default.createElement(
4556
4665
  "button",
4557
4666
  {
@@ -4565,7 +4674,7 @@ function DescriptionReadModePanel({
4565
4674
  {
4566
4675
  onClick: onEdit,
4567
4676
  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"
4677
+ title: "Editar Descri\xE7\xE3o / Estrutura"
4569
4678
  },
4570
4679
  /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiEdit2, { size: 16 })
4571
4680
  ), /* @__PURE__ */ import_react7.default.createElement(
@@ -4577,7 +4686,40 @@ function DescriptionReadModePanel({
4577
4686
  },
4578
4687
  "\xD7"
4579
4688
  ))),
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(
4689
+ /* @__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(
4690
+ "button",
4691
+ {
4692
+ onClick: (e) => {
4693
+ e.stopPropagation();
4694
+ onRenderAbstractionTree(targetRenderNodeId);
4695
+ },
4696
+ 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",
4697
+ title: "Renderiza no 3D apenas o caminho at\xE9 o Node selecionado"
4698
+ },
4699
+ /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiLayers, { size: 14 }),
4700
+ " Renderizar Caminho"
4701
+ ), onRenderAbstractionTree && /* @__PURE__ */ import_react7.default.createElement(
4702
+ "button",
4703
+ {
4704
+ onClick: (e) => {
4705
+ e.stopPropagation();
4706
+ setTargetRenderNodeId(null);
4707
+ onRenderAbstractionTree(null);
4708
+ },
4709
+ 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",
4710
+ title: "Renderiza a Abstraction Tree inteira verticalmente"
4711
+ },
4712
+ /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiLayers, { size: 14 }),
4713
+ " Renderizar Completa"
4714
+ ))), /* @__PURE__ */ import_react7.default.createElement("div", { className: "bg-slate-900/60 border border-white/10 rounded-lg p-4" }, /* @__PURE__ */ import_react7.default.createElement(
4715
+ ReadOnlyNodeItem,
4716
+ {
4717
+ nodeData: abstractionTree,
4718
+ onViewSelect: setTargetRenderNodeId,
4719
+ highlightedPathIds,
4720
+ targetRenderNodeId
4721
+ }
4722
+ ))) : 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
4723
  CustomPropertyDisplay,
4582
4724
  {
4583
4725
  key: prop.id,
@@ -4606,7 +4748,7 @@ function DescriptionReadModePanel({
4606
4748
  onImageClick
4607
4749
  }
4608
4750
  )),
4609
- leftAction && /* @__PURE__ */ import_react7.default.createElement(
4751
+ leftAction && !showAbstraction && !showProperties && /* @__PURE__ */ import_react7.default.createElement(
4610
4752
  "button",
4611
4753
  {
4612
4754
  onClick: leftAction.onClick,
@@ -4618,7 +4760,7 @@ function DescriptionReadModePanel({
4618
4760
  ${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
4761
  ` }, leftAction.type === "branch" ? /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiChevronLeft, { size: 20 }) : /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiCornerUpLeft, { size: 20 }))
4620
4762
  ),
4621
- rightAction && /* @__PURE__ */ import_react7.default.createElement(
4763
+ rightAction && !showAbstraction && !showProperties && /* @__PURE__ */ import_react7.default.createElement(
4622
4764
  "button",
4623
4765
  {
4624
4766
  onClick: rightAction.onClick,
@@ -4871,7 +5013,7 @@ function AncestryPickerModal({
4871
5013
  }
4872
5014
 
4873
5015
  // src/components/CreateAncestryPanel.jsx
4874
- var findNodePath = (tree, targetNodeId, currentPath = []) => {
5016
+ var findNodePath2 = (tree, targetNodeId, currentPath = []) => {
4875
5017
  var _a;
4876
5018
  if (!tree) return null;
4877
5019
  const currentNodeId = tree.is_section ? tree.section_id : String((_a = tree.node) == null ? void 0 : _a.id);
@@ -4880,22 +5022,41 @@ var findNodePath = (tree, targetNodeId, currentPath = []) => {
4880
5022
  }
4881
5023
  if (tree.children) {
4882
5024
  for (let i = 0; i < tree.children.length; i++) {
4883
- const res = findNodePath(tree.children[i], targetNodeId, [...currentPath, i]);
5025
+ const res = findNodePath2(tree.children[i], targetNodeId, [...currentPath, i]);
4884
5026
  if (res) return res;
4885
5027
  }
4886
5028
  }
4887
5029
  return null;
4888
5030
  };
4889
- var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, onMoveNode, selectedParentId, level = 0, isLast = false, path = [], isEditable }) => {
5031
+ var NodeItem = ({ nodeData, onSelectParent, onViewSelect, highlightedPathIds = [], targetRenderNodeId, onRemoveNode, onEditRelationship, onMoveNode, selectedParentId, level = 0, isLast = false, path = [], isEditable }) => {
4890
5032
  var _a, _b;
4891
5033
  const itemId = nodeData.is_section ? nodeData.id : (_a = nodeData.node) == null ? void 0 : _a.id;
4892
5034
  const itemName = nodeData.is_section ? nodeData.name : (_b = nodeData.node) == null ? void 0 : _b.name;
4893
5035
  const [isDragOver, setIsDragOver] = (0, import_react10.useState)(false);
4894
- const isSelected = String(selectedParentId) === String(itemId);
5036
+ const isSelectedParent = String(selectedParentId) === String(itemId);
5037
+ const isTargetViewNode = String(targetRenderNodeId) === String(itemId);
5038
+ const isHighlightedPath = highlightedPathIds.includes(String(itemId));
4895
5039
  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";
5040
+ let itemBgClass = "bg-slate-900/50 hover:bg-slate-800/80";
5041
+ let textColorClass = "text-slate-200";
5042
+ if (nodeData.is_section) {
5043
+ 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";
5044
+ textColorClass = isSelectedParent ? "text-indigo-200 font-bold" : "text-indigo-300";
5045
+ } else {
5046
+ if (isSelectedParent) {
5047
+ itemBgClass = "bg-purple-500/30 ring-2 ring-purple-400";
5048
+ textColorClass = "text-purple-200 font-semibold";
5049
+ } else if (isTargetViewNode) {
5050
+ itemBgClass = "bg-fuchsia-600/40 ring-2 ring-fuchsia-400 shadow-[0_0_15px_rgba(217,70,239,0.3)]";
5051
+ textColorClass = "text-white font-bold";
5052
+ } else if (isHighlightedPath) {
5053
+ itemBgClass = "bg-fuchsia-900/30 border border-fuchsia-500/40";
5054
+ textColorClass = "text-fuchsia-200 font-semibold";
5055
+ } else {
5056
+ textColorClass = "text-slate-200";
5057
+ }
5058
+ }
5059
+ const cursorClass = isEditable ? "cursor-grab active:cursor-grabbing" : "cursor-pointer";
4899
5060
  const handleDragStart = (e) => {
4900
5061
  if (!isEditable) {
4901
5062
  e.preventDefault();
@@ -4925,23 +5086,9 @@ var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, on
4925
5086
  if (!isEditable) return;
4926
5087
  const sourceId = e.dataTransfer.getData("nodeId");
4927
5088
  if (sourceId === String(itemId)) return;
4928
- if (onMoveNode) {
4929
- onMoveNode(sourceId, itemId);
4930
- }
5089
+ if (onMoveNode) onMoveNode(sourceId, itemId);
4931
5090
  };
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(
5091
+ 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
5092
  "div",
4946
5093
  {
4947
5094
  draggable: isEditable,
@@ -4949,63 +5096,35 @@ var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, on
4949
5096
  onDragOver: handleDragOver,
4950
5097
  onDragLeave: handleDragLeave,
4951
5098
  onDrop: handleDrop,
4952
- onClick: () => {
5099
+ onClick: (e) => {
5100
+ e.stopPropagation();
4953
5101
  if (isEditable) {
4954
5102
  onSelectParent(itemId);
5103
+ } else if (onViewSelect) {
5104
+ onViewSelect(itemId);
4955
5105
  }
4956
5106
  },
4957
5107
  className: `flex items-center justify-between gap-2 px-3 h-9 rounded-md transition-all duration-150 border
4958
5108
  ${isDragOver ? "border-dashed border-yellow-400 bg-yellow-400/10" : "border-transparent"}
4959
5109
  ${itemBgClass} ${cursorClass}`
4960
5110
  },
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
- ))
5111
+ /* @__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),
5112
+ 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) => {
5113
+ e.stopPropagation();
5114
+ onEditRelationship(path, nodeData.relationship || {});
5115
+ }, 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) => {
5116
+ e.stopPropagation();
5117
+ onRemoveNode(path);
5118
+ }, 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
5119
  ), 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
5120
  NodeItem,
5005
5121
  {
5006
5122
  key: `${child.is_section ? child.id : child.node.id}-${index}`,
5007
5123
  nodeData: child,
5008
5124
  onSelectParent,
5125
+ onViewSelect,
5126
+ highlightedPathIds,
5127
+ targetRenderNodeId,
5009
5128
  onRemoveNode,
5010
5129
  onEditRelationship,
5011
5130
  onMoveNode,
@@ -5020,11 +5139,8 @@ var NodeItem = ({ nodeData, onSelectParent, onRemoveNode, onEditRelationship, on
5020
5139
  function CreateAncestryPanel({
5021
5140
  ancestryMode,
5022
5141
  setAncestryMode,
5023
- // <--- Nova prop necessária para as novas funções manipuladoras
5024
5142
  onSelectParent,
5025
- // Mantido para compatibilidade, mas as novas funções usam setAncestryMode
5026
5143
  onRemoveNode,
5027
- // Mantido para compatibilidade
5028
5144
  onSave,
5029
5145
  onClose,
5030
5146
  onEditRelationship,
@@ -5035,14 +5151,12 @@ function CreateAncestryPanel({
5035
5151
  onUpdateTree,
5036
5152
  onAncestrySectionChange,
5037
5153
  onToggleAddNodes,
5038
- // Mantido para compatibilidade
5039
5154
  onRenderFullAncestry,
5040
5155
  onHighlightNode,
5041
5156
  onClearAncestryVisuals,
5042
5157
  onUploadFile,
5043
5158
  onOpenImageViewer,
5044
5159
  onRenderAbstractionTree
5045
- // <--- Nova prop recebida
5046
5160
  }) {
5047
5161
  const {
5048
5162
  tree: rootTree,
@@ -5059,6 +5173,20 @@ function CreateAncestryPanel({
5059
5173
  const [customProps, setCustomProps] = (0, import_react10.useState)([]);
5060
5174
  const propsEndRef = (0, import_react10.useRef)(null);
5061
5175
  const [branchStack, setBranchStack] = (0, import_react10.useState)([]);
5176
+ const [targetRenderNodeId, setTargetRenderNodeId] = (0, import_react10.useState)(null);
5177
+ const highlightedPathIds = (0, import_react10.useMemo)(() => {
5178
+ var _a, _b;
5179
+ if (!targetRenderNodeId || !ancestryMode.abstraction_tree) return [];
5180
+ const found = findNodePath2(ancestryMode.abstraction_tree, targetRenderNodeId);
5181
+ if (!found) return [];
5182
+ let current = ancestryMode.abstraction_tree;
5183
+ const ids = [current.is_section ? current.section_id : String((_a = current.node) == null ? void 0 : _a.id)];
5184
+ for (let i of found.path) {
5185
+ current = current.children[i];
5186
+ ids.push(current.is_section ? current.section_id : String((_b = current.node) == null ? void 0 : _b.id));
5187
+ }
5188
+ return ids;
5189
+ }, [targetRenderNodeId, ancestryMode.abstraction_tree]);
5062
5190
  const [targetScrollSectionId, setTargetScrollSectionId] = (0, import_react10.useState)(null);
5063
5191
  const [internalHighlightedNodeId, setInternalHighlightedNodeId] = (0, import_react10.useState)(null);
5064
5192
  const [ancestryName, setAncestryName] = (0, import_react10.useState)(initialName);
@@ -5082,6 +5210,9 @@ function CreateAncestryPanel({
5082
5210
  setAncestryMode((prev) => isAbstraction ? { ...prev, selectedAbstractionParentId: nodeId } : { ...prev, selectedParentId: nodeId });
5083
5211
  };
5084
5212
  const handleToggleAddMode = (isAbstraction = false) => {
5213
+ if (isAbstraction && !ancestryMode.isAddingAbstractionNodes) {
5214
+ setTargetRenderNodeId(null);
5215
+ }
5085
5216
  setAncestryMode((prev) => isAbstraction ? { ...prev, isAddingAbstractionNodes: !prev.isAddingAbstractionNodes } : { ...prev, isAddingNodes: !prev.isAddingNodes });
5086
5217
  };
5087
5218
  const handleRemoveNode = (0, import_react10.useCallback)((pathToRemove, isAbstraction = false) => {
@@ -5113,7 +5244,7 @@ function CreateAncestryPanel({
5113
5244
  if (!isAbstraction && branchStack.length > 0) {
5114
5245
  let ptr = rootTreeClone;
5115
5246
  for (const step of branchStack) {
5116
- const found = findNodePath(ptr, step.nodeId);
5247
+ const found = findNodePath2(ptr, step.nodeId);
5117
5248
  if (found && found.node.parallel_branches) {
5118
5249
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5119
5250
  if (branch) ptr = branch.tree;
@@ -5163,14 +5294,15 @@ function CreateAncestryPanel({
5163
5294
  }
5164
5295
  }
5165
5296
  };
5166
- const takeSnapshot = (tree, name, desc, sections, customProps2, isPrivateVal) => {
5297
+ const takeSnapshot = (tree, name, desc, sections, customProps2, isPrivateVal, abstractionTree = null) => {
5167
5298
  return {
5168
5299
  tree: JSON.stringify(tree),
5169
5300
  name,
5170
5301
  description: desc || "",
5171
5302
  sections: JSON.stringify(sections || []),
5172
5303
  customProps: JSON.stringify(customProps2 || []),
5173
- isPrivate: isPrivateVal
5304
+ isPrivate: isPrivateVal,
5305
+ abstractionTree: JSON.stringify(abstractionTree)
5174
5306
  };
5175
5307
  };
5176
5308
  const getCurrentContext = () => {
@@ -5189,7 +5321,7 @@ function CreateAncestryPanel({
5189
5321
  let currentBranch = null;
5190
5322
  let currentDirection = null;
5191
5323
  for (const step of branchStack) {
5192
- const found = findNodePath(currentTreePtr, step.nodeId);
5324
+ const found = findNodePath2(currentTreePtr, step.nodeId);
5193
5325
  if (!found || !found.node.parallel_branches) return null;
5194
5326
  currentBranch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5195
5327
  if (!currentBranch) return null;
@@ -5271,7 +5403,7 @@ function CreateAncestryPanel({
5271
5403
  let ptr = ancestryMode.tree;
5272
5404
  let foundBranch = null;
5273
5405
  for (const step of branchStack) {
5274
- const found = findNodePath(ptr, step.nodeId);
5406
+ const found = findNodePath2(ptr, step.nodeId);
5275
5407
  if (found && found.node.parallel_branches) {
5276
5408
  foundBranch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5277
5409
  if (foundBranch) ptr = foundBranch.tree;
@@ -5304,7 +5436,8 @@ function CreateAncestryPanel({
5304
5436
  ancestryMode.ancestryDescription,
5305
5437
  ancestryMode.ancestryDescriptionSections,
5306
5438
  extractedProps,
5307
- ancestryMode.is_private
5439
+ ancestryMode.is_private,
5440
+ ancestryMode.abstraction_tree
5308
5441
  ));
5309
5442
  } else if (ctx) {
5310
5443
  setLastSavedSnapshot(takeSnapshot(
@@ -5313,7 +5446,8 @@ function CreateAncestryPanel({
5313
5446
  ctx.description,
5314
5447
  ctx.sections,
5315
5448
  extractedProps,
5316
- isPrivate
5449
+ isPrivate,
5450
+ ancestryMode.abstraction_tree
5317
5451
  ));
5318
5452
  }
5319
5453
  }, [branchStack, ancestryMode]);
@@ -5328,7 +5462,7 @@ function CreateAncestryPanel({
5328
5462
  let ptr = rootTreeClone;
5329
5463
  let targetBranch = null;
5330
5464
  for (const step of branchStack) {
5331
- const found = findNodePath(ptr, step.nodeId);
5465
+ const found = findNodePath2(ptr, step.nodeId);
5332
5466
  if (found && found.node.parallel_branches) {
5333
5467
  targetBranch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5334
5468
  if (targetBranch) ptr = targetBranch.tree;
@@ -5356,7 +5490,7 @@ function CreateAncestryPanel({
5356
5490
  rootTreeClone,
5357
5491
  rootExtras
5358
5492
  );
5359
- setLastSavedSnapshot(takeSnapshot(rootTreeClone, ancestryName, description, processedSections, [], isPrivate));
5493
+ setLastSavedSnapshot(takeSnapshot(rootTreeClone, ancestryName, description, processedSections, [], isPrivate, ancestryMode.abstraction_tree));
5360
5494
  if (onRenderFullAncestry) {
5361
5495
  const fullTreePayload = {
5362
5496
  ancestry_id: ancestryMode.currentAncestryId || "temp_root",
@@ -5386,14 +5520,14 @@ function CreateAncestryPanel({
5386
5520
  let ptr = rootTreeClone;
5387
5521
  for (let i = 0; i < branchStack.length - 1; i++) {
5388
5522
  const step = branchStack[i];
5389
- const found = findNodePath(ptr, step.nodeId);
5523
+ const found = findNodePath2(ptr, step.nodeId);
5390
5524
  if (found && found.node.parallel_branches) {
5391
5525
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5392
5526
  if (branch) ptr = branch.tree;
5393
5527
  }
5394
5528
  }
5395
5529
  const currentStep = branchStack[branchStack.length - 1];
5396
- const foundParentPath = findNodePath(ptr, currentStep.nodeId);
5530
+ const foundParentPath = findNodePath2(ptr, currentStep.nodeId);
5397
5531
  if (foundParentPath && foundParentPath.node && foundParentPath.node.parallel_branches) {
5398
5532
  const branchIndex = foundParentPath.node.parallel_branches.findIndex((b) => b.id === currentStep.branchId);
5399
5533
  if (branchIndex !== -1) {
@@ -5417,7 +5551,8 @@ function CreateAncestryPanel({
5417
5551
  ancestryMode.ancestryDescription,
5418
5552
  ancestryMode.ancestryDescriptionSections,
5419
5553
  currentRootProps,
5420
- isPrivate
5554
+ isPrivate,
5555
+ ancestryMode.abstraction_tree
5421
5556
  ));
5422
5557
  if (onClearAncestryVisuals) {
5423
5558
  onClearAncestryVisuals(currentStep.branchId);
@@ -5436,7 +5571,7 @@ function CreateAncestryPanel({
5436
5571
  const actions = { left: null, right: null };
5437
5572
  const isInBranch = branchStack.length > 0;
5438
5573
  if (internalHighlightedNodeId) {
5439
- const found = findNodePath(activeTree, internalHighlightedNodeId);
5574
+ const found = findNodePath2(activeTree, internalHighlightedNodeId);
5440
5575
  if (found && found.node) {
5441
5576
  const branches = found.node.parallel_branches || [];
5442
5577
  const leftBranch = branches.find((b) => (b.direction || "right") === "left");
@@ -5488,7 +5623,7 @@ function CreateAncestryPanel({
5488
5623
  if (branchStack.length > 0) {
5489
5624
  let ptr = rootTreeClone;
5490
5625
  for (const step of branchStack) {
5491
- const found = findNodePath(ptr, step.nodeId);
5626
+ const found = findNodePath2(ptr, step.nodeId);
5492
5627
  if (found && found.node.parallel_branches) {
5493
5628
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5494
5629
  if (branch) ptr = branch.tree;
@@ -5606,6 +5741,11 @@ function CreateAncestryPanel({
5606
5741
  const sectionsChanged = JSON.stringify(existingSections) !== lastSavedSnapshot.sections;
5607
5742
  const propsChanged = JSON.stringify(customProps) !== lastSavedSnapshot.customProps;
5608
5743
  const privateChanged = isPrivate !== lastSavedSnapshot.isPrivate;
5744
+ let abstractionTreeChanged = false;
5745
+ if (branchStack.length === 0) {
5746
+ const currentAbsTreeStr = JSON.stringify(ancestryMode.abstraction_tree);
5747
+ abstractionTreeChanged = currentAbsTreeStr !== lastSavedSnapshot.abstractionTree;
5748
+ }
5609
5749
  return treeChanged || nameChanged || descChanged || sectionsChanged || propsChanged || privateChanged;
5610
5750
  }, [
5611
5751
  ancestryName,
@@ -5615,6 +5755,7 @@ function CreateAncestryPanel({
5615
5755
  branchStack,
5616
5756
  lastSavedSnapshot,
5617
5757
  ancestryMode.tree,
5758
+ ancestryMode.abstraction_tree,
5618
5759
  customProps,
5619
5760
  isPrivate
5620
5761
  ]);
@@ -5628,7 +5769,7 @@ function CreateAncestryPanel({
5628
5769
  let parentTreePtr = rootTree;
5629
5770
  let parentBranch = null;
5630
5771
  for (const step of parentStack) {
5631
- const found = findNodePath(parentTreePtr, step.nodeId);
5772
+ const found = findNodePath2(parentTreePtr, step.nodeId);
5632
5773
  if (found && found.node.parallel_branches) {
5633
5774
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5634
5775
  if (branch) {
@@ -5706,7 +5847,7 @@ function CreateAncestryPanel({
5706
5847
  const rootTreeClone = JSON.parse(JSON.stringify(ancestryMode.tree));
5707
5848
  let ptr = rootTreeClone;
5708
5849
  for (const step of branchStack) {
5709
- const foundParent = findNodePath(ptr, step.nodeId);
5850
+ const foundParent = findNodePath2(ptr, step.nodeId);
5710
5851
  if (foundParent && foundParent.node && foundParent.node.parallel_branches) {
5711
5852
  const existingBranch = foundParent.node.parallel_branches.find((b) => b.id === step.branchId);
5712
5853
  if (existingBranch) {
@@ -5714,7 +5855,7 @@ function CreateAncestryPanel({
5714
5855
  }
5715
5856
  }
5716
5857
  }
5717
- const found = findNodePath(ptr, nodeId);
5858
+ const found = findNodePath2(ptr, nodeId);
5718
5859
  if (!found) {
5719
5860
  console.error("Node alvo n\xE3o encontrado no contexto atual.");
5720
5861
  return;
@@ -5827,7 +5968,7 @@ function CreateAncestryPanel({
5827
5968
  let ptr = updatedRootTree;
5828
5969
  let targetBranch = null;
5829
5970
  for (const step of branchStack) {
5830
- const found = findNodePath(ptr, step.nodeId);
5971
+ const found = findNodePath2(ptr, step.nodeId);
5831
5972
  if (found && found.node.parallel_branches) {
5832
5973
  targetBranch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5833
5974
  if (targetBranch) ptr = targetBranch.tree;
@@ -5857,7 +5998,8 @@ function CreateAncestryPanel({
5857
5998
  currentInputDesc,
5858
5999
  processedSections,
5859
6000
  customProps,
5860
- isPrivate
6001
+ isPrivate,
6002
+ ancestryMode.abstraction_tree
5861
6003
  ));
5862
6004
  if (onRenderFullAncestry) {
5863
6005
  const rotation = branchStack.reduce((acc, step) => {
@@ -5916,7 +6058,8 @@ function CreateAncestryPanel({
5916
6058
  currentInputDesc,
5917
6059
  processedSections,
5918
6060
  customProps,
5919
- isPrivate
6061
+ isPrivate,
6062
+ ancestryMode.abstraction_tree
5920
6063
  ));
5921
6064
  if (!keepOpen) onClose();
5922
6065
  } finally {
@@ -5969,7 +6112,9 @@ function CreateAncestryPanel({
5969
6112
  const node = findNode(activeTree, selectedParentId);
5970
6113
  return node ? node.name : "Nenhum";
5971
6114
  };
5972
- const hasChildren = activeTree && activeTree.children && activeTree.children.length > 0;
6115
+ const hasMainChildren = activeTree && activeTree.children && activeTree.children.length > 0;
6116
+ const hasAbstractionChildren = branchStack.length === 0 && ancestryMode.abstraction_tree && ancestryMode.abstraction_tree.children && ancestryMode.abstraction_tree.children.length > 0;
6117
+ const canSave = hasMainChildren || hasAbstractionChildren;
5973
6118
  const handleSectionChangeWrapper = (sectionId) => {
5974
6119
  const ctx = getCurrentContext();
5975
6120
  const currentDesc = ctx ? ctx.description : description;
@@ -6172,7 +6317,7 @@ function CreateAncestryPanel({
6172
6317
  unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type),
6173
6318
  onUploadFile
6174
6319
  }
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(
6320
+ )), /* @__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
6321
  "button",
6177
6322
  {
6178
6323
  type: "button",
@@ -6203,44 +6348,77 @@ function CreateAncestryPanel({
6203
6348
  path: [],
6204
6349
  isEditable: isAddingNodes
6205
6350
  }
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",
6351
+ ), (!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(
6352
+ "div",
6223
6353
  {
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"
6354
+ 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"}`,
6355
+ onClick: () => setTargetRenderNodeId(null)
6227
6356
  },
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(
6357
+ /* @__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(
6358
+ "button",
6359
+ {
6360
+ type: "button",
6361
+ onClick: (e) => {
6362
+ e.stopPropagation();
6363
+ const tempPayload = {
6364
+ ancestry_id: currentAncestryId || "temp_rendering",
6365
+ abstraction_tree: ancestryMode.abstraction_tree
6366
+ };
6367
+ if (onRenderAbstractionTree) onRenderAbstractionTree(tempPayload, targetRenderNodeId);
6368
+ },
6369
+ 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",
6370
+ title: "Renderizar cen\xE1rio at\xE9 o caminho selecionado"
6371
+ },
6372
+ /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiLayers, { size: 13 }),
6373
+ /* @__PURE__ */ import_react10.default.createElement("span", { className: "text-[10px] font-bold uppercase tracking-wider" }, "Renderizar")
6374
+ ), /* @__PURE__ */ import_react10.default.createElement(
6375
+ "button",
6376
+ {
6377
+ type: "button",
6378
+ onClick: (e) => {
6379
+ e.stopPropagation();
6380
+ const tempPayload = {
6381
+ ancestry_id: currentAncestryId || "temp_rendering",
6382
+ abstraction_tree: ancestryMode.abstraction_tree
6383
+ };
6384
+ if (onRenderAbstractionTree) onRenderAbstractionTree(tempPayload);
6385
+ },
6386
+ className: "p-1.5 rounded-md bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600 transition-colors",
6387
+ title: "Renderizar Verticalmente Completo"
6388
+ },
6389
+ /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiLayers, { size: 14 })
6390
+ ), /* @__PURE__ */ import_react10.default.createElement(
6391
+ "button",
6392
+ {
6393
+ type: "button",
6394
+ onClick: (e) => {
6395
+ e.stopPropagation();
6396
+ handleToggleAddMode(true);
6397
+ },
6398
+ 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"}`,
6399
+ title: "Editar estrutura da abstra\xE7\xE3o"
6400
+ },
6401
+ ancestryMode.isAddingAbstractionNodes ? /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiCheck, { size: 14 }) : /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiEdit2, { size: 14 })
6402
+ ))),
6403
+ /* @__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(
6404
+ NodeItem,
6405
+ {
6406
+ nodeData: ancestryMode.abstraction_tree,
6407
+ onSelectParent: (id) => handleSelectAncestryParent(id, true),
6408
+ onViewSelect: setTargetRenderNodeId,
6409
+ highlightedPathIds,
6410
+ targetRenderNodeId,
6411
+ onRemoveNode: (path) => handleRemoveNode(path, true),
6412
+ onEditRelationship,
6413
+ onMoveNode: (s, t) => handleMoveNode(s, t, true),
6414
+ selectedParentId: ancestryMode.selectedAbstractionParentId,
6415
+ level: 0,
6416
+ isLast: true,
6417
+ path: [],
6418
+ isEditable: ancestryMode.isAddingAbstractionNodes
6419
+ }
6420
+ ))
6421
+ ), 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
6422
  "input",
6245
6423
  {
6246
6424
  type: "checkbox",
@@ -6248,7 +6426,7 @@ function CreateAncestryPanel({
6248
6426
  onChange: (e) => setIsPrivate(e.target.checked),
6249
6427
  className: "hidden"
6250
6428
  }
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(
6429
+ ), /* @__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
6430
  "button",
6253
6431
  {
6254
6432
  onClick: () => handleLocalSave(false),
@@ -8758,7 +8936,7 @@ var getAllNodeIdsFromTree = (treeNode) => {
8758
8936
  traverse(treeNode);
8759
8937
  return Array.from(ids);
8760
8938
  };
8761
- var findNodePath2 = (tree, targetNodeId, currentPath = []) => {
8939
+ var findNodePath3 = (tree, targetNodeId, currentPath = []) => {
8762
8940
  var _a;
8763
8941
  if (!tree) return null;
8764
8942
  const currentNodeId = tree.is_section ? tree.section_id : String((_a = tree.node) == null ? void 0 : _a.id);
@@ -8767,7 +8945,7 @@ var findNodePath2 = (tree, targetNodeId, currentPath = []) => {
8767
8945
  }
8768
8946
  if (tree.children) {
8769
8947
  for (let i = 0; i < tree.children.length; i++) {
8770
- const res = findNodePath2(tree.children[i], targetNodeId, [...currentPath, i]);
8948
+ const res = findNodePath3(tree.children[i], targetNodeId, [...currentPath, i]);
8771
8949
  if (res) return res;
8772
8950
  }
8773
8951
  }
@@ -10836,13 +11014,34 @@ function XViewScene({
10836
11014
  },
10837
11015
  [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, readingMode.isActive, ancestryMode.isActive]
10838
11016
  );
10839
- const handleRenderAbstractionTree = (0, import_react23.useCallback)((ancestryObject) => {
11017
+ const handleRenderAbstractionTree = (0, import_react23.useCallback)((ancestryObject, targetNodeId = null) => {
10840
11018
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
10841
11019
  if (!ancestryObject || !ancestryObject.abstraction_tree) return;
10842
11020
  const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
10843
11021
  const allParentNodes = Object.values(parentDataRef.current).flatMap((f) => f.nodes);
10844
- const fullTree = buildFullAncestryTree(ancestryObject.abstraction_tree, allParentNodes, ancestryDataRef.current);
11022
+ let fullTree = buildFullAncestryTree(ancestryObject.abstraction_tree, allParentNodes, ancestryDataRef.current);
10845
11023
  if (!fullTree || !fullTree.node) return;
11024
+ if (targetNodeId) {
11025
+ const pruneTreeToPath = (treeNode, targetId) => {
11026
+ var _a2;
11027
+ if (!treeNode) return null;
11028
+ const currentId = treeNode.is_section ? treeNode.section_id : String((_a2 = treeNode.node) == null ? void 0 : _a2.id);
11029
+ if (String(currentId) === String(targetId)) {
11030
+ return { ...treeNode, children: [] };
11031
+ }
11032
+ if (treeNode.children && treeNode.children.length > 0) {
11033
+ for (let child of treeNode.children) {
11034
+ const prunedChild = pruneTreeToPath(child, targetId);
11035
+ if (prunedChild) {
11036
+ return { ...treeNode, children: [prunedChild] };
11037
+ }
11038
+ }
11039
+ }
11040
+ return null;
11041
+ };
11042
+ const pruned = pruneTreeToPath(fullTree, targetNodeId);
11043
+ if (pruned) fullTree = pruned;
11044
+ }
10846
11045
  const absId = ancestryObject.ancestry_id + "_abs";
10847
11046
  handleClearAncestryVisuals(absId);
10848
11047
  const colorHex = 9133302;
@@ -10884,13 +11083,13 @@ function XViewScene({
10884
11083
  if (action === "open") {
10885
11084
  let currentPtr = fullTree;
10886
11085
  for (const step of branchStack) {
10887
- const found = findNodePath2(currentPtr, step.nodeId);
11086
+ const found = findNodePath3(currentPtr, step.nodeId);
10888
11087
  if (found && found.node.parallel_branches) {
10889
11088
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
10890
11089
  if (branch) currentPtr = branch.tree;
10891
11090
  }
10892
11091
  }
10893
- const foundTarget = findNodePath2(currentPtr, nodeId);
11092
+ const foundTarget = findNodePath3(currentPtr, nodeId);
10894
11093
  if (foundTarget && foundTarget.node && foundTarget.node.parallel_branches && foundTarget.node.parallel_branches.length > 0) {
10895
11094
  const branchToOpen = foundTarget.node.parallel_branches.find((b) => (b.direction || "right") === direction);
10896
11095
  if (!branchToOpen) return;
@@ -10957,7 +11156,7 @@ function XViewScene({
10957
11156
  if (newStack.length > 0) {
10958
11157
  let ptr = fullTree;
10959
11158
  for (const step of newStack) {
10960
- const found = findNodePath2(ptr, step.nodeId);
11159
+ const found = findNodePath3(ptr, step.nodeId);
10961
11160
  if (found && found.node.parallel_branches) {
10962
11161
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
10963
11162
  if (branch) {
@@ -11098,7 +11297,7 @@ function XViewScene({
11098
11297
  let currentMeta = ancestry;
11099
11298
  let currentDirection = null;
11100
11299
  for (const step of branchStack) {
11101
- const found = findNodePath2(currentPtr, step.nodeId);
11300
+ const found = findNodePath3(currentPtr, step.nodeId);
11102
11301
  if (found && found.node.parallel_branches) {
11103
11302
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
11104
11303
  if (branch) {
@@ -11118,6 +11317,18 @@ function XViewScene({
11118
11317
  // <--- ADICIONADO
11119
11318
  };
11120
11319
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
11320
+ const readModeAbstractionTree = (0, import_react23.useMemo)(() => {
11321
+ if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
11322
+ return null;
11323
+ }
11324
+ const allNodes = Object.values(parentDataRef.current || {}).flatMap((f) => f.nodes || []);
11325
+ const allAncestries = ancestryDataRef.current || [];
11326
+ return buildFullAncestryTree(
11327
+ readingMode.ancestry.abstraction_tree,
11328
+ allNodes,
11329
+ allAncestries
11330
+ );
11331
+ }, [readingMode.isActive, readingMode.ancestry, buildFullAncestryTree, sceneVersion]);
11121
11332
  const handleStartReadingAncestry = (0, import_react23.useCallback)(
11122
11333
  async (ancestryObject) => {
11123
11334
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
@@ -11158,7 +11369,7 @@ function XViewScene({
11158
11369
  );
11159
11370
  let currentPtr = fullTree;
11160
11371
  for (const step of branchStack) {
11161
- const found = findNodePath2(currentPtr, step.nodeId);
11372
+ const found = findNodePath3(currentPtr, step.nodeId);
11162
11373
  if (found && found.node && found.node.parallel_branches) {
11163
11374
  const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
11164
11375
  if (branch) {
@@ -11709,6 +11920,13 @@ function XViewScene({
11709
11920
  const handleToggleAncestryAddMode = (0, import_react23.useCallback)(() => {
11710
11921
  setAncestryMode((prev) => ({ ...prev, isAddingNodes: !prev.isAddingNodes }));
11711
11922
  }, []);
11923
+ const handleFocusNode = (0, import_react23.useCallback)((nodeData) => {
11924
+ if (!nodeData) return;
11925
+ const nodeMesh = stateRef.current.nodeObjects[String(nodeData.id)];
11926
+ if (nodeMesh) {
11927
+ tweenToTarget(nodeMesh, 1.2);
11928
+ }
11929
+ }, [tweenToTarget]);
11712
11930
  if (isLoading || status === "loading" || permissionStatus === "loading") {
11713
11931
  return /* @__PURE__ */ import_react23.default.createElement(LoadingScreen, null);
11714
11932
  }
@@ -11826,7 +12044,9 @@ function XViewScene({
11826
12044
  activeNodeBranches,
11827
12045
  backNavigationInfo,
11828
12046
  onImageClick: (url, name) => handleOpenImageViewer([{ name: name || "Imagem", value: url }], 0),
11829
- userRole: userPermissionRole
12047
+ userRole: userPermissionRole,
12048
+ abstractionTree: readModeAbstractionTree,
12049
+ onRenderAbstractionTree: (targetId) => handleRenderAbstractionTree(readingMode.ancestry, targetId)
11830
12050
  }
11831
12051
  )
11832
12052
  ),
@@ -11834,6 +12054,7 @@ function XViewScene({
11834
12054
  CreateAncestryPanel,
11835
12055
  {
11836
12056
  ancestryMode,
12057
+ setAncestryMode,
11837
12058
  onSelectParent: handleSelectAncestryParent,
11838
12059
  onRemoveNode: handleRemoveFromAncestry,
11839
12060
  onSave: handleSaveAncestry,
@@ -11853,7 +12074,7 @@ function XViewScene({
11853
12074
  onClearAncestryVisuals: handleClearAncestryVisuals,
11854
12075
  onUploadFile: upload_file_action,
11855
12076
  onOpenImageViewer: handleOpenImageViewer,
11856
- onRenderAbstractionTree: (data) => handleRenderAbstractionTree(data)
12077
+ onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
11857
12078
  }
11858
12079
  ),
11859
12080
  editingAncestryRel.visible && /* @__PURE__ */ import_react23.default.createElement(
@@ -11967,7 +12188,8 @@ function XViewScene({
11967
12188
  onExpandConnections: (sourceNode, links) => userActionHandlers.handleExpandConnections(actionHandlerContext, sourceNode, links),
11968
12189
  onRenderAncestry: handleStartReadingAncestry,
11969
12190
  onEditAncestry: handleEditAncestry,
11970
- onDeleteAncestry: (ancestryId) => handleDeleteAncestry(ancestryId)
12191
+ onDeleteAncestry: (ancestryId) => handleDeleteAncestry(ancestryId),
12192
+ onFocusNode: handleFocusNode
11971
12193
  }
11972
12194
  ),
11973
12195
  /* @__PURE__ */ import_react23.default.createElement(