@lv-x-software-house/x_view 1.2.2-dev.8 → 1.2.2

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 +1386 -895
  2. package/dist/index.mjs +849 -357
  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)
@@ -4216,15 +4419,14 @@ var renderTextWithMentions = (text, availableNodes, onMentionClick, activeMentio
4216
4419
  className: `
4217
4420
  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
4421
  ${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}`
4422
+ `
4221
4423
  },
4222
4424
  /* @__PURE__ */ React6.createElement("span", { className: "opacity-60 text-[0.8em]" }, "@"),
4223
4425
  displayName
4224
4426
  );
4225
4427
  });
4226
4428
  };
4227
- var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick) => {
4429
+ var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick, onToggleCheckbox, globalCheckboxCounterRef) => {
4228
4430
  const trimmedLine = line.replace(/\r$/, "");
4229
4431
  const processContent = (content) => renderTextWithMentions(content, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick);
4230
4432
  if (line.startsWith("# ")) {
@@ -4235,9 +4437,46 @@ var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionInd
4235
4437
  const content = line.replace("## ", "");
4236
4438
  return /* @__PURE__ */ React6.createElement("span", { className: "text-sm sm:text-base font-semibold text-indigo-200 leading-tight break-words" }, processContent(content));
4237
4439
  }
4440
+ const checkboxMatch = trimmedLine.match(/^(\s*)- \[([ xX])\]\s+(.*)/);
4441
+ if (checkboxMatch) {
4442
+ const [_, space, state, content] = checkboxMatch;
4443
+ const isChecked = state.toLowerCase() === "x";
4444
+ const currentIdx = globalCheckboxCounterRef.current;
4445
+ globalCheckboxCounterRef.current += 1;
4446
+ return /* @__PURE__ */ React6.createElement("span", { className: "flex items-start gap-2.5 my-1 break-words ml-1 group/checkbox" }, /* @__PURE__ */ React6.createElement(
4447
+ "div",
4448
+ {
4449
+ onClick: (e) => {
4450
+ e.stopPropagation();
4451
+ if (onToggleCheckbox) onToggleCheckbox(currentIdx);
4452
+ },
4453
+ className: `mt-1 cursor-pointer w-4 h-4 rounded border flex-shrink-0 flex items-center justify-center transition-all duration-200
4454
+ ${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"}
4455
+ `
4456
+ },
4457
+ isChecked && /* @__PURE__ */ React6.createElement(FiCheck3, { size: 12, className: "text-white" })
4458
+ ), /* @__PURE__ */ React6.createElement(
4459
+ "span",
4460
+ {
4461
+ className: `transition-all duration-200 cursor-pointer pt-[1px]
4462
+ ${isChecked ? "line-through text-slate-500" : "text-slate-200 group-hover/checkbox:text-white"}
4463
+ `,
4464
+ onClick: (e) => {
4465
+ e.stopPropagation();
4466
+ if (onToggleCheckbox) onToggleCheckbox(currentIdx);
4467
+ }
4468
+ },
4469
+ processContent(content)
4470
+ ));
4471
+ }
4472
+ const numberMatch = trimmedLine.match(/^(\s*)(\d+\.)\s+(.*)/);
4473
+ if (numberMatch) {
4474
+ const [_, space, numberStr, content] = numberMatch;
4475
+ 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)));
4476
+ }
4238
4477
  if (trimmedLine.trim().startsWith("- ") || trimmedLine.trim().startsWith("* ")) {
4239
4478
  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));
4479
+ 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
4480
  }
4242
4481
  return /* @__PURE__ */ React6.createElement("span", { className: "break-words" }, processContent(line));
4243
4482
  };
@@ -4249,14 +4488,33 @@ function DescriptionDisplay({
4249
4488
  onOpenReference,
4250
4489
  onMentionClick,
4251
4490
  onImageClick,
4252
- // <--- NOVA PROP RECEBIDA
4253
4491
  onSectionChange,
4254
4492
  onBranchNav,
4255
4493
  onHighlightNode,
4256
4494
  initialSectionId,
4257
- currentBranchDirection = null
4495
+ currentBranchDirection = null,
4496
+ onSaveDescription,
4497
+ onStepChange
4498
+ // 1. Adicione a nova prop aqui
4258
4499
  }) {
4259
- const sections = useMemo5(() => parseDescriptionSections(description, savedSections), [description, savedSections]);
4500
+ const [localDescription, setLocalDescription] = useState7(description || "");
4501
+ useEffect6(() => {
4502
+ setLocalDescription(description || "");
4503
+ }, [description]);
4504
+ const sections = useMemo5(() => parseDescriptionSections(localDescription, savedSections), [localDescription, savedSections]);
4505
+ const globalCheckboxCounterRef = useRef6(0);
4506
+ const handleToggleCheckbox = (targetIndex) => {
4507
+ let currentIndex = 0;
4508
+ const newDesc = localDescription.replace(/^(\s*)- \[([ xX])\]/gm, (match, space, state) => {
4509
+ if (currentIndex === targetIndex) {
4510
+ currentIndex++;
4511
+ return state === " " ? `${space}- [x]` : `${space}- [ ]`;
4512
+ }
4513
+ currentIndex++;
4514
+ return match;
4515
+ });
4516
+ setLocalDescription(newDesc);
4517
+ };
4260
4518
  const flatNavigation = useMemo5(() => {
4261
4519
  const navItems = [];
4262
4520
  sections.forEach((section, sIdx) => {
@@ -4283,7 +4541,12 @@ function DescriptionDisplay({
4283
4541
  });
4284
4542
  return navItems;
4285
4543
  }, [sections]);
4286
- const [currentStepIndex, setCurrentStepIndex] = useState6(0);
4544
+ const [currentStepIndex, setCurrentStepIndex] = useState7(0);
4545
+ useEffect6(() => {
4546
+ if (onStepChange) {
4547
+ onStepChange(currentStepIndex);
4548
+ }
4549
+ }, [currentStepIndex, onStepChange]);
4287
4550
  const activeRef = useRef6(null);
4288
4551
  const lastNotifiedSectionId = useRef6(null);
4289
4552
  const isInitialMount = useRef6(true);
@@ -4397,26 +4660,27 @@ function DescriptionDisplay({
4397
4660
  }
4398
4661
  const lines = part.replace(/\n$/, "").split("\n");
4399
4662
  return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: `text-${parentIndex}-${partIndex}` }, lines.map((line, lineIndex) => {
4400
- const isLastLine = lineIndex === lines.length - 1;
4401
4663
  const isEmptyLine = line.trim() === "";
4402
4664
  if (isEmptyLine) {
4403
4665
  return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: `${parentIndex}-${partIndex}-${lineIndex}` }, /* @__PURE__ */ React6.createElement("br", null));
4404
4666
  }
4405
4667
  return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: `${parentIndex}-${partIndex}-${lineIndex}` }, /* @__PURE__ */ React6.createElement(
4406
- "span",
4668
+ "div",
4407
4669
  {
4408
4670
  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);
4671
+ onClick: (e) => {
4672
+ if (e.target.type !== "checkbox") {
4673
+ const idx = flatNavigation.findIndex((item) => item.type === "section" && item.sectionIndex === parentIndex);
4674
+ if (idx !== -1) setCurrentStepIndex(idx);
4675
+ }
4412
4676
  },
4413
4677
  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"}
4678
+ transition-colors duration-200 cursor-pointer rounded-md px-1 py-0.5 -mx-1 box-decoration-clone inline-block w-full
4679
+ ${isActiveSection ? "bg-indigo-500/10 text-white ring-1 ring-indigo-500/30" : "hover:bg-white/5 hover:text-slate-200"}
4416
4680
  `
4417
4681
  },
4418
- formatLineContent2(line, availableNodes, onMentionClick, isActiveSection ? activeMentionIndex : -1, mentionCounterRef, setRef, onImageClick)
4419
- ), !isLastLine && /* @__PURE__ */ React6.createElement("br", null));
4682
+ formatLineContent2(line, availableNodes, onMentionClick, isActiveSection ? activeMentionIndex : -1, mentionCounterRef, setRef, onImageClick, handleToggleCheckbox, globalCheckboxCounterRef)
4683
+ ));
4420
4684
  }));
4421
4685
  });
4422
4686
  };
@@ -4434,8 +4698,7 @@ function DescriptionDisplay({
4434
4698
  if (onOpenReference) {
4435
4699
  onOpenReference({ type: resolved.type, id: resolved.sourceId });
4436
4700
  }
4437
- },
4438
- title: `Ir para ${resolved.type === "node" ? "Node" : "Ancestralidade"}: ${resolved.sourceName}`
4701
+ }
4439
4702
  },
4440
4703
  /* @__PURE__ */ React6.createElement(FiCornerDownRight, { size: 12, className: "text-indigo-400" }),
4441
4704
  /* @__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 +4707,9 @@ function DescriptionDisplay({
4444
4707
  ${isActiveSection ? "opacity-100" : "opacity-90"}
4445
4708
  ` }, renderMixedContent(resolved.content, index, isActiveSection, -1, setRef)));
4446
4709
  };
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) => {
4710
+ globalCheckboxCounterRef.current = 0;
4711
+ const hasUnsavedChanges = localDescription !== (description || "");
4712
+ 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
4713
  const currentNavItem = flatNavigation[currentStepIndex];
4449
4714
  const isSectionContextActive = currentNavItem && currentNavItem.sectionIndex === index;
4450
4715
  const activeMentionIndex = isSectionContextActive && currentNavItem.type === "mention" ? currentNavItem.mentionIndex : -1;
@@ -4460,11 +4725,22 @@ function DescriptionDisplay({
4460
4725
  if (index === 0) leadingSpace = "";
4461
4726
  const isRef = bodyText.trim().match(/^\[\[REF:(node|ancestry):([a-zA-Z0-9\-_]+):([a-zA-Z0-9\-_]+)\]\]$/);
4462
4727
  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
- }));
4728
+ })), 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(
4729
+ "button",
4730
+ {
4731
+ onClick: (e) => {
4732
+ e.stopPropagation();
4733
+ onSaveDescription(localDescription);
4734
+ },
4735
+ 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"
4736
+ },
4737
+ /* @__PURE__ */ React6.createElement(FiSave, { size: 12 }),
4738
+ " Salvar Checklist"
4739
+ )));
4464
4740
  }
4465
4741
 
4466
4742
  // src/components/DescriptionReadModePanel.jsx
4467
- import React7, { useState as useState7, useMemo as useMemo6, useEffect as useEffect7 } from "react";
4743
+ import React7, { useState as useState8, useMemo as useMemo6, useEffect as useEffect7 } from "react";
4468
4744
  import {
4469
4745
  FiArrowLeft,
4470
4746
  FiEdit2,
@@ -4543,7 +4819,6 @@ function DescriptionReadModePanel({
4543
4819
  title,
4544
4820
  description,
4545
4821
  ancestryId,
4546
- // <-- NOVO: Prop recebida do XViewScene
4547
4822
  savedSections,
4548
4823
  onBack,
4549
4824
  onEdit,
@@ -4565,12 +4840,14 @@ function DescriptionReadModePanel({
4565
4840
  userRole,
4566
4841
  abstractionTree = null,
4567
4842
  onRenderAbstractionTree = null,
4568
- initialShowAbstraction = false
4843
+ initialShowAbstraction = false,
4844
+ onSaveDescription
4569
4845
  }) {
4570
- const [showProperties, setShowProperties] = useState7(false);
4571
- const [showAbstraction, setShowAbstraction] = useState7(false);
4572
- const [targetRenderNodeId, setTargetRenderNodeId] = useState7(null);
4573
- const [isLinkCopied, setIsLinkCopied] = useState7(false);
4846
+ const [showProperties, setShowProperties] = useState8(false);
4847
+ const [showAbstraction, setShowAbstraction] = useState8(false);
4848
+ const [targetRenderNodeId, setTargetRenderNodeId] = useState8(null);
4849
+ const [isLinkCopied, setIsLinkCopied] = useState8(false);
4850
+ const [isAtStartOfBranch, setIsAtStartOfBranch] = useState8(true);
4574
4851
  const handleCopyLink = (e) => {
4575
4852
  e.stopPropagation();
4576
4853
  if (!ancestryId) return;
@@ -4623,7 +4900,7 @@ function DescriptionReadModePanel({
4623
4900
  onClick: () => onBranchNav(activeNodeBranches.nodeId, "open", "left")
4624
4901
  };
4625
4902
  }
4626
- if ((backNavigationInfo == null ? void 0 : backNavigationInfo.trigger) === "left") {
4903
+ if ((backNavigationInfo == null ? void 0 : backNavigationInfo.trigger) === "left" && isAtStartOfBranch) {
4627
4904
  return {
4628
4905
  type: "back",
4629
4906
  name: backNavigationInfo.name,
@@ -4631,7 +4908,7 @@ function DescriptionReadModePanel({
4631
4908
  };
4632
4909
  }
4633
4910
  return null;
4634
- }, [activeNodeBranches, backNavigationInfo, onBranchNav]);
4911
+ }, [activeNodeBranches, backNavigationInfo, onBranchNav, isAtStartOfBranch]);
4635
4912
  const rightAction = useMemo6(() => {
4636
4913
  if (activeNodeBranches == null ? void 0 : activeNodeBranches.right) {
4637
4914
  return {
@@ -4640,7 +4917,7 @@ function DescriptionReadModePanel({
4640
4917
  onClick: () => onBranchNav(activeNodeBranches.nodeId, "open", "right")
4641
4918
  };
4642
4919
  }
4643
- if ((backNavigationInfo == null ? void 0 : backNavigationInfo.trigger) === "right") {
4920
+ if ((backNavigationInfo == null ? void 0 : backNavigationInfo.trigger) === "right" && isAtStartOfBranch) {
4644
4921
  return {
4645
4922
  type: "back",
4646
4923
  name: backNavigationInfo.name,
@@ -4648,11 +4925,11 @@ function DescriptionReadModePanel({
4648
4925
  };
4649
4926
  }
4650
4927
  return null;
4651
- }, [activeNodeBranches, backNavigationInfo, onBranchNav]);
4928
+ }, [activeNodeBranches, backNavigationInfo, onBranchNav, isAtStartOfBranch]);
4652
4929
  return /* @__PURE__ */ React7.createElement(
4653
4930
  "div",
4654
4931
  {
4655
- className: "flex flex-col h-full w-full bg-slate-950/50 relative overflow-hidden group",
4932
+ className: "flex flex-col h-full max-h-full w-full bg-slate-950/50 relative overflow-hidden group min-h-0",
4656
4933
  onPointerDown: swallow,
4657
4934
  onClick: swallow
4658
4935
  },
@@ -4724,7 +5001,7 @@ function DescriptionReadModePanel({
4724
5001
  },
4725
5002
  "\xD7"
4726
5003
  ))),
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(
5004
+ /* @__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
5005
  "button",
4729
5006
  {
4730
5007
  onClick: (e) => {
@@ -4783,7 +5060,9 @@ function DescriptionReadModePanel({
4783
5060
  onHighlightNode,
4784
5061
  initialSectionId,
4785
5062
  currentBranchDirection,
4786
- onImageClick
5063
+ onImageClick,
5064
+ onSaveDescription,
5065
+ onStepChange: (stepIndex) => setIsAtStartOfBranch(stepIndex === 0)
4787
5066
  }
4788
5067
  )),
4789
5068
  leftAction && !showAbstraction && !showProperties && /* @__PURE__ */ React7.createElement(
@@ -4825,11 +5104,11 @@ function AncestryRelationshipPanel({
4825
5104
  onMentionClick,
4826
5105
  onUploadFile
4827
5106
  }) {
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);
5107
+ const [description, setDescription] = useState9((data == null ? void 0 : data.description) ?? "");
5108
+ const [customProps, setCustomProps] = useState9(() => extractCustomPropsFromNode(data || {}));
5109
+ const [existingSections, setExistingSections] = useState9((data == null ? void 0 : data.description_sections) || []);
5110
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState9(false);
5111
+ const [isReadMode, setIsReadMode] = useState9(false);
4833
5112
  const propsEndRef = useRef7(null);
4834
5113
  useEffect8(() => {
4835
5114
  setDescription((data == null ? void 0 : data.description) ?? "");
@@ -4853,6 +5132,17 @@ function AncestryRelationshipPanel({
4853
5132
  return newProps;
4854
5133
  });
4855
5134
  };
5135
+ const handleSaveDescriptionInline = (newDescription) => {
5136
+ setDescription(newDescription);
5137
+ const extrasObj = toObjectFromCustomProps(customProps.filter((p) => !p.isEditing));
5138
+ const processedSections = processDescriptionForSave(newDescription, existingSections);
5139
+ const dataToSave = {
5140
+ description: newDescription,
5141
+ description_sections: processedSections,
5142
+ ...extrasObj
5143
+ };
5144
+ onSave(dataToSave);
5145
+ };
4856
5146
  const handleSave = () => {
4857
5147
  const extrasObj = toObjectFromCustomProps(customProps.filter((p) => !p.isEditing));
4858
5148
  const processedSections = processDescriptionForSave(description, existingSections);
@@ -4902,7 +5192,8 @@ function AncestryRelationshipPanel({
4902
5192
  availableAncestries,
4903
5193
  onOpenReference,
4904
5194
  onMentionClick,
4905
- onImageClick: handleImageClickFromText
5195
+ onImageClick: handleImageClickFromText,
5196
+ onSaveDescription: handleSaveDescriptionInline
4906
5197
  }
4907
5198
  ) : /* @__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
5199
  DescriptionDisplay,
@@ -4913,7 +5204,8 @@ function AncestryRelationshipPanel({
4913
5204
  availableAncestries,
4914
5205
  onOpenReference,
4915
5206
  onMentionClick,
4916
- onImageClick: handleImageClickFromText
5207
+ onImageClick: handleImageClickFromText,
5208
+ onSaveDescription: handleSaveDescriptionInline
4917
5209
  }
4918
5210
  ), /* @__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
5211
  "button",
@@ -4971,7 +5263,7 @@ function AncestryRelationshipPanel({
4971
5263
  }
4972
5264
 
4973
5265
  // src/components/CreateAncestryPanel.jsx
4974
- import React10, { useState as useState10, useEffect as useEffect10, useMemo as useMemo8, useRef as useRef8, useCallback } from "react";
5266
+ import React10, { useState as useState11, useEffect as useEffect10, useMemo as useMemo8, useRef as useRef8, useCallback as useCallback2 } from "react";
4975
5267
  import {
4976
5268
  FiEdit2 as FiEdit23,
4977
5269
  FiBookOpen as FiBookOpen2,
@@ -4987,11 +5279,12 @@ import {
4987
5279
  FiGitBranch as FiGitBranch2,
4988
5280
  FiPlus as FiPlus2,
4989
5281
  FiLock,
4990
- FiLink as FiLink4
5282
+ FiLink as FiLink4,
5283
+ FiTrash2 as FiTrash22
4991
5284
  } from "react-icons/fi";
4992
5285
 
4993
5286
  // src/components/AncestryPickerModal.jsx
4994
- import React9, { useState as useState9, useMemo as useMemo7, useEffect as useEffect9 } from "react";
5287
+ import React9, { useState as useState10, useMemo as useMemo7, useEffect as useEffect9 } from "react";
4995
5288
  import { FiSearch as FiSearch3, FiLayers as FiLayers4, FiCornerUpRight as FiCornerUpRight2 } from "react-icons/fi";
4996
5289
  function AncestryPickerModal({
4997
5290
  isOpen,
@@ -5001,7 +5294,7 @@ function AncestryPickerModal({
5001
5294
  availableNodes = [],
5002
5295
  currentAncestryId
5003
5296
  }) {
5004
- const [searchTerm, setSearchTerm] = useState9("");
5297
+ const [searchTerm, setSearchTerm] = useState10("");
5005
5298
  useEffect9(() => {
5006
5299
  if (!isOpen) return;
5007
5300
  const handleKeyDown = (e) => {
@@ -5086,7 +5379,7 @@ var NodeItem = ({ nodeData, onSelectParent, onViewSelect, highlightedPathIds = [
5086
5379
  var _a, _b;
5087
5380
  const itemId = nodeData.is_section ? nodeData.id : (_a = nodeData.node) == null ? void 0 : _a.id;
5088
5381
  const itemName = nodeData.is_section ? nodeData.name : (_b = nodeData.node) == null ? void 0 : _b.name;
5089
- const [isDragOver, setIsDragOver] = useState10(false);
5382
+ const [isDragOver, setIsDragOver] = useState11(false);
5090
5383
  const isSelectedParent = String(selectedParentId) === String(itemId);
5091
5384
  const isTargetViewNode = String(targetRenderNodeId) === String(itemId);
5092
5385
  const isHighlightedPath = highlightedPathIds.includes(String(itemId));
@@ -5222,8 +5515,9 @@ function CreateAncestryPanel({
5222
5515
  isAddingNodes,
5223
5516
  currentAncestryId
5224
5517
  } = ancestryMode;
5225
- const [isSaving, setIsSaving] = useState10(false);
5226
- const [isLinkCopied, setIsLinkCopied] = useState10(false);
5518
+ const [isSaving, setIsSaving] = useState11(false);
5519
+ const [isLinkCopied, setIsLinkCopied] = useState11(false);
5520
+ const [showDeleteBranchConfirm, setShowDeleteBranchConfirm] = useState11(false);
5227
5521
  const handleCopyLink = (e) => {
5228
5522
  e.stopPropagation();
5229
5523
  if (!currentAncestryId || currentAncestryId === "temp_root" || currentAncestryId === "temp_creating") {
@@ -5237,11 +5531,14 @@ function CreateAncestryPanel({
5237
5531
  setTimeout(() => setIsLinkCopied(false), 2e3);
5238
5532
  }).catch((err) => console.error("Erro ao copiar link:", err));
5239
5533
  };
5240
- const [isPickerOpen, setIsPickerOpen] = useState10(false);
5241
- const [customProps, setCustomProps] = useState10([]);
5534
+ const [isPickerOpen, setIsPickerOpen] = useState11(false);
5535
+ const [customProps, setCustomProps] = useState11([]);
5242
5536
  const propsEndRef = useRef8(null);
5243
- const [branchStack, setBranchStack] = useState10([]);
5244
- const [targetRenderNodeId, setTargetRenderNodeId] = useState10(null);
5537
+ const [branchStack, setBranchStack] = useState11([]);
5538
+ useEffect10(() => {
5539
+ setShowDeleteBranchConfirm(false);
5540
+ }, [branchStack]);
5541
+ const [targetRenderNodeId, setTargetRenderNodeId] = useState11(null);
5245
5542
  const highlightedPathIds = useMemo8(() => {
5246
5543
  var _a, _b;
5247
5544
  if (!targetRenderNodeId || !ancestryMode.abstraction_tree) return [];
@@ -5255,17 +5552,27 @@ function CreateAncestryPanel({
5255
5552
  }
5256
5553
  return ids;
5257
5554
  }, [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);
5555
+ const [targetScrollSectionId, setTargetScrollSectionId] = useState11(null);
5556
+ const [internalHighlightedNodeId, setInternalHighlightedNodeId] = useState11(null);
5557
+ const [isAtStartOfBranch, setIsAtStartOfBranch] = useState11(true);
5558
+ const [ancestryName, setAncestryName] = useState11(initialName);
5559
+ const [description, setDescription] = useState11(initialDescription || "");
5560
+ const [existingSections, setExistingSections] = useState11(initialSections || []);
5561
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState11(false);
5562
+ const [isReadMode, setIsReadMode] = useState11(false);
5563
+ const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
5564
+ const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
5565
+ initialWidth: isReadMode ? 700 : 440,
5566
+ minWidth: 320,
5567
+ maxWidth: maxPanelW
5568
+ });
5569
+ useEffect10(() => {
5570
+ setWidth(isReadMode ? 700 : 440);
5571
+ }, [isReadMode, setWidth]);
5265
5572
  const currentMaxRenderIndexRef = useRef8(0);
5266
5573
  const branchProgressMapRef = useRef8({});
5267
- const [lastSavedSnapshot, setLastSavedSnapshot] = useState10(null);
5268
- const [isPrivate, setIsPrivate] = useState10(ancestryMode.is_private || false);
5574
+ const [lastSavedSnapshot, setLastSavedSnapshot] = useState11(null);
5575
+ const [isPrivate, setIsPrivate] = useState11(ancestryMode.is_private || false);
5269
5576
  const initializedContextIdRef = useRef8(null);
5270
5577
  const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
5271
5578
  const handleImageClickFromText = (url, name) => {
@@ -5284,7 +5591,7 @@ function CreateAncestryPanel({
5284
5591
  }
5285
5592
  setAncestryMode((prev) => isAbstraction ? { ...prev, isAddingAbstractionNodes: !prev.isAddingAbstractionNodes } : { ...prev, isAddingNodes: !prev.isAddingNodes });
5286
5593
  };
5287
- const handleRemoveNode = useCallback((pathToRemove, isAbstraction = false) => {
5594
+ const handleRemoveNode = useCallback2((pathToRemove, isAbstraction = false) => {
5288
5595
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) return;
5289
5596
  const treeKey = isAbstraction ? "abstraction_tree" : "tree";
5290
5597
  setAncestryMode((prev) => {
@@ -5641,6 +5948,59 @@ function CreateAncestryPanel({
5641
5948
  }
5642
5949
  }
5643
5950
  };
5951
+ const handleDeleteBranch = async () => {
5952
+ if (branchStack.length === 0) return;
5953
+ const rootTreeClone = JSON.parse(JSON.stringify(ancestryMode.tree));
5954
+ let ptr = rootTreeClone;
5955
+ for (let i = 0; i < branchStack.length - 1; i++) {
5956
+ const step = branchStack[i];
5957
+ const found = findNodePath2(ptr, step.nodeId);
5958
+ if (found && found.node.parallel_branches) {
5959
+ const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
5960
+ if (branch) ptr = branch.tree;
5961
+ }
5962
+ }
5963
+ const currentStep = branchStack[branchStack.length - 1];
5964
+ const foundParentPath = findNodePath2(ptr, currentStep.nodeId);
5965
+ if (foundParentPath && foundParentPath.node && foundParentPath.node.parallel_branches) {
5966
+ const branchIndex = foundParentPath.node.parallel_branches.findIndex((b) => b.id === currentStep.branchId);
5967
+ if (branchIndex !== -1) {
5968
+ foundParentPath.node.parallel_branches.splice(branchIndex, 1);
5969
+ updateGlobalTree(rootTreeClone);
5970
+ try {
5971
+ setIsSaving(true);
5972
+ const currentRootProps = extractCustomPropsFromNode(ancestryMode);
5973
+ const rootExtras = toObjectFromCustomProps(currentRootProps);
5974
+ await onSave(
5975
+ ancestryMode.ancestryName,
5976
+ ancestryMode.ancestryDescription,
5977
+ ancestryMode.ancestryDescriptionSections,
5978
+ true,
5979
+ rootTreeClone,
5980
+ rootExtras
5981
+ );
5982
+ setLastSavedSnapshot(takeSnapshot(
5983
+ rootTreeClone,
5984
+ ancestryMode.ancestryName,
5985
+ ancestryMode.ancestryDescription,
5986
+ ancestryMode.ancestryDescriptionSections,
5987
+ currentRootProps,
5988
+ isPrivate,
5989
+ ancestryMode.abstraction_tree
5990
+ ));
5991
+ if (onClearAncestryVisuals) {
5992
+ onClearAncestryVisuals(currentStep.branchId);
5993
+ }
5994
+ handleNavigateUp();
5995
+ } catch (err) {
5996
+ console.error("Erro ao remover a ramifica\xE7\xE3o:", err);
5997
+ alert("Erro ao remover a ramifica\xE7\xE3o.");
5998
+ } finally {
5999
+ setIsSaving(false);
6000
+ }
6001
+ }
6002
+ }
6003
+ };
5644
6004
  const sideActions = useMemo8(() => {
5645
6005
  const actions = { left: null, right: null };
5646
6006
  const isInBranch = branchStack.length > 0;
@@ -5679,7 +6039,7 @@ function CreateAncestryPanel({
5679
6039
  }
5680
6040
  return actions;
5681
6041
  }
5682
- if (isInBranch) {
6042
+ if (isInBranch && isAtStartOfBranch) {
5683
6043
  const lastStep = branchStack[branchStack.length - 1];
5684
6044
  const entryDir = lastStep.entryDirection || "right";
5685
6045
  const backSide = entryDir === "right" ? "left" : "right";
@@ -5690,7 +6050,7 @@ function CreateAncestryPanel({
5690
6050
  };
5691
6051
  }
5692
6052
  return actions;
5693
- }, [internalHighlightedNodeId, branchStack, activeTree]);
6053
+ }, [internalHighlightedNodeId, branchStack, activeTree, isAtStartOfBranch]);
5694
6054
  const applyDescriptionToTree = (baseTree, descText, descSections) => {
5695
6055
  const rootTreeClone = JSON.parse(JSON.stringify(baseTree));
5696
6056
  let targetTree = rootTreeClone;
@@ -6168,6 +6528,10 @@ function CreateAncestryPanel({
6168
6528
  setInternalHighlightedNodeId(id);
6169
6529
  if (onHighlightNode) onHighlightNode(id);
6170
6530
  };
6531
+ const handleSaveDescriptionInline = (newDesc) => {
6532
+ setDescription(newDesc);
6533
+ handleLocalSave(true, { description: newDesc });
6534
+ };
6171
6535
  const swallow = (e) => e.stopPropagation();
6172
6536
  const getSelectedParentName = () => {
6173
6537
  if (!activeTree || !selectedParentId) return "";
@@ -6240,10 +6604,8 @@ function CreateAncestryPanel({
6240
6604
  return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(
6241
6605
  "div",
6242
6606
  {
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)" },
6607
+ 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"}`,
6608
+ style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${panelWidth}px`, maxWidth: "92vw" },
6247
6609
  onPointerDown: swallow,
6248
6610
  onPointerMove: swallow,
6249
6611
  onPointerUp: swallow,
@@ -6252,6 +6614,17 @@ function CreateAncestryPanel({
6252
6614
  onContextMenu: swallow,
6253
6615
  onDoubleClick: swallow
6254
6616
  },
6617
+ /* @__PURE__ */ React10.createElement(
6618
+ "div",
6619
+ {
6620
+ onPointerDown: (e) => {
6621
+ e.stopPropagation();
6622
+ handleResize(e);
6623
+ },
6624
+ className: "absolute left-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-indigo-500/50 z-[2000] transition-colors",
6625
+ title: "Arraste para redimensionar"
6626
+ }
6627
+ ),
6255
6628
  isReadMode ? /* @__PURE__ */ React10.createElement(
6256
6629
  DescriptionReadModePanel,
6257
6630
  {
@@ -6270,7 +6643,8 @@ function CreateAncestryPanel({
6270
6643
  onMentionClick,
6271
6644
  onSectionChange: handleSectionChangeWrapper,
6272
6645
  onHighlightNode,
6273
- onImageClick: handleImageClickFromText
6646
+ onImageClick: handleImageClickFromText,
6647
+ onSaveDescription: handleSaveDescriptionInline
6274
6648
  }
6275
6649
  ) : /* @__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
6650
  "button",
@@ -6289,7 +6663,7 @@ function CreateAncestryPanel({
6289
6663
  placeholder: "Nome da Ancestralidade",
6290
6664
  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
6665
  }
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(
6666
+ )), /* @__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
6667
  "button",
6294
6668
  {
6295
6669
  onClick: handleNavigateUp,
@@ -6297,7 +6671,33 @@ function CreateAncestryPanel({
6297
6671
  },
6298
6672
  /* @__PURE__ */ React10.createElement(FiArrowLeft2, null),
6299
6673
  " 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(
6674
+ ), !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(
6675
+ "button",
6676
+ {
6677
+ onClick: () => {
6678
+ setShowDeleteBranchConfirm(false);
6679
+ handleDeleteBranch();
6680
+ },
6681
+ className: "text-xs font-bold text-rose-400 hover:text-rose-200 transition-colors"
6682
+ },
6683
+ "Sim"
6684
+ ), /* @__PURE__ */ React10.createElement("span", { className: "text-slate-600/50" }, "|"), /* @__PURE__ */ React10.createElement(
6685
+ "button",
6686
+ {
6687
+ onClick: () => setShowDeleteBranchConfirm(false),
6688
+ className: "text-xs text-slate-400 hover:text-white transition-colors"
6689
+ },
6690
+ "N\xE3o"
6691
+ ))) : /* @__PURE__ */ React10.createElement(
6692
+ "button",
6693
+ {
6694
+ onClick: () => setShowDeleteBranchConfirm(true),
6695
+ 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",
6696
+ title: "Excluir permanentemente esta ramifica\xE7\xE3o e seu conte\xFAdo"
6697
+ },
6698
+ /* @__PURE__ */ React10.createElement(FiTrash22, null),
6699
+ " Excluir Ramifica\xE7\xE3o"
6700
+ ))), /* @__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
6701
  "button",
6302
6702
  {
6303
6703
  onClick: handleUnlinkAncestry,
@@ -6327,7 +6727,9 @@ function CreateAncestryPanel({
6327
6727
  onHighlightNode: handleHighlightWrapper,
6328
6728
  initialSectionId: targetScrollSectionId,
6329
6729
  currentBranchDirection: currentContext ? currentContext.direction : null,
6330
- onImageClick: handleImageClickFromText
6730
+ onImageClick: handleImageClickFromText,
6731
+ onSaveDescription: handleSaveDescriptionInline,
6732
+ onStepChange: (stepIndex) => setIsAtStartOfBranch(stepIndex === 0)
6331
6733
  }
6332
6734
  ), /* @__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
6735
  "button",
@@ -6548,25 +6950,25 @@ function CreateAncestryPanel({
6548
6950
  }
6549
6951
 
6550
6952
  // src/components/ImageViewer.jsx
6551
- import React11, { useState as useState11, useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useCallback as useCallback2 } from "react";
6953
+ import React11, { useState as useState12, useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useCallback as useCallback3 } from "react";
6552
6954
  import { FiX as FiX2, FiChevronLeft as FiChevronLeft3, FiChevronRight as FiChevronRight5 } from "react-icons/fi";
6553
6955
  function ImageViewer({ data, onClose }) {
6554
6956
  var _a;
6555
6957
  const { images = [], startIndex = 0, visible } = data;
6556
- const [currentIndex, setCurrentIndex] = useState11(startIndex);
6557
- const [isLoading, setIsLoading] = useState11(false);
6558
- const [loadedSrc, setLoadedSrc] = useState11(null);
6958
+ const [currentIndex, setCurrentIndex] = useState12(startIndex);
6959
+ const [isLoading, setIsLoading] = useState12(false);
6960
+ const [loadedSrc, setLoadedSrc] = useState12(null);
6559
6961
  useLayoutEffect2(() => {
6560
6962
  if (visible) {
6561
6963
  setCurrentIndex(startIndex);
6562
6964
  }
6563
6965
  }, [visible, startIndex]);
6564
- const handleNext = useCallback2(() => {
6966
+ const handleNext = useCallback3(() => {
6565
6967
  if (images.length > 1) {
6566
6968
  setCurrentIndex((prev) => (prev + 1) % images.length);
6567
6969
  }
6568
6970
  }, [images.length]);
6569
- const handlePrev = useCallback2(() => {
6971
+ const handlePrev = useCallback3(() => {
6570
6972
  if (images.length > 1) {
6571
6973
  setCurrentIndex((prev) => (prev - 1 + images.length) % images.length);
6572
6974
  }
@@ -6671,10 +7073,10 @@ function ImageViewer({ data, onClose }) {
6671
7073
  }
6672
7074
 
6673
7075
  // src/components/InSceneCreationForm.jsx
6674
- import React13, { useState as useState13, useEffect as useEffect13, useRef as useRef10 } from "react";
7076
+ import React13, { useState as useState14, useEffect as useEffect13, useRef as useRef10 } from "react";
6675
7077
 
6676
7078
  // src/components/ColorPicker.jsx
6677
- import React12, { useState as useState12, useEffect as useEffect12, useRef as useRef9 } from "react";
7079
+ import React12, { useState as useState13, useEffect as useEffect12, useRef as useRef9 } from "react";
6678
7080
  import { HexColorPicker } from "react-colorful";
6679
7081
  import { FiHash, FiCheck as FiCheck6 } from "react-icons/fi";
6680
7082
  var PRESET_COLORS = [
@@ -6695,7 +7097,7 @@ var PRESET_COLORS = [
6695
7097
  "#000000"
6696
7098
  ];
6697
7099
  function ColorPicker({ color, onChange, disabled }) {
6698
- const [isOpen, setIsOpen] = useState12(false);
7100
+ const [isOpen, setIsOpen] = useState13(false);
6699
7101
  const popoverRef = useRef9(null);
6700
7102
  useEffect12(() => {
6701
7103
  const handleClickOutside = (event) => {
@@ -6770,7 +7172,7 @@ function ColorPicker({ color, onChange, disabled }) {
6770
7172
  }
6771
7173
 
6772
7174
  // src/components/InSceneCreationForm.jsx
6773
- import { FiPlus as FiPlus3, FiMaximize2, FiX as FiX3, FiCheck as FiCheck7, FiEdit2 as FiEdit24, FiSun } from "react-icons/fi";
7175
+ import { FiPlus as FiPlus3, FiMaximize2, FiX as FiX3, FiCheck as FiCheck7, FiEdit2 as FiEdit24, FiSun, FiChevronDown as FiChevronDown4 } from "react-icons/fi";
6774
7176
  function InSceneCreationForm({
6775
7177
  onSave,
6776
7178
  onCancel,
@@ -6789,28 +7191,43 @@ function InSceneCreationForm({
6789
7191
  onMentionClick,
6790
7192
  sourceTypes,
6791
7193
  onUploadFile,
6792
- // Props do Dataset adicionadas
6793
7194
  availableDatasets = [],
6794
7195
  sourceNodeDatasetId,
6795
7196
  viewType
6796
7197
  }) {
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 || "");
7198
+ var _a;
7199
+ const [name, setName] = useState14("");
7200
+ const [types, setTypes] = useState14([]);
7201
+ const [typeInput, setTypeInput] = useState14("");
7202
+ const [color, setColor] = useState14(initialColor || "#cccccc");
7203
+ const [size, setSize] = useState14("medium");
7204
+ const [intensity, setIntensity] = useState14(0);
7205
+ const [description, setDescription] = useState14("");
7206
+ const [customProps, setCustomProps] = useState14([]);
7207
+ const [showTypeSuggestions, setShowTypeSuggestions] = useState14(false);
7208
+ const [filteredTypes, setFilteredTypes] = useState14([]);
7209
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState14(false);
7210
+ const [useImageAsTexture, setUseImageAsTexture] = useState14(false);
7211
+ const [selectedImageUrl, setSelectedImageUrl] = useState14(null);
7212
+ const [targetDatasetId, setTargetDatasetId] = useState14(sourceNodeDatasetId || "");
7213
+ const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] = useState14(false);
7214
+ const datasetDropdownRef = useRef10(null);
6811
7215
  useEffect13(() => {
6812
7216
  if (sourceNodeDatasetId) setTargetDatasetId(sourceNodeDatasetId);
6813
7217
  }, [sourceNodeDatasetId]);
7218
+ useEffect13(() => {
7219
+ function handleClickOutside(event) {
7220
+ if (datasetDropdownRef.current && !datasetDropdownRef.current.contains(event.target)) {
7221
+ setIsDatasetDropdownOpen(false);
7222
+ }
7223
+ }
7224
+ if (isDatasetDropdownOpen) {
7225
+ document.addEventListener("mousedown", handleClickOutside);
7226
+ }
7227
+ return () => {
7228
+ document.removeEventListener("mousedown", handleClickOutside);
7229
+ };
7230
+ }, [isDatasetDropdownOpen]);
6814
7231
  const propsEndRef = useRef10(null);
6815
7232
  const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
6816
7233
  useEffect13(() => {
@@ -6856,8 +7273,8 @@ function InSceneCreationForm({
6856
7273
  const newProp = createNewCustomProperty(customProps);
6857
7274
  setCustomProps([...customProps, newProp]);
6858
7275
  setTimeout(() => {
6859
- var _a;
6860
- (_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
7276
+ var _a2;
7277
+ (_a2 = propsEndRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth", block: "center" });
6861
7278
  }, 100);
6862
7279
  };
6863
7280
  const handleRemoveProp = (index) => setCustomProps(customProps.filter((_, i) => i !== index));
@@ -6890,12 +7307,12 @@ function InSceneCreationForm({
6890
7307
  onSizeChange == null ? void 0 : onSizeChange(newSize);
6891
7308
  };
6892
7309
  const handleToggleImageMode = () => {
6893
- var _a, _b;
7310
+ var _a2, _b;
6894
7311
  const newValue = !useImageAsTexture;
6895
7312
  setUseImageAsTexture(newValue);
6896
7313
  if (newValue) {
6897
7314
  const firstImageProp = customProps.find((p) => p.type === "images");
6898
- if (firstImageProp && ((_b = (_a = firstImageProp.value) == null ? void 0 : _a[0]) == null ? void 0 : _b.value)) {
7315
+ if (firstImageProp && ((_b = (_a2 = firstImageProp.value) == null ? void 0 : _a2[0]) == null ? void 0 : _b.value)) {
6899
7316
  const url = firstImageProp.value[0].value;
6900
7317
  setSelectedImageUrl(url);
6901
7318
  onImageChange == null ? void 0 : onImageChange(true, url);
@@ -6929,7 +7346,6 @@ function InSceneCreationForm({
6929
7346
  useImageAsTexture,
6930
7347
  textureImageUrl: useImageAsTexture ? selectedImageUrl : null,
6931
7348
  targetDatasetId,
6932
- // Alvo do Dataset adicionado no onSave
6933
7349
  ...additionalData
6934
7350
  });
6935
7351
  };
@@ -6950,6 +7366,7 @@ function InSceneCreationForm({
6950
7366
  onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
6951
7367
  }
6952
7368
  };
7369
+ const selectedDatasetName = ((_a = availableDatasets.find((ds) => ds.id === targetDatasetId)) == null ? void 0 : _a.name) || "Selecione um Dataset...";
6953
7370
  return /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(
6954
7371
  "div",
6955
7372
  {
@@ -7007,15 +7424,27 @@ function InSceneCreationForm({
7007
7424
  }
7008
7425
  },
7009
7426
  suggestedType
7010
- ))))), /* @__PURE__ */ React13.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React13.createElement("label", { className: "text-xs text-slate-300" }, "Nome do Node"), /* @__PURE__ */ React13.createElement("input", { required: true, type: "text", placeholder: "Ex.: Cliente XPTO", value: name, onChange: handleNameInputChange, className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), viewType === "view" && availableDatasets.length > 0 && /* @__PURE__ */ React13.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React13.createElement("label", { className: "text-xs text-slate-300" }, "Criar Node no Dataset:"), /* @__PURE__ */ React13.createElement(
7011
- "select",
7427
+ ))))), /* @__PURE__ */ React13.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React13.createElement("label", { className: "text-xs text-slate-300" }, "Nome do Node"), /* @__PURE__ */ React13.createElement("input", { required: true, type: "text", placeholder: "Ex.: Cliente XPTO", value: name, onChange: handleNameInputChange, className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), viewType === "view" && availableDatasets.length > 0 && /* @__PURE__ */ React13.createElement("div", { className: "space-y-1.5 relative", ref: datasetDropdownRef }, /* @__PURE__ */ React13.createElement("label", { className: "text-xs text-slate-300" }, "Criar Node no Dataset:"), /* @__PURE__ */ React13.createElement(
7428
+ "button",
7429
+ {
7430
+ type: "button",
7431
+ onClick: () => setIsDatasetDropdownOpen(!isDatasetDropdownOpen),
7432
+ className: "w-full flex items-center justify-between bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 hover:bg-slate-700/70 transition-colors text-slate-200 text-left"
7433
+ },
7434
+ /* @__PURE__ */ React13.createElement("span", { className: "truncate pr-2" }, selectedDatasetName),
7435
+ /* @__PURE__ */ React13.createElement(FiChevronDown4, { className: `flex-shrink-0 text-slate-400 transition-transform ${isDatasetDropdownOpen ? "rotate-180" : ""}` })
7436
+ ), isDatasetDropdownOpen && /* @__PURE__ */ React13.createElement("ul", { className: "custom-scrollbar absolute top-[66px] left-0 z-20 w-full max-h-48 overflow-y-auto rounded-lg bg-slate-800 border border-white/10 shadow-xl py-1" }, availableDatasets.map((ds) => /* @__PURE__ */ React13.createElement(
7437
+ "li",
7012
7438
  {
7013
- value: targetDatasetId,
7014
- onChange: (e) => setTargetDatasetId(e.target.value),
7015
- className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 text-slate-200 cursor-pointer appearance-none"
7439
+ key: ds.id,
7440
+ onClick: () => {
7441
+ setTargetDatasetId(ds.id);
7442
+ setIsDatasetDropdownOpen(false);
7443
+ },
7444
+ className: `px-3 py-2 text-sm cursor-pointer transition-colors ${targetDatasetId === ds.id ? "bg-indigo-600/40 text-indigo-200 font-medium" : "text-slate-300 hover:bg-white/5"}`
7016
7445
  },
7017
- availableDatasets.map((ds) => /* @__PURE__ */ React13.createElement("option", { key: ds.id, value: ds.id }, ds.name))
7018
- )), /* @__PURE__ */ React13.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React13.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o (Opcional)"), /* @__PURE__ */ React13.createElement("div", { className: "relative group min-h-[80px] bg-slate-800/70 p-2.5 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ React13.createElement(
7446
+ ds.name
7447
+ )))), /* @__PURE__ */ React13.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React13.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o (Opcional)"), /* @__PURE__ */ React13.createElement("div", { className: "relative group min-h-[80px] bg-slate-800/70 p-2.5 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ React13.createElement(
7019
7448
  DescriptionDisplay,
7020
7449
  {
7021
7450
  description,
@@ -7023,7 +7452,8 @@ function InSceneCreationForm({
7023
7452
  availableNodes,
7024
7453
  availableAncestries,
7025
7454
  onMentionClick,
7026
- onImageClick: handleImageClickFromText
7455
+ onImageClick: handleImageClickFromText,
7456
+ onSaveDescription: (newDesc) => setDescription(newDesc)
7027
7457
  }
7028
7458
  ), /* @__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(
7029
7459
  "button",
@@ -7114,7 +7544,7 @@ function InSceneCreationForm({
7114
7544
  }
7115
7545
 
7116
7546
  // src/components/InSceneVersionForm.jsx
7117
- import React14, { useState as useState14, useEffect as useEffect14, useRef as useRef11 } from "react";
7547
+ import React14, { useState as useState15, useEffect as useEffect14, useRef as useRef11 } from "react";
7118
7548
  import { FiPlus as FiPlus4, FiMaximize2 as FiMaximize22, FiCheck as FiCheck8, FiEdit2 as FiEdit25 } from "react-icons/fi";
7119
7549
  function InSceneVersionForm({
7120
7550
  onSave,
@@ -7132,14 +7562,14 @@ function InSceneVersionForm({
7132
7562
  onMentionClick,
7133
7563
  onUploadFile
7134
7564
  }) {
7135
- const [name, setName] = useState14("");
7136
- const [size, setSize] = useState14("medium");
7137
- const [description, setDescription] = useState14("");
7138
- const [customProps, setCustomProps] = useState14([{ id: v4_default(), key: "Date", type: "date", value: { type: "Data", value: "" }, isEditing: true }]);
7139
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState14(false);
7565
+ const [name, setName] = useState15("");
7566
+ const [size, setSize] = useState15("medium");
7567
+ const [description, setDescription] = useState15("");
7568
+ const [customProps, setCustomProps] = useState15([{ id: v4_default(), key: "Date", type: "date", value: { type: "Data", value: "" }, isEditing: true }]);
7569
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState15(false);
7140
7570
  const propsEndRef = useRef11(null);
7141
- const [useImageAsTexture, setUseImageAsTexture] = useState14(false);
7142
- const [selectedImageUrl, setSelectedImageUrl] = useState14(null);
7571
+ const [useImageAsTexture, setUseImageAsTexture] = useState15(false);
7572
+ const [selectedImageUrl, setSelectedImageUrl] = useState15(null);
7143
7573
  const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
7144
7574
  useEffect14(() => {
7145
7575
  if (!hasImages && useImageAsTexture) {
@@ -7260,7 +7690,8 @@ function InSceneVersionForm({
7260
7690
  availableNodes,
7261
7691
  availableAncestries,
7262
7692
  onMentionClick,
7263
- onImageClick: handleImageClickFromText
7693
+ onImageClick: handleImageClickFromText,
7694
+ onSaveDescription: (newDesc) => setDescription(newDesc)
7264
7695
  }
7265
7696
  ), /* @__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(
7266
7697
  "button",
@@ -7332,7 +7763,7 @@ function InSceneVersionForm({
7332
7763
  }
7333
7764
 
7334
7765
  // src/components/NodeDetailsPanel.jsx
7335
- import React15, { useState as useState15, useEffect as useEffect15, useRef as useRef12 } from "react";
7766
+ import React15, { useState as useState16, useEffect as useEffect15, useRef as useRef12 } from "react";
7336
7767
  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";
7337
7768
  function NodeDetailsPanel({
7338
7769
  node,
@@ -7353,29 +7784,37 @@ function NodeDetailsPanel({
7353
7784
  onUploadFile,
7354
7785
  userRole,
7355
7786
  currentDatasetName
7356
- // Prop currentDatasetName adicionada
7357
7787
  }) {
7358
- const [name, setName] = useState15((node == null ? void 0 : node.name) ?? "");
7359
- const [types, setTypes] = useState15([]);
7360
- const [typeInput, setTypeInput] = useState15("");
7361
- const [color, setColor] = useState15((node == null ? void 0 : node.color) ?? "#8b5cf6");
7362
- const [size, setSize] = useState15((node == null ? void 0 : node.size) ?? "medium");
7363
- const [description, setDescription] = useState15((node == null ? void 0 : node.description) ?? "");
7364
- const [intensity, setIntensity] = useState15((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
7365
- const [customProps, setCustomProps] = useState15(() => extractCustomPropsFromNode(node || {}));
7366
- const [showTypeSuggestions, setShowTypeSuggestions] = useState15(false);
7367
- const [filteredTypes, setFilteredTypes] = useState15([]);
7368
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState15(false);
7369
- const [isReadMode, setIsReadMode] = useState15(false);
7370
- const [existingSections, setExistingSections] = useState15((node == null ? void 0 : node.description_sections) || []);
7371
- const [isSaving, setIsSaving] = useState15(false);
7372
- const [isLinkCopied, setIsLinkCopied] = useState15(false);
7373
- const [useImageAsTexture, setUseImageAsTexture] = useState15(() => {
7788
+ const [name, setName] = useState16((node == null ? void 0 : node.name) ?? "");
7789
+ const [types, setTypes] = useState16([]);
7790
+ const [typeInput, setTypeInput] = useState16("");
7791
+ const [color, setColor] = useState16((node == null ? void 0 : node.color) ?? "#8b5cf6");
7792
+ const [size, setSize] = useState16((node == null ? void 0 : node.size) ?? "medium");
7793
+ const [description, setDescription] = useState16((node == null ? void 0 : node.description) ?? "");
7794
+ const [intensity, setIntensity] = useState16((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
7795
+ const [customProps, setCustomProps] = useState16(() => extractCustomPropsFromNode(node || {}));
7796
+ const [showTypeSuggestions, setShowTypeSuggestions] = useState16(false);
7797
+ const [filteredTypes, setFilteredTypes] = useState16([]);
7798
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState16(false);
7799
+ const [isReadMode, setIsReadMode] = useState16(false);
7800
+ const [existingSections, setExistingSections] = useState16((node == null ? void 0 : node.description_sections) || []);
7801
+ const [isSaving, setIsSaving] = useState16(false);
7802
+ const [isLinkCopied, setIsLinkCopied] = useState16(false);
7803
+ const [useImageAsTexture, setUseImageAsTexture] = useState16(() => {
7374
7804
  if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
7375
7805
  if ((node == null ? void 0 : node.useImageAsTexture) === "false") return false;
7376
7806
  return !!(node == null ? void 0 : node.useImageAsTexture);
7377
7807
  });
7378
- const [selectedImageUrl, setSelectedImageUrl] = useState15((node == null ? void 0 : node.textureImageUrl) ?? null);
7808
+ const [selectedImageUrl, setSelectedImageUrl] = useState16((node == null ? void 0 : node.textureImageUrl) ?? null);
7809
+ const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
7810
+ const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
7811
+ initialWidth: isReadMode ? 700 : 440,
7812
+ minWidth: 320,
7813
+ maxWidth: maxPanelW
7814
+ });
7815
+ useEffect15(() => {
7816
+ setWidth(isReadMode ? 700 : 440);
7817
+ }, [isReadMode, setWidth]);
7379
7818
  const prevNodeIdRef = useRef12(null);
7380
7819
  const propsEndRef = useRef12(null);
7381
7820
  const canEdit = userRole !== "viewer";
@@ -7528,6 +7967,11 @@ function NodeDetailsPanel({
7528
7967
  textureImageUrl: url
7529
7968
  });
7530
7969
  };
7970
+ const handleSaveDescriptionInline = (newDescription) => {
7971
+ setDescription(newDescription);
7972
+ onDataUpdate({ ...node, description: newDescription });
7973
+ triggerAutoSave({ description: newDescription });
7974
+ };
7531
7975
  const handleSave = async (keepOpen = false, overrides = {}) => {
7532
7976
  const currentName = overrides.name !== void 0 ? overrides.name : name;
7533
7977
  const currentTypes = overrides.types !== void 0 ? overrides.types : types;
@@ -7583,10 +8027,8 @@ function NodeDetailsPanel({
7583
8027
  return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(
7584
8028
  "div",
7585
8029
  {
7586
- 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
7587
- ${isReadMode ? "w-[min(92vw,700px)]" : "w-[min(92vw,440px)]"}
7588
- `,
7589
- style: { top: 16, right: 16, zIndex: 1100 },
8030
+ 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"}`,
8031
+ style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${panelWidth}px`, maxWidth: "92vw" },
7590
8032
  onPointerDown: swallow,
7591
8033
  onPointerMove: swallow,
7592
8034
  onPointerUp: swallow,
@@ -7595,6 +8037,17 @@ function NodeDetailsPanel({
7595
8037
  onContextMenu: swallow,
7596
8038
  onDoubleClick: swallow
7597
8039
  },
8040
+ /* @__PURE__ */ React15.createElement(
8041
+ "div",
8042
+ {
8043
+ onPointerDown: (e) => {
8044
+ e.stopPropagation();
8045
+ handleResize(e);
8046
+ },
8047
+ className: "absolute left-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-indigo-500/50 z-[2000] transition-colors",
8048
+ title: "Arraste para redimensionar"
8049
+ }
8050
+ ),
7598
8051
  isReadMode ? /* @__PURE__ */ React15.createElement(
7599
8052
  DescriptionReadModePanel,
7600
8053
  {
@@ -7613,7 +8066,8 @@ function NodeDetailsPanel({
7613
8066
  availableAncestries,
7614
8067
  onOpenReference,
7615
8068
  onMentionClick,
7616
- onImageClick: handleImageClickFromText
8069
+ onImageClick: handleImageClickFromText,
8070
+ onSaveDescription: handleSaveDescriptionInline
7617
8071
  }
7618
8072
  ) : /* @__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(
7619
8073
  "button",
@@ -7681,7 +8135,8 @@ function NodeDetailsPanel({
7681
8135
  availableAncestries,
7682
8136
  onOpenReference,
7683
8137
  onMentionClick,
7684
- onImageClick: handleImageClickFromText
8138
+ onImageClick: handleImageClickFromText,
8139
+ onSaveDescription: handleSaveDescriptionInline
7685
8140
  }
7686
8141
  ), /* @__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(
7687
8142
  "button",
@@ -7764,7 +8219,7 @@ function NodeDetailsPanel({
7764
8219
  onUploadFile: canEdit ? onUploadFile : void 0,
7765
8220
  readOnly: !canEdit
7766
8221
  }
7767
- )), /* @__PURE__ */ React15.createElement("div", { ref: propsEndRef }))), currentDatasetName && /* @__PURE__ */ React15.createElement("div", { className: "pt-2 mt-4 border-t border-white/10" }, /* @__PURE__ */ React15.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Hospedado no Dataset"), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2 mt-1.5 px-3 py-2 bg-slate-800/40 rounded-lg border border-white/5" }, /* @__PURE__ */ React15.createElement(FiDatabase, { className: "text-indigo-400", size: 14 }), /* @__PURE__ */ React15.createElement("span", { className: "text-xs text-slate-300 truncate 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(
8222
+ )), /* @__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(
7768
8223
  "button",
7769
8224
  {
7770
8225
  onClick: () => handleSave(false),
@@ -7796,18 +8251,18 @@ function NodeDetailsPanel({
7796
8251
  }
7797
8252
 
7798
8253
  // src/components/MultiNodeContextMenu.jsx
7799
- import React16, { useLayoutEffect as useLayoutEffect3, useRef as useRef13, useState as useState16, useEffect as useEffect16 } from "react";
8254
+ import React16, { useLayoutEffect as useLayoutEffect3, useRef as useRef13, useState as useState17, useEffect as useEffect16 } from "react";
7800
8255
  function MultiNodeContextMenu({
7801
8256
  data,
7802
8257
  userRole,
7803
- // 2. Recebendo a role do usuário nas props
7804
8258
  onClose,
7805
8259
  onDismissNodes,
7806
8260
  onDismissOtherNodes,
7807
8261
  onDeleteNodes
7808
8262
  }) {
7809
8263
  const menuRef = useRef13(null);
7810
- const [menuPos, setMenuPos] = useState16({ left: 0, top: 0 });
8264
+ const [menuPos, setMenuPos] = useState17({ left: 0, top: 0 });
8265
+ const [isConfirmingDelete, setIsConfirmingDelete] = useState17(false);
7811
8266
  const ability = defineAbilityFor(userRole);
7812
8267
  const canDelete = ability.can("delete", "Node");
7813
8268
  useLayoutEffect3(() => {
@@ -7824,7 +8279,9 @@ function MultiNodeContextMenu({
7824
8279
  setMenuPos({ left, top });
7825
8280
  }, [data]);
7826
8281
  useEffect16(() => {
7827
- if (!data.visible) return;
8282
+ if (data.visible) {
8283
+ setIsConfirmingDelete(false);
8284
+ }
7828
8285
  const handleClickOutside = (e) => {
7829
8286
  if (menuRef.current && !menuRef.current.contains(e.target)) onClose();
7830
8287
  };
@@ -7851,12 +8308,26 @@ function MultiNodeContextMenu({
7851
8308
  onDoubleClick: swallow
7852
8309
  },
7853
8310
  /* @__PURE__ */ React16.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
7854
- /* @__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, ")"))))))
8311
+ /* @__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(
8312
+ "button",
8313
+ {
8314
+ onClick: () => setIsConfirmingDelete(false),
8315
+ className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
8316
+ },
8317
+ "Cancelar"
8318
+ ), /* @__PURE__ */ React16.createElement(
8319
+ "button",
8320
+ {
8321
+ onClick: () => onDeleteNodes(data.nodeIds),
8322
+ className: "flex-1 px-2 py-2 text-xs font-medium bg-red-500 hover:bg-red-600 rounded-md text-white transition-colors"
8323
+ },
8324
+ "Excluir"
8325
+ ))) : /* @__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, ")"))))))
7855
8326
  );
7856
8327
  }
7857
8328
 
7858
8329
  // src/components/RelationshipDetailsPanel.jsx
7859
- import React17, { useState as useState17, useEffect as useEffect17, useRef as useRef14, useMemo as useMemo9 } from "react";
8330
+ import React17, { useState as useState18, useEffect as useEffect17, useRef as useRef14, useMemo as useMemo9 } from "react";
7860
8331
  import { FiPlus as FiPlus6, FiEdit2 as FiEdit27, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4 } from "react-icons/fi";
7861
8332
  function RelationshipDetailsPanel({
7862
8333
  link,
@@ -7870,15 +8341,14 @@ function RelationshipDetailsPanel({
7870
8341
  onMentionClick,
7871
8342
  onUploadFile,
7872
8343
  userRole
7873
- // Recebendo userRole via props
7874
8344
  }) {
7875
- const [name, setName] = useState17((link == null ? void 0 : link.name) ?? "");
7876
- const [description, setDescription] = useState17((link == null ? void 0 : link.description) ?? "");
7877
- const [customProps, setCustomProps] = useState17(() => extractCustomPropsFromNode(link || {}));
7878
- const [existingSections, setExistingSections] = useState17((link == null ? void 0 : link.description_sections) || []);
7879
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState17(false);
7880
- const [isSaving, setIsSaving] = useState17(false);
7881
- const [isReadMode, setIsReadMode] = useState17(false);
8345
+ const [name, setName] = useState18((link == null ? void 0 : link.name) ?? "");
8346
+ const [description, setDescription] = useState18((link == null ? void 0 : link.description) ?? "");
8347
+ const [customProps, setCustomProps] = useState18(() => extractCustomPropsFromNode(link || {}));
8348
+ const [existingSections, setExistingSections] = useState18((link == null ? void 0 : link.description_sections) || []);
8349
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState18(false);
8350
+ const [isSaving, setIsSaving] = useState18(false);
8351
+ const [isReadMode, setIsReadMode] = useState18(false);
7882
8352
  const propsEndRef = useRef14(null);
7883
8353
  const canEdit = useMemo9(() => {
7884
8354
  const ability = defineAbilityFor(userRole);
@@ -7933,6 +8403,12 @@ function RelationshipDetailsPanel({
7933
8403
  const triggerAutoSave = (overrides = {}) => {
7934
8404
  if (canEdit) handleSave(true, overrides);
7935
8405
  };
8406
+ const handleSaveDescriptionInline = (newDescription) => {
8407
+ if (!canEdit) return;
8408
+ setDescription(newDescription);
8409
+ onDataUpdate((prev) => ({ ...prev, description: newDescription }));
8410
+ triggerAutoSave({ description: newDescription });
8411
+ };
7936
8412
  const handleRemoveProp = (i) => {
7937
8413
  const newProps = customProps.filter((_, idx) => idx !== i);
7938
8414
  setCustomProps(newProps);
@@ -7986,7 +8462,8 @@ function RelationshipDetailsPanel({
7986
8462
  availableAncestries,
7987
8463
  onOpenReference,
7988
8464
  onMentionClick,
7989
- onImageClick: handleImageClickFromText
8465
+ onImageClick: handleImageClickFromText,
8466
+ onSaveDescription: handleSaveDescriptionInline
7990
8467
  }
7991
8468
  ) : /* @__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(
7992
8469
  "input",
@@ -8009,7 +8486,8 @@ function RelationshipDetailsPanel({
8009
8486
  availableAncestries,
8010
8487
  onOpenReference,
8011
8488
  onMentionClick,
8012
- onImageClick: handleImageClickFromText
8489
+ onImageClick: handleImageClickFromText,
8490
+ onSaveDescription: handleSaveDescriptionInline
8013
8491
  }
8014
8492
  ), /* @__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(
8015
8493
  "button",
@@ -8081,11 +8559,10 @@ function RelationshipDetailsPanel({
8081
8559
  }
8082
8560
 
8083
8561
  // src/components/RelationshipContextMenu.jsx
8084
- import React18, { useLayoutEffect as useLayoutEffect4, useRef as useRef15, useState as useState18, useEffect as useEffect18, useMemo as useMemo10 } from "react";
8562
+ import React18, { useLayoutEffect as useLayoutEffect4, useRef as useRef15, useState as useState19, useEffect as useEffect18, useMemo as useMemo10 } from "react";
8085
8563
  function RelationshipContextMenu({
8086
8564
  data,
8087
8565
  userRole,
8088
- // Recebemos a role do usuário para verificar permissões
8089
8566
  onRelinkSource,
8090
8567
  onRelinkTarget,
8091
8568
  onOpenDetails,
@@ -8093,7 +8570,8 @@ function RelationshipContextMenu({
8093
8570
  onClose
8094
8571
  }) {
8095
8572
  const menuRef = useRef15(null);
8096
- const [menuPos, setMenuPos] = useState18({ left: 0, top: 0 });
8573
+ const [menuPos, setMenuPos] = useState19({ left: 0, top: 0 });
8574
+ const [isConfirmingDelete, setIsConfirmingDelete] = useState19(false);
8097
8575
  const ability = useMemo10(() => defineAbilityFor(userRole), [userRole]);
8098
8576
  const sourceName = useMemo10(
8099
8577
  () => {
@@ -8123,7 +8601,9 @@ function RelationshipContextMenu({
8123
8601
  setMenuPos({ left, top });
8124
8602
  }, [data]);
8125
8603
  useEffect18(() => {
8126
- if (!data.visible) return;
8604
+ if (data.visible) {
8605
+ setIsConfirmingDelete(false);
8606
+ }
8127
8607
  const handleClickOutside = (e) => {
8128
8608
  if (menuRef.current && !menuRef.current.contains(e.target)) onClose();
8129
8609
  };
@@ -8151,7 +8631,21 @@ function RelationshipContextMenu({
8151
8631
  onDoubleClick: swallow
8152
8632
  },
8153
8633
  /* @__PURE__ */ React18.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }),
8154
- /* @__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(
8634
+ /* @__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(
8635
+ "button",
8636
+ {
8637
+ onClick: () => setIsConfirmingDelete(false),
8638
+ className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
8639
+ },
8640
+ "Cancelar"
8641
+ ), /* @__PURE__ */ React18.createElement(
8642
+ "button",
8643
+ {
8644
+ onClick: () => onDelete == null ? void 0 : onDelete(data.linkObject),
8645
+ className: "flex-1 px-2 py-2 text-xs font-medium bg-rose-600 hover:bg-rose-500 rounded-md text-white transition-colors"
8646
+ },
8647
+ "Excluir"
8648
+ ))) : /* @__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(
8155
8649
  "button",
8156
8650
  {
8157
8651
  onClick: () => onRelinkSource == null ? void 0 : onRelinkSource(data.linkObject),
@@ -8230,7 +8724,7 @@ function RelationshipContextMenu({
8230
8724
  ), canDelete && /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" }), /* @__PURE__ */ React18.createElement(
8231
8725
  "button",
8232
8726
  {
8233
- onClick: () => onDelete == null ? void 0 : onDelete(data.linkObject),
8727
+ onClick: () => setIsConfirmingDelete(true),
8234
8728
  className: dangerButtonClass,
8235
8729
  title: "Excluir esta conex\xE3o"
8236
8730
  },
@@ -8254,7 +8748,7 @@ function RelationshipContextMenu({
8254
8748
  /* @__PURE__ */ React18.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" })
8255
8749
  ),
8256
8750
  /* @__PURE__ */ React18.createElement("span", null, "Excluir conex\xE3o (", sourceName, " \u2192 ", targetName, ")")
8257
- ))))
8751
+ )))))
8258
8752
  );
8259
8753
  }
8260
8754
 
@@ -8295,7 +8789,7 @@ function LoadingScreen() {
8295
8789
  }
8296
8790
 
8297
8791
  // src/components/ImportParentFileModal.jsx
8298
- import React20, { useEffect as useEffect19, useState as useState19 } from "react";
8792
+ import React20, { useEffect as useEffect19, useState as useState20 } from "react";
8299
8793
  function ImportParentFileModal({
8300
8794
  isOpen,
8301
8795
  onClose,
@@ -8306,11 +8800,11 @@ function ImportParentFileModal({
8306
8800
  onFetchAvailableFiles,
8307
8801
  currentViewName
8308
8802
  }) {
8309
- const [activeTab, setActiveTab] = useState19("databases");
8310
- const [availableDbs, setAvailableDbs] = useState19([]);
8311
- const [availableViews, setAvailableViews] = useState19([]);
8312
- const [selectedItem, setSelectedItem] = useState19(null);
8313
- const [isLoading, setIsLoading] = useState19(false);
8803
+ const [activeTab, setActiveTab] = useState20("databases");
8804
+ const [availableDbs, setAvailableDbs] = useState20([]);
8805
+ const [availableViews, setAvailableViews] = useState20([]);
8806
+ const [selectedItem, setSelectedItem] = useState20(null);
8807
+ const [isLoading, setIsLoading] = useState20(false);
8314
8808
  useEffect19(() => {
8315
8809
  if (isOpen && session && onFetchAvailableFiles) {
8316
8810
  const fetchData = async () => {
@@ -8456,7 +8950,7 @@ function ImportParentFileModal({
8456
8950
  }
8457
8951
 
8458
8952
  // src/components/AncestryLinkDetailsPanel.jsx
8459
- import React21, { useState as useState20 } from "react";
8953
+ import React21, { useState as useState21 } from "react";
8460
8954
  import { FiBookOpen as FiBookOpen5 } from "react-icons/fi";
8461
8955
  function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile }) {
8462
8956
  var _a, _b, _c, _d;
@@ -8466,7 +8960,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
8466
8960
  const customProps = extractCustomPropsFromNode(relationshipData);
8467
8961
  const sourceName = ((_b = (_a = data.sourceNode) == null ? void 0 : _a.userData) == null ? void 0 : _b.name) || "Origem";
8468
8962
  const targetName = ((_d = (_c = data.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) || "Destino";
8469
- const [isReadMode, setIsReadMode] = useState20(false);
8963
+ const [isReadMode, setIsReadMode] = useState21(false);
8470
8964
  const swallow = (e) => e.stopPropagation();
8471
8965
  const handleImageClickFromText = (url, name) => {
8472
8966
  if (onOpenImageViewer) {
@@ -8532,14 +9026,14 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
8532
9026
  }
8533
9027
 
8534
9028
  // src/components/AncestryBoard.jsx
8535
- import React22, { useState as useState21, useMemo as useMemo11, useEffect as useEffect20, useRef as useRef16 } from "react";
9029
+ import React22, { useState as useState22, useMemo as useMemo11, useEffect as useEffect20, useRef as useRef16 } from "react";
8536
9030
  import {
8537
9031
  FiSearch as FiSearch4,
8538
9032
  FiLayers as FiLayers6,
8539
9033
  FiCornerUpRight as FiCornerUpRight4,
8540
9034
  FiPlay,
8541
9035
  FiPlus as FiPlus7,
8542
- FiTrash2 as FiTrash22,
9036
+ FiTrash2 as FiTrash23,
8543
9037
  FiArrowLeft as FiArrowLeft3,
8544
9038
  FiArrowRight,
8545
9039
  FiCheckCircle,
@@ -8676,7 +9170,7 @@ var GroupItem = ({
8676
9170
  className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
8677
9171
  title: "Remover Grupo"
8678
9172
  },
8679
- /* @__PURE__ */ React22.createElement(FiTrash22, { size: 14 })
9173
+ /* @__PURE__ */ React22.createElement(FiTrash23, { size: 14 })
8680
9174
  )))), group.children && group.children.length > 0 && /* @__PURE__ */ React22.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ React22.createElement(
8681
9175
  GroupItem,
8682
9176
  {
@@ -8709,11 +9203,11 @@ function AncestryBoard({
8709
9203
  userRole
8710
9204
  // [NOVO] Recebe a role do usuário
8711
9205
  }) {
8712
- const [searchTerm, setSearchTerm] = useState21("");
8713
- const [groups, setGroups] = useState21([]);
8714
- const [isLoaded, setIsLoaded] = useState21(false);
8715
- const [pickingGroupId, setPickingGroupId] = useState21(null);
8716
- const [saveStatus, setSaveStatus] = useState21("idle");
9206
+ const [searchTerm, setSearchTerm] = useState22("");
9207
+ const [groups, setGroups] = useState22([]);
9208
+ const [isLoaded, setIsLoaded] = useState22(false);
9209
+ const [pickingGroupId, setPickingGroupId] = useState22(null);
9210
+ const [saveStatus, setSaveStatus] = useState22("idle");
8717
9211
  const canEdit = useMemo11(() => {
8718
9212
  return userRole !== "viewer";
8719
9213
  }, [userRole]);
@@ -9163,37 +9657,37 @@ function XViewScene({
9163
9657
  const sceneDataRef = useRef17(null);
9164
9658
  const parentDataRef = useRef17(null);
9165
9659
  const ancestryDataRef = useRef17(null);
9166
- const [isLoading, setIsLoading] = useState22(true);
9167
- const [permissionStatus, setPermissionStatus] = useState22("loading");
9168
- const [userPermissionRole, setUserPermissionRole] = useState22(null);
9169
- const [isInitialized, setIsInitialized] = useState22(false);
9170
- const [sceneVersion, setSceneVersion] = useState22(0);
9171
- const [contextMenu, setContextMenu] = useState22({ visible: false, x: 0, y: 0, nodeData: null });
9172
- const [multiContextMenu, setMultiContextMenu] = useState22({ visible: false, x: 0, y: 0, nodeIds: null });
9173
- const [relationshipMenu, setRelationshipMenu] = useState22({ visible: false, x: 0, y: 0, linkObject: null });
9174
- const [creationMode, setCreationMode] = useState22({ isActive: false, sourceNodeData: null });
9175
- const [versionMode, setVersionMode] = useState22({ isActive: false, sourceNodeData: null });
9176
- const [hasFocusedInitial, setHasFocusedInitial] = useState22(false);
9177
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState22(false);
9178
- const [ancestryMode, setAncestryMode] = useState22({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
9179
- const [readingMode, setReadingMode] = useState22({
9660
+ const [isLoading, setIsLoading] = useState23(true);
9661
+ const [permissionStatus, setPermissionStatus] = useState23("loading");
9662
+ const [userPermissionRole, setUserPermissionRole] = useState23(null);
9663
+ const [isInitialized, setIsInitialized] = useState23(false);
9664
+ const [sceneVersion, setSceneVersion] = useState23(0);
9665
+ const [contextMenu, setContextMenu] = useState23({ visible: false, x: 0, y: 0, nodeData: null });
9666
+ const [multiContextMenu, setMultiContextMenu] = useState23({ visible: false, x: 0, y: 0, nodeIds: null });
9667
+ const [relationshipMenu, setRelationshipMenu] = useState23({ visible: false, x: 0, y: 0, linkObject: null });
9668
+ const [creationMode, setCreationMode] = useState23({ isActive: false, sourceNodeData: null });
9669
+ const [versionMode, setVersionMode] = useState23({ isActive: false, sourceNodeData: null });
9670
+ const [hasFocusedInitial, setHasFocusedInitial] = useState23(false);
9671
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState23(false);
9672
+ const [ancestryMode, setAncestryMode] = useState23({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
9673
+ const [readingMode, setReadingMode] = useState23({
9180
9674
  isActive: false,
9181
9675
  ancestry: null,
9182
9676
  branchStack: [],
9183
9677
  autoAbstraction: false
9184
9678
  });
9185
- const [formPosition, setFormPosition] = useState22({ left: 16, top: 16, opacity: 0 });
9186
- const [detailsNode, setDetailsNode] = useState22(null);
9187
- const [detailsLink, setDetailsLink] = useState22(null);
9188
- const [ancestryLinkDetails, setAncestryLinkDetails] = useState22(null);
9189
- const [imageViewer, setImageViewer] = useState22({ visible: false, images: [], startIndex: 0 });
9190
- const [editingAncestryRel, setEditingAncestryRel] = useState22({ visible: false, data: null, path: null });
9191
- const [isImportModalOpen, setIsImportModalOpen] = useState22(false);
9192
- const [importSuccessMessage, setImportSuccessMessage] = useState22("");
9193
- const [highlightedNodeId, setHighlightedNodeId] = useState22(null);
9194
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState22(false);
9195
- const [ancestryBoardData, setAncestryBoardData] = useState22([]);
9196
- const [isSidebarOpen, setIsSidebarOpen] = useState22(false);
9679
+ const [formPosition, setFormPosition] = useState23({ left: 16, top: 16, opacity: 0 });
9680
+ const [detailsNode, setDetailsNode] = useState23(null);
9681
+ const [detailsLink, setDetailsLink] = useState23(null);
9682
+ const [ancestryLinkDetails, setAncestryLinkDetails] = useState23(null);
9683
+ const [imageViewer, setImageViewer] = useState23({ visible: false, images: [], startIndex: 0 });
9684
+ const [editingAncestryRel, setEditingAncestryRel] = useState23({ visible: false, data: null, path: null });
9685
+ const [isImportModalOpen, setIsImportModalOpen] = useState23(false);
9686
+ const [importSuccessMessage, setImportSuccessMessage] = useState23("");
9687
+ const [highlightedNodeId, setHighlightedNodeId] = useState23(null);
9688
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState23(false);
9689
+ const [ancestryBoardData, setAncestryBoardData] = useState23([]);
9690
+ const [isSidebarOpen, setIsSidebarOpen] = useState23(false);
9197
9691
  const mountRef = useRef17(null);
9198
9692
  const tooltipRef = useRef17(null);
9199
9693
  const formRef = useRef17(null);
@@ -9236,6 +9730,12 @@ function XViewScene({
9236
9730
  lastDescriptionLength: 0,
9237
9731
  highlightedNodeId: null
9238
9732
  });
9733
+ const maxReadPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
9734
+ const { width: readModeWidth, isResizing: isReadModeResizing, handlePointerDown: handleReadModeResize } = useResizablePanel({
9735
+ initialWidth: 700,
9736
+ minWidth: 320,
9737
+ maxWidth: maxReadPanelW
9738
+ });
9239
9739
  useEffect21(() => {
9240
9740
  stateRef.current.ancestry = ancestryMode;
9241
9741
  }, [ancestryMode]);
@@ -9260,10 +9760,10 @@ function XViewScene({
9260
9760
  }
9261
9761
  stateRef.current.nodeIdToParentFileMap = map;
9262
9762
  }, [isInitialized, sceneVersion]);
9263
- const handleNavigateBack = useCallback3(() => {
9763
+ const handleNavigateBack = useCallback4(() => {
9264
9764
  router.push("/dashboard/scenes");
9265
9765
  }, [router]);
9266
- const handleConfirmImport = useCallback3(
9766
+ const handleConfirmImport = useCallback4(
9267
9767
  async (importPayload) => {
9268
9768
  var _a2, _b2;
9269
9769
  let files = [];
@@ -9311,7 +9811,6 @@ function XViewScene({
9311
9811
  if (ancestryResponse.success && Array.isArray(ancestryResponse.data)) {
9312
9812
  const viewSpecificAncestries = ancestryResponse.data.filter(
9313
9813
  (anc) => anc._source_file_id === viewToImport.id && !anc.is_private
9314
- // <--- AQUI ESTÁ A TRAVA DE SEGURANÇA
9315
9814
  );
9316
9815
  const processedAncestries = viewSpecificAncestries.map((anc) => ({
9317
9816
  ...anc,
@@ -9362,7 +9861,7 @@ function XViewScene({
9362
9861
  const handleOpenImageViewer = (images, startIndex) => {
9363
9862
  setImageViewer({ visible: true, images, startIndex });
9364
9863
  };
9365
- const tweenToTarget = useCallback3((target, zoomFactor = 1, forcedDirection = null) => {
9864
+ const tweenToTarget = useCallback4((target, zoomFactor = 1, forcedDirection = null) => {
9366
9865
  const { camera, controls, tweenGroup } = stateRef.current;
9367
9866
  if (!camera || !controls || !tweenGroup) return;
9368
9867
  const targetPos = target instanceof THREE3.Mesh ? target.getWorldPosition(new THREE3.Vector3()) : target;
@@ -9385,7 +9884,7 @@ function XViewScene({
9385
9884
  if (!t || typeof t.closest !== "function") return false;
9386
9885
  return !!t.closest(".ui-overlay");
9387
9886
  };
9388
- const buildFullAncestryTree = useCallback3((idTree, nodes, ancestries = []) => {
9887
+ const buildFullAncestryTree = useCallback4((idTree, nodes, ancestries = []) => {
9389
9888
  if (!idTree) return null;
9390
9889
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
9391
9890
  const ancestryMap = new Map(ancestries.map((a) => [String(a.ancestry_id), a]));
@@ -9411,14 +9910,10 @@ function XViewScene({
9411
9910
  return {
9412
9911
  ...branch,
9413
9912
  name: linkedAncestry.name,
9414
- // Sobrescreve nome para exibição
9415
9913
  description: linkedAncestry.description,
9416
- // Sobrescreve descrição
9417
9914
  description_sections: linkedAncestry.description_sections,
9418
9915
  tree: graftedTree,
9419
- // ENXERTA A ÁRVORE AQUI
9420
9916
  isLinked: true
9421
- // Flag útil
9422
9917
  };
9423
9918
  }
9424
9919
  }
@@ -9465,7 +9960,7 @@ function XViewScene({
9465
9960
  }
9466
9961
  return recursiveBuild(idTree);
9467
9962
  }, []);
9468
- const handleActivateTimeline = useCallback3(() => {
9963
+ const handleActivateTimeline = useCallback4(() => {
9469
9964
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
9470
9965
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
9471
9966
  while (timelineIntervalsGroup.children.length > 0) {
@@ -9618,7 +10113,7 @@ function XViewScene({
9618
10113
  }
9619
10114
  });
9620
10115
  }, []);
9621
- const handleVersionTimeline = useCallback3((sourceMesh, versionMeshes) => {
10116
+ const handleVersionTimeline = useCallback4((sourceMesh, versionMeshes) => {
9622
10117
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
9623
10118
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0) return;
9624
10119
  versionMeshes.forEach((mesh) => {
@@ -9811,16 +10306,14 @@ function XViewScene({
9811
10306
  isInitialized,
9812
10307
  permissionStatus,
9813
10308
  focusNodeId,
9814
- // <-- MANTIDO
9815
10309
  focusAncestryId
9816
- // <-- ADICIONADO O focusAncestryId NAS DEPENDÊNCIAS
9817
10310
  ]);
9818
- const isNodeInView = useCallback3((id) => {
10311
+ const isNodeInView = useCallback4((id) => {
9819
10312
  const key = String(id);
9820
10313
  const objs = stateRef.current.nodeObjects || {};
9821
10314
  return !!objs[key];
9822
10315
  }, []);
9823
- const addOrUpdateNodeMesh = useCallback3((nodeData, position, suppressVersionUpdate = false) => {
10316
+ const addOrUpdateNodeMesh = useCallback4((nodeData, position, suppressVersionUpdate = false) => {
9824
10317
  const { graphGroup, nodeObjects, clickableNodes, glowTexture, tweenGroup } = stateRef.current;
9825
10318
  const nodeId = String(nodeData.id);
9826
10319
  if (nodeObjects[nodeId]) {
@@ -10469,7 +10962,7 @@ function XViewScene({
10469
10962
  }
10470
10963
  };
10471
10964
  }, [isInitialized, tweenToTarget, dbSaveUrl, isNodeInView, addOrUpdateNodeMesh, handleActivateTimeline, get_scene_view_data, save_view_data]);
10472
- const handleGhostNodeImageChange = useCallback3((useImage, imageUrl) => {
10965
+ const handleGhostNodeImageChange = useCallback4((useImage, imageUrl) => {
10473
10966
  const { node: ghostNode, line: ghostLine, aura: ghostAura } = stateRef.current.ghostElements;
10474
10967
  const { graphGroup, glowTexture } = stateRef.current;
10475
10968
  if (!ghostNode || !graphGroup) return;
@@ -10511,7 +11004,7 @@ function XViewScene({
10511
11004
  aura: newGhostNode.getObjectByName("aura")
10512
11005
  };
10513
11006
  }, []);
10514
- const handleGhostNodeIntensityChange = useCallback3((newIntensity) => {
11007
+ const handleGhostNodeIntensityChange = useCallback4((newIntensity) => {
10515
11008
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
10516
11009
  if (!ghostNode) return;
10517
11010
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -10532,7 +11025,7 @@ function XViewScene({
10532
11025
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
10533
11026
  }
10534
11027
  }, []);
10535
- const handleDetailNodeIntensityChange = useCallback3((nodeId, newIntensity) => {
11028
+ const handleDetailNodeIntensityChange = useCallback4((nodeId, newIntensity) => {
10536
11029
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
10537
11030
  if (!mesh) return;
10538
11031
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -10678,7 +11171,7 @@ function XViewScene({
10678
11171
  mountRef.current.style.cursor = "default";
10679
11172
  }
10680
11173
  };
10681
- const handleAncestryTreeUpdate = useCallback3((newTree, extraData = null) => {
11174
+ const handleAncestryTreeUpdate = useCallback4((newTree, extraData = null) => {
10682
11175
  setAncestryMode((prev) => {
10683
11176
  const prevTreeStr = JSON.stringify(prev.tree);
10684
11177
  const newTreeStr = JSON.stringify(newTree);
@@ -10748,7 +11241,7 @@ function XViewScene({
10748
11241
  const handleStartVersioning = (nodeData) => {
10749
11242
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
10750
11243
  };
10751
- const handleClearAncestryVisuals = useCallback3((ancestryId) => {
11244
+ const handleClearAncestryVisuals = useCallback4((ancestryId) => {
10752
11245
  const { renderedAncestries, ancestryGroup } = stateRef.current;
10753
11246
  const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
10754
11247
  if (renderIndex !== -1) {
@@ -10762,7 +11255,7 @@ function XViewScene({
10762
11255
  stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
10763
11256
  }
10764
11257
  }, []);
10765
- const handleRenderAncestry = useCallback3(
11258
+ const handleRenderAncestry = useCallback4(
10766
11259
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
10767
11260
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
10768
11261
  if (!ancestryObject || !ancestryObject.tree) {
@@ -11178,7 +11671,7 @@ function XViewScene({
11178
11671
  },
11179
11672
  [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, readingMode.isActive, ancestryMode.isActive]
11180
11673
  );
11181
- const handleRenderAbstractionTree = useCallback3((ancestryObject, targetNodeId = null) => {
11674
+ const handleRenderAbstractionTree = useCallback4((ancestryObject, targetNodeId = null) => {
11182
11675
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11183
11676
  if (!ancestryObject || !ancestryObject.abstraction_tree) return;
11184
11677
  const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
@@ -11239,7 +11732,7 @@ function XViewScene({
11239
11732
  stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
11240
11733
  tweenToTarget(rootTargetPos, 0.7);
11241
11734
  }, [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, handleClearAncestryVisuals]);
11242
- const handleReadModeBranchNav = useCallback3((nodeId, action, direction = "right") => {
11735
+ const handleReadModeBranchNav = useCallback4((nodeId, action, direction = "right") => {
11243
11736
  const { ancestry, branchStack } = readingMode;
11244
11737
  if (!ancestry || !ancestry.tree) return;
11245
11738
  const allAncestries = ancestryDataRef.current || [];
@@ -11277,9 +11770,7 @@ function XViewScene({
11277
11770
  description_sections: branchToOpen.description_sections,
11278
11771
  tree: branchToOpen.tree,
11279
11772
  _originNodeId: nodeId,
11280
- // <--- ID do node pai (link visual)
11281
11773
  _branchDirection: direction
11282
- // <--- Direção para cálculo de posição
11283
11774
  };
11284
11775
  const allowedIds = /* @__PURE__ */ new Set(["preamble", 0, "0"]);
11285
11776
  const branchSections = parseDescriptionSections(branchToOpen.description || "", branchToOpen.description_sections || []);
@@ -11335,7 +11826,6 @@ function XViewScene({
11335
11826
  const parentAncestryObj = {
11336
11827
  ...targetAncestryInfo,
11337
11828
  tree: targetTreeToRender,
11338
- // Re-injeta a origem se o pai também for uma branch aninhada
11339
11829
  _originNodeId: activeParentStackItem ? activeParentStackItem.nodeId : null,
11340
11830
  _branchDirection: activeParentStackItem ? activeParentStackItem.entryDirection : null
11341
11831
  };
@@ -11383,7 +11873,7 @@ function XViewScene({
11383
11873
  }));
11384
11874
  }
11385
11875
  }, [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]);
11386
- const handleReadModeHighlight = useCallback3((nodeId) => {
11876
+ const handleReadModeHighlight = useCallback4((nodeId) => {
11387
11877
  if (stateRef.current.highlightedNodeId !== nodeId) {
11388
11878
  stateRef.current.highlightedNodeId = nodeId;
11389
11879
  }
@@ -11395,7 +11885,6 @@ function XViewScene({
11395
11885
  readingMode.ancestry.tree,
11396
11886
  Object.values(parentDataRef.current).flatMap((f) => f.nodes),
11397
11887
  ancestryDataRef.current
11398
- // <--- Adicionar
11399
11888
  );
11400
11889
  const findNodeInTree = (tree, targetId) => {
11401
11890
  if (!tree) return null;
@@ -11449,7 +11938,6 @@ function XViewScene({
11449
11938
  description_sections: ancestry.description_sections,
11450
11939
  direction: null,
11451
11940
  customProperties: rootProps
11452
- // <--- ADICIONADO
11453
11941
  };
11454
11942
  }
11455
11943
  const fullTree = buildFullAncestryTree(
@@ -11478,7 +11966,6 @@ function XViewScene({
11478
11966
  description_sections: currentMeta.description_sections,
11479
11967
  direction: currentDirection,
11480
11968
  customProperties: branchProps
11481
- // <--- ADICIONADO
11482
11969
  };
11483
11970
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
11484
11971
  const readModeAbstractionTree = useMemo12(() => {
@@ -11493,7 +11980,7 @@ function XViewScene({
11493
11980
  allAncestries
11494
11981
  );
11495
11982
  }, [readingMode.isActive, readingMode.ancestry, buildFullAncestryTree, sceneVersion]);
11496
- const handleStartReadingAncestry = useCallback3(
11983
+ const handleStartReadingAncestry = useCallback4(
11497
11984
  async (ancestryObject) => {
11498
11985
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11499
11986
  if (!ancestryObject || !ancestryObject.tree) {
@@ -11514,7 +12001,6 @@ function XViewScene({
11514
12001
  ancestry: ancestryObject,
11515
12002
  branchStack: [],
11516
12003
  autoAbstraction: shouldAutoRenderAbstraction
11517
- // <--- FLAG ENVIADA PARA A UI
11518
12004
  });
11519
12005
  if (shouldAutoRenderAbstraction) {
11520
12006
  handleRenderAbstractionTree(ancestryObject, null);
@@ -11528,9 +12014,8 @@ function XViewScene({
11528
12014
  }
11529
12015
  },
11530
12016
  [handleRenderAncestry, handleRenderAbstractionTree]
11531
- // <--- DEPENDÊNCIA ADICIONADA
11532
12017
  );
11533
- const handleReadModeSectionChange = useCallback3((activeSectionId) => {
12018
+ const handleReadModeSectionChange = useCallback4((activeSectionId) => {
11534
12019
  const { ancestry, branchStack } = readingMode;
11535
12020
  if (!ancestry || !readingMode.isActive) return;
11536
12021
  let targetObj = ancestry;
@@ -11599,10 +12084,10 @@ function XViewScene({
11599
12084
  }, 0);
11600
12085
  handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
11601
12086
  }, [readingMode, handleRenderAncestry, buildFullAncestryTree, ancestryDataRef.current]);
11602
- const handleCloseReadMode = useCallback3(() => {
12087
+ const handleCloseReadMode = useCallback4(() => {
11603
12088
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
11604
12089
  }, []);
11605
- const handleAncestrySectionChange = useCallback3((activeSectionId, ancestryOverride = null, rotation = 0) => {
12090
+ const handleAncestrySectionChange = useCallback4((activeSectionId, ancestryOverride = null, rotation = 0) => {
11606
12091
  var _a2, _b2;
11607
12092
  const currentMode = stateRef.current.ancestry;
11608
12093
  let targetObj = ancestryOverride;
@@ -11654,7 +12139,7 @@ function XViewScene({
11654
12139
  const renderPayload = { ...targetObj, tree: treeToRender };
11655
12140
  handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
11656
12141
  }, [handleRenderAncestry]);
11657
- const handleEditAncestry = useCallback3(
12142
+ const handleEditAncestry = useCallback4(
11658
12143
  async (ancestryObject) => {
11659
12144
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11660
12145
  if (!ancestryObject || !ancestryObject.tree) {
@@ -11677,10 +12162,8 @@ function XViewScene({
11677
12162
  ...ancestryObject,
11678
12163
  tree: fullTree,
11679
12164
  abstraction_tree: fullAbstractionTree,
11680
- // NOVO
11681
12165
  selectedParentId: ancestryObject.ancestral_node,
11682
12166
  selectedAbstractionParentId: ancestryObject.ancestral_node,
11683
- // NOVO
11684
12167
  isEditMode: true,
11685
12168
  currentAncestryId: ancestryObject.ancestry_id,
11686
12169
  ancestryName: ancestryObject.name || `Ancestralidade ${fullTree.node.name}`,
@@ -11688,7 +12171,6 @@ function XViewScene({
11688
12171
  ancestryDescriptionSections: ancestryObject.description_sections || [],
11689
12172
  isAddingNodes: false,
11690
12173
  isAddingAbstractionNodes: false
11691
- // NOVO
11692
12174
  });
11693
12175
  },
11694
12176
  [handleRenderAncestry, buildFullAncestryTree]
@@ -11696,7 +12178,7 @@ function XViewScene({
11696
12178
  const handleSelectAncestryParent = (nodeId) => {
11697
12179
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
11698
12180
  };
11699
- const handleRemoveFromAncestry = useCallback3((pathToRemove) => {
12181
+ const handleRemoveFromAncestry = useCallback4((pathToRemove) => {
11700
12182
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
11701
12183
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
11702
12184
  return;
@@ -11721,7 +12203,7 @@ function XViewScene({
11721
12203
  return { ...prev, tree: newTree };
11722
12204
  });
11723
12205
  }, []);
11724
- const handleSaveAncestry = useCallback3(
12206
+ const handleSaveAncestry = useCallback4(
11725
12207
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
11726
12208
  const treeToUse = treeOverride || ancestryMode.tree;
11727
12209
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -11925,7 +12407,7 @@ function XViewScene({
11925
12407
  });
11926
12408
  setEditingAncestryRel({ visible: false, data: null, path: null });
11927
12409
  };
11928
- const handleDeleteAncestry = useCallback3(
12410
+ const handleDeleteAncestry = useCallback4(
11929
12411
  async (ancestryIdToDelete) => {
11930
12412
  if (!ancestryIdToDelete) {
11931
12413
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -11987,15 +12469,15 @@ function XViewScene({
11987
12469
  },
11988
12470
  [save_view_data, delete_file_action]
11989
12471
  );
11990
- const handleOpenAncestryBoard = useCallback3(() => {
12472
+ const handleOpenAncestryBoard = useCallback4(() => {
11991
12473
  setIsAncestryBoardOpen(true);
11992
12474
  }, []);
11993
- const handleSelectAncestryFromBoard = useCallback3((ancestry) => {
12475
+ const handleSelectAncestryFromBoard = useCallback4((ancestry) => {
11994
12476
  setIsAncestryBoardOpen(false);
11995
12477
  setIsSidebarOpen(false);
11996
12478
  handleStartReadingAncestry(ancestry);
11997
12479
  }, [handleStartReadingAncestry]);
11998
- const handleSaveAncestryBoard = useCallback3(async (groups) => {
12480
+ const handleSaveAncestryBoard = useCallback4(async (groups) => {
11999
12481
  if (!sceneConfigId || !viewParams || !session) return;
12000
12482
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
12001
12483
  await save_ancestry_board_action(sceneConfigId, sceneType, groups, session, ownerId);
@@ -12019,13 +12501,13 @@ function XViewScene({
12019
12501
  return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
12020
12502
  });
12021
12503
  }, [parentDataRef.current, sceneVersion]);
12022
- const handleAddExistingNode = useCallback3(
12504
+ const handleAddExistingNode = useCallback4(
12023
12505
  (nodeId) => {
12024
12506
  return userActionHandlers.handleAddExistingNodeById(actionHandlerContext, nodeId);
12025
12507
  },
12026
12508
  [actionHandlerContext]
12027
12509
  );
12028
- const handleSaveCurrentView = useCallback3(async () => {
12510
+ const handleSaveCurrentView = useCallback4(async () => {
12029
12511
  const { nodeObjects, allLinks } = stateRef.current;
12030
12512
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
12031
12513
  console.warn("N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente.");
@@ -12065,7 +12547,7 @@ function XViewScene({
12065
12547
  const allAvailableAncestries = useMemo12(() => {
12066
12548
  return ancestryDataRef.current || [];
12067
12549
  }, [sceneVersion, isInitialized]);
12068
- const handleOpenReference = useCallback3((referenceData) => {
12550
+ const handleOpenReference = useCallback4((referenceData) => {
12069
12551
  const { type, id } = referenceData;
12070
12552
  if (type === "node") {
12071
12553
  const targetNode = allAvailableNodes.find((n) => String(n.id) === String(id));
@@ -12092,10 +12574,10 @@ function XViewScene({
12092
12574
  }
12093
12575
  }
12094
12576
  }, [allAvailableNodes, allAvailableAncestries, handleEditAncestry, tweenToTarget]);
12095
- const handleToggleAncestryAddMode = useCallback3(() => {
12577
+ const handleToggleAncestryAddMode = useCallback4(() => {
12096
12578
  setAncestryMode((prev) => ({ ...prev, isAddingNodes: !prev.isAddingNodes }));
12097
12579
  }, []);
12098
- const handleFocusNode = useCallback3((nodeData) => {
12580
+ const handleFocusNode = useCallback4((nodeData) => {
12099
12581
  if (!nodeData) return;
12100
12582
  const nodeMesh = stateRef.current.nodeObjects[String(nodeData.id)];
12101
12583
  if (nodeMesh) {
@@ -12165,7 +12647,6 @@ function XViewScene({
12165
12647
  height: "100vh",
12166
12648
  position: "relative",
12167
12649
  overflow: "hidden",
12168
- // <--- ADICIONE ESTA LINHA
12169
12650
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
12170
12651
  }
12171
12652
  },
@@ -12232,9 +12713,20 @@ function XViewScene({
12232
12713
  readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React23.createElement(
12233
12714
  "div",
12234
12715
  {
12235
- 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)]",
12236
- style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)" }
12716
+ 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"}`,
12717
+ style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${readModeWidth}px`, maxWidth: "92vw" }
12237
12718
  },
12719
+ /* @__PURE__ */ React23.createElement(
12720
+ "div",
12721
+ {
12722
+ onPointerDown: (e) => {
12723
+ e.stopPropagation();
12724
+ handleReadModeResize(e);
12725
+ },
12726
+ className: "absolute left-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-indigo-500/50 z-[2000] transition-colors",
12727
+ title: "Arraste para redimensionar"
12728
+ }
12729
+ ),
12238
12730
  /* @__PURE__ */ React23.createElement(
12239
12731
  DescriptionReadModePanel,
12240
12732
  {