@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.js CHANGED
@@ -43,9 +43,9 @@ __export(index_exports, {
43
43
  module.exports = __toCommonJS(index_exports);
44
44
 
45
45
  // src/XViewScene.jsx
46
- var import_react24 = __toESM(require("react"));
46
+ var import_react25 = __toESM(require("react"));
47
47
  var import_navigation = require("next/navigation");
48
- var import_react25 = require("next-auth/react");
48
+ var import_react26 = require("next-auth/react");
49
49
  var import_crypto_js = __toESM(require("crypto-js"));
50
50
  var THREE3 = __toESM(require("three"));
51
51
  var import_OrbitControls = require("three/examples/jsm/controls/OrbitControls.js");
@@ -948,7 +948,7 @@ var createNodeMesh = (nodeData, position, glowTexture) => {
948
948
  if (useImage && nodeData.textureImageUrl) {
949
949
  geometry = new THREE.CircleGeometry(1.5, 48);
950
950
  const texture = getTexture(nodeData.textureImageUrl);
951
- material = new THREE.MeshBasicMaterial({
951
+ material = new MeshBasicMaterial({
952
952
  map: texture,
953
953
  color: 16777215,
954
954
  side: THREE.DoubleSide,
@@ -1559,7 +1559,7 @@ var addStandaloneNodeToScene = (state, nodeData, position) => {
1559
1559
  scaleTween.start();
1560
1560
  }
1561
1561
  };
1562
- var getParentFileInfoForNode = (allParentData, sceneData, nodeId) => {
1562
+ var getParentFileInfoForNode = (allParentData, sceneData, nodeId, sceneConfigId = null, sceneOwnerId = null) => {
1563
1563
  const parentDbsArray = (sceneData == null ? void 0 : sceneData.parent_dbs) || [];
1564
1564
  for (const parentFileId in allParentData) {
1565
1565
  if (allParentData.hasOwnProperty(parentFileId)) {
@@ -1568,6 +1568,8 @@ var getParentFileInfoForNode = (allParentData, sceneData, nodeId) => {
1568
1568
  const parentDbInfo = parentDbsArray.find((db) => String(db.db_id) === String(parentFileId));
1569
1569
  if (parentDbInfo) {
1570
1570
  return { parentFileId, ownerId: parentDbInfo.owner_id };
1571
+ } else if (sceneConfigId && String(parentFileId) === String(sceneConfigId)) {
1572
+ return { parentFileId, ownerId: sceneOwnerId };
1571
1573
  } else {
1572
1574
  console.warn(`Owner ID n\xE3o encontrado em sceneData.parent_dbs para o parentFileId: ${parentFileId}`);
1573
1575
  return { parentFileId, ownerId: null };
@@ -1837,6 +1839,7 @@ var userActionHandlers = {
1837
1839
  setters.setFormPosition((p) => ({ ...p, opacity: 0 }));
1838
1840
  },
1839
1841
  handleSaveVersionNode: async (context, newNodeData) => {
1842
+ var _a;
1840
1843
  const { graphDataRef, sceneDataRef, stateRef, versionMode, setters } = context;
1841
1844
  if (!graphDataRef.current || !sceneDataRef.current) return;
1842
1845
  const { sourceNodeData } = versionMode;
@@ -1846,7 +1849,7 @@ var userActionHandlers = {
1846
1849
  version_node: { is_version: true, parent_node: sourceNodeData.id }
1847
1850
  };
1848
1851
  const newLink = { id: `link_${import_short_uuid.default.generate()}`, source: sourceNodeData.id, target: newNode.id };
1849
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id);
1852
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id, context.sceneConfigId, context.ownerId);
1850
1853
  if (!parentInfo || !parentInfo.ownerId) {
1851
1854
  console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node de origem:", sourceNodeData.id);
1852
1855
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio.");
@@ -1856,9 +1859,21 @@ var userActionHandlers = {
1856
1859
  const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileId]));
1857
1860
  specificParentData.nodes.push(newNode);
1858
1861
  specificParentData.links.push(newLink);
1859
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
1860
1862
  try {
1861
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
1863
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
1864
+ if (isView && parentFileId === context.sceneConfigId) {
1865
+ const viewFilePayload = {
1866
+ parent_dbs: sceneDataRef.current.parent_dbs,
1867
+ nodes: sceneDataRef.current.nodes,
1868
+ links: sceneDataRef.current.links,
1869
+ quest_nodes: specificParentData.nodes,
1870
+ quest_links: specificParentData.links
1871
+ };
1872
+ await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
1873
+ } else {
1874
+ const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
1875
+ await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
1876
+ }
1862
1877
  graphDataRef.current[parentFileId] = specificParentData;
1863
1878
  const finalPosition = stateRef.current.ghostElements.node.position.clone();
1864
1879
  addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
@@ -2015,6 +2030,7 @@ var userActionHandlers = {
2015
2030
  if (mountRef.current) mountRef.current.style.cursor = "grab";
2016
2031
  },
2017
2032
  handleCompleteConnection: async (context, targetNodeData) => {
2033
+ var _a;
2018
2034
  const { stateRef, graphDataRef, sceneDataRef } = context;
2019
2035
  const { sourceNodeData } = stateRef.current.connection;
2020
2036
  if (!graphDataRef.current || !sceneDataRef.current || !sourceNodeData || !targetNodeData) {
@@ -2022,7 +2038,7 @@ var userActionHandlers = {
2022
2038
  userActionHandlers.handleCancelConnection(context);
2023
2039
  return;
2024
2040
  }
2025
- const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id);
2041
+ const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id, context.sceneConfigId, context.ownerId);
2026
2042
  if (!sourceParentInfo || !sourceParentInfo.ownerId) {
2027
2043
  console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node de origem:", sourceNodeData.id);
2028
2044
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio.");
@@ -2037,12 +2053,26 @@ var userActionHandlers = {
2037
2053
  source: sourceNodeData.id,
2038
2054
  target: targetNodeData.id
2039
2055
  };
2040
- const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
2041
- specificParentData.links.push(newLink);
2042
- const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
2043
2056
  try {
2044
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2045
- graphDataRef.current[parentFileIdToSave] = specificParentData;
2057
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2058
+ if (isView && parentFileIdToSave === context.sceneConfigId) {
2059
+ const specificParentData = graphDataRef.current[context.sceneConfigId];
2060
+ specificParentData.links.push(newLink);
2061
+ const viewFilePayload = {
2062
+ parent_dbs: sceneDataRef.current.parent_dbs,
2063
+ nodes: sceneDataRef.current.nodes,
2064
+ links: sceneDataRef.current.links,
2065
+ quest_nodes: specificParentData.nodes,
2066
+ quest_links: specificParentData.links
2067
+ };
2068
+ await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
2069
+ } else {
2070
+ const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
2071
+ specificParentData.links.push(newLink);
2072
+ const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
2073
+ await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2074
+ graphDataRef.current[parentFileIdToSave] = specificParentData;
2075
+ }
2046
2076
  addNewLinkToScene(stateRef.current, newLink);
2047
2077
  } catch (error) {
2048
2078
  console.error("Falha ao salvar a nova conex\xE3o:", error);
@@ -2111,8 +2141,8 @@ var userActionHandlers = {
2111
2141
  } else {
2112
2142
  newTargetId = newEndNodeData.id;
2113
2143
  }
2114
- const originalParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldSourceId);
2115
- const newParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newSourceId);
2144
+ const originalParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldSourceId, context.sceneConfigId, context.ownerId);
2145
+ const newParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newSourceId, context.sceneConfigId, context.ownerId);
2116
2146
  if (!originalParentInfo || !newParentInfo || !originalParentInfo.ownerId || !newParentInfo.ownerId) {
2117
2147
  console.error("N\xE3o foi poss\xEDvel encontrar informa\xE7\xF5es dos arquivos pai para o relink.");
2118
2148
  alert("Ocorreu um erro ao identificar os arquivos pai para salvar a altera\xE7\xE3o.");
@@ -2126,6 +2156,22 @@ var userActionHandlers = {
2126
2156
  target: newTargetId,
2127
2157
  id: linkId
2128
2158
  };
2159
+ const saveParentData = async (fileId, fileOwnerId, data) => {
2160
+ var _a;
2161
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2162
+ if (isView && fileId === context.sceneConfigId) {
2163
+ const viewFilePayload = {
2164
+ parent_dbs: sceneDataRef.current.parent_dbs,
2165
+ nodes: sceneDataRef.current.nodes,
2166
+ links: sceneDataRef.current.links,
2167
+ quest_nodes: data.nodes,
2168
+ quest_links: data.links
2169
+ };
2170
+ return context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
2171
+ } else {
2172
+ return context.actions.save_view_data(`x_view_dbs/${fileOwnerId}/${fileId}`, data);
2173
+ }
2174
+ };
2129
2175
  const savePromises = [];
2130
2176
  const filesToUpdate = {};
2131
2177
  if (originalParentInfo.parentFileId !== newParentInfo.parentFileId) {
@@ -2134,16 +2180,12 @@ var userActionHandlers = {
2134
2180
  (l) => String(l.id) !== String(linkId)
2135
2181
  );
2136
2182
  filesToUpdate[originalParentInfo.parentFileId] = updatedOriginalParentData;
2137
- savePromises.push(
2138
- context.actions.save_view_data(`x_view_dbs/${originalParentInfo.ownerId}/${originalParentInfo.parentFileId}`, updatedOriginalParentData)
2139
- );
2183
+ savePromises.push(saveParentData(originalParentInfo.parentFileId, originalParentInfo.ownerId, updatedOriginalParentData));
2140
2184
  const updatedNewParentData = JSON.parse(JSON.stringify(graphDataRef.current[newParentInfo.parentFileId]));
2141
2185
  if (!updatedNewParentData.links) updatedNewParentData.links = [];
2142
2186
  updatedNewParentData.links.push(newLinkData);
2143
2187
  filesToUpdate[newParentInfo.parentFileId] = updatedNewParentData;
2144
- savePromises.push(
2145
- context.actions.save_view_data(`x_view_dbs/${newParentInfo.ownerId}/${newParentInfo.parentFileId}`, updatedNewParentData)
2146
- );
2188
+ savePromises.push(saveParentData(newParentInfo.parentFileId, newParentInfo.ownerId, updatedNewParentData));
2147
2189
  } else {
2148
2190
  const updatedParentData = JSON.parse(JSON.stringify(graphDataRef.current[originalParentInfo.parentFileId]));
2149
2191
  updatedParentData.links = updatedParentData.links.filter(
@@ -2151,9 +2193,7 @@ var userActionHandlers = {
2151
2193
  );
2152
2194
  updatedParentData.links.push(newLinkData);
2153
2195
  filesToUpdate[originalParentInfo.parentFileId] = updatedParentData;
2154
- savePromises.push(
2155
- context.actions.save_view_data(`x_view_dbs/${originalParentInfo.ownerId}/${originalParentInfo.parentFileId}`, updatedParentData)
2156
- );
2196
+ savePromises.push(saveParentData(originalParentInfo.parentFileId, originalParentInfo.ownerId, updatedParentData));
2157
2197
  }
2158
2198
  try {
2159
2199
  await Promise.all(savePromises);
@@ -2171,7 +2211,7 @@ var userActionHandlers = {
2171
2211
  }
2172
2212
  },
2173
2213
  handleDeleteLink: async (context, linkObject) => {
2174
- var _a, _b, _c, _d, _e, _f;
2214
+ var _a, _b, _c, _d, _e, _f, _g;
2175
2215
  const { stateRef, graphDataRef, sceneDataRef, setters } = context;
2176
2216
  setters.setRelationshipMenu({ visible: false });
2177
2217
  if (!(linkObject == null ? void 0 : linkObject.userData) || !graphDataRef.current || !sceneDataRef.current) return;
@@ -2180,7 +2220,7 @@ var userActionHandlers = {
2180
2220
  console.error("Tentativa de deletar um link sem ID.", linkObject.userData);
2181
2221
  return;
2182
2222
  }
2183
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkObject.userData.source);
2223
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkObject.userData.source, context.sceneConfigId, context.ownerId);
2184
2224
  if (!parentInfo || !parentInfo.ownerId) {
2185
2225
  console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o link:", linkIdToDelete);
2186
2226
  alert("Ocorreu um erro ao identificar o arquivo pai da rela\xE7\xE3o para exclus\xE3o.");
@@ -2192,9 +2232,25 @@ var userActionHandlers = {
2192
2232
  const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileId]));
2193
2233
  const newLinks = (specificParentData.links || []).filter((l) => String(l.id) !== String(linkIdToDelete));
2194
2234
  specificParentData.links = newLinks;
2195
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2235
+ let filenameToSave;
2236
+ let payloadToSave;
2237
+ const isView = ((_g = context.viewType) == null ? void 0 : _g.toLowerCase()) === "view";
2238
+ if (isView && parentFileId === context.sceneConfigId) {
2239
+ filenameToSave = context.sceneSaveUrl;
2240
+ sceneDataRef.current.links = sceneDataRef.current.links.filter((l) => String(l.id) !== String(linkIdToDelete));
2241
+ payloadToSave = {
2242
+ parent_dbs: sceneDataRef.current.parent_dbs,
2243
+ nodes: sceneDataRef.current.nodes,
2244
+ links: sceneDataRef.current.links,
2245
+ quest_nodes: specificParentData.nodes,
2246
+ quest_links: specificParentData.links
2247
+ };
2248
+ } else {
2249
+ filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2250
+ payloadToSave = specificParentData;
2251
+ }
2196
2252
  try {
2197
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2253
+ await context.actions.save_view_data(filenameToSave, payloadToSave);
2198
2254
  graphDataRef.current[parentFileId] = specificParentData;
2199
2255
  setters.setDetailsLink((prev) => String(prev == null ? void 0 : prev.id) === String(linkIdToDelete) ? null : prev);
2200
2256
  if (stateRef.current.hoveredLink === linkObject) {
@@ -2339,6 +2395,7 @@ var userActionHandlers = {
2339
2395
  stateRef.current.selectedNodes.clear();
2340
2396
  },
2341
2397
  handleDeleteMultipleNodes: async (context, nodeIds) => {
2398
+ var _a;
2342
2399
  const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
2343
2400
  setters.setMultiContextMenu({ visible: false });
2344
2401
  if (!nodeIds || nodeIds.size === 0 || !graphDataRef.current || !sceneDataRef.current) return;
@@ -2357,7 +2414,7 @@ var userActionHandlers = {
2357
2414
  }
2358
2415
  const changesByParentFile = {};
2359
2416
  for (const nodeId of strNodeIdsToDelete) {
2360
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeId);
2417
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeId, context.sceneConfigId, context.ownerId);
2361
2418
  if (!parentInfo || !parentInfo.ownerId) {
2362
2419
  console.warn(`Node com ID ${nodeId} n\xE3o encontrado ou sem ownerId. Ignorando.`);
2363
2420
  continue;
@@ -2391,8 +2448,27 @@ var userActionHandlers = {
2391
2448
  originalData.links = (originalData.links || []).filter(
2392
2449
  (l) => !linksToDelete.has(String(l.id))
2393
2450
  );
2394
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2395
- savePromises.push(context.actions.save_view_data(filenameForSpecificParent, originalData));
2451
+ let filenameToSave;
2452
+ let payloadToSave;
2453
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2454
+ if (isView && parentFileId === context.sceneConfigId) {
2455
+ filenameToSave = context.sceneSaveUrl;
2456
+ const strNodesToDelete = Array.from(nodesToDelete).map(String);
2457
+ const strLinksToDelete = Array.from(linksToDelete).map(String);
2458
+ sceneDataRef.current.nodes = sceneDataRef.current.nodes.filter((n) => !strNodesToDelete.includes(String(n.id)));
2459
+ sceneDataRef.current.links = sceneDataRef.current.links.filter((l) => !strLinksToDelete.includes(String(l.id)));
2460
+ payloadToSave = {
2461
+ parent_dbs: sceneDataRef.current.parent_dbs,
2462
+ nodes: sceneDataRef.current.nodes,
2463
+ links: sceneDataRef.current.links,
2464
+ quest_nodes: originalData.nodes,
2465
+ quest_links: originalData.links
2466
+ };
2467
+ } else {
2468
+ filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2469
+ payloadToSave = originalData;
2470
+ }
2471
+ savePromises.push(context.actions.save_view_data(filenameToSave, payloadToSave));
2396
2472
  updatedParentDataCache[parentFileId] = originalData;
2397
2473
  }
2398
2474
  }
@@ -2413,6 +2489,7 @@ var userActionHandlers = {
2413
2489
  }
2414
2490
  },
2415
2491
  handleDeleteNode: async (context, nodeData) => {
2492
+ var _a;
2416
2493
  const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
2417
2494
  if (actions.delete_file && nodeData) {
2418
2495
  const urls = extractFileUrlsFromProperties(nodeData);
@@ -2424,7 +2501,7 @@ var userActionHandlers = {
2424
2501
  if (!nodeData || !graphDataRef.current || !sceneDataRef.current) return;
2425
2502
  const nodeIdToDelete = nodeData.id;
2426
2503
  const strNodeId = String(nodeIdToDelete);
2427
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeIdToDelete);
2504
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeIdToDelete, context.sceneConfigId, context.ownerId);
2428
2505
  if (!parentInfo || !parentInfo.ownerId) {
2429
2506
  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);
2430
2507
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para exclus\xE3o.");
@@ -2436,9 +2513,28 @@ var userActionHandlers = {
2436
2513
  const newLinks = (specificParentData.links || []).filter((l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId);
2437
2514
  specificParentData.nodes = newNodes;
2438
2515
  specificParentData.links = newLinks;
2439
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2516
+ let filenameToSave;
2517
+ let payloadToSave;
2518
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2519
+ if (isView && parentFileId === context.sceneConfigId) {
2520
+ filenameToSave = context.sceneSaveUrl;
2521
+ const newVisualNodes = sceneDataRef.current.nodes.filter((n) => String(n.id) !== strNodeId);
2522
+ const newVisualLinks = sceneDataRef.current.links.filter((l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId);
2523
+ sceneDataRef.current.nodes = newVisualNodes;
2524
+ sceneDataRef.current.links = newVisualLinks;
2525
+ payloadToSave = {
2526
+ parent_dbs: sceneDataRef.current.parent_dbs,
2527
+ nodes: newVisualNodes,
2528
+ links: newVisualLinks,
2529
+ quest_nodes: specificParentData.nodes,
2530
+ quest_links: specificParentData.links
2531
+ };
2532
+ } else {
2533
+ filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2534
+ payloadToSave = specificParentData;
2535
+ }
2440
2536
  try {
2441
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2537
+ await context.actions.save_view_data(filenameToSave, payloadToSave);
2442
2538
  graphDataRef.current[parentFileId] = specificParentData;
2443
2539
  setters.setDetailsNode((prev) => String(prev == null ? void 0 : prev.id) === String(nodeIdToDelete) ? null : prev);
2444
2540
  removeNodeFromScene(stateRef.current, nodeIdToDelete);
@@ -2449,10 +2545,11 @@ var userActionHandlers = {
2449
2545
  }
2450
2546
  },
2451
2547
  handleSaveNodeDetails: async (context, updatedNode, keepOpen = false) => {
2548
+ var _a;
2452
2549
  const { graphDataRef, sceneDataRef, stateRef, setters } = context;
2453
2550
  if (!graphDataRef.current || !sceneDataRef.current) return;
2454
2551
  const { _baseEmissiveIntensity: ignored, ...nodeToSave } = updatedNode;
2455
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeToSave.id);
2552
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeToSave.id, context.sceneConfigId, context.ownerId);
2456
2553
  if (!parentInfo || !parentInfo.ownerId) {
2457
2554
  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);
2458
2555
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para atualiza\xE7\xE3o.");
@@ -2468,9 +2565,21 @@ var userActionHandlers = {
2468
2565
  alert("Erro interno: Node n\xE3o encontrado para salvar.");
2469
2566
  return;
2470
2567
  }
2471
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2472
2568
  try {
2473
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2569
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2570
+ if (isView && parentFileId === context.sceneConfigId) {
2571
+ const viewFilePayload = {
2572
+ parent_dbs: sceneDataRef.current.parent_dbs,
2573
+ nodes: sceneDataRef.current.nodes,
2574
+ links: sceneDataRef.current.links,
2575
+ quest_nodes: specificParentData.nodes,
2576
+ quest_links: specificParentData.links
2577
+ };
2578
+ await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
2579
+ } else {
2580
+ const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2581
+ await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2582
+ }
2474
2583
  graphDataRef.current[parentFileId] = specificParentData;
2475
2584
  updateExistingNodeVisuals(stateRef.current, nodeToSave);
2476
2585
  setters.setSceneVersion((v) => v + 1);
@@ -2483,10 +2592,11 @@ var userActionHandlers = {
2483
2592
  }
2484
2593
  },
2485
2594
  handleSaveLinkDetails: async (context, updatedLink, keepOpen = false) => {
2595
+ var _a;
2486
2596
  const { graphDataRef, sceneDataRef, stateRef, setters } = context;
2487
2597
  if (!graphDataRef.current || !sceneDataRef.current) return;
2488
2598
  const { sourceNode, targetNode, ...linkToSave } = updatedLink;
2489
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkToSave.source);
2599
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkToSave.source, context.sceneConfigId, context.ownerId);
2490
2600
  if (!parentInfo || !parentInfo.ownerId) {
2491
2601
  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);
2492
2602
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para atualiza\xE7\xE3o.");
@@ -2502,9 +2612,21 @@ var userActionHandlers = {
2502
2612
  alert("Erro interno: link n\xE3o encontrado para salvar.");
2503
2613
  return;
2504
2614
  }
2505
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2506
2615
  try {
2507
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2616
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2617
+ if (isView && parentFileId === context.sceneConfigId) {
2618
+ const viewFilePayload = {
2619
+ parent_dbs: sceneDataRef.current.parent_dbs,
2620
+ nodes: sceneDataRef.current.nodes,
2621
+ links: sceneDataRef.current.links,
2622
+ quest_nodes: specificParentData.nodes,
2623
+ quest_links: specificParentData.links
2624
+ };
2625
+ await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
2626
+ } else {
2627
+ const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2628
+ await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2629
+ }
2508
2630
  graphDataRef.current[parentFileId] = specificParentData;
2509
2631
  const lineObject = stateRef.current.allLinks.find(
2510
2632
  (l) => String(l.userData.id) === String(linkToSave.id)
@@ -7848,9 +7970,180 @@ function InSceneVersionForm({
7848
7970
  ));
7849
7971
  }
7850
7972
 
7851
- // src/components/NodeDetailsPanel.jsx
7973
+ // src/components/InSceneQuestForm.jsx
7852
7974
  var import_react16 = __toESM(require("react"));
7853
7975
  var import_fi14 = require("react-icons/fi");
7976
+ var QUEST_STATUS_COLORS = {
7977
+ "Backlog": "#64748b",
7978
+ // Slate (Cinza azulado)
7979
+ "In Progress": "#eab308",
7980
+ // Yellow (Amarelo)
7981
+ "Review": "#a855f7",
7982
+ // Purple (Roxo)
7983
+ "Done": "#22c55e"
7984
+ // Green (Verde)
7985
+ };
7986
+ function InSceneQuestForm({
7987
+ onSave,
7988
+ onCancel,
7989
+ style,
7990
+ refEl,
7991
+ onOpenImageViewer,
7992
+ availableNodes = [],
7993
+ availableAncestries = [],
7994
+ onMentionClick,
7995
+ onUploadFile
7996
+ }) {
7997
+ const [name, setName] = (0, import_react16.useState)("");
7998
+ const [types, setTypes] = (0, import_react16.useState)(["quest"]);
7999
+ const [typeInput, setTypeInput] = (0, import_react16.useState)("");
8000
+ const [status, setStatus] = (0, import_react16.useState)("Backlog");
8001
+ const [size, setSize] = (0, import_react16.useState)("medium");
8002
+ const [intensity, setIntensity] = (0, import_react16.useState)(0);
8003
+ const [description, setDescription] = (0, import_react16.useState)("");
8004
+ const [customProps, setCustomProps] = (0, import_react16.useState)([]);
8005
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react16.useState)(false);
8006
+ const propsEndRef = (0, import_react16.useRef)(null);
8007
+ const handleAddProp = () => {
8008
+ const newProp = createNewCustomProperty(customProps);
8009
+ setCustomProps([...customProps, newProp]);
8010
+ setTimeout(() => {
8011
+ var _a;
8012
+ (_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
8013
+ }, 100);
8014
+ };
8015
+ const handleRemoveProp = (index) => setCustomProps(customProps.filter((_, i) => i !== index));
8016
+ const handleUpdateProp = (index, updatedProp) => {
8017
+ const newProps = [...customProps];
8018
+ newProps[index] = updatedProp;
8019
+ setCustomProps(newProps);
8020
+ };
8021
+ const handleAddType = (newType) => {
8022
+ const trimmed = newType.trim();
8023
+ if (trimmed && !types.includes(trimmed)) {
8024
+ setTypes([...types, trimmed]);
8025
+ setTypeInput("");
8026
+ }
8027
+ };
8028
+ const handleRemoveType = (indexToRemove) => {
8029
+ if (types[indexToRemove] === "quest") return;
8030
+ setTypes(types.filter((_, index) => index !== indexToRemove));
8031
+ };
8032
+ const handleTypeInputKeyDown = (e) => {
8033
+ if (e.key === "Enter") {
8034
+ e.preventDefault();
8035
+ handleAddType(typeInput);
8036
+ } else if (e.key === "Backspace" && typeInput === "" && types.length > 1) {
8037
+ handleRemoveType(types.length - 1);
8038
+ }
8039
+ };
8040
+ const handleSubmit = (e) => {
8041
+ e.preventDefault();
8042
+ if (!name.trim()) {
8043
+ alert("O campo 'Nome' \xE9 obrigat\xF3rio.");
8044
+ return;
8045
+ }
8046
+ const additionalData = toObjectFromCustomProps(
8047
+ customProps.filter((prop) => prop.key.trim() && !prop.isEditing)
8048
+ );
8049
+ const processedSections = processDescriptionForSave(description, []);
8050
+ onSave({
8051
+ name: name.trim(),
8052
+ type: types,
8053
+ color: QUEST_STATUS_COLORS[status],
8054
+ // Cor atrelada ao status
8055
+ status,
8056
+ size,
8057
+ intensity,
8058
+ description: description.trim(),
8059
+ description_sections: processedSections,
8060
+ useImageAsTexture: false,
8061
+ textureImageUrl: null,
8062
+ ...additionalData
8063
+ });
8064
+ };
8065
+ const swallow = (e) => e.stopPropagation();
8066
+ const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
8067
+ const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
8068
+ return /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement(
8069
+ "div",
8070
+ {
8071
+ ref: refEl,
8072
+ 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",
8073
+ style,
8074
+ onPointerDown: swallow,
8075
+ onClick: swallow,
8076
+ onWheel: swallow,
8077
+ onContextMenu: swallow,
8078
+ onDoubleClick: swallow
8079
+ },
8080
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS[status]}, transparent)` } }),
8081
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pt-5 pb-3" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova Tarefa / Objetivo")), /* @__PURE__ */ import_react16.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, "Criar Quest")),
8082
+ /* @__PURE__ */ import_react16.default.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col max-h-[68vh]" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ import_react16.default.createElement(
8083
+ "select",
8084
+ {
8085
+ value: status,
8086
+ onChange: (e) => setStatus(e.target.value),
8087
+ 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",
8088
+ style: { borderLeft: `4px solid ${QUEST_STATUS_COLORS[status]}` }
8089
+ },
8090
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "Backlog" }, "Backlog"),
8091
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "In Progress" }, "In Progress"),
8092
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "Review" }, "Review"),
8093
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "Done" }, "Done")
8094
+ )), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.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__ */ import_react16.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiX, { size: 12 })))), /* @__PURE__ */ import_react16.default.createElement(
8095
+ "input",
8096
+ {
8097
+ type: "text",
8098
+ value: typeInput,
8099
+ onChange: (e) => setTypeInput(e.target.value),
8100
+ onKeyDown: handleTypeInputKeyDown,
8101
+ onBlur: () => {
8102
+ if (typeInput.trim()) handleAddType(typeInput);
8103
+ },
8104
+ className: "flex-1 bg-transparent text-sm min-w-[80px] focus:outline-none text-slate-200",
8105
+ autoComplete: "off"
8106
+ }
8107
+ ))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o (Opcional)"), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(
8108
+ DescriptionDisplay,
8109
+ {
8110
+ description,
8111
+ savedSections: [],
8112
+ availableNodes,
8113
+ availableAncestries,
8114
+ onMentionClick,
8115
+ onSaveDescription: (newDesc) => setDescription(newDesc)
8116
+ }
8117
+ ), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement("button", { type: "button", onClick: () => setIsDescriptionModalOpen(true), className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiEdit2, { size: 14 }))), !description && /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no Cen\xE1rio (Size)"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => /* @__PURE__ */ import_react16.default.createElement("button", { key: s, type: "button", onClick: () => setSize(s), className: "flex items-center gap-2 group cursor-pointer focus:outline-none" }, /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(import_fi14.FiCheck, { size: 12, className: "text-white" })), /* @__PURE__ */ import_react16.default.createElement("span", { className: `text-sm capitalize transition-colors ${size === s ? "text-white font-medium" : "text-slate-400 group-hover:text-slate-300"}` }, s))))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react16.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(import_fi14.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ import_react16.default.createElement(
8118
+ CustomPropertyDisplay,
8119
+ {
8120
+ key: prop.id,
8121
+ prop,
8122
+ onUpdate: (updatedProp) => handleUpdateProp(index, updatedProp),
8123
+ onRemove: () => handleRemoveProp(index),
8124
+ onOpenImageViewer,
8125
+ unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type),
8126
+ onUploadFile
8127
+ }
8128
+ )), /* @__PURE__ */ import_react16.default.createElement("div", { ref: propsEndRef })))), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.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__ */ import_react16.default.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")))
8129
+ ), isDescriptionModalOpen && /* @__PURE__ */ import_react16.default.createElement(
8130
+ DescriptionEditModal,
8131
+ {
8132
+ isOpen: isDescriptionModalOpen,
8133
+ title: "Editar Descri\xE7\xE3o da Quest",
8134
+ initialValue: description,
8135
+ onSave: (newDescription) => setDescription(newDescription),
8136
+ onClose: () => setIsDescriptionModalOpen(false),
8137
+ availableNodes,
8138
+ availableAncestries,
8139
+ availableImages
8140
+ }
8141
+ ));
8142
+ }
8143
+
8144
+ // src/components/NodeDetailsPanel.jsx
8145
+ var import_react17 = __toESM(require("react"));
8146
+ var import_fi15 = require("react-icons/fi");
7854
8147
  function NodeDetailsPanel({
7855
8148
  node,
7856
8149
  onClose,
@@ -7871,38 +8164,38 @@ function NodeDetailsPanel({
7871
8164
  userRole,
7872
8165
  currentDatasetName
7873
8166
  }) {
7874
- const [name, setName] = (0, import_react16.useState)((node == null ? void 0 : node.name) ?? "");
7875
- const [types, setTypes] = (0, import_react16.useState)([]);
7876
- const [typeInput, setTypeInput] = (0, import_react16.useState)("");
7877
- const [color, setColor] = (0, import_react16.useState)((node == null ? void 0 : node.color) ?? "#8b5cf6");
7878
- const [size, setSize] = (0, import_react16.useState)((node == null ? void 0 : node.size) ?? "medium");
7879
- const [description, setDescription] = (0, import_react16.useState)((node == null ? void 0 : node.description) ?? "");
7880
- const [intensity, setIntensity] = (0, import_react16.useState)((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
7881
- const [customProps, setCustomProps] = (0, import_react16.useState)(() => extractCustomPropsFromNode(node || {}));
7882
- const [showTypeSuggestions, setShowTypeSuggestions] = (0, import_react16.useState)(false);
7883
- const [filteredTypes, setFilteredTypes] = (0, import_react16.useState)([]);
7884
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react16.useState)(false);
7885
- const [isReadMode, setIsReadMode] = (0, import_react16.useState)(false);
7886
- const [existingSections, setExistingSections] = (0, import_react16.useState)((node == null ? void 0 : node.description_sections) || []);
7887
- const [isSaving, setIsSaving] = (0, import_react16.useState)(false);
7888
- const [isLinkCopied, setIsLinkCopied] = (0, import_react16.useState)(false);
7889
- const [useImageAsTexture, setUseImageAsTexture] = (0, import_react16.useState)(() => {
8167
+ const [name, setName] = (0, import_react17.useState)((node == null ? void 0 : node.name) ?? "");
8168
+ const [types, setTypes] = (0, import_react17.useState)([]);
8169
+ const [typeInput, setTypeInput] = (0, import_react17.useState)("");
8170
+ const [color, setColor] = (0, import_react17.useState)((node == null ? void 0 : node.color) ?? "#8b5cf6");
8171
+ const [size, setSize] = (0, import_react17.useState)((node == null ? void 0 : node.size) ?? "medium");
8172
+ const [description, setDescription] = (0, import_react17.useState)((node == null ? void 0 : node.description) ?? "");
8173
+ const [intensity, setIntensity] = (0, import_react17.useState)((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
8174
+ const [customProps, setCustomProps] = (0, import_react17.useState)(() => extractCustomPropsFromNode(node || {}));
8175
+ const [showTypeSuggestions, setShowTypeSuggestions] = (0, import_react17.useState)(false);
8176
+ const [filteredTypes, setFilteredTypes] = (0, import_react17.useState)([]);
8177
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react17.useState)(false);
8178
+ const [isReadMode, setIsReadMode] = (0, import_react17.useState)(false);
8179
+ const [existingSections, setExistingSections] = (0, import_react17.useState)((node == null ? void 0 : node.description_sections) || []);
8180
+ const [isSaving, setIsSaving] = (0, import_react17.useState)(false);
8181
+ const [isLinkCopied, setIsLinkCopied] = (0, import_react17.useState)(false);
8182
+ const [useImageAsTexture, setUseImageAsTexture] = (0, import_react17.useState)(() => {
7890
8183
  if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
7891
8184
  if ((node == null ? void 0 : node.useImageAsTexture) === "false") return false;
7892
8185
  return !!(node == null ? void 0 : node.useImageAsTexture);
7893
8186
  });
7894
- const [selectedImageUrl, setSelectedImageUrl] = (0, import_react16.useState)((node == null ? void 0 : node.textureImageUrl) ?? null);
8187
+ const [selectedImageUrl, setSelectedImageUrl] = (0, import_react17.useState)((node == null ? void 0 : node.textureImageUrl) ?? null);
7895
8188
  const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
7896
8189
  const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
7897
8190
  initialWidth: isReadMode ? 700 : 440,
7898
8191
  minWidth: 320,
7899
8192
  maxWidth: maxPanelW
7900
8193
  });
7901
- (0, import_react16.useEffect)(() => {
8194
+ (0, import_react17.useEffect)(() => {
7902
8195
  setWidth(isReadMode ? 700 : 440);
7903
8196
  }, [isReadMode, setWidth]);
7904
- const prevNodeIdRef = (0, import_react16.useRef)(null);
7905
- const propsEndRef = (0, import_react16.useRef)(null);
8197
+ const prevNodeIdRef = (0, import_react17.useRef)(null);
8198
+ const propsEndRef = (0, import_react17.useRef)(null);
7906
8199
  const canEdit = userRole !== "viewer";
7907
8200
  const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
7908
8201
  const handleImageClickFromText = (url, name2) => {
@@ -7910,7 +8203,7 @@ function NodeDetailsPanel({
7910
8203
  onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
7911
8204
  }
7912
8205
  };
7913
- (0, import_react16.useEffect)(() => {
8206
+ (0, import_react17.useEffect)(() => {
7914
8207
  if ((node == null ? void 0 : node.id) !== prevNodeIdRef.current) {
7915
8208
  prevNodeIdRef.current = node == null ? void 0 : node.id;
7916
8209
  setName((node == null ? void 0 : node.name) ?? "");
@@ -7932,13 +8225,13 @@ function NodeDetailsPanel({
7932
8225
  }
7933
8226
  }, [node]);
7934
8227
  const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
7935
- (0, import_react16.useEffect)(() => {
8228
+ (0, import_react17.useEffect)(() => {
7936
8229
  if (!hasImages && useImageAsTexture) {
7937
8230
  setUseImageAsTexture(false);
7938
8231
  setSelectedImageUrl(null);
7939
8232
  }
7940
8233
  }, [hasImages, useImageAsTexture]);
7941
- (0, import_react16.useEffect)(() => {
8234
+ (0, import_react17.useEffect)(() => {
7942
8235
  if (typeInput.trim() === "") {
7943
8236
  setFilteredTypes(existingTypes.filter((t) => !types.includes(t)));
7944
8237
  } else {
@@ -8110,7 +8403,7 @@ function NodeDetailsPanel({
8110
8403
  onClose();
8111
8404
  };
8112
8405
  const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
8113
- return /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement(
8406
+ return /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, /* @__PURE__ */ import_react17.default.createElement(
8114
8407
  "div",
8115
8408
  {
8116
8409
  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"}`,
@@ -8123,7 +8416,7 @@ function NodeDetailsPanel({
8123
8416
  onContextMenu: swallow,
8124
8417
  onDoubleClick: swallow
8125
8418
  },
8126
- /* @__PURE__ */ import_react16.default.createElement(
8419
+ /* @__PURE__ */ import_react17.default.createElement(
8127
8420
  "div",
8128
8421
  {
8129
8422
  onPointerDown: (e) => {
@@ -8134,7 +8427,7 @@ function NodeDetailsPanel({
8134
8427
  title: "Arraste para redimensionar"
8135
8428
  }
8136
8429
  ),
8137
- isReadMode ? /* @__PURE__ */ import_react16.default.createElement(
8430
+ isReadMode ? /* @__PURE__ */ import_react17.default.createElement(
8138
8431
  DescriptionReadModePanel,
8139
8432
  {
8140
8433
  title: name || (node == null ? void 0 : node.name),
@@ -8155,23 +8448,23 @@ function NodeDetailsPanel({
8155
8448
  onImageClick: handleImageClickFromText,
8156
8449
  onSaveDescription: handleSaveDescriptionInline
8157
8450
  }
8158
- ) : /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react16.default.createElement("div", null, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node"), /* @__PURE__ */ import_react16.default.createElement(
8451
+ ) : /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, /* @__PURE__ */ import_react17.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ import_react17.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react17.default.createElement("div", null, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node"), /* @__PURE__ */ import_react17.default.createElement(
8159
8452
  "button",
8160
8453
  {
8161
8454
  onClick: handleCopyLink,
8162
8455
  className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-indigo-400"}`,
8163
8456
  title: isLinkCopied ? "Link Copiado!" : "Copiar link para este Node"
8164
8457
  },
8165
- isLinkCopied ? /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiLink, { size: 12 })
8166
- )), /* @__PURE__ */ import_react16.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos"), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.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__ */ import_react16.default.createElement(
8458
+ isLinkCopied ? /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiLink, { size: 12 })
8459
+ )), /* @__PURE__ */ import_react17.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos"), /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.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__ */ import_react17.default.createElement(
8167
8460
  "button",
8168
8461
  {
8169
8462
  type: "button",
8170
8463
  onClick: () => handleRemoveType(index),
8171
8464
  className: "hover:text-white transition-colors"
8172
8465
  },
8173
- /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiX, { size: 12 })
8174
- ))), canEdit && /* @__PURE__ */ import_react16.default.createElement(
8466
+ /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiX, { size: 12 })
8467
+ ))), canEdit && /* @__PURE__ */ import_react17.default.createElement(
8175
8468
  "input",
8176
8469
  {
8177
8470
  type: "text",
@@ -8192,7 +8485,7 @@ function NodeDetailsPanel({
8192
8485
  placeholder: types.length === 0 ? "Ex.: Cliente" : "",
8193
8486
  autoComplete: "off"
8194
8487
  }
8195
- ), canEdit && showTypeSuggestions && filteredTypes.length > 0 && /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(
8488
+ ), canEdit && showTypeSuggestions && filteredTypes.length > 0 && /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.createElement(
8196
8489
  "li",
8197
8490
  {
8198
8491
  key: index,
@@ -8203,7 +8496,7 @@ function NodeDetailsPanel({
8203
8496
  }
8204
8497
  },
8205
8498
  suggestedType
8206
- ))))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome"), /* @__PURE__ */ import_react16.default.createElement(
8499
+ ))))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome"), /* @__PURE__ */ import_react17.default.createElement(
8207
8500
  "input",
8208
8501
  {
8209
8502
  type: "text",
@@ -8212,7 +8505,7 @@ function NodeDetailsPanel({
8212
8505
  readOnly: !canEdit,
8213
8506
  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"}`
8214
8507
  }
8215
- )), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(
8508
+ )), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.createElement(
8216
8509
  DescriptionDisplay,
8217
8510
  {
8218
8511
  description,
@@ -8224,7 +8517,7 @@ function NodeDetailsPanel({
8224
8517
  onImageClick: handleImageClickFromText,
8225
8518
  onSaveDescription: handleSaveDescriptionInline
8226
8519
  }
8227
- ), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(
8520
+ ), /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.createElement(
8228
8521
  "button",
8229
8522
  {
8230
8523
  type: "button",
@@ -8232,8 +8525,8 @@ function NodeDetailsPanel({
8232
8525
  className: `p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors ${canEdit ? "border-r border-white/5" : ""}`,
8233
8526
  title: "Modo de Leitura"
8234
8527
  },
8235
- /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiBookOpen, { size: 14 })
8236
- ), canEdit && /* @__PURE__ */ import_react16.default.createElement(
8528
+ /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiBookOpen, { size: 14 })
8529
+ ), canEdit && /* @__PURE__ */ import_react17.default.createElement(
8237
8530
  "button",
8238
8531
  {
8239
8532
  type: "button",
@@ -8241,17 +8534,17 @@ function NodeDetailsPanel({
8241
8534
  className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
8242
8535
  title: "Editar descri\xE7\xE3o (Modo de Escrita)"
8243
8536
  },
8244
- /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiEdit2, { size: 14 })
8245
- )), canEdit && !description && /* @__PURE__ */ import_react16.default.createElement(
8537
+ /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiEdit2, { size: 14 })
8538
+ )), canEdit && !description && /* @__PURE__ */ import_react17.default.createElement(
8246
8539
  "div",
8247
8540
  {
8248
8541
  onClick: () => setIsDescriptionModalOpen(true),
8249
8542
  className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
8250
8543
  },
8251
8544
  "Adicionar descri\xE7\xE3o..."
8252
- ))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Size"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => {
8545
+ ))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Size"), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => {
8253
8546
  const isSelected = size === s;
8254
- return /* @__PURE__ */ import_react16.default.createElement(
8547
+ return /* @__PURE__ */ import_react17.default.createElement(
8255
8548
  "button",
8256
8549
  {
8257
8550
  key: s,
@@ -8259,10 +8552,10 @@ function NodeDetailsPanel({
8259
8552
  onClick: () => canEdit && handleSizeChange(s),
8260
8553
  className: `flex items-center gap-2 group focus:outline-none ${canEdit ? "cursor-pointer" : "cursor-default opacity-80"}`
8261
8554
  },
8262
- /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(import_fi14.FiCheck, { size: 12, className: "text-white" })),
8263
- /* @__PURE__ */ import_react16.default.createElement("span", { className: `text-sm capitalize transition-colors ${isSelected ? "text-white font-medium" : "text-slate-400 " + (canEdit ? "group-hover:text-slate-300" : "")}` }, s)
8555
+ /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.createElement(import_fi15.FiCheck, { size: 12, className: "text-white" })),
8556
+ /* @__PURE__ */ import_react17.default.createElement("span", { className: `text-sm capitalize transition-colors ${isSelected ? "text-white font-medium" : "text-slate-400 " + (canEdit ? "group-hover:text-slate-300" : "")}` }, s)
8264
8557
  );
8265
- }))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Cor e Brilho"), canEdit && hasImages && /* @__PURE__ */ import_react16.default.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(import_fi14.FiCheck, { size: 12, className: "text-white" })), /* @__PURE__ */ import_react16.default.createElement(
8558
+ }))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Cor e Brilho"), canEdit && hasImages && /* @__PURE__ */ import_react17.default.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.createElement(import_fi15.FiCheck, { size: 12, className: "text-white" })), /* @__PURE__ */ import_react17.default.createElement(
8266
8559
  "input",
8267
8560
  {
8268
8561
  type: "checkbox",
@@ -8270,14 +8563,14 @@ function NodeDetailsPanel({
8270
8563
  onChange: handleToggleImageMode,
8271
8564
  className: "hidden"
8272
8565
  }
8273
- ), /* @__PURE__ */ import_react16.default.createElement("span", { className: `text-xs ${useImageAsTexture ? "text-indigo-300" : "text-slate-400 group-hover:text-slate-300"}` }, "Usar imagem para representar o node"))), /* @__PURE__ */ import_react16.default.createElement(
8566
+ ), /* @__PURE__ */ import_react17.default.createElement("span", { className: `text-xs ${useImageAsTexture ? "text-indigo-300" : "text-slate-400 group-hover:text-slate-300"}` }, "Usar imagem para representar o node"))), /* @__PURE__ */ import_react17.default.createElement(
8274
8567
  ColorPicker,
8275
8568
  {
8276
8569
  color,
8277
8570
  onChange: handleColorChange,
8278
8571
  disabled: !canEdit || useImageAsTexture
8279
8572
  }
8280
- ), /* @__PURE__ */ import_react16.default.createElement("div", { className: "mt-3 flex items-center gap-3" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiSun, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ import_react16.default.createElement(
8573
+ ), /* @__PURE__ */ import_react17.default.createElement("div", { className: "mt-3 flex items-center gap-3" }, /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiSun, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ import_react17.default.createElement(
8281
8574
  "input",
8282
8575
  {
8283
8576
  type: "range",
@@ -8290,7 +8583,7 @@ function NodeDetailsPanel({
8290
8583
  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"}`,
8291
8584
  title: `Intensidade do brilho: ${intensity}`
8292
8585
  }
8293
- ), /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react16.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(import_fi14.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react16.default.createElement(
8586
+ ), /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react17.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.createElement(import_fi15.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react17.default.createElement(
8294
8587
  CustomPropertyDisplay,
8295
8588
  {
8296
8589
  key: prop.id,
@@ -8305,7 +8598,7 @@ function NodeDetailsPanel({
8305
8598
  onUploadFile: canEdit ? onUploadFile : void 0,
8306
8599
  readOnly: !canEdit
8307
8600
  }
8308
- )), /* @__PURE__ */ import_react16.default.createElement("div", { ref: propsEndRef }))), currentDatasetName && /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement("span", { className: "truncate text-right" }, /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-slate-200 font-medium" }, currentDatasetName)))), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.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__ */ import_react16.default.createElement(
8601
+ )), /* @__PURE__ */ import_react17.default.createElement("div", { ref: propsEndRef }))), currentDatasetName && /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.createElement("span", { className: "truncate text-right" }, /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-slate-200 font-medium" }, currentDatasetName)))), /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.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__ */ import_react17.default.createElement(
8309
8602
  "button",
8310
8603
  {
8311
8604
  onClick: () => handleSave(false),
@@ -8314,10 +8607,10 @@ function NodeDetailsPanel({
8314
8607
  ${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"}
8315
8608
  `
8316
8609
  },
8317
- isSaving && /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiLoader, { className: "animate-spin" }),
8610
+ isSaving && /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiLoader, { className: "animate-spin" }),
8318
8611
  isSaving ? "Salvando..." : "Salvar"
8319
8612
  )))
8320
- ), isDescriptionModalOpen && canEdit && /* @__PURE__ */ import_react16.default.createElement(
8613
+ ), isDescriptionModalOpen && canEdit && /* @__PURE__ */ import_react17.default.createElement(
8321
8614
  DescriptionEditModal,
8322
8615
  {
8323
8616
  isOpen: isDescriptionModalOpen,
@@ -8337,7 +8630,7 @@ function NodeDetailsPanel({
8337
8630
  }
8338
8631
 
8339
8632
  // src/components/MultiNodeContextMenu.jsx
8340
- var import_react17 = __toESM(require("react"));
8633
+ var import_react18 = __toESM(require("react"));
8341
8634
  function MultiNodeContextMenu({
8342
8635
  data,
8343
8636
  userRole,
@@ -8346,12 +8639,12 @@ function MultiNodeContextMenu({
8346
8639
  onDismissOtherNodes,
8347
8640
  onDeleteNodes
8348
8641
  }) {
8349
- const menuRef = (0, import_react17.useRef)(null);
8350
- const [menuPos, setMenuPos] = (0, import_react17.useState)({ left: 0, top: 0 });
8351
- const [isConfirmingDelete, setIsConfirmingDelete] = (0, import_react17.useState)(false);
8642
+ const menuRef = (0, import_react18.useRef)(null);
8643
+ const [menuPos, setMenuPos] = (0, import_react18.useState)({ left: 0, top: 0 });
8644
+ const [isConfirmingDelete, setIsConfirmingDelete] = (0, import_react18.useState)(false);
8352
8645
  const ability = defineAbilityFor(userRole);
8353
8646
  const canDelete = ability.can("delete", "Node");
8354
- (0, import_react17.useLayoutEffect)(() => {
8647
+ (0, import_react18.useLayoutEffect)(() => {
8355
8648
  if (!data.visible || !menuRef.current) return;
8356
8649
  const el = menuRef.current;
8357
8650
  const w = el.clientWidth;
@@ -8364,7 +8657,7 @@ function MultiNodeContextMenu({
8364
8657
  if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
8365
8658
  setMenuPos({ left, top });
8366
8659
  }, [data]);
8367
- (0, import_react17.useEffect)(() => {
8660
+ (0, import_react18.useEffect)(() => {
8368
8661
  if (data.visible) {
8369
8662
  setIsConfirmingDelete(false);
8370
8663
  }
@@ -8379,7 +8672,7 @@ function MultiNodeContextMenu({
8379
8672
  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";
8380
8673
  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";
8381
8674
  const nodeCount = data.nodeIds.size;
8382
- return /* @__PURE__ */ import_react17.default.createElement(
8675
+ return /* @__PURE__ */ import_react18.default.createElement(
8383
8676
  "div",
8384
8677
  {
8385
8678
  ref: menuRef,
@@ -8393,28 +8686,28 @@ function MultiNodeContextMenu({
8393
8686
  onContextMenu: swallow,
8394
8687
  onDoubleClick: swallow
8395
8688
  },
8396
- /* @__PURE__ */ import_react17.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
8397
- /* @__PURE__ */ import_react17.default.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "w-10 h-10 rounded-full bg-red-500/20 flex items-center justify-center text-red-400 mb-1" }, /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react17.default.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }))), /* @__PURE__ */ import_react17.default.createElement("p", { className: "text-sm text-slate-200" }, "Excluir ", /* @__PURE__ */ import_react17.default.createElement("strong", null, nodeCount, " Nodes"), "?"), /* @__PURE__ */ import_react17.default.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__ */ import_react17.default.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ import_react17.default.createElement(
8689
+ /* @__PURE__ */ import_react18.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
8690
+ /* @__PURE__ */ import_react18.default.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "w-10 h-10 rounded-full bg-red-500/20 flex items-center justify-center text-red-400 mb-1" }, /* @__PURE__ */ import_react18.default.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__ */ import_react18.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }))), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-sm text-slate-200" }, "Excluir ", /* @__PURE__ */ import_react18.default.createElement("strong", null, nodeCount, " Nodes"), "?"), /* @__PURE__ */ import_react18.default.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__ */ import_react18.default.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ import_react18.default.createElement(
8398
8691
  "button",
8399
8692
  {
8400
8693
  onClick: () => setIsConfirmingDelete(false),
8401
8694
  className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
8402
8695
  },
8403
8696
  "Cancelar"
8404
- ), /* @__PURE__ */ import_react17.default.createElement(
8697
+ ), /* @__PURE__ */ import_react18.default.createElement(
8405
8698
  "button",
8406
8699
  {
8407
8700
  onClick: () => onDeleteNodes(data.nodeIds),
8408
8701
  className: "flex-1 px-2 py-2 text-xs font-medium bg-red-500 hover:bg-red-600 rounded-md text-white transition-colors"
8409
8702
  },
8410
8703
  "Excluir"
8411
- ))) : /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react17.default.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ import_react17.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es em Grupo (", nodeCount, " Nodes)")), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ import_react17.default.createElement("button", { onClick: () => onDismissNodes(data.nodeIds), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react17.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react17.default.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ import_react17.default.createElement("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }), /* @__PURE__ */ import_react17.default.createElement("path", { d: "M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }), /* @__PURE__ */ import_react17.default.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ import_react17.default.createElement("span", null, "Dismiss (", nodeCount, ")")), /* @__PURE__ */ import_react17.default.createElement("button", { onClick: () => onDismissOtherNodes(data.nodeIds), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react17.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react17.default.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ import_react17.default.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ import_react17.default.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react17.default.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ import_react17.default.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ import_react17.default.createElement("span", null, "Dismiss other nodes")), canDelete && /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, /* @__PURE__ */ import_react17.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react17.default.createElement("button", { onClick: () => setIsConfirmingDelete(true), className: deleteButtonClass, title: "Excluir Nodes" }, /* @__PURE__ */ import_react17.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react17.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react17.default.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react17.default.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ import_react17.default.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ import_react17.default.createElement("span", null, "Excluir Nodes (", nodeCount, ")"))))))
8704
+ ))) : /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es em Grupo (", nodeCount, " Nodes)")), /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ import_react18.default.createElement("button", { onClick: () => onDismissNodes(data.nodeIds), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react18.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react18.default.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }), /* @__PURE__ */ import_react18.default.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ import_react18.default.createElement("span", null, "Dismiss (", nodeCount, ")")), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: () => onDismissOtherNodes(data.nodeIds), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react18.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react18.default.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ import_react18.default.createElement("span", null, "Dismiss other nodes")), canDelete && /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: () => setIsConfirmingDelete(true), className: deleteButtonClass, title: "Excluir Nodes" }, /* @__PURE__ */ import_react18.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react18.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react18.default.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ import_react18.default.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ import_react18.default.createElement("span", null, "Excluir Nodes (", nodeCount, ")"))))))
8412
8705
  );
8413
8706
  }
8414
8707
 
8415
8708
  // src/components/RelationshipDetailsPanel.jsx
8416
- var import_react18 = __toESM(require("react"));
8417
- var import_fi15 = require("react-icons/fi");
8709
+ var import_react19 = __toESM(require("react"));
8710
+ var import_fi16 = require("react-icons/fi");
8418
8711
  function RelationshipDetailsPanel({
8419
8712
  link,
8420
8713
  onClose,
@@ -8428,19 +8721,19 @@ function RelationshipDetailsPanel({
8428
8721
  onUploadFile,
8429
8722
  userRole
8430
8723
  }) {
8431
- const [name, setName] = (0, import_react18.useState)((link == null ? void 0 : link.name) ?? "");
8432
- const [description, setDescription] = (0, import_react18.useState)((link == null ? void 0 : link.description) ?? "");
8433
- const [customProps, setCustomProps] = (0, import_react18.useState)(() => extractCustomPropsFromNode(link || {}));
8434
- const [existingSections, setExistingSections] = (0, import_react18.useState)((link == null ? void 0 : link.description_sections) || []);
8435
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react18.useState)(false);
8436
- const [isSaving, setIsSaving] = (0, import_react18.useState)(false);
8437
- const [isReadMode, setIsReadMode] = (0, import_react18.useState)(false);
8438
- const propsEndRef = (0, import_react18.useRef)(null);
8439
- const canEdit = (0, import_react18.useMemo)(() => {
8724
+ const [name, setName] = (0, import_react19.useState)((link == null ? void 0 : link.name) ?? "");
8725
+ const [description, setDescription] = (0, import_react19.useState)((link == null ? void 0 : link.description) ?? "");
8726
+ const [customProps, setCustomProps] = (0, import_react19.useState)(() => extractCustomPropsFromNode(link || {}));
8727
+ const [existingSections, setExistingSections] = (0, import_react19.useState)((link == null ? void 0 : link.description_sections) || []);
8728
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react19.useState)(false);
8729
+ const [isSaving, setIsSaving] = (0, import_react19.useState)(false);
8730
+ const [isReadMode, setIsReadMode] = (0, import_react19.useState)(false);
8731
+ const propsEndRef = (0, import_react19.useRef)(null);
8732
+ const canEdit = (0, import_react19.useMemo)(() => {
8440
8733
  const ability = defineAbilityFor(userRole);
8441
8734
  return ability.can("update", "Connection");
8442
8735
  }, [userRole]);
8443
- (0, import_react18.useEffect)(() => {
8736
+ (0, import_react19.useEffect)(() => {
8444
8737
  setName((link == null ? void 0 : link.name) ?? "");
8445
8738
  setDescription((link == null ? void 0 : link.description) ?? "");
8446
8739
  setExistingSections((link == null ? void 0 : link.description_sections) || []);
@@ -8515,7 +8808,7 @@ function RelationshipDetailsPanel({
8515
8808
  onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
8516
8809
  }
8517
8810
  };
8518
- return /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement(
8811
+ return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement(
8519
8812
  "div",
8520
8813
  {
8521
8814
  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
@@ -8530,7 +8823,7 @@ function RelationshipDetailsPanel({
8530
8823
  onContextMenu: swallow,
8531
8824
  onDoubleClick: swallow
8532
8825
  },
8533
- isReadMode ? /* @__PURE__ */ import_react18.default.createElement(
8826
+ isReadMode ? /* @__PURE__ */ import_react19.default.createElement(
8534
8827
  DescriptionReadModePanel,
8535
8828
  {
8536
8829
  title: name || "Rela\xE7\xE3o",
@@ -8551,7 +8844,7 @@ function RelationshipDetailsPanel({
8551
8844
  onImageClick: handleImageClickFromText,
8552
8845
  onSaveDescription: handleSaveDescriptionInline
8553
8846
  }
8554
- ) : /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }), /* @__PURE__ */ import_react18.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react18.default.createElement("div", null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react18.default.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__ */ import_react18.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Rela\xE7\xE3o")), /* @__PURE__ */ import_react18.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || "Rela\xE7\xE3o")), /* @__PURE__ */ import_react18.default.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__ */ import_react18.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Rela\xE7\xE3o (Opcional)"), /* @__PURE__ */ import_react18.default.createElement(
8847
+ ) : /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }), /* @__PURE__ */ import_react19.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react19.default.createElement("div", null, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react19.default.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__ */ import_react19.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Rela\xE7\xE3o")), /* @__PURE__ */ import_react19.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || "Rela\xE7\xE3o")), /* @__PURE__ */ import_react19.default.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__ */ import_react19.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react19.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Rela\xE7\xE3o (Opcional)"), /* @__PURE__ */ import_react19.default.createElement(
8555
8848
  "input",
8556
8849
  {
8557
8850
  type: "text",
@@ -8563,7 +8856,7 @@ function RelationshipDetailsPanel({
8563
8856
  ${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
8564
8857
  `
8565
8858
  }
8566
- )), /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react18.default.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__ */ import_react18.default.createElement(
8859
+ )), /* @__PURE__ */ import_react19.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react19.default.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react19.default.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__ */ import_react19.default.createElement(
8567
8860
  DescriptionDisplay,
8568
8861
  {
8569
8862
  description,
@@ -8575,7 +8868,7 @@ function RelationshipDetailsPanel({
8575
8868
  onImageClick: handleImageClickFromText,
8576
8869
  onSaveDescription: handleSaveDescriptionInline
8577
8870
  }
8578
- ), /* @__PURE__ */ import_react18.default.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__ */ import_react18.default.createElement(
8871
+ ), /* @__PURE__ */ import_react19.default.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__ */ import_react19.default.createElement(
8579
8872
  "button",
8580
8873
  {
8581
8874
  type: "button",
@@ -8583,8 +8876,8 @@ function RelationshipDetailsPanel({
8583
8876
  className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors border-r border-white/5",
8584
8877
  title: "Modo de Leitura"
8585
8878
  },
8586
- /* @__PURE__ */ import_react18.default.createElement(import_fi15.FiBookOpen, { size: 14 })
8587
- ), canEdit && /* @__PURE__ */ import_react18.default.createElement(
8879
+ /* @__PURE__ */ import_react19.default.createElement(import_fi16.FiBookOpen, { size: 14 })
8880
+ ), canEdit && /* @__PURE__ */ import_react19.default.createElement(
8588
8881
  "button",
8589
8882
  {
8590
8883
  type: "button",
@@ -8592,15 +8885,15 @@ function RelationshipDetailsPanel({
8592
8885
  className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
8593
8886
  title: "Editar descri\xE7\xE3o"
8594
8887
  },
8595
- /* @__PURE__ */ import_react18.default.createElement(import_fi15.FiEdit2, { size: 14 })
8596
- )), !description && canEdit && /* @__PURE__ */ import_react18.default.createElement(
8888
+ /* @__PURE__ */ import_react19.default.createElement(import_fi16.FiEdit2, { size: 14 })
8889
+ )), !description && canEdit && /* @__PURE__ */ import_react19.default.createElement(
8597
8890
  "div",
8598
8891
  {
8599
8892
  onClick: () => setIsDescriptionModalOpen(true),
8600
8893
  className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
8601
8894
  },
8602
8895
  "Adicionar descri\xE7\xE3o..."
8603
- ))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react18.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ import_react18.default.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__ */ import_react18.default.createElement(import_fi15.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react18.default.createElement(
8896
+ ))), /* @__PURE__ */ import_react19.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react19.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ import_react19.default.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__ */ import_react19.default.createElement(import_fi16.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react19.default.createElement(
8604
8897
  CustomPropertyDisplay,
8605
8898
  {
8606
8899
  key: prop.id,
@@ -8612,7 +8905,7 @@ function RelationshipDetailsPanel({
8612
8905
  onUploadFile,
8613
8906
  disabled: !canEdit
8614
8907
  }
8615
- )), /* @__PURE__ */ import_react18.default.createElement("div", { ref: propsEndRef })))), /* @__PURE__ */ import_react18.default.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__ */ import_react18.default.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__ */ import_react18.default.createElement(
8908
+ )), /* @__PURE__ */ import_react19.default.createElement("div", { ref: propsEndRef })))), /* @__PURE__ */ import_react19.default.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__ */ import_react19.default.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__ */ import_react19.default.createElement(
8616
8909
  "button",
8617
8910
  {
8618
8911
  onClick: () => handleSave(false),
@@ -8621,10 +8914,10 @@ function RelationshipDetailsPanel({
8621
8914
  ${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"}
8622
8915
  `
8623
8916
  },
8624
- isSaving && /* @__PURE__ */ import_react18.default.createElement(import_fi15.FiLoader, { className: "animate-spin" }),
8917
+ isSaving && /* @__PURE__ */ import_react19.default.createElement(import_fi16.FiLoader, { className: "animate-spin" }),
8625
8918
  isSaving ? "Salvando..." : "Salvar"
8626
8919
  )))
8627
- ), isDescriptionModalOpen && /* @__PURE__ */ import_react18.default.createElement(
8920
+ ), isDescriptionModalOpen && /* @__PURE__ */ import_react19.default.createElement(
8628
8921
  DescriptionEditModal,
8629
8922
  {
8630
8923
  isOpen: isDescriptionModalOpen,
@@ -8645,7 +8938,7 @@ function RelationshipDetailsPanel({
8645
8938
  }
8646
8939
 
8647
8940
  // src/components/RelationshipContextMenu.jsx
8648
- var import_react19 = __toESM(require("react"));
8941
+ var import_react20 = __toESM(require("react"));
8649
8942
  function RelationshipContextMenu({
8650
8943
  data,
8651
8944
  userRole,
@@ -8655,25 +8948,25 @@ function RelationshipContextMenu({
8655
8948
  onDelete,
8656
8949
  onClose
8657
8950
  }) {
8658
- const menuRef = (0, import_react19.useRef)(null);
8659
- const [menuPos, setMenuPos] = (0, import_react19.useState)({ left: 0, top: 0 });
8660
- const [isConfirmingDelete, setIsConfirmingDelete] = (0, import_react19.useState)(false);
8661
- const ability = (0, import_react19.useMemo)(() => defineAbilityFor(userRole), [userRole]);
8662
- const sourceName = (0, import_react19.useMemo)(
8951
+ const menuRef = (0, import_react20.useRef)(null);
8952
+ const [menuPos, setMenuPos] = (0, import_react20.useState)({ left: 0, top: 0 });
8953
+ const [isConfirmingDelete, setIsConfirmingDelete] = (0, import_react20.useState)(false);
8954
+ const ability = (0, import_react20.useMemo)(() => defineAbilityFor(userRole), [userRole]);
8955
+ const sourceName = (0, import_react20.useMemo)(
8663
8956
  () => {
8664
8957
  var _a, _b, _c, _d;
8665
8958
  return ((_d = (_c = (_b = (_a = data == null ? void 0 : data.linkObject) == null ? void 0 : _a.userData) == null ? void 0 : _b.sourceNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) ?? "(sem nome)";
8666
8959
  },
8667
8960
  [data == null ? void 0 : data.linkObject]
8668
8961
  );
8669
- const targetName = (0, import_react19.useMemo)(
8962
+ const targetName = (0, import_react20.useMemo)(
8670
8963
  () => {
8671
8964
  var _a, _b, _c, _d;
8672
8965
  return ((_d = (_c = (_b = (_a = data == null ? void 0 : data.linkObject) == null ? void 0 : _a.userData) == null ? void 0 : _b.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) ?? "(sem nome)";
8673
8966
  },
8674
8967
  [data == null ? void 0 : data.linkObject]
8675
8968
  );
8676
- (0, import_react19.useLayoutEffect)(() => {
8969
+ (0, import_react20.useLayoutEffect)(() => {
8677
8970
  if (!data.visible || !menuRef.current) return;
8678
8971
  const el = menuRef.current;
8679
8972
  const w = el.clientWidth;
@@ -8686,7 +8979,7 @@ function RelationshipContextMenu({
8686
8979
  if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
8687
8980
  setMenuPos({ left, top });
8688
8981
  }, [data]);
8689
- (0, import_react19.useEffect)(() => {
8982
+ (0, import_react20.useEffect)(() => {
8690
8983
  if (data.visible) {
8691
8984
  setIsConfirmingDelete(false);
8692
8985
  }
@@ -8702,7 +8995,7 @@ function RelationshipContextMenu({
8702
8995
  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";
8703
8996
  const canUpdate = ability.can("update", "Connection");
8704
8997
  const canDelete = ability.can("delete", "Connection");
8705
- return /* @__PURE__ */ import_react19.default.createElement(
8998
+ return /* @__PURE__ */ import_react20.default.createElement(
8706
8999
  "div",
8707
9000
  {
8708
9001
  ref: menuRef,
@@ -8716,29 +9009,29 @@ function RelationshipContextMenu({
8716
9009
  onContextMenu: swallow,
8717
9010
  onDoubleClick: swallow
8718
9011
  },
8719
- /* @__PURE__ */ import_react19.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }),
8720
- /* @__PURE__ */ import_react19.default.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "w-10 h-10 rounded-full bg-rose-500/20 flex items-center justify-center text-rose-400 mb-1" }, /* @__PURE__ */ import_react19.default.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__ */ import_react19.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react19.default.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }), /* @__PURE__ */ import_react19.default.createElement("path", { d: "M10 11v6" }), /* @__PURE__ */ import_react19.default.createElement("path", { d: "M14 11v6" }), /* @__PURE__ */ import_react19.default.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" }))), /* @__PURE__ */ import_react19.default.createElement("p", { className: "text-sm text-slate-200" }, "Excluir rela\xE7\xE3o?"), /* @__PURE__ */ import_react19.default.createElement("p", { className: "text-[11px] text-slate-400 leading-tight break-words" }, "Desconectar ", /* @__PURE__ */ import_react19.default.createElement("strong", null, sourceName), " de ", /* @__PURE__ */ import_react19.default.createElement("strong", null, targetName), ".")), /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ import_react19.default.createElement(
9012
+ /* @__PURE__ */ import_react20.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }),
9013
+ /* @__PURE__ */ import_react20.default.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "w-10 h-10 rounded-full bg-rose-500/20 flex items-center justify-center text-rose-400 mb-1" }, /* @__PURE__ */ import_react20.default.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__ */ import_react20.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M10 11v6" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M14 11v6" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" }))), /* @__PURE__ */ import_react20.default.createElement("p", { className: "text-sm text-slate-200" }, "Excluir rela\xE7\xE3o?"), /* @__PURE__ */ import_react20.default.createElement("p", { className: "text-[11px] text-slate-400 leading-tight break-words" }, "Desconectar ", /* @__PURE__ */ import_react20.default.createElement("strong", null, sourceName), " de ", /* @__PURE__ */ import_react20.default.createElement("strong", null, targetName), ".")), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ import_react20.default.createElement(
8721
9014
  "button",
8722
9015
  {
8723
9016
  onClick: () => setIsConfirmingDelete(false),
8724
9017
  className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
8725
9018
  },
8726
9019
  "Cancelar"
8727
- ), /* @__PURE__ */ import_react19.default.createElement(
9020
+ ), /* @__PURE__ */ import_react20.default.createElement(
8728
9021
  "button",
8729
9022
  {
8730
9023
  onClick: () => onDelete == null ? void 0 : onDelete(data.linkObject),
8731
9024
  className: "flex-1 px-2 py-2 text-xs font-medium bg-rose-600 hover:bg-rose-500 rounded-md text-white transition-colors"
8732
9025
  },
8733
9026
  "Excluir"
8734
- ))) : /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react19.default.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__ */ import_react19.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Rela\xE7\xE3o")), /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex flex-col gap-1" }, canUpdate && /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement(
9027
+ ))) : /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react20.default.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__ */ import_react20.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Rela\xE7\xE3o")), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-col gap-1" }, canUpdate && /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement(
8735
9028
  "button",
8736
9029
  {
8737
9030
  onClick: () => onRelinkSource == null ? void 0 : onRelinkSource(data.linkObject),
8738
9031
  className: baseButtonClass,
8739
9032
  title: "Desconectar ponta ligada ao Source"
8740
9033
  },
8741
- /* @__PURE__ */ import_react19.default.createElement(
9034
+ /* @__PURE__ */ import_react20.default.createElement(
8742
9035
  "svg",
8743
9036
  {
8744
9037
  xmlns: "http://www.w3.org/2000/svg",
@@ -8751,18 +9044,18 @@ function RelationshipContextMenu({
8751
9044
  strokeLinecap: "round",
8752
9045
  strokeLinejoin: "round"
8753
9046
  },
8754
- /* @__PURE__ */ import_react19.default.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }),
8755
- /* @__PURE__ */ import_react19.default.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })
9047
+ /* @__PURE__ */ import_react20.default.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }),
9048
+ /* @__PURE__ */ import_react20.default.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })
8756
9049
  ),
8757
- /* @__PURE__ */ import_react19.default.createElement("span", null, "Desconectar Source (", sourceName, ")")
8758
- ), /* @__PURE__ */ import_react19.default.createElement(
9050
+ /* @__PURE__ */ import_react20.default.createElement("span", null, "Desconectar Source (", sourceName, ")")
9051
+ ), /* @__PURE__ */ import_react20.default.createElement(
8759
9052
  "button",
8760
9053
  {
8761
9054
  onClick: () => onRelinkTarget == null ? void 0 : onRelinkTarget(data.linkObject),
8762
9055
  className: baseButtonClass,
8763
9056
  title: "Desconectar ponta ligada ao Target"
8764
9057
  },
8765
- /* @__PURE__ */ import_react19.default.createElement(
9058
+ /* @__PURE__ */ import_react20.default.createElement(
8766
9059
  "svg",
8767
9060
  {
8768
9061
  xmlns: "http://www.w3.org/2000/svg",
@@ -8775,21 +9068,21 @@ function RelationshipContextMenu({
8775
9068
  strokeLinecap: "round",
8776
9069
  strokeLinejoin: "round"
8777
9070
  },
8778
- /* @__PURE__ */ import_react19.default.createElement("polyline", { points: "16 3 21 3 21 8" }),
8779
- /* @__PURE__ */ import_react19.default.createElement("line", { x1: "4", y1: "20", x2: "21", y2: "3" }),
8780
- /* @__PURE__ */ import_react19.default.createElement("polyline", { points: "21 16 21 21 16 21" }),
8781
- /* @__PURE__ */ import_react19.default.createElement("line", { x1: "15", y1: "15", x2: "21", y2: "21" }),
8782
- /* @__PURE__ */ import_react19.default.createElement("line", { x1: "4", y1: "4", x2: "9", y2: "9" })
9071
+ /* @__PURE__ */ import_react20.default.createElement("polyline", { points: "16 3 21 3 21 8" }),
9072
+ /* @__PURE__ */ import_react20.default.createElement("line", { x1: "4", y1: "20", x2: "21", y2: "3" }),
9073
+ /* @__PURE__ */ import_react20.default.createElement("polyline", { points: "21 16 21 21 16 21" }),
9074
+ /* @__PURE__ */ import_react20.default.createElement("line", { x1: "15", y1: "15", x2: "21", y2: "21" }),
9075
+ /* @__PURE__ */ import_react20.default.createElement("line", { x1: "4", y1: "4", x2: "9", y2: "9" })
8783
9076
  ),
8784
- /* @__PURE__ */ import_react19.default.createElement("span", null, "Desconectar Target (", targetName, ")")
8785
- ), /* @__PURE__ */ import_react19.default.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" })), /* @__PURE__ */ import_react19.default.createElement(
9077
+ /* @__PURE__ */ import_react20.default.createElement("span", null, "Desconectar Target (", targetName, ")")
9078
+ ), /* @__PURE__ */ import_react20.default.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" })), /* @__PURE__ */ import_react20.default.createElement(
8786
9079
  "button",
8787
9080
  {
8788
9081
  onClick: () => onOpenDetails == null ? void 0 : onOpenDetails(data.linkObject),
8789
9082
  className: baseButtonClass,
8790
9083
  title: "Abrir detalhes da rela\xE7\xE3o"
8791
9084
  },
8792
- /* @__PURE__ */ import_react19.default.createElement(
9085
+ /* @__PURE__ */ import_react20.default.createElement(
8793
9086
  "svg",
8794
9087
  {
8795
9088
  xmlns: "http://www.w3.org/2000/svg",
@@ -8802,19 +9095,19 @@ function RelationshipContextMenu({
8802
9095
  strokeLinecap: "round",
8803
9096
  strokeLinejoin: "round"
8804
9097
  },
8805
- /* @__PURE__ */ import_react19.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
8806
- /* @__PURE__ */ import_react19.default.createElement("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
8807
- /* @__PURE__ */ import_react19.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "8" })
9098
+ /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
9099
+ /* @__PURE__ */ import_react20.default.createElement("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
9100
+ /* @__PURE__ */ import_react20.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "8" })
8808
9101
  ),
8809
- /* @__PURE__ */ import_react19.default.createElement("span", null, "Abrir Detalhes")
8810
- ), canDelete && /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" }), /* @__PURE__ */ import_react19.default.createElement(
9102
+ /* @__PURE__ */ import_react20.default.createElement("span", null, "Abrir Detalhes")
9103
+ ), canDelete && /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" }), /* @__PURE__ */ import_react20.default.createElement(
8811
9104
  "button",
8812
9105
  {
8813
9106
  onClick: () => setIsConfirmingDelete(true),
8814
9107
  className: dangerButtonClass,
8815
9108
  title: "Excluir esta conex\xE3o"
8816
9109
  },
8817
- /* @__PURE__ */ import_react19.default.createElement(
9110
+ /* @__PURE__ */ import_react20.default.createElement(
8818
9111
  "svg",
8819
9112
  {
8820
9113
  xmlns: "http://www.w3.org/2000/svg",
@@ -8827,19 +9120,19 @@ function RelationshipContextMenu({
8827
9120
  strokeLinecap: "round",
8828
9121
  strokeLinejoin: "round"
8829
9122
  },
8830
- /* @__PURE__ */ import_react19.default.createElement("polyline", { points: "3 6 5 6 21 6" }),
8831
- /* @__PURE__ */ import_react19.default.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }),
8832
- /* @__PURE__ */ import_react19.default.createElement("path", { d: "M10 11v6" }),
8833
- /* @__PURE__ */ import_react19.default.createElement("path", { d: "M14 11v6" }),
8834
- /* @__PURE__ */ import_react19.default.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" })
9123
+ /* @__PURE__ */ import_react20.default.createElement("polyline", { points: "3 6 5 6 21 6" }),
9124
+ /* @__PURE__ */ import_react20.default.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }),
9125
+ /* @__PURE__ */ import_react20.default.createElement("path", { d: "M10 11v6" }),
9126
+ /* @__PURE__ */ import_react20.default.createElement("path", { d: "M14 11v6" }),
9127
+ /* @__PURE__ */ import_react20.default.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" })
8835
9128
  ),
8836
- /* @__PURE__ */ import_react19.default.createElement("span", null, "Excluir conex\xE3o (", sourceName, " \u2192 ", targetName, ")")
9129
+ /* @__PURE__ */ import_react20.default.createElement("span", null, "Excluir conex\xE3o (", sourceName, " \u2192 ", targetName, ")")
8837
9130
  )))))
8838
9131
  );
8839
9132
  }
8840
9133
 
8841
9134
  // src/components/LoadingScreen.jsx
8842
- var import_react20 = __toESM(require("react"));
9135
+ var import_react21 = __toESM(require("react"));
8843
9136
  var styles = {
8844
9137
  loadingOverlay: {
8845
9138
  position: "fixed",
@@ -8871,11 +9164,11 @@ var styles = {
8871
9164
  `
8872
9165
  };
8873
9166
  function LoadingScreen() {
8874
- return /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("style", null, styles.keyframes), /* @__PURE__ */ import_react20.default.createElement("div", { style: styles.loadingOverlay }, /* @__PURE__ */ import_react20.default.createElement("div", { style: styles.spinner })));
9167
+ return /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement("style", null, styles.keyframes), /* @__PURE__ */ import_react21.default.createElement("div", { style: styles.loadingOverlay }, /* @__PURE__ */ import_react21.default.createElement("div", { style: styles.spinner })));
8875
9168
  }
8876
9169
 
8877
9170
  // src/components/ImportParentFileModal.jsx
8878
- var import_react21 = __toESM(require("react"));
9171
+ var import_react22 = __toESM(require("react"));
8879
9172
  function ImportParentFileModal({
8880
9173
  isOpen,
8881
9174
  onClose,
@@ -8886,12 +9179,12 @@ function ImportParentFileModal({
8886
9179
  onFetchAvailableFiles,
8887
9180
  currentViewName
8888
9181
  }) {
8889
- const [activeTab, setActiveTab] = (0, import_react21.useState)("databases");
8890
- const [availableDbs, setAvailableDbs] = (0, import_react21.useState)([]);
8891
- const [availableViews, setAvailableViews] = (0, import_react21.useState)([]);
8892
- const [selectedItem, setSelectedItem] = (0, import_react21.useState)(null);
8893
- const [isLoading, setIsLoading] = (0, import_react21.useState)(false);
8894
- (0, import_react21.useEffect)(() => {
9182
+ const [activeTab, setActiveTab] = (0, import_react22.useState)("databases");
9183
+ const [availableDbs, setAvailableDbs] = (0, import_react22.useState)([]);
9184
+ const [availableViews, setAvailableViews] = (0, import_react22.useState)([]);
9185
+ const [selectedItem, setSelectedItem] = (0, import_react22.useState)(null);
9186
+ const [isLoading, setIsLoading] = (0, import_react22.useState)(false);
9187
+ (0, import_react22.useEffect)(() => {
8895
9188
  if (isOpen && session && onFetchAvailableFiles) {
8896
9189
  const fetchData = async () => {
8897
9190
  setIsLoading(true);
@@ -8927,7 +9220,7 @@ function ImportParentFileModal({
8927
9220
  fetchData();
8928
9221
  }
8929
9222
  }, [isOpen, session, parentDbs, onFetchAvailableFiles, currentViewName]);
8930
- (0, import_react21.useEffect)(() => {
9223
+ (0, import_react22.useEffect)(() => {
8931
9224
  setSelectedItem(null);
8932
9225
  }, [activeTab]);
8933
9226
  if (!isOpen) {
@@ -8956,13 +9249,13 @@ function ImportParentFileModal({
8956
9249
  const swallow = (e) => e.stopPropagation();
8957
9250
  const currentList = activeTab === "databases" ? availableDbs : availableViews;
8958
9251
  const emptyMessage = activeTab === "databases" ? "Nenhum novo arquivo parent dispon\xEDvel." : "Nenhuma view dispon\xEDvel para importa\xE7\xE3o.";
8959
- return /* @__PURE__ */ import_react21.default.createElement(
9252
+ return /* @__PURE__ */ import_react22.default.createElement(
8960
9253
  "div",
8961
9254
  {
8962
9255
  className: "ui-overlay fixed inset-0 z-[1200] flex items-center justify-center bg-black/60 backdrop-blur-sm",
8963
9256
  onClick: onClose
8964
9257
  },
8965
- /* @__PURE__ */ import_react21.default.createElement(
9258
+ /* @__PURE__ */ import_react22.default.createElement(
8966
9259
  "div",
8967
9260
  {
8968
9261
  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]",
@@ -8974,14 +9267,14 @@ function ImportParentFileModal({
8974
9267
  onContextMenu: swallow,
8975
9268
  onDoubleClick: swallow
8976
9269
  },
8977
- /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center justify-between px-6 py-4 border-b border-white/10 flex-shrink-0" }, /* @__PURE__ */ import_react21.default.createElement("h2", { className: "text-lg font-semibold" }, "Importar"), /* @__PURE__ */ import_react21.default.createElement(
9270
+ /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-between px-6 py-4 border-b border-white/10 flex-shrink-0" }, /* @__PURE__ */ import_react22.default.createElement("h2", { className: "text-lg font-semibold" }, "Importar"), /* @__PURE__ */ import_react22.default.createElement(
8978
9271
  "button",
8979
9272
  {
8980
9273
  onClick: onClose,
8981
9274
  className: "p-2 rounded-md text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
8982
9275
  title: "Fechar"
8983
9276
  },
8984
- /* @__PURE__ */ import_react21.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ import_react21.default.createElement(
9277
+ /* @__PURE__ */ import_react22.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ import_react22.default.createElement(
8985
9278
  "path",
8986
9279
  {
8987
9280
  fillRule: "evenodd",
@@ -8990,14 +9283,14 @@ function ImportParentFileModal({
8990
9283
  }
8991
9284
  ))
8992
9285
  )),
8993
- /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex px-6 border-b border-white/10 bg-white/5 flex-shrink-0" }, /* @__PURE__ */ import_react21.default.createElement(
9286
+ /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex px-6 border-b border-white/10 bg-white/5 flex-shrink-0" }, /* @__PURE__ */ import_react22.default.createElement(
8994
9287
  "button",
8995
9288
  {
8996
9289
  onClick: () => setActiveTab("databases"),
8997
9290
  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"}`
8998
9291
  },
8999
9292
  "Arquivos Parent"
9000
- ), /* @__PURE__ */ import_react21.default.createElement(
9293
+ ), /* @__PURE__ */ import_react22.default.createElement(
9001
9294
  "button",
9002
9295
  {
9003
9296
  onClick: () => setActiveTab("views"),
@@ -9005,24 +9298,24 @@ function ImportParentFileModal({
9005
9298
  },
9006
9299
  "Views (Ancestralidades)"
9007
9300
  )),
9008
- /* @__PURE__ */ import_react21.default.createElement("div", { className: "p-6 overflow-y-auto custom-scrollbar flex-grow min-h-[200px]" }, isLoading ? /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center justify-center h-40" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "w-8 h-8 border-4 border-t-indigo-500 border-slate-700 rounded-full animate-spin" })) : /* @__PURE__ */ import_react21.default.createElement("div", { className: "space-y-2" }, currentList.length > 0 ? currentList.map((item) => /* @__PURE__ */ import_react21.default.createElement(
9301
+ /* @__PURE__ */ import_react22.default.createElement("div", { className: "p-6 overflow-y-auto custom-scrollbar flex-grow min-h-[200px]" }, isLoading ? /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-center h-40" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "w-8 h-8 border-4 border-t-indigo-500 border-slate-700 rounded-full animate-spin" })) : /* @__PURE__ */ import_react22.default.createElement("div", { className: "space-y-2" }, currentList.length > 0 ? currentList.map((item) => /* @__PURE__ */ import_react22.default.createElement(
9009
9302
  "div",
9010
9303
  {
9011
9304
  key: item.id,
9012
9305
  onClick: () => setSelectedItem(item),
9013
9306
  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"}`
9014
9307
  },
9015
- /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react21.default.createElement("span", { className: "font-medium text-slate-100" }, item.name), activeTab === "views" && /* @__PURE__ */ import_react21.default.createElement("span", { className: "text-[10px] px-1.5 py-0.5 rounded bg-black/30 text-indigo-300 border border-indigo-500/30" }, "VIEW")),
9016
- item.description && /* @__PURE__ */ import_react21.default.createElement("p", { className: `text-xs ${(selectedItem == null ? void 0 : selectedItem.id) === item.id ? "text-indigo-200" : "text-slate-400"}` }, item.description)
9017
- )) : /* @__PURE__ */ import_react21.default.createElement("p", { className: "text-slate-400 text-center py-10" }, emptyMessage))),
9018
- /* @__PURE__ */ import_react21.default.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__ */ import_react21.default.createElement(
9308
+ /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react22.default.createElement("span", { className: "font-medium text-slate-100" }, item.name), activeTab === "views" && /* @__PURE__ */ import_react22.default.createElement("span", { className: "text-[10px] px-1.5 py-0.5 rounded bg-black/30 text-indigo-300 border border-indigo-500/30" }, "VIEW")),
9309
+ item.description && /* @__PURE__ */ import_react22.default.createElement("p", { className: `text-xs ${(selectedItem == null ? void 0 : selectedItem.id) === item.id ? "text-indigo-200" : "text-slate-400"}` }, item.description)
9310
+ )) : /* @__PURE__ */ import_react22.default.createElement("p", { className: "text-slate-400 text-center py-10" }, emptyMessage))),
9311
+ /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement(
9019
9312
  "button",
9020
9313
  {
9021
9314
  onClick: onClose,
9022
9315
  className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm text-slate-300"
9023
9316
  },
9024
9317
  "Cancelar"
9025
- ), /* @__PURE__ */ import_react21.default.createElement(
9318
+ ), /* @__PURE__ */ import_react22.default.createElement(
9026
9319
  "button",
9027
9320
  {
9028
9321
  onClick: handleConfirm,
@@ -9036,8 +9329,8 @@ function ImportParentFileModal({
9036
9329
  }
9037
9330
 
9038
9331
  // src/components/AncestryLinkDetailsPanel.jsx
9039
- var import_react22 = __toESM(require("react"));
9040
- var import_fi16 = require("react-icons/fi");
9332
+ var import_react23 = __toESM(require("react"));
9333
+ var import_fi17 = require("react-icons/fi");
9041
9334
  function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile }) {
9042
9335
  var _a, _b, _c, _d;
9043
9336
  const relationshipData = data.relationship || {};
@@ -9046,21 +9339,21 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9046
9339
  const customProps = extractCustomPropsFromNode(relationshipData);
9047
9340
  const sourceName = ((_b = (_a = data.sourceNode) == null ? void 0 : _a.userData) == null ? void 0 : _b.name) || "Origem";
9048
9341
  const targetName = ((_d = (_c = data.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) || "Destino";
9049
- const [isReadMode, setIsReadMode] = (0, import_react22.useState)(false);
9342
+ const [isReadMode, setIsReadMode] = (0, import_react23.useState)(false);
9050
9343
  const swallow = (e) => e.stopPropagation();
9051
9344
  const handleImageClickFromText = (url, name) => {
9052
9345
  if (onOpenImageViewer) {
9053
9346
  onOpenImageViewer([{ name: name || "Imagem", value: url }], 0);
9054
9347
  }
9055
9348
  };
9056
- return /* @__PURE__ */ import_react22.default.createElement(
9349
+ return /* @__PURE__ */ import_react23.default.createElement(
9057
9350
  "div",
9058
9351
  {
9059
9352
  className: "ui-overlay fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-[1200]",
9060
9353
  onClick: onClose,
9061
9354
  onPointerDown: swallow
9062
9355
  },
9063
- /* @__PURE__ */ import_react22.default.createElement(
9356
+ /* @__PURE__ */ import_react23.default.createElement(
9064
9357
  "div",
9065
9358
  {
9066
9359
  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
@@ -9068,7 +9361,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9068
9361
  `,
9069
9362
  onClick: swallow
9070
9363
  },
9071
- isReadMode ? /* @__PURE__ */ import_react22.default.createElement(
9364
+ isReadMode ? /* @__PURE__ */ import_react23.default.createElement(
9072
9365
  DescriptionReadModePanel,
9073
9366
  {
9074
9367
  title: `${sourceName} \u2794 ${targetName}`,
@@ -9080,15 +9373,15 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9080
9373
  onMentionClick,
9081
9374
  onImageClick: handleImageClickFromText
9082
9375
  }
9083
- ) : /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, /* @__PURE__ */ import_react22.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ import_react22.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react22.default.createElement("div", null, /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Ancestralidade")), /* @__PURE__ */ import_react22.default.createElement("h2", { className: "text-lg font-semibold tracking-tight flex items-center gap-2" }, /* @__PURE__ */ import_react22.default.createElement("span", { className: "truncate max-w-[150px]" }, sourceName), /* @__PURE__ */ import_react22.default.createElement("span", { className: "text-slate-500 text-sm" }, "\u2794"), /* @__PURE__ */ import_react22.default.createElement("span", { className: "truncate max-w-[150px]" }, targetName))), /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement("div", { className: "px-6 pb-6 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, description && /* @__PURE__ */ import_react22.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react22.default.createElement("label", { className: "text-xs text-slate-300 font-medium" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react22.default.createElement(
9376
+ ) : /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, /* @__PURE__ */ import_react23.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ import_react23.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react23.default.createElement("div", null, /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react23.default.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__ */ import_react23.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Ancestralidade")), /* @__PURE__ */ import_react23.default.createElement("h2", { className: "text-lg font-semibold tracking-tight flex items-center gap-2" }, /* @__PURE__ */ import_react23.default.createElement("span", { className: "truncate max-w-[150px]" }, sourceName), /* @__PURE__ */ import_react23.default.createElement("span", { className: "text-slate-500 text-sm" }, "\u2794"), /* @__PURE__ */ import_react23.default.createElement("span", { className: "truncate max-w-[150px]" }, targetName))), /* @__PURE__ */ import_react23.default.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__ */ import_react23.default.createElement("div", { className: "px-6 pb-6 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, description && /* @__PURE__ */ import_react23.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react23.default.createElement("label", { className: "text-xs text-slate-300 font-medium" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react23.default.createElement(
9084
9377
  "button",
9085
9378
  {
9086
9379
  onClick: () => setIsReadMode(true),
9087
9380
  className: "p-1 text-slate-400 hover:text-white transition-colors",
9088
9381
  title: "Modo de Leitura"
9089
9382
  },
9090
- /* @__PURE__ */ import_react22.default.createElement(import_fi16.FiBookOpen, { size: 14 })
9091
- )), /* @__PURE__ */ import_react22.default.createElement("div", { className: "bg-slate-800/40 rounded-lg border border-white/10 p-1 relative group" }, /* @__PURE__ */ import_react22.default.createElement(
9383
+ /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiBookOpen, { size: 14 })
9384
+ )), /* @__PURE__ */ import_react23.default.createElement("div", { className: "bg-slate-800/40 rounded-lg border border-white/10 p-1 relative group" }, /* @__PURE__ */ import_react23.default.createElement(
9092
9385
  DescriptionDisplay,
9093
9386
  {
9094
9387
  description,
@@ -9097,7 +9390,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9097
9390
  onMentionClick,
9098
9391
  onImageClick: handleImageClickFromText
9099
9392
  }
9100
- ))), customProps.length > 0 && /* @__PURE__ */ import_react22.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react22.default.createElement("label", { className: "text-xs text-slate-300 font-medium mb-2 block" }, "Propriedades"), /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop) => /* @__PURE__ */ import_react22.default.createElement(
9393
+ ))), customProps.length > 0 && /* @__PURE__ */ import_react23.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react23.default.createElement("label", { className: "text-xs text-slate-300 font-medium mb-2 block" }, "Propriedades"), /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop) => /* @__PURE__ */ import_react23.default.createElement(
9101
9394
  CustomPropertyDisplay,
9102
9395
  {
9103
9396
  key: prop.id,
@@ -9106,14 +9399,14 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9106
9399
  onOpenImageViewer,
9107
9400
  onUploadFile
9108
9401
  }
9109
- )))), !description && customProps.length === 0 && /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.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".')))
9402
+ )))), !description && customProps.length === 0 && /* @__PURE__ */ import_react23.default.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__ */ import_react23.default.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".')))
9110
9403
  )
9111
9404
  );
9112
9405
  }
9113
9406
 
9114
9407
  // src/components/AncestryBoard.jsx
9115
- var import_react23 = __toESM(require("react"));
9116
- var import_fi17 = require("react-icons/fi");
9408
+ var import_react24 = __toESM(require("react"));
9409
+ var import_fi18 = require("react-icons/fi");
9117
9410
  var GroupItem = ({
9118
9411
  group,
9119
9412
  index,
@@ -9133,7 +9426,7 @@ var GroupItem = ({
9133
9426
  }) => {
9134
9427
  const canIndent = index > 0;
9135
9428
  const isPickingForThisGroup = pickingGroupId === group.id;
9136
- const textareaRef = (0, import_react23.useRef)(null);
9429
+ const textareaRef = (0, import_react24.useRef)(null);
9137
9430
  const adjustHeight = () => {
9138
9431
  const textarea = textareaRef.current;
9139
9432
  if (textarea) {
@@ -9141,13 +9434,13 @@ var GroupItem = ({
9141
9434
  textarea.style.height = `${textarea.scrollHeight}px`;
9142
9435
  }
9143
9436
  };
9144
- (0, import_react23.useEffect)(() => {
9437
+ (0, import_react24.useEffect)(() => {
9145
9438
  adjustHeight();
9146
9439
  }, [group.text]);
9147
- return /* @__PURE__ */ import_react23.default.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__ */ import_react23.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react23.default.createElement("div", { className: `
9440
+ return /* @__PURE__ */ import_react24.default.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__ */ import_react24.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(
9443
+ ` }, /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
9460
+ ), group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(
9462
+ return /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(
9474
+ /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(import_fi17.FiPlay, { size: 10, className: "ml-0.5 fill-current" })
9481
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlay, { size: 10, className: "ml-0.5 fill-current" })
9189
9482
  )
9190
- ) : /* @__PURE__ */ import_react23.default.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiAlertTriangle, { size: 10 })),
9191
- /* @__PURE__ */ import_react23.default.createElement("span", { className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}` }, anc.name),
9192
- canEdit && /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, /* @__PURE__ */ import_react23.default.createElement("div", { className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}` }), /* @__PURE__ */ import_react23.default.createElement(
9483
+ ) : /* @__PURE__ */ import_react24.default.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiAlertTriangle, { size: 10 })),
9484
+ /* @__PURE__ */ import_react24.default.createElement("span", { className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}` }, anc.name),
9485
+ canEdit && /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement("div", { className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}` }), /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(import_fi17.FiX, { size: 12 })
9492
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiX, { size: 12 })
9200
9493
  ))
9201
9494
  );
9202
- })), canEdit && /* @__PURE__ */ import_react23.default.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__ */ import_react23.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react23.default.createElement(
9495
+ })), canEdit && /* @__PURE__ */ import_react24.default.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__ */ import_react24.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(import_fi17.FiCheckCircle, { size: 12 }) : /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiSearch, { size: 12 }),
9505
+ isPickingForThisGroup ? /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiCheckCircle, { size: 12 }) : /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiSearch, { size: 12 }),
9213
9506
  isPickingForThisGroup ? "Selecionando..." : "Adicionar"
9214
- ), /* @__PURE__ */ import_react23.default.createElement(
9507
+ ), /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(import_fi17.FiPlus, { size: 14 })
9222
- )), /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react23.default.createElement(
9514
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlus, { size: 14 })
9515
+ )), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(import_fi17.FiArrowRight, { size: 14 })
9231
- ), /* @__PURE__ */ import_react23.default.createElement(
9523
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiArrowRight, { size: 14 })
9524
+ ), /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(import_fi17.FiArrowLeft, { size: 14 })
9239
- ), /* @__PURE__ */ import_react23.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react23.default.createElement(
9531
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiArrowLeft, { size: 14 })
9532
+ ), /* @__PURE__ */ import_react24.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(import_fi17.FiTrash2, { size: 14 })
9247
- )))), group.children && group.children.length > 0 && /* @__PURE__ */ import_react23.default.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ import_react23.default.createElement(
9539
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiTrash2, { size: 14 })
9540
+ )))), group.children && group.children.length > 0 && /* @__PURE__ */ import_react24.default.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ import_react24.default.createElement(
9248
9541
  GroupItem,
9249
9542
  {
9250
9543
  key: childGroup.id,
@@ -9276,21 +9569,21 @@ function AncestryBoard({
9276
9569
  userRole
9277
9570
  // [NOVO] Recebe a role do usuário
9278
9571
  }) {
9279
- const [searchTerm, setSearchTerm] = (0, import_react23.useState)("");
9280
- const [groups, setGroups] = (0, import_react23.useState)([]);
9281
- const [isLoaded, setIsLoaded] = (0, import_react23.useState)(false);
9282
- const [pickingGroupId, setPickingGroupId] = (0, import_react23.useState)(null);
9283
- const [saveStatus, setSaveStatus] = (0, import_react23.useState)("idle");
9284
- const canEdit = (0, import_react23.useMemo)(() => {
9572
+ const [searchTerm, setSearchTerm] = (0, import_react24.useState)("");
9573
+ const [groups, setGroups] = (0, import_react24.useState)([]);
9574
+ const [isLoaded, setIsLoaded] = (0, import_react24.useState)(false);
9575
+ const [pickingGroupId, setPickingGroupId] = (0, import_react24.useState)(null);
9576
+ const [saveStatus, setSaveStatus] = (0, import_react24.useState)("idle");
9577
+ const canEdit = (0, import_react24.useMemo)(() => {
9285
9578
  return userRole !== "viewer";
9286
9579
  }, [userRole]);
9287
- (0, import_react23.useEffect)(() => {
9580
+ (0, import_react24.useEffect)(() => {
9288
9581
  if (initialGroups && !isLoaded) {
9289
9582
  setGroups(initialGroups);
9290
9583
  setIsLoaded(true);
9291
9584
  }
9292
9585
  }, [initialGroups, isLoaded]);
9293
- const nodeNamesMap = (0, import_react23.useMemo)(() => {
9586
+ const nodeNamesMap = (0, import_react24.useMemo)(() => {
9294
9587
  const map = /* @__PURE__ */ new Map();
9295
9588
  if (availableNodes && Array.isArray(availableNodes)) {
9296
9589
  availableNodes.forEach((node) => {
@@ -9301,7 +9594,7 @@ function AncestryBoard({
9301
9594
  }
9302
9595
  return map;
9303
9596
  }, [availableNodes]);
9304
- const availableIds = (0, import_react23.useMemo)(() => {
9597
+ const availableIds = (0, import_react24.useMemo)(() => {
9305
9598
  return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
9306
9599
  }, [availableAncestries]);
9307
9600
  const sanitizeGroups = (groupList) => {
@@ -9315,7 +9608,7 @@ function AncestryBoard({
9315
9608
  children: sanitizeGroups(g.children || [])
9316
9609
  }));
9317
9610
  };
9318
- (0, import_react23.useEffect)(() => {
9611
+ (0, import_react24.useEffect)(() => {
9319
9612
  if (!isLoaded || !onSave) return;
9320
9613
  const timeoutId = setTimeout(async () => {
9321
9614
  setSaveStatus("saving");
@@ -9333,7 +9626,7 @@ function AncestryBoard({
9333
9626
  }, 3e3);
9334
9627
  return () => clearTimeout(timeoutId);
9335
9628
  }, [groups, isLoaded, onSave]);
9336
- (0, import_react23.useEffect)(() => {
9629
+ (0, import_react24.useEffect)(() => {
9337
9630
  if (!isOpen) return;
9338
9631
  const handleKeyDown = (e) => {
9339
9632
  if (e.key === "Escape") {
@@ -9349,7 +9642,7 @@ function AncestryBoard({
9349
9642
  window.addEventListener("keydown", handleKeyDown);
9350
9643
  return () => window.removeEventListener("keydown", handleKeyDown);
9351
9644
  }, [isOpen, onClose, pickingGroupId]);
9352
- const filtered = (0, import_react23.useMemo)(() => {
9645
+ const filtered = (0, import_react24.useMemo)(() => {
9353
9646
  const term = searchTerm.toLowerCase().trim();
9354
9647
  return availableAncestries.filter((a) => {
9355
9648
  if (!term) return true;
@@ -9488,27 +9781,27 @@ function AncestryBoard({
9488
9781
  });
9489
9782
  };
9490
9783
  if (!isOpen) return null;
9491
- return /* @__PURE__ */ import_react23.default.createElement(
9784
+ return /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(
9790
+ /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react23.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react23.default.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__ */ import_react23.default.createElement(import_react23.default.Fragment, null, /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiLoader, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ import_react23.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ import_react23.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, /* @__PURE__ */ import_react23.default.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ import_react23.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ import_react23.default.createElement("span", { className: "text-xs text-indigo-300 font-medium animate-pulse hidden sm:inline-block mr-2" }, "Selecione na lateral..."), canEdit && /* @__PURE__ */ import_react23.default.createElement(
9796
+ /* @__PURE__ */ import_react24.default.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react24.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react24.default.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__ */ import_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiLoader, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ import_react24.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ import_react24.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ import_react24.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ import_react24.default.createElement("span", { className: "text-xs text-indigo-300 font-medium animate-pulse hidden sm:inline-block mr-2" }, "Selecione na lateral..."), canEdit && /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(import_fi17.FiPlus, { size: 14, className: "text-indigo-400" }),
9510
- /* @__PURE__ */ import_react23.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
9511
- ), /* @__PURE__ */ import_react23.default.createElement(
9802
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlus, { size: 14, className: "text-indigo-400" }),
9803
+ /* @__PURE__ */ import_react24.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
9804
+ ), /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: `
9812
+ /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "relative group" }, /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiSearch, { 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__ */ import_react23.default.createElement(
9816
+ ` }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "relative group" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiSearch, { 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__ */ import_react24.default.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__ */ import_react23.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
9829
+ ))), /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(
9832
+ return /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement("div", { className: `
9844
+ /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement(import_fi17.FiPlus, { size: 16 }) : /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiLayers, { size: 14 })),
9555
- /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react23.default.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__ */ import_react23.default.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__ */ import_react23.default.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__ */ import_react23.default.createElement(import_fi17.FiCornerUpRight, { size: 10 }), /* @__PURE__ */ import_react23.default.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.description && /* @__PURE__ */ import_react23.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
9556
- !isPicking && /* @__PURE__ */ import_react23.default.createElement(
9847
+ ` }, isPicking ? /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlus, { size: 16 }) : /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiLayers, { size: 14 })),
9848
+ /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react24.default.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__ */ import_react24.default.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__ */ import_react24.default.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__ */ import_react24.default.createElement(import_fi18.FiCornerUpRight, { size: 10 }), /* @__PURE__ */ import_react24.default.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.description && /* @__PURE__ */ import_react24.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
9849
+ !isPicking && /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiPlay, { size: 14, className: "ml-0.5" }))
9859
+ /* @__PURE__ */ import_react24.default.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlay, { size: 14, className: "ml-0.5" }))
9567
9860
  )
9568
9861
  );
9569
- }))), /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ import_react23.default.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__ */ import_react23.default.createElement(import_fi17.FiLayers, { size: 24, className: "opacity-20" }), /* @__PURE__ */ import_react23.default.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ import_react23.default.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ import_react23.default.createElement(
9862
+ }))), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ import_react24.default.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__ */ import_react24.default.createElement(import_fi18.FiLayers, { size: 24, className: "opacity-20" }), /* @__PURE__ */ import_react24.default.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ import_react24.default.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ import_react24.default.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__ */ import_react23.default.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__ */ import_react23.default.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ import_react23.default.createElement("span", null, groups.length, " grupos raiz"))
9882
+ /* @__PURE__ */ import_react24.default.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__ */ import_react24.default.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ import_react24.default.createElement("span", null, groups.length, " grupos raiz"))
9590
9883
  )
9591
9884
  );
9592
9885
  }
@@ -9666,12 +9959,12 @@ function XViewScene({
9666
9959
  check_user_permission
9667
9960
  }) {
9668
9961
  var _a, _b, _c, _d, _e, _f, _g;
9669
- const { data: session, status } = (0, import_react25.useSession)();
9962
+ const { data: session, status } = (0, import_react26.useSession)();
9670
9963
  const router = (0, import_navigation.useRouter)();
9671
9964
  const searchParams = (0, import_navigation.useSearchParams)();
9672
9965
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
9673
9966
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
9674
- const viewParams = (0, import_react24.useMemo)(() => {
9967
+ const viewParams = (0, import_react25.useMemo)(() => {
9675
9968
  if (encryptedConfig) {
9676
9969
  const data = decryptData(encryptedConfig);
9677
9970
  if (data) {
@@ -9680,7 +9973,7 @@ function XViewScene({
9680
9973
  }
9681
9974
  return null;
9682
9975
  }, [encryptedConfig, session]);
9683
- (0, import_react24.useEffect)(() => {
9976
+ (0, import_react25.useEffect)(() => {
9684
9977
  async function verifyPermission() {
9685
9978
  if (!viewParams || !session || !check_user_permission) return;
9686
9979
  const { id, type, owner_id } = viewParams;
@@ -9710,64 +10003,65 @@ function XViewScene({
9710
10003
  setIsLoading(false);
9711
10004
  }
9712
10005
  }, [viewParams, session, status, check_user_permission]);
9713
- const sceneConfigId = (0, import_react24.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
9714
- const ownerId = (0, import_react24.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
9715
- const dbSaveUrl = (0, import_react24.useMemo)(() => {
10006
+ const sceneConfigId = (0, import_react25.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
10007
+ const ownerId = (0, import_react25.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
10008
+ const dbSaveUrl = (0, import_react25.useMemo)(() => {
9716
10009
  if (ownerId && sceneConfigId) {
9717
10010
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
9718
10011
  }
9719
10012
  return null;
9720
10013
  }, [ownerId, sceneConfigId]);
9721
- const sceneSaveUrl = (0, import_react24.useMemo)(() => {
10014
+ const sceneSaveUrl = (0, import_react25.useMemo)(() => {
9722
10015
  if (ownerId && sceneConfigId) {
9723
10016
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
9724
10017
  }
9725
10018
  return null;
9726
10019
  }, [ownerId, sceneConfigId]);
9727
- const ancestry_save_url = (0, import_react24.useMemo)(() => {
10020
+ const ancestry_save_url = (0, import_react25.useMemo)(() => {
9728
10021
  if (ownerId && sceneConfigId) {
9729
10022
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
9730
10023
  }
9731
10024
  return null;
9732
10025
  }, [ownerId, sceneConfigId]);
9733
- const sceneDataRef = (0, import_react24.useRef)(null);
9734
- const parentDataRef = (0, import_react24.useRef)(null);
9735
- const ancestryDataRef = (0, import_react24.useRef)(null);
9736
- const [isLoading, setIsLoading] = (0, import_react24.useState)(true);
9737
- const [permissionStatus, setPermissionStatus] = (0, import_react24.useState)("loading");
9738
- const [userPermissionRole, setUserPermissionRole] = (0, import_react24.useState)(null);
9739
- const [isInitialized, setIsInitialized] = (0, import_react24.useState)(false);
9740
- const [sceneVersion, setSceneVersion] = (0, import_react24.useState)(0);
9741
- const [contextMenu, setContextMenu] = (0, import_react24.useState)({ visible: false, x: 0, y: 0, nodeData: null });
9742
- const [multiContextMenu, setMultiContextMenu] = (0, import_react24.useState)({ visible: false, x: 0, y: 0, nodeIds: null });
9743
- const [relationshipMenu, setRelationshipMenu] = (0, import_react24.useState)({ visible: false, x: 0, y: 0, linkObject: null });
9744
- const [creationMode, setCreationMode] = (0, import_react24.useState)({ isActive: false, sourceNodeData: null });
9745
- const [versionMode, setVersionMode] = (0, import_react24.useState)({ isActive: false, sourceNodeData: null });
9746
- const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react24.useState)(false);
9747
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react24.useState)(false);
9748
- const [ancestryMode, setAncestryMode] = (0, import_react24.useState)({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
9749
- const [readingMode, setReadingMode] = (0, import_react24.useState)({
10026
+ const sceneDataRef = (0, import_react25.useRef)(null);
10027
+ const parentDataRef = (0, import_react25.useRef)(null);
10028
+ const ancestryDataRef = (0, import_react25.useRef)(null);
10029
+ const [isLoading, setIsLoading] = (0, import_react25.useState)(true);
10030
+ const [permissionStatus, setPermissionStatus] = (0, import_react25.useState)("loading");
10031
+ const [userPermissionRole, setUserPermissionRole] = (0, import_react25.useState)(null);
10032
+ const [isInitialized, setIsInitialized] = (0, import_react25.useState)(false);
10033
+ const [sceneVersion, setSceneVersion] = (0, import_react25.useState)(0);
10034
+ const [contextMenu, setContextMenu] = (0, import_react25.useState)({ visible: false, x: 0, y: 0, nodeData: null });
10035
+ const [multiContextMenu, setMultiContextMenu] = (0, import_react25.useState)({ visible: false, x: 0, y: 0, nodeIds: null });
10036
+ const [relationshipMenu, setRelationshipMenu] = (0, import_react25.useState)({ visible: false, x: 0, y: 0, linkObject: null });
10037
+ const [creationMode, setCreationMode] = (0, import_react25.useState)({ isActive: false, sourceNodeData: null });
10038
+ const [versionMode, setVersionMode] = (0, import_react25.useState)({ isActive: false, sourceNodeData: null });
10039
+ const [questMode, setQuestMode] = (0, import_react25.useState)({ isActive: false });
10040
+ const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react25.useState)(false);
10041
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react25.useState)(false);
10042
+ const [ancestryMode, setAncestryMode] = (0, import_react25.useState)({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
10043
+ const [readingMode, setReadingMode] = (0, import_react25.useState)({
9750
10044
  isActive: false,
9751
10045
  ancestry: null,
9752
10046
  branchStack: [],
9753
10047
  autoAbstraction: false
9754
10048
  });
9755
- const [formPosition, setFormPosition] = (0, import_react24.useState)({ left: 16, top: 16, opacity: 0 });
9756
- const [detailsNode, setDetailsNode] = (0, import_react24.useState)(null);
9757
- const [detailsLink, setDetailsLink] = (0, import_react24.useState)(null);
9758
- const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react24.useState)(null);
9759
- const [imageViewer, setImageViewer] = (0, import_react24.useState)({ visible: false, images: [], startIndex: 0 });
9760
- const [editingAncestryRel, setEditingAncestryRel] = (0, import_react24.useState)({ visible: false, data: null, path: null });
9761
- const [isImportModalOpen, setIsImportModalOpen] = (0, import_react24.useState)(false);
9762
- const [importSuccessMessage, setImportSuccessMessage] = (0, import_react24.useState)("");
9763
- const [highlightedNodeId, setHighlightedNodeId] = (0, import_react24.useState)(null);
9764
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react24.useState)(false);
9765
- const [ancestryBoardData, setAncestryBoardData] = (0, import_react24.useState)([]);
9766
- const [isSidebarOpen, setIsSidebarOpen] = (0, import_react24.useState)(false);
9767
- const mountRef = (0, import_react24.useRef)(null);
9768
- const tooltipRef = (0, import_react24.useRef)(null);
9769
- const formRef = (0, import_react24.useRef)(null);
9770
- const stateRef = (0, import_react24.useRef)({
10049
+ const [formPosition, setFormPosition] = (0, import_react25.useState)({ left: 16, top: 16, opacity: 0 });
10050
+ const [detailsNode, setDetailsNode] = (0, import_react25.useState)(null);
10051
+ const [detailsLink, setDetailsLink] = (0, import_react25.useState)(null);
10052
+ const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react25.useState)(null);
10053
+ const [imageViewer, setImageViewer] = (0, import_react25.useState)({ visible: false, images: [], startIndex: 0 });
10054
+ const [editingAncestryRel, setEditingAncestryRel] = (0, import_react25.useState)({ visible: false, data: null, path: null });
10055
+ const [isImportModalOpen, setIsImportModalOpen] = (0, import_react25.useState)(false);
10056
+ const [importSuccessMessage, setImportSuccessMessage] = (0, import_react25.useState)("");
10057
+ const [highlightedNodeId, setHighlightedNodeId] = (0, import_react25.useState)(null);
10058
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react25.useState)(false);
10059
+ const [ancestryBoardData, setAncestryBoardData] = (0, import_react25.useState)([]);
10060
+ const [isSidebarOpen, setIsSidebarOpen] = (0, import_react25.useState)(false);
10061
+ const mountRef = (0, import_react25.useRef)(null);
10062
+ const tooltipRef = (0, import_react25.useRef)(null);
10063
+ const formRef = (0, import_react25.useRef)(null);
10064
+ const stateRef = (0, import_react25.useRef)({
9771
10065
  readMode: {
9772
10066
  currentMaxIndex: 0,
9773
10067
  progressMap: {}
@@ -9812,10 +10106,10 @@ function XViewScene({
9812
10106
  minWidth: 320,
9813
10107
  maxWidth: maxReadPanelW
9814
10108
  });
9815
- (0, import_react24.useEffect)(() => {
10109
+ (0, import_react25.useEffect)(() => {
9816
10110
  stateRef.current.ancestry = ancestryMode;
9817
10111
  }, [ancestryMode]);
9818
- (0, import_react24.useEffect)(() => {
10112
+ (0, import_react25.useEffect)(() => {
9819
10113
  var _a2;
9820
10114
  if (!isInitialized) return;
9821
10115
  const map = /* @__PURE__ */ new Map();
@@ -9836,10 +10130,10 @@ function XViewScene({
9836
10130
  }
9837
10131
  stateRef.current.nodeIdToParentFileMap = map;
9838
10132
  }, [isInitialized, sceneVersion]);
9839
- const handleNavigateBack = (0, import_react24.useCallback)(() => {
10133
+ const handleNavigateBack = (0, import_react25.useCallback)(() => {
9840
10134
  router.push("/dashboard/scenes");
9841
10135
  }, [router]);
9842
- const handleConfirmImport = (0, import_react24.useCallback)(
10136
+ const handleConfirmImport = (0, import_react25.useCallback)(
9843
10137
  async (importPayload) => {
9844
10138
  var _a2, _b2;
9845
10139
  let files = [];
@@ -9937,7 +10231,7 @@ function XViewScene({
9937
10231
  const handleOpenImageViewer = (images, startIndex) => {
9938
10232
  setImageViewer({ visible: true, images, startIndex });
9939
10233
  };
9940
- const tweenToTarget = (0, import_react24.useCallback)((target, zoomFactor = 1, forcedDirection = null) => {
10234
+ const tweenToTarget = (0, import_react25.useCallback)((target, zoomFactor = 1, forcedDirection = null) => {
9941
10235
  const { camera, controls, tweenGroup } = stateRef.current;
9942
10236
  if (!camera || !controls || !tweenGroup) return;
9943
10237
  const targetPos = target instanceof THREE3.Mesh ? target.getWorldPosition(new THREE3.Vector3()) : target;
@@ -9960,7 +10254,7 @@ function XViewScene({
9960
10254
  if (!t || typeof t.closest !== "function") return false;
9961
10255
  return !!t.closest(".ui-overlay");
9962
10256
  };
9963
- const buildFullAncestryTree = (0, import_react24.useCallback)((idTree, nodes, ancestries = []) => {
10257
+ const buildFullAncestryTree = (0, import_react25.useCallback)((idTree, nodes, ancestries = []) => {
9964
10258
  if (!idTree) return null;
9965
10259
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
9966
10260
  const ancestryMap = new Map(ancestries.map((a) => [String(a.ancestry_id), a]));
@@ -10036,7 +10330,7 @@ function XViewScene({
10036
10330
  }
10037
10331
  return recursiveBuild(idTree);
10038
10332
  }, []);
10039
- const handleActivateTimeline = (0, import_react24.useCallback)(() => {
10333
+ const handleActivateTimeline = (0, import_react25.useCallback)(() => {
10040
10334
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
10041
10335
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
10042
10336
  while (timelineIntervalsGroup.children.length > 0) {
@@ -10189,7 +10483,7 @@ function XViewScene({
10189
10483
  }
10190
10484
  });
10191
10485
  }, []);
10192
- const handleVersionTimeline = (0, import_react24.useCallback)((sourceMesh, versionMeshes) => {
10486
+ const handleVersionTimeline = (0, import_react25.useCallback)((sourceMesh, versionMeshes) => {
10193
10487
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
10194
10488
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0) return;
10195
10489
  versionMeshes.forEach((mesh) => {
@@ -10312,7 +10606,7 @@ function XViewScene({
10312
10606
  }
10313
10607
  });
10314
10608
  }, []);
10315
- (0, import_react24.useEffect)(() => {
10609
+ (0, import_react25.useEffect)(() => {
10316
10610
  async function fetchAllData(configPath, ownerId2) {
10317
10611
  var _a2, _b2;
10318
10612
  if (!get_scene_view_data) {
@@ -10384,12 +10678,12 @@ function XViewScene({
10384
10678
  focusNodeId,
10385
10679
  focusAncestryId
10386
10680
  ]);
10387
- const isNodeInView = (0, import_react24.useCallback)((id) => {
10681
+ const isNodeInView = (0, import_react25.useCallback)((id) => {
10388
10682
  const key = String(id);
10389
10683
  const objs = stateRef.current.nodeObjects || {};
10390
10684
  return !!objs[key];
10391
10685
  }, []);
10392
- const addOrUpdateNodeMesh = (0, import_react24.useCallback)((nodeData, position, suppressVersionUpdate = false) => {
10686
+ const addOrUpdateNodeMesh = (0, import_react25.useCallback)((nodeData, position, suppressVersionUpdate = false) => {
10393
10687
  const { graphGroup, nodeObjects, clickableNodes, glowTexture, tweenGroup } = stateRef.current;
10394
10688
  const nodeId = String(nodeData.id);
10395
10689
  if (nodeObjects[nodeId]) {
@@ -10416,7 +10710,7 @@ function XViewScene({
10416
10710
  }
10417
10711
  return mesh;
10418
10712
  }, []);
10419
- (0, import_react24.useEffect)(() => {
10713
+ (0, import_react25.useEffect)(() => {
10420
10714
  if (!isInitialized || !sceneDataRef.current) return;
10421
10715
  const currentMount = mountRef.current;
10422
10716
  if (!currentMount) return;
@@ -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();
@@ -11049,7 +11355,7 @@ function XViewScene({
11049
11355
  }
11050
11356
  };
11051
11357
  }, [isInitialized, tweenToTarget, dbSaveUrl, isNodeInView, addOrUpdateNodeMesh, handleActivateTimeline, get_scene_view_data, save_view_data]);
11052
- const handleGhostNodeImageChange = (0, import_react24.useCallback)((useImage, imageUrl) => {
11358
+ const handleGhostNodeImageChange = (0, import_react25.useCallback)((useImage, imageUrl) => {
11053
11359
  const { node: ghostNode, line: ghostLine, aura: ghostAura } = stateRef.current.ghostElements;
11054
11360
  const { graphGroup, glowTexture } = stateRef.current;
11055
11361
  if (!ghostNode || !graphGroup) return;
@@ -11091,7 +11397,7 @@ function XViewScene({
11091
11397
  aura: newGhostNode.getObjectByName("aura")
11092
11398
  };
11093
11399
  }, []);
11094
- const handleGhostNodeIntensityChange = (0, import_react24.useCallback)((newIntensity) => {
11400
+ const handleGhostNodeIntensityChange = (0, import_react25.useCallback)((newIntensity) => {
11095
11401
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
11096
11402
  if (!ghostNode) return;
11097
11403
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -11112,7 +11418,7 @@ function XViewScene({
11112
11418
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
11113
11419
  }
11114
11420
  }, []);
11115
- const handleDetailNodeIntensityChange = (0, import_react24.useCallback)((nodeId, newIntensity) => {
11421
+ const handleDetailNodeIntensityChange = (0, import_react25.useCallback)((nodeId, newIntensity) => {
11116
11422
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
11117
11423
  if (!mesh) return;
11118
11424
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -11258,7 +11564,7 @@ function XViewScene({
11258
11564
  mountRef.current.style.cursor = "default";
11259
11565
  }
11260
11566
  };
11261
- const handleAncestryTreeUpdate = (0, import_react24.useCallback)((newTree, extraData = null) => {
11567
+ const handleAncestryTreeUpdate = (0, import_react25.useCallback)((newTree, extraData = null) => {
11262
11568
  setAncestryMode((prev) => {
11263
11569
  const prevTreeStr = JSON.stringify(prev.tree);
11264
11570
  const newTreeStr = JSON.stringify(newTree);
@@ -11278,7 +11584,7 @@ function XViewScene({
11278
11584
  };
11279
11585
  });
11280
11586
  }, []);
11281
- const actionHandlerContext = (0, import_react24.useMemo)(
11587
+ const actionHandlerContext = (0, import_react25.useMemo)(
11282
11588
  () => {
11283
11589
  var _a2;
11284
11590
  return {
@@ -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,7 +11645,98 @@ function XViewScene({
11328
11645
  const handleStartVersioning = (nodeData) => {
11329
11646
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
11330
11647
  };
11331
- const handleClearAncestryVisuals = (0, import_react24.useCallback)((ancestryId) => {
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: import_short_uuid2.default.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_${import_short_uuid2.default.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
+ };
11739
+ const handleClearAncestryVisuals = (0, import_react25.useCallback)((ancestryId) => {
11332
11740
  const { renderedAncestries, ancestryGroup } = stateRef.current;
11333
11741
  const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
11334
11742
  if (renderIndex !== -1) {
@@ -11342,7 +11750,7 @@ function XViewScene({
11342
11750
  stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
11343
11751
  }
11344
11752
  }, []);
11345
- const handleRenderAncestry = (0, import_react24.useCallback)(
11753
+ const handleRenderAncestry = (0, import_react25.useCallback)(
11346
11754
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
11347
11755
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11348
11756
  if (!ancestryObject || !ancestryObject.tree) {
@@ -11758,7 +12166,7 @@ function XViewScene({
11758
12166
  },
11759
12167
  [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, readingMode.isActive, ancestryMode.isActive]
11760
12168
  );
11761
- const handleRenderAbstractionTree = (0, import_react24.useCallback)((ancestryObject, targetNodeId = null) => {
12169
+ const handleRenderAbstractionTree = (0, import_react25.useCallback)((ancestryObject, targetNodeId = null) => {
11762
12170
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11763
12171
  if (!ancestryObject || !ancestryObject.abstraction_tree) return;
11764
12172
  const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
@@ -11819,7 +12227,7 @@ function XViewScene({
11819
12227
  stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
11820
12228
  tweenToTarget(rootTargetPos, 0.7);
11821
12229
  }, [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, handleClearAncestryVisuals]);
11822
- const handleReadModeBranchNav = (0, import_react24.useCallback)((nodeId, action, direction = "right") => {
12230
+ const handleReadModeBranchNav = (0, import_react25.useCallback)((nodeId, action, direction = "right") => {
11823
12231
  const { ancestry, branchStack } = readingMode;
11824
12232
  if (!ancestry || !ancestry.tree) return;
11825
12233
  const allAncestries = ancestryDataRef.current || [];
@@ -11960,13 +12368,13 @@ function XViewScene({
11960
12368
  }));
11961
12369
  }
11962
12370
  }, [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]);
11963
- const handleReadModeHighlight = (0, import_react24.useCallback)((nodeId) => {
12371
+ const handleReadModeHighlight = (0, import_react25.useCallback)((nodeId) => {
11964
12372
  if (stateRef.current.highlightedNodeId !== nodeId) {
11965
12373
  stateRef.current.highlightedNodeId = nodeId;
11966
12374
  }
11967
12375
  setHighlightedNodeId(nodeId);
11968
12376
  }, []);
11969
- const activeNodeBranches = (0, import_react24.useMemo)(() => {
12377
+ const activeNodeBranches = (0, import_react25.useMemo)(() => {
11970
12378
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree) return null;
11971
12379
  const fullTree = buildFullAncestryTree(
11972
12380
  readingMode.ancestry.tree,
@@ -12003,7 +12411,7 @@ function XViewScene({
12003
12411
  }
12004
12412
  return null;
12005
12413
  }, [highlightedNodeId, readingMode.ancestry, buildFullAncestryTree, readingMode.branchStack, ancestryDataRef.current]);
12006
- const backNavigationInfo = (0, import_react24.useMemo)(() => {
12414
+ const backNavigationInfo = (0, import_react25.useMemo)(() => {
12007
12415
  const { branchStack } = readingMode;
12008
12416
  if (!branchStack || branchStack.length === 0) return null;
12009
12417
  const lastStep = branchStack[branchStack.length - 1];
@@ -12014,7 +12422,7 @@ function XViewScene({
12014
12422
  name: "Voltar para anterior"
12015
12423
  };
12016
12424
  }, [readingMode.branchStack]);
12017
- const getReadModeDisplayContext = (0, import_react24.useMemo)(() => {
12425
+ const getReadModeDisplayContext = (0, import_react25.useMemo)(() => {
12018
12426
  const { ancestry, branchStack } = readingMode;
12019
12427
  if (!ancestry) return null;
12020
12428
  if (branchStack.length === 0) {
@@ -12055,7 +12463,7 @@ function XViewScene({
12055
12463
  customProperties: branchProps
12056
12464
  };
12057
12465
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
12058
- const readModeAbstractionTree = (0, import_react24.useMemo)(() => {
12466
+ const readModeAbstractionTree = (0, import_react25.useMemo)(() => {
12059
12467
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
12060
12468
  return null;
12061
12469
  }
@@ -12067,7 +12475,7 @@ function XViewScene({
12067
12475
  allAncestries
12068
12476
  );
12069
12477
  }, [readingMode.isActive, readingMode.ancestry, buildFullAncestryTree, sceneVersion]);
12070
- const handleStartReadingAncestry = (0, import_react24.useCallback)(
12478
+ const handleStartReadingAncestry = (0, import_react25.useCallback)(
12071
12479
  async (ancestryObject) => {
12072
12480
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
12073
12481
  if (!ancestryObject || !ancestryObject.tree) {
@@ -12102,7 +12510,7 @@ function XViewScene({
12102
12510
  },
12103
12511
  [handleRenderAncestry, handleRenderAbstractionTree]
12104
12512
  );
12105
- const handleReadModeSectionChange = (0, import_react24.useCallback)((activeSectionId) => {
12513
+ const handleReadModeSectionChange = (0, import_react25.useCallback)((activeSectionId) => {
12106
12514
  const { ancestry, branchStack } = readingMode;
12107
12515
  if (!ancestry || !readingMode.isActive) return;
12108
12516
  let targetObj = ancestry;
@@ -12171,10 +12579,10 @@ function XViewScene({
12171
12579
  }, 0);
12172
12580
  handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
12173
12581
  }, [readingMode, handleRenderAncestry, buildFullAncestryTree, ancestryDataRef.current]);
12174
- const handleCloseReadMode = (0, import_react24.useCallback)(() => {
12582
+ const handleCloseReadMode = (0, import_react25.useCallback)(() => {
12175
12583
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
12176
12584
  }, []);
12177
- const handleAncestrySectionChange = (0, import_react24.useCallback)((activeSectionId, ancestryOverride = null, rotation = 0) => {
12585
+ const handleAncestrySectionChange = (0, import_react25.useCallback)((activeSectionId, ancestryOverride = null, rotation = 0) => {
12178
12586
  var _a2, _b2;
12179
12587
  const currentMode = stateRef.current.ancestry;
12180
12588
  let targetObj = ancestryOverride;
@@ -12226,7 +12634,7 @@ function XViewScene({
12226
12634
  const renderPayload = { ...targetObj, tree: treeToRender };
12227
12635
  handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
12228
12636
  }, [handleRenderAncestry]);
12229
- const handleEditAncestry = (0, import_react24.useCallback)(
12637
+ const handleEditAncestry = (0, import_react25.useCallback)(
12230
12638
  async (ancestryObject) => {
12231
12639
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
12232
12640
  if (!ancestryObject || !ancestryObject.tree) {
@@ -12265,7 +12673,7 @@ function XViewScene({
12265
12673
  const handleSelectAncestryParent = (nodeId) => {
12266
12674
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
12267
12675
  };
12268
- const handleRemoveFromAncestry = (0, import_react24.useCallback)((pathToRemove) => {
12676
+ const handleRemoveFromAncestry = (0, import_react25.useCallback)((pathToRemove) => {
12269
12677
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
12270
12678
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
12271
12679
  return;
@@ -12290,7 +12698,7 @@ function XViewScene({
12290
12698
  return { ...prev, tree: newTree };
12291
12699
  });
12292
12700
  }, []);
12293
- const handleSaveAncestry = (0, import_react24.useCallback)(
12701
+ const handleSaveAncestry = (0, import_react25.useCallback)(
12294
12702
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
12295
12703
  const treeToUse = treeOverride || ancestryMode.tree;
12296
12704
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -12494,7 +12902,7 @@ function XViewScene({
12494
12902
  });
12495
12903
  setEditingAncestryRel({ visible: false, data: null, path: null });
12496
12904
  };
12497
- const handleDeleteAncestry = (0, import_react24.useCallback)(
12905
+ const handleDeleteAncestry = (0, import_react25.useCallback)(
12498
12906
  async (ancestryIdToDelete) => {
12499
12907
  if (!ancestryIdToDelete) {
12500
12908
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -12556,20 +12964,20 @@ function XViewScene({
12556
12964
  },
12557
12965
  [save_view_data, delete_file_action]
12558
12966
  );
12559
- const handleOpenAncestryBoard = (0, import_react24.useCallback)(() => {
12967
+ const handleOpenAncestryBoard = (0, import_react25.useCallback)(() => {
12560
12968
  setIsAncestryBoardOpen(true);
12561
12969
  }, []);
12562
- const handleSelectAncestryFromBoard = (0, import_react24.useCallback)((ancestry) => {
12970
+ const handleSelectAncestryFromBoard = (0, import_react25.useCallback)((ancestry) => {
12563
12971
  setIsAncestryBoardOpen(false);
12564
12972
  setIsSidebarOpen(false);
12565
12973
  handleStartReadingAncestry(ancestry);
12566
12974
  }, [handleStartReadingAncestry]);
12567
- const handleSaveAncestryBoard = (0, import_react24.useCallback)(async (groups) => {
12975
+ const handleSaveAncestryBoard = (0, import_react25.useCallback)(async (groups) => {
12568
12976
  if (!sceneConfigId || !viewParams || !session) return;
12569
12977
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
12570
12978
  await save_ancestry_board_action(sceneConfigId, sceneType, groups, session, ownerId);
12571
12979
  }, [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]);
12572
- const existingNodeTypes = (0, import_react24.useMemo)(() => {
12980
+ const existingNodeTypes = (0, import_react25.useMemo)(() => {
12573
12981
  if (!parentDataRef.current) {
12574
12982
  return [];
12575
12983
  }
@@ -12579,7 +12987,7 @@ function XViewScene({
12579
12987
  })).filter(Boolean);
12580
12988
  return [...new Set(allTypes)];
12581
12989
  }, [parentDataRef.current, sceneVersion]);
12582
- const searchableDbNodes = (0, import_react24.useMemo)(() => {
12990
+ const searchableDbNodes = (0, import_react25.useMemo)(() => {
12583
12991
  if (!parentDataRef.current) {
12584
12992
  return [];
12585
12993
  }
@@ -12588,13 +12996,14 @@ function XViewScene({
12588
12996
  return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
12589
12997
  });
12590
12998
  }, [parentDataRef.current, sceneVersion]);
12591
- const handleAddExistingNode = (0, import_react24.useCallback)(
12999
+ const handleAddExistingNode = (0, import_react25.useCallback)(
12592
13000
  (nodeId) => {
12593
13001
  return userActionHandlers.handleAddExistingNodeById(actionHandlerContext, nodeId);
12594
13002
  },
12595
13003
  [actionHandlerContext]
12596
13004
  );
12597
- const handleSaveCurrentView = (0, import_react24.useCallback)(async () => {
13005
+ const handleSaveCurrentView = (0, import_react25.useCallback)(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,25 +13025,30 @@ 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]);
12630
- const allAvailableNodes = (0, import_react24.useMemo)(() => {
13043
+ }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
13044
+ const allAvailableNodes = (0, import_react25.useMemo)(() => {
12631
13045
  if (!parentDataRef.current) return [];
12632
13046
  return Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
12633
13047
  }, [sceneVersion, isInitialized]);
12634
- const allAvailableAncestries = (0, import_react24.useMemo)(() => {
13048
+ const allAvailableAncestries = (0, import_react25.useMemo)(() => {
12635
13049
  return ancestryDataRef.current || [];
12636
13050
  }, [sceneVersion, isInitialized]);
12637
- const handleOpenReference = (0, import_react24.useCallback)((referenceData) => {
13051
+ const handleOpenReference = (0, import_react25.useCallback)((referenceData) => {
12638
13052
  const { type, id } = referenceData;
12639
13053
  if (type === "node") {
12640
13054
  const targetNode = allAvailableNodes.find((n) => String(n.id) === String(id));
@@ -12661,17 +13075,17 @@ function XViewScene({
12661
13075
  }
12662
13076
  }
12663
13077
  }, [allAvailableNodes, allAvailableAncestries, handleEditAncestry, tweenToTarget]);
12664
- const handleToggleAncestryAddMode = (0, import_react24.useCallback)(() => {
13078
+ const handleToggleAncestryAddMode = (0, import_react25.useCallback)(() => {
12665
13079
  setAncestryMode((prev) => ({ ...prev, isAddingNodes: !prev.isAddingNodes }));
12666
13080
  }, []);
12667
- const handleFocusNode = (0, import_react24.useCallback)((nodeData) => {
13081
+ const handleFocusNode = (0, import_react25.useCallback)((nodeData) => {
12668
13082
  if (!nodeData) return;
12669
13083
  const nodeMesh = stateRef.current.nodeObjects[String(nodeData.id)];
12670
13084
  if (nodeMesh) {
12671
13085
  tweenToTarget(nodeMesh, 1.2);
12672
13086
  }
12673
13087
  }, [tweenToTarget]);
12674
- const availableDatasets = (0, import_react24.useMemo)(() => {
13088
+ const availableDatasets = (0, import_react25.useMemo)(() => {
12675
13089
  if (!sceneDataRef.current || !parentDataRef.current) return [];
12676
13090
  return sceneDataRef.current.parent_dbs.map((db) => {
12677
13091
  var _a2;
@@ -12683,7 +13097,7 @@ function XViewScene({
12683
13097
  }, [sceneVersion, isInitialized]);
12684
13098
  const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(String(creationMode.sourceNodeData.id))) == null ? void 0 : _b.parentFileId : null;
12685
13099
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
12686
- (0, import_react24.useEffect)(() => {
13100
+ (0, import_react25.useEffect)(() => {
12687
13101
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
12688
13102
  const nodeObjects = stateRef.current.nodeObjects || {};
12689
13103
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -12697,7 +13111,7 @@ function XViewScene({
12697
13111
  }
12698
13112
  }
12699
13113
  }, [isInitialized, sceneVersion, focusNodeId, hasFocusedInitial, tweenToTarget]);
12700
- (0, import_react24.useEffect)(() => {
13114
+ (0, import_react25.useEffect)(() => {
12701
13115
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
12702
13116
  const ancestries = ancestryDataRef.current || [];
12703
13117
  const targetAncestry = ancestries.find((a) => String(a.ancestry_id) === String(focusAncestryId));
@@ -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__ */ import_react24.default.createElement(LoadingScreen, null);
13129
+ return /* @__PURE__ */ import_react25.default.createElement(LoadingScreen, null);
12716
13130
  }
12717
13131
  if (permissionStatus === "denied") {
12718
- return /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react24.default.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__ */ import_react24.default.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__ */ import_react24.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ import_react24.default.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__ */ import_react24.default.createElement(
13132
+ return /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react25.default.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__ */ import_react25.default.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__ */ import_react25.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ import_react25.default.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__ */ import_react25.default.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__ */ import_react24.default.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__ */ import_react24.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" })),
13138
+ /* @__PURE__ */ import_react25.default.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__ */ import_react25.default.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__ */ import_react24.default.createElement(
13142
+ return /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13154
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13174
+ creationMode.isActive && /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13199
+ versionMode.isActive && /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13218
+ questMode.isActive && /* @__PURE__ */ import_react25.default.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__ */ import_react25.default.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__ */ import_react24.default.createElement(
13238
+ /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13249
+ /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13284
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13311
+ editingAncestryRel.visible && /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13325
+ detailsNode && /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13352
+ detailsLink && /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13366
+ ancestryLinkDetails && /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13377
+ /* @__PURE__ */ import_react25.default.createElement(
12950
13378
  "div",
12951
13379
  {
12952
13380
  ref: tooltipRef,
@@ -12973,7 +13401,7 @@ function XViewScene({
12973
13401
  }
12974
13402
  }
12975
13403
  ),
12976
- /* @__PURE__ */ import_react24.default.createElement(
13404
+ /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13427
+ /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13438
+ /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(ImageViewer, { data: imageViewer, onClose: () => setImageViewer({ ...imageViewer, visible: false }) }),
13029
- /* @__PURE__ */ import_react24.default.createElement(
13456
+ /* @__PURE__ */ import_react25.default.createElement(ImageViewer, { data: imageViewer, onClose: () => setImageViewer({ ...imageViewer, visible: false }) }),
13457
+ /* @__PURE__ */ import_react25.default.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__ */ import_react24.default.createElement(
13470
+ /* @__PURE__ */ import_react25.default.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}`);