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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.js +824 -373
  2. package/dist/index.mjs +744 -293
  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 useCallback4, useEffect as useEffect21, useRef as useRef17, useState as useState23, useMemo as useMemo12 } from "react";
2
+ import React24, { useCallback as useCallback4, useEffect as useEffect21, useRef as useRef18, useState as useState24, 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";
@@ -904,7 +904,7 @@ var createNodeMesh = (nodeData, position, glowTexture) => {
904
904
  if (useImage && nodeData.textureImageUrl) {
905
905
  geometry = new THREE.CircleGeometry(1.5, 48);
906
906
  const texture = getTexture(nodeData.textureImageUrl);
907
- material = new THREE.MeshBasicMaterial({
907
+ material = new MeshBasicMaterial({
908
908
  map: texture,
909
909
  color: 16777215,
910
910
  side: THREE.DoubleSide,
@@ -1515,7 +1515,7 @@ var addStandaloneNodeToScene = (state, nodeData, position) => {
1515
1515
  scaleTween.start();
1516
1516
  }
1517
1517
  };
1518
- var getParentFileInfoForNode = (allParentData, sceneData, nodeId) => {
1518
+ var getParentFileInfoForNode = (allParentData, sceneData, nodeId, sceneConfigId = null, sceneOwnerId = null) => {
1519
1519
  const parentDbsArray = (sceneData == null ? void 0 : sceneData.parent_dbs) || [];
1520
1520
  for (const parentFileId in allParentData) {
1521
1521
  if (allParentData.hasOwnProperty(parentFileId)) {
@@ -1524,6 +1524,8 @@ var getParentFileInfoForNode = (allParentData, sceneData, nodeId) => {
1524
1524
  const parentDbInfo = parentDbsArray.find((db) => String(db.db_id) === String(parentFileId));
1525
1525
  if (parentDbInfo) {
1526
1526
  return { parentFileId, ownerId: parentDbInfo.owner_id };
1527
+ } else if (sceneConfigId && String(parentFileId) === String(sceneConfigId)) {
1528
+ return { parentFileId, ownerId: sceneOwnerId };
1527
1529
  } else {
1528
1530
  console.warn(`Owner ID n\xE3o encontrado em sceneData.parent_dbs para o parentFileId: ${parentFileId}`);
1529
1531
  return { parentFileId, ownerId: null };
@@ -1793,6 +1795,7 @@ var userActionHandlers = {
1793
1795
  setters.setFormPosition((p) => ({ ...p, opacity: 0 }));
1794
1796
  },
1795
1797
  handleSaveVersionNode: async (context, newNodeData) => {
1798
+ var _a;
1796
1799
  const { graphDataRef, sceneDataRef, stateRef, versionMode, setters } = context;
1797
1800
  if (!graphDataRef.current || !sceneDataRef.current) return;
1798
1801
  const { sourceNodeData } = versionMode;
@@ -1802,7 +1805,7 @@ var userActionHandlers = {
1802
1805
  version_node: { is_version: true, parent_node: sourceNodeData.id }
1803
1806
  };
1804
1807
  const newLink = { id: `link_${short.generate()}`, source: sourceNodeData.id, target: newNode.id };
1805
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id);
1808
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id, context.sceneConfigId, context.ownerId);
1806
1809
  if (!parentInfo || !parentInfo.ownerId) {
1807
1810
  console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node de origem:", sourceNodeData.id);
1808
1811
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio.");
@@ -1812,9 +1815,21 @@ var userActionHandlers = {
1812
1815
  const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileId]));
1813
1816
  specificParentData.nodes.push(newNode);
1814
1817
  specificParentData.links.push(newLink);
1815
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
1816
1818
  try {
1817
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
1819
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
1820
+ if (isView && parentFileId === context.sceneConfigId) {
1821
+ const viewFilePayload = {
1822
+ parent_dbs: sceneDataRef.current.parent_dbs,
1823
+ nodes: sceneDataRef.current.nodes,
1824
+ links: sceneDataRef.current.links,
1825
+ quest_nodes: specificParentData.nodes,
1826
+ quest_links: specificParentData.links
1827
+ };
1828
+ await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
1829
+ } else {
1830
+ const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
1831
+ await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
1832
+ }
1818
1833
  graphDataRef.current[parentFileId] = specificParentData;
1819
1834
  const finalPosition = stateRef.current.ghostElements.node.position.clone();
1820
1835
  addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
@@ -1971,6 +1986,7 @@ var userActionHandlers = {
1971
1986
  if (mountRef.current) mountRef.current.style.cursor = "grab";
1972
1987
  },
1973
1988
  handleCompleteConnection: async (context, targetNodeData) => {
1989
+ var _a;
1974
1990
  const { stateRef, graphDataRef, sceneDataRef } = context;
1975
1991
  const { sourceNodeData } = stateRef.current.connection;
1976
1992
  if (!graphDataRef.current || !sceneDataRef.current || !sourceNodeData || !targetNodeData) {
@@ -1978,7 +1994,7 @@ var userActionHandlers = {
1978
1994
  userActionHandlers.handleCancelConnection(context);
1979
1995
  return;
1980
1996
  }
1981
- const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id);
1997
+ const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id, context.sceneConfigId, context.ownerId);
1982
1998
  if (!sourceParentInfo || !sourceParentInfo.ownerId) {
1983
1999
  console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node de origem:", sourceNodeData.id);
1984
2000
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio.");
@@ -1993,12 +2009,26 @@ var userActionHandlers = {
1993
2009
  source: sourceNodeData.id,
1994
2010
  target: targetNodeData.id
1995
2011
  };
1996
- const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
1997
- specificParentData.links.push(newLink);
1998
- const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
1999
2012
  try {
2000
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2001
- graphDataRef.current[parentFileIdToSave] = specificParentData;
2013
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2014
+ if (isView && parentFileIdToSave === context.sceneConfigId) {
2015
+ const specificParentData = graphDataRef.current[context.sceneConfigId];
2016
+ specificParentData.links.push(newLink);
2017
+ const viewFilePayload = {
2018
+ parent_dbs: sceneDataRef.current.parent_dbs,
2019
+ nodes: sceneDataRef.current.nodes,
2020
+ links: sceneDataRef.current.links,
2021
+ quest_nodes: specificParentData.nodes,
2022
+ quest_links: specificParentData.links
2023
+ };
2024
+ await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
2025
+ } else {
2026
+ const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
2027
+ specificParentData.links.push(newLink);
2028
+ const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
2029
+ await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2030
+ graphDataRef.current[parentFileIdToSave] = specificParentData;
2031
+ }
2002
2032
  addNewLinkToScene(stateRef.current, newLink);
2003
2033
  } catch (error) {
2004
2034
  console.error("Falha ao salvar a nova conex\xE3o:", error);
@@ -2067,8 +2097,8 @@ var userActionHandlers = {
2067
2097
  } else {
2068
2098
  newTargetId = newEndNodeData.id;
2069
2099
  }
2070
- const originalParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldSourceId);
2071
- const newParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newSourceId);
2100
+ const originalParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldSourceId, context.sceneConfigId, context.ownerId);
2101
+ const newParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newSourceId, context.sceneConfigId, context.ownerId);
2072
2102
  if (!originalParentInfo || !newParentInfo || !originalParentInfo.ownerId || !newParentInfo.ownerId) {
2073
2103
  console.error("N\xE3o foi poss\xEDvel encontrar informa\xE7\xF5es dos arquivos pai para o relink.");
2074
2104
  alert("Ocorreu um erro ao identificar os arquivos pai para salvar a altera\xE7\xE3o.");
@@ -2082,6 +2112,22 @@ var userActionHandlers = {
2082
2112
  target: newTargetId,
2083
2113
  id: linkId
2084
2114
  };
2115
+ const saveParentData = async (fileId, fileOwnerId, data) => {
2116
+ var _a;
2117
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2118
+ if (isView && fileId === context.sceneConfigId) {
2119
+ const viewFilePayload = {
2120
+ parent_dbs: sceneDataRef.current.parent_dbs,
2121
+ nodes: sceneDataRef.current.nodes,
2122
+ links: sceneDataRef.current.links,
2123
+ quest_nodes: data.nodes,
2124
+ quest_links: data.links
2125
+ };
2126
+ return context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
2127
+ } else {
2128
+ return context.actions.save_view_data(`x_view_dbs/${fileOwnerId}/${fileId}`, data);
2129
+ }
2130
+ };
2085
2131
  const savePromises = [];
2086
2132
  const filesToUpdate = {};
2087
2133
  if (originalParentInfo.parentFileId !== newParentInfo.parentFileId) {
@@ -2090,16 +2136,12 @@ var userActionHandlers = {
2090
2136
  (l) => String(l.id) !== String(linkId)
2091
2137
  );
2092
2138
  filesToUpdate[originalParentInfo.parentFileId] = updatedOriginalParentData;
2093
- savePromises.push(
2094
- context.actions.save_view_data(`x_view_dbs/${originalParentInfo.ownerId}/${originalParentInfo.parentFileId}`, updatedOriginalParentData)
2095
- );
2139
+ savePromises.push(saveParentData(originalParentInfo.parentFileId, originalParentInfo.ownerId, updatedOriginalParentData));
2096
2140
  const updatedNewParentData = JSON.parse(JSON.stringify(graphDataRef.current[newParentInfo.parentFileId]));
2097
2141
  if (!updatedNewParentData.links) updatedNewParentData.links = [];
2098
2142
  updatedNewParentData.links.push(newLinkData);
2099
2143
  filesToUpdate[newParentInfo.parentFileId] = updatedNewParentData;
2100
- savePromises.push(
2101
- context.actions.save_view_data(`x_view_dbs/${newParentInfo.ownerId}/${newParentInfo.parentFileId}`, updatedNewParentData)
2102
- );
2144
+ savePromises.push(saveParentData(newParentInfo.parentFileId, newParentInfo.ownerId, updatedNewParentData));
2103
2145
  } else {
2104
2146
  const updatedParentData = JSON.parse(JSON.stringify(graphDataRef.current[originalParentInfo.parentFileId]));
2105
2147
  updatedParentData.links = updatedParentData.links.filter(
@@ -2107,9 +2149,7 @@ var userActionHandlers = {
2107
2149
  );
2108
2150
  updatedParentData.links.push(newLinkData);
2109
2151
  filesToUpdate[originalParentInfo.parentFileId] = updatedParentData;
2110
- savePromises.push(
2111
- context.actions.save_view_data(`x_view_dbs/${originalParentInfo.ownerId}/${originalParentInfo.parentFileId}`, updatedParentData)
2112
- );
2152
+ savePromises.push(saveParentData(originalParentInfo.parentFileId, originalParentInfo.ownerId, updatedParentData));
2113
2153
  }
2114
2154
  try {
2115
2155
  await Promise.all(savePromises);
@@ -2127,7 +2167,7 @@ var userActionHandlers = {
2127
2167
  }
2128
2168
  },
2129
2169
  handleDeleteLink: async (context, linkObject) => {
2130
- var _a, _b, _c, _d, _e, _f;
2170
+ var _a, _b, _c, _d, _e, _f, _g;
2131
2171
  const { stateRef, graphDataRef, sceneDataRef, setters } = context;
2132
2172
  setters.setRelationshipMenu({ visible: false });
2133
2173
  if (!(linkObject == null ? void 0 : linkObject.userData) || !graphDataRef.current || !sceneDataRef.current) return;
@@ -2136,7 +2176,7 @@ var userActionHandlers = {
2136
2176
  console.error("Tentativa de deletar um link sem ID.", linkObject.userData);
2137
2177
  return;
2138
2178
  }
2139
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkObject.userData.source);
2179
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkObject.userData.source, context.sceneConfigId, context.ownerId);
2140
2180
  if (!parentInfo || !parentInfo.ownerId) {
2141
2181
  console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o link:", linkIdToDelete);
2142
2182
  alert("Ocorreu um erro ao identificar o arquivo pai da rela\xE7\xE3o para exclus\xE3o.");
@@ -2148,9 +2188,25 @@ var userActionHandlers = {
2148
2188
  const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileId]));
2149
2189
  const newLinks = (specificParentData.links || []).filter((l) => String(l.id) !== String(linkIdToDelete));
2150
2190
  specificParentData.links = newLinks;
2151
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2191
+ let filenameToSave;
2192
+ let payloadToSave;
2193
+ const isView = ((_g = context.viewType) == null ? void 0 : _g.toLowerCase()) === "view";
2194
+ if (isView && parentFileId === context.sceneConfigId) {
2195
+ filenameToSave = context.sceneSaveUrl;
2196
+ sceneDataRef.current.links = sceneDataRef.current.links.filter((l) => String(l.id) !== String(linkIdToDelete));
2197
+ payloadToSave = {
2198
+ parent_dbs: sceneDataRef.current.parent_dbs,
2199
+ nodes: sceneDataRef.current.nodes,
2200
+ links: sceneDataRef.current.links,
2201
+ quest_nodes: specificParentData.nodes,
2202
+ quest_links: specificParentData.links
2203
+ };
2204
+ } else {
2205
+ filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2206
+ payloadToSave = specificParentData;
2207
+ }
2152
2208
  try {
2153
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2209
+ await context.actions.save_view_data(filenameToSave, payloadToSave);
2154
2210
  graphDataRef.current[parentFileId] = specificParentData;
2155
2211
  setters.setDetailsLink((prev) => String(prev == null ? void 0 : prev.id) === String(linkIdToDelete) ? null : prev);
2156
2212
  if (stateRef.current.hoveredLink === linkObject) {
@@ -2295,6 +2351,7 @@ var userActionHandlers = {
2295
2351
  stateRef.current.selectedNodes.clear();
2296
2352
  },
2297
2353
  handleDeleteMultipleNodes: async (context, nodeIds) => {
2354
+ var _a;
2298
2355
  const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
2299
2356
  setters.setMultiContextMenu({ visible: false });
2300
2357
  if (!nodeIds || nodeIds.size === 0 || !graphDataRef.current || !sceneDataRef.current) return;
@@ -2313,7 +2370,7 @@ var userActionHandlers = {
2313
2370
  }
2314
2371
  const changesByParentFile = {};
2315
2372
  for (const nodeId of strNodeIdsToDelete) {
2316
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeId);
2373
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeId, context.sceneConfigId, context.ownerId);
2317
2374
  if (!parentInfo || !parentInfo.ownerId) {
2318
2375
  console.warn(`Node com ID ${nodeId} n\xE3o encontrado ou sem ownerId. Ignorando.`);
2319
2376
  continue;
@@ -2347,8 +2404,27 @@ var userActionHandlers = {
2347
2404
  originalData.links = (originalData.links || []).filter(
2348
2405
  (l) => !linksToDelete.has(String(l.id))
2349
2406
  );
2350
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2351
- savePromises.push(context.actions.save_view_data(filenameForSpecificParent, originalData));
2407
+ let filenameToSave;
2408
+ let payloadToSave;
2409
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2410
+ if (isView && parentFileId === context.sceneConfigId) {
2411
+ filenameToSave = context.sceneSaveUrl;
2412
+ const strNodesToDelete = Array.from(nodesToDelete).map(String);
2413
+ const strLinksToDelete = Array.from(linksToDelete).map(String);
2414
+ sceneDataRef.current.nodes = sceneDataRef.current.nodes.filter((n) => !strNodesToDelete.includes(String(n.id)));
2415
+ sceneDataRef.current.links = sceneDataRef.current.links.filter((l) => !strLinksToDelete.includes(String(l.id)));
2416
+ payloadToSave = {
2417
+ parent_dbs: sceneDataRef.current.parent_dbs,
2418
+ nodes: sceneDataRef.current.nodes,
2419
+ links: sceneDataRef.current.links,
2420
+ quest_nodes: originalData.nodes,
2421
+ quest_links: originalData.links
2422
+ };
2423
+ } else {
2424
+ filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2425
+ payloadToSave = originalData;
2426
+ }
2427
+ savePromises.push(context.actions.save_view_data(filenameToSave, payloadToSave));
2352
2428
  updatedParentDataCache[parentFileId] = originalData;
2353
2429
  }
2354
2430
  }
@@ -2369,6 +2445,7 @@ var userActionHandlers = {
2369
2445
  }
2370
2446
  },
2371
2447
  handleDeleteNode: async (context, nodeData) => {
2448
+ var _a;
2372
2449
  const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
2373
2450
  if (actions.delete_file && nodeData) {
2374
2451
  const urls = extractFileUrlsFromProperties(nodeData);
@@ -2380,7 +2457,7 @@ var userActionHandlers = {
2380
2457
  if (!nodeData || !graphDataRef.current || !sceneDataRef.current) return;
2381
2458
  const nodeIdToDelete = nodeData.id;
2382
2459
  const strNodeId = String(nodeIdToDelete);
2383
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeIdToDelete);
2460
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeIdToDelete, context.sceneConfigId, context.ownerId);
2384
2461
  if (!parentInfo || !parentInfo.ownerId) {
2385
2462
  console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node a ser exclu\xEDdo:", nodeIdToDelete);
2386
2463
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para exclus\xE3o.");
@@ -2392,9 +2469,28 @@ var userActionHandlers = {
2392
2469
  const newLinks = (specificParentData.links || []).filter((l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId);
2393
2470
  specificParentData.nodes = newNodes;
2394
2471
  specificParentData.links = newLinks;
2395
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2472
+ let filenameToSave;
2473
+ let payloadToSave;
2474
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2475
+ if (isView && parentFileId === context.sceneConfigId) {
2476
+ filenameToSave = context.sceneSaveUrl;
2477
+ const newVisualNodes = sceneDataRef.current.nodes.filter((n) => String(n.id) !== strNodeId);
2478
+ const newVisualLinks = sceneDataRef.current.links.filter((l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId);
2479
+ sceneDataRef.current.nodes = newVisualNodes;
2480
+ sceneDataRef.current.links = newVisualLinks;
2481
+ payloadToSave = {
2482
+ parent_dbs: sceneDataRef.current.parent_dbs,
2483
+ nodes: newVisualNodes,
2484
+ links: newVisualLinks,
2485
+ quest_nodes: specificParentData.nodes,
2486
+ quest_links: specificParentData.links
2487
+ };
2488
+ } else {
2489
+ filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2490
+ payloadToSave = specificParentData;
2491
+ }
2396
2492
  try {
2397
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2493
+ await context.actions.save_view_data(filenameToSave, payloadToSave);
2398
2494
  graphDataRef.current[parentFileId] = specificParentData;
2399
2495
  setters.setDetailsNode((prev) => String(prev == null ? void 0 : prev.id) === String(nodeIdToDelete) ? null : prev);
2400
2496
  removeNodeFromScene(stateRef.current, nodeIdToDelete);
@@ -2405,10 +2501,11 @@ var userActionHandlers = {
2405
2501
  }
2406
2502
  },
2407
2503
  handleSaveNodeDetails: async (context, updatedNode, keepOpen = false) => {
2504
+ var _a;
2408
2505
  const { graphDataRef, sceneDataRef, stateRef, setters } = context;
2409
2506
  if (!graphDataRef.current || !sceneDataRef.current) return;
2410
2507
  const { _baseEmissiveIntensity: ignored, ...nodeToSave } = updatedNode;
2411
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeToSave.id);
2508
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeToSave.id, context.sceneConfigId, context.ownerId);
2412
2509
  if (!parentInfo || !parentInfo.ownerId) {
2413
2510
  console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node a ser atualizado:", nodeToSave.id);
2414
2511
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para atualiza\xE7\xE3o.");
@@ -2424,9 +2521,21 @@ var userActionHandlers = {
2424
2521
  alert("Erro interno: Node n\xE3o encontrado para salvar.");
2425
2522
  return;
2426
2523
  }
2427
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2428
2524
  try {
2429
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2525
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2526
+ if (isView && parentFileId === context.sceneConfigId) {
2527
+ const viewFilePayload = {
2528
+ parent_dbs: sceneDataRef.current.parent_dbs,
2529
+ nodes: sceneDataRef.current.nodes,
2530
+ links: sceneDataRef.current.links,
2531
+ quest_nodes: specificParentData.nodes,
2532
+ quest_links: specificParentData.links
2533
+ };
2534
+ await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
2535
+ } else {
2536
+ const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2537
+ await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2538
+ }
2430
2539
  graphDataRef.current[parentFileId] = specificParentData;
2431
2540
  updateExistingNodeVisuals(stateRef.current, nodeToSave);
2432
2541
  setters.setSceneVersion((v) => v + 1);
@@ -2439,10 +2548,11 @@ var userActionHandlers = {
2439
2548
  }
2440
2549
  },
2441
2550
  handleSaveLinkDetails: async (context, updatedLink, keepOpen = false) => {
2551
+ var _a;
2442
2552
  const { graphDataRef, sceneDataRef, stateRef, setters } = context;
2443
2553
  if (!graphDataRef.current || !sceneDataRef.current) return;
2444
2554
  const { sourceNode, targetNode, ...linkToSave } = updatedLink;
2445
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkToSave.source);
2555
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkToSave.source, context.sceneConfigId, context.ownerId);
2446
2556
  if (!parentInfo || !parentInfo.ownerId) {
2447
2557
  console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o link a ser atualizado:", linkToSave.id);
2448
2558
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para atualiza\xE7\xE3o.");
@@ -2458,9 +2568,21 @@ var userActionHandlers = {
2458
2568
  alert("Erro interno: link n\xE3o encontrado para salvar.");
2459
2569
  return;
2460
2570
  }
2461
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2462
2571
  try {
2463
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2572
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2573
+ if (isView && parentFileId === context.sceneConfigId) {
2574
+ const viewFilePayload = {
2575
+ parent_dbs: sceneDataRef.current.parent_dbs,
2576
+ nodes: sceneDataRef.current.nodes,
2577
+ links: sceneDataRef.current.links,
2578
+ quest_nodes: specificParentData.nodes,
2579
+ quest_links: specificParentData.links
2580
+ };
2581
+ await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
2582
+ } else {
2583
+ const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2584
+ await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2585
+ }
2464
2586
  graphDataRef.current[parentFileId] = specificParentData;
2465
2587
  const lineObject = stateRef.current.allLinks.find(
2466
2588
  (l) => String(l.userData.id) === String(linkToSave.id)
@@ -7835,9 +7957,180 @@ function InSceneVersionForm({
7835
7957
  ));
7836
7958
  }
7837
7959
 
7960
+ // src/components/InSceneQuestForm.jsx
7961
+ import React15, { useState as useState16, useRef as useRef12 } from "react";
7962
+ import { FiPlus as FiPlus5, FiCheck as FiCheck9, FiEdit2 as FiEdit26, FiTarget, FiX as FiX4 } from "react-icons/fi";
7963
+ var QUEST_STATUS_COLORS = {
7964
+ "Backlog": "#64748b",
7965
+ // Slate (Cinza azulado)
7966
+ "In Progress": "#eab308",
7967
+ // Yellow (Amarelo)
7968
+ "Review": "#a855f7",
7969
+ // Purple (Roxo)
7970
+ "Done": "#22c55e"
7971
+ // Green (Verde)
7972
+ };
7973
+ function InSceneQuestForm({
7974
+ onSave,
7975
+ onCancel,
7976
+ style,
7977
+ refEl,
7978
+ onOpenImageViewer,
7979
+ availableNodes = [],
7980
+ availableAncestries = [],
7981
+ onMentionClick,
7982
+ onUploadFile
7983
+ }) {
7984
+ const [name, setName] = useState16("");
7985
+ const [types, setTypes] = useState16(["quest"]);
7986
+ const [typeInput, setTypeInput] = useState16("");
7987
+ const [status, setStatus] = useState16("Backlog");
7988
+ const [size, setSize] = useState16("medium");
7989
+ const [intensity, setIntensity] = useState16(0);
7990
+ const [description, setDescription] = useState16("");
7991
+ const [customProps, setCustomProps] = useState16([]);
7992
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState16(false);
7993
+ const propsEndRef = useRef12(null);
7994
+ const handleAddProp = () => {
7995
+ const newProp = createNewCustomProperty(customProps);
7996
+ setCustomProps([...customProps, newProp]);
7997
+ setTimeout(() => {
7998
+ var _a;
7999
+ (_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
8000
+ }, 100);
8001
+ };
8002
+ const handleRemoveProp = (index) => setCustomProps(customProps.filter((_, i) => i !== index));
8003
+ const handleUpdateProp = (index, updatedProp) => {
8004
+ const newProps = [...customProps];
8005
+ newProps[index] = updatedProp;
8006
+ setCustomProps(newProps);
8007
+ };
8008
+ const handleAddType = (newType) => {
8009
+ const trimmed = newType.trim();
8010
+ if (trimmed && !types.includes(trimmed)) {
8011
+ setTypes([...types, trimmed]);
8012
+ setTypeInput("");
8013
+ }
8014
+ };
8015
+ const handleRemoveType = (indexToRemove) => {
8016
+ if (types[indexToRemove] === "quest") return;
8017
+ setTypes(types.filter((_, index) => index !== indexToRemove));
8018
+ };
8019
+ const handleTypeInputKeyDown = (e) => {
8020
+ if (e.key === "Enter") {
8021
+ e.preventDefault();
8022
+ handleAddType(typeInput);
8023
+ } else if (e.key === "Backspace" && typeInput === "" && types.length > 1) {
8024
+ handleRemoveType(types.length - 1);
8025
+ }
8026
+ };
8027
+ const handleSubmit = (e) => {
8028
+ e.preventDefault();
8029
+ if (!name.trim()) {
8030
+ alert("O campo 'Nome' \xE9 obrigat\xF3rio.");
8031
+ return;
8032
+ }
8033
+ const additionalData = toObjectFromCustomProps(
8034
+ customProps.filter((prop) => prop.key.trim() && !prop.isEditing)
8035
+ );
8036
+ const processedSections = processDescriptionForSave(description, []);
8037
+ onSave({
8038
+ name: name.trim(),
8039
+ type: types,
8040
+ color: QUEST_STATUS_COLORS[status],
8041
+ // Cor atrelada ao status
8042
+ status,
8043
+ size,
8044
+ intensity,
8045
+ description: description.trim(),
8046
+ description_sections: processedSections,
8047
+ useImageAsTexture: false,
8048
+ textureImageUrl: null,
8049
+ ...additionalData
8050
+ });
8051
+ };
8052
+ const swallow = (e) => e.stopPropagation();
8053
+ const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
8054
+ const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
8055
+ return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(
8056
+ "div",
8057
+ {
8058
+ ref: refEl,
8059
+ 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 w-[min(92vw,440px)] overflow-hidden",
8060
+ style,
8061
+ onPointerDown: swallow,
8062
+ onClick: swallow,
8063
+ onWheel: swallow,
8064
+ onContextMenu: swallow,
8065
+ onDoubleClick: swallow
8066
+ },
8067
+ /* @__PURE__ */ React15.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS[status]}, transparent)` } }),
8068
+ /* @__PURE__ */ React15.createElement("div", { className: "px-6 pt-5 pb-3" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React15.createElement(FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React15.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova Tarefa / Objetivo")), /* @__PURE__ */ React15.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, "Criar Quest")),
8069
+ /* @__PURE__ */ React15.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col max-h-[68vh]" }, /* @__PURE__ */ React15.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ React15.createElement(
8070
+ "select",
8071
+ {
8072
+ value: status,
8073
+ onChange: (e) => setStatus(e.target.value),
8074
+ className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 appearance-none cursor-pointer",
8075
+ style: { borderLeft: `4px solid ${QUEST_STATUS_COLORS[status]}` }
8076
+ },
8077
+ /* @__PURE__ */ React15.createElement("option", { value: "Backlog" }, "Backlog"),
8078
+ /* @__PURE__ */ React15.createElement("option", { value: "In Progress" }, "In Progress"),
8079
+ /* @__PURE__ */ React15.createElement("option", { value: "Review" }, "Review"),
8080
+ /* @__PURE__ */ React15.createElement("option", { value: "Done" }, "Done")
8081
+ )), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ React15.createElement("input", { required: true, type: "text", placeholder: "Ex.: Refatorar M\xF3dulo X", value: name, onChange: (e) => setName(e.target.value), className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ React15.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ React15.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ React15.createElement(FiX4, { size: 12 })))), /* @__PURE__ */ React15.createElement(
8082
+ "input",
8083
+ {
8084
+ type: "text",
8085
+ value: typeInput,
8086
+ onChange: (e) => setTypeInput(e.target.value),
8087
+ onKeyDown: handleTypeInputKeyDown,
8088
+ onBlur: () => {
8089
+ if (typeInput.trim()) handleAddType(typeInput);
8090
+ },
8091
+ className: "flex-1 bg-transparent text-sm min-w-[80px] focus:outline-none text-slate-200",
8092
+ autoComplete: "off"
8093
+ }
8094
+ ))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o (Opcional)"), /* @__PURE__ */ React15.createElement("div", { className: "relative group min-h-[80px] bg-slate-800/70 p-2.5 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ React15.createElement(
8095
+ DescriptionDisplay,
8096
+ {
8097
+ description,
8098
+ savedSections: [],
8099
+ availableNodes,
8100
+ availableAncestries,
8101
+ onMentionClick,
8102
+ onSaveDescription: (newDesc) => setDescription(newDesc)
8103
+ }
8104
+ ), /* @__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 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: () => setIsDescriptionModalOpen(true), className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors" }, /* @__PURE__ */ React15.createElement(FiEdit26, { size: 14 }))), !description && /* @__PURE__ */ React15.createElement("div", { onClick: () => setIsDescriptionModalOpen(true), className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text" }, "Adicionar descri\xE7\xE3o..."))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no Cen\xE1rio (Size)"), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => /* @__PURE__ */ React15.createElement("button", { key: s, type: "button", onClick: () => setSize(s), className: "flex items-center gap-2 group cursor-pointer focus:outline-none" }, /* @__PURE__ */ React15.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${size === s ? "bg-indigo-500 border-indigo-500" : "border-slate-600 bg-transparent group-hover:border-slate-500"}` }, size === s && /* @__PURE__ */ React15.createElement(FiCheck9, { size: 12, className: "text-white" })), /* @__PURE__ */ React15.createElement("span", { className: `text-sm capitalize transition-colors ${size === s ? "text-white font-medium" : "text-slate-400 group-hover:text-slate-300"}` }, s))))), /* @__PURE__ */ React15.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React15.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ React15.createElement(FiPlus5, { size: 14 }), " Adicionar")), /* @__PURE__ */ React15.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ React15.createElement(
8105
+ CustomPropertyDisplay,
8106
+ {
8107
+ key: prop.id,
8108
+ prop,
8109
+ onUpdate: (updatedProp) => handleUpdateProp(index, updatedProp),
8110
+ onRemove: () => handleRemoveProp(index),
8111
+ onOpenImageViewer,
8112
+ unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type),
8113
+ onUploadFile
8114
+ }
8115
+ )), /* @__PURE__ */ React15.createElement("div", { ref: propsEndRef })))), /* @__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", { type: "button", onClick: onCancel, className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm" }, "Cancelar"), /* @__PURE__ */ React15.createElement("button", { type: "submit", className: "px-4 py-2 rounded-lg bg-gradient-to-tr from-indigo-600 to-indigo-400 hover:from-indigo-500 hover:to-indigo-300 transition-colors font-semibold text-sm shadow-[0_8px_24px_rgba(99,102,241,0.35)]" }, "Salvar Quest")))
8116
+ ), isDescriptionModalOpen && /* @__PURE__ */ React15.createElement(
8117
+ DescriptionEditModal,
8118
+ {
8119
+ isOpen: isDescriptionModalOpen,
8120
+ title: "Editar Descri\xE7\xE3o da Quest",
8121
+ initialValue: description,
8122
+ onSave: (newDescription) => setDescription(newDescription),
8123
+ onClose: () => setIsDescriptionModalOpen(false),
8124
+ availableNodes,
8125
+ availableAncestries,
8126
+ availableImages
8127
+ }
8128
+ ));
8129
+ }
8130
+
7838
8131
  // src/components/NodeDetailsPanel.jsx
7839
- import React15, { useState as useState16, useEffect as useEffect15, useRef as useRef12 } from "react";
7840
- 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";
8132
+ import React16, { useState as useState17, useEffect as useEffect15, useRef as useRef13 } from "react";
8133
+ import { FiPlus as FiPlus6, FiMaximize2 as FiMaximize23, FiX as FiX5, FiCheck as FiCheck10, FiImage as FiImage3, FiEdit2 as FiEdit27, FiLoader as FiLoader2, FiBookOpen as FiBookOpen3, FiSun as FiSun2, FiLink as FiLink5, FiDatabase } from "react-icons/fi";
7841
8134
  function NodeDetailsPanel({
7842
8135
  node,
7843
8136
  onClose,
@@ -7858,27 +8151,27 @@ function NodeDetailsPanel({
7858
8151
  userRole,
7859
8152
  currentDatasetName
7860
8153
  }) {
7861
- const [name, setName] = useState16((node == null ? void 0 : node.name) ?? "");
7862
- const [types, setTypes] = useState16([]);
7863
- const [typeInput, setTypeInput] = useState16("");
7864
- const [color, setColor] = useState16((node == null ? void 0 : node.color) ?? "#8b5cf6");
7865
- const [size, setSize] = useState16((node == null ? void 0 : node.size) ?? "medium");
7866
- const [description, setDescription] = useState16((node == null ? void 0 : node.description) ?? "");
7867
- const [intensity, setIntensity] = useState16((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
7868
- const [customProps, setCustomProps] = useState16(() => extractCustomPropsFromNode(node || {}));
7869
- const [showTypeSuggestions, setShowTypeSuggestions] = useState16(false);
7870
- const [filteredTypes, setFilteredTypes] = useState16([]);
7871
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState16(false);
7872
- const [isReadMode, setIsReadMode] = useState16(false);
7873
- const [existingSections, setExistingSections] = useState16((node == null ? void 0 : node.description_sections) || []);
7874
- const [isSaving, setIsSaving] = useState16(false);
7875
- const [isLinkCopied, setIsLinkCopied] = useState16(false);
7876
- const [useImageAsTexture, setUseImageAsTexture] = useState16(() => {
8154
+ const [name, setName] = useState17((node == null ? void 0 : node.name) ?? "");
8155
+ const [types, setTypes] = useState17([]);
8156
+ const [typeInput, setTypeInput] = useState17("");
8157
+ const [color, setColor] = useState17((node == null ? void 0 : node.color) ?? "#8b5cf6");
8158
+ const [size, setSize] = useState17((node == null ? void 0 : node.size) ?? "medium");
8159
+ const [description, setDescription] = useState17((node == null ? void 0 : node.description) ?? "");
8160
+ const [intensity, setIntensity] = useState17((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
8161
+ const [customProps, setCustomProps] = useState17(() => extractCustomPropsFromNode(node || {}));
8162
+ const [showTypeSuggestions, setShowTypeSuggestions] = useState17(false);
8163
+ const [filteredTypes, setFilteredTypes] = useState17([]);
8164
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState17(false);
8165
+ const [isReadMode, setIsReadMode] = useState17(false);
8166
+ const [existingSections, setExistingSections] = useState17((node == null ? void 0 : node.description_sections) || []);
8167
+ const [isSaving, setIsSaving] = useState17(false);
8168
+ const [isLinkCopied, setIsLinkCopied] = useState17(false);
8169
+ const [useImageAsTexture, setUseImageAsTexture] = useState17(() => {
7877
8170
  if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
7878
8171
  if ((node == null ? void 0 : node.useImageAsTexture) === "false") return false;
7879
8172
  return !!(node == null ? void 0 : node.useImageAsTexture);
7880
8173
  });
7881
- const [selectedImageUrl, setSelectedImageUrl] = useState16((node == null ? void 0 : node.textureImageUrl) ?? null);
8174
+ const [selectedImageUrl, setSelectedImageUrl] = useState17((node == null ? void 0 : node.textureImageUrl) ?? null);
7882
8175
  const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
7883
8176
  const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
7884
8177
  initialWidth: isReadMode ? 700 : 440,
@@ -7888,8 +8181,8 @@ function NodeDetailsPanel({
7888
8181
  useEffect15(() => {
7889
8182
  setWidth(isReadMode ? 700 : 440);
7890
8183
  }, [isReadMode, setWidth]);
7891
- const prevNodeIdRef = useRef12(null);
7892
- const propsEndRef = useRef12(null);
8184
+ const prevNodeIdRef = useRef13(null);
8185
+ const propsEndRef = useRef13(null);
7893
8186
  const canEdit = userRole !== "viewer";
7894
8187
  const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
7895
8188
  const handleImageClickFromText = (url, name2) => {
@@ -8097,7 +8390,7 @@ function NodeDetailsPanel({
8097
8390
  onClose();
8098
8391
  };
8099
8392
  const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
8100
- return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(
8393
+ return /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(
8101
8394
  "div",
8102
8395
  {
8103
8396
  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"}`,
@@ -8110,7 +8403,7 @@ function NodeDetailsPanel({
8110
8403
  onContextMenu: swallow,
8111
8404
  onDoubleClick: swallow
8112
8405
  },
8113
- /* @__PURE__ */ React15.createElement(
8406
+ /* @__PURE__ */ React16.createElement(
8114
8407
  "div",
8115
8408
  {
8116
8409
  onPointerDown: (e) => {
@@ -8121,7 +8414,7 @@ function NodeDetailsPanel({
8121
8414
  title: "Arraste para redimensionar"
8122
8415
  }
8123
8416
  ),
8124
- isReadMode ? /* @__PURE__ */ React15.createElement(
8417
+ isReadMode ? /* @__PURE__ */ React16.createElement(
8125
8418
  DescriptionReadModePanel,
8126
8419
  {
8127
8420
  title: name || (node == null ? void 0 : node.name),
@@ -8142,23 +8435,23 @@ function NodeDetailsPanel({
8142
8435
  onImageClick: handleImageClickFromText,
8143
8436
  onSaveDescription: handleSaveDescriptionInline
8144
8437
  }
8145
- ) : /* @__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(
8438
+ ) : /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ React16.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React16.createElement("div", null, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React16.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__ */ React16.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node"), /* @__PURE__ */ React16.createElement(
8146
8439
  "button",
8147
8440
  {
8148
8441
  onClick: handleCopyLink,
8149
8442
  className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-indigo-400"}`,
8150
8443
  title: isLinkCopied ? "Link Copiado!" : "Copiar link para este Node"
8151
8444
  },
8152
- isLinkCopied ? /* @__PURE__ */ React15.createElement(FiCheck9, { size: 12 }) : /* @__PURE__ */ React15.createElement(FiLink5, { size: 12 })
8153
- )), /* @__PURE__ */ React15.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ React15.createElement("button", { onClick: handleCancel, 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: "Cancelar" }, "\xD7")), /* @__PURE__ */ React15.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tipos"), /* @__PURE__ */ React15.createElement("div", { className: `relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 ${canEdit ? "focus-within:ring-2 focus-within:ring-indigo-400/60" : ""} transition-all` }, types.map((t, index) => /* @__PURE__ */ React15.createElement("span", { key: index, className: "flex items-center gap-1 bg-indigo-500/30 text-indigo-100 px-1.5 py-0.5 rounded-md text-xs font-medium border border-indigo-500/20" }, t, canEdit && /* @__PURE__ */ React15.createElement(
8445
+ isLinkCopied ? /* @__PURE__ */ React16.createElement(FiCheck10, { size: 12 }) : /* @__PURE__ */ React16.createElement(FiLink5, { size: 12 })
8446
+ )), /* @__PURE__ */ React16.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ React16.createElement("button", { onClick: handleCancel, 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: "Cancelar" }, "\xD7")), /* @__PURE__ */ React16.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React16.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300" }, "Tipos"), /* @__PURE__ */ React16.createElement("div", { className: `relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 ${canEdit ? "focus-within:ring-2 focus-within:ring-indigo-400/60" : ""} transition-all` }, types.map((t, index) => /* @__PURE__ */ React16.createElement("span", { key: index, className: "flex items-center gap-1 bg-indigo-500/30 text-indigo-100 px-1.5 py-0.5 rounded-md text-xs font-medium border border-indigo-500/20" }, t, canEdit && /* @__PURE__ */ React16.createElement(
8154
8447
  "button",
8155
8448
  {
8156
8449
  type: "button",
8157
8450
  onClick: () => handleRemoveType(index),
8158
8451
  className: "hover:text-white transition-colors"
8159
8452
  },
8160
- /* @__PURE__ */ React15.createElement(FiX4, { size: 12 })
8161
- ))), canEdit && /* @__PURE__ */ React15.createElement(
8453
+ /* @__PURE__ */ React16.createElement(FiX5, { size: 12 })
8454
+ ))), canEdit && /* @__PURE__ */ React16.createElement(
8162
8455
  "input",
8163
8456
  {
8164
8457
  type: "text",
@@ -8179,7 +8472,7 @@ function NodeDetailsPanel({
8179
8472
  placeholder: types.length === 0 ? "Ex.: Cliente" : "",
8180
8473
  autoComplete: "off"
8181
8474
  }
8182
- ), canEdit && showTypeSuggestions && filteredTypes.length > 0 && /* @__PURE__ */ React15.createElement("ul", { className: "custom-scrollbar absolute top-full left-0 z-10 w-full mt-1 max-h-40 overflow-y-auto rounded-lg bg-slate-800 border border-white/10 shadow-lg" }, filteredTypes.map((suggestedType, index) => /* @__PURE__ */ React15.createElement(
8475
+ ), canEdit && showTypeSuggestions && filteredTypes.length > 0 && /* @__PURE__ */ React16.createElement("ul", { className: "custom-scrollbar absolute top-full left-0 z-10 w-full mt-1 max-h-40 overflow-y-auto rounded-lg bg-slate-800 border border-white/10 shadow-lg" }, filteredTypes.map((suggestedType, index) => /* @__PURE__ */ React16.createElement(
8183
8476
  "li",
8184
8477
  {
8185
8478
  key: index,
@@ -8190,7 +8483,7 @@ function NodeDetailsPanel({
8190
8483
  }
8191
8484
  },
8192
8485
  suggestedType
8193
- ))))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Nome"), /* @__PURE__ */ React15.createElement(
8486
+ ))))), /* @__PURE__ */ React16.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300" }, "Nome"), /* @__PURE__ */ React16.createElement(
8194
8487
  "input",
8195
8488
  {
8196
8489
  type: "text",
@@ -8199,7 +8492,7 @@ function NodeDetailsPanel({
8199
8492
  readOnly: !canEdit,
8200
8493
  className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none ${canEdit ? "focus:ring-2 focus:ring-indigo-400/60" : "cursor-default text-slate-400"}`
8201
8494
  }
8202
- )), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React15.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__ */ React15.createElement(
8495
+ )), /* @__PURE__ */ React16.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React16.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__ */ React16.createElement(
8203
8496
  DescriptionDisplay,
8204
8497
  {
8205
8498
  description,
@@ -8211,7 +8504,7 @@ function NodeDetailsPanel({
8211
8504
  onImageClick: handleImageClickFromText,
8212
8505
  onSaveDescription: handleSaveDescriptionInline
8213
8506
  }
8214
- ), /* @__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(
8507
+ ), /* @__PURE__ */ React16.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__ */ React16.createElement(
8215
8508
  "button",
8216
8509
  {
8217
8510
  type: "button",
@@ -8219,8 +8512,8 @@ function NodeDetailsPanel({
8219
8512
  className: `p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors ${canEdit ? "border-r border-white/5" : ""}`,
8220
8513
  title: "Modo de Leitura"
8221
8514
  },
8222
- /* @__PURE__ */ React15.createElement(FiBookOpen3, { size: 14 })
8223
- ), canEdit && /* @__PURE__ */ React15.createElement(
8515
+ /* @__PURE__ */ React16.createElement(FiBookOpen3, { size: 14 })
8516
+ ), canEdit && /* @__PURE__ */ React16.createElement(
8224
8517
  "button",
8225
8518
  {
8226
8519
  type: "button",
@@ -8228,17 +8521,17 @@ function NodeDetailsPanel({
8228
8521
  className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
8229
8522
  title: "Editar descri\xE7\xE3o (Modo de Escrita)"
8230
8523
  },
8231
- /* @__PURE__ */ React15.createElement(FiEdit26, { size: 14 })
8232
- )), canEdit && !description && /* @__PURE__ */ React15.createElement(
8524
+ /* @__PURE__ */ React16.createElement(FiEdit27, { size: 14 })
8525
+ )), canEdit && !description && /* @__PURE__ */ React16.createElement(
8233
8526
  "div",
8234
8527
  {
8235
8528
  onClick: () => setIsDescriptionModalOpen(true),
8236
8529
  className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
8237
8530
  },
8238
8531
  "Adicionar descri\xE7\xE3o..."
8239
- ))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Size"), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => {
8532
+ ))), /* @__PURE__ */ React16.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300" }, "Size"), /* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => {
8240
8533
  const isSelected = size === s;
8241
- return /* @__PURE__ */ React15.createElement(
8534
+ return /* @__PURE__ */ React16.createElement(
8242
8535
  "button",
8243
8536
  {
8244
8537
  key: s,
@@ -8246,10 +8539,10 @@ function NodeDetailsPanel({
8246
8539
  onClick: () => canEdit && handleSizeChange(s),
8247
8540
  className: `flex items-center gap-2 group focus:outline-none ${canEdit ? "cursor-pointer" : "cursor-default opacity-80"}`
8248
8541
  },
8249
- /* @__PURE__ */ React15.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${isSelected ? "bg-indigo-500 border-indigo-500 shadow-[0_0_10px_rgba(99,102,241,0.4)]" : "border-slate-600 bg-transparent " + (canEdit ? "group-hover:border-slate-500" : "")}` }, isSelected && /* @__PURE__ */ React15.createElement(FiCheck9, { size: 12, className: "text-white" })),
8250
- /* @__PURE__ */ React15.createElement("span", { className: `text-sm capitalize transition-colors ${isSelected ? "text-white font-medium" : "text-slate-400 " + (canEdit ? "group-hover:text-slate-300" : "")}` }, s)
8542
+ /* @__PURE__ */ React16.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${isSelected ? "bg-indigo-500 border-indigo-500 shadow-[0_0_10px_rgba(99,102,241,0.4)]" : "border-slate-600 bg-transparent " + (canEdit ? "group-hover:border-slate-500" : "")}` }, isSelected && /* @__PURE__ */ React16.createElement(FiCheck10, { size: 12, className: "text-white" })),
8543
+ /* @__PURE__ */ React16.createElement("span", { className: `text-sm capitalize transition-colors ${isSelected ? "text-white font-medium" : "text-slate-400 " + (canEdit ? "group-hover:text-slate-300" : "")}` }, s)
8251
8544
  );
8252
- }))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Cor e Brilho"), canEdit && hasImages && /* @__PURE__ */ React15.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ React15.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${useImageAsTexture ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, useImageAsTexture && /* @__PURE__ */ React15.createElement(FiCheck9, { size: 12, className: "text-white" })), /* @__PURE__ */ React15.createElement(
8545
+ }))), /* @__PURE__ */ React16.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300" }, "Cor e Brilho"), canEdit && hasImages && /* @__PURE__ */ React16.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ React16.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${useImageAsTexture ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, useImageAsTexture && /* @__PURE__ */ React16.createElement(FiCheck10, { size: 12, className: "text-white" })), /* @__PURE__ */ React16.createElement(
8253
8546
  "input",
8254
8547
  {
8255
8548
  type: "checkbox",
@@ -8257,14 +8550,14 @@ function NodeDetailsPanel({
8257
8550
  onChange: handleToggleImageMode,
8258
8551
  className: "hidden"
8259
8552
  }
8260
- ), /* @__PURE__ */ React15.createElement("span", { className: `text-xs ${useImageAsTexture ? "text-indigo-300" : "text-slate-400 group-hover:text-slate-300"}` }, "Usar imagem para representar o node"))), /* @__PURE__ */ React15.createElement(
8553
+ ), /* @__PURE__ */ React16.createElement("span", { className: `text-xs ${useImageAsTexture ? "text-indigo-300" : "text-slate-400 group-hover:text-slate-300"}` }, "Usar imagem para representar o node"))), /* @__PURE__ */ React16.createElement(
8261
8554
  ColorPicker,
8262
8555
  {
8263
8556
  color,
8264
8557
  onChange: handleColorChange,
8265
8558
  disabled: !canEdit || useImageAsTexture
8266
8559
  }
8267
- ), /* @__PURE__ */ React15.createElement("div", { className: "mt-3 flex items-center gap-3" }, /* @__PURE__ */ React15.createElement(FiSun2, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ React15.createElement(
8560
+ ), /* @__PURE__ */ React16.createElement("div", { className: "mt-3 flex items-center gap-3" }, /* @__PURE__ */ React16.createElement(FiSun2, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ React16.createElement(
8268
8561
  "input",
8269
8562
  {
8270
8563
  type: "range",
@@ -8277,7 +8570,7 @@ function NodeDetailsPanel({
8277
8570
  className: `w-full h-1.5 bg-slate-700 rounded-lg appearance-none ${canEdit ? "cursor-pointer accent-indigo-500 hover:accent-indigo-400" : "cursor-default accent-slate-500"}`,
8278
8571
  title: `Intensidade do brilho: ${intensity}`
8279
8572
  }
8280
- ), /* @__PURE__ */ React15.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ React15.createElement("span", { className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}` }, useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Ajuste a cor e a intensidade do brilho.")), /* @__PURE__ */ React15.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React15.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ React15.createElement(FiPlus5, { size: 14 }), " Adicionar")), /* @__PURE__ */ React15.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ React15.createElement(
8573
+ ), /* @__PURE__ */ React16.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ React16.createElement("span", { className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}` }, useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Ajuste a cor e a intensidade do brilho.")), /* @__PURE__ */ React16.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React16.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ React16.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ React16.createElement(FiPlus6, { size: 14 }), " Adicionar")), /* @__PURE__ */ React16.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ React16.createElement(
8281
8574
  CustomPropertyDisplay,
8282
8575
  {
8283
8576
  key: prop.id,
@@ -8292,7 +8585,7 @@ function NodeDetailsPanel({
8292
8585
  onUploadFile: canEdit ? onUploadFile : void 0,
8293
8586
  readOnly: !canEdit
8294
8587
  }
8295
- )), /* @__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(
8588
+ )), /* @__PURE__ */ React16.createElement("div", { ref: propsEndRef }))), currentDatasetName && /* @__PURE__ */ React16.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__ */ React16.createElement("span", { className: "truncate text-right" }, /* @__PURE__ */ React16.createElement("span", { className: "text-slate-200 font-medium" }, currentDatasetName)))), /* @__PURE__ */ React16.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__ */ React16.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__ */ React16.createElement(
8296
8589
  "button",
8297
8590
  {
8298
8591
  onClick: () => handleSave(false),
@@ -8301,10 +8594,10 @@ function NodeDetailsPanel({
8301
8594
  ${isSaving ? "bg-slate-700 text-slate-300 cursor-wait" : "bg-gradient-to-tr from-indigo-600 to-indigo-400 hover:from-indigo-500 hover:to-indigo-300 text-white"}
8302
8595
  `
8303
8596
  },
8304
- isSaving && /* @__PURE__ */ React15.createElement(FiLoader2, { className: "animate-spin" }),
8597
+ isSaving && /* @__PURE__ */ React16.createElement(FiLoader2, { className: "animate-spin" }),
8305
8598
  isSaving ? "Salvando..." : "Salvar"
8306
8599
  )))
8307
- ), isDescriptionModalOpen && canEdit && /* @__PURE__ */ React15.createElement(
8600
+ ), isDescriptionModalOpen && canEdit && /* @__PURE__ */ React16.createElement(
8308
8601
  DescriptionEditModal,
8309
8602
  {
8310
8603
  isOpen: isDescriptionModalOpen,
@@ -8324,7 +8617,7 @@ function NodeDetailsPanel({
8324
8617
  }
8325
8618
 
8326
8619
  // src/components/MultiNodeContextMenu.jsx
8327
- import React16, { useLayoutEffect as useLayoutEffect3, useRef as useRef13, useState as useState17, useEffect as useEffect16 } from "react";
8620
+ import React17, { useLayoutEffect as useLayoutEffect3, useRef as useRef14, useState as useState18, useEffect as useEffect16 } from "react";
8328
8621
  function MultiNodeContextMenu({
8329
8622
  data,
8330
8623
  userRole,
@@ -8333,9 +8626,9 @@ function MultiNodeContextMenu({
8333
8626
  onDismissOtherNodes,
8334
8627
  onDeleteNodes
8335
8628
  }) {
8336
- const menuRef = useRef13(null);
8337
- const [menuPos, setMenuPos] = useState17({ left: 0, top: 0 });
8338
- const [isConfirmingDelete, setIsConfirmingDelete] = useState17(false);
8629
+ const menuRef = useRef14(null);
8630
+ const [menuPos, setMenuPos] = useState18({ left: 0, top: 0 });
8631
+ const [isConfirmingDelete, setIsConfirmingDelete] = useState18(false);
8339
8632
  const ability = defineAbilityFor(userRole);
8340
8633
  const canDelete = ability.can("delete", "Node");
8341
8634
  useLayoutEffect3(() => {
@@ -8366,7 +8659,7 @@ function MultiNodeContextMenu({
8366
8659
  const baseButtonClass = "w-full flex items-center gap-2.5 px-2 py-1.5 text-left text-sm rounded-md hover:bg-indigo-500/20 text-slate-200 hover:text-white transition-colors duration-150 truncate";
8367
8660
  const deleteButtonClass = "w-full flex items-center gap-2.5 px-2 py-1.5 text-left text-sm rounded-md hover:bg-red-500/25 text-red-400 hover:text-red-300 transition-colors duration-150 truncate";
8368
8661
  const nodeCount = data.nodeIds.size;
8369
- return /* @__PURE__ */ React16.createElement(
8662
+ return /* @__PURE__ */ React17.createElement(
8370
8663
  "div",
8371
8664
  {
8372
8665
  ref: menuRef,
@@ -8380,28 +8673,28 @@ function MultiNodeContextMenu({
8380
8673
  onContextMenu: swallow,
8381
8674
  onDoubleClick: swallow
8382
8675
  },
8383
- /* @__PURE__ */ React16.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
8384
- /* @__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(
8676
+ /* @__PURE__ */ React17.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
8677
+ /* @__PURE__ */ React17.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ React17.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ React17.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ React17.createElement("div", { className: "w-10 h-10 rounded-full bg-red-500/20 flex items-center justify-center text-red-400 mb-1" }, /* @__PURE__ */ React17.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__ */ React17.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React17.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__ */ React17.createElement("p", { className: "text-sm text-slate-200" }, "Excluir ", /* @__PURE__ */ React17.createElement("strong", null, nodeCount, " Nodes"), "?"), /* @__PURE__ */ React17.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__ */ React17.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ React17.createElement(
8385
8678
  "button",
8386
8679
  {
8387
8680
  onClick: () => setIsConfirmingDelete(false),
8388
8681
  className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
8389
8682
  },
8390
8683
  "Cancelar"
8391
- ), /* @__PURE__ */ React16.createElement(
8684
+ ), /* @__PURE__ */ React17.createElement(
8392
8685
  "button",
8393
8686
  {
8394
8687
  onClick: () => onDeleteNodes(data.nodeIds),
8395
8688
  className: "flex-1 px-2 py-2 text-xs font-medium bg-red-500 hover:bg-red-600 rounded-md text-white transition-colors"
8396
8689
  },
8397
8690
  "Excluir"
8398
- ))) : /* @__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, ")"))))))
8691
+ ))) : /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React17.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__ */ React17.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es em Grupo (", nodeCount, " Nodes)")), /* @__PURE__ */ React17.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React17.createElement("button", { onClick: () => onDismissNodes(data.nodeIds), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ React17.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__ */ React17.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ React17.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__ */ React17.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__ */ React17.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ React17.createElement("span", null, "Dismiss (", nodeCount, ")")), /* @__PURE__ */ React17.createElement("button", { onClick: () => onDismissOtherNodes(data.nodeIds), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ React17.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__ */ React17.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ React17.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ React17.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React17.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ React17.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ React17.createElement("span", null, "Dismiss other nodes")), canDelete && /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React17.createElement("button", { onClick: () => setIsConfirmingDelete(true), className: deleteButtonClass, title: "Excluir Nodes" }, /* @__PURE__ */ React17.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__ */ React17.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React17.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__ */ React17.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ React17.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ React17.createElement("span", null, "Excluir Nodes (", nodeCount, ")"))))))
8399
8692
  );
8400
8693
  }
8401
8694
 
8402
8695
  // src/components/RelationshipDetailsPanel.jsx
8403
- import React17, { useState as useState18, useEffect as useEffect17, useRef as useRef14, useMemo as useMemo9 } from "react";
8404
- import { FiPlus as FiPlus6, FiEdit2 as FiEdit27, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4 } from "react-icons/fi";
8696
+ import React18, { useState as useState19, useEffect as useEffect17, useRef as useRef15, useMemo as useMemo9 } from "react";
8697
+ import { FiPlus as FiPlus7, FiEdit2 as FiEdit28, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4 } from "react-icons/fi";
8405
8698
  function RelationshipDetailsPanel({
8406
8699
  link,
8407
8700
  onClose,
@@ -8415,14 +8708,14 @@ function RelationshipDetailsPanel({
8415
8708
  onUploadFile,
8416
8709
  userRole
8417
8710
  }) {
8418
- const [name, setName] = useState18((link == null ? void 0 : link.name) ?? "");
8419
- const [description, setDescription] = useState18((link == null ? void 0 : link.description) ?? "");
8420
- const [customProps, setCustomProps] = useState18(() => extractCustomPropsFromNode(link || {}));
8421
- const [existingSections, setExistingSections] = useState18((link == null ? void 0 : link.description_sections) || []);
8422
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState18(false);
8423
- const [isSaving, setIsSaving] = useState18(false);
8424
- const [isReadMode, setIsReadMode] = useState18(false);
8425
- const propsEndRef = useRef14(null);
8711
+ const [name, setName] = useState19((link == null ? void 0 : link.name) ?? "");
8712
+ const [description, setDescription] = useState19((link == null ? void 0 : link.description) ?? "");
8713
+ const [customProps, setCustomProps] = useState19(() => extractCustomPropsFromNode(link || {}));
8714
+ const [existingSections, setExistingSections] = useState19((link == null ? void 0 : link.description_sections) || []);
8715
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState19(false);
8716
+ const [isSaving, setIsSaving] = useState19(false);
8717
+ const [isReadMode, setIsReadMode] = useState19(false);
8718
+ const propsEndRef = useRef15(null);
8426
8719
  const canEdit = useMemo9(() => {
8427
8720
  const ability = defineAbilityFor(userRole);
8428
8721
  return ability.can("update", "Connection");
@@ -8502,7 +8795,7 @@ function RelationshipDetailsPanel({
8502
8795
  onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
8503
8796
  }
8504
8797
  };
8505
- return /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement(
8798
+ return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(
8506
8799
  "div",
8507
8800
  {
8508
8801
  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
@@ -8517,7 +8810,7 @@ function RelationshipDetailsPanel({
8517
8810
  onContextMenu: swallow,
8518
8811
  onDoubleClick: swallow
8519
8812
  },
8520
- isReadMode ? /* @__PURE__ */ React17.createElement(
8813
+ isReadMode ? /* @__PURE__ */ React18.createElement(
8521
8814
  DescriptionReadModePanel,
8522
8815
  {
8523
8816
  title: name || "Rela\xE7\xE3o",
@@ -8538,7 +8831,7 @@ function RelationshipDetailsPanel({
8538
8831
  onImageClick: handleImageClickFromText,
8539
8832
  onSaveDescription: handleSaveDescriptionInline
8540
8833
  }
8541
- ) : /* @__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(
8834
+ ) : /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }), /* @__PURE__ */ React18.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React18.createElement("div", null, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React18.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__ */ React18.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Rela\xE7\xE3o")), /* @__PURE__ */ React18.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || "Rela\xE7\xE3o")), /* @__PURE__ */ React18.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__ */ React18.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React18.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React18.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Rela\xE7\xE3o (Opcional)"), /* @__PURE__ */ React18.createElement(
8542
8835
  "input",
8543
8836
  {
8544
8837
  type: "text",
@@ -8550,7 +8843,7 @@ function RelationshipDetailsPanel({
8550
8843
  ${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
8551
8844
  `
8552
8845
  }
8553
- )), /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React17.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__ */ React17.createElement(
8846
+ )), /* @__PURE__ */ React18.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React18.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React18.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__ */ React18.createElement(
8554
8847
  DescriptionDisplay,
8555
8848
  {
8556
8849
  description,
@@ -8562,7 +8855,7 @@ function RelationshipDetailsPanel({
8562
8855
  onImageClick: handleImageClickFromText,
8563
8856
  onSaveDescription: handleSaveDescriptionInline
8564
8857
  }
8565
- ), /* @__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(
8858
+ ), /* @__PURE__ */ React18.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__ */ React18.createElement(
8566
8859
  "button",
8567
8860
  {
8568
8861
  type: "button",
@@ -8570,8 +8863,8 @@ function RelationshipDetailsPanel({
8570
8863
  className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors border-r border-white/5",
8571
8864
  title: "Modo de Leitura"
8572
8865
  },
8573
- /* @__PURE__ */ React17.createElement(FiBookOpen4, { size: 14 })
8574
- ), canEdit && /* @__PURE__ */ React17.createElement(
8866
+ /* @__PURE__ */ React18.createElement(FiBookOpen4, { size: 14 })
8867
+ ), canEdit && /* @__PURE__ */ React18.createElement(
8575
8868
  "button",
8576
8869
  {
8577
8870
  type: "button",
@@ -8579,15 +8872,15 @@ function RelationshipDetailsPanel({
8579
8872
  className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
8580
8873
  title: "Editar descri\xE7\xE3o"
8581
8874
  },
8582
- /* @__PURE__ */ React17.createElement(FiEdit27, { size: 14 })
8583
- )), !description && canEdit && /* @__PURE__ */ React17.createElement(
8875
+ /* @__PURE__ */ React18.createElement(FiEdit28, { size: 14 })
8876
+ )), !description && canEdit && /* @__PURE__ */ React18.createElement(
8584
8877
  "div",
8585
8878
  {
8586
8879
  onClick: () => setIsDescriptionModalOpen(true),
8587
8880
  className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
8588
8881
  },
8589
8882
  "Adicionar descri\xE7\xE3o..."
8590
- ))), /* @__PURE__ */ React17.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React17.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ React17.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ React17.createElement(FiPlus6, { size: 14 }), " Adicionar")), /* @__PURE__ */ React17.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ React17.createElement(
8883
+ ))), /* @__PURE__ */ React18.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React18.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ React18.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ React18.createElement(FiPlus7, { size: 14 }), " Adicionar")), /* @__PURE__ */ React18.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ React18.createElement(
8591
8884
  CustomPropertyDisplay,
8592
8885
  {
8593
8886
  key: prop.id,
@@ -8599,7 +8892,7 @@ function RelationshipDetailsPanel({
8599
8892
  onUploadFile,
8600
8893
  disabled: !canEdit
8601
8894
  }
8602
- )), /* @__PURE__ */ React17.createElement("div", { ref: propsEndRef })))), /* @__PURE__ */ React17.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__ */ React17.createElement("button", { onClick: onClose, 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__ */ React17.createElement(
8895
+ )), /* @__PURE__ */ React18.createElement("div", { ref: propsEndRef })))), /* @__PURE__ */ React18.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__ */ React18.createElement("button", { onClick: onClose, 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__ */ React18.createElement(
8603
8896
  "button",
8604
8897
  {
8605
8898
  onClick: () => handleSave(false),
@@ -8608,10 +8901,10 @@ function RelationshipDetailsPanel({
8608
8901
  ${isSaving ? "bg-slate-700 text-slate-300 cursor-wait" : "bg-gradient-to-tr from-teal-600 to-teal-400 hover:from-teal-500 hover:to-teal-300 text-white"}
8609
8902
  `
8610
8903
  },
8611
- isSaving && /* @__PURE__ */ React17.createElement(FiLoader3, { className: "animate-spin" }),
8904
+ isSaving && /* @__PURE__ */ React18.createElement(FiLoader3, { className: "animate-spin" }),
8612
8905
  isSaving ? "Salvando..." : "Salvar"
8613
8906
  )))
8614
- ), isDescriptionModalOpen && /* @__PURE__ */ React17.createElement(
8907
+ ), isDescriptionModalOpen && /* @__PURE__ */ React18.createElement(
8615
8908
  DescriptionEditModal,
8616
8909
  {
8617
8910
  isOpen: isDescriptionModalOpen,
@@ -8632,7 +8925,7 @@ function RelationshipDetailsPanel({
8632
8925
  }
8633
8926
 
8634
8927
  // src/components/RelationshipContextMenu.jsx
8635
- import React18, { useLayoutEffect as useLayoutEffect4, useRef as useRef15, useState as useState19, useEffect as useEffect18, useMemo as useMemo10 } from "react";
8928
+ import React19, { useLayoutEffect as useLayoutEffect4, useRef as useRef16, useState as useState20, useEffect as useEffect18, useMemo as useMemo10 } from "react";
8636
8929
  function RelationshipContextMenu({
8637
8930
  data,
8638
8931
  userRole,
@@ -8642,9 +8935,9 @@ function RelationshipContextMenu({
8642
8935
  onDelete,
8643
8936
  onClose
8644
8937
  }) {
8645
- const menuRef = useRef15(null);
8646
- const [menuPos, setMenuPos] = useState19({ left: 0, top: 0 });
8647
- const [isConfirmingDelete, setIsConfirmingDelete] = useState19(false);
8938
+ const menuRef = useRef16(null);
8939
+ const [menuPos, setMenuPos] = useState20({ left: 0, top: 0 });
8940
+ const [isConfirmingDelete, setIsConfirmingDelete] = useState20(false);
8648
8941
  const ability = useMemo10(() => defineAbilityFor(userRole), [userRole]);
8649
8942
  const sourceName = useMemo10(
8650
8943
  () => {
@@ -8689,7 +8982,7 @@ function RelationshipContextMenu({
8689
8982
  const dangerButtonClass = "w-full flex items-center gap-2.5 px-2 py-1.5 text-left text-sm rounded-md hover:bg-rose-500/20 text-rose-300 hover:text-rose-100 transition-colors duration-150 truncate";
8690
8983
  const canUpdate = ability.can("update", "Connection");
8691
8984
  const canDelete = ability.can("delete", "Connection");
8692
- return /* @__PURE__ */ React18.createElement(
8985
+ return /* @__PURE__ */ React19.createElement(
8693
8986
  "div",
8694
8987
  {
8695
8988
  ref: menuRef,
@@ -8703,29 +8996,29 @@ function RelationshipContextMenu({
8703
8996
  onContextMenu: swallow,
8704
8997
  onDoubleClick: swallow
8705
8998
  },
8706
- /* @__PURE__ */ React18.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }),
8707
- /* @__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(
8999
+ /* @__PURE__ */ React19.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }),
9000
+ /* @__PURE__ */ React19.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ React19.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ React19.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ React19.createElement("div", { className: "w-10 h-10 rounded-full bg-rose-500/20 flex items-center justify-center text-rose-400 mb-1" }, /* @__PURE__ */ React19.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__ */ React19.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React19.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }), /* @__PURE__ */ React19.createElement("path", { d: "M10 11v6" }), /* @__PURE__ */ React19.createElement("path", { d: "M14 11v6" }), /* @__PURE__ */ React19.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" }))), /* @__PURE__ */ React19.createElement("p", { className: "text-sm text-slate-200" }, "Excluir rela\xE7\xE3o?"), /* @__PURE__ */ React19.createElement("p", { className: "text-[11px] text-slate-400 leading-tight break-words" }, "Desconectar ", /* @__PURE__ */ React19.createElement("strong", null, sourceName), " de ", /* @__PURE__ */ React19.createElement("strong", null, targetName), ".")), /* @__PURE__ */ React19.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ React19.createElement(
8708
9001
  "button",
8709
9002
  {
8710
9003
  onClick: () => setIsConfirmingDelete(false),
8711
9004
  className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
8712
9005
  },
8713
9006
  "Cancelar"
8714
- ), /* @__PURE__ */ React18.createElement(
9007
+ ), /* @__PURE__ */ React19.createElement(
8715
9008
  "button",
8716
9009
  {
8717
9010
  onClick: () => onDelete == null ? void 0 : onDelete(data.linkObject),
8718
9011
  className: "flex-1 px-2 py-2 text-xs font-medium bg-rose-600 hover:bg-rose-500 rounded-md text-white transition-colors"
8719
9012
  },
8720
9013
  "Excluir"
8721
- ))) : /* @__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(
9014
+ ))) : /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React19.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__ */ React19.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Rela\xE7\xE3o")), /* @__PURE__ */ React19.createElement("div", { className: "flex flex-col gap-1" }, canUpdate && /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(
8722
9015
  "button",
8723
9016
  {
8724
9017
  onClick: () => onRelinkSource == null ? void 0 : onRelinkSource(data.linkObject),
8725
9018
  className: baseButtonClass,
8726
9019
  title: "Desconectar ponta ligada ao Source"
8727
9020
  },
8728
- /* @__PURE__ */ React18.createElement(
9021
+ /* @__PURE__ */ React19.createElement(
8729
9022
  "svg",
8730
9023
  {
8731
9024
  xmlns: "http://www.w3.org/2000/svg",
@@ -8738,18 +9031,18 @@ function RelationshipContextMenu({
8738
9031
  strokeLinecap: "round",
8739
9032
  strokeLinejoin: "round"
8740
9033
  },
8741
- /* @__PURE__ */ React18.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" }),
8742
- /* @__PURE__ */ React18.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" })
9034
+ /* @__PURE__ */ React19.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" }),
9035
+ /* @__PURE__ */ React19.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" })
8743
9036
  ),
8744
- /* @__PURE__ */ React18.createElement("span", null, "Desconectar Source (", sourceName, ")")
8745
- ), /* @__PURE__ */ React18.createElement(
9037
+ /* @__PURE__ */ React19.createElement("span", null, "Desconectar Source (", sourceName, ")")
9038
+ ), /* @__PURE__ */ React19.createElement(
8746
9039
  "button",
8747
9040
  {
8748
9041
  onClick: () => onRelinkTarget == null ? void 0 : onRelinkTarget(data.linkObject),
8749
9042
  className: baseButtonClass,
8750
9043
  title: "Desconectar ponta ligada ao Target"
8751
9044
  },
8752
- /* @__PURE__ */ React18.createElement(
9045
+ /* @__PURE__ */ React19.createElement(
8753
9046
  "svg",
8754
9047
  {
8755
9048
  xmlns: "http://www.w3.org/2000/svg",
@@ -8762,21 +9055,21 @@ function RelationshipContextMenu({
8762
9055
  strokeLinecap: "round",
8763
9056
  strokeLinejoin: "round"
8764
9057
  },
8765
- /* @__PURE__ */ React18.createElement("polyline", { points: "16 3 21 3 21 8" }),
8766
- /* @__PURE__ */ React18.createElement("line", { x1: "4", y1: "20", x2: "21", y2: "3" }),
8767
- /* @__PURE__ */ React18.createElement("polyline", { points: "21 16 21 21 16 21" }),
8768
- /* @__PURE__ */ React18.createElement("line", { x1: "15", y1: "15", x2: "21", y2: "21" }),
8769
- /* @__PURE__ */ React18.createElement("line", { x1: "4", y1: "4", x2: "9", y2: "9" })
9058
+ /* @__PURE__ */ React19.createElement("polyline", { points: "16 3 21 3 21 8" }),
9059
+ /* @__PURE__ */ React19.createElement("line", { x1: "4", y1: "20", x2: "21", y2: "3" }),
9060
+ /* @__PURE__ */ React19.createElement("polyline", { points: "21 16 21 21 16 21" }),
9061
+ /* @__PURE__ */ React19.createElement("line", { x1: "15", y1: "15", x2: "21", y2: "21" }),
9062
+ /* @__PURE__ */ React19.createElement("line", { x1: "4", y1: "4", x2: "9", y2: "9" })
8770
9063
  ),
8771
- /* @__PURE__ */ React18.createElement("span", null, "Desconectar Target (", targetName, ")")
8772
- ), /* @__PURE__ */ React18.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" })), /* @__PURE__ */ React18.createElement(
9064
+ /* @__PURE__ */ React19.createElement("span", null, "Desconectar Target (", targetName, ")")
9065
+ ), /* @__PURE__ */ React19.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" })), /* @__PURE__ */ React19.createElement(
8773
9066
  "button",
8774
9067
  {
8775
9068
  onClick: () => onOpenDetails == null ? void 0 : onOpenDetails(data.linkObject),
8776
9069
  className: baseButtonClass,
8777
9070
  title: "Abrir detalhes da rela\xE7\xE3o"
8778
9071
  },
8779
- /* @__PURE__ */ React18.createElement(
9072
+ /* @__PURE__ */ React19.createElement(
8780
9073
  "svg",
8781
9074
  {
8782
9075
  xmlns: "http://www.w3.org/2000/svg",
@@ -8789,19 +9082,19 @@ function RelationshipContextMenu({
8789
9082
  strokeLinecap: "round",
8790
9083
  strokeLinejoin: "round"
8791
9084
  },
8792
- /* @__PURE__ */ React18.createElement("circle", { cx: "12", cy: "12", r: "10" }),
8793
- /* @__PURE__ */ React18.createElement("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
8794
- /* @__PURE__ */ React18.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "8" })
9085
+ /* @__PURE__ */ React19.createElement("circle", { cx: "12", cy: "12", r: "10" }),
9086
+ /* @__PURE__ */ React19.createElement("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
9087
+ /* @__PURE__ */ React19.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "8" })
8795
9088
  ),
8796
- /* @__PURE__ */ React18.createElement("span", null, "Abrir Detalhes")
8797
- ), canDelete && /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" }), /* @__PURE__ */ React18.createElement(
9089
+ /* @__PURE__ */ React19.createElement("span", null, "Abrir Detalhes")
9090
+ ), canDelete && /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" }), /* @__PURE__ */ React19.createElement(
8798
9091
  "button",
8799
9092
  {
8800
9093
  onClick: () => setIsConfirmingDelete(true),
8801
9094
  className: dangerButtonClass,
8802
9095
  title: "Excluir esta conex\xE3o"
8803
9096
  },
8804
- /* @__PURE__ */ React18.createElement(
9097
+ /* @__PURE__ */ React19.createElement(
8805
9098
  "svg",
8806
9099
  {
8807
9100
  xmlns: "http://www.w3.org/2000/svg",
@@ -8814,19 +9107,19 @@ function RelationshipContextMenu({
8814
9107
  strokeLinecap: "round",
8815
9108
  strokeLinejoin: "round"
8816
9109
  },
8817
- /* @__PURE__ */ React18.createElement("polyline", { points: "3 6 5 6 21 6" }),
8818
- /* @__PURE__ */ React18.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }),
8819
- /* @__PURE__ */ React18.createElement("path", { d: "M10 11v6" }),
8820
- /* @__PURE__ */ React18.createElement("path", { d: "M14 11v6" }),
8821
- /* @__PURE__ */ React18.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" })
9110
+ /* @__PURE__ */ React19.createElement("polyline", { points: "3 6 5 6 21 6" }),
9111
+ /* @__PURE__ */ React19.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }),
9112
+ /* @__PURE__ */ React19.createElement("path", { d: "M10 11v6" }),
9113
+ /* @__PURE__ */ React19.createElement("path", { d: "M14 11v6" }),
9114
+ /* @__PURE__ */ React19.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" })
8822
9115
  ),
8823
- /* @__PURE__ */ React18.createElement("span", null, "Excluir conex\xE3o (", sourceName, " \u2192 ", targetName, ")")
9116
+ /* @__PURE__ */ React19.createElement("span", null, "Excluir conex\xE3o (", sourceName, " \u2192 ", targetName, ")")
8824
9117
  )))))
8825
9118
  );
8826
9119
  }
8827
9120
 
8828
9121
  // src/components/LoadingScreen.jsx
8829
- import React19 from "react";
9122
+ import React20 from "react";
8830
9123
  var styles = {
8831
9124
  loadingOverlay: {
8832
9125
  position: "fixed",
@@ -8858,11 +9151,11 @@ var styles = {
8858
9151
  `
8859
9152
  };
8860
9153
  function LoadingScreen() {
8861
- return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("style", null, styles.keyframes), /* @__PURE__ */ React19.createElement("div", { style: styles.loadingOverlay }, /* @__PURE__ */ React19.createElement("div", { style: styles.spinner })));
9154
+ return /* @__PURE__ */ React20.createElement(React20.Fragment, null, /* @__PURE__ */ React20.createElement("style", null, styles.keyframes), /* @__PURE__ */ React20.createElement("div", { style: styles.loadingOverlay }, /* @__PURE__ */ React20.createElement("div", { style: styles.spinner })));
8862
9155
  }
8863
9156
 
8864
9157
  // src/components/ImportParentFileModal.jsx
8865
- import React20, { useEffect as useEffect19, useState as useState20 } from "react";
9158
+ import React21, { useEffect as useEffect19, useState as useState21 } from "react";
8866
9159
  function ImportParentFileModal({
8867
9160
  isOpen,
8868
9161
  onClose,
@@ -8873,11 +9166,11 @@ function ImportParentFileModal({
8873
9166
  onFetchAvailableFiles,
8874
9167
  currentViewName
8875
9168
  }) {
8876
- const [activeTab, setActiveTab] = useState20("databases");
8877
- const [availableDbs, setAvailableDbs] = useState20([]);
8878
- const [availableViews, setAvailableViews] = useState20([]);
8879
- const [selectedItem, setSelectedItem] = useState20(null);
8880
- const [isLoading, setIsLoading] = useState20(false);
9169
+ const [activeTab, setActiveTab] = useState21("databases");
9170
+ const [availableDbs, setAvailableDbs] = useState21([]);
9171
+ const [availableViews, setAvailableViews] = useState21([]);
9172
+ const [selectedItem, setSelectedItem] = useState21(null);
9173
+ const [isLoading, setIsLoading] = useState21(false);
8881
9174
  useEffect19(() => {
8882
9175
  if (isOpen && session && onFetchAvailableFiles) {
8883
9176
  const fetchData = async () => {
@@ -8943,13 +9236,13 @@ function ImportParentFileModal({
8943
9236
  const swallow = (e) => e.stopPropagation();
8944
9237
  const currentList = activeTab === "databases" ? availableDbs : availableViews;
8945
9238
  const emptyMessage = activeTab === "databases" ? "Nenhum novo arquivo parent dispon\xEDvel." : "Nenhuma view dispon\xEDvel para importa\xE7\xE3o.";
8946
- return /* @__PURE__ */ React20.createElement(
9239
+ return /* @__PURE__ */ React21.createElement(
8947
9240
  "div",
8948
9241
  {
8949
9242
  className: "ui-overlay fixed inset-0 z-[1200] flex items-center justify-center bg-black/60 backdrop-blur-sm",
8950
9243
  onClick: onClose
8951
9244
  },
8952
- /* @__PURE__ */ React20.createElement(
9245
+ /* @__PURE__ */ React21.createElement(
8953
9246
  "div",
8954
9247
  {
8955
9248
  className: "ui-overlay relative rounded-2xl border border-white/10 bg-slate-950/80 shadow-[0_20px_80px_rgba(0,0,0,0.6)] text-white w-[min(92vw,500px)] flex flex-col max-h-[85vh]",
@@ -8961,14 +9254,14 @@ function ImportParentFileModal({
8961
9254
  onContextMenu: swallow,
8962
9255
  onDoubleClick: swallow
8963
9256
  },
8964
- /* @__PURE__ */ React20.createElement("div", { className: "flex items-center justify-between px-6 py-4 border-b border-white/10 flex-shrink-0" }, /* @__PURE__ */ React20.createElement("h2", { className: "text-lg font-semibold" }, "Importar"), /* @__PURE__ */ React20.createElement(
9257
+ /* @__PURE__ */ React21.createElement("div", { className: "flex items-center justify-between px-6 py-4 border-b border-white/10 flex-shrink-0" }, /* @__PURE__ */ React21.createElement("h2", { className: "text-lg font-semibold" }, "Importar"), /* @__PURE__ */ React21.createElement(
8965
9258
  "button",
8966
9259
  {
8967
9260
  onClick: onClose,
8968
9261
  className: "p-2 rounded-md text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
8969
9262
  title: "Fechar"
8970
9263
  },
8971
- /* @__PURE__ */ React20.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ React20.createElement(
9264
+ /* @__PURE__ */ React21.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ React21.createElement(
8972
9265
  "path",
8973
9266
  {
8974
9267
  fillRule: "evenodd",
@@ -8977,14 +9270,14 @@ function ImportParentFileModal({
8977
9270
  }
8978
9271
  ))
8979
9272
  )),
8980
- /* @__PURE__ */ React20.createElement("div", { className: "flex px-6 border-b border-white/10 bg-white/5 flex-shrink-0" }, /* @__PURE__ */ React20.createElement(
9273
+ /* @__PURE__ */ React21.createElement("div", { className: "flex px-6 border-b border-white/10 bg-white/5 flex-shrink-0" }, /* @__PURE__ */ React21.createElement(
8981
9274
  "button",
8982
9275
  {
8983
9276
  onClick: () => setActiveTab("databases"),
8984
9277
  className: `flex-1 py-3 text-sm font-medium border-b-2 transition-colors ${activeTab === "databases" ? "border-indigo-500 text-white" : "border-transparent text-slate-400 hover:text-slate-200"}`
8985
9278
  },
8986
9279
  "Arquivos Parent"
8987
- ), /* @__PURE__ */ React20.createElement(
9280
+ ), /* @__PURE__ */ React21.createElement(
8988
9281
  "button",
8989
9282
  {
8990
9283
  onClick: () => setActiveTab("views"),
@@ -8992,24 +9285,24 @@ function ImportParentFileModal({
8992
9285
  },
8993
9286
  "Views (Ancestralidades)"
8994
9287
  )),
8995
- /* @__PURE__ */ React20.createElement("div", { className: "p-6 overflow-y-auto custom-scrollbar flex-grow min-h-[200px]" }, isLoading ? /* @__PURE__ */ React20.createElement("div", { className: "flex items-center justify-center h-40" }, /* @__PURE__ */ React20.createElement("div", { className: "w-8 h-8 border-4 border-t-indigo-500 border-slate-700 rounded-full animate-spin" })) : /* @__PURE__ */ React20.createElement("div", { className: "space-y-2" }, currentList.length > 0 ? currentList.map((item) => /* @__PURE__ */ React20.createElement(
9288
+ /* @__PURE__ */ React21.createElement("div", { className: "p-6 overflow-y-auto custom-scrollbar flex-grow min-h-[200px]" }, isLoading ? /* @__PURE__ */ React21.createElement("div", { className: "flex items-center justify-center h-40" }, /* @__PURE__ */ React21.createElement("div", { className: "w-8 h-8 border-4 border-t-indigo-500 border-slate-700 rounded-full animate-spin" })) : /* @__PURE__ */ React21.createElement("div", { className: "space-y-2" }, currentList.length > 0 ? currentList.map((item) => /* @__PURE__ */ React21.createElement(
8996
9289
  "div",
8997
9290
  {
8998
9291
  key: item.id,
8999
9292
  onClick: () => setSelectedItem(item),
9000
9293
  className: `px-4 py-3 rounded-lg border cursor-pointer transition-all duration-150 flex flex-col gap-1 ${(selectedItem == null ? void 0 : selectedItem.id) === item.id ? "bg-indigo-600 border-indigo-500 shadow-lg" : "bg-slate-800/60 border-white/10 hover:border-white/20 hover:bg-slate-800"}`
9001
9294
  },
9002
- /* @__PURE__ */ React20.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React20.createElement("span", { className: "font-medium text-slate-100" }, item.name), activeTab === "views" && /* @__PURE__ */ React20.createElement("span", { className: "text-[10px] px-1.5 py-0.5 rounded bg-black/30 text-indigo-300 border border-indigo-500/30" }, "VIEW")),
9003
- item.description && /* @__PURE__ */ React20.createElement("p", { className: `text-xs ${(selectedItem == null ? void 0 : selectedItem.id) === item.id ? "text-indigo-200" : "text-slate-400"}` }, item.description)
9004
- )) : /* @__PURE__ */ React20.createElement("p", { className: "text-slate-400 text-center py-10" }, emptyMessage))),
9005
- /* @__PURE__ */ React20.createElement("div", { className: "px-6 py-4 border-t border-white/10 flex justify-end gap-3 flex-shrink-0 bg-slate-900/50" }, /* @__PURE__ */ React20.createElement(
9295
+ /* @__PURE__ */ React21.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React21.createElement("span", { className: "font-medium text-slate-100" }, item.name), activeTab === "views" && /* @__PURE__ */ React21.createElement("span", { className: "text-[10px] px-1.5 py-0.5 rounded bg-black/30 text-indigo-300 border border-indigo-500/30" }, "VIEW")),
9296
+ item.description && /* @__PURE__ */ React21.createElement("p", { className: `text-xs ${(selectedItem == null ? void 0 : selectedItem.id) === item.id ? "text-indigo-200" : "text-slate-400"}` }, item.description)
9297
+ )) : /* @__PURE__ */ React21.createElement("p", { className: "text-slate-400 text-center py-10" }, emptyMessage))),
9298
+ /* @__PURE__ */ React21.createElement("div", { className: "px-6 py-4 border-t border-white/10 flex justify-end gap-3 flex-shrink-0 bg-slate-900/50" }, /* @__PURE__ */ React21.createElement(
9006
9299
  "button",
9007
9300
  {
9008
9301
  onClick: onClose,
9009
9302
  className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm text-slate-300"
9010
9303
  },
9011
9304
  "Cancelar"
9012
- ), /* @__PURE__ */ React20.createElement(
9305
+ ), /* @__PURE__ */ React21.createElement(
9013
9306
  "button",
9014
9307
  {
9015
9308
  onClick: handleConfirm,
@@ -9023,7 +9316,7 @@ function ImportParentFileModal({
9023
9316
  }
9024
9317
 
9025
9318
  // src/components/AncestryLinkDetailsPanel.jsx
9026
- import React21, { useState as useState21 } from "react";
9319
+ import React22, { useState as useState22 } from "react";
9027
9320
  import { FiBookOpen as FiBookOpen5 } from "react-icons/fi";
9028
9321
  function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile }) {
9029
9322
  var _a, _b, _c, _d;
@@ -9033,21 +9326,21 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9033
9326
  const customProps = extractCustomPropsFromNode(relationshipData);
9034
9327
  const sourceName = ((_b = (_a = data.sourceNode) == null ? void 0 : _a.userData) == null ? void 0 : _b.name) || "Origem";
9035
9328
  const targetName = ((_d = (_c = data.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) || "Destino";
9036
- const [isReadMode, setIsReadMode] = useState21(false);
9329
+ const [isReadMode, setIsReadMode] = useState22(false);
9037
9330
  const swallow = (e) => e.stopPropagation();
9038
9331
  const handleImageClickFromText = (url, name) => {
9039
9332
  if (onOpenImageViewer) {
9040
9333
  onOpenImageViewer([{ name: name || "Imagem", value: url }], 0);
9041
9334
  }
9042
9335
  };
9043
- return /* @__PURE__ */ React21.createElement(
9336
+ return /* @__PURE__ */ React22.createElement(
9044
9337
  "div",
9045
9338
  {
9046
9339
  className: "ui-overlay fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-[1200]",
9047
9340
  onClick: onClose,
9048
9341
  onPointerDown: swallow
9049
9342
  },
9050
- /* @__PURE__ */ React21.createElement(
9343
+ /* @__PURE__ */ React22.createElement(
9051
9344
  "div",
9052
9345
  {
9053
9346
  className: `relative group rounded-2xl border border-white/10 bg-slate-950/80 shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col max-h-[calc(100vh-4rem)] transition-all duration-300 ease-out
@@ -9055,7 +9348,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9055
9348
  `,
9056
9349
  onClick: swallow
9057
9350
  },
9058
- isReadMode ? /* @__PURE__ */ React21.createElement(
9351
+ isReadMode ? /* @__PURE__ */ React22.createElement(
9059
9352
  DescriptionReadModePanel,
9060
9353
  {
9061
9354
  title: `${sourceName} \u2794 ${targetName}`,
@@ -9067,15 +9360,15 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9067
9360
  onMentionClick,
9068
9361
  onImageClick: handleImageClickFromText
9069
9362
  }
9070
- ) : /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ React21.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React21.createElement("div", null, /* @__PURE__ */ React21.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React21.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-blue-500/80 shadow-[0_0_18px_2px_rgba(59,130,246,0.55)]" }), /* @__PURE__ */ React21.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Ancestralidade")), /* @__PURE__ */ React21.createElement("h2", { className: "text-lg font-semibold tracking-tight flex items-center gap-2" }, /* @__PURE__ */ React21.createElement("span", { className: "truncate max-w-[150px]" }, sourceName), /* @__PURE__ */ React21.createElement("span", { className: "text-slate-500 text-sm" }, "\u2794"), /* @__PURE__ */ React21.createElement("span", { className: "truncate max-w-[150px]" }, targetName))), /* @__PURE__ */ React21.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__ */ React21.createElement("div", { className: "px-6 pb-6 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, description && /* @__PURE__ */ React21.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React21.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React21.createElement("label", { className: "text-xs text-slate-300 font-medium" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React21.createElement(
9363
+ ) : /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ React22.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React22.createElement("div", null, /* @__PURE__ */ React22.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React22.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-blue-500/80 shadow-[0_0_18px_2px_rgba(59,130,246,0.55)]" }), /* @__PURE__ */ React22.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Ancestralidade")), /* @__PURE__ */ React22.createElement("h2", { className: "text-lg font-semibold tracking-tight flex items-center gap-2" }, /* @__PURE__ */ React22.createElement("span", { className: "truncate max-w-[150px]" }, sourceName), /* @__PURE__ */ React22.createElement("span", { className: "text-slate-500 text-sm" }, "\u2794"), /* @__PURE__ */ React22.createElement("span", { className: "truncate max-w-[150px]" }, targetName))), /* @__PURE__ */ React22.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__ */ React22.createElement("div", { className: "px-6 pb-6 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, description && /* @__PURE__ */ React22.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React22.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React22.createElement("label", { className: "text-xs text-slate-300 font-medium" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React22.createElement(
9071
9364
  "button",
9072
9365
  {
9073
9366
  onClick: () => setIsReadMode(true),
9074
9367
  className: "p-1 text-slate-400 hover:text-white transition-colors",
9075
9368
  title: "Modo de Leitura"
9076
9369
  },
9077
- /* @__PURE__ */ React21.createElement(FiBookOpen5, { size: 14 })
9078
- )), /* @__PURE__ */ React21.createElement("div", { className: "bg-slate-800/40 rounded-lg border border-white/10 p-1 relative group" }, /* @__PURE__ */ React21.createElement(
9370
+ /* @__PURE__ */ React22.createElement(FiBookOpen5, { size: 14 })
9371
+ )), /* @__PURE__ */ React22.createElement("div", { className: "bg-slate-800/40 rounded-lg border border-white/10 p-1 relative group" }, /* @__PURE__ */ React22.createElement(
9079
9372
  DescriptionDisplay,
9080
9373
  {
9081
9374
  description,
@@ -9084,7 +9377,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9084
9377
  onMentionClick,
9085
9378
  onImageClick: handleImageClickFromText
9086
9379
  }
9087
- ))), customProps.length > 0 && /* @__PURE__ */ React21.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React21.createElement("label", { className: "text-xs text-slate-300 font-medium mb-2 block" }, "Propriedades"), /* @__PURE__ */ React21.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop) => /* @__PURE__ */ React21.createElement(
9380
+ ))), customProps.length > 0 && /* @__PURE__ */ React22.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React22.createElement("label", { className: "text-xs text-slate-300 font-medium mb-2 block" }, "Propriedades"), /* @__PURE__ */ React22.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop) => /* @__PURE__ */ React22.createElement(
9088
9381
  CustomPropertyDisplay,
9089
9382
  {
9090
9383
  key: prop.id,
@@ -9093,25 +9386,25 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9093
9386
  onOpenImageViewer,
9094
9387
  onUploadFile
9095
9388
  }
9096
- )))), !description && customProps.length === 0 && /* @__PURE__ */ React21.createElement("div", { className: "py-8 text-center text-slate-500 text-sm italic border border-dashed border-white/10 rounded-lg" }, "Nenhum detalhe adicional dispon\xEDvel para esta conex\xE3o."), /* @__PURE__ */ React21.createElement("div", { className: "mt-4 p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg text-xs text-blue-200/80 text-center" }, 'Para editar esta conex\xE3o, utilize o menu "Editar Ancestralidade".')))
9389
+ )))), !description && customProps.length === 0 && /* @__PURE__ */ React22.createElement("div", { className: "py-8 text-center text-slate-500 text-sm italic border border-dashed border-white/10 rounded-lg" }, "Nenhum detalhe adicional dispon\xEDvel para esta conex\xE3o."), /* @__PURE__ */ React22.createElement("div", { className: "mt-4 p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg text-xs text-blue-200/80 text-center" }, 'Para editar esta conex\xE3o, utilize o menu "Editar Ancestralidade".')))
9097
9390
  )
9098
9391
  );
9099
9392
  }
9100
9393
 
9101
9394
  // src/components/AncestryBoard.jsx
9102
- import React22, { useState as useState22, useMemo as useMemo11, useEffect as useEffect20, useRef as useRef16 } from "react";
9395
+ import React23, { useState as useState23, useMemo as useMemo11, useEffect as useEffect20, useRef as useRef17 } from "react";
9103
9396
  import {
9104
9397
  FiSearch as FiSearch4,
9105
9398
  FiLayers as FiLayers6,
9106
9399
  FiCornerUpRight as FiCornerUpRight4,
9107
9400
  FiPlay,
9108
- FiPlus as FiPlus7,
9401
+ FiPlus as FiPlus8,
9109
9402
  FiTrash2 as FiTrash23,
9110
9403
  FiArrowLeft as FiArrowLeft3,
9111
9404
  FiArrowRight,
9112
9405
  FiCheckCircle,
9113
9406
  FiLoader as FiLoader4,
9114
- FiX as FiX5,
9407
+ FiX as FiX6,
9115
9408
  FiAlertTriangle
9116
9409
  } from "react-icons/fi";
9117
9410
  var GroupItem = ({
@@ -9133,7 +9426,7 @@ var GroupItem = ({
9133
9426
  }) => {
9134
9427
  const canIndent = index > 0;
9135
9428
  const isPickingForThisGroup = pickingGroupId === group.id;
9136
- const textareaRef = useRef16(null);
9429
+ const textareaRef = useRef17(null);
9137
9430
  const adjustHeight = () => {
9138
9431
  const textarea = textareaRef.current;
9139
9432
  if (textarea) {
@@ -9144,10 +9437,10 @@ var GroupItem = ({
9144
9437
  useEffect20(() => {
9145
9438
  adjustHeight();
9146
9439
  }, [group.text]);
9147
- return /* @__PURE__ */ React22.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React22.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ React22.createElement("div", { className: `
9440
+ return /* @__PURE__ */ React23.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React23.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ React23.createElement("div", { className: `
9148
9441
  flex flex-col gap-2 py-2 px-3 transition-all duration-200
9149
9442
  ${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
9150
- ` }, /* @__PURE__ */ React22.createElement(
9443
+ ` }, /* @__PURE__ */ React23.createElement(
9151
9444
  "textarea",
9152
9445
  {
9153
9446
  ref: textareaRef,
@@ -9164,9 +9457,9 @@ var GroupItem = ({
9164
9457
  if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
9165
9458
  }
9166
9459
  }
9167
- ), group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ React22.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
9460
+ ), group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ React23.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
9168
9461
  const isValid = availableIds.has(String(anc.ancestry_id));
9169
- return /* @__PURE__ */ React22.createElement(
9462
+ return /* @__PURE__ */ React23.createElement(
9170
9463
  "div",
9171
9464
  {
9172
9465
  key: anc.ancestry_id,
@@ -9178,28 +9471,28 @@ var GroupItem = ({
9178
9471
  },
9179
9472
  isValid ? (
9180
9473
  // [MANTIDO] Botão Play visível para todos
9181
- /* @__PURE__ */ React22.createElement(
9474
+ /* @__PURE__ */ React23.createElement(
9182
9475
  "button",
9183
9476
  {
9184
9477
  onClick: () => onPlayAncestry(anc.ancestry_id),
9185
9478
  className: "text-indigo-400 hover:text-white hover:bg-indigo-500 p-1 rounded-full transition-colors",
9186
9479
  title: "Renderizar no cen\xE1rio"
9187
9480
  },
9188
- /* @__PURE__ */ React22.createElement(FiPlay, { size: 10, className: "ml-0.5 fill-current" })
9481
+ /* @__PURE__ */ React23.createElement(FiPlay, { size: 10, className: "ml-0.5 fill-current" })
9189
9482
  )
9190
- ) : /* @__PURE__ */ React22.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ React22.createElement(FiAlertTriangle, { size: 10 })),
9191
- /* @__PURE__ */ React22.createElement("span", { className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}` }, anc.name),
9192
- canEdit && /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement("div", { className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}` }), /* @__PURE__ */ React22.createElement(
9483
+ ) : /* @__PURE__ */ React23.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ React23.createElement(FiAlertTriangle, { size: 10 })),
9484
+ /* @__PURE__ */ React23.createElement("span", { className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}` }, anc.name),
9485
+ canEdit && /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement("div", { className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}` }), /* @__PURE__ */ React23.createElement(
9193
9486
  "button",
9194
9487
  {
9195
9488
  onClick: () => onRemoveAncestry(group.id, anc.ancestry_id),
9196
9489
  className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
9197
9490
  title: "Remover men\xE7\xE3o"
9198
9491
  },
9199
- /* @__PURE__ */ React22.createElement(FiX5, { size: 12 })
9492
+ /* @__PURE__ */ React23.createElement(FiX6, { size: 12 })
9200
9493
  ))
9201
9494
  );
9202
- })), canEdit && /* @__PURE__ */ React22.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ React22.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React22.createElement(
9495
+ })), canEdit && /* @__PURE__ */ React23.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ React23.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React23.createElement(
9203
9496
  "button",
9204
9497
  {
9205
9498
  onClick: () => onRequestPickAncestry(group.id),
@@ -9209,17 +9502,17 @@ var GroupItem = ({
9209
9502
  `,
9210
9503
  title: "Adicionar Ancestralidade a este grupo"
9211
9504
  },
9212
- isPickingForThisGroup ? /* @__PURE__ */ React22.createElement(FiCheckCircle, { size: 12 }) : /* @__PURE__ */ React22.createElement(FiSearch4, { size: 12 }),
9505
+ isPickingForThisGroup ? /* @__PURE__ */ React23.createElement(FiCheckCircle, { size: 12 }) : /* @__PURE__ */ React23.createElement(FiSearch4, { size: 12 }),
9213
9506
  isPickingForThisGroup ? "Selecionando..." : "Adicionar"
9214
- ), /* @__PURE__ */ React22.createElement(
9507
+ ), /* @__PURE__ */ React23.createElement(
9215
9508
  "button",
9216
9509
  {
9217
9510
  onClick: () => onAddSubgroup(group.id),
9218
9511
  className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
9219
9512
  title: "Criar Subgrupo"
9220
9513
  },
9221
- /* @__PURE__ */ React22.createElement(FiPlus7, { size: 14 })
9222
- )), /* @__PURE__ */ React22.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React22.createElement(
9514
+ /* @__PURE__ */ React23.createElement(FiPlus8, { size: 14 })
9515
+ )), /* @__PURE__ */ React23.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React23.createElement(
9223
9516
  "button",
9224
9517
  {
9225
9518
  onClick: () => onIndent(group.id),
@@ -9227,24 +9520,24 @@ var GroupItem = ({
9227
9520
  className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
9228
9521
  title: "Aninhar no grupo acima"
9229
9522
  },
9230
- /* @__PURE__ */ React22.createElement(FiArrowRight, { size: 14 })
9231
- ), /* @__PURE__ */ React22.createElement(
9523
+ /* @__PURE__ */ React23.createElement(FiArrowRight, { size: 14 })
9524
+ ), /* @__PURE__ */ React23.createElement(
9232
9525
  "button",
9233
9526
  {
9234
9527
  onClick: () => onOutdent(group.id),
9235
9528
  className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
9236
9529
  title: "Desaninhar"
9237
9530
  },
9238
- /* @__PURE__ */ React22.createElement(FiArrowLeft3, { size: 14 })
9239
- ), /* @__PURE__ */ React22.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React22.createElement(
9531
+ /* @__PURE__ */ React23.createElement(FiArrowLeft3, { size: 14 })
9532
+ ), /* @__PURE__ */ React23.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React23.createElement(
9240
9533
  "button",
9241
9534
  {
9242
9535
  onClick: () => onDelete(group.id),
9243
9536
  className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
9244
9537
  title: "Remover Grupo"
9245
9538
  },
9246
- /* @__PURE__ */ React22.createElement(FiTrash23, { size: 14 })
9247
- )))), group.children && group.children.length > 0 && /* @__PURE__ */ React22.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ React22.createElement(
9539
+ /* @__PURE__ */ React23.createElement(FiTrash23, { size: 14 })
9540
+ )))), group.children && group.children.length > 0 && /* @__PURE__ */ React23.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ React23.createElement(
9248
9541
  GroupItem,
9249
9542
  {
9250
9543
  key: childGroup.id,
@@ -9276,11 +9569,11 @@ function AncestryBoard({
9276
9569
  userRole
9277
9570
  // [NOVO] Recebe a role do usuário
9278
9571
  }) {
9279
- const [searchTerm, setSearchTerm] = useState22("");
9280
- const [groups, setGroups] = useState22([]);
9281
- const [isLoaded, setIsLoaded] = useState22(false);
9282
- const [pickingGroupId, setPickingGroupId] = useState22(null);
9283
- const [saveStatus, setSaveStatus] = useState22("idle");
9572
+ const [searchTerm, setSearchTerm] = useState23("");
9573
+ const [groups, setGroups] = useState23([]);
9574
+ const [isLoaded, setIsLoaded] = useState23(false);
9575
+ const [pickingGroupId, setPickingGroupId] = useState23(null);
9576
+ const [saveStatus, setSaveStatus] = useState23("idle");
9284
9577
  const canEdit = useMemo11(() => {
9285
9578
  return userRole !== "viewer";
9286
9579
  }, [userRole]);
@@ -9488,27 +9781,27 @@ function AncestryBoard({
9488
9781
  });
9489
9782
  };
9490
9783
  if (!isOpen) return null;
9491
- return /* @__PURE__ */ React22.createElement(
9784
+ return /* @__PURE__ */ React23.createElement(
9492
9785
  "div",
9493
9786
  {
9494
9787
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
9495
9788
  onClick: onClose
9496
9789
  },
9497
- /* @__PURE__ */ React22.createElement(
9790
+ /* @__PURE__ */ React23.createElement(
9498
9791
  "div",
9499
9792
  {
9500
9793
  className: "bg-slate-950 border border-white/10 rounded-xl w-[98vw] h-[97vh] flex flex-col shadow-2xl overflow-hidden animate-in fade-in zoom-in-95 duration-200",
9501
9794
  onClick: (e) => e.stopPropagation()
9502
9795
  },
9503
- /* @__PURE__ */ React22.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ React22.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React22.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ React22.createElement(FiLayers6, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ React22.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React22.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ React22.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(FiLoader4, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ React22.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ React22.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ React22.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ React22.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ React22.createElement("span", { className: "text-xs text-indigo-300 font-medium animate-pulse hidden sm:inline-block mr-2" }, "Selecione na lateral..."), canEdit && /* @__PURE__ */ React22.createElement(
9796
+ /* @__PURE__ */ React23.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ React23.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React23.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ React23.createElement(FiLayers6, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ React23.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React23.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ React23.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(FiLoader4, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ React23.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ React23.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ React23.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ React23.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ React23.createElement("span", { className: "text-xs text-indigo-300 font-medium animate-pulse hidden sm:inline-block mr-2" }, "Selecione na lateral..."), canEdit && /* @__PURE__ */ React23.createElement(
9504
9797
  "button",
9505
9798
  {
9506
9799
  onClick: handleAddRootGroup,
9507
9800
  className: "\n flex items-center gap-2 px-3 py-1.5 \n bg-white/5 hover:bg-white/10 \n border border-white/10 hover:border-white/20\n backdrop-blur-sm\n text-slate-200 hover:text-white\n rounded-md transition-all duration-200\n text-xs font-medium shadow-sm\n "
9508
9801
  },
9509
- /* @__PURE__ */ React22.createElement(FiPlus7, { size: 14, className: "text-indigo-400" }),
9510
- /* @__PURE__ */ React22.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
9511
- ), /* @__PURE__ */ React22.createElement(
9802
+ /* @__PURE__ */ React23.createElement(FiPlus8, { size: 14, className: "text-indigo-400" }),
9803
+ /* @__PURE__ */ React23.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
9804
+ ), /* @__PURE__ */ React23.createElement(
9512
9805
  "button",
9513
9806
  {
9514
9807
  onClick: onClose,
@@ -9516,11 +9809,11 @@ function AncestryBoard({
9516
9809
  },
9517
9810
  "\xD7"
9518
9811
  ))),
9519
- /* @__PURE__ */ React22.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React22.createElement("div", { className: `
9812
+ /* @__PURE__ */ React23.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React23.createElement("div", { className: `
9520
9813
  flex flex-col border-r border-white/10 transition-all duration-300 flex-none
9521
9814
  ${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
9522
9815
  min-w-[280px] max-w-[500px] bg-slate-900
9523
- ` }, /* @__PURE__ */ React22.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ React22.createElement("div", { className: "relative group" }, /* @__PURE__ */ React22.createElement(FiSearch4, { className: `absolute left-3 top-1/2 -translate-y-1/2 transition-colors ${pickingGroupId ? "text-indigo-400" : "text-slate-500 group-focus-within:text-indigo-400"}` }), /* @__PURE__ */ React22.createElement(
9816
+ ` }, /* @__PURE__ */ React23.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ React23.createElement("div", { className: "relative group" }, /* @__PURE__ */ React23.createElement(FiSearch4, { className: `absolute left-3 top-1/2 -translate-y-1/2 transition-colors ${pickingGroupId ? "text-indigo-400" : "text-slate-500 group-focus-within:text-indigo-400"}` }), /* @__PURE__ */ React23.createElement(
9524
9817
  "input",
9525
9818
  {
9526
9819
  type: "text",
@@ -9533,10 +9826,10 @@ function AncestryBoard({
9533
9826
  onChange: (e) => setSearchTerm(e.target.value),
9534
9827
  autoFocus: !pickingGroupId
9535
9828
  }
9536
- ))), /* @__PURE__ */ React22.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
9829
+ ))), /* @__PURE__ */ React23.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
9537
9830
  const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
9538
9831
  const isPicking = !!pickingGroupId;
9539
- return /* @__PURE__ */ React22.createElement(
9832
+ return /* @__PURE__ */ React23.createElement(
9540
9833
  "div",
9541
9834
  {
9542
9835
  key: anc.ancestry_id,
@@ -9548,12 +9841,12 @@ function AncestryBoard({
9548
9841
  ${isPicking ? "border-indigo-500/30 bg-indigo-500/5 hover:bg-indigo-500/20 hover:border-indigo-400 cursor-pointer" : "border-white/5 bg-slate-800/40 hover:bg-indigo-600/10 hover:border-indigo-500/30 cursor-default"}
9549
9842
  `
9550
9843
  },
9551
- /* @__PURE__ */ React22.createElement("div", { className: `
9844
+ /* @__PURE__ */ React23.createElement("div", { className: `
9552
9845
  mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
9553
9846
  ${isPicking ? "bg-indigo-500 text-white border-indigo-400" : "bg-slate-800 text-indigo-400 border-white/5 group-hover:bg-indigo-500 group-hover:text-white"}
9554
- ` }, isPicking ? /* @__PURE__ */ React22.createElement(FiPlus7, { size: 16 }) : /* @__PURE__ */ React22.createElement(FiLayers6, { size: 14 })),
9555
- /* @__PURE__ */ React22.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ React22.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ React22.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, anc.name || "Sem Nome"), anc.is_private && /* @__PURE__ */ React22.createElement("span", { className: "text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-300 border border-amber-500/20" }, "Priv")), /* @__PURE__ */ React22.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ React22.createElement(FiCornerUpRight4, { size: 10 }), /* @__PURE__ */ React22.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.description && /* @__PURE__ */ React22.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
9556
- !isPicking && /* @__PURE__ */ React22.createElement(
9847
+ ` }, isPicking ? /* @__PURE__ */ React23.createElement(FiPlus8, { size: 16 }) : /* @__PURE__ */ React23.createElement(FiLayers6, { size: 14 })),
9848
+ /* @__PURE__ */ React23.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ React23.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ React23.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, anc.name || "Sem Nome"), anc.is_private && /* @__PURE__ */ React23.createElement("span", { className: "text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-300 border border-amber-500/20" }, "Priv")), /* @__PURE__ */ React23.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ React23.createElement(FiCornerUpRight4, { size: 10 }), /* @__PURE__ */ React23.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.description && /* @__PURE__ */ React23.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
9849
+ !isPicking && /* @__PURE__ */ React23.createElement(
9557
9850
  "button",
9558
9851
  {
9559
9852
  onClick: (e) => {
@@ -9563,10 +9856,10 @@ function AncestryBoard({
9563
9856
  className: "absolute right-2 bottom-2 opacity-0 group-hover:opacity-100 transition-all duration-300 transform translate-y-2 group-hover:translate-y-0 z-10",
9564
9857
  title: "Renderizar Ancestralidade"
9565
9858
  },
9566
- /* @__PURE__ */ React22.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ React22.createElement(FiPlay, { size: 14, className: "ml-0.5" }))
9859
+ /* @__PURE__ */ React23.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ React23.createElement(FiPlay, { size: 14, className: "ml-0.5" }))
9567
9860
  )
9568
9861
  );
9569
- }))), /* @__PURE__ */ React22.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ React22.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ React22.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-3 border-2 border-dashed border-white/5 rounded-xl m-4 bg-slate-900/20" }, /* @__PURE__ */ React22.createElement(FiLayers6, { size: 24, className: "opacity-20" }), /* @__PURE__ */ React22.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ React22.createElement(React22.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ React22.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ React22.createElement(React22.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ React22.createElement(
9862
+ }))), /* @__PURE__ */ React23.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ React23.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ React23.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-3 border-2 border-dashed border-white/5 rounded-xl m-4 bg-slate-900/20" }, /* @__PURE__ */ React23.createElement(FiLayers6, { size: 24, className: "opacity-20" }), /* @__PURE__ */ React23.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ React23.createElement(React23.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ React23.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ React23.createElement(React23.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ React23.createElement(
9570
9863
  GroupItem,
9571
9864
  {
9572
9865
  key: group.id,
@@ -9586,7 +9879,7 @@ function AncestryBoard({
9586
9879
  canEdit
9587
9880
  }
9588
9881
  ))))),
9589
- /* @__PURE__ */ React22.createElement("div", { className: "px-5 py-2 border-t border-white/10 bg-slate-950/50 text-xs text-slate-500 flex justify-between flex-shrink-0" }, /* @__PURE__ */ React22.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ React22.createElement("span", null, groups.length, " grupos raiz"))
9882
+ /* @__PURE__ */ React23.createElement("div", { className: "px-5 py-2 border-t border-white/10 bg-slate-950/50 text-xs text-slate-500 flex justify-between flex-shrink-0" }, /* @__PURE__ */ React23.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ React23.createElement("span", null, groups.length, " grupos raiz"))
9590
9883
  )
9591
9884
  );
9592
9885
  }
@@ -9730,44 +10023,45 @@ function XViewScene({
9730
10023
  }
9731
10024
  return null;
9732
10025
  }, [ownerId, sceneConfigId]);
9733
- const sceneDataRef = useRef17(null);
9734
- const parentDataRef = useRef17(null);
9735
- const ancestryDataRef = useRef17(null);
9736
- const [isLoading, setIsLoading] = useState23(true);
9737
- const [permissionStatus, setPermissionStatus] = useState23("loading");
9738
- const [userPermissionRole, setUserPermissionRole] = useState23(null);
9739
- const [isInitialized, setIsInitialized] = useState23(false);
9740
- const [sceneVersion, setSceneVersion] = useState23(0);
9741
- const [contextMenu, setContextMenu] = useState23({ visible: false, x: 0, y: 0, nodeData: null });
9742
- const [multiContextMenu, setMultiContextMenu] = useState23({ visible: false, x: 0, y: 0, nodeIds: null });
9743
- const [relationshipMenu, setRelationshipMenu] = useState23({ visible: false, x: 0, y: 0, linkObject: null });
9744
- const [creationMode, setCreationMode] = useState23({ isActive: false, sourceNodeData: null });
9745
- const [versionMode, setVersionMode] = useState23({ isActive: false, sourceNodeData: null });
9746
- const [hasFocusedInitial, setHasFocusedInitial] = useState23(false);
9747
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState23(false);
9748
- const [ancestryMode, setAncestryMode] = useState23({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
9749
- const [readingMode, setReadingMode] = useState23({
10026
+ const sceneDataRef = useRef18(null);
10027
+ const parentDataRef = useRef18(null);
10028
+ const ancestryDataRef = useRef18(null);
10029
+ const [isLoading, setIsLoading] = useState24(true);
10030
+ const [permissionStatus, setPermissionStatus] = useState24("loading");
10031
+ const [userPermissionRole, setUserPermissionRole] = useState24(null);
10032
+ const [isInitialized, setIsInitialized] = useState24(false);
10033
+ const [sceneVersion, setSceneVersion] = useState24(0);
10034
+ const [contextMenu, setContextMenu] = useState24({ visible: false, x: 0, y: 0, nodeData: null });
10035
+ const [multiContextMenu, setMultiContextMenu] = useState24({ visible: false, x: 0, y: 0, nodeIds: null });
10036
+ const [relationshipMenu, setRelationshipMenu] = useState24({ visible: false, x: 0, y: 0, linkObject: null });
10037
+ const [creationMode, setCreationMode] = useState24({ isActive: false, sourceNodeData: null });
10038
+ const [versionMode, setVersionMode] = useState24({ isActive: false, sourceNodeData: null });
10039
+ const [questMode, setQuestMode] = useState24({ isActive: false });
10040
+ const [hasFocusedInitial, setHasFocusedInitial] = useState24(false);
10041
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState24(false);
10042
+ const [ancestryMode, setAncestryMode] = useState24({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
10043
+ const [readingMode, setReadingMode] = useState24({
9750
10044
  isActive: false,
9751
10045
  ancestry: null,
9752
10046
  branchStack: [],
9753
10047
  autoAbstraction: false
9754
10048
  });
9755
- const [formPosition, setFormPosition] = useState23({ left: 16, top: 16, opacity: 0 });
9756
- const [detailsNode, setDetailsNode] = useState23(null);
9757
- const [detailsLink, setDetailsLink] = useState23(null);
9758
- const [ancestryLinkDetails, setAncestryLinkDetails] = useState23(null);
9759
- const [imageViewer, setImageViewer] = useState23({ visible: false, images: [], startIndex: 0 });
9760
- const [editingAncestryRel, setEditingAncestryRel] = useState23({ visible: false, data: null, path: null });
9761
- const [isImportModalOpen, setIsImportModalOpen] = useState23(false);
9762
- const [importSuccessMessage, setImportSuccessMessage] = useState23("");
9763
- const [highlightedNodeId, setHighlightedNodeId] = useState23(null);
9764
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState23(false);
9765
- const [ancestryBoardData, setAncestryBoardData] = useState23([]);
9766
- const [isSidebarOpen, setIsSidebarOpen] = useState23(false);
9767
- const mountRef = useRef17(null);
9768
- const tooltipRef = useRef17(null);
9769
- const formRef = useRef17(null);
9770
- const stateRef = useRef17({
10049
+ const [formPosition, setFormPosition] = useState24({ left: 16, top: 16, opacity: 0 });
10050
+ const [detailsNode, setDetailsNode] = useState24(null);
10051
+ const [detailsLink, setDetailsLink] = useState24(null);
10052
+ const [ancestryLinkDetails, setAncestryLinkDetails] = useState24(null);
10053
+ const [imageViewer, setImageViewer] = useState24({ visible: false, images: [], startIndex: 0 });
10054
+ const [editingAncestryRel, setEditingAncestryRel] = useState24({ visible: false, data: null, path: null });
10055
+ const [isImportModalOpen, setIsImportModalOpen] = useState24(false);
10056
+ const [importSuccessMessage, setImportSuccessMessage] = useState24("");
10057
+ const [highlightedNodeId, setHighlightedNodeId] = useState24(null);
10058
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState24(false);
10059
+ const [ancestryBoardData, setAncestryBoardData] = useState24([]);
10060
+ const [isSidebarOpen, setIsSidebarOpen] = useState24(false);
10061
+ const mountRef = useRef18(null);
10062
+ const tooltipRef = useRef18(null);
10063
+ const formRef = useRef18(null);
10064
+ const stateRef = useRef18({
9771
10065
  readMode: {
9772
10066
  currentMaxIndex: 0,
9773
10067
  progressMap: {}
@@ -10809,12 +11103,15 @@ function XViewScene({
10809
11103
  if (mountRef.current) mountRef.current.style.cursor = "grab";
10810
11104
  }
10811
11105
  function handleKeyDown(event) {
11106
+ var _a2, _b2, _c2, _d2;
10812
11107
  const context = actionHandlerContext;
10813
11108
  if (event.key === "Escape") {
10814
11109
  if (stateRef.current.connection.isActive) userActionHandlers.handleCancelConnection(context);
10815
11110
  if (stateRef.current.relink.isActive) userActionHandlers.handleCancelRelink(context);
10816
11111
  if (stateRef.current.creation.isActive) userActionHandlers.handleCancelCreation(context);
11112
+ if ((_a2 = stateRef.current.versionMode) == null ? void 0 : _a2.isActive) userActionHandlers.handleCancelVersioning(context);
10817
11113
  if (stateRef.current.ancestry.isActive) handleCancelAncestryCreation();
11114
+ if ((_b2 = context.questMode) == null ? void 0 : _b2.isActive) context.setters.setQuestMode({ isActive: false });
10818
11115
  if (stateRef.current.selectedNodes.size > 0) {
10819
11116
  stateRef.current.selectedNodes.clear();
10820
11117
  }
@@ -10822,6 +11119,17 @@ function XViewScene({
10822
11119
  setMultiContextMenu((prev) => ({ ...prev, visible: false }));
10823
11120
  setRelationshipMenu((prev) => ({ ...prev, visible: false }));
10824
11121
  }
11122
+ if (event.key.toLowerCase() === "q") {
11123
+ const isUiClear = !stateRef.current.creation.isActive && !stateRef.current.connection.isActive && !stateRef.current.relink.isActive && !stateRef.current.ancestry.isActive && !((_c2 = context.versionMode) == null ? void 0 : _c2.isActive) && !contextMenu.visible && !multiContextMenu.visible && !relationshipMenu.visible && !readingMode.isActive && !isImportModalOpen && !isAncestryBoardOpen;
11124
+ if (isUiClear) {
11125
+ const isView = ((_d2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _d2.toLowerCase()) === "view";
11126
+ if (!isView) {
11127
+ alert("Nodes de Quest s\xF3 podem ser criados dentro de uma View.");
11128
+ return;
11129
+ }
11130
+ setQuestMode({ isActive: true });
11131
+ }
11132
+ }
10825
11133
  }
10826
11134
  function handleDoubleClick(event) {
10827
11135
  if (stateRef.current.camera) stateRef.current.camera.layers.enableAll();
@@ -10980,9 +11288,7 @@ function XViewScene({
10980
11288
  mountEl: currentMount,
10981
11289
  isSceneBusy: stateRef.current.isDragging || creation.isActive || connection.isActive || relink.isActive || ancestryMode.isActive,
10982
11290
  parentData: parentDataRef.current,
10983
- // <--- ADICIONADO AQUI
10984
11291
  ancestryData: ancestryDataRef.current
10985
- // <--- ADICIONADO AQUI
10986
11292
  });
10987
11293
  (_b2 = stateRef.current.tweenGroup) == null ? void 0 : _b2.update(time);
10988
11294
  stateRef.current.controls.update();
@@ -11288,6 +11594,11 @@ function XViewScene({
11288
11594
  mountRef,
11289
11595
  creationMode,
11290
11596
  versionMode,
11597
+ questMode,
11598
+ sceneSaveUrl,
11599
+ sceneConfigId,
11600
+ ownerId,
11601
+ viewType: viewParams == null ? void 0 : viewParams.type,
11291
11602
  userId: (_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id,
11292
11603
  setters: {
11293
11604
  setContextMenu,
@@ -11299,7 +11610,8 @@ function XViewScene({
11299
11610
  setDetailsNode,
11300
11611
  setDetailsLink,
11301
11612
  setSceneVersion,
11302
- setAncestryMode
11613
+ setAncestryMode,
11614
+ setQuestMode
11303
11615
  },
11304
11616
  tweenToTarget,
11305
11617
  handleVersionTimeline,
@@ -11315,8 +11627,13 @@ function XViewScene({
11315
11627
  [
11316
11628
  creationMode,
11317
11629
  versionMode,
11318
- tweenToTarget,
11630
+ questMode,
11631
+ sceneSaveUrl,
11632
+ sceneConfigId,
11633
+ ownerId,
11634
+ viewParams == null ? void 0 : viewParams.type,
11319
11635
  (_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id,
11636
+ tweenToTarget,
11320
11637
  handleVersionTimeline,
11321
11638
  save_view_data,
11322
11639
  get_single_parent_file,
@@ -11328,6 +11645,97 @@ function XViewScene({
11328
11645
  const handleStartVersioning = (nodeData) => {
11329
11646
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
11330
11647
  };
11648
+ const handleSaveQuestNode = async (context, newQuestData) => {
11649
+ const { graphDataRef, sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType, sceneConfigId: sceneConfigId2, ownerId: ownerId2 } = context;
11650
+ if (!graphDataRef.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
11651
+ const newNode = {
11652
+ id: short2.generate(),
11653
+ ...newQuestData,
11654
+ is_quest: true,
11655
+ type: ["quest", ...newQuestData.type.filter((t) => t !== "quest")]
11656
+ };
11657
+ if (!graphDataRef.current[sceneConfigId2]) {
11658
+ graphDataRef.current[sceneConfigId2] = { nodes: [], links: [] };
11659
+ }
11660
+ graphDataRef.current[sceneConfigId2].nodes.push(newNode);
11661
+ const sceneFileData = {
11662
+ parent_dbs: sceneDataRef2.current.parent_dbs,
11663
+ nodes: sceneDataRef2.current.nodes,
11664
+ // <-- Mantém o cenário inicial inalterado
11665
+ links: sceneDataRef2.current.links,
11666
+ // <-- Mantém o cenário inicial inalterado
11667
+ quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
11668
+ quest_links: graphDataRef.current[sceneConfigId2].links
11669
+ };
11670
+ try {
11671
+ await actions.save_view_data(sceneSaveUrl2, sceneFileData);
11672
+ stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
11673
+ parentFileId: sceneConfigId2,
11674
+ ownerId: ownerId2,
11675
+ datasetName: "Quests Internas (View)"
11676
+ });
11677
+ const basePosition = stateRef2.current.controls.target.clone();
11678
+ const offset = new THREE3.Vector3((Math.random() - 0.5) * 15, (Math.random() - 0.5) * 5, 0);
11679
+ const finalPosition = basePosition.add(offset);
11680
+ addStandaloneNodeToScene(stateRef2.current, newNode, finalPosition);
11681
+ context.tweenToTarget(finalPosition, 1.2);
11682
+ setters.setQuestMode({ isActive: false });
11683
+ setters.setSceneVersion((v) => v + 1);
11684
+ } catch (error) {
11685
+ console.error("Falha ao salvar Quest na View:", error);
11686
+ alert("Ocorreu um erro ao criar a Quest.");
11687
+ }
11688
+ };
11689
+ userActionHandlers.handleCompleteConnection = async (context, targetNodeData) => {
11690
+ const { stateRef: stateRef2, graphDataRef, sceneDataRef: sceneDataRef2, sceneConfigId: sceneConfigId2, sceneSaveUrl: sceneSaveUrl2, ownerId: ownerId2 } = context;
11691
+ const { sourceNodeData } = stateRef2.current.connection;
11692
+ if (!graphDataRef.current || !sceneDataRef2.current || !sourceNodeData || !targetNodeData) {
11693
+ userActionHandlers.handleCancelConnection(context);
11694
+ return;
11695
+ }
11696
+ const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, sourceNodeData.id, sceneConfigId2, ownerId2);
11697
+ const targetParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, targetNodeData.id, sceneConfigId2, ownerId2);
11698
+ let parentInfoToSave = sourceParentInfo;
11699
+ if (sourceParentInfo.parentFileId === sceneConfigId2 && targetParentInfo.parentFileId !== sceneConfigId2) {
11700
+ parentInfoToSave = targetParentInfo;
11701
+ } else if (targetParentInfo.parentFileId === sceneConfigId2 && sourceParentInfo.parentFileId !== sceneConfigId2) {
11702
+ parentInfoToSave = sourceParentInfo;
11703
+ }
11704
+ const { parentFileId: parentFileIdToSave, ownerId: ownerIdToSave } = parentInfoToSave;
11705
+ const newLink = {
11706
+ id: `link_${short2.generate()}`,
11707
+ source: sourceNodeData.id,
11708
+ target: targetNodeData.id
11709
+ };
11710
+ try {
11711
+ if (parentFileIdToSave === sceneConfigId2) {
11712
+ const specificParentData = graphDataRef.current[sceneConfigId2];
11713
+ specificParentData.links.push(newLink);
11714
+ const viewFilePayload = {
11715
+ parent_dbs: sceneDataRef2.current.parent_dbs,
11716
+ nodes: sceneDataRef2.current.nodes,
11717
+ // <-- Usa o estado original intocado
11718
+ links: sceneDataRef2.current.links,
11719
+ // <-- Usa o estado original intocado
11720
+ quest_nodes: specificParentData.nodes,
11721
+ quest_links: specificParentData.links
11722
+ // Salva a conexão aqui!
11723
+ };
11724
+ await context.actions.save_view_data(sceneSaveUrl2, viewFilePayload);
11725
+ } else {
11726
+ const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
11727
+ specificParentData.links.push(newLink);
11728
+ const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
11729
+ await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
11730
+ graphDataRef.current[parentFileIdToSave] = specificParentData;
11731
+ }
11732
+ addNewLinkToScene(stateRef2.current, newLink);
11733
+ } catch (error) {
11734
+ console.error("Falha ao salvar a nova conex\xE3o:", error);
11735
+ alert("Ocorreu um erro ao salvar a nova conex\xE3o.");
11736
+ }
11737
+ userActionHandlers.handleCancelConnection(context);
11738
+ };
11331
11739
  const handleClearAncestryVisuals = useCallback4((ancestryId) => {
11332
11740
  const { renderedAncestries, ancestryGroup } = stateRef.current;
11333
11741
  const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
@@ -12595,6 +13003,7 @@ function XViewScene({
12595
13003
  [actionHandlerContext]
12596
13004
  );
12597
13005
  const handleSaveCurrentView = useCallback4(async () => {
13006
+ var _a2, _b2, _c2;
12598
13007
  const { nodeObjects, allLinks } = stateRef.current;
12599
13008
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
12600
13009
  console.warn("N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente.");
@@ -12616,17 +13025,22 @@ function XViewScene({
12616
13025
  const { sourceNode, targetNode, ...serializableLinkData } = line.userData;
12617
13026
  return serializableLinkData;
12618
13027
  });
13028
+ sceneDataRef.current.nodes = currentNodes;
13029
+ sceneDataRef.current.links = currentLinks;
13030
+ const isView = ((_a2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _a2.toLowerCase()) === "view";
12619
13031
  const sceneFileData = {
12620
13032
  parent_dbs: sceneDataRef.current.parent_dbs,
12621
13033
  nodes: currentNodes,
12622
- links: currentLinks
13034
+ links: currentLinks,
13035
+ quest_nodes: isView ? ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || [] : sceneDataRef.current.quest_nodes || [],
13036
+ quest_links: isView ? ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || [] : sceneDataRef.current.quest_links || []
12623
13037
  };
12624
13038
  try {
12625
13039
  await save_view_data(sceneSaveUrl, sceneFileData);
12626
13040
  } catch (error) {
12627
13041
  console.error("Erro na chamada de save_view_data:", error);
12628
13042
  }
12629
- }, [sceneSaveUrl, save_view_data]);
13043
+ }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
12630
13044
  const allAvailableNodes = useMemo12(() => {
12631
13045
  if (!parentDataRef.current) return [];
12632
13046
  return Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
@@ -12712,20 +13126,20 @@ function XViewScene({
12712
13126
  }
12713
13127
  }, [isInitialized, sceneVersion, focusAncestryId, hasOpenedInitialAncestry, handleStartReadingAncestry]);
12714
13128
  if (isLoading || status === "loading" || permissionStatus === "loading") {
12715
- return /* @__PURE__ */ React23.createElement(LoadingScreen, null);
13129
+ return /* @__PURE__ */ React24.createElement(LoadingScreen, null);
12716
13130
  }
12717
13131
  if (permissionStatus === "denied") {
12718
- return /* @__PURE__ */ React23.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ React23.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ React23.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ React23.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", className: "w-16 h-16 mx-auto" }, /* @__PURE__ */ React23.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" }))), /* @__PURE__ */ React23.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ React23.createElement("p", { className: "text-slate-400 mb-6" }, "Voc\xEA n\xE3o tem permiss\xE3o para acessar este conte\xFAdo. Solicite acesso ao propriet\xE1rio ou verifique se est\xE1 na conta correta."), /* @__PURE__ */ React23.createElement(
13132
+ return /* @__PURE__ */ React24.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ React24.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ React24.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ React24.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", className: "w-16 h-16 mx-auto" }, /* @__PURE__ */ React24.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" }))), /* @__PURE__ */ React24.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ React24.createElement("p", { className: "text-slate-400 mb-6" }, "Voc\xEA n\xE3o tem permiss\xE3o para acessar este conte\xFAdo. Solicite acesso ao propriet\xE1rio ou verifique se est\xE1 na conta correta."), /* @__PURE__ */ React24.createElement(
12719
13133
  "button",
12720
13134
  {
12721
13135
  onClick: () => router.push("/dashboard/scenes"),
12722
13136
  className: "flex items-center justify-center gap-2 w-full py-3 px-4 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors font-medium"
12723
13137
  },
12724
- /* @__PURE__ */ React23.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", className: "w-5 h-5" }, /* @__PURE__ */ React23.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" })),
13138
+ /* @__PURE__ */ React24.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", className: "w-5 h-5" }, /* @__PURE__ */ React24.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" })),
12725
13139
  "Voltar para Scenes"
12726
13140
  )));
12727
13141
  }
12728
- return /* @__PURE__ */ React23.createElement(
13142
+ return /* @__PURE__ */ React24.createElement(
12729
13143
  "div",
12730
13144
  {
12731
13145
  ref: mountRef,
@@ -12737,7 +13151,7 @@ function XViewScene({
12737
13151
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
12738
13152
  }
12739
13153
  },
12740
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ React23.createElement(
13154
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ React24.createElement(
12741
13155
  XViewSidebar,
12742
13156
  {
12743
13157
  dbNodes: searchableDbNodes,
@@ -12757,7 +13171,7 @@ function XViewScene({
12757
13171
  userRole: userPermissionRole
12758
13172
  }
12759
13173
  ),
12760
- creationMode.isActive && /* @__PURE__ */ React23.createElement(
13174
+ creationMode.isActive && /* @__PURE__ */ React24.createElement(
12761
13175
  InSceneCreationForm,
12762
13176
  {
12763
13177
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -12782,7 +13196,7 @@ function XViewScene({
12782
13196
  availableAncestries: allAvailableAncestries
12783
13197
  }
12784
13198
  ),
12785
- versionMode.isActive && /* @__PURE__ */ React23.createElement(
13199
+ versionMode.isActive && /* @__PURE__ */ React24.createElement(
12786
13200
  InSceneVersionForm,
12787
13201
  {
12788
13202
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -12801,13 +13215,27 @@ function XViewScene({
12801
13215
  availableAncestries: allAvailableAncestries
12802
13216
  }
12803
13217
  ),
12804
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React23.createElement(
13218
+ questMode.isActive && /* @__PURE__ */ React24.createElement(
13219
+ InSceneQuestForm,
13220
+ {
13221
+ onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
13222
+ onCancel: () => setQuestMode({ isActive: false }),
13223
+ style: { position: "absolute", left: `16px`, top: `16px`, zIndex: 20, transition: "opacity 200ms ease-out" },
13224
+ refEl: formRef,
13225
+ onOpenImageViewer: handleOpenImageViewer,
13226
+ onMentionClick: handleAddExistingNode,
13227
+ onUploadFile: upload_file_action,
13228
+ availableNodes: allAvailableNodes,
13229
+ availableAncestries: allAvailableAncestries
13230
+ }
13231
+ ),
13232
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React24.createElement(
12805
13233
  "div",
12806
13234
  {
12807
13235
  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"}`,
12808
13236
  style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${readModeWidth}px`, maxWidth: "92vw" }
12809
13237
  },
12810
- /* @__PURE__ */ React23.createElement(
13238
+ /* @__PURE__ */ React24.createElement(
12811
13239
  "div",
12812
13240
  {
12813
13241
  onPointerDown: (e) => {
@@ -12818,7 +13246,7 @@ function XViewScene({
12818
13246
  title: "Arraste para redimensionar"
12819
13247
  }
12820
13248
  ),
12821
- /* @__PURE__ */ React23.createElement(
13249
+ /* @__PURE__ */ React24.createElement(
12822
13250
  DescriptionReadModePanel,
12823
13251
  {
12824
13252
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -12853,7 +13281,7 @@ function XViewScene({
12853
13281
  }
12854
13282
  )
12855
13283
  ),
12856
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React23.createElement(
13284
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React24.createElement(
12857
13285
  CreateAncestryPanel,
12858
13286
  {
12859
13287
  ancestryMode,
@@ -12880,7 +13308,7 @@ function XViewScene({
12880
13308
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
12881
13309
  }
12882
13310
  ),
12883
- editingAncestryRel.visible && /* @__PURE__ */ React23.createElement(
13311
+ editingAncestryRel.visible && /* @__PURE__ */ React24.createElement(
12884
13312
  AncestryRelationshipPanel,
12885
13313
  {
12886
13314
  data: editingAncestryRel.data,
@@ -12894,7 +13322,7 @@ function XViewScene({
12894
13322
  onUploadFile: upload_file_action
12895
13323
  }
12896
13324
  ),
12897
- detailsNode && /* @__PURE__ */ React23.createElement(
13325
+ detailsNode && /* @__PURE__ */ React24.createElement(
12898
13326
  NodeDetailsPanel,
12899
13327
  {
12900
13328
  node: detailsNode,
@@ -12921,7 +13349,7 @@ function XViewScene({
12921
13349
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
12922
13350
  }
12923
13351
  ),
12924
- detailsLink && /* @__PURE__ */ React23.createElement(
13352
+ detailsLink && /* @__PURE__ */ React24.createElement(
12925
13353
  RelationshipDetailsPanel,
12926
13354
  {
12927
13355
  link: detailsLink,
@@ -12935,7 +13363,7 @@ function XViewScene({
12935
13363
  userRole: userPermissionRole
12936
13364
  }
12937
13365
  ),
12938
- ancestryLinkDetails && /* @__PURE__ */ React23.createElement(
13366
+ ancestryLinkDetails && /* @__PURE__ */ React24.createElement(
12939
13367
  AncestryLinkDetailsPanel,
12940
13368
  {
12941
13369
  data: ancestryLinkDetails,
@@ -12946,7 +13374,7 @@ function XViewScene({
12946
13374
  onUploadFile: upload_file_action
12947
13375
  }
12948
13376
  ),
12949
- /* @__PURE__ */ React23.createElement(
13377
+ /* @__PURE__ */ React24.createElement(
12950
13378
  "div",
12951
13379
  {
12952
13380
  ref: tooltipRef,
@@ -12973,7 +13401,7 @@ function XViewScene({
12973
13401
  }
12974
13402
  }
12975
13403
  ),
12976
- /* @__PURE__ */ React23.createElement(
13404
+ /* @__PURE__ */ React24.createElement(
12977
13405
  ContextMenu,
12978
13406
  {
12979
13407
  data: contextMenu,
@@ -12996,7 +13424,7 @@ function XViewScene({
12996
13424
  onFocusNode: handleFocusNode
12997
13425
  }
12998
13426
  ),
12999
- /* @__PURE__ */ React23.createElement(
13427
+ /* @__PURE__ */ React24.createElement(
13000
13428
  MultiNodeContextMenu,
13001
13429
  {
13002
13430
  data: multiContextMenu,
@@ -13007,7 +13435,7 @@ function XViewScene({
13007
13435
  onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(actionHandlerContext, ids)
13008
13436
  }
13009
13437
  ),
13010
- /* @__PURE__ */ React23.createElement(
13438
+ /* @__PURE__ */ React24.createElement(
13011
13439
  RelationshipContextMenu,
13012
13440
  {
13013
13441
  data: relationshipMenu,
@@ -13025,8 +13453,8 @@ function XViewScene({
13025
13453
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
13026
13454
  }
13027
13455
  ),
13028
- /* @__PURE__ */ React23.createElement(ImageViewer, { data: imageViewer, onClose: () => setImageViewer({ ...imageViewer, visible: false }) }),
13029
- /* @__PURE__ */ React23.createElement(
13456
+ /* @__PURE__ */ React24.createElement(ImageViewer, { data: imageViewer, onClose: () => setImageViewer({ ...imageViewer, visible: false }) }),
13457
+ /* @__PURE__ */ React24.createElement(
13030
13458
  AncestryBoard,
13031
13459
  {
13032
13460
  isOpen: isAncestryBoardOpen,
@@ -13039,7 +13467,7 @@ function XViewScene({
13039
13467
  userRole: userPermissionRole
13040
13468
  }
13041
13469
  ),
13042
- /* @__PURE__ */ React23.createElement(
13470
+ /* @__PURE__ */ React24.createElement(
13043
13471
  ImportParentFileModal,
13044
13472
  {
13045
13473
  isOpen: isImportModalOpen,
@@ -13083,6 +13511,12 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
13083
13511
  }
13084
13512
  const sceneData = sceneResponse.data;
13085
13513
  const parentDbObjects = sceneData.parent_dbs || [];
13514
+ if (type && type.toLowerCase().includes("database")) {
13515
+ const selfExists = parentDbObjects.some((db) => String(db.db_id) === String(scene_config));
13516
+ if (!selfExists) {
13517
+ parentDbObjects.push({ db_id: scene_config, owner_id });
13518
+ }
13519
+ }
13086
13520
  const parentResponsesPromises = parentDbObjects.map(
13087
13521
  (db_info) => db_services.get_file(`x_view_dbs/${db_info.owner_id}/${db_info.db_id}`)
13088
13522
  );
@@ -13100,11 +13534,28 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
13100
13534
  );
13101
13535
  }
13102
13536
  }
13537
+ if (type && type.toLowerCase() === "view") {
13538
+ parentData[scene_config] = {
13539
+ dataset_name: "Quests Internas (View)",
13540
+ nodes: sceneData.quest_nodes || [],
13541
+ links: sceneData.quest_links || []
13542
+ };
13543
+ }
13103
13544
  const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
13104
13545
  const allLinks = Object.values(parentData).flatMap((db) => db.links || []);
13105
13546
  const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
13106
13547
  const parentLinkMap = new Map(allLinks.map((link) => [`${link.source}-${link.target}`, link]));
13107
- const validatedNodes = (sceneData.nodes || []).map((sceneNode) => parentNodeMap.get(String(sceneNode.id))).filter(Boolean);
13548
+ const validatedNodes = (sceneData.nodes || []).map((sceneNode) => {
13549
+ const nodeTypes = Array.isArray(sceneNode.type) ? sceneNode.type : [sceneNode.type];
13550
+ if (nodeTypes.includes("quest")) {
13551
+ return sceneNode;
13552
+ }
13553
+ const dbNode = parentNodeMap.get(String(sceneNode.id));
13554
+ if (dbNode) {
13555
+ return { ...dbNode, ...sceneNode };
13556
+ }
13557
+ return null;
13558
+ }).filter(Boolean);
13108
13559
  const validNodeIdsInScene = new Set(validatedNodes.map((node) => String(node.id)));
13109
13560
  const validatedLinks = (sceneData.links || []).filter((sceneLink) => {
13110
13561
  const linkExistsInParent = parentLinkMap.has(`${sceneLink.source}-${sceneLink.target}`);