@lv-x-software-house/x_view 1.2.2-dev.9 → 1.2.3-dev.1

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 +1366 -890
  2. package/dist/index.mjs +821 -344
  3. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/XViewScene.jsx
2
- import React23, { useCallback as useCallback3, useEffect as useEffect21, useRef as useRef17, useState as useState22, useMemo as useMemo12 } from "react";
2
+ import React23, { useCallback as useCallback4, useEffect as useEffect21, useRef as useRef17, useState as useState23, useMemo as useMemo12 } from "react";
3
3
  import { useRouter, useSearchParams } from "next/navigation";
4
4
  import { useSession } from "next-auth/react";
5
5
  import CryptoJS from "crypto-js";
@@ -246,7 +246,7 @@ function ContextMenu({
246
246
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React.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__ */ React.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1" }, ability.can("create", "Connection") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__PURE__ */ React.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__ */ React.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__ */ React.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__ */ React.createElement("span", null, "Conectar")), ability.can("create", "Node") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__PURE__ */ React.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__ */ React.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ React.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ React.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar Ancestralidade" }, /* @__PURE__ */ React.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__ */ React.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__ */ React.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ React.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__ */ React.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ React.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__PURE__ */ React.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__ */ React.createElement("line", { x1: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ React.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ React.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ React.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ React.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__PURE__ */ React.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__ */ React.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__ */ React.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ React.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ React.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => {
247
247
  onFocusNode == null ? void 0 : onFocusNode(data.nodeData);
248
248
  onClose();
249
- }, className: baseButtonClass, title: "Focar na c\xE2mera" }, /* @__PURE__ */ React.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__ */ React.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "3" })), /* @__PURE__ */ React.createElement("span", null, "Focar neste Node")), /* @__PURE__ */ React.createElement("button", { onClick: (e) => handleCopyLink(e, data.nodeData), className: baseButtonClass, title: "Copiar Link para Compartilhar" }, isLinkCopied ? /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#4ade80", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("polyline", { points: "20 6 9 17 4 12" })) : /* @__PURE__ */ React.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__ */ React.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__ */ React.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__ */ React.createElement("span", { className: isLinkCopied ? "text-green-400" : "" }, isLinkCopied ? "Copiado!" : "Copiar Link")), ability.can("dismiss", "Node") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("button", { onClick: () => onDismissNode == null ? void 0 : onDismissNode(data.nodeData), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ React.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__ */ React.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ React.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__ */ React.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__ */ React.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ React.createElement("span", null, "Dismiss")), /* @__PURE__ */ React.createElement("button", { onClick: () => onDismissOtherNodes == null ? void 0 : onDismissOtherNodes(data.nodeData), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ React.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__ */ React.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ React.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ React.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ React.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ React.createElement("span", null, "Dismiss other nodes"))), ability.can("delete", "Node") && /* @__PURE__ */ React.createElement("button", { onClick: () => onDeleteNode == null ? void 0 : onDeleteNode(data.nodeData), className: deleteButtonClass, title: "Excluir Node" }, /* @__PURE__ */ React.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__ */ React.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React.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__ */ React.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ React.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ React.createElement("span", null, "Excluir Node"))));
249
+ }, className: baseButtonClass, title: "Focar na c\xE2mera" }, /* @__PURE__ */ React.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__ */ React.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "3" })), /* @__PURE__ */ React.createElement("span", null, "Focar neste Node")), /* @__PURE__ */ React.createElement("button", { onClick: (e) => handleCopyLink(e, data.nodeData), className: baseButtonClass, title: "Copiar Link para Compartilhar" }, isLinkCopied ? /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#4ade80", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("polyline", { points: "20 6 9 17 4 12" })) : /* @__PURE__ */ React.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__ */ React.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__ */ React.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__ */ React.createElement("span", { className: isLinkCopied ? "text-green-400" : "" }, isLinkCopied ? "Copiado!" : "Copiar Link")), ability.can("dismiss", "Node") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("button", { onClick: () => onDismissNode == null ? void 0 : onDismissNode(data.nodeData), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ React.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__ */ React.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ React.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__ */ React.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__ */ React.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ React.createElement("span", null, "Dismiss")), /* @__PURE__ */ React.createElement("button", { onClick: () => onDismissOtherNodes == null ? void 0 : onDismissOtherNodes(data.nodeData), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ React.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__ */ React.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ React.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ React.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ React.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ React.createElement("span", null, "Dismiss other nodes"))), ability.can("delete", "Node") && /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("deleteConfirmation"), className: deleteButtonClass, title: "Excluir Node" }, /* @__PURE__ */ React.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__ */ React.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React.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__ */ React.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ React.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ React.createElement("span", null, "Excluir Node"))));
250
250
  };
251
251
  const renderVersionSubMenuView = () => {
252
252
  const group = versionSubMenu;
@@ -338,6 +338,24 @@ function ContextMenu({
338
338
  /* @__PURE__ */ React.createElement("span", { className: "flex-1 truncate" }, version.name)
339
339
  ))));
340
340
  };
341
+ const renderDeleteConfirmationView = () => {
342
+ var _a2;
343
+ return /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ React.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ React.createElement("div", { className: "w-10 h-10 rounded-full bg-red-500/20 flex items-center justify-center text-red-400 mb-1" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React.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__ */ React.createElement("p", { className: "text-sm text-slate-200" }, "Excluir ", /* @__PURE__ */ React.createElement("strong", null, (_a2 = data.nodeData) == null ? void 0 : _a2.name), "?"), /* @__PURE__ */ React.createElement("p", { className: "text-[11px] text-slate-400 leading-tight" }, "Todas as conex\xF5es associadas tamb\xE9m ser\xE3o apagadas.")), /* @__PURE__ */ React.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ React.createElement(
344
+ "button",
345
+ {
346
+ onClick: () => setMenuView("main"),
347
+ className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
348
+ },
349
+ "Cancelar"
350
+ ), /* @__PURE__ */ React.createElement(
351
+ "button",
352
+ {
353
+ onClick: () => onDeleteNode == null ? void 0 : onDeleteNode(data.nodeData),
354
+ className: "flex-1 px-2 py-2 text-xs font-medium bg-red-500 hover:bg-red-600 rounded-md text-white transition-colors"
355
+ },
356
+ "Excluir"
357
+ )));
358
+ };
341
359
  return /* @__PURE__ */ React.createElement(
342
360
  "div",
343
361
  {
@@ -353,7 +371,7 @@ function ContextMenu({
353
371
  onDoubleClick: swallow
354
372
  },
355
373
  /* @__PURE__ */ React.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
356
- /* @__PURE__ */ React.createElement("div", { className: "p-1.5" }, menuView === "main" && renderMainView(), menuView === "connections" && renderConnectionsView(), menuView === "ancestryActions" && renderAncestryActionsView(), menuView === "versioning" && renderVersioningView())
374
+ /* @__PURE__ */ React.createElement("div", { className: "p-1.5" }, menuView === "main" && renderMainView(), menuView === "connections" && renderConnectionsView(), menuView === "ancestryActions" && renderAncestryActionsView(), menuView === "versioning" && renderVersioningView(), menuView === "deleteConfirmation" && renderDeleteConfirmationView())
357
375
  );
358
376
  }
359
377
 
@@ -735,7 +753,7 @@ function XViewSidebar({
735
753
  }
736
754
 
737
755
  // src/components/AncestryRelationshipPanel.jsx
738
- import React8, { useState as useState8, useEffect as useEffect8, useRef as useRef7 } from "react";
756
+ import React8, { useState as useState9, useEffect as useEffect8, useRef as useRef7 } from "react";
739
757
 
740
758
  // node_modules/uuid/dist/esm-node/rng.js
741
759
  import crypto from "crypto";
@@ -785,6 +803,7 @@ function v4(options, buf, offset) {
785
803
  var v4_default = v4;
786
804
 
787
805
  // src/logic/x_view_utils.js
806
+ import { useState as useState3, useCallback } from "react";
788
807
  import * as THREE2 from "three";
789
808
 
790
809
  // src/logic/x_view_config.js
@@ -1534,7 +1553,6 @@ var userActionHandlers = {
1534
1553
  color: ghostColor,
1535
1554
  emissive: ghostEmissive,
1536
1555
  emissiveIntensity: MIN_VISIBILITY_INTENSITY,
1537
- // <-- Forçamos o brilho mínimo
1538
1556
  roughness: 0.6,
1539
1557
  metalness: 0,
1540
1558
  transparent: true,
@@ -1691,7 +1709,6 @@ var userActionHandlers = {
1691
1709
  color: ghostColor,
1692
1710
  emissive: ghostEmissive,
1693
1711
  emissiveIntensity: MIN_VISIBILITY_INTENSITY,
1694
- // <-- Forçamos o brilho mínimo
1695
1712
  roughness: 0.6,
1696
1713
  metalness: 0,
1697
1714
  transparent: true,
@@ -1988,9 +2005,7 @@ var userActionHandlers = {
1988
2005
  linkObject.visible = false;
1989
2006
  controls.enabled = false;
1990
2007
  if (mountRef.current) mountRef.current.style.cursor = "crosshair";
1991
- const tempMat = new LineMaterial({
1992
- /* ... material tracejado ... */
1993
- });
2008
+ const tempMat = new LineMaterial({});
1994
2009
  const tempGeom = new LineGeometry().setPositions([
1995
2010
  ...fixedNode.position.toArray(),
1996
2011
  ...fixedNode.position.toArray()
@@ -2119,9 +2134,6 @@ var userActionHandlers = {
2119
2134
  const { parentFileId, ownerId } = parentInfo;
2120
2135
  const srcName = ((_c = (_b = (_a = linkObject.userData) == null ? void 0 : _a.sourceNode) == null ? void 0 : _b.userData) == null ? void 0 : _c.name) ?? linkObject.userData.source;
2121
2136
  const tgtName = ((_f = (_e = (_d = linkObject.userData) == null ? void 0 : _d.targetNode) == null ? void 0 : _e.userData) == null ? void 0 : _f.name) ?? linkObject.userData.target;
2122
- if (!window.confirm(`Tem certeza que deseja excluir a conex\xE3o entre "${srcName}" \u2192 "${tgtName}"?`)) {
2123
- return;
2124
- }
2125
2137
  const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileId]));
2126
2138
  const newLinks = (specificParentData.links || []).filter((l) => String(l.id) !== String(linkIdToDelete));
2127
2139
  specificParentData.links = newLinks;
@@ -2275,9 +2287,6 @@ var userActionHandlers = {
2275
2287
  const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
2276
2288
  setters.setMultiContextMenu({ visible: false });
2277
2289
  if (!nodeIds || nodeIds.size === 0 || !graphDataRef.current || !sceneDataRef.current) return;
2278
- if (!window.confirm(`Tem certeza que deseja excluir ${nodeIds.size} Nodes e todas as suas conex\xF5es? Esta a\xE7\xE3o \xE9 irrevers\xEDvel.`)) {
2279
- return;
2280
- }
2281
2290
  const strNodeIdsToDelete = Array.from(nodeIds).map(String);
2282
2291
  if (actions.delete_file) {
2283
2292
  strNodeIdsToDelete.forEach((id) => {
@@ -2358,9 +2367,6 @@ var userActionHandlers = {
2358
2367
  }
2359
2368
  setters.setContextMenu({ visible: false });
2360
2369
  if (!nodeData || !graphDataRef.current || !sceneDataRef.current) return;
2361
- if (!window.confirm(`Tem certeza que deseja excluir o Node "${nodeData.name}" e todas as sua conex\xF5es?`)) {
2362
- return;
2363
- }
2364
2370
  const nodeIdToDelete = nodeData.id;
2365
2371
  const strNodeId = String(nodeIdToDelete);
2366
2372
  const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeIdToDelete);
@@ -2999,9 +3005,36 @@ var extractFileUrlsFromProperties = (dataObject) => {
2999
3005
  });
3000
3006
  return urlsToDelete;
3001
3007
  };
3008
+ function useResizablePanel({ initialWidth, minWidth, maxWidth }) {
3009
+ const [width, setWidth] = useState3(initialWidth);
3010
+ const [isResizing, setIsResizing] = useState3(false);
3011
+ const handlePointerDown = useCallback((e) => {
3012
+ e.preventDefault();
3013
+ e.stopPropagation();
3014
+ setIsResizing(true);
3015
+ const startX = e.clientX;
3016
+ const startWidth = width;
3017
+ const originalUserSelect = document.body.style.userSelect;
3018
+ document.body.style.userSelect = "none";
3019
+ const handlePointerMove = (moveEvent) => {
3020
+ const deltaX = startX - moveEvent.clientX;
3021
+ const newWidth = Math.min(Math.max(startWidth + deltaX, minWidth), maxWidth);
3022
+ setWidth(newWidth);
3023
+ };
3024
+ const handlePointerUp = () => {
3025
+ setIsResizing(false);
3026
+ document.body.style.userSelect = originalUserSelect;
3027
+ document.removeEventListener("pointermove", handlePointerMove);
3028
+ document.removeEventListener("pointerup", handlePointerUp);
3029
+ };
3030
+ document.addEventListener("pointermove", handlePointerMove);
3031
+ document.addEventListener("pointerup", handlePointerUp);
3032
+ }, [width, minWidth, maxWidth]);
3033
+ return { width, isResizing, handlePointerDown, setWidth };
3034
+ }
3002
3035
 
3003
3036
  // src/components/CustomPropertyDisplay.jsx
3004
- import React3, { useState as useState3, useRef as useRef3, useEffect as useEffect3 } from "react";
3037
+ import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
3005
3038
  import { FiCheck, FiX, FiEdit3, FiTrash2, FiExternalLink, FiFileText, FiChevronDown, FiUpload, FiLoader } from "react-icons/fi";
3006
3039
  function CustomPropertyDisplay({
3007
3040
  prop,
@@ -3016,12 +3049,12 @@ function CustomPropertyDisplay({
3016
3049
  },
3017
3050
  onUploadFile
3018
3051
  }) {
3019
- const [isEditing, setIsEditing] = useState3(prop.isEditing ?? false);
3020
- const [tempProp, setTempProp] = useState3(prop);
3021
- const [isHovered, setIsHovered] = useState3(false);
3022
- const [isTypeDropdownOpen, setIsTypeDropdownOpen] = useState3(false);
3052
+ const [isEditing, setIsEditing] = useState4(prop.isEditing ?? false);
3053
+ const [tempProp, setTempProp] = useState4(prop);
3054
+ const [isHovered, setIsHovered] = useState4(false);
3055
+ const [isTypeDropdownOpen, setIsTypeDropdownOpen] = useState4(false);
3023
3056
  const dropdownRef = useRef3(null);
3024
- const [uploadingItemIndex, setUploadingItemIndex] = useState3(null);
3057
+ const [uploadingItemIndex, setUploadingItemIndex] = useState4(null);
3025
3058
  const fileInputRef = useRef3(null);
3026
3059
  const currentUploadTargetRef = useRef3(null);
3027
3060
  useEffect3(() => {
@@ -3144,8 +3177,8 @@ function CustomPropertyDisplay({
3144
3177
  const availableOptions = [
3145
3178
  { value: "links", label: "Links", unique: true },
3146
3179
  { value: "images", label: "Images", unique: true },
3147
- { value: "documents", label: "Documents", unique: true },
3148
3180
  { value: "date", label: "Data", unique: true },
3181
+ { value: "documents", label: "Documents", unique: true },
3149
3182
  { value: "text", label: "Texto", unique: false },
3150
3183
  { value: "number", label: "N\xFAmero", unique: false },
3151
3184
  { value: "list", label: "Lista", unique: false }
@@ -3367,15 +3400,15 @@ function CustomPropertyDisplay({
3367
3400
  import { FiPlus, FiEdit2 as FiEdit22, FiBookOpen } from "react-icons/fi";
3368
3401
 
3369
3402
  // src/components/DescriptionEditModal.jsx
3370
- import React5, { useState as useState5, useEffect as useEffect5, useRef as useRef5, useMemo as useMemo4 } from "react";
3371
- import { FiType, FiList, FiCode, FiLink as FiLink2, FiAtSign, FiSearch as FiSearch2, FiHexagon as FiHexagon2, FiGlobe, FiImage } from "react-icons/fi";
3403
+ import React5, { useState as useState6, useEffect as useEffect5, useRef as useRef5, useMemo as useMemo4 } from "react";
3404
+ import { FiType, FiList, FiCode, FiLink as FiLink2, FiAtSign, FiSearch as FiSearch2, FiHexagon as FiHexagon2, FiGlobe, FiImage, FiCheckSquare } from "react-icons/fi";
3372
3405
 
3373
3406
  // src/components/SectionImportModal.jsx
3374
- import React4, { useState as useState4, useMemo as useMemo3, useRef as useRef4, useEffect as useEffect4 } from "react";
3407
+ import React4, { useState as useState5, useMemo as useMemo3, useRef as useRef4, useEffect as useEffect4 } from "react";
3375
3408
  import { FiSearch, FiLayers as FiLayers2, FiHexagon, FiClock, FiCheck as FiCheck2, FiCopy, FiTerminal, FiChevronDown as FiChevronDown2, FiChevronRight, FiDownload, FiLink } from "react-icons/fi";
3376
3409
  var CodeBlock = ({ content, isActive, onClick }) => {
3377
- const [isExpanded, setIsExpanded] = useState4(false);
3378
- const [copied, setCopied] = useState4(false);
3410
+ const [isExpanded, setIsExpanded] = useState5(false);
3411
+ const [copied, setCopied] = useState5(false);
3379
3412
  const cleanContent = content.replace(/^```|```$/g, "").trim();
3380
3413
  const isLongCode = cleanContent.split("\n").length > 4;
3381
3414
  const handleCopy = (e) => {
@@ -3438,12 +3471,14 @@ var formatLineContent = (line) => {
3438
3471
  return /* @__PURE__ */ React4.createElement("span", { className: "break-words" }, line);
3439
3472
  };
3440
3473
  function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], availableAncestries = [] }) {
3441
- const [searchTerm, setSearchTerm] = useState4("");
3442
- const [selectedItem, setSelectedItem] = useState4(null);
3443
- const [searchHistory, setSearchHistory] = useState4([]);
3444
- const [activeIndex, setActiveIndex] = useState4(0);
3474
+ const [searchTerm, setSearchTerm] = useState5("");
3475
+ const [selectedItem, setSelectedItem] = useState5(null);
3476
+ const [searchHistory, setSearchHistory] = useState5([]);
3477
+ const [activeIndex, setActiveIndex] = useState5(0);
3478
+ const [selectedIndices, setSelectedIndices] = useState5(/* @__PURE__ */ new Set([0]));
3479
+ const [lastSelectedIndex, setLastSelectedIndex] = useState5(0);
3445
3480
  const sectionRefs = useRef4([]);
3446
- const [isDropdownOpen, setIsDropdownOpen] = useState4(false);
3481
+ const [isDropdownOpen, setIsDropdownOpen] = useState5(false);
3447
3482
  const inputRef = useRef4(null);
3448
3483
  useEffect4(() => {
3449
3484
  if (!selectedItem) return;
@@ -3490,6 +3525,8 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
3490
3525
  }, [selectedItem]);
3491
3526
  useEffect4(() => {
3492
3527
  setActiveIndex(0);
3528
+ setSelectedIndices(/* @__PURE__ */ new Set([0]));
3529
+ setLastSelectedIndex(0);
3493
3530
  }, [selectedItem]);
3494
3531
  useEffect4(() => {
3495
3532
  if (selectedItem && sectionRefs.current[activeIndex]) {
@@ -3506,22 +3543,64 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
3506
3543
  if (document.activeElement === inputRef.current) return;
3507
3544
  if (e.key === "ArrowDown" || e.key === "ArrowRight") {
3508
3545
  e.preventDefault();
3509
- setActiveIndex((prev) => Math.min(prev + 1, itemSections.length - 1));
3546
+ setActiveIndex((prev) => {
3547
+ const next = Math.min(prev + 1, itemSections.length - 1);
3548
+ if (e.shiftKey) {
3549
+ setSelectedIndices((old) => /* @__PURE__ */ new Set([...old, next]));
3550
+ } else if (!e.ctrlKey && !e.metaKey) {
3551
+ setSelectedIndices(/* @__PURE__ */ new Set([next]));
3552
+ setLastSelectedIndex(next);
3553
+ }
3554
+ return next;
3555
+ });
3510
3556
  }
3511
3557
  if (e.key === "ArrowUp" || e.key === "ArrowLeft") {
3512
3558
  e.preventDefault();
3513
- setActiveIndex((prev) => Math.max(prev - 1, 0));
3559
+ setActiveIndex((prev) => {
3560
+ const next = Math.max(prev - 1, 0);
3561
+ if (e.shiftKey) {
3562
+ setSelectedIndices((old) => /* @__PURE__ */ new Set([...old, next]));
3563
+ } else if (!e.ctrlKey && !e.metaKey) {
3564
+ setSelectedIndices(/* @__PURE__ */ new Set([next]));
3565
+ setLastSelectedIndex(next);
3566
+ }
3567
+ return next;
3568
+ });
3514
3569
  }
3515
3570
  if (e.key === "Enter") {
3516
3571
  e.preventDefault();
3517
- if (itemSections[activeIndex]) {
3518
- handleConfirmImport(itemSections[activeIndex]);
3519
- }
3572
+ handleConfirmImport();
3520
3573
  }
3521
3574
  };
3522
3575
  window.addEventListener("keydown", handleKeyDown);
3523
3576
  return () => window.removeEventListener("keydown", handleKeyDown);
3524
- }, [itemSections, activeIndex, selectedItem]);
3577
+ }, [itemSections, selectedItem]);
3578
+ const handleSectionClick = (index, e) => {
3579
+ e.stopPropagation();
3580
+ if (e.shiftKey && lastSelectedIndex !== null) {
3581
+ const start = Math.min(lastSelectedIndex, index);
3582
+ const end = Math.max(lastSelectedIndex, index);
3583
+ const newSelection = new Set(selectedIndices);
3584
+ for (let i = start; i <= end; i++) {
3585
+ newSelection.add(i);
3586
+ }
3587
+ setSelectedIndices(newSelection);
3588
+ } else if (e.ctrlKey || e.metaKey) {
3589
+ const newSelection = new Set(selectedIndices);
3590
+ if (newSelection.has(index)) {
3591
+ newSelection.delete(index);
3592
+ if (newSelection.size === 0) newSelection.add(index);
3593
+ } else {
3594
+ newSelection.add(index);
3595
+ }
3596
+ setSelectedIndices(newSelection);
3597
+ setLastSelectedIndex(index);
3598
+ } else {
3599
+ setSelectedIndices(/* @__PURE__ */ new Set([index]));
3600
+ setLastSelectedIndex(index);
3601
+ }
3602
+ setActiveIndex(index);
3603
+ };
3525
3604
  const handleSelectItem = (item) => {
3526
3605
  setSelectedItem(item);
3527
3606
  setSearchHistory((prev) => {
@@ -3535,16 +3614,22 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
3535
3614
  setSearchTerm("");
3536
3615
  setIsDropdownOpen(false);
3537
3616
  };
3538
- const handleConfirmImport = (sectionToImport = null) => {
3539
- const section = sectionToImport || itemSections[activeIndex];
3540
- if (!section) return;
3617
+ const handleConfirmImport = () => {
3618
+ if (selectedIndices.size === 0) return;
3541
3619
  const type = selectedItem._type;
3542
3620
  const itemId = selectedItem.id || selectedItem.ancestry_id;
3543
- if (section.id) {
3544
- const tag = `[[REF:${type}:${itemId}:${section.id}]]`;
3545
- onSelect(tag);
3621
+ const indicesToImport = Array.from(selectedIndices).sort((a, b) => a - b);
3622
+ const tagsToImport = [];
3623
+ indicesToImport.forEach((idx) => {
3624
+ const section = itemSections[idx];
3625
+ if (section && section.id) {
3626
+ tagsToImport.push(`[[REF:${type}:${itemId}:${section.id}]]`);
3627
+ }
3628
+ });
3629
+ if (tagsToImport.length > 0) {
3630
+ onSelect(tagsToImport);
3546
3631
  } else {
3547
- alert("Esta se\xE7\xE3o n\xE3o possui um ID \xFAnico salvo. Salve o node de origem primeiro.");
3632
+ alert("Nenhuma se\xE7\xE3o v\xE1lida selecionada.");
3548
3633
  }
3549
3634
  };
3550
3635
  const renderSectionContent = (content) => {
@@ -3615,7 +3700,8 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
3615
3700
  /* @__PURE__ */ React4.createElement("div", { className: "truncate" }, /* @__PURE__ */ React4.createElement("div", { className: "text-sm font-medium text-slate-200 truncate" }, item.name), /* @__PURE__ */ React4.createElement("div", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, isNode ? ((_a = item.version_node) == null ? void 0 : _a.is_version) ? "Vers\xE3o" : "Node" : "Ancestralidade"))
3616
3701
  );
3617
3702
  }))), /* @__PURE__ */ React4.createElement("div", { className: "flex-1 flex flex-col bg-black/20 relative z-10" }, selectedItem ? /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 pr-8" }, /* @__PURE__ */ React4.createElement("div", { className: "w-full text-sm leading-relaxed text-slate-300 break-words whitespace-pre-wrap" }, itemSections.map((section, index) => {
3618
- const isActive = index === activeIndex;
3703
+ const isSelected = selectedIndices.has(index);
3704
+ const isFocused = index === activeIndex;
3619
3705
  const match = section.content.match(/^(\s*)([\s\S]*?)(\s*)$/);
3620
3706
  let leadingSpace = match ? match[1] : "";
3621
3707
  const bodyText = match ? match[2] : section.content;
@@ -3633,10 +3719,11 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
3633
3719
  refAssigned = true;
3634
3720
  }
3635
3721
  },
3636
- onClick: () => setActiveIndex(index),
3722
+ onClick: (e) => handleSectionClick(index, e),
3637
3723
  className: `
3638
3724
  transition-colors duration-200 cursor-pointer rounded-md px-1 py-0.5 -mx-1 box-decoration-clone
3639
- ${isActive ? "bg-indigo-500/20 ring-1 ring-indigo-500/30" : "hover:bg-white/5"}
3725
+ ${isSelected ? "bg-indigo-500/30 ring-1 ring-indigo-500/50" : "hover:bg-white/5"}
3726
+ ${isFocused && !isSelected ? "ring-1 ring-white/20" : ""}
3640
3727
  `
3641
3728
  },
3642
3729
  renderSectionContent(bodyText)
@@ -3657,8 +3744,8 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
3657
3744
  CodeBlock,
3658
3745
  {
3659
3746
  content: part,
3660
- isActive,
3661
- onClick: () => setActiveIndex(index)
3747
+ isActive: isSelected,
3748
+ onClick: (e) => handleSectionClick(index, e)
3662
3749
  }
3663
3750
  )
3664
3751
  );
@@ -3668,7 +3755,7 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
3668
3755
  const isLastLine = lineIndex === lines.length - 1;
3669
3756
  const isEmptyLine = line.trim() === "";
3670
3757
  if (isEmptyLine) {
3671
- return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: `${index}-${partIndex}-${lineIndex}` }, /* @__PURE__ */ React4.createElement("br", null));
3758
+ return /* @__PURE__ */ React4.createElement("br", { key: `${index}-${partIndex}-${lineIndex}` });
3672
3759
  }
3673
3760
  return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: `${index}-${partIndex}-${lineIndex}` }, /* @__PURE__ */ React4.createElement(
3674
3761
  "span",
@@ -3679,10 +3766,11 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
3679
3766
  refAssigned = true;
3680
3767
  }
3681
3768
  },
3682
- onClick: () => setActiveIndex(index),
3769
+ onClick: (e) => handleSectionClick(index, e),
3683
3770
  className: `
3684
- transition-colors duration-200 cursor-pointer rounded-md px-1 py-0.5 -mx-1 box-decoration-clone
3685
- ${isActive ? "bg-indigo-500/20 text-white ring-1 ring-indigo-500/30" : "hover:bg-white/5 hover:text-slate-200"}
3771
+ transition-colors duration-200 cursor-pointer rounded-md px-1 py-0.5 -mx-1 box-decoration-clone select-none
3772
+ ${isSelected ? "bg-indigo-500/30 text-white ring-1 ring-indigo-500/50 shadow-sm" : "hover:bg-white/5 hover:text-slate-200"}
3773
+ ${isFocused && !isSelected ? "ring-1 ring-white/20" : ""}
3686
3774
  `
3687
3775
  },
3688
3776
  formatLineContent(line)
@@ -3696,7 +3784,8 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
3696
3784
  className: "flex items-center gap-2 px-6 py-2.5 bg-indigo-600 hover:bg-indigo-500 text-white text-sm font-semibold rounded-lg shadow-lg shadow-indigo-500/20 transition-all transform active:scale-95"
3697
3785
  },
3698
3786
  /* @__PURE__ */ React4.createElement(FiDownload, { className: "text-indigo-200" }),
3699
- "Importar Se\xE7\xE3o"
3787
+ "Importar ",
3788
+ selectedIndices.size > 1 ? `${selectedIndices.size} Se\xE7\xF5es` : "Se\xE7\xE3o"
3700
3789
  ))) : /* @__PURE__ */ React4.createElement("div", { className: "flex-1 flex flex-col items-center justify-center text-slate-500" }, /* @__PURE__ */ React4.createElement("div", { className: "w-16 h-16 rounded-full bg-white/5 flex items-center justify-center mb-4" }, /* @__PURE__ */ React4.createElement(FiSearch, { size: 24, className: "opacity-50" })), /* @__PURE__ */ React4.createElement("p", null, "Selecione um item \xE0 esquerda para visualizar suas se\xE7\xF5es."))))
3701
3790
  ));
3702
3791
  }
@@ -3728,16 +3817,22 @@ function DescriptionEditModal({
3728
3817
  availableAncestries = [],
3729
3818
  availableImages = []
3730
3819
  }) {
3731
- const [text, setText] = useState5(initialValue || "");
3820
+ const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.9 : 1200;
3821
+ const { width: panelWidth, isResizing, handlePointerDown: handleResize } = useResizablePanel({
3822
+ initialWidth: 700,
3823
+ minWidth: 400,
3824
+ maxWidth: maxPanelW
3825
+ });
3826
+ const [text, setText] = useState6(initialValue || "");
3732
3827
  const textareaRef = useRef5(null);
3733
- const [isImportModalOpen, setIsImportModalOpen] = useState5(false);
3734
- const [isMentionModalOpen, setIsMentionModalOpen] = useState5(false);
3735
- const [mentionSearch, setMentionSearch] = useState5("");
3736
- const [mentionTriggerIndex, setMentionTriggerIndex] = useState5(null);
3737
- const [isImageModalOpen, setIsImageModalOpen] = useState5(false);
3738
- const [manualImageUrl, setManualImageUrl] = useState5("");
3828
+ const [isImportModalOpen, setIsImportModalOpen] = useState6(false);
3829
+ const [isMentionModalOpen, setIsMentionModalOpen] = useState6(false);
3830
+ const [mentionSearch, setMentionSearch] = useState6("");
3831
+ const [mentionTriggerIndex, setMentionTriggerIndex] = useState6(null);
3832
+ const [isImageModalOpen, setIsImageModalOpen] = useState6(false);
3833
+ const [manualImageUrl, setManualImageUrl] = useState6("");
3739
3834
  const hoverTimeoutRef = useRef5(null);
3740
- const [tooltipData, setTooltipData] = useState5(null);
3835
+ const [tooltipData, setTooltipData] = useState6(null);
3741
3836
  useEffect5(() => {
3742
3837
  const handleKeyDown = (e) => {
3743
3838
  if (e.key === "Escape") {
@@ -3830,12 +3925,28 @@ function DescriptionEditModal({
3830
3925
  const uniqueSuffix = v4_default().slice(0, 4);
3831
3926
  insertAtCursor(`*/${nextNum}:${uniqueSuffix}/ `);
3832
3927
  };
3833
- const handleImportSelect = (tag) => {
3834
- const nextNum = getNextSectionNumber(text);
3835
- const uniqueSuffix = v4_default().slice(0, 4);
3836
- insertAtCursor(`
3837
- */${nextNum}:${uniqueSuffix}/ ${tag}
3838
- `);
3928
+ const handleImportSelect = (tags) => {
3929
+ const tagsArray = Array.isArray(tags) ? tags : [tags];
3930
+ const el = textareaRef.current;
3931
+ if (!el) return;
3932
+ let currentText = text;
3933
+ let currentNum = getNextSectionNumber(currentText);
3934
+ let blockToInsert = "";
3935
+ tagsArray.forEach((tag) => {
3936
+ const uniqueSuffix = v4_default().slice(0, 4);
3937
+ blockToInsert += `
3938
+ */${currentNum}:${uniqueSuffix}/ ${tag}
3939
+ `;
3940
+ currentNum++;
3941
+ });
3942
+ const start = el.selectionStart;
3943
+ const end = el.selectionEnd;
3944
+ const newText = currentText.substring(0, start) + blockToInsert + currentText.substring(end);
3945
+ el.value = newText;
3946
+ el.setSelectionRange(start + blockToInsert.length, start + blockToInsert.length);
3947
+ el.dispatchEvent(new Event("input", { bubbles: true }));
3948
+ el.focus();
3949
+ setText(newText);
3839
3950
  setIsImportModalOpen(false);
3840
3951
  };
3841
3952
  const handleMentionSelect = (node) => {
@@ -3871,6 +3982,70 @@ function DescriptionEditModal({
3871
3982
  setIsMentionModalOpen(true);
3872
3983
  }
3873
3984
  };
3985
+ const handleKeyDownTextarea = (e) => {
3986
+ const el = textareaRef.current;
3987
+ if (!el) return;
3988
+ if (e.key === "Enter") {
3989
+ const cursorPosition = el.selectionStart;
3990
+ const textBeforeCursor = text.substring(0, cursorPosition);
3991
+ const linesBeforeCursor = textBeforeCursor.split("\n");
3992
+ const currentLine = linesBeforeCursor[linesBeforeCursor.length - 1];
3993
+ const numberMatch = currentLine.match(/^(\s*)(\d+)\.\s(.*)/);
3994
+ if (numberMatch) {
3995
+ e.preventDefault();
3996
+ const space = numberMatch[1];
3997
+ const number = parseInt(numberMatch[2], 10);
3998
+ const content = numberMatch[3];
3999
+ if (content.trim() === "") {
4000
+ const newTextBeforeCursor = textBeforeCursor.substring(0, textBeforeCursor.length - currentLine.length);
4001
+ const newText = newTextBeforeCursor + "\n" + text.substring(el.selectionEnd);
4002
+ el.value = newText;
4003
+ el.setSelectionRange(newTextBeforeCursor.length + 1, newTextBeforeCursor.length + 1);
4004
+ setText(newText);
4005
+ return;
4006
+ }
4007
+ const nextNumber = number + 1;
4008
+ insertAtCursor(`
4009
+ ${space}${nextNumber}. `);
4010
+ return;
4011
+ }
4012
+ const checklistMatch = currentLine.match(/^(\s*)- \[[ xX]\]\s(.*)/);
4013
+ if (checklistMatch) {
4014
+ e.preventDefault();
4015
+ const space = checklistMatch[1];
4016
+ const content = checklistMatch[2];
4017
+ if (content.trim() === "") {
4018
+ const newTextBeforeCursor = textBeforeCursor.substring(0, textBeforeCursor.length - currentLine.length);
4019
+ const newText = newTextBeforeCursor + "\n" + text.substring(el.selectionEnd);
4020
+ el.value = newText;
4021
+ el.setSelectionRange(newTextBeforeCursor.length + 1, newTextBeforeCursor.length + 1);
4022
+ setText(newText);
4023
+ return;
4024
+ }
4025
+ insertAtCursor(`
4026
+ ${space}- [ ] `);
4027
+ return;
4028
+ }
4029
+ const bulletMatch = currentLine.match(/^(\s*)([-*])\s(.*)/);
4030
+ if (bulletMatch) {
4031
+ e.preventDefault();
4032
+ const space = bulletMatch[1];
4033
+ const bullet = bulletMatch[2];
4034
+ const content = bulletMatch[3];
4035
+ if (content.trim() === "") {
4036
+ const newTextBeforeCursor = textBeforeCursor.substring(0, textBeforeCursor.length - currentLine.length);
4037
+ const newText = newTextBeforeCursor + "\n" + text.substring(el.selectionEnd);
4038
+ el.value = newText;
4039
+ el.setSelectionRange(newTextBeforeCursor.length + 1, newTextBeforeCursor.length + 1);
4040
+ setText(newText);
4041
+ return;
4042
+ }
4043
+ insertAtCursor(`
4044
+ ${space}${bullet} `);
4045
+ return;
4046
+ }
4047
+ }
4048
+ };
3874
4049
  const openMentionModalViaButton = () => {
3875
4050
  setMentionTriggerIndex(null);
3876
4051
  setIsMentionModalOpen(true);
@@ -3880,7 +4055,8 @@ function DescriptionEditModal({
3880
4055
  return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement("div", { className: "fixed inset-0 z-[2000] flex justify-end pointer-events-none bg-transparent" }, /* @__PURE__ */ React5.createElement(
3881
4056
  "div",
3882
4057
  {
3883
- className: "ui-overlay pointer-events-auto relative group h-full w-[min(90vw,700px)] border-l border-white/10 bg-slate-950/95 shadow-2xl text-white flex flex-col",
4058
+ className: `ui-overlay pointer-events-auto relative group h-full border-l border-white/10 bg-slate-950/95 shadow-2xl text-white flex flex-col ${isResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
4059
+ style: { width: `${panelWidth}px`, maxWidth: "90vw" },
3884
4060
  onClick: swallow,
3885
4061
  onPointerDown: swallow,
3886
4062
  onPointerMove: swallow,
@@ -3889,13 +4065,24 @@ function DescriptionEditModal({
3889
4065
  onContextMenu: swallow,
3890
4066
  onDoubleClick: swallow
3891
4067
  },
4068
+ /* @__PURE__ */ React5.createElement(
4069
+ "div",
4070
+ {
4071
+ onPointerDown: (e) => {
4072
+ e.stopPropagation();
4073
+ handleResize(e);
4074
+ },
4075
+ className: "absolute left-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-indigo-500/50 z-[2000] transition-colors",
4076
+ title: "Arraste para redimensionar"
4077
+ }
4078
+ ),
3892
4079
  /* @__PURE__ */ React5.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0 shrink-0" }),
3893
4080
  /* @__PURE__ */ React5.createElement("div", { className: "px-6 pt-5 pb-3 flex items-center justify-between gap-4 shrink-0" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React5.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80" }), /* @__PURE__ */ React5.createElement("p", { className: "text-sm font-medium text-slate-200" }, title || "Editar Descri\xE7\xE3o")), /* @__PURE__ */ React5.createElement("button", { onClick: handleClose, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")),
3894
- /* @__PURE__ */ React5.createElement("div", { className: "px-6 py-3 flex flex-col gap-3 border-b border-white/5 bg-white/5 shrink-0" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 overflow-x-auto custom-scrollbar" }, /* @__PURE__ */ React5.createElement(
4081
+ /* @__PURE__ */ React5.createElement("div", { className: "px-6 py-3 flex flex-col gap-3 border-b border-white/5 bg-white/5 shrink-0" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 flex-wrap" }, /* @__PURE__ */ React5.createElement(
3895
4082
  "button",
3896
4083
  {
3897
4084
  onClick: () => insertAtCursor("# "),
3898
- className: "flex items-center gap-1 px-3 py-1.5 rounded bg-slate-800 hover:bg-slate-700 border border-white/10 text-xs font-medium transition-colors whitespace-nowrap",
4085
+ className: "flex items-center gap-1 px-3 py-1.5 rounded bg-indigo-600/30 hover:bg-indigo-600/50 border border-indigo-500/30 text-indigo-200 text-xs font-medium transition-colors whitespace-nowrap",
3899
4086
  title: "T\xEDtulo Principal"
3900
4087
  },
3901
4088
  /* @__PURE__ */ React5.createElement(FiType, { size: 12 }),
@@ -3904,7 +4091,7 @@ function DescriptionEditModal({
3904
4091
  "button",
3905
4092
  {
3906
4093
  onClick: () => insertAtCursor("## "),
3907
- className: "flex items-center gap-1 px-3 py-1.5 rounded bg-slate-800 hover:bg-slate-700 border border-white/10 text-xs font-medium transition-colors whitespace-nowrap",
4094
+ className: "flex items-center gap-1 px-3 py-1.5 rounded bg-indigo-600/30 hover:bg-indigo-600/50 border border-indigo-500/30 text-indigo-200 text-xs font-medium transition-colors whitespace-nowrap",
3908
4095
  title: "Subt\xEDtulo"
3909
4096
  },
3910
4097
  /* @__PURE__ */ React5.createElement(FiType, { size: 10 }),
@@ -3913,16 +4100,34 @@ function DescriptionEditModal({
3913
4100
  "button",
3914
4101
  {
3915
4102
  onClick: () => insertAtCursor("- "),
3916
- className: "flex items-center gap-1 px-3 py-1.5 rounded bg-slate-800 hover:bg-slate-700 border border-white/10 text-xs font-medium transition-colors whitespace-nowrap",
4103
+ className: "flex items-center gap-1 px-3 py-1.5 rounded bg-indigo-600/30 hover:bg-indigo-600/50 border border-indigo-500/30 text-indigo-200 text-xs font-medium transition-colors whitespace-nowrap",
3917
4104
  title: "Lista com bullets"
3918
4105
  },
3919
4106
  /* @__PURE__ */ React5.createElement(FiList, { size: 12 }),
3920
4107
  " Lista"
4108
+ ), /* @__PURE__ */ React5.createElement(
4109
+ "button",
4110
+ {
4111
+ onClick: () => insertAtCursor("1. "),
4112
+ className: "flex items-center gap-1 px-3 py-1.5 rounded bg-indigo-600/30 hover:bg-indigo-600/50 border border-indigo-500/30 text-indigo-200 text-xs font-medium transition-colors whitespace-nowrap",
4113
+ title: "Lista Numerada"
4114
+ },
4115
+ /* @__PURE__ */ React5.createElement("span", { className: "text-[10px] font-bold" }, "1."),
4116
+ " Numerada"
4117
+ ), /* @__PURE__ */ React5.createElement(
4118
+ "button",
4119
+ {
4120
+ onClick: () => insertAtCursor("- [ ] "),
4121
+ className: "flex items-center gap-1 px-3 py-1.5 rounded bg-indigo-600/30 hover:bg-indigo-600/50 border border-indigo-500/30 text-indigo-200 text-xs font-medium transition-colors whitespace-nowrap",
4122
+ title: "Checklist (Checkbox)"
4123
+ },
4124
+ /* @__PURE__ */ React5.createElement(FiCheckSquare, { size: 12 }),
4125
+ " Checklist"
3921
4126
  ), /* @__PURE__ */ React5.createElement(
3922
4127
  "button",
3923
4128
  {
3924
4129
  onClick: () => insertAtCursor("``` ```"),
3925
- className: "flex items-center gap-1 px-3 py-1.5 rounded bg-slate-800 hover:bg-slate-700 border border-white/10 text-xs font-medium transition-colors whitespace-nowrap",
4130
+ className: "flex items-center gap-1 px-3 py-1.5 rounded bg-indigo-600/30 hover:bg-indigo-600/50 border border-indigo-500/30 text-indigo-200 text-xs font-medium transition-colors whitespace-nowrap",
3926
4131
  title: "Inserir Code Block"
3927
4132
  },
3928
4133
  /* @__PURE__ */ React5.createElement(FiCode, { size: 12 }),
@@ -3931,21 +4136,21 @@ function DescriptionEditModal({
3931
4136
  "button",
3932
4137
  {
3933
4138
  onClick: () => insertAtCursor("[Link Texto](https://)"),
3934
- className: "flex items-center gap-1 px-3 py-1.5 rounded bg-slate-800 hover:bg-slate-700 border border-white/10 text-xs font-medium transition-colors whitespace-nowrap",
4139
+ className: "flex items-center gap-1 px-3 py-1.5 rounded bg-indigo-600/30 hover:bg-indigo-600/50 border border-indigo-500/30 text-indigo-200 text-xs font-medium transition-colors whitespace-nowrap",
3935
4140
  title: "Inserir Link Web [Texto](Url)"
3936
4141
  },
3937
4142
  /* @__PURE__ */ React5.createElement(FiGlobe, { size: 12 }),
3938
4143
  " Link"
3939
- ), /* @__PURE__ */ React5.createElement(
4144
+ )), /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 flex-wrap" }, /* @__PURE__ */ React5.createElement(
3940
4145
  "button",
3941
4146
  {
3942
4147
  onClick: () => setIsImageModalOpen(true),
3943
- className: "flex items-center gap-1 px-3 py-1.5 rounded bg-slate-800 hover:bg-slate-700 border border-white/10 text-xs font-medium transition-colors whitespace-nowrap",
4148
+ className: "flex items-center gap-1 px-3 py-1.5 rounded bg-indigo-600/30 hover:bg-indigo-600/50 border border-indigo-500/30 text-indigo-200 text-xs font-medium transition-colors whitespace-nowrap",
3944
4149
  title: "Inserir Imagem (Propriedade ou URL)"
3945
4150
  },
3946
4151
  /* @__PURE__ */ React5.createElement(FiImage, { size: 12 }),
3947
4152
  " Imagem"
3948
- )), /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 overflow-x-auto custom-scrollbar" }, /* @__PURE__ */ React5.createElement(
4153
+ ), /* @__PURE__ */ React5.createElement(
3949
4154
  "button",
3950
4155
  {
3951
4156
  onClick: openMentionModalViaButton,
@@ -3978,6 +4183,7 @@ function DescriptionEditModal({
3978
4183
  ref: textareaRef,
3979
4184
  value: text,
3980
4185
  onChange: handleTextChange,
4186
+ onKeyDown: handleKeyDownTextarea,
3981
4187
  placeholder: "Escreva aqui... Use *// para dividir o texto em 'Sess\xF5es'... Digite @ para mencionar...",
3982
4188
  autoFocus: true,
3983
4189
  className: "w-full flex-1 h-full bg-slate-800/70 p-4 text-sm leading-relaxed rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 custom-scrollbar font-mono resize-none"
@@ -4080,11 +4286,11 @@ function DescriptionEditModal({
4080
4286
  }
4081
4287
 
4082
4288
  // src/components/DescriptionDisplay.jsx
4083
- import React6, { useMemo as useMemo5, useState as useState6, useEffect as useEffect6, useRef as useRef6 } from "react";
4084
- import { FiCopy as FiCopy2, FiCheck as FiCheck3, FiChevronDown as FiChevronDown3, FiChevronRight as FiChevronRight2, FiTerminal as FiTerminal2, FiCornerDownRight, FiExternalLink as FiExternalLink2, FiImage as FiImage2 } from "react-icons/fi";
4289
+ import React6, { useMemo as useMemo5, useState as useState7, useEffect as useEffect6, useRef as useRef6 } from "react";
4290
+ import { FiCopy as FiCopy2, FiCheck as FiCheck3, FiChevronDown as FiChevronDown3, FiChevronRight as FiChevronRight2, FiTerminal as FiTerminal2, FiCornerDownRight, FiExternalLink as FiExternalLink2, FiImage as FiImage2, FiSave } from "react-icons/fi";
4085
4291
  var CodeBlock2 = ({ content, isActive, onClick }) => {
4086
- const [isExpanded, setIsExpanded] = useState6(false);
4087
- const [copied, setCopied] = useState6(false);
4292
+ const [isExpanded, setIsExpanded] = useState7(false);
4293
+ const [copied, setCopied] = useState7(false);
4088
4294
  const cleanContent = content.replace(/^```|```$/g, "").trim();
4089
4295
  const isLongCode = cleanContent.split("\n").length > 4;
4090
4296
  const handleCopy = (e) => {
@@ -4118,8 +4324,7 @@ var CodeBlock2 = ({ content, isActive, onClick }) => {
4118
4324
  "button",
4119
4325
  {
4120
4326
  onClick: handleCopy,
4121
- className: "flex items-center gap-1.5 px-2 py-1 rounded hover:bg-white/10 transition-colors text-xs text-slate-400 hover:text-white",
4122
- title: "Copiar c\xF3digo"
4327
+ className: "flex items-center gap-1.5 px-2 py-1 rounded hover:bg-white/10 transition-colors text-xs text-slate-400 hover:text-white"
4123
4328
  },
4124
4329
  copied ? /* @__PURE__ */ React6.createElement(FiCheck3, { size: 12, className: "text-emerald-400" }) : /* @__PURE__ */ React6.createElement(FiCopy2, { size: 12 }),
4125
4330
  copied ? /* @__PURE__ */ React6.createElement("span", { className: "text-emerald-400" }, "Copiado") : /* @__PURE__ */ React6.createElement("span", null, "Copiar")
@@ -4148,8 +4353,7 @@ var renderLinks = (text) => {
4148
4353
  target: "_blank",
4149
4354
  rel: "noopener noreferrer",
4150
4355
  className: "inline-flex items-center gap-0.5 text-cyan-400 hover:text-cyan-300 hover:underline decoration-cyan-500/50 underline-offset-2 transition-colors cursor-pointer",
4151
- onClick: (e) => e.stopPropagation(),
4152
- title: `Abrir link externo: ${url}`
4356
+ onClick: (e) => e.stopPropagation()
4153
4357
  },
4154
4358
  part,
4155
4359
  /* @__PURE__ */ React6.createElement(FiExternalLink2, { size: 10, className: "opacity-70 mb-0.5" })
@@ -4178,8 +4382,7 @@ var renderTextWithImages = (text, onImageClick) => {
4178
4382
  e.stopPropagation();
4179
4383
  onImageClick == null ? void 0 : onImageClick(url, name);
4180
4384
  },
4181
- className: "inline-flex items-center gap-1 text-emerald-400 hover:text-emerald-300 hover:underline decoration-emerald-500/50 underline-offset-2 transition-colors cursor-pointer align-baseline mx-0.5",
4182
- title: `Ver imagem: ${name}`
4385
+ className: "inline-flex items-center gap-1 text-emerald-400 hover:text-emerald-300 hover:underline decoration-emerald-500/50 underline-offset-2 transition-colors cursor-pointer align-baseline mx-0.5"
4183
4386
  },
4184
4387
  /* @__PURE__ */ React6.createElement(FiImage2, { size: 11 }),
4185
4388
  /* @__PURE__ */ React6.createElement("span", null, name)
@@ -4199,7 +4402,18 @@ var renderTextWithMentions = (text, availableNodes, onMentionClick, activeMentio
4199
4402
  }
4200
4403
  const nodeId = part;
4201
4404
  const node = availableNodes.find((n) => String(n.id) === String(nodeId));
4202
- if (!node) return null;
4405
+ if (!node) {
4406
+ return /* @__PURE__ */ React6.createElement(
4407
+ "span",
4408
+ {
4409
+ key: i,
4410
+ className: "inline-flex items-center gap-0.5 align-baseline font-medium px-1.5 rounded-md mx-0.5 select-none text-[0.95em] text-slate-400 bg-slate-800/40 border border-slate-600/50 border-dashed cursor-help",
4411
+ title: `Node externo ou n\xE3o carregado na view atual (ID: ${nodeId})`
4412
+ },
4413
+ /* @__PURE__ */ React6.createElement("span", { className: "opacity-60 text-[0.8em]" }, "@"),
4414
+ "Desconhecido"
4415
+ );
4416
+ }
4203
4417
  const displayName = node.name;
4204
4418
  const currentMentionIdx = mentionCounterRef.current;
4205
4419
  const isMentionActive = activeMentionIndex === currentMentionIdx;
@@ -4216,15 +4430,14 @@ var renderTextWithMentions = (text, availableNodes, onMentionClick, activeMentio
4216
4430
  className: `
4217
4431
  inline-flex items-center gap-0.5 align-baseline font-medium px-1.5 rounded-md mx-0.5 select-none transition-all cursor-pointer text-[0.95em]
4218
4432
  ${isMentionActive ? "text-white bg-indigo-500 ring-2 ring-yellow-400 shadow-[0_0_10px_rgba(250,204,21,0.5)] z-10 relative" : "text-indigo-200 bg-indigo-600/30 border border-indigo-500/30 hover:bg-indigo-600/50 hover:text-white"}
4219
- `,
4220
- title: `Clique para focar no Node: ${displayName}`
4433
+ `
4221
4434
  },
4222
4435
  /* @__PURE__ */ React6.createElement("span", { className: "opacity-60 text-[0.8em]" }, "@"),
4223
4436
  displayName
4224
4437
  );
4225
4438
  });
4226
4439
  };
4227
- var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick) => {
4440
+ var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick, onToggleCheckbox, globalCheckboxCounterRef) => {
4228
4441
  const trimmedLine = line.replace(/\r$/, "");
4229
4442
  const processContent = (content) => renderTextWithMentions(content, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick);
4230
4443
  if (line.startsWith("# ")) {
@@ -4235,9 +4448,46 @@ var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionInd
4235
4448
  const content = line.replace("## ", "");
4236
4449
  return /* @__PURE__ */ React6.createElement("span", { className: "text-sm sm:text-base font-semibold text-indigo-200 leading-tight break-words" }, processContent(content));
4237
4450
  }
4451
+ const checkboxMatch = trimmedLine.match(/^(\s*)- \[([ xX])\]\s+(.*)/);
4452
+ if (checkboxMatch) {
4453
+ const [_, space, state, content] = checkboxMatch;
4454
+ const isChecked = state.toLowerCase() === "x";
4455
+ const currentIdx = globalCheckboxCounterRef.current;
4456
+ globalCheckboxCounterRef.current += 1;
4457
+ return /* @__PURE__ */ React6.createElement("span", { className: "flex items-start gap-2.5 my-1 break-words ml-1 group/checkbox" }, /* @__PURE__ */ React6.createElement(
4458
+ "div",
4459
+ {
4460
+ onClick: (e) => {
4461
+ e.stopPropagation();
4462
+ if (onToggleCheckbox) onToggleCheckbox(currentIdx);
4463
+ },
4464
+ className: `mt-1 cursor-pointer w-4 h-4 rounded border flex-shrink-0 flex items-center justify-center transition-all duration-200
4465
+ ${isChecked ? "bg-indigo-500 border-indigo-500 shadow-[0_0_8px_rgba(99,102,241,0.4)]" : "border-slate-500 bg-slate-900/50 hover:border-slate-400 group-hover/checkbox:border-slate-400"}
4466
+ `
4467
+ },
4468
+ isChecked && /* @__PURE__ */ React6.createElement(FiCheck3, { size: 12, className: "text-white" })
4469
+ ), /* @__PURE__ */ React6.createElement(
4470
+ "span",
4471
+ {
4472
+ className: `transition-all duration-200 cursor-pointer pt-[1px]
4473
+ ${isChecked ? "line-through text-slate-500" : "text-slate-200 group-hover/checkbox:text-white"}
4474
+ `,
4475
+ onClick: (e) => {
4476
+ e.stopPropagation();
4477
+ if (onToggleCheckbox) onToggleCheckbox(currentIdx);
4478
+ }
4479
+ },
4480
+ processContent(content)
4481
+ ));
4482
+ }
4483
+ const numberMatch = trimmedLine.match(/^(\s*)(\d+\.)\s+(.*)/);
4484
+ if (numberMatch) {
4485
+ const [_, space, numberStr, content] = numberMatch;
4486
+ return /* @__PURE__ */ React6.createElement("span", { className: "flex items-start gap-2 my-0.5 break-words ml-1" }, /* @__PURE__ */ React6.createElement("span", { className: "text-indigo-400 font-mono font-bold text-xs mt-[3px] shrink-0" }, numberStr), /* @__PURE__ */ React6.createElement("span", { className: "text-slate-200" }, processContent(content)));
4487
+ }
4238
4488
  if (trimmedLine.trim().startsWith("- ") || trimmedLine.trim().startsWith("* ")) {
4239
4489
  const content = trimmedLine.trim().substring(2);
4240
- return /* @__PURE__ */ React6.createElement("span", { className: "pl-2 text-slate-200 break-words" }, /* @__PURE__ */ React6.createElement("span", { className: "text-indigo-400 font-bold mr-1.5" }, "\u2022"), processContent(content));
4490
+ return /* @__PURE__ */ React6.createElement("span", { className: "flex items-start gap-2 my-0.5 break-words ml-1 text-slate-200" }, /* @__PURE__ */ React6.createElement("span", { className: "text-indigo-400 font-bold shrink-0 mt-[2px] text-xs" }, "\u2022"), /* @__PURE__ */ React6.createElement("span", null, processContent(content)));
4241
4491
  }
4242
4492
  return /* @__PURE__ */ React6.createElement("span", { className: "break-words" }, processContent(line));
4243
4493
  };
@@ -4249,14 +4499,33 @@ function DescriptionDisplay({
4249
4499
  onOpenReference,
4250
4500
  onMentionClick,
4251
4501
  onImageClick,
4252
- // <--- NOVA PROP RECEBIDA
4253
4502
  onSectionChange,
4254
4503
  onBranchNav,
4255
4504
  onHighlightNode,
4256
4505
  initialSectionId,
4257
- currentBranchDirection = null
4506
+ currentBranchDirection = null,
4507
+ onSaveDescription,
4508
+ onStepChange
4509
+ // 1. Adicione a nova prop aqui
4258
4510
  }) {
4259
- const sections = useMemo5(() => parseDescriptionSections(description, savedSections), [description, savedSections]);
4511
+ const [localDescription, setLocalDescription] = useState7(description || "");
4512
+ useEffect6(() => {
4513
+ setLocalDescription(description || "");
4514
+ }, [description]);
4515
+ const sections = useMemo5(() => parseDescriptionSections(localDescription, savedSections), [localDescription, savedSections]);
4516
+ const globalCheckboxCounterRef = useRef6(0);
4517
+ const handleToggleCheckbox = (targetIndex) => {
4518
+ let currentIndex = 0;
4519
+ const newDesc = localDescription.replace(/^(\s*)- \[([ xX])\]/gm, (match, space, state) => {
4520
+ if (currentIndex === targetIndex) {
4521
+ currentIndex++;
4522
+ return state === " " ? `${space}- [x]` : `${space}- [ ]`;
4523
+ }
4524
+ currentIndex++;
4525
+ return match;
4526
+ });
4527
+ setLocalDescription(newDesc);
4528
+ };
4260
4529
  const flatNavigation = useMemo5(() => {
4261
4530
  const navItems = [];
4262
4531
  sections.forEach((section, sIdx) => {
@@ -4283,7 +4552,12 @@ function DescriptionDisplay({
4283
4552
  });
4284
4553
  return navItems;
4285
4554
  }, [sections]);
4286
- const [currentStepIndex, setCurrentStepIndex] = useState6(0);
4555
+ const [currentStepIndex, setCurrentStepIndex] = useState7(0);
4556
+ useEffect6(() => {
4557
+ if (onStepChange) {
4558
+ onStepChange(currentStepIndex);
4559
+ }
4560
+ }, [currentStepIndex, onStepChange]);
4287
4561
  const activeRef = useRef6(null);
4288
4562
  const lastNotifiedSectionId = useRef6(null);
4289
4563
  const isInitialMount = useRef6(true);
@@ -4397,26 +4671,27 @@ function DescriptionDisplay({
4397
4671
  }
4398
4672
  const lines = part.replace(/\n$/, "").split("\n");
4399
4673
  return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: `text-${parentIndex}-${partIndex}` }, lines.map((line, lineIndex) => {
4400
- const isLastLine = lineIndex === lines.length - 1;
4401
4674
  const isEmptyLine = line.trim() === "";
4402
4675
  if (isEmptyLine) {
4403
4676
  return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: `${parentIndex}-${partIndex}-${lineIndex}` }, /* @__PURE__ */ React6.createElement("br", null));
4404
4677
  }
4405
4678
  return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: `${parentIndex}-${partIndex}-${lineIndex}` }, /* @__PURE__ */ React6.createElement(
4406
- "span",
4679
+ "div",
4407
4680
  {
4408
4681
  ref: isActiveSection && activeMentionIndex === -1 && partIndex === 0 && lineIndex === 0 ? setRef : null,
4409
- onClick: () => {
4410
- const idx = flatNavigation.findIndex((item) => item.type === "section" && item.sectionIndex === parentIndex);
4411
- if (idx !== -1) setCurrentStepIndex(idx);
4682
+ onClick: (e) => {
4683
+ if (e.target.type !== "checkbox") {
4684
+ const idx = flatNavigation.findIndex((item) => item.type === "section" && item.sectionIndex === parentIndex);
4685
+ if (idx !== -1) setCurrentStepIndex(idx);
4686
+ }
4412
4687
  },
4413
4688
  className: `
4414
- transition-colors duration-200 cursor-pointer rounded-md px-1 py-0.5 -mx-1 box-decoration-clone
4415
- ${isActiveSection ? "bg-indigo-500/20 text-white ring-1 ring-indigo-500/30" : "hover:bg-white/5 hover:text-slate-200"}
4689
+ transition-colors duration-200 cursor-pointer rounded-md px-1 py-0.5 -mx-1 box-decoration-clone inline-block w-full
4690
+ ${isActiveSection ? "bg-indigo-500/10 text-white ring-1 ring-indigo-500/30" : "hover:bg-white/5 hover:text-slate-200"}
4416
4691
  `
4417
4692
  },
4418
- formatLineContent2(line, availableNodes, onMentionClick, isActiveSection ? activeMentionIndex : -1, mentionCounterRef, setRef, onImageClick)
4419
- ), !isLastLine && /* @__PURE__ */ React6.createElement("br", null));
4693
+ formatLineContent2(line, availableNodes, onMentionClick, isActiveSection ? activeMentionIndex : -1, mentionCounterRef, setRef, onImageClick, handleToggleCheckbox, globalCheckboxCounterRef)
4694
+ ));
4420
4695
  }));
4421
4696
  });
4422
4697
  };
@@ -4434,8 +4709,7 @@ function DescriptionDisplay({
4434
4709
  if (onOpenReference) {
4435
4710
  onOpenReference({ type: resolved.type, id: resolved.sourceId });
4436
4711
  }
4437
- },
4438
- title: `Ir para ${resolved.type === "node" ? "Node" : "Ancestralidade"}: ${resolved.sourceName}`
4712
+ }
4439
4713
  },
4440
4714
  /* @__PURE__ */ React6.createElement(FiCornerDownRight, { size: 12, className: "text-indigo-400" }),
4441
4715
  /* @__PURE__ */ React6.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wide flex items-center gap-1" }, "Importado de ", /* @__PURE__ */ React6.createElement("span", { className: "font-semibold text-indigo-300 hover:underline" }, resolved.sourceName), /* @__PURE__ */ React6.createElement(FiExternalLink2, { size: 10, className: "text-slate-600" }))
@@ -4444,7 +4718,9 @@ function DescriptionDisplay({
4444
4718
  ${isActiveSection ? "opacity-100" : "opacity-90"}
4445
4719
  ` }, renderMixedContent(resolved.content, index, isActiveSection, -1, setRef)));
4446
4720
  };
4447
- return /* @__PURE__ */ React6.createElement("div", { className: "w-full text-sm leading-relaxed text-slate-300 break-words whitespace-pre-wrap px-3 pt-1 pb-2 pr-9" }, sections.map((section, index) => {
4721
+ globalCheckboxCounterRef.current = 0;
4722
+ const hasUnsavedChanges = localDescription !== (description || "");
4723
+ return /* @__PURE__ */ React6.createElement("div", { className: "relative w-full h-full min-h-[100px]" }, /* @__PURE__ */ React6.createElement("div", { className: "w-full text-sm leading-relaxed text-slate-300 break-words whitespace-pre-wrap px-3 pt-1 pb-16 pr-9" }, sections.map((section, index) => {
4448
4724
  const currentNavItem = flatNavigation[currentStepIndex];
4449
4725
  const isSectionContextActive = currentNavItem && currentNavItem.sectionIndex === index;
4450
4726
  const activeMentionIndex = isSectionContextActive && currentNavItem.type === "mention" ? currentNavItem.mentionIndex : -1;
@@ -4460,11 +4736,22 @@ function DescriptionDisplay({
4460
4736
  if (index === 0) leadingSpace = "";
4461
4737
  const isRef = bodyText.trim().match(/^\[\[REF:(node|ancestry):([a-zA-Z0-9\-_]+):([a-zA-Z0-9\-_]+)\]\]$/);
4462
4738
  return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: index }, /* @__PURE__ */ React6.createElement("span", null, leadingSpace), isRef ? renderReferenceSection(bodyText, index, isSectionContextActive, setRef) : renderMixedContent(bodyText, index, isSectionContextActive, activeMentionIndex, setRef), /* @__PURE__ */ React6.createElement("span", null, trailingSpace));
4463
- }));
4739
+ })), hasUnsavedChanges && onSaveDescription && /* @__PURE__ */ React6.createElement("div", { className: "absolute bottom-2 left-2 z-[100] animate-in slide-in-from-bottom-2 fade-in duration-300" }, /* @__PURE__ */ React6.createElement(
4740
+ "button",
4741
+ {
4742
+ onClick: (e) => {
4743
+ e.stopPropagation();
4744
+ onSaveDescription(localDescription);
4745
+ },
4746
+ className: "flex items-center gap-1.5 px-3 py-1.5 bg-indigo-600/90 hover:bg-indigo-500 text-white rounded-md shadow-[0_4px_12px_rgba(99,102,241,0.3)] text-xs font-medium transition-all hover:scale-105 active:scale-95 border border-indigo-400/20 backdrop-blur-sm"
4747
+ },
4748
+ /* @__PURE__ */ React6.createElement(FiSave, { size: 12 }),
4749
+ " Salvar Checklist"
4750
+ )));
4464
4751
  }
4465
4752
 
4466
4753
  // src/components/DescriptionReadModePanel.jsx
4467
- import React7, { useState as useState7, useMemo as useMemo6, useEffect as useEffect7 } from "react";
4754
+ import React7, { useState as useState8, useMemo as useMemo6, useEffect as useEffect7 } from "react";
4468
4755
  import {
4469
4756
  FiArrowLeft,
4470
4757
  FiEdit2,
@@ -4543,7 +4830,6 @@ function DescriptionReadModePanel({
4543
4830
  title,
4544
4831
  description,
4545
4832
  ancestryId,
4546
- // <-- NOVO: Prop recebida do XViewScene
4547
4833
  savedSections,
4548
4834
  onBack,
4549
4835
  onEdit,
@@ -4565,12 +4851,14 @@ function DescriptionReadModePanel({
4565
4851
  userRole,
4566
4852
  abstractionTree = null,
4567
4853
  onRenderAbstractionTree = null,
4568
- initialShowAbstraction = false
4854
+ initialShowAbstraction = false,
4855
+ onSaveDescription
4569
4856
  }) {
4570
- const [showProperties, setShowProperties] = useState7(false);
4571
- const [showAbstraction, setShowAbstraction] = useState7(false);
4572
- const [targetRenderNodeId, setTargetRenderNodeId] = useState7(null);
4573
- const [isLinkCopied, setIsLinkCopied] = useState7(false);
4857
+ const [showProperties, setShowProperties] = useState8(false);
4858
+ const [showAbstraction, setShowAbstraction] = useState8(false);
4859
+ const [targetRenderNodeId, setTargetRenderNodeId] = useState8(null);
4860
+ const [isLinkCopied, setIsLinkCopied] = useState8(false);
4861
+ const [isAtStartOfBranch, setIsAtStartOfBranch] = useState8(true);
4574
4862
  const handleCopyLink = (e) => {
4575
4863
  e.stopPropagation();
4576
4864
  if (!ancestryId) return;
@@ -4623,7 +4911,7 @@ function DescriptionReadModePanel({
4623
4911
  onClick: () => onBranchNav(activeNodeBranches.nodeId, "open", "left")
4624
4912
  };
4625
4913
  }
4626
- if ((backNavigationInfo == null ? void 0 : backNavigationInfo.trigger) === "left") {
4914
+ if ((backNavigationInfo == null ? void 0 : backNavigationInfo.trigger) === "left" && isAtStartOfBranch) {
4627
4915
  return {
4628
4916
  type: "back",
4629
4917
  name: backNavigationInfo.name,
@@ -4631,7 +4919,7 @@ function DescriptionReadModePanel({
4631
4919
  };
4632
4920
  }
4633
4921
  return null;
4634
- }, [activeNodeBranches, backNavigationInfo, onBranchNav]);
4922
+ }, [activeNodeBranches, backNavigationInfo, onBranchNav, isAtStartOfBranch]);
4635
4923
  const rightAction = useMemo6(() => {
4636
4924
  if (activeNodeBranches == null ? void 0 : activeNodeBranches.right) {
4637
4925
  return {
@@ -4640,7 +4928,7 @@ function DescriptionReadModePanel({
4640
4928
  onClick: () => onBranchNav(activeNodeBranches.nodeId, "open", "right")
4641
4929
  };
4642
4930
  }
4643
- if ((backNavigationInfo == null ? void 0 : backNavigationInfo.trigger) === "right") {
4931
+ if ((backNavigationInfo == null ? void 0 : backNavigationInfo.trigger) === "right" && isAtStartOfBranch) {
4644
4932
  return {
4645
4933
  type: "back",
4646
4934
  name: backNavigationInfo.name,
@@ -4648,11 +4936,11 @@ function DescriptionReadModePanel({
4648
4936
  };
4649
4937
  }
4650
4938
  return null;
4651
- }, [activeNodeBranches, backNavigationInfo, onBranchNav]);
4939
+ }, [activeNodeBranches, backNavigationInfo, onBranchNav, isAtStartOfBranch]);
4652
4940
  return /* @__PURE__ */ React7.createElement(
4653
4941
  "div",
4654
4942
  {
4655
- className: "flex flex-col h-full w-full bg-slate-950/50 relative overflow-hidden group",
4943
+ className: "flex flex-col h-full max-h-full w-full bg-slate-950/50 relative overflow-hidden group min-h-0",
4656
4944
  onPointerDown: swallow,
4657
4945
  onClick: swallow
4658
4946
  },
@@ -4724,7 +5012,7 @@ function DescriptionReadModePanel({
4724
5012
  },
4725
5013
  "\xD7"
4726
5014
  ))),
4727
- /* @__PURE__ */ React7.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 bg-slate-900/20 relative z-10", onClick: () => setTargetRenderNodeId(null) }, showAbstraction ? /* @__PURE__ */ React7.createElement("div", { className: "space-y-4 animate-in fade-in slide-in-from-bottom-2 duration-300", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-4" }, /* @__PURE__ */ React7.createElement("h3", { className: "text-sm font-semibold text-purple-300 uppercase tracking-wider" }, "Explorar Hierarquia"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-wrap gap-2" }, targetRenderNodeId && onRenderAbstractionTree && /* @__PURE__ */ React7.createElement(
5015
+ /* @__PURE__ */ React7.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 bg-slate-900/20 relative z-10 min-h-0", onClick: () => setTargetRenderNodeId(null) }, showAbstraction ? /* @__PURE__ */ React7.createElement("div", { className: "space-y-4 animate-in fade-in slide-in-from-bottom-2 duration-300", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-4" }, /* @__PURE__ */ React7.createElement("h3", { className: "text-sm font-semibold text-purple-300 uppercase tracking-wider" }, "Explorar Hierarquia"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-wrap gap-2" }, targetRenderNodeId && onRenderAbstractionTree && /* @__PURE__ */ React7.createElement(
4728
5016
  "button",
4729
5017
  {
4730
5018
  onClick: (e) => {
@@ -4783,7 +5071,9 @@ function DescriptionReadModePanel({
4783
5071
  onHighlightNode,
4784
5072
  initialSectionId,
4785
5073
  currentBranchDirection,
4786
- onImageClick
5074
+ onImageClick,
5075
+ onSaveDescription,
5076
+ onStepChange: (stepIndex) => setIsAtStartOfBranch(stepIndex === 0)
4787
5077
  }
4788
5078
  )),
4789
5079
  leftAction && !showAbstraction && !showProperties && /* @__PURE__ */ React7.createElement(
@@ -4825,11 +5115,11 @@ function AncestryRelationshipPanel({
4825
5115
  onMentionClick,
4826
5116
  onUploadFile
4827
5117
  }) {
4828
- const [description, setDescription] = useState8((data == null ? void 0 : data.description) ?? "");
4829
- const [customProps, setCustomProps] = useState8(() => extractCustomPropsFromNode(data || {}));
4830
- const [existingSections, setExistingSections] = useState8((data == null ? void 0 : data.description_sections) || []);
4831
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState8(false);
4832
- const [isReadMode, setIsReadMode] = useState8(false);
5118
+ const [description, setDescription] = useState9((data == null ? void 0 : data.description) ?? "");
5119
+ const [customProps, setCustomProps] = useState9(() => extractCustomPropsFromNode(data || {}));
5120
+ const [existingSections, setExistingSections] = useState9((data == null ? void 0 : data.description_sections) || []);
5121
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState9(false);
5122
+ const [isReadMode, setIsReadMode] = useState9(false);
4833
5123
  const propsEndRef = useRef7(null);
4834
5124
  useEffect8(() => {
4835
5125
  setDescription((data == null ? void 0 : data.description) ?? "");
@@ -4853,6 +5143,17 @@ function AncestryRelationshipPanel({
4853
5143
  return newProps;
4854
5144
  });
4855
5145
  };
5146
+ const handleSaveDescriptionInline = (newDescription) => {
5147
+ setDescription(newDescription);
5148
+ const extrasObj = toObjectFromCustomProps(customProps.filter((p) => !p.isEditing));
5149
+ const processedSections = processDescriptionForSave(newDescription, existingSections);
5150
+ const dataToSave = {
5151
+ description: newDescription,
5152
+ description_sections: processedSections,
5153
+ ...extrasObj
5154
+ };
5155
+ onSave(dataToSave);
5156
+ };
4856
5157
  const handleSave = () => {
4857
5158
  const extrasObj = toObjectFromCustomProps(customProps.filter((p) => !p.isEditing));
4858
5159
  const processedSections = processDescriptionForSave(description, existingSections);
@@ -4902,7 +5203,8 @@ function AncestryRelationshipPanel({
4902
5203
  availableAncestries,
4903
5204
  onOpenReference,
4904
5205
  onMentionClick,
4905
- onImageClick: handleImageClickFromText
5206
+ onImageClick: handleImageClickFromText,
5207
+ onSaveDescription: handleSaveDescriptionInline
4906
5208
  }
4907
5209
  ) : /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement("div", { className: "h-[2px] bg-gradient-to-r from-cyan-400/0 via-cyan-400/70 to-cyan-400/0" }), /* @__PURE__ */ React8.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React8.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-cyan-400/80 shadow-[0_0_18px_2px_rgba(45,212,191,0.55)]" }), /* @__PURE__ */ React8.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Rela\xE7\xE3o de Ancestralidade")), /* @__PURE__ */ React8.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, "Editar Rela\xE7\xE3o")), /* @__PURE__ */ React8.createElement("button", { onClick: onClose, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")), /* @__PURE__ */ React8.createElement("div", { className: "px-6 pb-4 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ React8.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React8.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o da Rela\xE7\xE3o"), /* @__PURE__ */ React8.createElement("div", { className: "relative group min-h-[60px] bg-slate-800/40 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ React8.createElement(
4908
5210
  DescriptionDisplay,
@@ -4913,7 +5215,8 @@ function AncestryRelationshipPanel({
4913
5215
  availableAncestries,
4914
5216
  onOpenReference,
4915
5217
  onMentionClick,
4916
- onImageClick: handleImageClickFromText
5218
+ onImageClick: handleImageClickFromText,
5219
+ onSaveDescription: handleSaveDescriptionInline
4917
5220
  }
4918
5221
  ), /* @__PURE__ */ React8.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ React8.createElement(
4919
5222
  "button",
@@ -4971,7 +5274,7 @@ function AncestryRelationshipPanel({
4971
5274
  }
4972
5275
 
4973
5276
  // src/components/CreateAncestryPanel.jsx
4974
- import React10, { useState as useState10, useEffect as useEffect10, useMemo as useMemo8, useRef as useRef8, useCallback } from "react";
5277
+ import React10, { useState as useState11, useEffect as useEffect10, useMemo as useMemo8, useRef as useRef8, useCallback as useCallback2 } from "react";
4975
5278
  import {
4976
5279
  FiEdit2 as FiEdit23,
4977
5280
  FiBookOpen as FiBookOpen2,
@@ -4987,11 +5290,12 @@ import {
4987
5290
  FiGitBranch as FiGitBranch2,
4988
5291
  FiPlus as FiPlus2,
4989
5292
  FiLock,
4990
- FiLink as FiLink4
5293
+ FiLink as FiLink4,
5294
+ FiTrash2 as FiTrash22
4991
5295
  } from "react-icons/fi";
4992
5296
 
4993
5297
  // src/components/AncestryPickerModal.jsx
4994
- import React9, { useState as useState9, useMemo as useMemo7, useEffect as useEffect9 } from "react";
5298
+ import React9, { useState as useState10, useMemo as useMemo7, useEffect as useEffect9 } from "react";
4995
5299
  import { FiSearch as FiSearch3, FiLayers as FiLayers4, FiCornerUpRight as FiCornerUpRight2 } from "react-icons/fi";
4996
5300
  function AncestryPickerModal({
4997
5301
  isOpen,
@@ -5001,7 +5305,7 @@ function AncestryPickerModal({
5001
5305
  availableNodes = [],
5002
5306
  currentAncestryId
5003
5307
  }) {
5004
- const [searchTerm, setSearchTerm] = useState9("");
5308
+ const [searchTerm, setSearchTerm] = useState10("");
5005
5309
  useEffect9(() => {
5006
5310
  if (!isOpen) return;
5007
5311
  const handleKeyDown = (e) => {
@@ -5086,7 +5390,7 @@ var NodeItem = ({ nodeData, onSelectParent, onViewSelect, highlightedPathIds = [
5086
5390
  var _a, _b;
5087
5391
  const itemId = nodeData.is_section ? nodeData.id : (_a = nodeData.node) == null ? void 0 : _a.id;
5088
5392
  const itemName = nodeData.is_section ? nodeData.name : (_b = nodeData.node) == null ? void 0 : _b.name;
5089
- const [isDragOver, setIsDragOver] = useState10(false);
5393
+ const [isDragOver, setIsDragOver] = useState11(false);
5090
5394
  const isSelectedParent = String(selectedParentId) === String(itemId);
5091
5395
  const isTargetViewNode = String(targetRenderNodeId) === String(itemId);
5092
5396
  const isHighlightedPath = highlightedPathIds.includes(String(itemId));
@@ -5222,8 +5526,9 @@ function CreateAncestryPanel({
5222
5526
  isAddingNodes,
5223
5527
  currentAncestryId
5224
5528
  } = ancestryMode;
5225
- const [isSaving, setIsSaving] = useState10(false);
5226
- const [isLinkCopied, setIsLinkCopied] = useState10(false);
5529
+ const [isSaving, setIsSaving] = useState11(false);
5530
+ const [isLinkCopied, setIsLinkCopied] = useState11(false);
5531
+ const [showDeleteBranchConfirm, setShowDeleteBranchConfirm] = useState11(false);
5227
5532
  const handleCopyLink = (e) => {
5228
5533
  e.stopPropagation();
5229
5534
  if (!currentAncestryId || currentAncestryId === "temp_root" || currentAncestryId === "temp_creating") {
@@ -5237,11 +5542,14 @@ function CreateAncestryPanel({
5237
5542
  setTimeout(() => setIsLinkCopied(false), 2e3);
5238
5543
  }).catch((err) => console.error("Erro ao copiar link:", err));
5239
5544
  };
5240
- const [isPickerOpen, setIsPickerOpen] = useState10(false);
5241
- const [customProps, setCustomProps] = useState10([]);
5545
+ const [isPickerOpen, setIsPickerOpen] = useState11(false);
5546
+ const [customProps, setCustomProps] = useState11([]);
5242
5547
  const propsEndRef = useRef8(null);
5243
- const [branchStack, setBranchStack] = useState10([]);
5244
- const [targetRenderNodeId, setTargetRenderNodeId] = useState10(null);
5548
+ const [branchStack, setBranchStack] = useState11([]);
5549
+ useEffect10(() => {
5550
+ setShowDeleteBranchConfirm(false);
5551
+ }, [branchStack]);
5552
+ const [targetRenderNodeId, setTargetRenderNodeId] = useState11(null);
5245
5553
  const highlightedPathIds = useMemo8(() => {
5246
5554
  var _a, _b;
5247
5555
  if (!targetRenderNodeId || !ancestryMode.abstraction_tree) return [];
@@ -5255,17 +5563,27 @@ function CreateAncestryPanel({
5255
5563
  }
5256
5564
  return ids;
5257
5565
  }, [targetRenderNodeId, ancestryMode.abstraction_tree]);
5258
- const [targetScrollSectionId, setTargetScrollSectionId] = useState10(null);
5259
- const [internalHighlightedNodeId, setInternalHighlightedNodeId] = useState10(null);
5260
- const [ancestryName, setAncestryName] = useState10(initialName);
5261
- const [description, setDescription] = useState10(initialDescription || "");
5262
- const [existingSections, setExistingSections] = useState10(initialSections || []);
5263
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState10(false);
5264
- const [isReadMode, setIsReadMode] = useState10(false);
5566
+ const [targetScrollSectionId, setTargetScrollSectionId] = useState11(null);
5567
+ const [internalHighlightedNodeId, setInternalHighlightedNodeId] = useState11(null);
5568
+ const [isAtStartOfBranch, setIsAtStartOfBranch] = useState11(true);
5569
+ const [ancestryName, setAncestryName] = useState11(initialName);
5570
+ const [description, setDescription] = useState11(initialDescription || "");
5571
+ const [existingSections, setExistingSections] = useState11(initialSections || []);
5572
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState11(false);
5573
+ const [isReadMode, setIsReadMode] = useState11(false);
5574
+ const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
5575
+ const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
5576
+ initialWidth: isReadMode ? 700 : 440,
5577
+ minWidth: 320,
5578
+ maxWidth: maxPanelW
5579
+ });
5580
+ useEffect10(() => {
5581
+ setWidth(isReadMode ? 700 : 440);
5582
+ }, [isReadMode, setWidth]);
5265
5583
  const currentMaxRenderIndexRef = useRef8(0);
5266
5584
  const branchProgressMapRef = useRef8({});
5267
- const [lastSavedSnapshot, setLastSavedSnapshot] = useState10(null);
5268
- const [isPrivate, setIsPrivate] = useState10(ancestryMode.is_private || false);
5585
+ const [lastSavedSnapshot, setLastSavedSnapshot] = useState11(null);
5586
+ const [isPrivate, setIsPrivate] = useState11(ancestryMode.is_private || false);
5269
5587
  const initializedContextIdRef = useRef8(null);
5270
5588
  const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
5271
5589
  const handleImageClickFromText = (url, name) => {
@@ -5284,7 +5602,7 @@ function CreateAncestryPanel({
5284
5602
  }
5285
5603
  setAncestryMode((prev) => isAbstraction ? { ...prev, isAddingAbstractionNodes: !prev.isAddingAbstractionNodes } : { ...prev, isAddingNodes: !prev.isAddingNodes });
5286
5604
  };
5287
- const handleRemoveNode = useCallback((pathToRemove, isAbstraction = false) => {
5605
+ const handleRemoveNode = useCallback2((pathToRemove, isAbstraction = false) => {
5288
5606
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) return;
5289
5607
  const treeKey = isAbstraction ? "abstraction_tree" : "tree";
5290
5608
  setAncestryMode((prev) => {
@@ -5641,6 +5959,59 @@ function CreateAncestryPanel({
5641
5959
  }
5642
5960
  }
5643
5961
  };
5962
+ const handleDeleteBranch = async () => {
5963
+ if (branchStack.length === 0) return;
5964
+ const rootTreeClone = JSON.parse(JSON.stringify(ancestryMode.tree));
5965
+ let ptr = rootTreeClone;
5966
+ for (let i = 0; i < branchStack.length - 1; i++) {
5967
+ const step = branchStack[i];
5968
+ const found = findNodePath2(ptr, step.nodeId);
5969
+ if (found && found.node.parallel_branches) {
5970
+ const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5971
+ if (branch) ptr = branch.tree;
5972
+ }
5973
+ }
5974
+ const currentStep = branchStack[branchStack.length - 1];
5975
+ const foundParentPath = findNodePath2(ptr, currentStep.nodeId);
5976
+ if (foundParentPath && foundParentPath.node && foundParentPath.node.parallel_branches) {
5977
+ const branchIndex = foundParentPath.node.parallel_branches.findIndex((b) => b.id === currentStep.branchId);
5978
+ if (branchIndex !== -1) {
5979
+ foundParentPath.node.parallel_branches.splice(branchIndex, 1);
5980
+ updateGlobalTree(rootTreeClone);
5981
+ try {
5982
+ setIsSaving(true);
5983
+ const currentRootProps = extractCustomPropsFromNode(ancestryMode);
5984
+ const rootExtras = toObjectFromCustomProps(currentRootProps);
5985
+ await onSave(
5986
+ ancestryMode.ancestryName,
5987
+ ancestryMode.ancestryDescription,
5988
+ ancestryMode.ancestryDescriptionSections,
5989
+ true,
5990
+ rootTreeClone,
5991
+ rootExtras
5992
+ );
5993
+ setLastSavedSnapshot(takeSnapshot(
5994
+ rootTreeClone,
5995
+ ancestryMode.ancestryName,
5996
+ ancestryMode.ancestryDescription,
5997
+ ancestryMode.ancestryDescriptionSections,
5998
+ currentRootProps,
5999
+ isPrivate,
6000
+ ancestryMode.abstraction_tree
6001
+ ));
6002
+ if (onClearAncestryVisuals) {
6003
+ onClearAncestryVisuals(currentStep.branchId);
6004
+ }
6005
+ handleNavigateUp();
6006
+ } catch (err) {
6007
+ console.error("Erro ao remover a ramifica\xE7\xE3o:", err);
6008
+ alert("Erro ao remover a ramifica\xE7\xE3o.");
6009
+ } finally {
6010
+ setIsSaving(false);
6011
+ }
6012
+ }
6013
+ }
6014
+ };
5644
6015
  const sideActions = useMemo8(() => {
5645
6016
  const actions = { left: null, right: null };
5646
6017
  const isInBranch = branchStack.length > 0;
@@ -5679,7 +6050,7 @@ function CreateAncestryPanel({
5679
6050
  }
5680
6051
  return actions;
5681
6052
  }
5682
- if (isInBranch) {
6053
+ if (isInBranch && isAtStartOfBranch) {
5683
6054
  const lastStep = branchStack[branchStack.length - 1];
5684
6055
  const entryDir = lastStep.entryDirection || "right";
5685
6056
  const backSide = entryDir === "right" ? "left" : "right";
@@ -5690,7 +6061,7 @@ function CreateAncestryPanel({
5690
6061
  };
5691
6062
  }
5692
6063
  return actions;
5693
- }, [internalHighlightedNodeId, branchStack, activeTree]);
6064
+ }, [internalHighlightedNodeId, branchStack, activeTree, isAtStartOfBranch]);
5694
6065
  const applyDescriptionToTree = (baseTree, descText, descSections) => {
5695
6066
  const rootTreeClone = JSON.parse(JSON.stringify(baseTree));
5696
6067
  let targetTree = rootTreeClone;
@@ -6168,6 +6539,10 @@ function CreateAncestryPanel({
6168
6539
  setInternalHighlightedNodeId(id);
6169
6540
  if (onHighlightNode) onHighlightNode(id);
6170
6541
  };
6542
+ const handleSaveDescriptionInline = (newDesc) => {
6543
+ setDescription(newDesc);
6544
+ handleLocalSave(true, { description: newDesc });
6545
+ };
6171
6546
  const swallow = (e) => e.stopPropagation();
6172
6547
  const getSelectedParentName = () => {
6173
6548
  if (!activeTree || !selectedParentId) return "";
@@ -6240,10 +6615,8 @@ function CreateAncestryPanel({
6240
6615
  return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(
6241
6616
  "div",
6242
6617
  {
6243
- className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col transition-all duration-300 ease-out
6244
- ${isReadMode ? "w-[min(92vw,700px)]" : "w-[min(92vw,440px)]"}
6245
- `,
6246
- style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)" },
6618
+ className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col ${isResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
6619
+ style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${panelWidth}px`, maxWidth: "92vw" },
6247
6620
  onPointerDown: swallow,
6248
6621
  onPointerMove: swallow,
6249
6622
  onPointerUp: swallow,
@@ -6252,6 +6625,17 @@ function CreateAncestryPanel({
6252
6625
  onContextMenu: swallow,
6253
6626
  onDoubleClick: swallow
6254
6627
  },
6628
+ /* @__PURE__ */ React10.createElement(
6629
+ "div",
6630
+ {
6631
+ onPointerDown: (e) => {
6632
+ e.stopPropagation();
6633
+ handleResize(e);
6634
+ },
6635
+ className: "absolute left-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-indigo-500/50 z-[2000] transition-colors",
6636
+ title: "Arraste para redimensionar"
6637
+ }
6638
+ ),
6255
6639
  isReadMode ? /* @__PURE__ */ React10.createElement(
6256
6640
  DescriptionReadModePanel,
6257
6641
  {
@@ -6270,7 +6654,8 @@ function CreateAncestryPanel({
6270
6654
  onMentionClick,
6271
6655
  onSectionChange: handleSectionChangeWrapper,
6272
6656
  onHighlightNode,
6273
- onImageClick: handleImageClickFromText
6657
+ onImageClick: handleImageClickFromText,
6658
+ onSaveDescription: handleSaveDescriptionInline
6274
6659
  }
6275
6660
  ) : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0 flex-shrink-0" }), /* @__PURE__ */ React10.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4 flex-shrink-0" }, /* @__PURE__ */ React10.createElement("div", { className: "w-full" }, /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React10.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ React10.createElement("p", { className: "text-xs/relaxed text-slate-300" }, branchStack.length > 0 ? `Ramifica\xE7\xE3o (N\xEDvel ${branchStack.length})` : isEditMode ? "Editar Ancestralidade" : "Criar Ancestralidade"), currentAncestryId && currentAncestryId !== "temp_creating" && currentAncestryId !== "temp_root" && /* @__PURE__ */ React10.createElement(
6276
6661
  "button",
@@ -6289,7 +6674,7 @@ function CreateAncestryPanel({
6289
6674
  placeholder: "Nome da Ancestralidade",
6290
6675
  className: "text-xl sm:text-2xl font-semibold tracking-tight bg-transparent border-none p-0 focus:ring-2 focus:ring-indigo-500 rounded-md -ml-1.5 px-1.5 w-full outline-none transition-all focus:bg-slate-800/70"
6291
6676
  }
6292
- )), /* @__PURE__ */ React10.createElement("button", { onClick: onClose, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl flex-shrink-0", title: "Cancelar" }, "\xD7")), branchStack.length > 0 && /* @__PURE__ */ React10.createElement("div", { className: "px-6 pb-2" }, /* @__PURE__ */ React10.createElement(
6677
+ )), /* @__PURE__ */ React10.createElement("button", { onClick: onClose, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl flex-shrink-0", title: "Cancelar" }, "\xD7")), branchStack.length > 0 && /* @__PURE__ */ React10.createElement("div", { className: "px-6 pb-2 flex items-center justify-between" }, /* @__PURE__ */ React10.createElement(
6293
6678
  "button",
6294
6679
  {
6295
6680
  onClick: handleNavigateUp,
@@ -6297,7 +6682,33 @@ function CreateAncestryPanel({
6297
6682
  },
6298
6683
  /* @__PURE__ */ React10.createElement(FiArrowLeft2, null),
6299
6684
  " Voltar para Principal / N\xEDvel Anterior"
6300
- )), /* @__PURE__ */ React10.createElement("div", { className: "px-6 pb-4 pt-2 overflow-y-auto flex-grow custom-scrollbar" }, branchStack.length > 0 && /* @__PURE__ */ React10.createElement("div", { className: "mb-4" }, isContextLinked ? /* @__PURE__ */ React10.createElement("div", { className: "p-3 rounded-lg bg-indigo-500/10 border border-indigo-500/30 flex items-center justify-between" }, /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React10.createElement("div", { className: "w-8 h-8 rounded bg-indigo-500/20 text-indigo-300 grid place-content-center" }, /* @__PURE__ */ React10.createElement(FiLayers5, null)), /* @__PURE__ */ React10.createElement("div", null, /* @__PURE__ */ React10.createElement("div", { className: "text-xs text-indigo-200 font-semibold uppercase tracking-wider" }, "Ancestralidade Vinculada"), /* @__PURE__ */ React10.createElement("div", { className: "text-sm text-white font-medium truncate max-w-[200px]" }, currentContext.name.replace("[REF] ", "")))), /* @__PURE__ */ React10.createElement(
6685
+ ), !isContextLinked && /* @__PURE__ */ React10.createElement("div", { className: "relative animate-in fade-in duration-200" }, showDeleteBranchConfirm ? /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-3 bg-rose-500/10 border border-rose-500/30 px-3 py-1 rounded-md shadow-inner" }, /* @__PURE__ */ React10.createElement("span", { className: "text-xs text-rose-300 font-medium" }, "Excluir?"), /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React10.createElement(
6686
+ "button",
6687
+ {
6688
+ onClick: () => {
6689
+ setShowDeleteBranchConfirm(false);
6690
+ handleDeleteBranch();
6691
+ },
6692
+ className: "text-xs font-bold text-rose-400 hover:text-rose-200 transition-colors"
6693
+ },
6694
+ "Sim"
6695
+ ), /* @__PURE__ */ React10.createElement("span", { className: "text-slate-600/50" }, "|"), /* @__PURE__ */ React10.createElement(
6696
+ "button",
6697
+ {
6698
+ onClick: () => setShowDeleteBranchConfirm(false),
6699
+ className: "text-xs text-slate-400 hover:text-white transition-colors"
6700
+ },
6701
+ "N\xE3o"
6702
+ ))) : /* @__PURE__ */ React10.createElement(
6703
+ "button",
6704
+ {
6705
+ onClick: () => setShowDeleteBranchConfirm(true),
6706
+ className: "flex items-center gap-1.5 text-xs text-rose-400/80 hover:text-white hover:bg-rose-500/20 px-2 py-1 rounded transition-colors",
6707
+ title: "Excluir permanentemente esta ramifica\xE7\xE3o e seu conte\xFAdo"
6708
+ },
6709
+ /* @__PURE__ */ React10.createElement(FiTrash22, null),
6710
+ " Excluir Ramifica\xE7\xE3o"
6711
+ ))), /* @__PURE__ */ React10.createElement("div", { className: "px-6 pb-4 pt-2 overflow-y-auto flex-grow custom-scrollbar" }, branchStack.length > 0 && /* @__PURE__ */ React10.createElement("div", { className: "mb-4" }, isContextLinked ? /* @__PURE__ */ React10.createElement("div", { className: "p-3 rounded-lg bg-indigo-500/10 border border-indigo-500/30 flex items-center justify-between" }, /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React10.createElement("div", { className: "w-8 h-8 rounded bg-indigo-500/20 text-indigo-300 grid place-content-center" }, /* @__PURE__ */ React10.createElement(FiLayers5, null)), /* @__PURE__ */ React10.createElement("div", null, /* @__PURE__ */ React10.createElement("div", { className: "text-xs text-indigo-200 font-semibold uppercase tracking-wider" }, "Ancestralidade Vinculada"), /* @__PURE__ */ React10.createElement("div", { className: "text-sm text-white font-medium truncate max-w-[200px]" }, currentContext.name.replace("[REF] ", "")))), /* @__PURE__ */ React10.createElement(
6301
6712
  "button",
6302
6713
  {
6303
6714
  onClick: handleUnlinkAncestry,
@@ -6327,7 +6738,9 @@ function CreateAncestryPanel({
6327
6738
  onHighlightNode: handleHighlightWrapper,
6328
6739
  initialSectionId: targetScrollSectionId,
6329
6740
  currentBranchDirection: currentContext ? currentContext.direction : null,
6330
- onImageClick: handleImageClickFromText
6741
+ onImageClick: handleImageClickFromText,
6742
+ onSaveDescription: handleSaveDescriptionInline,
6743
+ onStepChange: (stepIndex) => setIsAtStartOfBranch(stepIndex === 0)
6331
6744
  }
6332
6745
  ), /* @__PURE__ */ React10.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5 z-30" }, /* @__PURE__ */ React10.createElement(
6333
6746
  "button",
@@ -6548,25 +6961,25 @@ function CreateAncestryPanel({
6548
6961
  }
6549
6962
 
6550
6963
  // src/components/ImageViewer.jsx
6551
- import React11, { useState as useState11, useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useCallback as useCallback2 } from "react";
6964
+ import React11, { useState as useState12, useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useCallback as useCallback3 } from "react";
6552
6965
  import { FiX as FiX2, FiChevronLeft as FiChevronLeft3, FiChevronRight as FiChevronRight5 } from "react-icons/fi";
6553
6966
  function ImageViewer({ data, onClose }) {
6554
6967
  var _a;
6555
6968
  const { images = [], startIndex = 0, visible } = data;
6556
- const [currentIndex, setCurrentIndex] = useState11(startIndex);
6557
- const [isLoading, setIsLoading] = useState11(false);
6558
- const [loadedSrc, setLoadedSrc] = useState11(null);
6969
+ const [currentIndex, setCurrentIndex] = useState12(startIndex);
6970
+ const [isLoading, setIsLoading] = useState12(false);
6971
+ const [loadedSrc, setLoadedSrc] = useState12(null);
6559
6972
  useLayoutEffect2(() => {
6560
6973
  if (visible) {
6561
6974
  setCurrentIndex(startIndex);
6562
6975
  }
6563
6976
  }, [visible, startIndex]);
6564
- const handleNext = useCallback2(() => {
6977
+ const handleNext = useCallback3(() => {
6565
6978
  if (images.length > 1) {
6566
6979
  setCurrentIndex((prev) => (prev + 1) % images.length);
6567
6980
  }
6568
6981
  }, [images.length]);
6569
- const handlePrev = useCallback2(() => {
6982
+ const handlePrev = useCallback3(() => {
6570
6983
  if (images.length > 1) {
6571
6984
  setCurrentIndex((prev) => (prev - 1 + images.length) % images.length);
6572
6985
  }
@@ -6671,10 +7084,10 @@ function ImageViewer({ data, onClose }) {
6671
7084
  }
6672
7085
 
6673
7086
  // src/components/InSceneCreationForm.jsx
6674
- import React13, { useState as useState13, useEffect as useEffect13, useRef as useRef10 } from "react";
7087
+ import React13, { useState as useState14, useEffect as useEffect13, useRef as useRef10 } from "react";
6675
7088
 
6676
7089
  // src/components/ColorPicker.jsx
6677
- import React12, { useState as useState12, useEffect as useEffect12, useRef as useRef9 } from "react";
7090
+ import React12, { useState as useState13, useEffect as useEffect12, useRef as useRef9 } from "react";
6678
7091
  import { HexColorPicker } from "react-colorful";
6679
7092
  import { FiHash, FiCheck as FiCheck6 } from "react-icons/fi";
6680
7093
  var PRESET_COLORS = [
@@ -6695,7 +7108,7 @@ var PRESET_COLORS = [
6695
7108
  "#000000"
6696
7109
  ];
6697
7110
  function ColorPicker({ color, onChange, disabled }) {
6698
- const [isOpen, setIsOpen] = useState12(false);
7111
+ const [isOpen, setIsOpen] = useState13(false);
6699
7112
  const popoverRef = useRef9(null);
6700
7113
  useEffect12(() => {
6701
7114
  const handleClickOutside = (event) => {
@@ -6794,21 +7207,21 @@ function InSceneCreationForm({
6794
7207
  viewType
6795
7208
  }) {
6796
7209
  var _a;
6797
- const [name, setName] = useState13("");
6798
- const [types, setTypes] = useState13([]);
6799
- const [typeInput, setTypeInput] = useState13("");
6800
- const [color, setColor] = useState13(initialColor || "#cccccc");
6801
- const [size, setSize] = useState13("medium");
6802
- const [intensity, setIntensity] = useState13(0);
6803
- const [description, setDescription] = useState13("");
6804
- const [customProps, setCustomProps] = useState13([]);
6805
- const [showTypeSuggestions, setShowTypeSuggestions] = useState13(false);
6806
- const [filteredTypes, setFilteredTypes] = useState13([]);
6807
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState13(false);
6808
- const [useImageAsTexture, setUseImageAsTexture] = useState13(false);
6809
- const [selectedImageUrl, setSelectedImageUrl] = useState13(null);
6810
- const [targetDatasetId, setTargetDatasetId] = useState13(sourceNodeDatasetId || "");
6811
- const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] = useState13(false);
7210
+ const [name, setName] = useState14("");
7211
+ const [types, setTypes] = useState14([]);
7212
+ const [typeInput, setTypeInput] = useState14("");
7213
+ const [color, setColor] = useState14(initialColor || "#cccccc");
7214
+ const [size, setSize] = useState14("medium");
7215
+ const [intensity, setIntensity] = useState14(0);
7216
+ const [description, setDescription] = useState14("");
7217
+ const [customProps, setCustomProps] = useState14([]);
7218
+ const [showTypeSuggestions, setShowTypeSuggestions] = useState14(false);
7219
+ const [filteredTypes, setFilteredTypes] = useState14([]);
7220
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState14(false);
7221
+ const [useImageAsTexture, setUseImageAsTexture] = useState14(false);
7222
+ const [selectedImageUrl, setSelectedImageUrl] = useState14(null);
7223
+ const [targetDatasetId, setTargetDatasetId] = useState14(sourceNodeDatasetId || "");
7224
+ const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] = useState14(false);
6812
7225
  const datasetDropdownRef = useRef10(null);
6813
7226
  useEffect13(() => {
6814
7227
  if (sourceNodeDatasetId) setTargetDatasetId(sourceNodeDatasetId);
@@ -7050,7 +7463,8 @@ function InSceneCreationForm({
7050
7463
  availableNodes,
7051
7464
  availableAncestries,
7052
7465
  onMentionClick,
7053
- onImageClick: handleImageClickFromText
7466
+ onImageClick: handleImageClickFromText,
7467
+ onSaveDescription: (newDesc) => setDescription(newDesc)
7054
7468
  }
7055
7469
  ), /* @__PURE__ */ React13.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ React13.createElement(
7056
7470
  "button",
@@ -7141,7 +7555,7 @@ function InSceneCreationForm({
7141
7555
  }
7142
7556
 
7143
7557
  // src/components/InSceneVersionForm.jsx
7144
- import React14, { useState as useState14, useEffect as useEffect14, useRef as useRef11 } from "react";
7558
+ import React14, { useState as useState15, useEffect as useEffect14, useRef as useRef11 } from "react";
7145
7559
  import { FiPlus as FiPlus4, FiMaximize2 as FiMaximize22, FiCheck as FiCheck8, FiEdit2 as FiEdit25 } from "react-icons/fi";
7146
7560
  function InSceneVersionForm({
7147
7561
  onSave,
@@ -7159,14 +7573,14 @@ function InSceneVersionForm({
7159
7573
  onMentionClick,
7160
7574
  onUploadFile
7161
7575
  }) {
7162
- const [name, setName] = useState14("");
7163
- const [size, setSize] = useState14("medium");
7164
- const [description, setDescription] = useState14("");
7165
- const [customProps, setCustomProps] = useState14([{ id: v4_default(), key: "Date", type: "date", value: { type: "Data", value: "" }, isEditing: true }]);
7166
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState14(false);
7576
+ const [name, setName] = useState15("");
7577
+ const [size, setSize] = useState15("medium");
7578
+ const [description, setDescription] = useState15("");
7579
+ const [customProps, setCustomProps] = useState15([{ id: v4_default(), key: "Date", type: "date", value: { type: "Data", value: "" }, isEditing: true }]);
7580
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState15(false);
7167
7581
  const propsEndRef = useRef11(null);
7168
- const [useImageAsTexture, setUseImageAsTexture] = useState14(false);
7169
- const [selectedImageUrl, setSelectedImageUrl] = useState14(null);
7582
+ const [useImageAsTexture, setUseImageAsTexture] = useState15(false);
7583
+ const [selectedImageUrl, setSelectedImageUrl] = useState15(null);
7170
7584
  const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
7171
7585
  useEffect14(() => {
7172
7586
  if (!hasImages && useImageAsTexture) {
@@ -7287,7 +7701,8 @@ function InSceneVersionForm({
7287
7701
  availableNodes,
7288
7702
  availableAncestries,
7289
7703
  onMentionClick,
7290
- onImageClick: handleImageClickFromText
7704
+ onImageClick: handleImageClickFromText,
7705
+ onSaveDescription: (newDesc) => setDescription(newDesc)
7291
7706
  }
7292
7707
  ), /* @__PURE__ */ React14.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ React14.createElement(
7293
7708
  "button",
@@ -7359,7 +7774,7 @@ function InSceneVersionForm({
7359
7774
  }
7360
7775
 
7361
7776
  // src/components/NodeDetailsPanel.jsx
7362
- import React15, { useState as useState15, useEffect as useEffect15, useRef as useRef12 } from "react";
7777
+ import React15, { useState as useState16, useEffect as useEffect15, useRef as useRef12 } from "react";
7363
7778
  import { FiPlus as FiPlus5, FiMaximize2 as FiMaximize23, FiX as FiX4, FiCheck as FiCheck9, FiImage as FiImage3, FiEdit2 as FiEdit26, FiLoader as FiLoader2, FiBookOpen as FiBookOpen3, FiSun as FiSun2, FiLink as FiLink5, FiDatabase } from "react-icons/fi";
7364
7779
  function NodeDetailsPanel({
7365
7780
  node,
@@ -7381,27 +7796,36 @@ function NodeDetailsPanel({
7381
7796
  userRole,
7382
7797
  currentDatasetName
7383
7798
  }) {
7384
- const [name, setName] = useState15((node == null ? void 0 : node.name) ?? "");
7385
- const [types, setTypes] = useState15([]);
7386
- const [typeInput, setTypeInput] = useState15("");
7387
- const [color, setColor] = useState15((node == null ? void 0 : node.color) ?? "#8b5cf6");
7388
- const [size, setSize] = useState15((node == null ? void 0 : node.size) ?? "medium");
7389
- const [description, setDescription] = useState15((node == null ? void 0 : node.description) ?? "");
7390
- const [intensity, setIntensity] = useState15((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
7391
- const [customProps, setCustomProps] = useState15(() => extractCustomPropsFromNode(node || {}));
7392
- const [showTypeSuggestions, setShowTypeSuggestions] = useState15(false);
7393
- const [filteredTypes, setFilteredTypes] = useState15([]);
7394
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState15(false);
7395
- const [isReadMode, setIsReadMode] = useState15(false);
7396
- const [existingSections, setExistingSections] = useState15((node == null ? void 0 : node.description_sections) || []);
7397
- const [isSaving, setIsSaving] = useState15(false);
7398
- const [isLinkCopied, setIsLinkCopied] = useState15(false);
7399
- const [useImageAsTexture, setUseImageAsTexture] = useState15(() => {
7799
+ const [name, setName] = useState16((node == null ? void 0 : node.name) ?? "");
7800
+ const [types, setTypes] = useState16([]);
7801
+ const [typeInput, setTypeInput] = useState16("");
7802
+ const [color, setColor] = useState16((node == null ? void 0 : node.color) ?? "#8b5cf6");
7803
+ const [size, setSize] = useState16((node == null ? void 0 : node.size) ?? "medium");
7804
+ const [description, setDescription] = useState16((node == null ? void 0 : node.description) ?? "");
7805
+ const [intensity, setIntensity] = useState16((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
7806
+ const [customProps, setCustomProps] = useState16(() => extractCustomPropsFromNode(node || {}));
7807
+ const [showTypeSuggestions, setShowTypeSuggestions] = useState16(false);
7808
+ const [filteredTypes, setFilteredTypes] = useState16([]);
7809
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState16(false);
7810
+ const [isReadMode, setIsReadMode] = useState16(false);
7811
+ const [existingSections, setExistingSections] = useState16((node == null ? void 0 : node.description_sections) || []);
7812
+ const [isSaving, setIsSaving] = useState16(false);
7813
+ const [isLinkCopied, setIsLinkCopied] = useState16(false);
7814
+ const [useImageAsTexture, setUseImageAsTexture] = useState16(() => {
7400
7815
  if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
7401
7816
  if ((node == null ? void 0 : node.useImageAsTexture) === "false") return false;
7402
7817
  return !!(node == null ? void 0 : node.useImageAsTexture);
7403
7818
  });
7404
- const [selectedImageUrl, setSelectedImageUrl] = useState15((node == null ? void 0 : node.textureImageUrl) ?? null);
7819
+ const [selectedImageUrl, setSelectedImageUrl] = useState16((node == null ? void 0 : node.textureImageUrl) ?? null);
7820
+ const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
7821
+ const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
7822
+ initialWidth: isReadMode ? 700 : 440,
7823
+ minWidth: 320,
7824
+ maxWidth: maxPanelW
7825
+ });
7826
+ useEffect15(() => {
7827
+ setWidth(isReadMode ? 700 : 440);
7828
+ }, [isReadMode, setWidth]);
7405
7829
  const prevNodeIdRef = useRef12(null);
7406
7830
  const propsEndRef = useRef12(null);
7407
7831
  const canEdit = userRole !== "viewer";
@@ -7554,6 +7978,11 @@ function NodeDetailsPanel({
7554
7978
  textureImageUrl: url
7555
7979
  });
7556
7980
  };
7981
+ const handleSaveDescriptionInline = (newDescription) => {
7982
+ setDescription(newDescription);
7983
+ onDataUpdate({ ...node, description: newDescription });
7984
+ triggerAutoSave({ description: newDescription });
7985
+ };
7557
7986
  const handleSave = async (keepOpen = false, overrides = {}) => {
7558
7987
  const currentName = overrides.name !== void 0 ? overrides.name : name;
7559
7988
  const currentTypes = overrides.types !== void 0 ? overrides.types : types;
@@ -7609,10 +8038,8 @@ function NodeDetailsPanel({
7609
8038
  return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(
7610
8039
  "div",
7611
8040
  {
7612
- className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden transition-all duration-300 ease-out
7613
- ${isReadMode ? "w-[min(92vw,700px)]" : "w-[min(92vw,440px)]"}
7614
- `,
7615
- style: { top: 16, right: 16, zIndex: 1100 },
8041
+ className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col ${isResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
8042
+ style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${panelWidth}px`, maxWidth: "92vw" },
7616
8043
  onPointerDown: swallow,
7617
8044
  onPointerMove: swallow,
7618
8045
  onPointerUp: swallow,
@@ -7621,6 +8048,17 @@ function NodeDetailsPanel({
7621
8048
  onContextMenu: swallow,
7622
8049
  onDoubleClick: swallow
7623
8050
  },
8051
+ /* @__PURE__ */ React15.createElement(
8052
+ "div",
8053
+ {
8054
+ onPointerDown: (e) => {
8055
+ e.stopPropagation();
8056
+ handleResize(e);
8057
+ },
8058
+ className: "absolute left-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-indigo-500/50 z-[2000] transition-colors",
8059
+ title: "Arraste para redimensionar"
8060
+ }
8061
+ ),
7624
8062
  isReadMode ? /* @__PURE__ */ React15.createElement(
7625
8063
  DescriptionReadModePanel,
7626
8064
  {
@@ -7639,7 +8077,8 @@ function NodeDetailsPanel({
7639
8077
  availableAncestries,
7640
8078
  onOpenReference,
7641
8079
  onMentionClick,
7642
- onImageClick: handleImageClickFromText
8080
+ onImageClick: handleImageClickFromText,
8081
+ onSaveDescription: handleSaveDescriptionInline
7643
8082
  }
7644
8083
  ) : /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ React15.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React15.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ React15.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node"), /* @__PURE__ */ React15.createElement(
7645
8084
  "button",
@@ -7707,7 +8146,8 @@ function NodeDetailsPanel({
7707
8146
  availableAncestries,
7708
8147
  onOpenReference,
7709
8148
  onMentionClick,
7710
- onImageClick: handleImageClickFromText
8149
+ onImageClick: handleImageClickFromText,
8150
+ onSaveDescription: handleSaveDescriptionInline
7711
8151
  }
7712
8152
  ), /* @__PURE__ */ React15.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ React15.createElement(
7713
8153
  "button",
@@ -7790,7 +8230,7 @@ function NodeDetailsPanel({
7790
8230
  onUploadFile: canEdit ? onUploadFile : void 0,
7791
8231
  readOnly: !canEdit
7792
8232
  }
7793
- )), /* @__PURE__ */ React15.createElement("div", { ref: propsEndRef }))), currentDatasetName && /* @__PURE__ */ React15.createElement("div", { className: "pt-3 mt-4 border-t border-white/10 flex items-center gap-2 text-xs text-slate-400" }, /* @__PURE__ */ React15.createElement(FiDatabase, { className: "text-indigo-400 shrink-0", size: 14 }), /* @__PURE__ */ React15.createElement("span", { className: "truncate" }, "Dataset ", /* @__PURE__ */ React15.createElement("span", { className: "text-slate-200 font-medium" }, currentDatasetName)))), /* @__PURE__ */ React15.createElement("div", { className: "sticky bottom-0 z-10 bg-gradient-to-t from-slate-950/80 via-slate-950/50 to-transparent px-6 py-4 border-t border-white/10 flex justify-end gap-3" }, /* @__PURE__ */ React15.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm disabled:opacity-50" }, canEdit ? "Cancelar" : "Fechar"), canEdit && /* @__PURE__ */ React15.createElement(
8233
+ )), /* @__PURE__ */ React15.createElement("div", { ref: propsEndRef }))), currentDatasetName && /* @__PURE__ */ React15.createElement("div", { className: "pt-3 mt-4 border-t border-white/10 flex items-center justify-end gap-2 text-xs text-slate-400" }, /* @__PURE__ */ React15.createElement("span", { className: "truncate text-right" }, /* @__PURE__ */ React15.createElement("span", { className: "text-slate-200 font-medium" }, currentDatasetName)))), /* @__PURE__ */ React15.createElement("div", { className: "sticky bottom-0 z-10 bg-gradient-to-t from-slate-950/80 via-slate-950/50 to-transparent px-6 py-4 border-t border-white/10 flex justify-end gap-3" }, /* @__PURE__ */ React15.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm disabled:opacity-50" }, canEdit ? "Cancelar" : "Fechar"), canEdit && /* @__PURE__ */ React15.createElement(
7794
8234
  "button",
7795
8235
  {
7796
8236
  onClick: () => handleSave(false),
@@ -7822,18 +8262,18 @@ function NodeDetailsPanel({
7822
8262
  }
7823
8263
 
7824
8264
  // src/components/MultiNodeContextMenu.jsx
7825
- import React16, { useLayoutEffect as useLayoutEffect3, useRef as useRef13, useState as useState16, useEffect as useEffect16 } from "react";
8265
+ import React16, { useLayoutEffect as useLayoutEffect3, useRef as useRef13, useState as useState17, useEffect as useEffect16 } from "react";
7826
8266
  function MultiNodeContextMenu({
7827
8267
  data,
7828
8268
  userRole,
7829
- // 2. Recebendo a role do usuário nas props
7830
8269
  onClose,
7831
8270
  onDismissNodes,
7832
8271
  onDismissOtherNodes,
7833
8272
  onDeleteNodes
7834
8273
  }) {
7835
8274
  const menuRef = useRef13(null);
7836
- const [menuPos, setMenuPos] = useState16({ left: 0, top: 0 });
8275
+ const [menuPos, setMenuPos] = useState17({ left: 0, top: 0 });
8276
+ const [isConfirmingDelete, setIsConfirmingDelete] = useState17(false);
7837
8277
  const ability = defineAbilityFor(userRole);
7838
8278
  const canDelete = ability.can("delete", "Node");
7839
8279
  useLayoutEffect3(() => {
@@ -7850,7 +8290,9 @@ function MultiNodeContextMenu({
7850
8290
  setMenuPos({ left, top });
7851
8291
  }, [data]);
7852
8292
  useEffect16(() => {
7853
- if (!data.visible) return;
8293
+ if (data.visible) {
8294
+ setIsConfirmingDelete(false);
8295
+ }
7854
8296
  const handleClickOutside = (e) => {
7855
8297
  if (menuRef.current && !menuRef.current.contains(e.target)) onClose();
7856
8298
  };
@@ -7877,12 +8319,26 @@ function MultiNodeContextMenu({
7877
8319
  onDoubleClick: swallow
7878
8320
  },
7879
8321
  /* @__PURE__ */ React16.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
7880
- /* @__PURE__ */ React16.createElement("div", { className: "p-1.5" }, /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React16.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__ */ React16.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es em Grupo (", nodeCount, " Nodes)")), /* @__PURE__ */ React16.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React16.createElement("button", { onClick: () => onDismissNodes(data.nodeIds), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ React16.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__ */ React16.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ React16.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__ */ React16.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__ */ React16.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ React16.createElement("span", null, "Dismiss (", nodeCount, ")")), /* @__PURE__ */ React16.createElement("button", { onClick: () => onDismissOtherNodes(data.nodeIds), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ React16.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__ */ React16.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ React16.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ React16.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React16.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ React16.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ React16.createElement("span", null, "Dismiss other nodes")), canDelete && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React16.createElement("button", { onClick: () => onDeleteNodes(data.nodeIds), className: deleteButtonClass, title: "Excluir Nodes" }, /* @__PURE__ */ React16.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__ */ React16.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React16.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__ */ React16.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ React16.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ React16.createElement("span", null, "Excluir Nodes (", nodeCount, ")"))))))
8322
+ /* @__PURE__ */ React16.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ React16.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ React16.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ React16.createElement("div", { className: "w-10 h-10 rounded-full bg-red-500/20 flex items-center justify-center text-red-400 mb-1" }, /* @__PURE__ */ React16.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React16.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React16.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__ */ React16.createElement("p", { className: "text-sm text-slate-200" }, "Excluir ", /* @__PURE__ */ React16.createElement("strong", null, nodeCount, " Nodes"), "?"), /* @__PURE__ */ React16.createElement("p", { className: "text-[11px] text-slate-400 leading-tight" }, "Esta a\xE7\xE3o \xE9 irrevers\xEDvel. Todas as conex\xF5es associadas a eles ser\xE3o apagadas.")), /* @__PURE__ */ React16.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ React16.createElement(
8323
+ "button",
8324
+ {
8325
+ onClick: () => setIsConfirmingDelete(false),
8326
+ className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
8327
+ },
8328
+ "Cancelar"
8329
+ ), /* @__PURE__ */ React16.createElement(
8330
+ "button",
8331
+ {
8332
+ onClick: () => onDeleteNodes(data.nodeIds),
8333
+ className: "flex-1 px-2 py-2 text-xs font-medium bg-red-500 hover:bg-red-600 rounded-md text-white transition-colors"
8334
+ },
8335
+ "Excluir"
8336
+ ))) : /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React16.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__ */ React16.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es em Grupo (", nodeCount, " Nodes)")), /* @__PURE__ */ React16.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React16.createElement("button", { onClick: () => onDismissNodes(data.nodeIds), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ React16.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__ */ React16.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ React16.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__ */ React16.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__ */ React16.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ React16.createElement("span", null, "Dismiss (", nodeCount, ")")), /* @__PURE__ */ React16.createElement("button", { onClick: () => onDismissOtherNodes(data.nodeIds), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ React16.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__ */ React16.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ React16.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ React16.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React16.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ React16.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ React16.createElement("span", null, "Dismiss other nodes")), canDelete && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React16.createElement("button", { onClick: () => setIsConfirmingDelete(true), className: deleteButtonClass, title: "Excluir Nodes" }, /* @__PURE__ */ React16.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__ */ React16.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React16.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__ */ React16.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ React16.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ React16.createElement("span", null, "Excluir Nodes (", nodeCount, ")"))))))
7881
8337
  );
7882
8338
  }
7883
8339
 
7884
8340
  // src/components/RelationshipDetailsPanel.jsx
7885
- import React17, { useState as useState17, useEffect as useEffect17, useRef as useRef14, useMemo as useMemo9 } from "react";
8341
+ import React17, { useState as useState18, useEffect as useEffect17, useRef as useRef14, useMemo as useMemo9 } from "react";
7886
8342
  import { FiPlus as FiPlus6, FiEdit2 as FiEdit27, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4 } from "react-icons/fi";
7887
8343
  function RelationshipDetailsPanel({
7888
8344
  link,
@@ -7896,15 +8352,14 @@ function RelationshipDetailsPanel({
7896
8352
  onMentionClick,
7897
8353
  onUploadFile,
7898
8354
  userRole
7899
- // Recebendo userRole via props
7900
8355
  }) {
7901
- const [name, setName] = useState17((link == null ? void 0 : link.name) ?? "");
7902
- const [description, setDescription] = useState17((link == null ? void 0 : link.description) ?? "");
7903
- const [customProps, setCustomProps] = useState17(() => extractCustomPropsFromNode(link || {}));
7904
- const [existingSections, setExistingSections] = useState17((link == null ? void 0 : link.description_sections) || []);
7905
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState17(false);
7906
- const [isSaving, setIsSaving] = useState17(false);
7907
- const [isReadMode, setIsReadMode] = useState17(false);
8356
+ const [name, setName] = useState18((link == null ? void 0 : link.name) ?? "");
8357
+ const [description, setDescription] = useState18((link == null ? void 0 : link.description) ?? "");
8358
+ const [customProps, setCustomProps] = useState18(() => extractCustomPropsFromNode(link || {}));
8359
+ const [existingSections, setExistingSections] = useState18((link == null ? void 0 : link.description_sections) || []);
8360
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState18(false);
8361
+ const [isSaving, setIsSaving] = useState18(false);
8362
+ const [isReadMode, setIsReadMode] = useState18(false);
7908
8363
  const propsEndRef = useRef14(null);
7909
8364
  const canEdit = useMemo9(() => {
7910
8365
  const ability = defineAbilityFor(userRole);
@@ -7959,6 +8414,12 @@ function RelationshipDetailsPanel({
7959
8414
  const triggerAutoSave = (overrides = {}) => {
7960
8415
  if (canEdit) handleSave(true, overrides);
7961
8416
  };
8417
+ const handleSaveDescriptionInline = (newDescription) => {
8418
+ if (!canEdit) return;
8419
+ setDescription(newDescription);
8420
+ onDataUpdate((prev) => ({ ...prev, description: newDescription }));
8421
+ triggerAutoSave({ description: newDescription });
8422
+ };
7962
8423
  const handleRemoveProp = (i) => {
7963
8424
  const newProps = customProps.filter((_, idx) => idx !== i);
7964
8425
  setCustomProps(newProps);
@@ -8012,7 +8473,8 @@ function RelationshipDetailsPanel({
8012
8473
  availableAncestries,
8013
8474
  onOpenReference,
8014
8475
  onMentionClick,
8015
- onImageClick: handleImageClickFromText
8476
+ onImageClick: handleImageClickFromText,
8477
+ onSaveDescription: handleSaveDescriptionInline
8016
8478
  }
8017
8479
  ) : /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React17.createElement("div", null, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React17.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-teal-400/80 shadow-[0_0_18px_2px_rgba(45,212,191,0.55)]" }), /* @__PURE__ */ React17.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Rela\xE7\xE3o")), /* @__PURE__ */ React17.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || "Rela\xE7\xE3o")), /* @__PURE__ */ React17.createElement("button", { onClick: onClose, disabled: isSaving, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Fechar" }, "\xD7")), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Rela\xE7\xE3o (Opcional)"), /* @__PURE__ */ React17.createElement(
8018
8480
  "input",
@@ -8035,7 +8497,8 @@ function RelationshipDetailsPanel({
8035
8497
  availableAncestries,
8036
8498
  onOpenReference,
8037
8499
  onMentionClick,
8038
- onImageClick: handleImageClickFromText
8500
+ onImageClick: handleImageClickFromText,
8501
+ onSaveDescription: handleSaveDescriptionInline
8039
8502
  }
8040
8503
  ), /* @__PURE__ */ React17.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ React17.createElement(
8041
8504
  "button",
@@ -8107,11 +8570,10 @@ function RelationshipDetailsPanel({
8107
8570
  }
8108
8571
 
8109
8572
  // src/components/RelationshipContextMenu.jsx
8110
- import React18, { useLayoutEffect as useLayoutEffect4, useRef as useRef15, useState as useState18, useEffect as useEffect18, useMemo as useMemo10 } from "react";
8573
+ import React18, { useLayoutEffect as useLayoutEffect4, useRef as useRef15, useState as useState19, useEffect as useEffect18, useMemo as useMemo10 } from "react";
8111
8574
  function RelationshipContextMenu({
8112
8575
  data,
8113
8576
  userRole,
8114
- // Recebemos a role do usuário para verificar permissões
8115
8577
  onRelinkSource,
8116
8578
  onRelinkTarget,
8117
8579
  onOpenDetails,
@@ -8119,7 +8581,8 @@ function RelationshipContextMenu({
8119
8581
  onClose
8120
8582
  }) {
8121
8583
  const menuRef = useRef15(null);
8122
- const [menuPos, setMenuPos] = useState18({ left: 0, top: 0 });
8584
+ const [menuPos, setMenuPos] = useState19({ left: 0, top: 0 });
8585
+ const [isConfirmingDelete, setIsConfirmingDelete] = useState19(false);
8123
8586
  const ability = useMemo10(() => defineAbilityFor(userRole), [userRole]);
8124
8587
  const sourceName = useMemo10(
8125
8588
  () => {
@@ -8149,7 +8612,9 @@ function RelationshipContextMenu({
8149
8612
  setMenuPos({ left, top });
8150
8613
  }, [data]);
8151
8614
  useEffect18(() => {
8152
- if (!data.visible) return;
8615
+ if (data.visible) {
8616
+ setIsConfirmingDelete(false);
8617
+ }
8153
8618
  const handleClickOutside = (e) => {
8154
8619
  if (menuRef.current && !menuRef.current.contains(e.target)) onClose();
8155
8620
  };
@@ -8177,7 +8642,21 @@ function RelationshipContextMenu({
8177
8642
  onDoubleClick: swallow
8178
8643
  },
8179
8644
  /* @__PURE__ */ React18.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }),
8180
- /* @__PURE__ */ React18.createElement("div", { className: "p-1.5" }, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React18.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-teal-400/80 shadow-[0_0_12px_1px_rgba(45,212,191,0.5)]" }), /* @__PURE__ */ React18.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Rela\xE7\xE3o")), /* @__PURE__ */ React18.createElement("div", { className: "flex flex-col gap-1" }, canUpdate && /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(
8645
+ /* @__PURE__ */ React18.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ React18.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ React18.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ React18.createElement("div", { className: "w-10 h-10 rounded-full bg-rose-500/20 flex items-center justify-center text-rose-400 mb-1" }, /* @__PURE__ */ React18.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React18.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React18.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }), /* @__PURE__ */ React18.createElement("path", { d: "M10 11v6" }), /* @__PURE__ */ React18.createElement("path", { d: "M14 11v6" }), /* @__PURE__ */ React18.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" }))), /* @__PURE__ */ React18.createElement("p", { className: "text-sm text-slate-200" }, "Excluir rela\xE7\xE3o?"), /* @__PURE__ */ React18.createElement("p", { className: "text-[11px] text-slate-400 leading-tight break-words" }, "Desconectar ", /* @__PURE__ */ React18.createElement("strong", null, sourceName), " de ", /* @__PURE__ */ React18.createElement("strong", null, targetName), ".")), /* @__PURE__ */ React18.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ React18.createElement(
8646
+ "button",
8647
+ {
8648
+ onClick: () => setIsConfirmingDelete(false),
8649
+ className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
8650
+ },
8651
+ "Cancelar"
8652
+ ), /* @__PURE__ */ React18.createElement(
8653
+ "button",
8654
+ {
8655
+ onClick: () => onDelete == null ? void 0 : onDelete(data.linkObject),
8656
+ className: "flex-1 px-2 py-2 text-xs font-medium bg-rose-600 hover:bg-rose-500 rounded-md text-white transition-colors"
8657
+ },
8658
+ "Excluir"
8659
+ ))) : /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React18.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-teal-400/80 shadow-[0_0_12px_1px_rgba(45,212,191,0.5)]" }), /* @__PURE__ */ React18.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Rela\xE7\xE3o")), /* @__PURE__ */ React18.createElement("div", { className: "flex flex-col gap-1" }, canUpdate && /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(
8181
8660
  "button",
8182
8661
  {
8183
8662
  onClick: () => onRelinkSource == null ? void 0 : onRelinkSource(data.linkObject),
@@ -8256,7 +8735,7 @@ function RelationshipContextMenu({
8256
8735
  ), canDelete && /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" }), /* @__PURE__ */ React18.createElement(
8257
8736
  "button",
8258
8737
  {
8259
- onClick: () => onDelete == null ? void 0 : onDelete(data.linkObject),
8738
+ onClick: () => setIsConfirmingDelete(true),
8260
8739
  className: dangerButtonClass,
8261
8740
  title: "Excluir esta conex\xE3o"
8262
8741
  },
@@ -8280,7 +8759,7 @@ function RelationshipContextMenu({
8280
8759
  /* @__PURE__ */ React18.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" })
8281
8760
  ),
8282
8761
  /* @__PURE__ */ React18.createElement("span", null, "Excluir conex\xE3o (", sourceName, " \u2192 ", targetName, ")")
8283
- ))))
8762
+ )))))
8284
8763
  );
8285
8764
  }
8286
8765
 
@@ -8321,7 +8800,7 @@ function LoadingScreen() {
8321
8800
  }
8322
8801
 
8323
8802
  // src/components/ImportParentFileModal.jsx
8324
- import React20, { useEffect as useEffect19, useState as useState19 } from "react";
8803
+ import React20, { useEffect as useEffect19, useState as useState20 } from "react";
8325
8804
  function ImportParentFileModal({
8326
8805
  isOpen,
8327
8806
  onClose,
@@ -8332,11 +8811,11 @@ function ImportParentFileModal({
8332
8811
  onFetchAvailableFiles,
8333
8812
  currentViewName
8334
8813
  }) {
8335
- const [activeTab, setActiveTab] = useState19("databases");
8336
- const [availableDbs, setAvailableDbs] = useState19([]);
8337
- const [availableViews, setAvailableViews] = useState19([]);
8338
- const [selectedItem, setSelectedItem] = useState19(null);
8339
- const [isLoading, setIsLoading] = useState19(false);
8814
+ const [activeTab, setActiveTab] = useState20("databases");
8815
+ const [availableDbs, setAvailableDbs] = useState20([]);
8816
+ const [availableViews, setAvailableViews] = useState20([]);
8817
+ const [selectedItem, setSelectedItem] = useState20(null);
8818
+ const [isLoading, setIsLoading] = useState20(false);
8340
8819
  useEffect19(() => {
8341
8820
  if (isOpen && session && onFetchAvailableFiles) {
8342
8821
  const fetchData = async () => {
@@ -8482,7 +8961,7 @@ function ImportParentFileModal({
8482
8961
  }
8483
8962
 
8484
8963
  // src/components/AncestryLinkDetailsPanel.jsx
8485
- import React21, { useState as useState20 } from "react";
8964
+ import React21, { useState as useState21 } from "react";
8486
8965
  import { FiBookOpen as FiBookOpen5 } from "react-icons/fi";
8487
8966
  function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile }) {
8488
8967
  var _a, _b, _c, _d;
@@ -8492,7 +8971,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
8492
8971
  const customProps = extractCustomPropsFromNode(relationshipData);
8493
8972
  const sourceName = ((_b = (_a = data.sourceNode) == null ? void 0 : _a.userData) == null ? void 0 : _b.name) || "Origem";
8494
8973
  const targetName = ((_d = (_c = data.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) || "Destino";
8495
- const [isReadMode, setIsReadMode] = useState20(false);
8974
+ const [isReadMode, setIsReadMode] = useState21(false);
8496
8975
  const swallow = (e) => e.stopPropagation();
8497
8976
  const handleImageClickFromText = (url, name) => {
8498
8977
  if (onOpenImageViewer) {
@@ -8558,14 +9037,14 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
8558
9037
  }
8559
9038
 
8560
9039
  // src/components/AncestryBoard.jsx
8561
- import React22, { useState as useState21, useMemo as useMemo11, useEffect as useEffect20, useRef as useRef16 } from "react";
9040
+ import React22, { useState as useState22, useMemo as useMemo11, useEffect as useEffect20, useRef as useRef16 } from "react";
8562
9041
  import {
8563
9042
  FiSearch as FiSearch4,
8564
9043
  FiLayers as FiLayers6,
8565
9044
  FiCornerUpRight as FiCornerUpRight4,
8566
9045
  FiPlay,
8567
9046
  FiPlus as FiPlus7,
8568
- FiTrash2 as FiTrash22,
9047
+ FiTrash2 as FiTrash23,
8569
9048
  FiArrowLeft as FiArrowLeft3,
8570
9049
  FiArrowRight,
8571
9050
  FiCheckCircle,
@@ -8702,7 +9181,7 @@ var GroupItem = ({
8702
9181
  className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
8703
9182
  title: "Remover Grupo"
8704
9183
  },
8705
- /* @__PURE__ */ React22.createElement(FiTrash22, { size: 14 })
9184
+ /* @__PURE__ */ React22.createElement(FiTrash23, { size: 14 })
8706
9185
  )))), group.children && group.children.length > 0 && /* @__PURE__ */ React22.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ React22.createElement(
8707
9186
  GroupItem,
8708
9187
  {
@@ -8735,11 +9214,11 @@ function AncestryBoard({
8735
9214
  userRole
8736
9215
  // [NOVO] Recebe a role do usuário
8737
9216
  }) {
8738
- const [searchTerm, setSearchTerm] = useState21("");
8739
- const [groups, setGroups] = useState21([]);
8740
- const [isLoaded, setIsLoaded] = useState21(false);
8741
- const [pickingGroupId, setPickingGroupId] = useState21(null);
8742
- const [saveStatus, setSaveStatus] = useState21("idle");
9217
+ const [searchTerm, setSearchTerm] = useState22("");
9218
+ const [groups, setGroups] = useState22([]);
9219
+ const [isLoaded, setIsLoaded] = useState22(false);
9220
+ const [pickingGroupId, setPickingGroupId] = useState22(null);
9221
+ const [saveStatus, setSaveStatus] = useState22("idle");
8743
9222
  const canEdit = useMemo11(() => {
8744
9223
  return userRole !== "viewer";
8745
9224
  }, [userRole]);
@@ -9189,37 +9668,37 @@ function XViewScene({
9189
9668
  const sceneDataRef = useRef17(null);
9190
9669
  const parentDataRef = useRef17(null);
9191
9670
  const ancestryDataRef = useRef17(null);
9192
- const [isLoading, setIsLoading] = useState22(true);
9193
- const [permissionStatus, setPermissionStatus] = useState22("loading");
9194
- const [userPermissionRole, setUserPermissionRole] = useState22(null);
9195
- const [isInitialized, setIsInitialized] = useState22(false);
9196
- const [sceneVersion, setSceneVersion] = useState22(0);
9197
- const [contextMenu, setContextMenu] = useState22({ visible: false, x: 0, y: 0, nodeData: null });
9198
- const [multiContextMenu, setMultiContextMenu] = useState22({ visible: false, x: 0, y: 0, nodeIds: null });
9199
- const [relationshipMenu, setRelationshipMenu] = useState22({ visible: false, x: 0, y: 0, linkObject: null });
9200
- const [creationMode, setCreationMode] = useState22({ isActive: false, sourceNodeData: null });
9201
- const [versionMode, setVersionMode] = useState22({ isActive: false, sourceNodeData: null });
9202
- const [hasFocusedInitial, setHasFocusedInitial] = useState22(false);
9203
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState22(false);
9204
- const [ancestryMode, setAncestryMode] = useState22({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
9205
- const [readingMode, setReadingMode] = useState22({
9671
+ const [isLoading, setIsLoading] = useState23(true);
9672
+ const [permissionStatus, setPermissionStatus] = useState23("loading");
9673
+ const [userPermissionRole, setUserPermissionRole] = useState23(null);
9674
+ const [isInitialized, setIsInitialized] = useState23(false);
9675
+ const [sceneVersion, setSceneVersion] = useState23(0);
9676
+ const [contextMenu, setContextMenu] = useState23({ visible: false, x: 0, y: 0, nodeData: null });
9677
+ const [multiContextMenu, setMultiContextMenu] = useState23({ visible: false, x: 0, y: 0, nodeIds: null });
9678
+ const [relationshipMenu, setRelationshipMenu] = useState23({ visible: false, x: 0, y: 0, linkObject: null });
9679
+ const [creationMode, setCreationMode] = useState23({ isActive: false, sourceNodeData: null });
9680
+ const [versionMode, setVersionMode] = useState23({ isActive: false, sourceNodeData: null });
9681
+ const [hasFocusedInitial, setHasFocusedInitial] = useState23(false);
9682
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState23(false);
9683
+ const [ancestryMode, setAncestryMode] = useState23({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
9684
+ const [readingMode, setReadingMode] = useState23({
9206
9685
  isActive: false,
9207
9686
  ancestry: null,
9208
9687
  branchStack: [],
9209
9688
  autoAbstraction: false
9210
9689
  });
9211
- const [formPosition, setFormPosition] = useState22({ left: 16, top: 16, opacity: 0 });
9212
- const [detailsNode, setDetailsNode] = useState22(null);
9213
- const [detailsLink, setDetailsLink] = useState22(null);
9214
- const [ancestryLinkDetails, setAncestryLinkDetails] = useState22(null);
9215
- const [imageViewer, setImageViewer] = useState22({ visible: false, images: [], startIndex: 0 });
9216
- const [editingAncestryRel, setEditingAncestryRel] = useState22({ visible: false, data: null, path: null });
9217
- const [isImportModalOpen, setIsImportModalOpen] = useState22(false);
9218
- const [importSuccessMessage, setImportSuccessMessage] = useState22("");
9219
- const [highlightedNodeId, setHighlightedNodeId] = useState22(null);
9220
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState22(false);
9221
- const [ancestryBoardData, setAncestryBoardData] = useState22([]);
9222
- const [isSidebarOpen, setIsSidebarOpen] = useState22(false);
9690
+ const [formPosition, setFormPosition] = useState23({ left: 16, top: 16, opacity: 0 });
9691
+ const [detailsNode, setDetailsNode] = useState23(null);
9692
+ const [detailsLink, setDetailsLink] = useState23(null);
9693
+ const [ancestryLinkDetails, setAncestryLinkDetails] = useState23(null);
9694
+ const [imageViewer, setImageViewer] = useState23({ visible: false, images: [], startIndex: 0 });
9695
+ const [editingAncestryRel, setEditingAncestryRel] = useState23({ visible: false, data: null, path: null });
9696
+ const [isImportModalOpen, setIsImportModalOpen] = useState23(false);
9697
+ const [importSuccessMessage, setImportSuccessMessage] = useState23("");
9698
+ const [highlightedNodeId, setHighlightedNodeId] = useState23(null);
9699
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState23(false);
9700
+ const [ancestryBoardData, setAncestryBoardData] = useState23([]);
9701
+ const [isSidebarOpen, setIsSidebarOpen] = useState23(false);
9223
9702
  const mountRef = useRef17(null);
9224
9703
  const tooltipRef = useRef17(null);
9225
9704
  const formRef = useRef17(null);
@@ -9262,6 +9741,12 @@ function XViewScene({
9262
9741
  lastDescriptionLength: 0,
9263
9742
  highlightedNodeId: null
9264
9743
  });
9744
+ const maxReadPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
9745
+ const { width: readModeWidth, isResizing: isReadModeResizing, handlePointerDown: handleReadModeResize } = useResizablePanel({
9746
+ initialWidth: 700,
9747
+ minWidth: 320,
9748
+ maxWidth: maxReadPanelW
9749
+ });
9265
9750
  useEffect21(() => {
9266
9751
  stateRef.current.ancestry = ancestryMode;
9267
9752
  }, [ancestryMode]);
@@ -9286,10 +9771,10 @@ function XViewScene({
9286
9771
  }
9287
9772
  stateRef.current.nodeIdToParentFileMap = map;
9288
9773
  }, [isInitialized, sceneVersion]);
9289
- const handleNavigateBack = useCallback3(() => {
9774
+ const handleNavigateBack = useCallback4(() => {
9290
9775
  router.push("/dashboard/scenes");
9291
9776
  }, [router]);
9292
- const handleConfirmImport = useCallback3(
9777
+ const handleConfirmImport = useCallback4(
9293
9778
  async (importPayload) => {
9294
9779
  var _a2, _b2;
9295
9780
  let files = [];
@@ -9337,7 +9822,6 @@ function XViewScene({
9337
9822
  if (ancestryResponse.success && Array.isArray(ancestryResponse.data)) {
9338
9823
  const viewSpecificAncestries = ancestryResponse.data.filter(
9339
9824
  (anc) => anc._source_file_id === viewToImport.id && !anc.is_private
9340
- // <--- AQUI ESTÁ A TRAVA DE SEGURANÇA
9341
9825
  );
9342
9826
  const processedAncestries = viewSpecificAncestries.map((anc) => ({
9343
9827
  ...anc,
@@ -9388,7 +9872,7 @@ function XViewScene({
9388
9872
  const handleOpenImageViewer = (images, startIndex) => {
9389
9873
  setImageViewer({ visible: true, images, startIndex });
9390
9874
  };
9391
- const tweenToTarget = useCallback3((target, zoomFactor = 1, forcedDirection = null) => {
9875
+ const tweenToTarget = useCallback4((target, zoomFactor = 1, forcedDirection = null) => {
9392
9876
  const { camera, controls, tweenGroup } = stateRef.current;
9393
9877
  if (!camera || !controls || !tweenGroup) return;
9394
9878
  const targetPos = target instanceof THREE3.Mesh ? target.getWorldPosition(new THREE3.Vector3()) : target;
@@ -9411,7 +9895,7 @@ function XViewScene({
9411
9895
  if (!t || typeof t.closest !== "function") return false;
9412
9896
  return !!t.closest(".ui-overlay");
9413
9897
  };
9414
- const buildFullAncestryTree = useCallback3((idTree, nodes, ancestries = []) => {
9898
+ const buildFullAncestryTree = useCallback4((idTree, nodes, ancestries = []) => {
9415
9899
  if (!idTree) return null;
9416
9900
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
9417
9901
  const ancestryMap = new Map(ancestries.map((a) => [String(a.ancestry_id), a]));
@@ -9437,14 +9921,10 @@ function XViewScene({
9437
9921
  return {
9438
9922
  ...branch,
9439
9923
  name: linkedAncestry.name,
9440
- // Sobrescreve nome para exibição
9441
9924
  description: linkedAncestry.description,
9442
- // Sobrescreve descrição
9443
9925
  description_sections: linkedAncestry.description_sections,
9444
9926
  tree: graftedTree,
9445
- // ENXERTA A ÁRVORE AQUI
9446
9927
  isLinked: true
9447
- // Flag útil
9448
9928
  };
9449
9929
  }
9450
9930
  }
@@ -9491,7 +9971,7 @@ function XViewScene({
9491
9971
  }
9492
9972
  return recursiveBuild(idTree);
9493
9973
  }, []);
9494
- const handleActivateTimeline = useCallback3(() => {
9974
+ const handleActivateTimeline = useCallback4(() => {
9495
9975
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
9496
9976
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
9497
9977
  while (timelineIntervalsGroup.children.length > 0) {
@@ -9644,7 +10124,7 @@ function XViewScene({
9644
10124
  }
9645
10125
  });
9646
10126
  }, []);
9647
- const handleVersionTimeline = useCallback3((sourceMesh, versionMeshes) => {
10127
+ const handleVersionTimeline = useCallback4((sourceMesh, versionMeshes) => {
9648
10128
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
9649
10129
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0) return;
9650
10130
  versionMeshes.forEach((mesh) => {
@@ -9837,16 +10317,14 @@ function XViewScene({
9837
10317
  isInitialized,
9838
10318
  permissionStatus,
9839
10319
  focusNodeId,
9840
- // <-- MANTIDO
9841
10320
  focusAncestryId
9842
- // <-- ADICIONADO O focusAncestryId NAS DEPENDÊNCIAS
9843
10321
  ]);
9844
- const isNodeInView = useCallback3((id) => {
10322
+ const isNodeInView = useCallback4((id) => {
9845
10323
  const key = String(id);
9846
10324
  const objs = stateRef.current.nodeObjects || {};
9847
10325
  return !!objs[key];
9848
10326
  }, []);
9849
- const addOrUpdateNodeMesh = useCallback3((nodeData, position, suppressVersionUpdate = false) => {
10327
+ const addOrUpdateNodeMesh = useCallback4((nodeData, position, suppressVersionUpdate = false) => {
9850
10328
  const { graphGroup, nodeObjects, clickableNodes, glowTexture, tweenGroup } = stateRef.current;
9851
10329
  const nodeId = String(nodeData.id);
9852
10330
  if (nodeObjects[nodeId]) {
@@ -10495,7 +10973,7 @@ function XViewScene({
10495
10973
  }
10496
10974
  };
10497
10975
  }, [isInitialized, tweenToTarget, dbSaveUrl, isNodeInView, addOrUpdateNodeMesh, handleActivateTimeline, get_scene_view_data, save_view_data]);
10498
- const handleGhostNodeImageChange = useCallback3((useImage, imageUrl) => {
10976
+ const handleGhostNodeImageChange = useCallback4((useImage, imageUrl) => {
10499
10977
  const { node: ghostNode, line: ghostLine, aura: ghostAura } = stateRef.current.ghostElements;
10500
10978
  const { graphGroup, glowTexture } = stateRef.current;
10501
10979
  if (!ghostNode || !graphGroup) return;
@@ -10537,7 +11015,7 @@ function XViewScene({
10537
11015
  aura: newGhostNode.getObjectByName("aura")
10538
11016
  };
10539
11017
  }, []);
10540
- const handleGhostNodeIntensityChange = useCallback3((newIntensity) => {
11018
+ const handleGhostNodeIntensityChange = useCallback4((newIntensity) => {
10541
11019
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
10542
11020
  if (!ghostNode) return;
10543
11021
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -10558,7 +11036,7 @@ function XViewScene({
10558
11036
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
10559
11037
  }
10560
11038
  }, []);
10561
- const handleDetailNodeIntensityChange = useCallback3((nodeId, newIntensity) => {
11039
+ const handleDetailNodeIntensityChange = useCallback4((nodeId, newIntensity) => {
10562
11040
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
10563
11041
  if (!mesh) return;
10564
11042
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -10704,7 +11182,7 @@ function XViewScene({
10704
11182
  mountRef.current.style.cursor = "default";
10705
11183
  }
10706
11184
  };
10707
- const handleAncestryTreeUpdate = useCallback3((newTree, extraData = null) => {
11185
+ const handleAncestryTreeUpdate = useCallback4((newTree, extraData = null) => {
10708
11186
  setAncestryMode((prev) => {
10709
11187
  const prevTreeStr = JSON.stringify(prev.tree);
10710
11188
  const newTreeStr = JSON.stringify(newTree);
@@ -10774,7 +11252,7 @@ function XViewScene({
10774
11252
  const handleStartVersioning = (nodeData) => {
10775
11253
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
10776
11254
  };
10777
- const handleClearAncestryVisuals = useCallback3((ancestryId) => {
11255
+ const handleClearAncestryVisuals = useCallback4((ancestryId) => {
10778
11256
  const { renderedAncestries, ancestryGroup } = stateRef.current;
10779
11257
  const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
10780
11258
  if (renderIndex !== -1) {
@@ -10788,7 +11266,7 @@ function XViewScene({
10788
11266
  stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
10789
11267
  }
10790
11268
  }, []);
10791
- const handleRenderAncestry = useCallback3(
11269
+ const handleRenderAncestry = useCallback4(
10792
11270
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
10793
11271
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
10794
11272
  if (!ancestryObject || !ancestryObject.tree) {
@@ -11204,7 +11682,7 @@ function XViewScene({
11204
11682
  },
11205
11683
  [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, readingMode.isActive, ancestryMode.isActive]
11206
11684
  );
11207
- const handleRenderAbstractionTree = useCallback3((ancestryObject, targetNodeId = null) => {
11685
+ const handleRenderAbstractionTree = useCallback4((ancestryObject, targetNodeId = null) => {
11208
11686
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11209
11687
  if (!ancestryObject || !ancestryObject.abstraction_tree) return;
11210
11688
  const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
@@ -11265,7 +11743,7 @@ function XViewScene({
11265
11743
  stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
11266
11744
  tweenToTarget(rootTargetPos, 0.7);
11267
11745
  }, [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, handleClearAncestryVisuals]);
11268
- const handleReadModeBranchNav = useCallback3((nodeId, action, direction = "right") => {
11746
+ const handleReadModeBranchNav = useCallback4((nodeId, action, direction = "right") => {
11269
11747
  const { ancestry, branchStack } = readingMode;
11270
11748
  if (!ancestry || !ancestry.tree) return;
11271
11749
  const allAncestries = ancestryDataRef.current || [];
@@ -11303,9 +11781,7 @@ function XViewScene({
11303
11781
  description_sections: branchToOpen.description_sections,
11304
11782
  tree: branchToOpen.tree,
11305
11783
  _originNodeId: nodeId,
11306
- // <--- ID do node pai (link visual)
11307
11784
  _branchDirection: direction
11308
- // <--- Direção para cálculo de posição
11309
11785
  };
11310
11786
  const allowedIds = /* @__PURE__ */ new Set(["preamble", 0, "0"]);
11311
11787
  const branchSections = parseDescriptionSections(branchToOpen.description || "", branchToOpen.description_sections || []);
@@ -11361,7 +11837,6 @@ function XViewScene({
11361
11837
  const parentAncestryObj = {
11362
11838
  ...targetAncestryInfo,
11363
11839
  tree: targetTreeToRender,
11364
- // Re-injeta a origem se o pai também for uma branch aninhada
11365
11840
  _originNodeId: activeParentStackItem ? activeParentStackItem.nodeId : null,
11366
11841
  _branchDirection: activeParentStackItem ? activeParentStackItem.entryDirection : null
11367
11842
  };
@@ -11409,7 +11884,7 @@ function XViewScene({
11409
11884
  }));
11410
11885
  }
11411
11886
  }, [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]);
11412
- const handleReadModeHighlight = useCallback3((nodeId) => {
11887
+ const handleReadModeHighlight = useCallback4((nodeId) => {
11413
11888
  if (stateRef.current.highlightedNodeId !== nodeId) {
11414
11889
  stateRef.current.highlightedNodeId = nodeId;
11415
11890
  }
@@ -11421,7 +11896,6 @@ function XViewScene({
11421
11896
  readingMode.ancestry.tree,
11422
11897
  Object.values(parentDataRef.current).flatMap((f) => f.nodes),
11423
11898
  ancestryDataRef.current
11424
- // <--- Adicionar
11425
11899
  );
11426
11900
  const findNodeInTree = (tree, targetId) => {
11427
11901
  if (!tree) return null;
@@ -11475,7 +11949,6 @@ function XViewScene({
11475
11949
  description_sections: ancestry.description_sections,
11476
11950
  direction: null,
11477
11951
  customProperties: rootProps
11478
- // <--- ADICIONADO
11479
11952
  };
11480
11953
  }
11481
11954
  const fullTree = buildFullAncestryTree(
@@ -11504,7 +11977,6 @@ function XViewScene({
11504
11977
  description_sections: currentMeta.description_sections,
11505
11978
  direction: currentDirection,
11506
11979
  customProperties: branchProps
11507
- // <--- ADICIONADO
11508
11980
  };
11509
11981
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
11510
11982
  const readModeAbstractionTree = useMemo12(() => {
@@ -11519,7 +11991,7 @@ function XViewScene({
11519
11991
  allAncestries
11520
11992
  );
11521
11993
  }, [readingMode.isActive, readingMode.ancestry, buildFullAncestryTree, sceneVersion]);
11522
- const handleStartReadingAncestry = useCallback3(
11994
+ const handleStartReadingAncestry = useCallback4(
11523
11995
  async (ancestryObject) => {
11524
11996
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11525
11997
  if (!ancestryObject || !ancestryObject.tree) {
@@ -11540,7 +12012,6 @@ function XViewScene({
11540
12012
  ancestry: ancestryObject,
11541
12013
  branchStack: [],
11542
12014
  autoAbstraction: shouldAutoRenderAbstraction
11543
- // <--- FLAG ENVIADA PARA A UI
11544
12015
  });
11545
12016
  if (shouldAutoRenderAbstraction) {
11546
12017
  handleRenderAbstractionTree(ancestryObject, null);
@@ -11554,9 +12025,8 @@ function XViewScene({
11554
12025
  }
11555
12026
  },
11556
12027
  [handleRenderAncestry, handleRenderAbstractionTree]
11557
- // <--- DEPENDÊNCIA ADICIONADA
11558
12028
  );
11559
- const handleReadModeSectionChange = useCallback3((activeSectionId) => {
12029
+ const handleReadModeSectionChange = useCallback4((activeSectionId) => {
11560
12030
  const { ancestry, branchStack } = readingMode;
11561
12031
  if (!ancestry || !readingMode.isActive) return;
11562
12032
  let targetObj = ancestry;
@@ -11625,10 +12095,10 @@ function XViewScene({
11625
12095
  }, 0);
11626
12096
  handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
11627
12097
  }, [readingMode, handleRenderAncestry, buildFullAncestryTree, ancestryDataRef.current]);
11628
- const handleCloseReadMode = useCallback3(() => {
12098
+ const handleCloseReadMode = useCallback4(() => {
11629
12099
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
11630
12100
  }, []);
11631
- const handleAncestrySectionChange = useCallback3((activeSectionId, ancestryOverride = null, rotation = 0) => {
12101
+ const handleAncestrySectionChange = useCallback4((activeSectionId, ancestryOverride = null, rotation = 0) => {
11632
12102
  var _a2, _b2;
11633
12103
  const currentMode = stateRef.current.ancestry;
11634
12104
  let targetObj = ancestryOverride;
@@ -11680,7 +12150,7 @@ function XViewScene({
11680
12150
  const renderPayload = { ...targetObj, tree: treeToRender };
11681
12151
  handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
11682
12152
  }, [handleRenderAncestry]);
11683
- const handleEditAncestry = useCallback3(
12153
+ const handleEditAncestry = useCallback4(
11684
12154
  async (ancestryObject) => {
11685
12155
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11686
12156
  if (!ancestryObject || !ancestryObject.tree) {
@@ -11703,10 +12173,8 @@ function XViewScene({
11703
12173
  ...ancestryObject,
11704
12174
  tree: fullTree,
11705
12175
  abstraction_tree: fullAbstractionTree,
11706
- // NOVO
11707
12176
  selectedParentId: ancestryObject.ancestral_node,
11708
12177
  selectedAbstractionParentId: ancestryObject.ancestral_node,
11709
- // NOVO
11710
12178
  isEditMode: true,
11711
12179
  currentAncestryId: ancestryObject.ancestry_id,
11712
12180
  ancestryName: ancestryObject.name || `Ancestralidade ${fullTree.node.name}`,
@@ -11714,7 +12182,6 @@ function XViewScene({
11714
12182
  ancestryDescriptionSections: ancestryObject.description_sections || [],
11715
12183
  isAddingNodes: false,
11716
12184
  isAddingAbstractionNodes: false
11717
- // NOVO
11718
12185
  });
11719
12186
  },
11720
12187
  [handleRenderAncestry, buildFullAncestryTree]
@@ -11722,7 +12189,7 @@ function XViewScene({
11722
12189
  const handleSelectAncestryParent = (nodeId) => {
11723
12190
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
11724
12191
  };
11725
- const handleRemoveFromAncestry = useCallback3((pathToRemove) => {
12192
+ const handleRemoveFromAncestry = useCallback4((pathToRemove) => {
11726
12193
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
11727
12194
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
11728
12195
  return;
@@ -11747,7 +12214,7 @@ function XViewScene({
11747
12214
  return { ...prev, tree: newTree };
11748
12215
  });
11749
12216
  }, []);
11750
- const handleSaveAncestry = useCallback3(
12217
+ const handleSaveAncestry = useCallback4(
11751
12218
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
11752
12219
  const treeToUse = treeOverride || ancestryMode.tree;
11753
12220
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -11951,7 +12418,7 @@ function XViewScene({
11951
12418
  });
11952
12419
  setEditingAncestryRel({ visible: false, data: null, path: null });
11953
12420
  };
11954
- const handleDeleteAncestry = useCallback3(
12421
+ const handleDeleteAncestry = useCallback4(
11955
12422
  async (ancestryIdToDelete) => {
11956
12423
  if (!ancestryIdToDelete) {
11957
12424
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -12013,15 +12480,15 @@ function XViewScene({
12013
12480
  },
12014
12481
  [save_view_data, delete_file_action]
12015
12482
  );
12016
- const handleOpenAncestryBoard = useCallback3(() => {
12483
+ const handleOpenAncestryBoard = useCallback4(() => {
12017
12484
  setIsAncestryBoardOpen(true);
12018
12485
  }, []);
12019
- const handleSelectAncestryFromBoard = useCallback3((ancestry) => {
12486
+ const handleSelectAncestryFromBoard = useCallback4((ancestry) => {
12020
12487
  setIsAncestryBoardOpen(false);
12021
12488
  setIsSidebarOpen(false);
12022
12489
  handleStartReadingAncestry(ancestry);
12023
12490
  }, [handleStartReadingAncestry]);
12024
- const handleSaveAncestryBoard = useCallback3(async (groups) => {
12491
+ const handleSaveAncestryBoard = useCallback4(async (groups) => {
12025
12492
  if (!sceneConfigId || !viewParams || !session) return;
12026
12493
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
12027
12494
  await save_ancestry_board_action(sceneConfigId, sceneType, groups, session, ownerId);
@@ -12045,13 +12512,13 @@ function XViewScene({
12045
12512
  return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
12046
12513
  });
12047
12514
  }, [parentDataRef.current, sceneVersion]);
12048
- const handleAddExistingNode = useCallback3(
12515
+ const handleAddExistingNode = useCallback4(
12049
12516
  (nodeId) => {
12050
12517
  return userActionHandlers.handleAddExistingNodeById(actionHandlerContext, nodeId);
12051
12518
  },
12052
12519
  [actionHandlerContext]
12053
12520
  );
12054
- const handleSaveCurrentView = useCallback3(async () => {
12521
+ const handleSaveCurrentView = useCallback4(async () => {
12055
12522
  const { nodeObjects, allLinks } = stateRef.current;
12056
12523
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
12057
12524
  console.warn("N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente.");
@@ -12091,7 +12558,7 @@ function XViewScene({
12091
12558
  const allAvailableAncestries = useMemo12(() => {
12092
12559
  return ancestryDataRef.current || [];
12093
12560
  }, [sceneVersion, isInitialized]);
12094
- const handleOpenReference = useCallback3((referenceData) => {
12561
+ const handleOpenReference = useCallback4((referenceData) => {
12095
12562
  const { type, id } = referenceData;
12096
12563
  if (type === "node") {
12097
12564
  const targetNode = allAvailableNodes.find((n) => String(n.id) === String(id));
@@ -12118,10 +12585,10 @@ function XViewScene({
12118
12585
  }
12119
12586
  }
12120
12587
  }, [allAvailableNodes, allAvailableAncestries, handleEditAncestry, tweenToTarget]);
12121
- const handleToggleAncestryAddMode = useCallback3(() => {
12588
+ const handleToggleAncestryAddMode = useCallback4(() => {
12122
12589
  setAncestryMode((prev) => ({ ...prev, isAddingNodes: !prev.isAddingNodes }));
12123
12590
  }, []);
12124
- const handleFocusNode = useCallback3((nodeData) => {
12591
+ const handleFocusNode = useCallback4((nodeData) => {
12125
12592
  if (!nodeData) return;
12126
12593
  const nodeMesh = stateRef.current.nodeObjects[String(nodeData.id)];
12127
12594
  if (nodeMesh) {
@@ -12191,7 +12658,6 @@ function XViewScene({
12191
12658
  height: "100vh",
12192
12659
  position: "relative",
12193
12660
  overflow: "hidden",
12194
- // <--- ADICIONE ESTA LINHA
12195
12661
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
12196
12662
  }
12197
12663
  },
@@ -12258,9 +12724,20 @@ function XViewScene({
12258
12724
  readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React23.createElement(
12259
12725
  "div",
12260
12726
  {
12261
- className: "ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col transition-all duration-300 ease-out w-[min(92vw,700px)]",
12262
- style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)" }
12727
+ className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col ${isReadModeResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
12728
+ style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${readModeWidth}px`, maxWidth: "92vw" }
12263
12729
  },
12730
+ /* @__PURE__ */ React23.createElement(
12731
+ "div",
12732
+ {
12733
+ onPointerDown: (e) => {
12734
+ e.stopPropagation();
12735
+ handleReadModeResize(e);
12736
+ },
12737
+ className: "absolute left-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-indigo-500/50 z-[2000] transition-colors",
12738
+ title: "Arraste para redimensionar"
12739
+ }
12740
+ ),
12264
12741
  /* @__PURE__ */ React23.createElement(
12265
12742
  DescriptionReadModePanel,
12266
12743
  {