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

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 +723 -351
  2. package/dist/index.mjs +643 -271
  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");
@@ -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 };
@@ -1846,7 +1848,7 @@ var userActionHandlers = {
1846
1848
  version_node: { is_version: true, parent_node: sourceNodeData.id }
1847
1849
  };
1848
1850
  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);
1851
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id, context.sceneConfigId, context.ownerId);
1850
1852
  if (!parentInfo || !parentInfo.ownerId) {
1851
1853
  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
1854
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio.");
@@ -2022,7 +2024,7 @@ var userActionHandlers = {
2022
2024
  userActionHandlers.handleCancelConnection(context);
2023
2025
  return;
2024
2026
  }
2025
- const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id);
2027
+ const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id, context.sceneConfigId, context.ownerId);
2026
2028
  if (!sourceParentInfo || !sourceParentInfo.ownerId) {
2027
2029
  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
2030
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio.");
@@ -2111,8 +2113,8 @@ var userActionHandlers = {
2111
2113
  } else {
2112
2114
  newTargetId = newEndNodeData.id;
2113
2115
  }
2114
- const originalParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldSourceId);
2115
- const newParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newSourceId);
2116
+ const originalParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldSourceId, context.sceneConfigId, context.ownerId);
2117
+ const newParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newSourceId, context.sceneConfigId, context.ownerId);
2116
2118
  if (!originalParentInfo || !newParentInfo || !originalParentInfo.ownerId || !newParentInfo.ownerId) {
2117
2119
  console.error("N\xE3o foi poss\xEDvel encontrar informa\xE7\xF5es dos arquivos pai para o relink.");
2118
2120
  alert("Ocorreu um erro ao identificar os arquivos pai para salvar a altera\xE7\xE3o.");
@@ -2180,7 +2182,7 @@ var userActionHandlers = {
2180
2182
  console.error("Tentativa de deletar um link sem ID.", linkObject.userData);
2181
2183
  return;
2182
2184
  }
2183
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkObject.userData.source);
2185
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkObject.userData.source, context.sceneConfigId, context.ownerId);
2184
2186
  if (!parentInfo || !parentInfo.ownerId) {
2185
2187
  console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o link:", linkIdToDelete);
2186
2188
  alert("Ocorreu um erro ao identificar o arquivo pai da rela\xE7\xE3o para exclus\xE3o.");
@@ -2192,9 +2194,24 @@ var userActionHandlers = {
2192
2194
  const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileId]));
2193
2195
  const newLinks = (specificParentData.links || []).filter((l) => String(l.id) !== String(linkIdToDelete));
2194
2196
  specificParentData.links = newLinks;
2195
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2197
+ let filenameToSave;
2198
+ let payloadToSave;
2199
+ if (parentFileId === context.sceneConfigId) {
2200
+ filenameToSave = context.sceneSaveUrl;
2201
+ sceneDataRef.current.links = sceneDataRef.current.links.filter((l) => String(l.id) !== String(linkIdToDelete));
2202
+ payloadToSave = {
2203
+ parent_dbs: sceneDataRef.current.parent_dbs,
2204
+ nodes: sceneDataRef.current.nodes,
2205
+ links: sceneDataRef.current.links,
2206
+ quest_nodes: specificParentData.nodes,
2207
+ quest_links: specificParentData.links
2208
+ };
2209
+ } else {
2210
+ filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2211
+ payloadToSave = specificParentData;
2212
+ }
2196
2213
  try {
2197
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2214
+ await context.actions.save_view_data(filenameToSave, payloadToSave);
2198
2215
  graphDataRef.current[parentFileId] = specificParentData;
2199
2216
  setters.setDetailsLink((prev) => String(prev == null ? void 0 : prev.id) === String(linkIdToDelete) ? null : prev);
2200
2217
  if (stateRef.current.hoveredLink === linkObject) {
@@ -2357,7 +2374,7 @@ var userActionHandlers = {
2357
2374
  }
2358
2375
  const changesByParentFile = {};
2359
2376
  for (const nodeId of strNodeIdsToDelete) {
2360
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeId);
2377
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeId, context.sceneConfigId, context.ownerId);
2361
2378
  if (!parentInfo || !parentInfo.ownerId) {
2362
2379
  console.warn(`Node com ID ${nodeId} n\xE3o encontrado ou sem ownerId. Ignorando.`);
2363
2380
  continue;
@@ -2391,8 +2408,26 @@ var userActionHandlers = {
2391
2408
  originalData.links = (originalData.links || []).filter(
2392
2409
  (l) => !linksToDelete.has(String(l.id))
2393
2410
  );
2394
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2395
- savePromises.push(context.actions.save_view_data(filenameForSpecificParent, originalData));
2411
+ let filenameToSave;
2412
+ let payloadToSave;
2413
+ if (parentFileId === context.sceneConfigId) {
2414
+ filenameToSave = context.sceneSaveUrl;
2415
+ const strNodesToDelete = Array.from(nodesToDelete).map(String);
2416
+ const strLinksToDelete = Array.from(linksToDelete).map(String);
2417
+ sceneDataRef.current.nodes = sceneDataRef.current.nodes.filter((n) => !strNodesToDelete.includes(String(n.id)));
2418
+ sceneDataRef.current.links = sceneDataRef.current.links.filter((l) => !strLinksToDelete.includes(String(l.id)));
2419
+ payloadToSave = {
2420
+ parent_dbs: sceneDataRef.current.parent_dbs,
2421
+ nodes: sceneDataRef.current.nodes,
2422
+ links: sceneDataRef.current.links,
2423
+ quest_nodes: originalData.nodes,
2424
+ quest_links: originalData.links
2425
+ };
2426
+ } else {
2427
+ filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2428
+ payloadToSave = originalData;
2429
+ }
2430
+ savePromises.push(context.actions.save_view_data(filenameToSave, payloadToSave));
2396
2431
  updatedParentDataCache[parentFileId] = originalData;
2397
2432
  }
2398
2433
  }
@@ -2424,7 +2459,7 @@ var userActionHandlers = {
2424
2459
  if (!nodeData || !graphDataRef.current || !sceneDataRef.current) return;
2425
2460
  const nodeIdToDelete = nodeData.id;
2426
2461
  const strNodeId = String(nodeIdToDelete);
2427
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeIdToDelete);
2462
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeIdToDelete, context.sceneConfigId, context.ownerId);
2428
2463
  if (!parentInfo || !parentInfo.ownerId) {
2429
2464
  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
2465
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para exclus\xE3o.");
@@ -2436,9 +2471,27 @@ var userActionHandlers = {
2436
2471
  const newLinks = (specificParentData.links || []).filter((l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId);
2437
2472
  specificParentData.nodes = newNodes;
2438
2473
  specificParentData.links = newLinks;
2439
- const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2474
+ let filenameToSave;
2475
+ let payloadToSave;
2476
+ if (parentFileId === context.sceneConfigId) {
2477
+ filenameToSave = context.sceneSaveUrl;
2478
+ const newVisualNodes = sceneDataRef.current.nodes.filter((n) => String(n.id) !== strNodeId);
2479
+ const newVisualLinks = sceneDataRef.current.links.filter((l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId);
2480
+ sceneDataRef.current.nodes = newVisualNodes;
2481
+ sceneDataRef.current.links = newVisualLinks;
2482
+ payloadToSave = {
2483
+ parent_dbs: sceneDataRef.current.parent_dbs,
2484
+ nodes: newVisualNodes,
2485
+ links: newVisualLinks,
2486
+ quest_nodes: specificParentData.nodes,
2487
+ quest_links: specificParentData.links
2488
+ };
2489
+ } else {
2490
+ filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2491
+ payloadToSave = specificParentData;
2492
+ }
2440
2493
  try {
2441
- await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
2494
+ await context.actions.save_view_data(filenameToSave, payloadToSave);
2442
2495
  graphDataRef.current[parentFileId] = specificParentData;
2443
2496
  setters.setDetailsNode((prev) => String(prev == null ? void 0 : prev.id) === String(nodeIdToDelete) ? null : prev);
2444
2497
  removeNodeFromScene(stateRef.current, nodeIdToDelete);
@@ -2452,7 +2505,7 @@ var userActionHandlers = {
2452
2505
  const { graphDataRef, sceneDataRef, stateRef, setters } = context;
2453
2506
  if (!graphDataRef.current || !sceneDataRef.current) return;
2454
2507
  const { _baseEmissiveIntensity: ignored, ...nodeToSave } = updatedNode;
2455
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeToSave.id);
2508
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeToSave.id, context.sceneConfigId, context.ownerId);
2456
2509
  if (!parentInfo || !parentInfo.ownerId) {
2457
2510
  console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node a ser atualizado:", nodeToSave.id);
2458
2511
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para atualiza\xE7\xE3o.");
@@ -2486,7 +2539,7 @@ var userActionHandlers = {
2486
2539
  const { graphDataRef, sceneDataRef, stateRef, setters } = context;
2487
2540
  if (!graphDataRef.current || !sceneDataRef.current) return;
2488
2541
  const { sourceNode, targetNode, ...linkToSave } = updatedLink;
2489
- const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkToSave.source);
2542
+ const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkToSave.source, context.sceneConfigId, context.ownerId);
2490
2543
  if (!parentInfo || !parentInfo.ownerId) {
2491
2544
  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
2545
  alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para atualiza\xE7\xE3o.");
@@ -7848,9 +7901,180 @@ function InSceneVersionForm({
7848
7901
  ));
7849
7902
  }
7850
7903
 
7851
- // src/components/NodeDetailsPanel.jsx
7904
+ // src/components/InSceneQuestForm.jsx
7852
7905
  var import_react16 = __toESM(require("react"));
7853
7906
  var import_fi14 = require("react-icons/fi");
7907
+ var QUEST_STATUS_COLORS = {
7908
+ "Backlog": "#64748b",
7909
+ // Slate (Cinza azulado)
7910
+ "In Progress": "#eab308",
7911
+ // Yellow (Amarelo)
7912
+ "Review": "#a855f7",
7913
+ // Purple (Roxo)
7914
+ "Done": "#22c55e"
7915
+ // Green (Verde)
7916
+ };
7917
+ function InSceneQuestForm({
7918
+ onSave,
7919
+ onCancel,
7920
+ style,
7921
+ refEl,
7922
+ onOpenImageViewer,
7923
+ availableNodes = [],
7924
+ availableAncestries = [],
7925
+ onMentionClick,
7926
+ onUploadFile
7927
+ }) {
7928
+ const [name, setName] = (0, import_react16.useState)("");
7929
+ const [types, setTypes] = (0, import_react16.useState)(["quest"]);
7930
+ const [typeInput, setTypeInput] = (0, import_react16.useState)("");
7931
+ const [status, setStatus] = (0, import_react16.useState)("Backlog");
7932
+ const [size, setSize] = (0, import_react16.useState)("medium");
7933
+ const [intensity, setIntensity] = (0, import_react16.useState)(0);
7934
+ const [description, setDescription] = (0, import_react16.useState)("");
7935
+ const [customProps, setCustomProps] = (0, import_react16.useState)([]);
7936
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react16.useState)(false);
7937
+ const propsEndRef = (0, import_react16.useRef)(null);
7938
+ const handleAddProp = () => {
7939
+ const newProp = createNewCustomProperty(customProps);
7940
+ setCustomProps([...customProps, newProp]);
7941
+ setTimeout(() => {
7942
+ var _a;
7943
+ (_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
7944
+ }, 100);
7945
+ };
7946
+ const handleRemoveProp = (index) => setCustomProps(customProps.filter((_, i) => i !== index));
7947
+ const handleUpdateProp = (index, updatedProp) => {
7948
+ const newProps = [...customProps];
7949
+ newProps[index] = updatedProp;
7950
+ setCustomProps(newProps);
7951
+ };
7952
+ const handleAddType = (newType) => {
7953
+ const trimmed = newType.trim();
7954
+ if (trimmed && !types.includes(trimmed)) {
7955
+ setTypes([...types, trimmed]);
7956
+ setTypeInput("");
7957
+ }
7958
+ };
7959
+ const handleRemoveType = (indexToRemove) => {
7960
+ if (types[indexToRemove] === "quest") return;
7961
+ setTypes(types.filter((_, index) => index !== indexToRemove));
7962
+ };
7963
+ const handleTypeInputKeyDown = (e) => {
7964
+ if (e.key === "Enter") {
7965
+ e.preventDefault();
7966
+ handleAddType(typeInput);
7967
+ } else if (e.key === "Backspace" && typeInput === "" && types.length > 1) {
7968
+ handleRemoveType(types.length - 1);
7969
+ }
7970
+ };
7971
+ const handleSubmit = (e) => {
7972
+ e.preventDefault();
7973
+ if (!name.trim()) {
7974
+ alert("O campo 'Nome' \xE9 obrigat\xF3rio.");
7975
+ return;
7976
+ }
7977
+ const additionalData = toObjectFromCustomProps(
7978
+ customProps.filter((prop) => prop.key.trim() && !prop.isEditing)
7979
+ );
7980
+ const processedSections = processDescriptionForSave(description, []);
7981
+ onSave({
7982
+ name: name.trim(),
7983
+ type: types,
7984
+ color: QUEST_STATUS_COLORS[status],
7985
+ // Cor atrelada ao status
7986
+ status,
7987
+ size,
7988
+ intensity,
7989
+ description: description.trim(),
7990
+ description_sections: processedSections,
7991
+ useImageAsTexture: false,
7992
+ textureImageUrl: null,
7993
+ ...additionalData
7994
+ });
7995
+ };
7996
+ const swallow = (e) => e.stopPropagation();
7997
+ const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
7998
+ const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
7999
+ return /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement(
8000
+ "div",
8001
+ {
8002
+ ref: refEl,
8003
+ 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",
8004
+ style,
8005
+ onPointerDown: swallow,
8006
+ onClick: swallow,
8007
+ onWheel: swallow,
8008
+ onContextMenu: swallow,
8009
+ onDoubleClick: swallow
8010
+ },
8011
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS[status]}, transparent)` } }),
8012
+ /* @__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")),
8013
+ /* @__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(
8014
+ "select",
8015
+ {
8016
+ value: status,
8017
+ onChange: (e) => setStatus(e.target.value),
8018
+ 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",
8019
+ style: { borderLeft: `4px solid ${QUEST_STATUS_COLORS[status]}` }
8020
+ },
8021
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "Backlog" }, "Backlog"),
8022
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "In Progress" }, "In Progress"),
8023
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "Review" }, "Review"),
8024
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "Done" }, "Done")
8025
+ )), /* @__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(
8026
+ "input",
8027
+ {
8028
+ type: "text",
8029
+ value: typeInput,
8030
+ onChange: (e) => setTypeInput(e.target.value),
8031
+ onKeyDown: handleTypeInputKeyDown,
8032
+ onBlur: () => {
8033
+ if (typeInput.trim()) handleAddType(typeInput);
8034
+ },
8035
+ className: "flex-1 bg-transparent text-sm min-w-[80px] focus:outline-none text-slate-200",
8036
+ autoComplete: "off"
8037
+ }
8038
+ ))), /* @__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(
8039
+ DescriptionDisplay,
8040
+ {
8041
+ description,
8042
+ savedSections: [],
8043
+ availableNodes,
8044
+ availableAncestries,
8045
+ onMentionClick,
8046
+ onSaveDescription: (newDesc) => setDescription(newDesc)
8047
+ }
8048
+ ), /* @__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(
8049
+ CustomPropertyDisplay,
8050
+ {
8051
+ key: prop.id,
8052
+ prop,
8053
+ onUpdate: (updatedProp) => handleUpdateProp(index, updatedProp),
8054
+ onRemove: () => handleRemoveProp(index),
8055
+ onOpenImageViewer,
8056
+ unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type),
8057
+ onUploadFile
8058
+ }
8059
+ )), /* @__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")))
8060
+ ), isDescriptionModalOpen && /* @__PURE__ */ import_react16.default.createElement(
8061
+ DescriptionEditModal,
8062
+ {
8063
+ isOpen: isDescriptionModalOpen,
8064
+ title: "Editar Descri\xE7\xE3o da Quest",
8065
+ initialValue: description,
8066
+ onSave: (newDescription) => setDescription(newDescription),
8067
+ onClose: () => setIsDescriptionModalOpen(false),
8068
+ availableNodes,
8069
+ availableAncestries,
8070
+ availableImages
8071
+ }
8072
+ ));
8073
+ }
8074
+
8075
+ // src/components/NodeDetailsPanel.jsx
8076
+ var import_react17 = __toESM(require("react"));
8077
+ var import_fi15 = require("react-icons/fi");
7854
8078
  function NodeDetailsPanel({
7855
8079
  node,
7856
8080
  onClose,
@@ -7871,38 +8095,38 @@ function NodeDetailsPanel({
7871
8095
  userRole,
7872
8096
  currentDatasetName
7873
8097
  }) {
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)(() => {
8098
+ const [name, setName] = (0, import_react17.useState)((node == null ? void 0 : node.name) ?? "");
8099
+ const [types, setTypes] = (0, import_react17.useState)([]);
8100
+ const [typeInput, setTypeInput] = (0, import_react17.useState)("");
8101
+ const [color, setColor] = (0, import_react17.useState)((node == null ? void 0 : node.color) ?? "#8b5cf6");
8102
+ const [size, setSize] = (0, import_react17.useState)((node == null ? void 0 : node.size) ?? "medium");
8103
+ const [description, setDescription] = (0, import_react17.useState)((node == null ? void 0 : node.description) ?? "");
8104
+ const [intensity, setIntensity] = (0, import_react17.useState)((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
8105
+ const [customProps, setCustomProps] = (0, import_react17.useState)(() => extractCustomPropsFromNode(node || {}));
8106
+ const [showTypeSuggestions, setShowTypeSuggestions] = (0, import_react17.useState)(false);
8107
+ const [filteredTypes, setFilteredTypes] = (0, import_react17.useState)([]);
8108
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react17.useState)(false);
8109
+ const [isReadMode, setIsReadMode] = (0, import_react17.useState)(false);
8110
+ const [existingSections, setExistingSections] = (0, import_react17.useState)((node == null ? void 0 : node.description_sections) || []);
8111
+ const [isSaving, setIsSaving] = (0, import_react17.useState)(false);
8112
+ const [isLinkCopied, setIsLinkCopied] = (0, import_react17.useState)(false);
8113
+ const [useImageAsTexture, setUseImageAsTexture] = (0, import_react17.useState)(() => {
7890
8114
  if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
7891
8115
  if ((node == null ? void 0 : node.useImageAsTexture) === "false") return false;
7892
8116
  return !!(node == null ? void 0 : node.useImageAsTexture);
7893
8117
  });
7894
- const [selectedImageUrl, setSelectedImageUrl] = (0, import_react16.useState)((node == null ? void 0 : node.textureImageUrl) ?? null);
8118
+ const [selectedImageUrl, setSelectedImageUrl] = (0, import_react17.useState)((node == null ? void 0 : node.textureImageUrl) ?? null);
7895
8119
  const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
7896
8120
  const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
7897
8121
  initialWidth: isReadMode ? 700 : 440,
7898
8122
  minWidth: 320,
7899
8123
  maxWidth: maxPanelW
7900
8124
  });
7901
- (0, import_react16.useEffect)(() => {
8125
+ (0, import_react17.useEffect)(() => {
7902
8126
  setWidth(isReadMode ? 700 : 440);
7903
8127
  }, [isReadMode, setWidth]);
7904
- const prevNodeIdRef = (0, import_react16.useRef)(null);
7905
- const propsEndRef = (0, import_react16.useRef)(null);
8128
+ const prevNodeIdRef = (0, import_react17.useRef)(null);
8129
+ const propsEndRef = (0, import_react17.useRef)(null);
7906
8130
  const canEdit = userRole !== "viewer";
7907
8131
  const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
7908
8132
  const handleImageClickFromText = (url, name2) => {
@@ -7910,7 +8134,7 @@ function NodeDetailsPanel({
7910
8134
  onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
7911
8135
  }
7912
8136
  };
7913
- (0, import_react16.useEffect)(() => {
8137
+ (0, import_react17.useEffect)(() => {
7914
8138
  if ((node == null ? void 0 : node.id) !== prevNodeIdRef.current) {
7915
8139
  prevNodeIdRef.current = node == null ? void 0 : node.id;
7916
8140
  setName((node == null ? void 0 : node.name) ?? "");
@@ -7932,13 +8156,13 @@ function NodeDetailsPanel({
7932
8156
  }
7933
8157
  }, [node]);
7934
8158
  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)(() => {
8159
+ (0, import_react17.useEffect)(() => {
7936
8160
  if (!hasImages && useImageAsTexture) {
7937
8161
  setUseImageAsTexture(false);
7938
8162
  setSelectedImageUrl(null);
7939
8163
  }
7940
8164
  }, [hasImages, useImageAsTexture]);
7941
- (0, import_react16.useEffect)(() => {
8165
+ (0, import_react17.useEffect)(() => {
7942
8166
  if (typeInput.trim() === "") {
7943
8167
  setFilteredTypes(existingTypes.filter((t) => !types.includes(t)));
7944
8168
  } else {
@@ -8110,7 +8334,7 @@ function NodeDetailsPanel({
8110
8334
  onClose();
8111
8335
  };
8112
8336
  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(
8337
+ return /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, /* @__PURE__ */ import_react17.default.createElement(
8114
8338
  "div",
8115
8339
  {
8116
8340
  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 +8347,7 @@ function NodeDetailsPanel({
8123
8347
  onContextMenu: swallow,
8124
8348
  onDoubleClick: swallow
8125
8349
  },
8126
- /* @__PURE__ */ import_react16.default.createElement(
8350
+ /* @__PURE__ */ import_react17.default.createElement(
8127
8351
  "div",
8128
8352
  {
8129
8353
  onPointerDown: (e) => {
@@ -8134,7 +8358,7 @@ function NodeDetailsPanel({
8134
8358
  title: "Arraste para redimensionar"
8135
8359
  }
8136
8360
  ),
8137
- isReadMode ? /* @__PURE__ */ import_react16.default.createElement(
8361
+ isReadMode ? /* @__PURE__ */ import_react17.default.createElement(
8138
8362
  DescriptionReadModePanel,
8139
8363
  {
8140
8364
  title: name || (node == null ? void 0 : node.name),
@@ -8155,23 +8379,23 @@ function NodeDetailsPanel({
8155
8379
  onImageClick: handleImageClickFromText,
8156
8380
  onSaveDescription: handleSaveDescriptionInline
8157
8381
  }
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(
8382
+ ) : /* @__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
8383
  "button",
8160
8384
  {
8161
8385
  onClick: handleCopyLink,
8162
8386
  className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-indigo-400"}`,
8163
8387
  title: isLinkCopied ? "Link Copiado!" : "Copiar link para este Node"
8164
8388
  },
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(
8389
+ isLinkCopied ? /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiLink, { size: 12 })
8390
+ )), /* @__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
8391
  "button",
8168
8392
  {
8169
8393
  type: "button",
8170
8394
  onClick: () => handleRemoveType(index),
8171
8395
  className: "hover:text-white transition-colors"
8172
8396
  },
8173
- /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiX, { size: 12 })
8174
- ))), canEdit && /* @__PURE__ */ import_react16.default.createElement(
8397
+ /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiX, { size: 12 })
8398
+ ))), canEdit && /* @__PURE__ */ import_react17.default.createElement(
8175
8399
  "input",
8176
8400
  {
8177
8401
  type: "text",
@@ -8192,7 +8416,7 @@ function NodeDetailsPanel({
8192
8416
  placeholder: types.length === 0 ? "Ex.: Cliente" : "",
8193
8417
  autoComplete: "off"
8194
8418
  }
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(
8419
+ ), 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
8420
  "li",
8197
8421
  {
8198
8422
  key: index,
@@ -8203,7 +8427,7 @@ function NodeDetailsPanel({
8203
8427
  }
8204
8428
  },
8205
8429
  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(
8430
+ ))))), /* @__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
8431
  "input",
8208
8432
  {
8209
8433
  type: "text",
@@ -8212,7 +8436,7 @@ function NodeDetailsPanel({
8212
8436
  readOnly: !canEdit,
8213
8437
  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
8438
  }
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(
8439
+ )), /* @__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
8440
  DescriptionDisplay,
8217
8441
  {
8218
8442
  description,
@@ -8224,7 +8448,7 @@ function NodeDetailsPanel({
8224
8448
  onImageClick: handleImageClickFromText,
8225
8449
  onSaveDescription: handleSaveDescriptionInline
8226
8450
  }
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(
8451
+ ), /* @__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
8452
  "button",
8229
8453
  {
8230
8454
  type: "button",
@@ -8232,8 +8456,8 @@ function NodeDetailsPanel({
8232
8456
  className: `p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors ${canEdit ? "border-r border-white/5" : ""}`,
8233
8457
  title: "Modo de Leitura"
8234
8458
  },
8235
- /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiBookOpen, { size: 14 })
8236
- ), canEdit && /* @__PURE__ */ import_react16.default.createElement(
8459
+ /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiBookOpen, { size: 14 })
8460
+ ), canEdit && /* @__PURE__ */ import_react17.default.createElement(
8237
8461
  "button",
8238
8462
  {
8239
8463
  type: "button",
@@ -8241,17 +8465,17 @@ function NodeDetailsPanel({
8241
8465
  className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
8242
8466
  title: "Editar descri\xE7\xE3o (Modo de Escrita)"
8243
8467
  },
8244
- /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiEdit2, { size: 14 })
8245
- )), canEdit && !description && /* @__PURE__ */ import_react16.default.createElement(
8468
+ /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiEdit2, { size: 14 })
8469
+ )), canEdit && !description && /* @__PURE__ */ import_react17.default.createElement(
8246
8470
  "div",
8247
8471
  {
8248
8472
  onClick: () => setIsDescriptionModalOpen(true),
8249
8473
  className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
8250
8474
  },
8251
8475
  "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) => {
8476
+ ))), /* @__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
8477
  const isSelected = size === s;
8254
- return /* @__PURE__ */ import_react16.default.createElement(
8478
+ return /* @__PURE__ */ import_react17.default.createElement(
8255
8479
  "button",
8256
8480
  {
8257
8481
  key: s,
@@ -8259,10 +8483,10 @@ function NodeDetailsPanel({
8259
8483
  onClick: () => canEdit && handleSizeChange(s),
8260
8484
  className: `flex items-center gap-2 group focus:outline-none ${canEdit ? "cursor-pointer" : "cursor-default opacity-80"}`
8261
8485
  },
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)
8486
+ /* @__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" })),
8487
+ /* @__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
8488
  );
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(
8489
+ }))), /* @__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
8490
  "input",
8267
8491
  {
8268
8492
  type: "checkbox",
@@ -8270,14 +8494,14 @@ function NodeDetailsPanel({
8270
8494
  onChange: handleToggleImageMode,
8271
8495
  className: "hidden"
8272
8496
  }
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(
8497
+ ), /* @__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
8498
  ColorPicker,
8275
8499
  {
8276
8500
  color,
8277
8501
  onChange: handleColorChange,
8278
8502
  disabled: !canEdit || useImageAsTexture
8279
8503
  }
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(
8504
+ ), /* @__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
8505
  "input",
8282
8506
  {
8283
8507
  type: "range",
@@ -8290,7 +8514,7 @@ function NodeDetailsPanel({
8290
8514
  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
8515
  title: `Intensidade do brilho: ${intensity}`
8292
8516
  }
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(
8517
+ ), /* @__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
8518
  CustomPropertyDisplay,
8295
8519
  {
8296
8520
  key: prop.id,
@@ -8305,7 +8529,7 @@ function NodeDetailsPanel({
8305
8529
  onUploadFile: canEdit ? onUploadFile : void 0,
8306
8530
  readOnly: !canEdit
8307
8531
  }
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(
8532
+ )), /* @__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
8533
  "button",
8310
8534
  {
8311
8535
  onClick: () => handleSave(false),
@@ -8314,10 +8538,10 @@ function NodeDetailsPanel({
8314
8538
  ${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
8539
  `
8316
8540
  },
8317
- isSaving && /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiLoader, { className: "animate-spin" }),
8541
+ isSaving && /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiLoader, { className: "animate-spin" }),
8318
8542
  isSaving ? "Salvando..." : "Salvar"
8319
8543
  )))
8320
- ), isDescriptionModalOpen && canEdit && /* @__PURE__ */ import_react16.default.createElement(
8544
+ ), isDescriptionModalOpen && canEdit && /* @__PURE__ */ import_react17.default.createElement(
8321
8545
  DescriptionEditModal,
8322
8546
  {
8323
8547
  isOpen: isDescriptionModalOpen,
@@ -8337,7 +8561,7 @@ function NodeDetailsPanel({
8337
8561
  }
8338
8562
 
8339
8563
  // src/components/MultiNodeContextMenu.jsx
8340
- var import_react17 = __toESM(require("react"));
8564
+ var import_react18 = __toESM(require("react"));
8341
8565
  function MultiNodeContextMenu({
8342
8566
  data,
8343
8567
  userRole,
@@ -8346,12 +8570,12 @@ function MultiNodeContextMenu({
8346
8570
  onDismissOtherNodes,
8347
8571
  onDeleteNodes
8348
8572
  }) {
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);
8573
+ const menuRef = (0, import_react18.useRef)(null);
8574
+ const [menuPos, setMenuPos] = (0, import_react18.useState)({ left: 0, top: 0 });
8575
+ const [isConfirmingDelete, setIsConfirmingDelete] = (0, import_react18.useState)(false);
8352
8576
  const ability = defineAbilityFor(userRole);
8353
8577
  const canDelete = ability.can("delete", "Node");
8354
- (0, import_react17.useLayoutEffect)(() => {
8578
+ (0, import_react18.useLayoutEffect)(() => {
8355
8579
  if (!data.visible || !menuRef.current) return;
8356
8580
  const el = menuRef.current;
8357
8581
  const w = el.clientWidth;
@@ -8364,7 +8588,7 @@ function MultiNodeContextMenu({
8364
8588
  if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
8365
8589
  setMenuPos({ left, top });
8366
8590
  }, [data]);
8367
- (0, import_react17.useEffect)(() => {
8591
+ (0, import_react18.useEffect)(() => {
8368
8592
  if (data.visible) {
8369
8593
  setIsConfirmingDelete(false);
8370
8594
  }
@@ -8379,7 +8603,7 @@ function MultiNodeContextMenu({
8379
8603
  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
8604
  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
8605
  const nodeCount = data.nodeIds.size;
8382
- return /* @__PURE__ */ import_react17.default.createElement(
8606
+ return /* @__PURE__ */ import_react18.default.createElement(
8383
8607
  "div",
8384
8608
  {
8385
8609
  ref: menuRef,
@@ -8393,28 +8617,28 @@ function MultiNodeContextMenu({
8393
8617
  onContextMenu: swallow,
8394
8618
  onDoubleClick: swallow
8395
8619
  },
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(
8620
+ /* @__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" }),
8621
+ /* @__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
8622
  "button",
8399
8623
  {
8400
8624
  onClick: () => setIsConfirmingDelete(false),
8401
8625
  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
8626
  },
8403
8627
  "Cancelar"
8404
- ), /* @__PURE__ */ import_react17.default.createElement(
8628
+ ), /* @__PURE__ */ import_react18.default.createElement(
8405
8629
  "button",
8406
8630
  {
8407
8631
  onClick: () => onDeleteNodes(data.nodeIds),
8408
8632
  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
8633
  },
8410
8634
  "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, ")"))))))
8635
+ ))) : /* @__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
8636
  );
8413
8637
  }
8414
8638
 
8415
8639
  // src/components/RelationshipDetailsPanel.jsx
8416
- var import_react18 = __toESM(require("react"));
8417
- var import_fi15 = require("react-icons/fi");
8640
+ var import_react19 = __toESM(require("react"));
8641
+ var import_fi16 = require("react-icons/fi");
8418
8642
  function RelationshipDetailsPanel({
8419
8643
  link,
8420
8644
  onClose,
@@ -8428,19 +8652,19 @@ function RelationshipDetailsPanel({
8428
8652
  onUploadFile,
8429
8653
  userRole
8430
8654
  }) {
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)(() => {
8655
+ const [name, setName] = (0, import_react19.useState)((link == null ? void 0 : link.name) ?? "");
8656
+ const [description, setDescription] = (0, import_react19.useState)((link == null ? void 0 : link.description) ?? "");
8657
+ const [customProps, setCustomProps] = (0, import_react19.useState)(() => extractCustomPropsFromNode(link || {}));
8658
+ const [existingSections, setExistingSections] = (0, import_react19.useState)((link == null ? void 0 : link.description_sections) || []);
8659
+ const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react19.useState)(false);
8660
+ const [isSaving, setIsSaving] = (0, import_react19.useState)(false);
8661
+ const [isReadMode, setIsReadMode] = (0, import_react19.useState)(false);
8662
+ const propsEndRef = (0, import_react19.useRef)(null);
8663
+ const canEdit = (0, import_react19.useMemo)(() => {
8440
8664
  const ability = defineAbilityFor(userRole);
8441
8665
  return ability.can("update", "Connection");
8442
8666
  }, [userRole]);
8443
- (0, import_react18.useEffect)(() => {
8667
+ (0, import_react19.useEffect)(() => {
8444
8668
  setName((link == null ? void 0 : link.name) ?? "");
8445
8669
  setDescription((link == null ? void 0 : link.description) ?? "");
8446
8670
  setExistingSections((link == null ? void 0 : link.description_sections) || []);
@@ -8515,7 +8739,7 @@ function RelationshipDetailsPanel({
8515
8739
  onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
8516
8740
  }
8517
8741
  };
8518
- return /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement(
8742
+ return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement(
8519
8743
  "div",
8520
8744
  {
8521
8745
  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 +8754,7 @@ function RelationshipDetailsPanel({
8530
8754
  onContextMenu: swallow,
8531
8755
  onDoubleClick: swallow
8532
8756
  },
8533
- isReadMode ? /* @__PURE__ */ import_react18.default.createElement(
8757
+ isReadMode ? /* @__PURE__ */ import_react19.default.createElement(
8534
8758
  DescriptionReadModePanel,
8535
8759
  {
8536
8760
  title: name || "Rela\xE7\xE3o",
@@ -8551,7 +8775,7 @@ function RelationshipDetailsPanel({
8551
8775
  onImageClick: handleImageClickFromText,
8552
8776
  onSaveDescription: handleSaveDescriptionInline
8553
8777
  }
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(
8778
+ ) : /* @__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
8779
  "input",
8556
8780
  {
8557
8781
  type: "text",
@@ -8563,7 +8787,7 @@ function RelationshipDetailsPanel({
8563
8787
  ${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
8564
8788
  `
8565
8789
  }
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(
8790
+ )), /* @__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
8791
  DescriptionDisplay,
8568
8792
  {
8569
8793
  description,
@@ -8575,7 +8799,7 @@ function RelationshipDetailsPanel({
8575
8799
  onImageClick: handleImageClickFromText,
8576
8800
  onSaveDescription: handleSaveDescriptionInline
8577
8801
  }
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(
8802
+ ), /* @__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
8803
  "button",
8580
8804
  {
8581
8805
  type: "button",
@@ -8583,8 +8807,8 @@ function RelationshipDetailsPanel({
8583
8807
  className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors border-r border-white/5",
8584
8808
  title: "Modo de Leitura"
8585
8809
  },
8586
- /* @__PURE__ */ import_react18.default.createElement(import_fi15.FiBookOpen, { size: 14 })
8587
- ), canEdit && /* @__PURE__ */ import_react18.default.createElement(
8810
+ /* @__PURE__ */ import_react19.default.createElement(import_fi16.FiBookOpen, { size: 14 })
8811
+ ), canEdit && /* @__PURE__ */ import_react19.default.createElement(
8588
8812
  "button",
8589
8813
  {
8590
8814
  type: "button",
@@ -8592,15 +8816,15 @@ function RelationshipDetailsPanel({
8592
8816
  className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
8593
8817
  title: "Editar descri\xE7\xE3o"
8594
8818
  },
8595
- /* @__PURE__ */ import_react18.default.createElement(import_fi15.FiEdit2, { size: 14 })
8596
- )), !description && canEdit && /* @__PURE__ */ import_react18.default.createElement(
8819
+ /* @__PURE__ */ import_react19.default.createElement(import_fi16.FiEdit2, { size: 14 })
8820
+ )), !description && canEdit && /* @__PURE__ */ import_react19.default.createElement(
8597
8821
  "div",
8598
8822
  {
8599
8823
  onClick: () => setIsDescriptionModalOpen(true),
8600
8824
  className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
8601
8825
  },
8602
8826
  "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(
8827
+ ))), /* @__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
8828
  CustomPropertyDisplay,
8605
8829
  {
8606
8830
  key: prop.id,
@@ -8612,7 +8836,7 @@ function RelationshipDetailsPanel({
8612
8836
  onUploadFile,
8613
8837
  disabled: !canEdit
8614
8838
  }
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(
8839
+ )), /* @__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
8840
  "button",
8617
8841
  {
8618
8842
  onClick: () => handleSave(false),
@@ -8621,10 +8845,10 @@ function RelationshipDetailsPanel({
8621
8845
  ${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
8846
  `
8623
8847
  },
8624
- isSaving && /* @__PURE__ */ import_react18.default.createElement(import_fi15.FiLoader, { className: "animate-spin" }),
8848
+ isSaving && /* @__PURE__ */ import_react19.default.createElement(import_fi16.FiLoader, { className: "animate-spin" }),
8625
8849
  isSaving ? "Salvando..." : "Salvar"
8626
8850
  )))
8627
- ), isDescriptionModalOpen && /* @__PURE__ */ import_react18.default.createElement(
8851
+ ), isDescriptionModalOpen && /* @__PURE__ */ import_react19.default.createElement(
8628
8852
  DescriptionEditModal,
8629
8853
  {
8630
8854
  isOpen: isDescriptionModalOpen,
@@ -8645,7 +8869,7 @@ function RelationshipDetailsPanel({
8645
8869
  }
8646
8870
 
8647
8871
  // src/components/RelationshipContextMenu.jsx
8648
- var import_react19 = __toESM(require("react"));
8872
+ var import_react20 = __toESM(require("react"));
8649
8873
  function RelationshipContextMenu({
8650
8874
  data,
8651
8875
  userRole,
@@ -8655,25 +8879,25 @@ function RelationshipContextMenu({
8655
8879
  onDelete,
8656
8880
  onClose
8657
8881
  }) {
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)(
8882
+ const menuRef = (0, import_react20.useRef)(null);
8883
+ const [menuPos, setMenuPos] = (0, import_react20.useState)({ left: 0, top: 0 });
8884
+ const [isConfirmingDelete, setIsConfirmingDelete] = (0, import_react20.useState)(false);
8885
+ const ability = (0, import_react20.useMemo)(() => defineAbilityFor(userRole), [userRole]);
8886
+ const sourceName = (0, import_react20.useMemo)(
8663
8887
  () => {
8664
8888
  var _a, _b, _c, _d;
8665
8889
  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
8890
  },
8667
8891
  [data == null ? void 0 : data.linkObject]
8668
8892
  );
8669
- const targetName = (0, import_react19.useMemo)(
8893
+ const targetName = (0, import_react20.useMemo)(
8670
8894
  () => {
8671
8895
  var _a, _b, _c, _d;
8672
8896
  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
8897
  },
8674
8898
  [data == null ? void 0 : data.linkObject]
8675
8899
  );
8676
- (0, import_react19.useLayoutEffect)(() => {
8900
+ (0, import_react20.useLayoutEffect)(() => {
8677
8901
  if (!data.visible || !menuRef.current) return;
8678
8902
  const el = menuRef.current;
8679
8903
  const w = el.clientWidth;
@@ -8686,7 +8910,7 @@ function RelationshipContextMenu({
8686
8910
  if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
8687
8911
  setMenuPos({ left, top });
8688
8912
  }, [data]);
8689
- (0, import_react19.useEffect)(() => {
8913
+ (0, import_react20.useEffect)(() => {
8690
8914
  if (data.visible) {
8691
8915
  setIsConfirmingDelete(false);
8692
8916
  }
@@ -8702,7 +8926,7 @@ function RelationshipContextMenu({
8702
8926
  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
8927
  const canUpdate = ability.can("update", "Connection");
8704
8928
  const canDelete = ability.can("delete", "Connection");
8705
- return /* @__PURE__ */ import_react19.default.createElement(
8929
+ return /* @__PURE__ */ import_react20.default.createElement(
8706
8930
  "div",
8707
8931
  {
8708
8932
  ref: menuRef,
@@ -8716,29 +8940,29 @@ function RelationshipContextMenu({
8716
8940
  onContextMenu: swallow,
8717
8941
  onDoubleClick: swallow
8718
8942
  },
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(
8943
+ /* @__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" }),
8944
+ /* @__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
8945
  "button",
8722
8946
  {
8723
8947
  onClick: () => setIsConfirmingDelete(false),
8724
8948
  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
8949
  },
8726
8950
  "Cancelar"
8727
- ), /* @__PURE__ */ import_react19.default.createElement(
8951
+ ), /* @__PURE__ */ import_react20.default.createElement(
8728
8952
  "button",
8729
8953
  {
8730
8954
  onClick: () => onDelete == null ? void 0 : onDelete(data.linkObject),
8731
8955
  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
8956
  },
8733
8957
  "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(
8958
+ ))) : /* @__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
8959
  "button",
8736
8960
  {
8737
8961
  onClick: () => onRelinkSource == null ? void 0 : onRelinkSource(data.linkObject),
8738
8962
  className: baseButtonClass,
8739
8963
  title: "Desconectar ponta ligada ao Source"
8740
8964
  },
8741
- /* @__PURE__ */ import_react19.default.createElement(
8965
+ /* @__PURE__ */ import_react20.default.createElement(
8742
8966
  "svg",
8743
8967
  {
8744
8968
  xmlns: "http://www.w3.org/2000/svg",
@@ -8751,18 +8975,18 @@ function RelationshipContextMenu({
8751
8975
  strokeLinecap: "round",
8752
8976
  strokeLinejoin: "round"
8753
8977
  },
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" })
8978
+ /* @__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" }),
8979
+ /* @__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
8980
  ),
8757
- /* @__PURE__ */ import_react19.default.createElement("span", null, "Desconectar Source (", sourceName, ")")
8758
- ), /* @__PURE__ */ import_react19.default.createElement(
8981
+ /* @__PURE__ */ import_react20.default.createElement("span", null, "Desconectar Source (", sourceName, ")")
8982
+ ), /* @__PURE__ */ import_react20.default.createElement(
8759
8983
  "button",
8760
8984
  {
8761
8985
  onClick: () => onRelinkTarget == null ? void 0 : onRelinkTarget(data.linkObject),
8762
8986
  className: baseButtonClass,
8763
8987
  title: "Desconectar ponta ligada ao Target"
8764
8988
  },
8765
- /* @__PURE__ */ import_react19.default.createElement(
8989
+ /* @__PURE__ */ import_react20.default.createElement(
8766
8990
  "svg",
8767
8991
  {
8768
8992
  xmlns: "http://www.w3.org/2000/svg",
@@ -8775,21 +8999,21 @@ function RelationshipContextMenu({
8775
8999
  strokeLinecap: "round",
8776
9000
  strokeLinejoin: "round"
8777
9001
  },
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" })
9002
+ /* @__PURE__ */ import_react20.default.createElement("polyline", { points: "16 3 21 3 21 8" }),
9003
+ /* @__PURE__ */ import_react20.default.createElement("line", { x1: "4", y1: "20", x2: "21", y2: "3" }),
9004
+ /* @__PURE__ */ import_react20.default.createElement("polyline", { points: "21 16 21 21 16 21" }),
9005
+ /* @__PURE__ */ import_react20.default.createElement("line", { x1: "15", y1: "15", x2: "21", y2: "21" }),
9006
+ /* @__PURE__ */ import_react20.default.createElement("line", { x1: "4", y1: "4", x2: "9", y2: "9" })
8783
9007
  ),
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(
9008
+ /* @__PURE__ */ import_react20.default.createElement("span", null, "Desconectar Target (", targetName, ")")
9009
+ ), /* @__PURE__ */ import_react20.default.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" })), /* @__PURE__ */ import_react20.default.createElement(
8786
9010
  "button",
8787
9011
  {
8788
9012
  onClick: () => onOpenDetails == null ? void 0 : onOpenDetails(data.linkObject),
8789
9013
  className: baseButtonClass,
8790
9014
  title: "Abrir detalhes da rela\xE7\xE3o"
8791
9015
  },
8792
- /* @__PURE__ */ import_react19.default.createElement(
9016
+ /* @__PURE__ */ import_react20.default.createElement(
8793
9017
  "svg",
8794
9018
  {
8795
9019
  xmlns: "http://www.w3.org/2000/svg",
@@ -8802,19 +9026,19 @@ function RelationshipContextMenu({
8802
9026
  strokeLinecap: "round",
8803
9027
  strokeLinejoin: "round"
8804
9028
  },
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" })
9029
+ /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
9030
+ /* @__PURE__ */ import_react20.default.createElement("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
9031
+ /* @__PURE__ */ import_react20.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "8" })
8808
9032
  ),
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(
9033
+ /* @__PURE__ */ import_react20.default.createElement("span", null, "Abrir Detalhes")
9034
+ ), 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
9035
  "button",
8812
9036
  {
8813
9037
  onClick: () => setIsConfirmingDelete(true),
8814
9038
  className: dangerButtonClass,
8815
9039
  title: "Excluir esta conex\xE3o"
8816
9040
  },
8817
- /* @__PURE__ */ import_react19.default.createElement(
9041
+ /* @__PURE__ */ import_react20.default.createElement(
8818
9042
  "svg",
8819
9043
  {
8820
9044
  xmlns: "http://www.w3.org/2000/svg",
@@ -8827,19 +9051,19 @@ function RelationshipContextMenu({
8827
9051
  strokeLinecap: "round",
8828
9052
  strokeLinejoin: "round"
8829
9053
  },
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" })
9054
+ /* @__PURE__ */ import_react20.default.createElement("polyline", { points: "3 6 5 6 21 6" }),
9055
+ /* @__PURE__ */ import_react20.default.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }),
9056
+ /* @__PURE__ */ import_react20.default.createElement("path", { d: "M10 11v6" }),
9057
+ /* @__PURE__ */ import_react20.default.createElement("path", { d: "M14 11v6" }),
9058
+ /* @__PURE__ */ import_react20.default.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" })
8835
9059
  ),
8836
- /* @__PURE__ */ import_react19.default.createElement("span", null, "Excluir conex\xE3o (", sourceName, " \u2192 ", targetName, ")")
9060
+ /* @__PURE__ */ import_react20.default.createElement("span", null, "Excluir conex\xE3o (", sourceName, " \u2192 ", targetName, ")")
8837
9061
  )))))
8838
9062
  );
8839
9063
  }
8840
9064
 
8841
9065
  // src/components/LoadingScreen.jsx
8842
- var import_react20 = __toESM(require("react"));
9066
+ var import_react21 = __toESM(require("react"));
8843
9067
  var styles = {
8844
9068
  loadingOverlay: {
8845
9069
  position: "fixed",
@@ -8871,11 +9095,11 @@ var styles = {
8871
9095
  `
8872
9096
  };
8873
9097
  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 })));
9098
+ 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
9099
  }
8876
9100
 
8877
9101
  // src/components/ImportParentFileModal.jsx
8878
- var import_react21 = __toESM(require("react"));
9102
+ var import_react22 = __toESM(require("react"));
8879
9103
  function ImportParentFileModal({
8880
9104
  isOpen,
8881
9105
  onClose,
@@ -8886,12 +9110,12 @@ function ImportParentFileModal({
8886
9110
  onFetchAvailableFiles,
8887
9111
  currentViewName
8888
9112
  }) {
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)(() => {
9113
+ const [activeTab, setActiveTab] = (0, import_react22.useState)("databases");
9114
+ const [availableDbs, setAvailableDbs] = (0, import_react22.useState)([]);
9115
+ const [availableViews, setAvailableViews] = (0, import_react22.useState)([]);
9116
+ const [selectedItem, setSelectedItem] = (0, import_react22.useState)(null);
9117
+ const [isLoading, setIsLoading] = (0, import_react22.useState)(false);
9118
+ (0, import_react22.useEffect)(() => {
8895
9119
  if (isOpen && session && onFetchAvailableFiles) {
8896
9120
  const fetchData = async () => {
8897
9121
  setIsLoading(true);
@@ -8927,7 +9151,7 @@ function ImportParentFileModal({
8927
9151
  fetchData();
8928
9152
  }
8929
9153
  }, [isOpen, session, parentDbs, onFetchAvailableFiles, currentViewName]);
8930
- (0, import_react21.useEffect)(() => {
9154
+ (0, import_react22.useEffect)(() => {
8931
9155
  setSelectedItem(null);
8932
9156
  }, [activeTab]);
8933
9157
  if (!isOpen) {
@@ -8956,13 +9180,13 @@ function ImportParentFileModal({
8956
9180
  const swallow = (e) => e.stopPropagation();
8957
9181
  const currentList = activeTab === "databases" ? availableDbs : availableViews;
8958
9182
  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(
9183
+ return /* @__PURE__ */ import_react22.default.createElement(
8960
9184
  "div",
8961
9185
  {
8962
9186
  className: "ui-overlay fixed inset-0 z-[1200] flex items-center justify-center bg-black/60 backdrop-blur-sm",
8963
9187
  onClick: onClose
8964
9188
  },
8965
- /* @__PURE__ */ import_react21.default.createElement(
9189
+ /* @__PURE__ */ import_react22.default.createElement(
8966
9190
  "div",
8967
9191
  {
8968
9192
  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 +9198,14 @@ function ImportParentFileModal({
8974
9198
  onContextMenu: swallow,
8975
9199
  onDoubleClick: swallow
8976
9200
  },
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(
9201
+ /* @__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
9202
  "button",
8979
9203
  {
8980
9204
  onClick: onClose,
8981
9205
  className: "p-2 rounded-md text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
8982
9206
  title: "Fechar"
8983
9207
  },
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(
9208
+ /* @__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
9209
  "path",
8986
9210
  {
8987
9211
  fillRule: "evenodd",
@@ -8990,14 +9214,14 @@ function ImportParentFileModal({
8990
9214
  }
8991
9215
  ))
8992
9216
  )),
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(
9217
+ /* @__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
9218
  "button",
8995
9219
  {
8996
9220
  onClick: () => setActiveTab("databases"),
8997
9221
  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
9222
  },
8999
9223
  "Arquivos Parent"
9000
- ), /* @__PURE__ */ import_react21.default.createElement(
9224
+ ), /* @__PURE__ */ import_react22.default.createElement(
9001
9225
  "button",
9002
9226
  {
9003
9227
  onClick: () => setActiveTab("views"),
@@ -9005,24 +9229,24 @@ function ImportParentFileModal({
9005
9229
  },
9006
9230
  "Views (Ancestralidades)"
9007
9231
  )),
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(
9232
+ /* @__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
9233
  "div",
9010
9234
  {
9011
9235
  key: item.id,
9012
9236
  onClick: () => setSelectedItem(item),
9013
9237
  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
9238
  },
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(
9239
+ /* @__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")),
9240
+ 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)
9241
+ )) : /* @__PURE__ */ import_react22.default.createElement("p", { className: "text-slate-400 text-center py-10" }, emptyMessage))),
9242
+ /* @__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
9243
  "button",
9020
9244
  {
9021
9245
  onClick: onClose,
9022
9246
  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
9247
  },
9024
9248
  "Cancelar"
9025
- ), /* @__PURE__ */ import_react21.default.createElement(
9249
+ ), /* @__PURE__ */ import_react22.default.createElement(
9026
9250
  "button",
9027
9251
  {
9028
9252
  onClick: handleConfirm,
@@ -9036,8 +9260,8 @@ function ImportParentFileModal({
9036
9260
  }
9037
9261
 
9038
9262
  // src/components/AncestryLinkDetailsPanel.jsx
9039
- var import_react22 = __toESM(require("react"));
9040
- var import_fi16 = require("react-icons/fi");
9263
+ var import_react23 = __toESM(require("react"));
9264
+ var import_fi17 = require("react-icons/fi");
9041
9265
  function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile }) {
9042
9266
  var _a, _b, _c, _d;
9043
9267
  const relationshipData = data.relationship || {};
@@ -9046,21 +9270,21 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9046
9270
  const customProps = extractCustomPropsFromNode(relationshipData);
9047
9271
  const sourceName = ((_b = (_a = data.sourceNode) == null ? void 0 : _a.userData) == null ? void 0 : _b.name) || "Origem";
9048
9272
  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);
9273
+ const [isReadMode, setIsReadMode] = (0, import_react23.useState)(false);
9050
9274
  const swallow = (e) => e.stopPropagation();
9051
9275
  const handleImageClickFromText = (url, name) => {
9052
9276
  if (onOpenImageViewer) {
9053
9277
  onOpenImageViewer([{ name: name || "Imagem", value: url }], 0);
9054
9278
  }
9055
9279
  };
9056
- return /* @__PURE__ */ import_react22.default.createElement(
9280
+ return /* @__PURE__ */ import_react23.default.createElement(
9057
9281
  "div",
9058
9282
  {
9059
9283
  className: "ui-overlay fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-[1200]",
9060
9284
  onClick: onClose,
9061
9285
  onPointerDown: swallow
9062
9286
  },
9063
- /* @__PURE__ */ import_react22.default.createElement(
9287
+ /* @__PURE__ */ import_react23.default.createElement(
9064
9288
  "div",
9065
9289
  {
9066
9290
  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 +9292,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9068
9292
  `,
9069
9293
  onClick: swallow
9070
9294
  },
9071
- isReadMode ? /* @__PURE__ */ import_react22.default.createElement(
9295
+ isReadMode ? /* @__PURE__ */ import_react23.default.createElement(
9072
9296
  DescriptionReadModePanel,
9073
9297
  {
9074
9298
  title: `${sourceName} \u2794 ${targetName}`,
@@ -9080,15 +9304,15 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9080
9304
  onMentionClick,
9081
9305
  onImageClick: handleImageClickFromText
9082
9306
  }
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(
9307
+ ) : /* @__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
9308
  "button",
9085
9309
  {
9086
9310
  onClick: () => setIsReadMode(true),
9087
9311
  className: "p-1 text-slate-400 hover:text-white transition-colors",
9088
9312
  title: "Modo de Leitura"
9089
9313
  },
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(
9314
+ /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiBookOpen, { size: 14 })
9315
+ )), /* @__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
9316
  DescriptionDisplay,
9093
9317
  {
9094
9318
  description,
@@ -9097,7 +9321,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9097
9321
  onMentionClick,
9098
9322
  onImageClick: handleImageClickFromText
9099
9323
  }
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(
9324
+ ))), 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
9325
  CustomPropertyDisplay,
9102
9326
  {
9103
9327
  key: prop.id,
@@ -9106,14 +9330,14 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
9106
9330
  onOpenImageViewer,
9107
9331
  onUploadFile
9108
9332
  }
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".')))
9333
+ )))), !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
9334
  )
9111
9335
  );
9112
9336
  }
9113
9337
 
9114
9338
  // src/components/AncestryBoard.jsx
9115
- var import_react23 = __toESM(require("react"));
9116
- var import_fi17 = require("react-icons/fi");
9339
+ var import_react24 = __toESM(require("react"));
9340
+ var import_fi18 = require("react-icons/fi");
9117
9341
  var GroupItem = ({
9118
9342
  group,
9119
9343
  index,
@@ -9133,7 +9357,7 @@ var GroupItem = ({
9133
9357
  }) => {
9134
9358
  const canIndent = index > 0;
9135
9359
  const isPickingForThisGroup = pickingGroupId === group.id;
9136
- const textareaRef = (0, import_react23.useRef)(null);
9360
+ const textareaRef = (0, import_react24.useRef)(null);
9137
9361
  const adjustHeight = () => {
9138
9362
  const textarea = textareaRef.current;
9139
9363
  if (textarea) {
@@ -9141,13 +9365,13 @@ var GroupItem = ({
9141
9365
  textarea.style.height = `${textarea.scrollHeight}px`;
9142
9366
  }
9143
9367
  };
9144
- (0, import_react23.useEffect)(() => {
9368
+ (0, import_react24.useEffect)(() => {
9145
9369
  adjustHeight();
9146
9370
  }, [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: `
9371
+ 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
9372
  flex flex-col gap-2 py-2 px-3 transition-all duration-200
9149
9373
  ${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(
9374
+ ` }, /* @__PURE__ */ import_react24.default.createElement(
9151
9375
  "textarea",
9152
9376
  {
9153
9377
  ref: textareaRef,
@@ -9164,9 +9388,9 @@ var GroupItem = ({
9164
9388
  if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
9165
9389
  }
9166
9390
  }
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) => {
9391
+ ), 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
9392
  const isValid = availableIds.has(String(anc.ancestry_id));
9169
- return /* @__PURE__ */ import_react23.default.createElement(
9393
+ return /* @__PURE__ */ import_react24.default.createElement(
9170
9394
  "div",
9171
9395
  {
9172
9396
  key: anc.ancestry_id,
@@ -9178,28 +9402,28 @@ var GroupItem = ({
9178
9402
  },
9179
9403
  isValid ? (
9180
9404
  // [MANTIDO] Botão Play visível para todos
9181
- /* @__PURE__ */ import_react23.default.createElement(
9405
+ /* @__PURE__ */ import_react24.default.createElement(
9182
9406
  "button",
9183
9407
  {
9184
9408
  onClick: () => onPlayAncestry(anc.ancestry_id),
9185
9409
  className: "text-indigo-400 hover:text-white hover:bg-indigo-500 p-1 rounded-full transition-colors",
9186
9410
  title: "Renderizar no cen\xE1rio"
9187
9411
  },
9188
- /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiPlay, { size: 10, className: "ml-0.5 fill-current" })
9412
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlay, { size: 10, className: "ml-0.5 fill-current" })
9189
9413
  )
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(
9414
+ ) : /* @__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 })),
9415
+ /* @__PURE__ */ import_react24.default.createElement("span", { className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}` }, anc.name),
9416
+ 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
9417
  "button",
9194
9418
  {
9195
9419
  onClick: () => onRemoveAncestry(group.id, anc.ancestry_id),
9196
9420
  className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
9197
9421
  title: "Remover men\xE7\xE3o"
9198
9422
  },
9199
- /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiX, { size: 12 })
9423
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiX, { size: 12 })
9200
9424
  ))
9201
9425
  );
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(
9426
+ })), 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
9427
  "button",
9204
9428
  {
9205
9429
  onClick: () => onRequestPickAncestry(group.id),
@@ -9209,17 +9433,17 @@ var GroupItem = ({
9209
9433
  `,
9210
9434
  title: "Adicionar Ancestralidade a este grupo"
9211
9435
  },
9212
- isPickingForThisGroup ? /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiCheckCircle, { size: 12 }) : /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiSearch, { size: 12 }),
9436
+ isPickingForThisGroup ? /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiCheckCircle, { size: 12 }) : /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiSearch, { size: 12 }),
9213
9437
  isPickingForThisGroup ? "Selecionando..." : "Adicionar"
9214
- ), /* @__PURE__ */ import_react23.default.createElement(
9438
+ ), /* @__PURE__ */ import_react24.default.createElement(
9215
9439
  "button",
9216
9440
  {
9217
9441
  onClick: () => onAddSubgroup(group.id),
9218
9442
  className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
9219
9443
  title: "Criar Subgrupo"
9220
9444
  },
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(
9445
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlus, { size: 14 })
9446
+ )), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react24.default.createElement(
9223
9447
  "button",
9224
9448
  {
9225
9449
  onClick: () => onIndent(group.id),
@@ -9227,24 +9451,24 @@ var GroupItem = ({
9227
9451
  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
9452
  title: "Aninhar no grupo acima"
9229
9453
  },
9230
- /* @__PURE__ */ import_react23.default.createElement(import_fi17.FiArrowRight, { size: 14 })
9231
- ), /* @__PURE__ */ import_react23.default.createElement(
9454
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiArrowRight, { size: 14 })
9455
+ ), /* @__PURE__ */ import_react24.default.createElement(
9232
9456
  "button",
9233
9457
  {
9234
9458
  onClick: () => onOutdent(group.id),
9235
9459
  className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
9236
9460
  title: "Desaninhar"
9237
9461
  },
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(
9462
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiArrowLeft, { size: 14 })
9463
+ ), /* @__PURE__ */ import_react24.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react24.default.createElement(
9240
9464
  "button",
9241
9465
  {
9242
9466
  onClick: () => onDelete(group.id),
9243
9467
  className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
9244
9468
  title: "Remover Grupo"
9245
9469
  },
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(
9470
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiTrash2, { size: 14 })
9471
+ )))), 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
9472
  GroupItem,
9249
9473
  {
9250
9474
  key: childGroup.id,
@@ -9276,21 +9500,21 @@ function AncestryBoard({
9276
9500
  userRole
9277
9501
  // [NOVO] Recebe a role do usuário
9278
9502
  }) {
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)(() => {
9503
+ const [searchTerm, setSearchTerm] = (0, import_react24.useState)("");
9504
+ const [groups, setGroups] = (0, import_react24.useState)([]);
9505
+ const [isLoaded, setIsLoaded] = (0, import_react24.useState)(false);
9506
+ const [pickingGroupId, setPickingGroupId] = (0, import_react24.useState)(null);
9507
+ const [saveStatus, setSaveStatus] = (0, import_react24.useState)("idle");
9508
+ const canEdit = (0, import_react24.useMemo)(() => {
9285
9509
  return userRole !== "viewer";
9286
9510
  }, [userRole]);
9287
- (0, import_react23.useEffect)(() => {
9511
+ (0, import_react24.useEffect)(() => {
9288
9512
  if (initialGroups && !isLoaded) {
9289
9513
  setGroups(initialGroups);
9290
9514
  setIsLoaded(true);
9291
9515
  }
9292
9516
  }, [initialGroups, isLoaded]);
9293
- const nodeNamesMap = (0, import_react23.useMemo)(() => {
9517
+ const nodeNamesMap = (0, import_react24.useMemo)(() => {
9294
9518
  const map = /* @__PURE__ */ new Map();
9295
9519
  if (availableNodes && Array.isArray(availableNodes)) {
9296
9520
  availableNodes.forEach((node) => {
@@ -9301,7 +9525,7 @@ function AncestryBoard({
9301
9525
  }
9302
9526
  return map;
9303
9527
  }, [availableNodes]);
9304
- const availableIds = (0, import_react23.useMemo)(() => {
9528
+ const availableIds = (0, import_react24.useMemo)(() => {
9305
9529
  return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
9306
9530
  }, [availableAncestries]);
9307
9531
  const sanitizeGroups = (groupList) => {
@@ -9315,7 +9539,7 @@ function AncestryBoard({
9315
9539
  children: sanitizeGroups(g.children || [])
9316
9540
  }));
9317
9541
  };
9318
- (0, import_react23.useEffect)(() => {
9542
+ (0, import_react24.useEffect)(() => {
9319
9543
  if (!isLoaded || !onSave) return;
9320
9544
  const timeoutId = setTimeout(async () => {
9321
9545
  setSaveStatus("saving");
@@ -9333,7 +9557,7 @@ function AncestryBoard({
9333
9557
  }, 3e3);
9334
9558
  return () => clearTimeout(timeoutId);
9335
9559
  }, [groups, isLoaded, onSave]);
9336
- (0, import_react23.useEffect)(() => {
9560
+ (0, import_react24.useEffect)(() => {
9337
9561
  if (!isOpen) return;
9338
9562
  const handleKeyDown = (e) => {
9339
9563
  if (e.key === "Escape") {
@@ -9349,7 +9573,7 @@ function AncestryBoard({
9349
9573
  window.addEventListener("keydown", handleKeyDown);
9350
9574
  return () => window.removeEventListener("keydown", handleKeyDown);
9351
9575
  }, [isOpen, onClose, pickingGroupId]);
9352
- const filtered = (0, import_react23.useMemo)(() => {
9576
+ const filtered = (0, import_react24.useMemo)(() => {
9353
9577
  const term = searchTerm.toLowerCase().trim();
9354
9578
  return availableAncestries.filter((a) => {
9355
9579
  if (!term) return true;
@@ -9488,27 +9712,27 @@ function AncestryBoard({
9488
9712
  });
9489
9713
  };
9490
9714
  if (!isOpen) return null;
9491
- return /* @__PURE__ */ import_react23.default.createElement(
9715
+ return /* @__PURE__ */ import_react24.default.createElement(
9492
9716
  "div",
9493
9717
  {
9494
9718
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
9495
9719
  onClick: onClose
9496
9720
  },
9497
- /* @__PURE__ */ import_react23.default.createElement(
9721
+ /* @__PURE__ */ import_react24.default.createElement(
9498
9722
  "div",
9499
9723
  {
9500
9724
  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
9725
  onClick: (e) => e.stopPropagation()
9502
9726
  },
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(
9727
+ /* @__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
9728
  "button",
9505
9729
  {
9506
9730
  onClick: handleAddRootGroup,
9507
9731
  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
9732
  },
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(
9733
+ /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlus, { size: 14, className: "text-indigo-400" }),
9734
+ /* @__PURE__ */ import_react24.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
9735
+ ), /* @__PURE__ */ import_react24.default.createElement(
9512
9736
  "button",
9513
9737
  {
9514
9738
  onClick: onClose,
@@ -9516,11 +9740,11 @@ function AncestryBoard({
9516
9740
  },
9517
9741
  "\xD7"
9518
9742
  ))),
9519
- /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: `
9743
+ /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: `
9520
9744
  flex flex-col border-r border-white/10 transition-all duration-300 flex-none
9521
9745
  ${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
9522
9746
  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(
9747
+ ` }, /* @__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
9748
  "input",
9525
9749
  {
9526
9750
  type: "text",
@@ -9533,10 +9757,10 @@ function AncestryBoard({
9533
9757
  onChange: (e) => setSearchTerm(e.target.value),
9534
9758
  autoFocus: !pickingGroupId
9535
9759
  }
9536
- ))), /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
9760
+ ))), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
9537
9761
  const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
9538
9762
  const isPicking = !!pickingGroupId;
9539
- return /* @__PURE__ */ import_react23.default.createElement(
9763
+ return /* @__PURE__ */ import_react24.default.createElement(
9540
9764
  "div",
9541
9765
  {
9542
9766
  key: anc.ancestry_id,
@@ -9548,12 +9772,12 @@ function AncestryBoard({
9548
9772
  ${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
9773
  `
9550
9774
  },
9551
- /* @__PURE__ */ import_react23.default.createElement("div", { className: `
9775
+ /* @__PURE__ */ import_react24.default.createElement("div", { className: `
9552
9776
  mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
9553
9777
  ${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(
9778
+ ` }, isPicking ? /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlus, { size: 16 }) : /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiLayers, { size: 14 })),
9779
+ /* @__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)),
9780
+ !isPicking && /* @__PURE__ */ import_react24.default.createElement(
9557
9781
  "button",
9558
9782
  {
9559
9783
  onClick: (e) => {
@@ -9563,10 +9787,10 @@ function AncestryBoard({
9563
9787
  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
9788
  title: "Renderizar Ancestralidade"
9565
9789
  },
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" }))
9790
+ /* @__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
9791
  )
9568
9792
  );
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(
9793
+ }))), /* @__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
9794
  GroupItem,
9571
9795
  {
9572
9796
  key: group.id,
@@ -9586,7 +9810,7 @@ function AncestryBoard({
9586
9810
  canEdit
9587
9811
  }
9588
9812
  ))))),
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"))
9813
+ /* @__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
9814
  )
9591
9815
  );
9592
9816
  }
@@ -9666,12 +9890,12 @@ function XViewScene({
9666
9890
  check_user_permission
9667
9891
  }) {
9668
9892
  var _a, _b, _c, _d, _e, _f, _g;
9669
- const { data: session, status } = (0, import_react25.useSession)();
9893
+ const { data: session, status } = (0, import_react26.useSession)();
9670
9894
  const router = (0, import_navigation.useRouter)();
9671
9895
  const searchParams = (0, import_navigation.useSearchParams)();
9672
9896
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
9673
9897
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
9674
- const viewParams = (0, import_react24.useMemo)(() => {
9898
+ const viewParams = (0, import_react25.useMemo)(() => {
9675
9899
  if (encryptedConfig) {
9676
9900
  const data = decryptData(encryptedConfig);
9677
9901
  if (data) {
@@ -9680,7 +9904,7 @@ function XViewScene({
9680
9904
  }
9681
9905
  return null;
9682
9906
  }, [encryptedConfig, session]);
9683
- (0, import_react24.useEffect)(() => {
9907
+ (0, import_react25.useEffect)(() => {
9684
9908
  async function verifyPermission() {
9685
9909
  if (!viewParams || !session || !check_user_permission) return;
9686
9910
  const { id, type, owner_id } = viewParams;
@@ -9710,64 +9934,65 @@ function XViewScene({
9710
9934
  setIsLoading(false);
9711
9935
  }
9712
9936
  }, [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)(() => {
9937
+ const sceneConfigId = (0, import_react25.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
9938
+ const ownerId = (0, import_react25.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
9939
+ const dbSaveUrl = (0, import_react25.useMemo)(() => {
9716
9940
  if (ownerId && sceneConfigId) {
9717
9941
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
9718
9942
  }
9719
9943
  return null;
9720
9944
  }, [ownerId, sceneConfigId]);
9721
- const sceneSaveUrl = (0, import_react24.useMemo)(() => {
9945
+ const sceneSaveUrl = (0, import_react25.useMemo)(() => {
9722
9946
  if (ownerId && sceneConfigId) {
9723
9947
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
9724
9948
  }
9725
9949
  return null;
9726
9950
  }, [ownerId, sceneConfigId]);
9727
- const ancestry_save_url = (0, import_react24.useMemo)(() => {
9951
+ const ancestry_save_url = (0, import_react25.useMemo)(() => {
9728
9952
  if (ownerId && sceneConfigId) {
9729
9953
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
9730
9954
  }
9731
9955
  return null;
9732
9956
  }, [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)({
9957
+ const sceneDataRef = (0, import_react25.useRef)(null);
9958
+ const parentDataRef = (0, import_react25.useRef)(null);
9959
+ const ancestryDataRef = (0, import_react25.useRef)(null);
9960
+ const [isLoading, setIsLoading] = (0, import_react25.useState)(true);
9961
+ const [permissionStatus, setPermissionStatus] = (0, import_react25.useState)("loading");
9962
+ const [userPermissionRole, setUserPermissionRole] = (0, import_react25.useState)(null);
9963
+ const [isInitialized, setIsInitialized] = (0, import_react25.useState)(false);
9964
+ const [sceneVersion, setSceneVersion] = (0, import_react25.useState)(0);
9965
+ const [contextMenu, setContextMenu] = (0, import_react25.useState)({ visible: false, x: 0, y: 0, nodeData: null });
9966
+ const [multiContextMenu, setMultiContextMenu] = (0, import_react25.useState)({ visible: false, x: 0, y: 0, nodeIds: null });
9967
+ const [relationshipMenu, setRelationshipMenu] = (0, import_react25.useState)({ visible: false, x: 0, y: 0, linkObject: null });
9968
+ const [creationMode, setCreationMode] = (0, import_react25.useState)({ isActive: false, sourceNodeData: null });
9969
+ const [versionMode, setVersionMode] = (0, import_react25.useState)({ isActive: false, sourceNodeData: null });
9970
+ const [questMode, setQuestMode] = (0, import_react25.useState)({ isActive: false });
9971
+ const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react25.useState)(false);
9972
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react25.useState)(false);
9973
+ const [ancestryMode, setAncestryMode] = (0, import_react25.useState)({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
9974
+ const [readingMode, setReadingMode] = (0, import_react25.useState)({
9750
9975
  isActive: false,
9751
9976
  ancestry: null,
9752
9977
  branchStack: [],
9753
9978
  autoAbstraction: false
9754
9979
  });
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)({
9980
+ const [formPosition, setFormPosition] = (0, import_react25.useState)({ left: 16, top: 16, opacity: 0 });
9981
+ const [detailsNode, setDetailsNode] = (0, import_react25.useState)(null);
9982
+ const [detailsLink, setDetailsLink] = (0, import_react25.useState)(null);
9983
+ const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react25.useState)(null);
9984
+ const [imageViewer, setImageViewer] = (0, import_react25.useState)({ visible: false, images: [], startIndex: 0 });
9985
+ const [editingAncestryRel, setEditingAncestryRel] = (0, import_react25.useState)({ visible: false, data: null, path: null });
9986
+ const [isImportModalOpen, setIsImportModalOpen] = (0, import_react25.useState)(false);
9987
+ const [importSuccessMessage, setImportSuccessMessage] = (0, import_react25.useState)("");
9988
+ const [highlightedNodeId, setHighlightedNodeId] = (0, import_react25.useState)(null);
9989
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react25.useState)(false);
9990
+ const [ancestryBoardData, setAncestryBoardData] = (0, import_react25.useState)([]);
9991
+ const [isSidebarOpen, setIsSidebarOpen] = (0, import_react25.useState)(false);
9992
+ const mountRef = (0, import_react25.useRef)(null);
9993
+ const tooltipRef = (0, import_react25.useRef)(null);
9994
+ const formRef = (0, import_react25.useRef)(null);
9995
+ const stateRef = (0, import_react25.useRef)({
9771
9996
  readMode: {
9772
9997
  currentMaxIndex: 0,
9773
9998
  progressMap: {}
@@ -9812,10 +10037,10 @@ function XViewScene({
9812
10037
  minWidth: 320,
9813
10038
  maxWidth: maxReadPanelW
9814
10039
  });
9815
- (0, import_react24.useEffect)(() => {
10040
+ (0, import_react25.useEffect)(() => {
9816
10041
  stateRef.current.ancestry = ancestryMode;
9817
10042
  }, [ancestryMode]);
9818
- (0, import_react24.useEffect)(() => {
10043
+ (0, import_react25.useEffect)(() => {
9819
10044
  var _a2;
9820
10045
  if (!isInitialized) return;
9821
10046
  const map = /* @__PURE__ */ new Map();
@@ -9836,10 +10061,10 @@ function XViewScene({
9836
10061
  }
9837
10062
  stateRef.current.nodeIdToParentFileMap = map;
9838
10063
  }, [isInitialized, sceneVersion]);
9839
- const handleNavigateBack = (0, import_react24.useCallback)(() => {
10064
+ const handleNavigateBack = (0, import_react25.useCallback)(() => {
9840
10065
  router.push("/dashboard/scenes");
9841
10066
  }, [router]);
9842
- const handleConfirmImport = (0, import_react24.useCallback)(
10067
+ const handleConfirmImport = (0, import_react25.useCallback)(
9843
10068
  async (importPayload) => {
9844
10069
  var _a2, _b2;
9845
10070
  let files = [];
@@ -9937,7 +10162,7 @@ function XViewScene({
9937
10162
  const handleOpenImageViewer = (images, startIndex) => {
9938
10163
  setImageViewer({ visible: true, images, startIndex });
9939
10164
  };
9940
- const tweenToTarget = (0, import_react24.useCallback)((target, zoomFactor = 1, forcedDirection = null) => {
10165
+ const tweenToTarget = (0, import_react25.useCallback)((target, zoomFactor = 1, forcedDirection = null) => {
9941
10166
  const { camera, controls, tweenGroup } = stateRef.current;
9942
10167
  if (!camera || !controls || !tweenGroup) return;
9943
10168
  const targetPos = target instanceof THREE3.Mesh ? target.getWorldPosition(new THREE3.Vector3()) : target;
@@ -9960,7 +10185,7 @@ function XViewScene({
9960
10185
  if (!t || typeof t.closest !== "function") return false;
9961
10186
  return !!t.closest(".ui-overlay");
9962
10187
  };
9963
- const buildFullAncestryTree = (0, import_react24.useCallback)((idTree, nodes, ancestries = []) => {
10188
+ const buildFullAncestryTree = (0, import_react25.useCallback)((idTree, nodes, ancestries = []) => {
9964
10189
  if (!idTree) return null;
9965
10190
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
9966
10191
  const ancestryMap = new Map(ancestries.map((a) => [String(a.ancestry_id), a]));
@@ -10036,7 +10261,7 @@ function XViewScene({
10036
10261
  }
10037
10262
  return recursiveBuild(idTree);
10038
10263
  }, []);
10039
- const handleActivateTimeline = (0, import_react24.useCallback)(() => {
10264
+ const handleActivateTimeline = (0, import_react25.useCallback)(() => {
10040
10265
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
10041
10266
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
10042
10267
  while (timelineIntervalsGroup.children.length > 0) {
@@ -10189,7 +10414,7 @@ function XViewScene({
10189
10414
  }
10190
10415
  });
10191
10416
  }, []);
10192
- const handleVersionTimeline = (0, import_react24.useCallback)((sourceMesh, versionMeshes) => {
10417
+ const handleVersionTimeline = (0, import_react25.useCallback)((sourceMesh, versionMeshes) => {
10193
10418
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
10194
10419
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0) return;
10195
10420
  versionMeshes.forEach((mesh) => {
@@ -10312,7 +10537,7 @@ function XViewScene({
10312
10537
  }
10313
10538
  });
10314
10539
  }, []);
10315
- (0, import_react24.useEffect)(() => {
10540
+ (0, import_react25.useEffect)(() => {
10316
10541
  async function fetchAllData(configPath, ownerId2) {
10317
10542
  var _a2, _b2;
10318
10543
  if (!get_scene_view_data) {
@@ -10384,12 +10609,12 @@ function XViewScene({
10384
10609
  focusNodeId,
10385
10610
  focusAncestryId
10386
10611
  ]);
10387
- const isNodeInView = (0, import_react24.useCallback)((id) => {
10612
+ const isNodeInView = (0, import_react25.useCallback)((id) => {
10388
10613
  const key = String(id);
10389
10614
  const objs = stateRef.current.nodeObjects || {};
10390
10615
  return !!objs[key];
10391
10616
  }, []);
10392
- const addOrUpdateNodeMesh = (0, import_react24.useCallback)((nodeData, position, suppressVersionUpdate = false) => {
10617
+ const addOrUpdateNodeMesh = (0, import_react25.useCallback)((nodeData, position, suppressVersionUpdate = false) => {
10393
10618
  const { graphGroup, nodeObjects, clickableNodes, glowTexture, tweenGroup } = stateRef.current;
10394
10619
  const nodeId = String(nodeData.id);
10395
10620
  if (nodeObjects[nodeId]) {
@@ -10416,7 +10641,7 @@ function XViewScene({
10416
10641
  }
10417
10642
  return mesh;
10418
10643
  }, []);
10419
- (0, import_react24.useEffect)(() => {
10644
+ (0, import_react25.useEffect)(() => {
10420
10645
  if (!isInitialized || !sceneDataRef.current) return;
10421
10646
  const currentMount = mountRef.current;
10422
10647
  if (!currentMount) return;
@@ -10809,12 +11034,15 @@ function XViewScene({
10809
11034
  if (mountRef.current) mountRef.current.style.cursor = "grab";
10810
11035
  }
10811
11036
  function handleKeyDown(event) {
11037
+ var _a2, _b2, _c2, _d2;
10812
11038
  const context = actionHandlerContext;
10813
11039
  if (event.key === "Escape") {
10814
11040
  if (stateRef.current.connection.isActive) userActionHandlers.handleCancelConnection(context);
10815
11041
  if (stateRef.current.relink.isActive) userActionHandlers.handleCancelRelink(context);
10816
11042
  if (stateRef.current.creation.isActive) userActionHandlers.handleCancelCreation(context);
11043
+ if ((_a2 = stateRef.current.versionMode) == null ? void 0 : _a2.isActive) userActionHandlers.handleCancelVersioning(context);
10817
11044
  if (stateRef.current.ancestry.isActive) handleCancelAncestryCreation();
11045
+ if ((_b2 = context.questMode) == null ? void 0 : _b2.isActive) context.setters.setQuestMode({ isActive: false });
10818
11046
  if (stateRef.current.selectedNodes.size > 0) {
10819
11047
  stateRef.current.selectedNodes.clear();
10820
11048
  }
@@ -10822,6 +11050,17 @@ function XViewScene({
10822
11050
  setMultiContextMenu((prev) => ({ ...prev, visible: false }));
10823
11051
  setRelationshipMenu((prev) => ({ ...prev, visible: false }));
10824
11052
  }
11053
+ if (event.key.toLowerCase() === "q") {
11054
+ 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;
11055
+ if (isUiClear) {
11056
+ const isView = ((_d2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _d2.toLowerCase()) === "view";
11057
+ if (!isView) {
11058
+ alert("Nodes de Quest s\xF3 podem ser criados dentro de uma View.");
11059
+ return;
11060
+ }
11061
+ setQuestMode({ isActive: true });
11062
+ }
11063
+ }
10825
11064
  }
10826
11065
  function handleDoubleClick(event) {
10827
11066
  if (stateRef.current.camera) stateRef.current.camera.layers.enableAll();
@@ -10980,9 +11219,7 @@ function XViewScene({
10980
11219
  mountEl: currentMount,
10981
11220
  isSceneBusy: stateRef.current.isDragging || creation.isActive || connection.isActive || relink.isActive || ancestryMode.isActive,
10982
11221
  parentData: parentDataRef.current,
10983
- // <--- ADICIONADO AQUI
10984
11222
  ancestryData: ancestryDataRef.current
10985
- // <--- ADICIONADO AQUI
10986
11223
  });
10987
11224
  (_b2 = stateRef.current.tweenGroup) == null ? void 0 : _b2.update(time);
10988
11225
  stateRef.current.controls.update();
@@ -11049,7 +11286,7 @@ function XViewScene({
11049
11286
  }
11050
11287
  };
11051
11288
  }, [isInitialized, tweenToTarget, dbSaveUrl, isNodeInView, addOrUpdateNodeMesh, handleActivateTimeline, get_scene_view_data, save_view_data]);
11052
- const handleGhostNodeImageChange = (0, import_react24.useCallback)((useImage, imageUrl) => {
11289
+ const handleGhostNodeImageChange = (0, import_react25.useCallback)((useImage, imageUrl) => {
11053
11290
  const { node: ghostNode, line: ghostLine, aura: ghostAura } = stateRef.current.ghostElements;
11054
11291
  const { graphGroup, glowTexture } = stateRef.current;
11055
11292
  if (!ghostNode || !graphGroup) return;
@@ -11091,7 +11328,7 @@ function XViewScene({
11091
11328
  aura: newGhostNode.getObjectByName("aura")
11092
11329
  };
11093
11330
  }, []);
11094
- const handleGhostNodeIntensityChange = (0, import_react24.useCallback)((newIntensity) => {
11331
+ const handleGhostNodeIntensityChange = (0, import_react25.useCallback)((newIntensity) => {
11095
11332
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
11096
11333
  if (!ghostNode) return;
11097
11334
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -11112,7 +11349,7 @@ function XViewScene({
11112
11349
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
11113
11350
  }
11114
11351
  }, []);
11115
- const handleDetailNodeIntensityChange = (0, import_react24.useCallback)((nodeId, newIntensity) => {
11352
+ const handleDetailNodeIntensityChange = (0, import_react25.useCallback)((nodeId, newIntensity) => {
11116
11353
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
11117
11354
  if (!mesh) return;
11118
11355
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -11258,7 +11495,7 @@ function XViewScene({
11258
11495
  mountRef.current.style.cursor = "default";
11259
11496
  }
11260
11497
  };
11261
- const handleAncestryTreeUpdate = (0, import_react24.useCallback)((newTree, extraData = null) => {
11498
+ const handleAncestryTreeUpdate = (0, import_react25.useCallback)((newTree, extraData = null) => {
11262
11499
  setAncestryMode((prev) => {
11263
11500
  const prevTreeStr = JSON.stringify(prev.tree);
11264
11501
  const newTreeStr = JSON.stringify(newTree);
@@ -11278,7 +11515,7 @@ function XViewScene({
11278
11515
  };
11279
11516
  });
11280
11517
  }, []);
11281
- const actionHandlerContext = (0, import_react24.useMemo)(
11518
+ const actionHandlerContext = (0, import_react25.useMemo)(
11282
11519
  () => {
11283
11520
  var _a2;
11284
11521
  return {
@@ -11288,6 +11525,11 @@ function XViewScene({
11288
11525
  mountRef,
11289
11526
  creationMode,
11290
11527
  versionMode,
11528
+ questMode,
11529
+ sceneSaveUrl,
11530
+ sceneConfigId,
11531
+ ownerId,
11532
+ viewType: viewParams == null ? void 0 : viewParams.type,
11291
11533
  userId: (_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id,
11292
11534
  setters: {
11293
11535
  setContextMenu,
@@ -11299,7 +11541,8 @@ function XViewScene({
11299
11541
  setDetailsNode,
11300
11542
  setDetailsLink,
11301
11543
  setSceneVersion,
11302
- setAncestryMode
11544
+ setAncestryMode,
11545
+ setQuestMode
11303
11546
  },
11304
11547
  tweenToTarget,
11305
11548
  handleVersionTimeline,
@@ -11315,8 +11558,13 @@ function XViewScene({
11315
11558
  [
11316
11559
  creationMode,
11317
11560
  versionMode,
11318
- tweenToTarget,
11561
+ questMode,
11562
+ sceneSaveUrl,
11563
+ sceneConfigId,
11564
+ ownerId,
11565
+ viewParams == null ? void 0 : viewParams.type,
11319
11566
  (_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id,
11567
+ tweenToTarget,
11320
11568
  handleVersionTimeline,
11321
11569
  save_view_data,
11322
11570
  get_single_parent_file,
@@ -11328,7 +11576,98 @@ function XViewScene({
11328
11576
  const handleStartVersioning = (nodeData) => {
11329
11577
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
11330
11578
  };
11331
- const handleClearAncestryVisuals = (0, import_react24.useCallback)((ancestryId) => {
11579
+ const handleSaveQuestNode = async (context, newQuestData) => {
11580
+ const { graphDataRef, sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType, sceneConfigId: sceneConfigId2, ownerId: ownerId2 } = context;
11581
+ if (!graphDataRef.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
11582
+ const newNode = {
11583
+ id: import_short_uuid2.default.generate(),
11584
+ ...newQuestData,
11585
+ is_quest: true,
11586
+ type: ["quest", ...newQuestData.type.filter((t) => t !== "quest")]
11587
+ };
11588
+ if (!graphDataRef.current[sceneConfigId2]) {
11589
+ graphDataRef.current[sceneConfigId2] = { nodes: [], links: [] };
11590
+ }
11591
+ graphDataRef.current[sceneConfigId2].nodes.push(newNode);
11592
+ const sceneFileData = {
11593
+ parent_dbs: sceneDataRef2.current.parent_dbs,
11594
+ nodes: sceneDataRef2.current.nodes,
11595
+ // <-- Mantém o cenário inicial inalterado
11596
+ links: sceneDataRef2.current.links,
11597
+ // <-- Mantém o cenário inicial inalterado
11598
+ quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
11599
+ quest_links: graphDataRef.current[sceneConfigId2].links
11600
+ };
11601
+ try {
11602
+ await actions.save_view_data(sceneSaveUrl2, sceneFileData);
11603
+ stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
11604
+ parentFileId: sceneConfigId2,
11605
+ ownerId: ownerId2,
11606
+ datasetName: "Quests Internas (View)"
11607
+ });
11608
+ const basePosition = stateRef2.current.controls.target.clone();
11609
+ const offset = new THREE3.Vector3((Math.random() - 0.5) * 15, (Math.random() - 0.5) * 5, 0);
11610
+ const finalPosition = basePosition.add(offset);
11611
+ addStandaloneNodeToScene(stateRef2.current, newNode, finalPosition);
11612
+ context.tweenToTarget(finalPosition, 1.2);
11613
+ setters.setQuestMode({ isActive: false });
11614
+ setters.setSceneVersion((v) => v + 1);
11615
+ } catch (error) {
11616
+ console.error("Falha ao salvar Quest na View:", error);
11617
+ alert("Ocorreu um erro ao criar a Quest.");
11618
+ }
11619
+ };
11620
+ userActionHandlers.handleCompleteConnection = async (context, targetNodeData) => {
11621
+ const { stateRef: stateRef2, graphDataRef, sceneDataRef: sceneDataRef2, sceneConfigId: sceneConfigId2, sceneSaveUrl: sceneSaveUrl2, ownerId: ownerId2 } = context;
11622
+ const { sourceNodeData } = stateRef2.current.connection;
11623
+ if (!graphDataRef.current || !sceneDataRef2.current || !sourceNodeData || !targetNodeData) {
11624
+ userActionHandlers.handleCancelConnection(context);
11625
+ return;
11626
+ }
11627
+ const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, sourceNodeData.id, sceneConfigId2, ownerId2);
11628
+ const targetParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, targetNodeData.id, sceneConfigId2, ownerId2);
11629
+ let parentInfoToSave = sourceParentInfo;
11630
+ if (sourceParentInfo.parentFileId === sceneConfigId2 && targetParentInfo.parentFileId !== sceneConfigId2) {
11631
+ parentInfoToSave = targetParentInfo;
11632
+ } else if (targetParentInfo.parentFileId === sceneConfigId2 && sourceParentInfo.parentFileId !== sceneConfigId2) {
11633
+ parentInfoToSave = sourceParentInfo;
11634
+ }
11635
+ const { parentFileId: parentFileIdToSave, ownerId: ownerIdToSave } = parentInfoToSave;
11636
+ const newLink = {
11637
+ id: `link_${import_short_uuid2.default.generate()}`,
11638
+ source: sourceNodeData.id,
11639
+ target: targetNodeData.id
11640
+ };
11641
+ try {
11642
+ if (parentFileIdToSave === sceneConfigId2) {
11643
+ const specificParentData = graphDataRef.current[sceneConfigId2];
11644
+ specificParentData.links.push(newLink);
11645
+ const viewFilePayload = {
11646
+ parent_dbs: sceneDataRef2.current.parent_dbs,
11647
+ nodes: sceneDataRef2.current.nodes,
11648
+ // <-- Usa o estado original intocado
11649
+ links: sceneDataRef2.current.links,
11650
+ // <-- Usa o estado original intocado
11651
+ quest_nodes: specificParentData.nodes,
11652
+ quest_links: specificParentData.links
11653
+ // Salva a conexão aqui!
11654
+ };
11655
+ await context.actions.save_view_data(sceneSaveUrl2, viewFilePayload);
11656
+ } else {
11657
+ const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
11658
+ specificParentData.links.push(newLink);
11659
+ const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
11660
+ await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
11661
+ graphDataRef.current[parentFileIdToSave] = specificParentData;
11662
+ }
11663
+ addNewLinkToScene(stateRef2.current, newLink);
11664
+ } catch (error) {
11665
+ console.error("Falha ao salvar a nova conex\xE3o:", error);
11666
+ alert("Ocorreu um erro ao salvar a nova conex\xE3o.");
11667
+ }
11668
+ userActionHandlers.handleCancelConnection(context);
11669
+ };
11670
+ const handleClearAncestryVisuals = (0, import_react25.useCallback)((ancestryId) => {
11332
11671
  const { renderedAncestries, ancestryGroup } = stateRef.current;
11333
11672
  const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
11334
11673
  if (renderIndex !== -1) {
@@ -11342,7 +11681,7 @@ function XViewScene({
11342
11681
  stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
11343
11682
  }
11344
11683
  }, []);
11345
- const handleRenderAncestry = (0, import_react24.useCallback)(
11684
+ const handleRenderAncestry = (0, import_react25.useCallback)(
11346
11685
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
11347
11686
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11348
11687
  if (!ancestryObject || !ancestryObject.tree) {
@@ -11758,7 +12097,7 @@ function XViewScene({
11758
12097
  },
11759
12098
  [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, readingMode.isActive, ancestryMode.isActive]
11760
12099
  );
11761
- const handleRenderAbstractionTree = (0, import_react24.useCallback)((ancestryObject, targetNodeId = null) => {
12100
+ const handleRenderAbstractionTree = (0, import_react25.useCallback)((ancestryObject, targetNodeId = null) => {
11762
12101
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
11763
12102
  if (!ancestryObject || !ancestryObject.abstraction_tree) return;
11764
12103
  const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
@@ -11819,7 +12158,7 @@ function XViewScene({
11819
12158
  stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
11820
12159
  tweenToTarget(rootTargetPos, 0.7);
11821
12160
  }, [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, handleClearAncestryVisuals]);
11822
- const handleReadModeBranchNav = (0, import_react24.useCallback)((nodeId, action, direction = "right") => {
12161
+ const handleReadModeBranchNav = (0, import_react25.useCallback)((nodeId, action, direction = "right") => {
11823
12162
  const { ancestry, branchStack } = readingMode;
11824
12163
  if (!ancestry || !ancestry.tree) return;
11825
12164
  const allAncestries = ancestryDataRef.current || [];
@@ -11960,13 +12299,13 @@ function XViewScene({
11960
12299
  }));
11961
12300
  }
11962
12301
  }, [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]);
11963
- const handleReadModeHighlight = (0, import_react24.useCallback)((nodeId) => {
12302
+ const handleReadModeHighlight = (0, import_react25.useCallback)((nodeId) => {
11964
12303
  if (stateRef.current.highlightedNodeId !== nodeId) {
11965
12304
  stateRef.current.highlightedNodeId = nodeId;
11966
12305
  }
11967
12306
  setHighlightedNodeId(nodeId);
11968
12307
  }, []);
11969
- const activeNodeBranches = (0, import_react24.useMemo)(() => {
12308
+ const activeNodeBranches = (0, import_react25.useMemo)(() => {
11970
12309
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree) return null;
11971
12310
  const fullTree = buildFullAncestryTree(
11972
12311
  readingMode.ancestry.tree,
@@ -12003,7 +12342,7 @@ function XViewScene({
12003
12342
  }
12004
12343
  return null;
12005
12344
  }, [highlightedNodeId, readingMode.ancestry, buildFullAncestryTree, readingMode.branchStack, ancestryDataRef.current]);
12006
- const backNavigationInfo = (0, import_react24.useMemo)(() => {
12345
+ const backNavigationInfo = (0, import_react25.useMemo)(() => {
12007
12346
  const { branchStack } = readingMode;
12008
12347
  if (!branchStack || branchStack.length === 0) return null;
12009
12348
  const lastStep = branchStack[branchStack.length - 1];
@@ -12014,7 +12353,7 @@ function XViewScene({
12014
12353
  name: "Voltar para anterior"
12015
12354
  };
12016
12355
  }, [readingMode.branchStack]);
12017
- const getReadModeDisplayContext = (0, import_react24.useMemo)(() => {
12356
+ const getReadModeDisplayContext = (0, import_react25.useMemo)(() => {
12018
12357
  const { ancestry, branchStack } = readingMode;
12019
12358
  if (!ancestry) return null;
12020
12359
  if (branchStack.length === 0) {
@@ -12055,7 +12394,7 @@ function XViewScene({
12055
12394
  customProperties: branchProps
12056
12395
  };
12057
12396
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
12058
- const readModeAbstractionTree = (0, import_react24.useMemo)(() => {
12397
+ const readModeAbstractionTree = (0, import_react25.useMemo)(() => {
12059
12398
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
12060
12399
  return null;
12061
12400
  }
@@ -12067,7 +12406,7 @@ function XViewScene({
12067
12406
  allAncestries
12068
12407
  );
12069
12408
  }, [readingMode.isActive, readingMode.ancestry, buildFullAncestryTree, sceneVersion]);
12070
- const handleStartReadingAncestry = (0, import_react24.useCallback)(
12409
+ const handleStartReadingAncestry = (0, import_react25.useCallback)(
12071
12410
  async (ancestryObject) => {
12072
12411
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
12073
12412
  if (!ancestryObject || !ancestryObject.tree) {
@@ -12102,7 +12441,7 @@ function XViewScene({
12102
12441
  },
12103
12442
  [handleRenderAncestry, handleRenderAbstractionTree]
12104
12443
  );
12105
- const handleReadModeSectionChange = (0, import_react24.useCallback)((activeSectionId) => {
12444
+ const handleReadModeSectionChange = (0, import_react25.useCallback)((activeSectionId) => {
12106
12445
  const { ancestry, branchStack } = readingMode;
12107
12446
  if (!ancestry || !readingMode.isActive) return;
12108
12447
  let targetObj = ancestry;
@@ -12171,10 +12510,10 @@ function XViewScene({
12171
12510
  }, 0);
12172
12511
  handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
12173
12512
  }, [readingMode, handleRenderAncestry, buildFullAncestryTree, ancestryDataRef.current]);
12174
- const handleCloseReadMode = (0, import_react24.useCallback)(() => {
12513
+ const handleCloseReadMode = (0, import_react25.useCallback)(() => {
12175
12514
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
12176
12515
  }, []);
12177
- const handleAncestrySectionChange = (0, import_react24.useCallback)((activeSectionId, ancestryOverride = null, rotation = 0) => {
12516
+ const handleAncestrySectionChange = (0, import_react25.useCallback)((activeSectionId, ancestryOverride = null, rotation = 0) => {
12178
12517
  var _a2, _b2;
12179
12518
  const currentMode = stateRef.current.ancestry;
12180
12519
  let targetObj = ancestryOverride;
@@ -12226,7 +12565,7 @@ function XViewScene({
12226
12565
  const renderPayload = { ...targetObj, tree: treeToRender };
12227
12566
  handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
12228
12567
  }, [handleRenderAncestry]);
12229
- const handleEditAncestry = (0, import_react24.useCallback)(
12568
+ const handleEditAncestry = (0, import_react25.useCallback)(
12230
12569
  async (ancestryObject) => {
12231
12570
  setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
12232
12571
  if (!ancestryObject || !ancestryObject.tree) {
@@ -12265,7 +12604,7 @@ function XViewScene({
12265
12604
  const handleSelectAncestryParent = (nodeId) => {
12266
12605
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
12267
12606
  };
12268
- const handleRemoveFromAncestry = (0, import_react24.useCallback)((pathToRemove) => {
12607
+ const handleRemoveFromAncestry = (0, import_react25.useCallback)((pathToRemove) => {
12269
12608
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
12270
12609
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
12271
12610
  return;
@@ -12290,7 +12629,7 @@ function XViewScene({
12290
12629
  return { ...prev, tree: newTree };
12291
12630
  });
12292
12631
  }, []);
12293
- const handleSaveAncestry = (0, import_react24.useCallback)(
12632
+ const handleSaveAncestry = (0, import_react25.useCallback)(
12294
12633
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
12295
12634
  const treeToUse = treeOverride || ancestryMode.tree;
12296
12635
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -12494,7 +12833,7 @@ function XViewScene({
12494
12833
  });
12495
12834
  setEditingAncestryRel({ visible: false, data: null, path: null });
12496
12835
  };
12497
- const handleDeleteAncestry = (0, import_react24.useCallback)(
12836
+ const handleDeleteAncestry = (0, import_react25.useCallback)(
12498
12837
  async (ancestryIdToDelete) => {
12499
12838
  if (!ancestryIdToDelete) {
12500
12839
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -12556,20 +12895,20 @@ function XViewScene({
12556
12895
  },
12557
12896
  [save_view_data, delete_file_action]
12558
12897
  );
12559
- const handleOpenAncestryBoard = (0, import_react24.useCallback)(() => {
12898
+ const handleOpenAncestryBoard = (0, import_react25.useCallback)(() => {
12560
12899
  setIsAncestryBoardOpen(true);
12561
12900
  }, []);
12562
- const handleSelectAncestryFromBoard = (0, import_react24.useCallback)((ancestry) => {
12901
+ const handleSelectAncestryFromBoard = (0, import_react25.useCallback)((ancestry) => {
12563
12902
  setIsAncestryBoardOpen(false);
12564
12903
  setIsSidebarOpen(false);
12565
12904
  handleStartReadingAncestry(ancestry);
12566
12905
  }, [handleStartReadingAncestry]);
12567
- const handleSaveAncestryBoard = (0, import_react24.useCallback)(async (groups) => {
12906
+ const handleSaveAncestryBoard = (0, import_react25.useCallback)(async (groups) => {
12568
12907
  if (!sceneConfigId || !viewParams || !session) return;
12569
12908
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
12570
12909
  await save_ancestry_board_action(sceneConfigId, sceneType, groups, session, ownerId);
12571
12910
  }, [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]);
12572
- const existingNodeTypes = (0, import_react24.useMemo)(() => {
12911
+ const existingNodeTypes = (0, import_react25.useMemo)(() => {
12573
12912
  if (!parentDataRef.current) {
12574
12913
  return [];
12575
12914
  }
@@ -12579,7 +12918,7 @@ function XViewScene({
12579
12918
  })).filter(Boolean);
12580
12919
  return [...new Set(allTypes)];
12581
12920
  }, [parentDataRef.current, sceneVersion]);
12582
- const searchableDbNodes = (0, import_react24.useMemo)(() => {
12921
+ const searchableDbNodes = (0, import_react25.useMemo)(() => {
12583
12922
  if (!parentDataRef.current) {
12584
12923
  return [];
12585
12924
  }
@@ -12588,13 +12927,14 @@ function XViewScene({
12588
12927
  return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
12589
12928
  });
12590
12929
  }, [parentDataRef.current, sceneVersion]);
12591
- const handleAddExistingNode = (0, import_react24.useCallback)(
12930
+ const handleAddExistingNode = (0, import_react25.useCallback)(
12592
12931
  (nodeId) => {
12593
12932
  return userActionHandlers.handleAddExistingNodeById(actionHandlerContext, nodeId);
12594
12933
  },
12595
12934
  [actionHandlerContext]
12596
12935
  );
12597
- const handleSaveCurrentView = (0, import_react24.useCallback)(async () => {
12936
+ const handleSaveCurrentView = (0, import_react25.useCallback)(async () => {
12937
+ var _a2, _b2, _c2;
12598
12938
  const { nodeObjects, allLinks } = stateRef.current;
12599
12939
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
12600
12940
  console.warn("N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente.");
@@ -12616,25 +12956,30 @@ function XViewScene({
12616
12956
  const { sourceNode, targetNode, ...serializableLinkData } = line.userData;
12617
12957
  return serializableLinkData;
12618
12958
  });
12959
+ sceneDataRef.current.nodes = currentNodes;
12960
+ sceneDataRef.current.links = currentLinks;
12961
+ const isView = ((_a2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _a2.toLowerCase()) === "view";
12619
12962
  const sceneFileData = {
12620
12963
  parent_dbs: sceneDataRef.current.parent_dbs,
12621
12964
  nodes: currentNodes,
12622
- links: currentLinks
12965
+ links: currentLinks,
12966
+ quest_nodes: isView ? ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || [] : sceneDataRef.current.quest_nodes || [],
12967
+ quest_links: isView ? ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || [] : sceneDataRef.current.quest_links || []
12623
12968
  };
12624
12969
  try {
12625
12970
  await save_view_data(sceneSaveUrl, sceneFileData);
12626
12971
  } catch (error) {
12627
12972
  console.error("Erro na chamada de save_view_data:", error);
12628
12973
  }
12629
- }, [sceneSaveUrl, save_view_data]);
12630
- const allAvailableNodes = (0, import_react24.useMemo)(() => {
12974
+ }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
12975
+ const allAvailableNodes = (0, import_react25.useMemo)(() => {
12631
12976
  if (!parentDataRef.current) return [];
12632
12977
  return Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
12633
12978
  }, [sceneVersion, isInitialized]);
12634
- const allAvailableAncestries = (0, import_react24.useMemo)(() => {
12979
+ const allAvailableAncestries = (0, import_react25.useMemo)(() => {
12635
12980
  return ancestryDataRef.current || [];
12636
12981
  }, [sceneVersion, isInitialized]);
12637
- const handleOpenReference = (0, import_react24.useCallback)((referenceData) => {
12982
+ const handleOpenReference = (0, import_react25.useCallback)((referenceData) => {
12638
12983
  const { type, id } = referenceData;
12639
12984
  if (type === "node") {
12640
12985
  const targetNode = allAvailableNodes.find((n) => String(n.id) === String(id));
@@ -12661,17 +13006,17 @@ function XViewScene({
12661
13006
  }
12662
13007
  }
12663
13008
  }, [allAvailableNodes, allAvailableAncestries, handleEditAncestry, tweenToTarget]);
12664
- const handleToggleAncestryAddMode = (0, import_react24.useCallback)(() => {
13009
+ const handleToggleAncestryAddMode = (0, import_react25.useCallback)(() => {
12665
13010
  setAncestryMode((prev) => ({ ...prev, isAddingNodes: !prev.isAddingNodes }));
12666
13011
  }, []);
12667
- const handleFocusNode = (0, import_react24.useCallback)((nodeData) => {
13012
+ const handleFocusNode = (0, import_react25.useCallback)((nodeData) => {
12668
13013
  if (!nodeData) return;
12669
13014
  const nodeMesh = stateRef.current.nodeObjects[String(nodeData.id)];
12670
13015
  if (nodeMesh) {
12671
13016
  tweenToTarget(nodeMesh, 1.2);
12672
13017
  }
12673
13018
  }, [tweenToTarget]);
12674
- const availableDatasets = (0, import_react24.useMemo)(() => {
13019
+ const availableDatasets = (0, import_react25.useMemo)(() => {
12675
13020
  if (!sceneDataRef.current || !parentDataRef.current) return [];
12676
13021
  return sceneDataRef.current.parent_dbs.map((db) => {
12677
13022
  var _a2;
@@ -12683,7 +13028,7 @@ function XViewScene({
12683
13028
  }, [sceneVersion, isInitialized]);
12684
13029
  const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(String(creationMode.sourceNodeData.id))) == null ? void 0 : _b.parentFileId : null;
12685
13030
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
12686
- (0, import_react24.useEffect)(() => {
13031
+ (0, import_react25.useEffect)(() => {
12687
13032
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
12688
13033
  const nodeObjects = stateRef.current.nodeObjects || {};
12689
13034
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -12697,7 +13042,7 @@ function XViewScene({
12697
13042
  }
12698
13043
  }
12699
13044
  }, [isInitialized, sceneVersion, focusNodeId, hasFocusedInitial, tweenToTarget]);
12700
- (0, import_react24.useEffect)(() => {
13045
+ (0, import_react25.useEffect)(() => {
12701
13046
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
12702
13047
  const ancestries = ancestryDataRef.current || [];
12703
13048
  const targetAncestry = ancestries.find((a) => String(a.ancestry_id) === String(focusAncestryId));
@@ -12712,20 +13057,20 @@ function XViewScene({
12712
13057
  }
12713
13058
  }, [isInitialized, sceneVersion, focusAncestryId, hasOpenedInitialAncestry, handleStartReadingAncestry]);
12714
13059
  if (isLoading || status === "loading" || permissionStatus === "loading") {
12715
- return /* @__PURE__ */ import_react24.default.createElement(LoadingScreen, null);
13060
+ return /* @__PURE__ */ import_react25.default.createElement(LoadingScreen, null);
12716
13061
  }
12717
13062
  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(
13063
+ 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
13064
  "button",
12720
13065
  {
12721
13066
  onClick: () => router.push("/dashboard/scenes"),
12722
13067
  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
13068
  },
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" })),
13069
+ /* @__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
13070
  "Voltar para Scenes"
12726
13071
  )));
12727
13072
  }
12728
- return /* @__PURE__ */ import_react24.default.createElement(
13073
+ return /* @__PURE__ */ import_react25.default.createElement(
12729
13074
  "div",
12730
13075
  {
12731
13076
  ref: mountRef,
@@ -12737,7 +13082,7 @@ function XViewScene({
12737
13082
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
12738
13083
  }
12739
13084
  },
12740
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react24.default.createElement(
13085
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react25.default.createElement(
12741
13086
  XViewSidebar,
12742
13087
  {
12743
13088
  dbNodes: searchableDbNodes,
@@ -12757,7 +13102,7 @@ function XViewScene({
12757
13102
  userRole: userPermissionRole
12758
13103
  }
12759
13104
  ),
12760
- creationMode.isActive && /* @__PURE__ */ import_react24.default.createElement(
13105
+ creationMode.isActive && /* @__PURE__ */ import_react25.default.createElement(
12761
13106
  InSceneCreationForm,
12762
13107
  {
12763
13108
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -12782,7 +13127,7 @@ function XViewScene({
12782
13127
  availableAncestries: allAvailableAncestries
12783
13128
  }
12784
13129
  ),
12785
- versionMode.isActive && /* @__PURE__ */ import_react24.default.createElement(
13130
+ versionMode.isActive && /* @__PURE__ */ import_react25.default.createElement(
12786
13131
  InSceneVersionForm,
12787
13132
  {
12788
13133
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -12801,13 +13146,27 @@ function XViewScene({
12801
13146
  availableAncestries: allAvailableAncestries
12802
13147
  }
12803
13148
  ),
12804
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react24.default.createElement(
13149
+ questMode.isActive && /* @__PURE__ */ import_react25.default.createElement(
13150
+ InSceneQuestForm,
13151
+ {
13152
+ onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
13153
+ onCancel: () => setQuestMode({ isActive: false }),
13154
+ style: { position: "absolute", left: `16px`, top: `16px`, zIndex: 20, transition: "opacity 200ms ease-out" },
13155
+ refEl: formRef,
13156
+ onOpenImageViewer: handleOpenImageViewer,
13157
+ onMentionClick: handleAddExistingNode,
13158
+ onUploadFile: upload_file_action,
13159
+ availableNodes: allAvailableNodes,
13160
+ availableAncestries: allAvailableAncestries
13161
+ }
13162
+ ),
13163
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react25.default.createElement(
12805
13164
  "div",
12806
13165
  {
12807
13166
  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
13167
  style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${readModeWidth}px`, maxWidth: "92vw" }
12809
13168
  },
12810
- /* @__PURE__ */ import_react24.default.createElement(
13169
+ /* @__PURE__ */ import_react25.default.createElement(
12811
13170
  "div",
12812
13171
  {
12813
13172
  onPointerDown: (e) => {
@@ -12818,7 +13177,7 @@ function XViewScene({
12818
13177
  title: "Arraste para redimensionar"
12819
13178
  }
12820
13179
  ),
12821
- /* @__PURE__ */ import_react24.default.createElement(
13180
+ /* @__PURE__ */ import_react25.default.createElement(
12822
13181
  DescriptionReadModePanel,
12823
13182
  {
12824
13183
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -12853,7 +13212,7 @@ function XViewScene({
12853
13212
  }
12854
13213
  )
12855
13214
  ),
12856
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react24.default.createElement(
13215
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react25.default.createElement(
12857
13216
  CreateAncestryPanel,
12858
13217
  {
12859
13218
  ancestryMode,
@@ -12880,7 +13239,7 @@ function XViewScene({
12880
13239
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
12881
13240
  }
12882
13241
  ),
12883
- editingAncestryRel.visible && /* @__PURE__ */ import_react24.default.createElement(
13242
+ editingAncestryRel.visible && /* @__PURE__ */ import_react25.default.createElement(
12884
13243
  AncestryRelationshipPanel,
12885
13244
  {
12886
13245
  data: editingAncestryRel.data,
@@ -12894,7 +13253,7 @@ function XViewScene({
12894
13253
  onUploadFile: upload_file_action
12895
13254
  }
12896
13255
  ),
12897
- detailsNode && /* @__PURE__ */ import_react24.default.createElement(
13256
+ detailsNode && /* @__PURE__ */ import_react25.default.createElement(
12898
13257
  NodeDetailsPanel,
12899
13258
  {
12900
13259
  node: detailsNode,
@@ -12921,7 +13280,7 @@ function XViewScene({
12921
13280
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
12922
13281
  }
12923
13282
  ),
12924
- detailsLink && /* @__PURE__ */ import_react24.default.createElement(
13283
+ detailsLink && /* @__PURE__ */ import_react25.default.createElement(
12925
13284
  RelationshipDetailsPanel,
12926
13285
  {
12927
13286
  link: detailsLink,
@@ -12935,7 +13294,7 @@ function XViewScene({
12935
13294
  userRole: userPermissionRole
12936
13295
  }
12937
13296
  ),
12938
- ancestryLinkDetails && /* @__PURE__ */ import_react24.default.createElement(
13297
+ ancestryLinkDetails && /* @__PURE__ */ import_react25.default.createElement(
12939
13298
  AncestryLinkDetailsPanel,
12940
13299
  {
12941
13300
  data: ancestryLinkDetails,
@@ -12946,7 +13305,7 @@ function XViewScene({
12946
13305
  onUploadFile: upload_file_action
12947
13306
  }
12948
13307
  ),
12949
- /* @__PURE__ */ import_react24.default.createElement(
13308
+ /* @__PURE__ */ import_react25.default.createElement(
12950
13309
  "div",
12951
13310
  {
12952
13311
  ref: tooltipRef,
@@ -12973,7 +13332,7 @@ function XViewScene({
12973
13332
  }
12974
13333
  }
12975
13334
  ),
12976
- /* @__PURE__ */ import_react24.default.createElement(
13335
+ /* @__PURE__ */ import_react25.default.createElement(
12977
13336
  ContextMenu,
12978
13337
  {
12979
13338
  data: contextMenu,
@@ -12996,7 +13355,7 @@ function XViewScene({
12996
13355
  onFocusNode: handleFocusNode
12997
13356
  }
12998
13357
  ),
12999
- /* @__PURE__ */ import_react24.default.createElement(
13358
+ /* @__PURE__ */ import_react25.default.createElement(
13000
13359
  MultiNodeContextMenu,
13001
13360
  {
13002
13361
  data: multiContextMenu,
@@ -13007,7 +13366,7 @@ function XViewScene({
13007
13366
  onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(actionHandlerContext, ids)
13008
13367
  }
13009
13368
  ),
13010
- /* @__PURE__ */ import_react24.default.createElement(
13369
+ /* @__PURE__ */ import_react25.default.createElement(
13011
13370
  RelationshipContextMenu,
13012
13371
  {
13013
13372
  data: relationshipMenu,
@@ -13025,8 +13384,8 @@ function XViewScene({
13025
13384
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
13026
13385
  }
13027
13386
  ),
13028
- /* @__PURE__ */ import_react24.default.createElement(ImageViewer, { data: imageViewer, onClose: () => setImageViewer({ ...imageViewer, visible: false }) }),
13029
- /* @__PURE__ */ import_react24.default.createElement(
13387
+ /* @__PURE__ */ import_react25.default.createElement(ImageViewer, { data: imageViewer, onClose: () => setImageViewer({ ...imageViewer, visible: false }) }),
13388
+ /* @__PURE__ */ import_react25.default.createElement(
13030
13389
  AncestryBoard,
13031
13390
  {
13032
13391
  isOpen: isAncestryBoardOpen,
@@ -13039,7 +13398,7 @@ function XViewScene({
13039
13398
  userRole: userPermissionRole
13040
13399
  }
13041
13400
  ),
13042
- /* @__PURE__ */ import_react24.default.createElement(
13401
+ /* @__PURE__ */ import_react25.default.createElement(
13043
13402
  ImportParentFileModal,
13044
13403
  {
13045
13404
  isOpen: isImportModalOpen,
@@ -13100,11 +13459,24 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
13100
13459
  );
13101
13460
  }
13102
13461
  }
13462
+ if (type && type.toLowerCase() === "view") {
13463
+ parentData[scene_config] = {
13464
+ dataset_name: "Quests Internas (View)",
13465
+ nodes: sceneData.quest_nodes || [],
13466
+ links: sceneData.quest_links || []
13467
+ };
13468
+ }
13103
13469
  const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
13104
13470
  const allLinks = Object.values(parentData).flatMap((db) => db.links || []);
13105
13471
  const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
13106
13472
  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);
13473
+ const validatedNodes = (sceneData.nodes || []).map((sceneNode) => {
13474
+ const nodeTypes = Array.isArray(sceneNode.type) ? sceneNode.type : [sceneNode.type];
13475
+ if (nodeTypes.includes("quest")) {
13476
+ return sceneNode;
13477
+ }
13478
+ return parentNodeMap.get(String(sceneNode.id));
13479
+ }).filter(Boolean);
13108
13480
  const validNodeIdsInScene = new Set(validatedNodes.map((node) => String(node.id)));
13109
13481
  const validatedLinks = (sceneData.links || []).filter((sceneLink) => {
13110
13482
  const linkExistsInParent = parentLinkMap.has(`${sceneLink.source}-${sceneLink.target}`);