@lv-x-software-house/x_view 1.2.2-dev.9 → 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 +1354 -889
  2. package/dist/index.mjs +809 -343
  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) => {
@@ -6794,21 +7196,21 @@ function InSceneCreationForm({
6794
7196
  viewType
6795
7197
  }) {
6796
7198
  var _a;
6797
- const [name, setName] = useState13("");
6798
- const [types, setTypes] = useState13([]);
6799
- const [typeInput, setTypeInput] = useState13("");
6800
- const [color, setColor] = useState13(initialColor || "#cccccc");
6801
- const [size, setSize] = useState13("medium");
6802
- const [intensity, setIntensity] = useState13(0);
6803
- const [description, setDescription] = useState13("");
6804
- const [customProps, setCustomProps] = useState13([]);
6805
- const [showTypeSuggestions, setShowTypeSuggestions] = useState13(false);
6806
- const [filteredTypes, setFilteredTypes] = useState13([]);
6807
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState13(false);
6808
- const [useImageAsTexture, setUseImageAsTexture] = useState13(false);
6809
- const [selectedImageUrl, setSelectedImageUrl] = useState13(null);
6810
- const [targetDatasetId, setTargetDatasetId] = useState13(sourceNodeDatasetId || "");
6811
- const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] = useState13(false);
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);
6812
7214
  const datasetDropdownRef = useRef10(null);
6813
7215
  useEffect13(() => {
6814
7216
  if (sourceNodeDatasetId) setTargetDatasetId(sourceNodeDatasetId);
@@ -7050,7 +7452,8 @@ function InSceneCreationForm({
7050
7452
  availableNodes,
7051
7453
  availableAncestries,
7052
7454
  onMentionClick,
7053
- onImageClick: handleImageClickFromText
7455
+ onImageClick: handleImageClickFromText,
7456
+ onSaveDescription: (newDesc) => setDescription(newDesc)
7054
7457
  }
7055
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(
7056
7459
  "button",
@@ -7141,7 +7544,7 @@ function InSceneCreationForm({
7141
7544
  }
7142
7545
 
7143
7546
  // src/components/InSceneVersionForm.jsx
7144
- 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";
7145
7548
  import { FiPlus as FiPlus4, FiMaximize2 as FiMaximize22, FiCheck as FiCheck8, FiEdit2 as FiEdit25 } from "react-icons/fi";
7146
7549
  function InSceneVersionForm({
7147
7550
  onSave,
@@ -7159,14 +7562,14 @@ function InSceneVersionForm({
7159
7562
  onMentionClick,
7160
7563
  onUploadFile
7161
7564
  }) {
7162
- const [name, setName] = useState14("");
7163
- const [size, setSize] = useState14("medium");
7164
- const [description, setDescription] = useState14("");
7165
- const [customProps, setCustomProps] = useState14([{ id: v4_default(), key: "Date", type: "date", value: { type: "Data", value: "" }, isEditing: true }]);
7166
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState14(false);
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);
7167
7570
  const propsEndRef = useRef11(null);
7168
- const [useImageAsTexture, setUseImageAsTexture] = useState14(false);
7169
- const [selectedImageUrl, setSelectedImageUrl] = useState14(null);
7571
+ const [useImageAsTexture, setUseImageAsTexture] = useState15(false);
7572
+ const [selectedImageUrl, setSelectedImageUrl] = useState15(null);
7170
7573
  const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
7171
7574
  useEffect14(() => {
7172
7575
  if (!hasImages && useImageAsTexture) {
@@ -7287,7 +7690,8 @@ function InSceneVersionForm({
7287
7690
  availableNodes,
7288
7691
  availableAncestries,
7289
7692
  onMentionClick,
7290
- onImageClick: handleImageClickFromText
7693
+ onImageClick: handleImageClickFromText,
7694
+ onSaveDescription: (newDesc) => setDescription(newDesc)
7291
7695
  }
7292
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(
7293
7697
  "button",
@@ -7359,7 +7763,7 @@ function InSceneVersionForm({
7359
7763
  }
7360
7764
 
7361
7765
  // src/components/NodeDetailsPanel.jsx
7362
- 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";
7363
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";
7364
7768
  function NodeDetailsPanel({
7365
7769
  node,
@@ -7381,27 +7785,36 @@ function NodeDetailsPanel({
7381
7785
  userRole,
7382
7786
  currentDatasetName
7383
7787
  }) {
7384
- const [name, setName] = useState15((node == null ? void 0 : node.name) ?? "");
7385
- const [types, setTypes] = useState15([]);
7386
- const [typeInput, setTypeInput] = useState15("");
7387
- const [color, setColor] = useState15((node == null ? void 0 : node.color) ?? "#8b5cf6");
7388
- const [size, setSize] = useState15((node == null ? void 0 : node.size) ?? "medium");
7389
- const [description, setDescription] = useState15((node == null ? void 0 : node.description) ?? "");
7390
- const [intensity, setIntensity] = useState15((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
7391
- const [customProps, setCustomProps] = useState15(() => extractCustomPropsFromNode(node || {}));
7392
- const [showTypeSuggestions, setShowTypeSuggestions] = useState15(false);
7393
- const [filteredTypes, setFilteredTypes] = useState15([]);
7394
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState15(false);
7395
- const [isReadMode, setIsReadMode] = useState15(false);
7396
- const [existingSections, setExistingSections] = useState15((node == null ? void 0 : node.description_sections) || []);
7397
- const [isSaving, setIsSaving] = useState15(false);
7398
- const [isLinkCopied, setIsLinkCopied] = useState15(false);
7399
- const [useImageAsTexture, setUseImageAsTexture] = useState15(() => {
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(() => {
7400
7804
  if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
7401
7805
  if ((node == null ? void 0 : node.useImageAsTexture) === "false") return false;
7402
7806
  return !!(node == null ? void 0 : node.useImageAsTexture);
7403
7807
  });
7404
- 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]);
7405
7818
  const prevNodeIdRef = useRef12(null);
7406
7819
  const propsEndRef = useRef12(null);
7407
7820
  const canEdit = userRole !== "viewer";
@@ -7554,6 +7967,11 @@ function NodeDetailsPanel({
7554
7967
  textureImageUrl: url
7555
7968
  });
7556
7969
  };
7970
+ const handleSaveDescriptionInline = (newDescription) => {
7971
+ setDescription(newDescription);
7972
+ onDataUpdate({ ...node, description: newDescription });
7973
+ triggerAutoSave({ description: newDescription });
7974
+ };
7557
7975
  const handleSave = async (keepOpen = false, overrides = {}) => {
7558
7976
  const currentName = overrides.name !== void 0 ? overrides.name : name;
7559
7977
  const currentTypes = overrides.types !== void 0 ? overrides.types : types;
@@ -7609,10 +8027,8 @@ function NodeDetailsPanel({
7609
8027
  return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(
7610
8028
  "div",
7611
8029
  {
7612
- className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden transition-all duration-300 ease-out
7613
- ${isReadMode ? "w-[min(92vw,700px)]" : "w-[min(92vw,440px)]"}
7614
- `,
7615
- style: { top: 16, right: 16, zIndex: 1100 },
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" },
7616
8032
  onPointerDown: swallow,
7617
8033
  onPointerMove: swallow,
7618
8034
  onPointerUp: swallow,
@@ -7621,6 +8037,17 @@ function NodeDetailsPanel({
7621
8037
  onContextMenu: swallow,
7622
8038
  onDoubleClick: swallow
7623
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
+ ),
7624
8051
  isReadMode ? /* @__PURE__ */ React15.createElement(
7625
8052
  DescriptionReadModePanel,
7626
8053
  {
@@ -7639,7 +8066,8 @@ function NodeDetailsPanel({
7639
8066
  availableAncestries,
7640
8067
  onOpenReference,
7641
8068
  onMentionClick,
7642
- onImageClick: handleImageClickFromText
8069
+ onImageClick: handleImageClickFromText,
8070
+ onSaveDescription: handleSaveDescriptionInline
7643
8071
  }
7644
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(
7645
8073
  "button",
@@ -7707,7 +8135,8 @@ function NodeDetailsPanel({
7707
8135
  availableAncestries,
7708
8136
  onOpenReference,
7709
8137
  onMentionClick,
7710
- onImageClick: handleImageClickFromText
8138
+ onImageClick: handleImageClickFromText,
8139
+ onSaveDescription: handleSaveDescriptionInline
7711
8140
  }
7712
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(
7713
8142
  "button",
@@ -7790,7 +8219,7 @@ function NodeDetailsPanel({
7790
8219
  onUploadFile: canEdit ? onUploadFile : void 0,
7791
8220
  readOnly: !canEdit
7792
8221
  }
7793
- )), /* @__PURE__ */ React15.createElement("div", { ref: propsEndRef }))), currentDatasetName && /* @__PURE__ */ React15.createElement("div", { className: "pt-3 mt-4 border-t border-white/10 flex items-center gap-2 text-xs text-slate-400" }, /* @__PURE__ */ React15.createElement(FiDatabase, { className: "text-indigo-400 shrink-0", size: 14 }), /* @__PURE__ */ React15.createElement("span", { className: "truncate" }, "Dataset ", /* @__PURE__ */ React15.createElement("span", { className: "text-slate-200 font-medium" }, currentDatasetName)))), /* @__PURE__ */ React15.createElement("div", { className: "sticky bottom-0 z-10 bg-gradient-to-t from-slate-950/80 via-slate-950/50 to-transparent px-6 py-4 border-t border-white/10 flex justify-end gap-3" }, /* @__PURE__ */ React15.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm disabled:opacity-50" }, canEdit ? "Cancelar" : "Fechar"), canEdit && /* @__PURE__ */ React15.createElement(
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(
7794
8223
  "button",
7795
8224
  {
7796
8225
  onClick: () => handleSave(false),
@@ -7822,18 +8251,18 @@ function NodeDetailsPanel({
7822
8251
  }
7823
8252
 
7824
8253
  // src/components/MultiNodeContextMenu.jsx
7825
- 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";
7826
8255
  function MultiNodeContextMenu({
7827
8256
  data,
7828
8257
  userRole,
7829
- // 2. Recebendo a role do usuário nas props
7830
8258
  onClose,
7831
8259
  onDismissNodes,
7832
8260
  onDismissOtherNodes,
7833
8261
  onDeleteNodes
7834
8262
  }) {
7835
8263
  const menuRef = useRef13(null);
7836
- const [menuPos, setMenuPos] = useState16({ left: 0, top: 0 });
8264
+ const [menuPos, setMenuPos] = useState17({ left: 0, top: 0 });
8265
+ const [isConfirmingDelete, setIsConfirmingDelete] = useState17(false);
7837
8266
  const ability = defineAbilityFor(userRole);
7838
8267
  const canDelete = ability.can("delete", "Node");
7839
8268
  useLayoutEffect3(() => {
@@ -7850,7 +8279,9 @@ function MultiNodeContextMenu({
7850
8279
  setMenuPos({ left, top });
7851
8280
  }, [data]);
7852
8281
  useEffect16(() => {
7853
- if (!data.visible) return;
8282
+ if (data.visible) {
8283
+ setIsConfirmingDelete(false);
8284
+ }
7854
8285
  const handleClickOutside = (e) => {
7855
8286
  if (menuRef.current && !menuRef.current.contains(e.target)) onClose();
7856
8287
  };
@@ -7877,12 +8308,26 @@ function MultiNodeContextMenu({
7877
8308
  onDoubleClick: swallow
7878
8309
  },
7879
8310
  /* @__PURE__ */ React16.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
7880
- /* @__PURE__ */ React16.createElement("div", { className: "p-1.5" }, /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React16.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ React16.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es em Grupo (", nodeCount, " Nodes)")), /* @__PURE__ */ React16.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React16.createElement("button", { onClick: () => onDismissNodes(data.nodeIds), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ React16.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React16.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ React16.createElement("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }), /* @__PURE__ */ React16.createElement("path", { d: "M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }), /* @__PURE__ */ React16.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ React16.createElement("span", null, "Dismiss (", nodeCount, ")")), /* @__PURE__ */ React16.createElement("button", { onClick: () => onDismissOtherNodes(data.nodeIds), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ React16.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React16.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ React16.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ React16.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React16.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ React16.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ React16.createElement("span", null, "Dismiss other nodes")), canDelete && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React16.createElement("button", { onClick: () => onDeleteNodes(data.nodeIds), className: deleteButtonClass, title: "Excluir Nodes" }, /* @__PURE__ */ React16.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React16.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React16.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React16.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ React16.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ React16.createElement("span", null, "Excluir Nodes (", nodeCount, ")"))))))
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, ")"))))))
7881
8326
  );
7882
8327
  }
7883
8328
 
7884
8329
  // src/components/RelationshipDetailsPanel.jsx
7885
- 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";
7886
8331
  import { FiPlus as FiPlus6, FiEdit2 as FiEdit27, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4 } from "react-icons/fi";
7887
8332
  function RelationshipDetailsPanel({
7888
8333
  link,
@@ -7896,15 +8341,14 @@ function RelationshipDetailsPanel({
7896
8341
  onMentionClick,
7897
8342
  onUploadFile,
7898
8343
  userRole
7899
- // Recebendo userRole via props
7900
8344
  }) {
7901
- const [name, setName] = useState17((link == null ? void 0 : link.name) ?? "");
7902
- const [description, setDescription] = useState17((link == null ? void 0 : link.description) ?? "");
7903
- const [customProps, setCustomProps] = useState17(() => extractCustomPropsFromNode(link || {}));
7904
- const [existingSections, setExistingSections] = useState17((link == null ? void 0 : link.description_sections) || []);
7905
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState17(false);
7906
- const [isSaving, setIsSaving] = useState17(false);
7907
- const [isReadMode, setIsReadMode] = useState17(false);
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);
7908
8352
  const propsEndRef = useRef14(null);
7909
8353
  const canEdit = useMemo9(() => {
7910
8354
  const ability = defineAbilityFor(userRole);
@@ -7959,6 +8403,12 @@ function RelationshipDetailsPanel({
7959
8403
  const triggerAutoSave = (overrides = {}) => {
7960
8404
  if (canEdit) handleSave(true, overrides);
7961
8405
  };
8406
+ const handleSaveDescriptionInline = (newDescription) => {
8407
+ if (!canEdit) return;
8408
+ setDescription(newDescription);
8409
+ onDataUpdate((prev) => ({ ...prev, description: newDescription }));
8410
+ triggerAutoSave({ description: newDescription });
8411
+ };
7962
8412
  const handleRemoveProp = (i) => {
7963
8413
  const newProps = customProps.filter((_, idx) => idx !== i);
7964
8414
  setCustomProps(newProps);
@@ -8012,7 +8462,8 @@ function RelationshipDetailsPanel({
8012
8462
  availableAncestries,
8013
8463
  onOpenReference,
8014
8464
  onMentionClick,
8015
- onImageClick: handleImageClickFromText
8465
+ onImageClick: handleImageClickFromText,
8466
+ onSaveDescription: handleSaveDescriptionInline
8016
8467
  }
8017
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(
8018
8469
  "input",
@@ -8035,7 +8486,8 @@ function RelationshipDetailsPanel({
8035
8486
  availableAncestries,
8036
8487
  onOpenReference,
8037
8488
  onMentionClick,
8038
- onImageClick: handleImageClickFromText
8489
+ onImageClick: handleImageClickFromText,
8490
+ onSaveDescription: handleSaveDescriptionInline
8039
8491
  }
8040
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(
8041
8493
  "button",
@@ -8107,11 +8559,10 @@ function RelationshipDetailsPanel({
8107
8559
  }
8108
8560
 
8109
8561
  // src/components/RelationshipContextMenu.jsx
8110
- 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";
8111
8563
  function RelationshipContextMenu({
8112
8564
  data,
8113
8565
  userRole,
8114
- // Recebemos a role do usuário para verificar permissões
8115
8566
  onRelinkSource,
8116
8567
  onRelinkTarget,
8117
8568
  onOpenDetails,
@@ -8119,7 +8570,8 @@ function RelationshipContextMenu({
8119
8570
  onClose
8120
8571
  }) {
8121
8572
  const menuRef = useRef15(null);
8122
- const [menuPos, setMenuPos] = useState18({ left: 0, top: 0 });
8573
+ const [menuPos, setMenuPos] = useState19({ left: 0, top: 0 });
8574
+ const [isConfirmingDelete, setIsConfirmingDelete] = useState19(false);
8123
8575
  const ability = useMemo10(() => defineAbilityFor(userRole), [userRole]);
8124
8576
  const sourceName = useMemo10(
8125
8577
  () => {
@@ -8149,7 +8601,9 @@ function RelationshipContextMenu({
8149
8601
  setMenuPos({ left, top });
8150
8602
  }, [data]);
8151
8603
  useEffect18(() => {
8152
- if (!data.visible) return;
8604
+ if (data.visible) {
8605
+ setIsConfirmingDelete(false);
8606
+ }
8153
8607
  const handleClickOutside = (e) => {
8154
8608
  if (menuRef.current && !menuRef.current.contains(e.target)) onClose();
8155
8609
  };
@@ -8177,7 +8631,21 @@ function RelationshipContextMenu({
8177
8631
  onDoubleClick: swallow
8178
8632
  },
8179
8633
  /* @__PURE__ */ React18.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }),
8180
- /* @__PURE__ */ React18.createElement("div", { className: "p-1.5" }, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React18.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-teal-400/80 shadow-[0_0_12px_1px_rgba(45,212,191,0.5)]" }), /* @__PURE__ */ React18.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Rela\xE7\xE3o")), /* @__PURE__ */ React18.createElement("div", { className: "flex flex-col gap-1" }, canUpdate && /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(
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(
8181
8649
  "button",
8182
8650
  {
8183
8651
  onClick: () => onRelinkSource == null ? void 0 : onRelinkSource(data.linkObject),
@@ -8256,7 +8724,7 @@ function RelationshipContextMenu({
8256
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(
8257
8725
  "button",
8258
8726
  {
8259
- onClick: () => onDelete == null ? void 0 : onDelete(data.linkObject),
8727
+ onClick: () => setIsConfirmingDelete(true),
8260
8728
  className: dangerButtonClass,
8261
8729
  title: "Excluir esta conex\xE3o"
8262
8730
  },
@@ -8280,7 +8748,7 @@ function RelationshipContextMenu({
8280
8748
  /* @__PURE__ */ React18.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" })
8281
8749
  ),
8282
8750
  /* @__PURE__ */ React18.createElement("span", null, "Excluir conex\xE3o (", sourceName, " \u2192 ", targetName, ")")
8283
- ))))
8751
+ )))))
8284
8752
  );
8285
8753
  }
8286
8754
 
@@ -8321,7 +8789,7 @@ function LoadingScreen() {
8321
8789
  }
8322
8790
 
8323
8791
  // src/components/ImportParentFileModal.jsx
8324
- import React20, { useEffect as useEffect19, useState as useState19 } from "react";
8792
+ import React20, { useEffect as useEffect19, useState as useState20 } from "react";
8325
8793
  function ImportParentFileModal({
8326
8794
  isOpen,
8327
8795
  onClose,
@@ -8332,11 +8800,11 @@ function ImportParentFileModal({
8332
8800
  onFetchAvailableFiles,
8333
8801
  currentViewName
8334
8802
  }) {
8335
- const [activeTab, setActiveTab] = useState19("databases");
8336
- const [availableDbs, setAvailableDbs] = useState19([]);
8337
- const [availableViews, setAvailableViews] = useState19([]);
8338
- const [selectedItem, setSelectedItem] = useState19(null);
8339
- const [isLoading, setIsLoading] = useState19(false);
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);
8340
8808
  useEffect19(() => {
8341
8809
  if (isOpen && session && onFetchAvailableFiles) {
8342
8810
  const fetchData = async () => {
@@ -8482,7 +8950,7 @@ function ImportParentFileModal({
8482
8950
  }
8483
8951
 
8484
8952
  // src/components/AncestryLinkDetailsPanel.jsx
8485
- import React21, { useState as useState20 } from "react";
8953
+ import React21, { useState as useState21 } from "react";
8486
8954
  import { FiBookOpen as FiBookOpen5 } from "react-icons/fi";
8487
8955
  function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile }) {
8488
8956
  var _a, _b, _c, _d;
@@ -8492,7 +8960,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
8492
8960
  const customProps = extractCustomPropsFromNode(relationshipData);
8493
8961
  const sourceName = ((_b = (_a = data.sourceNode) == null ? void 0 : _a.userData) == null ? void 0 : _b.name) || "Origem";
8494
8962
  const targetName = ((_d = (_c = data.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) || "Destino";
8495
- const [isReadMode, setIsReadMode] = useState20(false);
8963
+ const [isReadMode, setIsReadMode] = useState21(false);
8496
8964
  const swallow = (e) => e.stopPropagation();
8497
8965
  const handleImageClickFromText = (url, name) => {
8498
8966
  if (onOpenImageViewer) {
@@ -8558,14 +9026,14 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
8558
9026
  }
8559
9027
 
8560
9028
  // src/components/AncestryBoard.jsx
8561
- 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";
8562
9030
  import {
8563
9031
  FiSearch as FiSearch4,
8564
9032
  FiLayers as FiLayers6,
8565
9033
  FiCornerUpRight as FiCornerUpRight4,
8566
9034
  FiPlay,
8567
9035
  FiPlus as FiPlus7,
8568
- FiTrash2 as FiTrash22,
9036
+ FiTrash2 as FiTrash23,
8569
9037
  FiArrowLeft as FiArrowLeft3,
8570
9038
  FiArrowRight,
8571
9039
  FiCheckCircle,
@@ -8702,7 +9170,7 @@ var GroupItem = ({
8702
9170
  className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
8703
9171
  title: "Remover Grupo"
8704
9172
  },
8705
- /* @__PURE__ */ React22.createElement(FiTrash22, { size: 14 })
9173
+ /* @__PURE__ */ React22.createElement(FiTrash23, { size: 14 })
8706
9174
  )))), group.children && group.children.length > 0 && /* @__PURE__ */ React22.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ React22.createElement(
8707
9175
  GroupItem,
8708
9176
  {
@@ -8735,11 +9203,11 @@ function AncestryBoard({
8735
9203
  userRole
8736
9204
  // [NOVO] Recebe a role do usuário
8737
9205
  }) {
8738
- const [searchTerm, setSearchTerm] = useState21("");
8739
- const [groups, setGroups] = useState21([]);
8740
- const [isLoaded, setIsLoaded] = useState21(false);
8741
- const [pickingGroupId, setPickingGroupId] = useState21(null);
8742
- const [saveStatus, setSaveStatus] = useState21("idle");
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");
8743
9211
  const canEdit = useMemo11(() => {
8744
9212
  return userRole !== "viewer";
8745
9213
  }, [userRole]);
@@ -9189,37 +9657,37 @@ function XViewScene({
9189
9657
  const sceneDataRef = useRef17(null);
9190
9658
  const parentDataRef = useRef17(null);
9191
9659
  const ancestryDataRef = useRef17(null);
9192
- const [isLoading, setIsLoading] = useState22(true);
9193
- const [permissionStatus, setPermissionStatus] = useState22("loading");
9194
- const [userPermissionRole, setUserPermissionRole] = useState22(null);
9195
- const [isInitialized, setIsInitialized] = useState22(false);
9196
- const [sceneVersion, setSceneVersion] = useState22(0);
9197
- const [contextMenu, setContextMenu] = useState22({ visible: false, x: 0, y: 0, nodeData: null });
9198
- const [multiContextMenu, setMultiContextMenu] = useState22({ visible: false, x: 0, y: 0, nodeIds: null });
9199
- const [relationshipMenu, setRelationshipMenu] = useState22({ visible: false, x: 0, y: 0, linkObject: null });
9200
- const [creationMode, setCreationMode] = useState22({ isActive: false, sourceNodeData: null });
9201
- const [versionMode, setVersionMode] = useState22({ isActive: false, sourceNodeData: null });
9202
- const [hasFocusedInitial, setHasFocusedInitial] = useState22(false);
9203
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState22(false);
9204
- const [ancestryMode, setAncestryMode] = useState22({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
9205
- const [readingMode, setReadingMode] = useState22({
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({
9206
9674
  isActive: false,
9207
9675
  ancestry: null,
9208
9676
  branchStack: [],
9209
9677
  autoAbstraction: false
9210
9678
  });
9211
- const [formPosition, setFormPosition] = useState22({ left: 16, top: 16, opacity: 0 });
9212
- const [detailsNode, setDetailsNode] = useState22(null);
9213
- const [detailsLink, setDetailsLink] = useState22(null);
9214
- const [ancestryLinkDetails, setAncestryLinkDetails] = useState22(null);
9215
- const [imageViewer, setImageViewer] = useState22({ visible: false, images: [], startIndex: 0 });
9216
- const [editingAncestryRel, setEditingAncestryRel] = useState22({ visible: false, data: null, path: null });
9217
- const [isImportModalOpen, setIsImportModalOpen] = useState22(false);
9218
- const [importSuccessMessage, setImportSuccessMessage] = useState22("");
9219
- const [highlightedNodeId, setHighlightedNodeId] = useState22(null);
9220
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState22(false);
9221
- const [ancestryBoardData, setAncestryBoardData] = useState22([]);
9222
- const [isSidebarOpen, setIsSidebarOpen] = useState22(false);
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);
9223
9691
  const mountRef = useRef17(null);
9224
9692
  const tooltipRef = useRef17(null);
9225
9693
  const formRef = useRef17(null);
@@ -9262,6 +9730,12 @@ function XViewScene({
9262
9730
  lastDescriptionLength: 0,
9263
9731
  highlightedNodeId: null
9264
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
+ });
9265
9739
  useEffect21(() => {
9266
9740
  stateRef.current.ancestry = ancestryMode;
9267
9741
  }, [ancestryMode]);
@@ -9286,10 +9760,10 @@ function XViewScene({
9286
9760
  }
9287
9761
  stateRef.current.nodeIdToParentFileMap = map;
9288
9762
  }, [isInitialized, sceneVersion]);
9289
- const handleNavigateBack = useCallback3(() => {
9763
+ const handleNavigateBack = useCallback4(() => {
9290
9764
  router.push("/dashboard/scenes");
9291
9765
  }, [router]);
9292
- const handleConfirmImport = useCallback3(
9766
+ const handleConfirmImport = useCallback4(
9293
9767
  async (importPayload) => {
9294
9768
  var _a2, _b2;
9295
9769
  let files = [];
@@ -9337,7 +9811,6 @@ function XViewScene({
9337
9811
  if (ancestryResponse.success && Array.isArray(ancestryResponse.data)) {
9338
9812
  const viewSpecificAncestries = ancestryResponse.data.filter(
9339
9813
  (anc) => anc._source_file_id === viewToImport.id && !anc.is_private
9340
- // <--- AQUI ESTÁ A TRAVA DE SEGURANÇA
9341
9814
  );
9342
9815
  const processedAncestries = viewSpecificAncestries.map((anc) => ({
9343
9816
  ...anc,
@@ -9388,7 +9861,7 @@ function XViewScene({
9388
9861
  const handleOpenImageViewer = (images, startIndex) => {
9389
9862
  setImageViewer({ visible: true, images, startIndex });
9390
9863
  };
9391
- const tweenToTarget = useCallback3((target, zoomFactor = 1, forcedDirection = null) => {
9864
+ const tweenToTarget = useCallback4((target, zoomFactor = 1, forcedDirection = null) => {
9392
9865
  const { camera, controls, tweenGroup } = stateRef.current;
9393
9866
  if (!camera || !controls || !tweenGroup) return;
9394
9867
  const targetPos = target instanceof THREE3.Mesh ? target.getWorldPosition(new THREE3.Vector3()) : target;
@@ -9411,7 +9884,7 @@ function XViewScene({
9411
9884
  if (!t || typeof t.closest !== "function") return false;
9412
9885
  return !!t.closest(".ui-overlay");
9413
9886
  };
9414
- const buildFullAncestryTree = useCallback3((idTree, nodes, ancestries = []) => {
9887
+ const buildFullAncestryTree = useCallback4((idTree, nodes, ancestries = []) => {
9415
9888
  if (!idTree) return null;
9416
9889
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
9417
9890
  const ancestryMap = new Map(ancestries.map((a) => [String(a.ancestry_id), a]));
@@ -9437,14 +9910,10 @@ function XViewScene({
9437
9910
  return {
9438
9911
  ...branch,
9439
9912
  name: linkedAncestry.name,
9440
- // Sobrescreve nome para exibição
9441
9913
  description: linkedAncestry.description,
9442
- // Sobrescreve descrição
9443
9914
  description_sections: linkedAncestry.description_sections,
9444
9915
  tree: graftedTree,
9445
- // ENXERTA A ÁRVORE AQUI
9446
9916
  isLinked: true
9447
- // Flag útil
9448
9917
  };
9449
9918
  }
9450
9919
  }
@@ -9491,7 +9960,7 @@ function XViewScene({
9491
9960
  }
9492
9961
  return recursiveBuild(idTree);
9493
9962
  }, []);
9494
- const handleActivateTimeline = useCallback3(() => {
9963
+ const handleActivateTimeline = useCallback4(() => {
9495
9964
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
9496
9965
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
9497
9966
  while (timelineIntervalsGroup.children.length > 0) {
@@ -9644,7 +10113,7 @@ function XViewScene({
9644
10113
  }
9645
10114
  });
9646
10115
  }, []);
9647
- const handleVersionTimeline = useCallback3((sourceMesh, versionMeshes) => {
10116
+ const handleVersionTimeline = useCallback4((sourceMesh, versionMeshes) => {
9648
10117
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
9649
10118
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0) return;
9650
10119
  versionMeshes.forEach((mesh) => {
@@ -9837,16 +10306,14 @@ function XViewScene({
9837
10306
  isInitialized,
9838
10307
  permissionStatus,
9839
10308
  focusNodeId,
9840
- // <-- MANTIDO
9841
10309
  focusAncestryId
9842
- // <-- ADICIONADO O focusAncestryId NAS DEPENDÊNCIAS
9843
10310
  ]);
9844
- const isNodeInView = useCallback3((id) => {
10311
+ const isNodeInView = useCallback4((id) => {
9845
10312
  const key = String(id);
9846
10313
  const objs = stateRef.current.nodeObjects || {};
9847
10314
  return !!objs[key];
9848
10315
  }, []);
9849
- const addOrUpdateNodeMesh = useCallback3((nodeData, position, suppressVersionUpdate = false) => {
10316
+ const addOrUpdateNodeMesh = useCallback4((nodeData, position, suppressVersionUpdate = false) => {
9850
10317
  const { graphGroup, nodeObjects, clickableNodes, glowTexture, tweenGroup } = stateRef.current;
9851
10318
  const nodeId = String(nodeData.id);
9852
10319
  if (nodeObjects[nodeId]) {
@@ -10495,7 +10962,7 @@ function XViewScene({
10495
10962
  }
10496
10963
  };
10497
10964
  }, [isInitialized, tweenToTarget, dbSaveUrl, isNodeInView, addOrUpdateNodeMesh, handleActivateTimeline, get_scene_view_data, save_view_data]);
10498
- const handleGhostNodeImageChange = useCallback3((useImage, imageUrl) => {
10965
+ const handleGhostNodeImageChange = useCallback4((useImage, imageUrl) => {
10499
10966
  const { node: ghostNode, line: ghostLine, aura: ghostAura } = stateRef.current.ghostElements;
10500
10967
  const { graphGroup, glowTexture } = stateRef.current;
10501
10968
  if (!ghostNode || !graphGroup) return;
@@ -10537,7 +11004,7 @@ function XViewScene({
10537
11004
  aura: newGhostNode.getObjectByName("aura")
10538
11005
  };
10539
11006
  }, []);
10540
- const handleGhostNodeIntensityChange = useCallback3((newIntensity) => {
11007
+ const handleGhostNodeIntensityChange = useCallback4((newIntensity) => {
10541
11008
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
10542
11009
  if (!ghostNode) return;
10543
11010
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -10558,7 +11025,7 @@ function XViewScene({
10558
11025
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
10559
11026
  }
10560
11027
  }, []);
10561
- const handleDetailNodeIntensityChange = useCallback3((nodeId, newIntensity) => {
11028
+ const handleDetailNodeIntensityChange = useCallback4((nodeId, newIntensity) => {
10562
11029
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
10563
11030
  if (!mesh) return;
10564
11031
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -10704,7 +11171,7 @@ function XViewScene({
10704
11171
  mountRef.current.style.cursor = "default";
10705
11172
  }
10706
11173
  };
10707
- const handleAncestryTreeUpdate = useCallback3((newTree, extraData = null) => {
11174
+ const handleAncestryTreeUpdate = useCallback4((newTree, extraData = null) => {
10708
11175
  setAncestryMode((prev) => {
10709
11176
  const prevTreeStr = JSON.stringify(prev.tree);
10710
11177
  const newTreeStr = JSON.stringify(newTree);
@@ -10774,7 +11241,7 @@ function XViewScene({
10774
11241
  const handleStartVersioning = (nodeData) => {
10775
11242
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
10776
11243
  };
10777
- const handleClearAncestryVisuals = useCallback3((ancestryId) => {
11244
+ const handleClearAncestryVisuals = useCallback4((ancestryId) => {
10778
11245
  const { renderedAncestries, ancestryGroup } = stateRef.current;
10779
11246
  const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
10780
11247
  if (renderIndex !== -1) {
@@ -10788,7 +11255,7 @@ function XViewScene({
10788
11255
  stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
10789
11256
  }
10790
11257
  }, []);
10791
- const handleRenderAncestry = useCallback3(
11258
+ const handleRenderAncestry = useCallback4(
10792
11259
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
10793
11260
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
10794
11261
  if (!ancestryObject || !ancestryObject.tree) {
@@ -11204,7 +11671,7 @@ function XViewScene({
11204
11671
  },
11205
11672
  [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, readingMode.isActive, ancestryMode.isActive]
11206
11673
  );
11207
- const handleRenderAbstractionTree = useCallback3((ancestryObject, targetNodeId = null) => {
11674
+ const handleRenderAbstractionTree = useCallback4((ancestryObject, targetNodeId = null) => {
11208
11675
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11209
11676
  if (!ancestryObject || !ancestryObject.abstraction_tree) return;
11210
11677
  const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
@@ -11265,7 +11732,7 @@ function XViewScene({
11265
11732
  stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
11266
11733
  tweenToTarget(rootTargetPos, 0.7);
11267
11734
  }, [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, handleClearAncestryVisuals]);
11268
- const handleReadModeBranchNav = useCallback3((nodeId, action, direction = "right") => {
11735
+ const handleReadModeBranchNav = useCallback4((nodeId, action, direction = "right") => {
11269
11736
  const { ancestry, branchStack } = readingMode;
11270
11737
  if (!ancestry || !ancestry.tree) return;
11271
11738
  const allAncestries = ancestryDataRef.current || [];
@@ -11303,9 +11770,7 @@ function XViewScene({
11303
11770
  description_sections: branchToOpen.description_sections,
11304
11771
  tree: branchToOpen.tree,
11305
11772
  _originNodeId: nodeId,
11306
- // <--- ID do node pai (link visual)
11307
11773
  _branchDirection: direction
11308
- // <--- Direção para cálculo de posição
11309
11774
  };
11310
11775
  const allowedIds = /* @__PURE__ */ new Set(["preamble", 0, "0"]);
11311
11776
  const branchSections = parseDescriptionSections(branchToOpen.description || "", branchToOpen.description_sections || []);
@@ -11361,7 +11826,6 @@ function XViewScene({
11361
11826
  const parentAncestryObj = {
11362
11827
  ...targetAncestryInfo,
11363
11828
  tree: targetTreeToRender,
11364
- // Re-injeta a origem se o pai também for uma branch aninhada
11365
11829
  _originNodeId: activeParentStackItem ? activeParentStackItem.nodeId : null,
11366
11830
  _branchDirection: activeParentStackItem ? activeParentStackItem.entryDirection : null
11367
11831
  };
@@ -11409,7 +11873,7 @@ function XViewScene({
11409
11873
  }));
11410
11874
  }
11411
11875
  }, [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]);
11412
- const handleReadModeHighlight = useCallback3((nodeId) => {
11876
+ const handleReadModeHighlight = useCallback4((nodeId) => {
11413
11877
  if (stateRef.current.highlightedNodeId !== nodeId) {
11414
11878
  stateRef.current.highlightedNodeId = nodeId;
11415
11879
  }
@@ -11421,7 +11885,6 @@ function XViewScene({
11421
11885
  readingMode.ancestry.tree,
11422
11886
  Object.values(parentDataRef.current).flatMap((f) => f.nodes),
11423
11887
  ancestryDataRef.current
11424
- // <--- Adicionar
11425
11888
  );
11426
11889
  const findNodeInTree = (tree, targetId) => {
11427
11890
  if (!tree) return null;
@@ -11475,7 +11938,6 @@ function XViewScene({
11475
11938
  description_sections: ancestry.description_sections,
11476
11939
  direction: null,
11477
11940
  customProperties: rootProps
11478
- // <--- ADICIONADO
11479
11941
  };
11480
11942
  }
11481
11943
  const fullTree = buildFullAncestryTree(
@@ -11504,7 +11966,6 @@ function XViewScene({
11504
11966
  description_sections: currentMeta.description_sections,
11505
11967
  direction: currentDirection,
11506
11968
  customProperties: branchProps
11507
- // <--- ADICIONADO
11508
11969
  };
11509
11970
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
11510
11971
  const readModeAbstractionTree = useMemo12(() => {
@@ -11519,7 +11980,7 @@ function XViewScene({
11519
11980
  allAncestries
11520
11981
  );
11521
11982
  }, [readingMode.isActive, readingMode.ancestry, buildFullAncestryTree, sceneVersion]);
11522
- const handleStartReadingAncestry = useCallback3(
11983
+ const handleStartReadingAncestry = useCallback4(
11523
11984
  async (ancestryObject) => {
11524
11985
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11525
11986
  if (!ancestryObject || !ancestryObject.tree) {
@@ -11540,7 +12001,6 @@ function XViewScene({
11540
12001
  ancestry: ancestryObject,
11541
12002
  branchStack: [],
11542
12003
  autoAbstraction: shouldAutoRenderAbstraction
11543
- // <--- FLAG ENVIADA PARA A UI
11544
12004
  });
11545
12005
  if (shouldAutoRenderAbstraction) {
11546
12006
  handleRenderAbstractionTree(ancestryObject, null);
@@ -11554,9 +12014,8 @@ function XViewScene({
11554
12014
  }
11555
12015
  },
11556
12016
  [handleRenderAncestry, handleRenderAbstractionTree]
11557
- // <--- DEPENDÊNCIA ADICIONADA
11558
12017
  );
11559
- const handleReadModeSectionChange = useCallback3((activeSectionId) => {
12018
+ const handleReadModeSectionChange = useCallback4((activeSectionId) => {
11560
12019
  const { ancestry, branchStack } = readingMode;
11561
12020
  if (!ancestry || !readingMode.isActive) return;
11562
12021
  let targetObj = ancestry;
@@ -11625,10 +12084,10 @@ function XViewScene({
11625
12084
  }, 0);
11626
12085
  handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
11627
12086
  }, [readingMode, handleRenderAncestry, buildFullAncestryTree, ancestryDataRef.current]);
11628
- const handleCloseReadMode = useCallback3(() => {
12087
+ const handleCloseReadMode = useCallback4(() => {
11629
12088
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
11630
12089
  }, []);
11631
- const handleAncestrySectionChange = useCallback3((activeSectionId, ancestryOverride = null, rotation = 0) => {
12090
+ const handleAncestrySectionChange = useCallback4((activeSectionId, ancestryOverride = null, rotation = 0) => {
11632
12091
  var _a2, _b2;
11633
12092
  const currentMode = stateRef.current.ancestry;
11634
12093
  let targetObj = ancestryOverride;
@@ -11680,7 +12139,7 @@ function XViewScene({
11680
12139
  const renderPayload = { ...targetObj, tree: treeToRender };
11681
12140
  handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
11682
12141
  }, [handleRenderAncestry]);
11683
- const handleEditAncestry = useCallback3(
12142
+ const handleEditAncestry = useCallback4(
11684
12143
  async (ancestryObject) => {
11685
12144
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11686
12145
  if (!ancestryObject || !ancestryObject.tree) {
@@ -11703,10 +12162,8 @@ function XViewScene({
11703
12162
  ...ancestryObject,
11704
12163
  tree: fullTree,
11705
12164
  abstraction_tree: fullAbstractionTree,
11706
- // NOVO
11707
12165
  selectedParentId: ancestryObject.ancestral_node,
11708
12166
  selectedAbstractionParentId: ancestryObject.ancestral_node,
11709
- // NOVO
11710
12167
  isEditMode: true,
11711
12168
  currentAncestryId: ancestryObject.ancestry_id,
11712
12169
  ancestryName: ancestryObject.name || `Ancestralidade ${fullTree.node.name}`,
@@ -11714,7 +12171,6 @@ function XViewScene({
11714
12171
  ancestryDescriptionSections: ancestryObject.description_sections || [],
11715
12172
  isAddingNodes: false,
11716
12173
  isAddingAbstractionNodes: false
11717
- // NOVO
11718
12174
  });
11719
12175
  },
11720
12176
  [handleRenderAncestry, buildFullAncestryTree]
@@ -11722,7 +12178,7 @@ function XViewScene({
11722
12178
  const handleSelectAncestryParent = (nodeId) => {
11723
12179
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
11724
12180
  };
11725
- const handleRemoveFromAncestry = useCallback3((pathToRemove) => {
12181
+ const handleRemoveFromAncestry = useCallback4((pathToRemove) => {
11726
12182
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
11727
12183
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
11728
12184
  return;
@@ -11747,7 +12203,7 @@ function XViewScene({
11747
12203
  return { ...prev, tree: newTree };
11748
12204
  });
11749
12205
  }, []);
11750
- const handleSaveAncestry = useCallback3(
12206
+ const handleSaveAncestry = useCallback4(
11751
12207
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
11752
12208
  const treeToUse = treeOverride || ancestryMode.tree;
11753
12209
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -11951,7 +12407,7 @@ function XViewScene({
11951
12407
  });
11952
12408
  setEditingAncestryRel({ visible: false, data: null, path: null });
11953
12409
  };
11954
- const handleDeleteAncestry = useCallback3(
12410
+ const handleDeleteAncestry = useCallback4(
11955
12411
  async (ancestryIdToDelete) => {
11956
12412
  if (!ancestryIdToDelete) {
11957
12413
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -12013,15 +12469,15 @@ function XViewScene({
12013
12469
  },
12014
12470
  [save_view_data, delete_file_action]
12015
12471
  );
12016
- const handleOpenAncestryBoard = useCallback3(() => {
12472
+ const handleOpenAncestryBoard = useCallback4(() => {
12017
12473
  setIsAncestryBoardOpen(true);
12018
12474
  }, []);
12019
- const handleSelectAncestryFromBoard = useCallback3((ancestry) => {
12475
+ const handleSelectAncestryFromBoard = useCallback4((ancestry) => {
12020
12476
  setIsAncestryBoardOpen(false);
12021
12477
  setIsSidebarOpen(false);
12022
12478
  handleStartReadingAncestry(ancestry);
12023
12479
  }, [handleStartReadingAncestry]);
12024
- const handleSaveAncestryBoard = useCallback3(async (groups) => {
12480
+ const handleSaveAncestryBoard = useCallback4(async (groups) => {
12025
12481
  if (!sceneConfigId || !viewParams || !session) return;
12026
12482
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
12027
12483
  await save_ancestry_board_action(sceneConfigId, sceneType, groups, session, ownerId);
@@ -12045,13 +12501,13 @@ function XViewScene({
12045
12501
  return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
12046
12502
  });
12047
12503
  }, [parentDataRef.current, sceneVersion]);
12048
- const handleAddExistingNode = useCallback3(
12504
+ const handleAddExistingNode = useCallback4(
12049
12505
  (nodeId) => {
12050
12506
  return userActionHandlers.handleAddExistingNodeById(actionHandlerContext, nodeId);
12051
12507
  },
12052
12508
  [actionHandlerContext]
12053
12509
  );
12054
- const handleSaveCurrentView = useCallback3(async () => {
12510
+ const handleSaveCurrentView = useCallback4(async () => {
12055
12511
  const { nodeObjects, allLinks } = stateRef.current;
12056
12512
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
12057
12513
  console.warn("N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente.");
@@ -12091,7 +12547,7 @@ function XViewScene({
12091
12547
  const allAvailableAncestries = useMemo12(() => {
12092
12548
  return ancestryDataRef.current || [];
12093
12549
  }, [sceneVersion, isInitialized]);
12094
- const handleOpenReference = useCallback3((referenceData) => {
12550
+ const handleOpenReference = useCallback4((referenceData) => {
12095
12551
  const { type, id } = referenceData;
12096
12552
  if (type === "node") {
12097
12553
  const targetNode = allAvailableNodes.find((n) => String(n.id) === String(id));
@@ -12118,10 +12574,10 @@ function XViewScene({
12118
12574
  }
12119
12575
  }
12120
12576
  }, [allAvailableNodes, allAvailableAncestries, handleEditAncestry, tweenToTarget]);
12121
- const handleToggleAncestryAddMode = useCallback3(() => {
12577
+ const handleToggleAncestryAddMode = useCallback4(() => {
12122
12578
  setAncestryMode((prev) => ({ ...prev, isAddingNodes: !prev.isAddingNodes }));
12123
12579
  }, []);
12124
- const handleFocusNode = useCallback3((nodeData) => {
12580
+ const handleFocusNode = useCallback4((nodeData) => {
12125
12581
  if (!nodeData) return;
12126
12582
  const nodeMesh = stateRef.current.nodeObjects[String(nodeData.id)];
12127
12583
  if (nodeMesh) {
@@ -12191,7 +12647,6 @@ function XViewScene({
12191
12647
  height: "100vh",
12192
12648
  position: "relative",
12193
12649
  overflow: "hidden",
12194
- // <--- ADICIONE ESTA LINHA
12195
12650
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
12196
12651
  }
12197
12652
  },
@@ -12258,9 +12713,20 @@ function XViewScene({
12258
12713
  readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React23.createElement(
12259
12714
  "div",
12260
12715
  {
12261
- className: "ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col transition-all duration-300 ease-out w-[min(92vw,700px)]",
12262
- style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)" }
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" }
12263
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
+ ),
12264
12730
  /* @__PURE__ */ React23.createElement(
12265
12731
  DescriptionReadModePanel,
12266
12732
  {