@lv-x-software-house/x_view 1.3.3 → 1.3.5

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.
package/dist/index.mjs CHANGED
@@ -897,7 +897,7 @@ var getParentFileInfoForNode = (allParentData, sceneData, nodeId, sceneConfigId
897
897
  };
898
898
  async function instantiateSubProcess(context, templateProcess, versionedProcess, startCounter) {
899
899
  var _a, _b, _c;
900
- const { graphDataRef, sceneDataRef, actions: actions2 } = context;
900
+ const { graphDataRef, sceneDataRef, actions } = context;
901
901
  const ownerId = context.ownerId;
902
902
  const parentFileId = context.sceneConfigId;
903
903
  const viewName = context.viewName || "View";
@@ -952,7 +952,7 @@ async function instantiateSubProcess(context, templateProcess, versionedProcess,
952
952
  }
953
953
  ] : originalChildNode.timeline || []
954
954
  };
955
- if (actions2.copy_google_doc_action && versionedChildNode.Links) {
955
+ if (actions.copy_google_doc_action && versionedChildNode.Links) {
956
956
  const docIdx = versionedChildNode.Links.findIndex((l) => l.name === "Google docs");
957
957
  if (docIdx !== -1) {
958
958
  const url = versionedChildNode.Links[docIdx].value;
@@ -960,7 +960,7 @@ async function instantiateSubProcess(context, templateProcess, versionedProcess,
960
960
  const match = url.match(/\/d\/([a-zA-Z0-9-_]+)/);
961
961
  if (match == null ? void 0 : match[1]) {
962
962
  try {
963
- const res = await actions2.copy_google_doc_action(
963
+ const res = await actions.copy_google_doc_action(
964
964
  match[1],
965
965
  nextName,
966
966
  (_c = sceneDataRef.current) == null ? void 0 : _c.view_google_folder_id
@@ -999,14 +999,14 @@ async function instantiateSubProcess(context, templateProcess, versionedProcess,
999
999
  childRef.node.version_node = versionedChildNode.version_node;
1000
1000
  }
1001
1001
  childRef.node_id = versionedChildId;
1002
- if (versionedChildNode.is_quest && actions2.upsert_quest_firestore) {
1003
- savePromises.push(actions2.upsert_quest_firestore(ownerId, parentFileId, versionedChildNode));
1004
- if (actions2.upsert_quest_link_firestore)
1005
- savePromises.push(actions2.upsert_quest_link_firestore(ownerId, parentFileId, childVersionLink));
1006
- } else if (versionedChildNode.is_process && actions2.upsert_process_firestore) {
1007
- savePromises.push(actions2.upsert_process_firestore(ownerId, parentFileId, versionedChildNode));
1008
- if (actions2.upsert_process_link_firestore)
1009
- savePromises.push(actions2.upsert_process_link_firestore(ownerId, parentFileId, childVersionLink));
1002
+ if (versionedChildNode.is_quest && actions.upsert_quest_firestore) {
1003
+ savePromises.push(actions.upsert_quest_firestore(ownerId, parentFileId, versionedChildNode));
1004
+ if (actions.upsert_quest_link_firestore)
1005
+ savePromises.push(actions.upsert_quest_link_firestore(ownerId, parentFileId, childVersionLink));
1006
+ } else if (versionedChildNode.is_process && actions.upsert_process_firestore) {
1007
+ savePromises.push(actions.upsert_process_firestore(ownerId, parentFileId, versionedChildNode));
1008
+ if (actions.upsert_process_link_firestore)
1009
+ savePromises.push(actions.upsert_process_link_firestore(ownerId, parentFileId, childVersionLink));
1010
1010
  }
1011
1011
  }
1012
1012
  if (versionedProcess.process_abstraction_tree) {
@@ -1138,7 +1138,7 @@ var userActionHandlers = {
1138
1138
  stateRef,
1139
1139
  creationMode,
1140
1140
  setters,
1141
- actions: actions2,
1141
+ actions,
1142
1142
  checkLimit
1143
1143
  } = context;
1144
1144
  if (!graphDataRef.current || !sceneDataRef.current) return;
@@ -1172,20 +1172,20 @@ var userActionHandlers = {
1172
1172
  const savePromises = [];
1173
1173
  if (isCrossDataset) {
1174
1174
  savePromises.push(
1175
- actions2.save_view_data(
1175
+ actions.save_view_data(
1176
1176
  `x_view_dbs/${sourceParentInfo.ownerId}/${sourceParentInfo.parentFileId}`,
1177
1177
  sourceDataToUpdate
1178
1178
  )
1179
1179
  );
1180
1180
  savePromises.push(
1181
- actions2.save_view_data(
1181
+ actions.save_view_data(
1182
1182
  `x_view_dbs/${targetParentInfo.owner_id}/${finalTargetDatasetId}`,
1183
1183
  targetDataToUpdate
1184
1184
  )
1185
1185
  );
1186
1186
  } else {
1187
1187
  savePromises.push(
1188
- actions2.save_view_data(
1188
+ actions.save_view_data(
1189
1189
  `x_view_dbs/${sourceParentInfo.ownerId}/${sourceParentInfo.parentFileId}`,
1190
1190
  sourceDataToUpdate
1191
1191
  )
@@ -1208,8 +1208,8 @@ var userActionHandlers = {
1208
1208
  ownerId: targetParentInfo.owner_id,
1209
1209
  datasetName: targetDataToUpdate.dataset_name || "Dataset Desconhecido"
1210
1210
  });
1211
- if (actions2.update_node_counter) {
1212
- await actions2.update_node_counter(targetParentInfo.owner_id, 1);
1211
+ if (actions.update_node_counter) {
1212
+ await actions.update_node_counter(targetParentInfo.owner_id, 1);
1213
1213
  }
1214
1214
  setters.setSceneVersion((v) => v + 1);
1215
1215
  } catch (error) {
@@ -1343,7 +1343,7 @@ var userActionHandlers = {
1343
1343
  },
1344
1344
  handleSaveVersionNode: async (context, newNodeData) => {
1345
1345
  var _a;
1346
- const { graphDataRef, sceneDataRef, stateRef, versionMode, setters, checkLimit } = context;
1346
+ const { graphDataRef, sceneDataRef, stateRef, versionMode, setters, checkLimit, actions } = context;
1347
1347
  if (!graphDataRef.current || !sceneDataRef.current) return;
1348
1348
  if (checkLimit && checkLimit()) return;
1349
1349
  const { sourceNodeData } = versionMode;
@@ -1454,8 +1454,8 @@ var userActionHandlers = {
1454
1454
  );
1455
1455
  const targetFinalPositions = [];
1456
1456
  const newVersionMeshes = [];
1457
+ const newNodesToCreate = [];
1457
1458
  linksToExpand.forEach((link) => {
1458
- var _a;
1459
1459
  const isSource = String(link.source) === String(sourceNode.id);
1460
1460
  const targetNodeId = isSource ? link.target : link.source;
1461
1461
  if (!nodeObjects[String(targetNodeId)]) {
@@ -1465,44 +1465,93 @@ var userActionHandlers = {
1465
1465
  const nodeData = allParentNodes.find(
1466
1466
  (n) => String(n.id) === String(targetNodeId)
1467
1467
  );
1468
- if (!nodeData) {
1469
- console.warn(
1470
- `Dados do Node com ID ${targetNodeId} n\xE3o encontrados no cache.`
1471
- );
1472
- return;
1468
+ if (nodeData) {
1469
+ newNodesToCreate.push({ link, nodeData, targetNodeId });
1473
1470
  }
1474
- const startPosition = sourceNodeMesh.position.clone();
1475
- const endPosition = startPosition.clone().add(
1476
- new THREE.Vector3(
1477
- (Math.random() - 0.5) * 60,
1478
- (Math.random() - 0.5) * 15,
1479
- (Math.random() - 0.5) * 60
1480
- )
1481
- );
1482
- targetFinalPositions.push(endPosition);
1483
- const targetMesh = createNodeMesh(
1484
- nodeData,
1485
- startPosition,
1486
- glowTexture,
1487
- !!nodeData.is_quest
1488
- );
1489
- targetMesh.scale.set(0.01, 0.01, 0.01);
1490
- graphGroup.add(targetMesh);
1491
- if (targetMesh.userData.labelObject) {
1492
- graphGroup.add(targetMesh.userData.labelObject);
1493
- }
1494
- nodeObjects[String(targetNodeId)] = targetMesh;
1495
- clickableNodes.push(targetMesh);
1496
- const posTween = new Tween(targetMesh.position).to(endPosition, 1200).easing(Easing.Quadratic.Out);
1497
- tweenGroup.add(posTween);
1498
- posTween.start();
1499
- const targetScale = NODE_SCALE_FACTORS[nodeData.size || "medium"] || 1;
1500
- const scaleTween = new Tween(targetMesh.scale).to({ x: targetScale, y: targetScale, z: targetScale }, 1e3).easing(Easing.Elastic.Out);
1501
- tweenGroup.add(scaleTween);
1502
- scaleTween.start();
1503
- if (((_a = nodeData.version_node) == null ? void 0 : _a.is_version) && String(nodeData.version_node.parent_node) === String(sourceNode.id)) {
1504
- newVersionMeshes.push(targetMesh);
1471
+ }
1472
+ });
1473
+ const N = newNodesToCreate.length;
1474
+ let referenceDir = new THREE.Vector3(0, 0, 1);
1475
+ if (N > 0) {
1476
+ const incomingVectors = [];
1477
+ allLinks.forEach((l) => {
1478
+ const srcId = String(l.userData.source);
1479
+ const tgtId = String(l.userData.target);
1480
+ if (srcId === String(sourceNode.id) || tgtId === String(sourceNode.id)) {
1481
+ const otherId = srcId === String(sourceNode.id) ? tgtId : srcId;
1482
+ const otherMesh = nodeObjects[otherId];
1483
+ if (otherMesh) {
1484
+ const dir = new THREE.Vector3().subVectors(
1485
+ sourceNodeMesh.position,
1486
+ otherMesh.position
1487
+ );
1488
+ if (dir.lengthSq() > 1e-3) {
1489
+ dir.normalize();
1490
+ incomingVectors.push(dir);
1491
+ }
1492
+ }
1493
+ }
1494
+ });
1495
+ if (incomingVectors.length > 0) {
1496
+ referenceDir.set(0, 0, 0);
1497
+ incomingVectors.forEach((v) => referenceDir.add(v));
1498
+ if (referenceDir.lengthSq() > 1e-3) {
1499
+ referenceDir.normalize();
1500
+ } else {
1501
+ referenceDir.set(0, 0, 1);
1505
1502
  }
1503
+ } else {
1504
+ const toSource = sourceNodeMesh.position.clone();
1505
+ if (toSource.lengthSq() > 1e-3) {
1506
+ referenceDir.copy(toSource).normalize();
1507
+ }
1508
+ }
1509
+ }
1510
+ const up = new THREE.Vector3(0, 1, 0);
1511
+ if (Math.abs(referenceDir.y) > 0.95) {
1512
+ up.set(1, 0, 0);
1513
+ }
1514
+ const right = new THREE.Vector3().crossVectors(up, referenceDir).normalize();
1515
+ const upActual = new THREE.Vector3().crossVectors(referenceDir, right).normalize();
1516
+ const maxSpread = N <= 1 ? 0 : Math.min(Math.PI * 0.4 + (N - 2) * 0.15, Math.PI * 0.8);
1517
+ const baseDistance = 40;
1518
+ newNodesToCreate.forEach((item, i) => {
1519
+ var _a;
1520
+ const { link, nodeData, targetNodeId } = item;
1521
+ let phi = 0;
1522
+ if (N > 1) {
1523
+ phi = -maxSpread / 2 + i / (N - 1) * maxSpread;
1524
+ }
1525
+ const angleY = N > 1 ? Math.sin(i * Math.PI) * 0.12 : 0;
1526
+ const nodeDir = referenceDir.clone().multiplyScalar(Math.cos(phi)).add(right.clone().multiplyScalar(Math.sin(phi))).add(upActual.clone().multiplyScalar(angleY)).normalize();
1527
+ const distFactor = N > 1 ? 1 + (i % 2 === 0 ? 0 : 0.15) : 1;
1528
+ const distance = baseDistance * distFactor;
1529
+ const startPosition = sourceNodeMesh.position.clone();
1530
+ const endPosition = startPosition.clone().add(nodeDir.multiplyScalar(distance));
1531
+ targetFinalPositions.push(endPosition);
1532
+ const targetMesh = createNodeMesh(
1533
+ nodeData,
1534
+ startPosition,
1535
+ glowTexture,
1536
+ !!nodeData.is_quest
1537
+ );
1538
+ targetMesh.scale.set(0.01, 0.01, 0.01);
1539
+ graphGroup.add(targetMesh);
1540
+ if (targetMesh.userData.labelObject) {
1541
+ graphGroup.add(targetMesh.userData.labelObject);
1542
+ }
1543
+ nodeObjects[String(targetNodeId)] = targetMesh;
1544
+ clickableNodes.push(targetMesh);
1545
+ const delay = i * 60;
1546
+ const posTween = new Tween(targetMesh.position).to(endPosition, 1200).delay(delay).easing(Easing.Quadratic.Out);
1547
+ tweenGroup.add(posTween);
1548
+ posTween.start();
1549
+ const targetScale = NODE_SCALE_FACTORS[nodeData.size || "medium"] || 1;
1550
+ const scaleTween = new Tween(targetMesh.scale).to({ x: targetScale, y: targetScale, z: targetScale }, 1e3).delay(delay).easing(Easing.Elastic.Out);
1551
+ tweenGroup.add(scaleTween);
1552
+ scaleTween.start();
1553
+ if (((_a = nodeData.version_node) == null ? void 0 : _a.is_version) && String(nodeData.version_node.parent_node) === String(sourceNode.id)) {
1554
+ newVersionMeshes.push(targetMesh);
1506
1555
  }
1507
1556
  });
1508
1557
  linksToExpand.forEach((link) => {
@@ -1535,7 +1584,12 @@ var userActionHandlers = {
1535
1584
  newLine.material.opacity = 0;
1536
1585
  graphGroup.add(newLine);
1537
1586
  allLinks.push(newLine);
1538
- const opacityTween = new Tween(newLine.material).to({ opacity: 0.3 }, 800).delay(500);
1587
+ const targetId = String(newLine.userData.target);
1588
+ const newNodeIndex = newNodesToCreate.findIndex(
1589
+ (item) => String(item.targetNodeId) === targetId
1590
+ );
1591
+ const delay = newNodeIndex !== -1 ? newNodeIndex * 60 : 0;
1592
+ const opacityTween = new Tween(newLine.material).to({ opacity: 0.3 }, 800).delay(delay);
1539
1593
  tweenGroup.add(opacityTween);
1540
1594
  opacityTween.start();
1541
1595
  });
@@ -2032,7 +2086,7 @@ var userActionHandlers = {
2032
2086
  },
2033
2087
  syncQuestTemplateFlags: async (context) => {
2034
2088
  var _a, _b;
2035
- const { sceneDataRef, graphDataRef, actions: actions2, setters, sceneConfigId, ownerId, stateRef } = context;
2089
+ const { sceneDataRef, graphDataRef, actions, setters, sceneConfigId, ownerId, stateRef } = context;
2036
2090
  if (!((_a = sceneDataRef.current) == null ? void 0 : _a.process_nodes)) return;
2037
2091
  const allTemplateQuestIds = /* @__PURE__ */ new Set();
2038
2092
  sceneDataRef.current.process_nodes.forEach((proc) => {
@@ -2067,8 +2121,8 @@ var userActionHandlers = {
2067
2121
  const pIdx = graphDataRef.current[sceneConfigId].nodes.findIndex((n) => String(n.id) === String(quest.id));
2068
2122
  if (pIdx !== -1) graphDataRef.current[sceneConfigId].nodes[pIdx] = quest;
2069
2123
  }
2070
- if (actions2.upsert_quest_firestore) {
2071
- await actions2.upsert_quest_firestore(ownerId, sceneConfigId, quest);
2124
+ if (actions.upsert_quest_firestore) {
2125
+ await actions.upsert_quest_firestore(ownerId, sceneConfigId, quest);
2072
2126
  }
2073
2127
  const mesh = (_b = stateRef.current.nodeObjects) == null ? void 0 : _b[String(quest.id)];
2074
2128
  if (mesh) {
@@ -2203,19 +2257,19 @@ var userActionHandlers = {
2203
2257
  },
2204
2258
  handleDeleteMultipleNodes: async (context, nodeIds) => {
2205
2259
  var _a;
2206
- const { stateRef, graphDataRef, sceneDataRef, setters, actions: actions2 } = context;
2260
+ const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
2207
2261
  setters.setMultiContextMenu({ visible: false });
2208
2262
  if (!nodeIds || nodeIds.size === 0 || !graphDataRef.current || !sceneDataRef.current)
2209
2263
  return;
2210
2264
  const strNodeIdsToDelete = Array.from(nodeIds).map(String);
2211
- if (actions2.delete_file) {
2265
+ if (actions.delete_file) {
2212
2266
  strNodeIdsToDelete.forEach((id) => {
2213
2267
  const nodeMesh = stateRef.current.nodeObjects[id];
2214
2268
  const nodeData = nodeMesh ? nodeMesh.userData : null;
2215
2269
  if (nodeData) {
2216
2270
  const urls = extractFileUrlsFromProperties(nodeData);
2217
2271
  if (urls.length > 0) {
2218
- Promise.all(urls.map((url) => actions2.delete_file(url))).catch(
2272
+ Promise.all(urls.map((url) => actions.delete_file(url))).catch(
2219
2273
  (err) => console.error(`Erro ao deletar arquivos do node ${id}:`, err)
2220
2274
  );
2221
2275
  }
@@ -2346,9 +2400,9 @@ var userActionHandlers = {
2346
2400
  } else {
2347
2401
  filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2348
2402
  payloadToSave = originalData;
2349
- if (actions2.update_node_counter) {
2403
+ if (actions.update_node_counter) {
2350
2404
  savePromises.push(
2351
- actions2.update_node_counter(ownerId, -nodesToDelete.size)
2405
+ actions.update_node_counter(ownerId, -nodesToDelete.size)
2352
2406
  );
2353
2407
  }
2354
2408
  }
@@ -2393,11 +2447,11 @@ var userActionHandlers = {
2393
2447
  },
2394
2448
  handleDeleteNode: async (context, nodeData) => {
2395
2449
  var _a;
2396
- const { stateRef, graphDataRef, sceneDataRef, setters, actions: actions2 } = context;
2397
- if (actions2.delete_file && nodeData) {
2450
+ const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
2451
+ if (actions.delete_file && nodeData) {
2398
2452
  const urls = extractFileUrlsFromProperties(nodeData);
2399
2453
  if (urls.length > 0) {
2400
- Promise.all(urls.map((url) => actions2.delete_file(url))).then(() => console.log("Arquivos do node deletados.")).catch(
2454
+ Promise.all(urls.map((url) => actions.delete_file(url))).then(() => console.log("Arquivos do node deletados.")).catch(
2401
2455
  (err) => console.error("Erro ao deletar arquivos do node:", err)
2402
2456
  );
2403
2457
  }
@@ -2501,8 +2555,8 @@ var userActionHandlers = {
2501
2555
  setters.setSceneVersion((v) => v + 1);
2502
2556
  if (nodeData.is_process) {
2503
2557
  await userActionHandlers.syncQuestTemplateFlags(context);
2504
- } else if (!nodeData.is_quest && actions2.update_node_counter) {
2505
- await actions2.update_node_counter(ownerId, -1);
2558
+ } else if (!nodeData.is_quest && actions.update_node_counter) {
2559
+ await actions.update_node_counter(ownerId, -1);
2506
2560
  }
2507
2561
  } catch (e) {
2508
2562
  console.error("Falha ao salvar remo\xE7\xE3o do Node:", e);
@@ -2520,8 +2574,8 @@ var userActionHandlers = {
2520
2574
  (prev) => String(prev == null ? void 0 : prev.id) === String(nodeIdToDelete) ? null : prev
2521
2575
  );
2522
2576
  removeNodeFromScene(stateRef.current, nodeIdToDelete);
2523
- if (!isQuestOrProcess && actions2.update_node_counter) {
2524
- await actions2.update_node_counter(ownerId, -1);
2577
+ if (!isQuestOrProcess && actions.update_node_counter) {
2578
+ await actions.update_node_counter(ownerId, -1);
2525
2579
  } else if (isQuestOrProcess && setters.setNodeCounter) {
2526
2580
  setters.setNodeCounter((prev) => prev - 1);
2527
2581
  }
@@ -3171,16 +3225,26 @@ var userActionHandlers = {
3171
3225
  links: specificParentData.links,
3172
3226
  milestones: sceneDataRef.current.milestones || []
3173
3227
  };
3174
- await context.actions.save_view_data(
3175
- context.sceneSaveUrl,
3176
- viewFilePayload
3177
- );
3178
- if (context.actions.upsert_quest_firestore) {
3228
+ const isQuestNode = nodeToSave.is_quest || (Array.isArray(nodeToSave.type) ? nodeToSave.type.includes("quest") : nodeToSave.type === "quest");
3229
+ const isProcessNode = nodeToSave.is_process || (Array.isArray(nodeToSave.type) ? nodeToSave.type.includes("process") : nodeToSave.type === "process");
3230
+ if (!isQuestNode && !isProcessNode) {
3231
+ await context.actions.save_view_data(
3232
+ context.sceneSaveUrl,
3233
+ viewFilePayload
3234
+ );
3235
+ }
3236
+ if (isQuestNode && context.actions.upsert_quest_firestore) {
3179
3237
  await context.actions.upsert_quest_firestore(
3180
3238
  context.ownerId,
3181
3239
  context.sceneConfigId,
3182
3240
  nodeToSave
3183
3241
  );
3242
+ } else if (isProcessNode && context.actions.upsert_process_firestore) {
3243
+ await context.actions.upsert_process_firestore(
3244
+ context.ownerId,
3245
+ context.sceneConfigId,
3246
+ nodeToSave
3247
+ );
3184
3248
  }
3185
3249
  } else {
3186
3250
  const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
@@ -3213,7 +3277,7 @@ var userActionHandlers = {
3213
3277
  },
3214
3278
  handleTriggerProcessBranch: async (context, parentProcess, selectedTemplateChild, triggeringQuestId) => {
3215
3279
  var _a, _b, _c;
3216
- const { graphDataRef, sceneDataRef, stateRef, setters, actions: actions2 } = context;
3280
+ const { graphDataRef, sceneDataRef, stateRef, setters, actions } = context;
3217
3281
  if (!graphDataRef.current || !sceneDataRef.current) return;
3218
3282
  try {
3219
3283
  setters.setIsProcessing(true);
@@ -3275,7 +3339,7 @@ var userActionHandlers = {
3275
3339
  }
3276
3340
  ] : originalChildNode.timeline || []
3277
3341
  };
3278
- if (actions2.copy_google_doc_action && versionedChildNode.Links) {
3342
+ if (actions.copy_google_doc_action && versionedChildNode.Links) {
3279
3343
  const docLinkIndex = versionedChildNode.Links.findIndex((l) => l.name === "Google docs");
3280
3344
  if (docLinkIndex !== -1) {
3281
3345
  const originalUrl = versionedChildNode.Links[docLinkIndex].value;
@@ -3283,7 +3347,7 @@ var userActionHandlers = {
3283
3347
  const docIdMatch = originalUrl.match(/\/d\/([a-zA-Z0-9-_]+)/);
3284
3348
  if (docIdMatch && docIdMatch[1]) {
3285
3349
  try {
3286
- const copyRes = await actions2.copy_google_doc_action(
3350
+ const copyRes = await actions.copy_google_doc_action(
3287
3351
  docIdMatch[1],
3288
3352
  nextName,
3289
3353
  (_c = sceneDataRef.current) == null ? void 0 : _c.view_google_folder_id
@@ -3346,15 +3410,15 @@ var userActionHandlers = {
3346
3410
  }
3347
3411
  }
3348
3412
  if (versionedChildNode.is_quest) {
3349
- savePromises.push(actions2.upsert_quest_firestore(ownerId, parentFileId, versionedChildNode));
3350
- savePromises.push(actions2.upsert_quest_link_firestore(ownerId, parentFileId, childVersionLink));
3413
+ savePromises.push(actions.upsert_quest_firestore(ownerId, parentFileId, versionedChildNode));
3414
+ savePromises.push(actions.upsert_quest_link_firestore(ownerId, parentFileId, childVersionLink));
3351
3415
  } else {
3352
- savePromises.push(actions2.upsert_process_firestore(ownerId, parentFileId, versionedChildNode));
3353
- savePromises.push(actions2.upsert_process_link_firestore(ownerId, parentFileId, childVersionLink));
3416
+ savePromises.push(actions.upsert_process_firestore(ownerId, parentFileId, versionedChildNode));
3417
+ savePromises.push(actions.upsert_process_link_firestore(ownerId, parentFileId, childVersionLink));
3354
3418
  }
3355
3419
  sceneDataRef.current.quest_counter = currentCounter;
3356
- savePromises.push(actions2.update_view_counter(ownerId, parentFileId, currentCounter));
3357
- savePromises.push(actions2.upsert_process_firestore(ownerId, parentFileId, parentProcess));
3420
+ savePromises.push(actions.update_view_counter(ownerId, parentFileId, currentCounter));
3421
+ savePromises.push(actions.upsert_process_firestore(ownerId, parentFileId, parentProcess));
3358
3422
  const specificParentData = graphDataRef.current[parentFileId];
3359
3423
  if (specificParentData) {
3360
3424
  specificParentData.nodes.push(...newNodes);
@@ -3521,7 +3585,7 @@ var userActionHandlers = {
3521
3585
  },
3522
3586
  handleInitiateProcess: async (context, processNode) => {
3523
3587
  var _a, _b, _c, _d, _e;
3524
- const { graphDataRef, sceneDataRef, stateRef, setters, actions: actions2 } = context;
3588
+ const { graphDataRef, sceneDataRef, stateRef, setters, actions } = context;
3525
3589
  if (!graphDataRef.current || !sceneDataRef.current) return;
3526
3590
  try {
3527
3591
  setters.setIsProcessing(true);
@@ -3559,9 +3623,9 @@ var userActionHandlers = {
3559
3623
  target: versionedProcessId
3560
3624
  };
3561
3625
  newLinks.push(processVersionLink);
3562
- if (actions2.upsert_process_link_firestore) {
3626
+ if (actions.upsert_process_link_firestore) {
3563
3627
  savePromises.push(
3564
- actions2.upsert_process_link_firestore(
3628
+ actions.upsert_process_link_firestore(
3565
3629
  ownerId,
3566
3630
  parentFileId,
3567
3631
  processVersionLink
@@ -3621,7 +3685,7 @@ var userActionHandlers = {
3621
3685
  }
3622
3686
  ] : originalChildNode.timeline || []
3623
3687
  };
3624
- if (actions2.copy_google_doc_action && versionedChildNode.Links) {
3688
+ if (actions.copy_google_doc_action && versionedChildNode.Links) {
3625
3689
  const docLinkIndex = versionedChildNode.Links.findIndex(
3626
3690
  (l) => l.name === "Google docs"
3627
3691
  );
@@ -3631,7 +3695,7 @@ var userActionHandlers = {
3631
3695
  const docIdMatch = originalUrl.match(/\/d\/([a-zA-Z0-9-_]+)/);
3632
3696
  if (docIdMatch && docIdMatch[1]) {
3633
3697
  try {
3634
- const copyRes = await actions2.copy_google_doc_action(
3698
+ const copyRes = await actions.copy_google_doc_action(
3635
3699
  docIdMatch[1],
3636
3700
  nextName,
3637
3701
  (_d = sceneDataRef.current) == null ? void 0 : _d.view_google_folder_id
@@ -3680,34 +3744,34 @@ var userActionHandlers = {
3680
3744
  newLinks.push(...subResult.newLinks);
3681
3745
  savePromises.push(...subResult.savePromises);
3682
3746
  }
3683
- if (versionedChildNode.is_quest && actions2.upsert_quest_firestore) {
3747
+ if (versionedChildNode.is_quest && actions.upsert_quest_firestore) {
3684
3748
  savePromises.push(
3685
- actions2.upsert_quest_firestore(
3749
+ actions.upsert_quest_firestore(
3686
3750
  ownerId,
3687
3751
  parentFileId,
3688
3752
  versionedChildNode
3689
3753
  )
3690
3754
  );
3691
- if (actions2.upsert_quest_link_firestore) {
3755
+ if (actions.upsert_quest_link_firestore) {
3692
3756
  savePromises.push(
3693
- actions2.upsert_quest_link_firestore(
3757
+ actions.upsert_quest_link_firestore(
3694
3758
  ownerId,
3695
3759
  parentFileId,
3696
3760
  childVersionLink
3697
3761
  )
3698
3762
  );
3699
3763
  }
3700
- } else if (versionedChildNode.is_process && actions2.upsert_process_firestore) {
3764
+ } else if (versionedChildNode.is_process && actions.upsert_process_firestore) {
3701
3765
  savePromises.push(
3702
- actions2.upsert_process_firestore(
3766
+ actions.upsert_process_firestore(
3703
3767
  ownerId,
3704
3768
  parentFileId,
3705
3769
  versionedChildNode
3706
3770
  )
3707
3771
  );
3708
- if (actions2.upsert_process_link_firestore) {
3772
+ if (actions.upsert_process_link_firestore) {
3709
3773
  savePromises.push(
3710
- actions2.upsert_process_link_firestore(
3774
+ actions.upsert_process_link_firestore(
3711
3775
  ownerId,
3712
3776
  parentFileId,
3713
3777
  childVersionLink
@@ -3724,14 +3788,14 @@ var userActionHandlers = {
3724
3788
  versionedProcess.process_abstraction_tree.node_id = versionedProcessId;
3725
3789
  }
3726
3790
  sceneDataRef.current.quest_counter = currentCounter;
3727
- if (actions2.update_view_counter) {
3791
+ if (actions.update_view_counter) {
3728
3792
  savePromises.push(
3729
- actions2.update_view_counter(ownerId, parentFileId, currentCounter)
3793
+ actions.update_view_counter(ownerId, parentFileId, currentCounter)
3730
3794
  );
3731
3795
  }
3732
- if (actions2.upsert_process_firestore) {
3796
+ if (actions.upsert_process_firestore) {
3733
3797
  savePromises.push(
3734
- actions2.upsert_process_firestore(
3798
+ actions.upsert_process_firestore(
3735
3799
  ownerId,
3736
3800
  parentFileId,
3737
3801
  versionedProcess
@@ -3772,7 +3836,7 @@ var userActionHandlers = {
3772
3836
  );
3773
3837
  } else {
3774
3838
  savePromises.push(
3775
- actions2.save_view_data(
3839
+ actions.save_view_data(
3776
3840
  `x_view_dbs/${ownerId}/${parentFileId}`,
3777
3841
  specificParentData
3778
3842
  )
@@ -3823,7 +3887,7 @@ var userActionHandlers = {
3823
3887
  var SECTION_SPLIT_REGEX = /\*\/\s*(\d+)(?::([a-zA-Z0-9-]+))?\s*\//;
3824
3888
  var MENTION_REGEX = /\[\[MENTION:node:([a-zA-Z0-9\-_]+)\]\]/g;
3825
3889
  var IMAGE_MENTION_REGEX = /\[\[MENTION:image:([^|\]]+)\|?([^\]]*)\]\]/g;
3826
- var LINK_REGEX = /\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g;
3890
+ var LINK_REGEX = /\[([^\]]+)\]\((https?:\/\/[^)]+)\)/g;
3827
3891
  var UNIQUE_PROP_TYPES = ["links", "images", "date", "documents"];
3828
3892
  var QUEST_STATUS_COLORS = {
3829
3893
  Backlog: "#64748b",
@@ -3886,7 +3950,7 @@ var resolveDescriptionReference = (refString, availableNodes = [], availableAnce
3886
3950
  /\[\[REF:(node|ancestry):([a-zA-Z0-9\-_]+):([a-zA-Z0-9\-_]+)\]\]/
3887
3951
  );
3888
3952
  if (!match) return null;
3889
- const [_, type, itemId, sectionId] = match;
3953
+ const [, type, itemId, sectionId] = match;
3890
3954
  let sourceItem = null;
3891
3955
  if (type === "node") {
3892
3956
  sourceItem = availableNodes.find((n) => String(n.id) === String(itemId));
@@ -3918,7 +3982,7 @@ function formatDescriptionForTooltip(rawText, parentData, ancestryData) {
3918
3982
  const allAncestries = ancestryData || [];
3919
3983
  text = text.replace(
3920
3984
  /\[\[REF:(node|ancestry):([a-zA-Z0-9\-_]+):([a-zA-Z0-9\-_]+)\]\]/g,
3921
- (match, type, itemId, sectionId) => {
3985
+ (match) => {
3922
3986
  const resolved = resolveDescriptionReference(
3923
3987
  match,
3924
3988
  allNodes,
@@ -3947,7 +4011,7 @@ function formatDescriptionForTooltip(rawText, parentData, ancestryData) {
3947
4011
  text = text.replace(/^#+\s*/gm, "");
3948
4012
  text = text.replace(/```[\s\S]*?```/g, "[C\xF3digo]");
3949
4013
  text = text.replace(/-\s\[[xX ]\]\s*/g, "\u2022 ");
3950
- text = text.replace(/\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g, "$1");
4014
+ text = text.replace(/\[([^\]]+)\]\((https?:\/\/[^)]+)\)/g, "$1");
3951
4015
  return text.trim();
3952
4016
  }
3953
4017
  function generateTooltipHtml(data, parentData, ancestryData) {
@@ -4583,7 +4647,8 @@ function createTimelineEntry(actorId, description, type = "comment", extras = {}
4583
4647
  id: img.id || uuidv4(),
4584
4648
  name: img.name || "",
4585
4649
  value: img.value || ""
4586
- }))
4650
+ })),
4651
+ metadata
4587
4652
  };
4588
4653
  }
4589
4654
  function calculateNextRecurrenceDate(config) {
@@ -4594,14 +4659,15 @@ function calculateNextRecurrenceDate(config) {
4594
4659
  case "daily":
4595
4660
  nextDate.setDate(now.getDate() + 1);
4596
4661
  break;
4597
- case "weekly":
4662
+ case "weekly": {
4598
4663
  const targetDay = parseInt(config.day_of_week, 10);
4599
4664
  const currentDay = now.getDay();
4600
4665
  let daysUntilNext = targetDay - currentDay;
4601
4666
  if (daysUntilNext <= 0) daysUntilNext += 7;
4602
4667
  nextDate.setDate(now.getDate() + daysUntilNext);
4603
4668
  break;
4604
- case "monthly":
4669
+ }
4670
+ case "monthly": {
4605
4671
  const dayOfMonth = parseInt(config.day_of_month || 1, 10);
4606
4672
  let mYear = now.getFullYear();
4607
4673
  let mMonth = now.getMonth();
@@ -4614,7 +4680,8 @@ function calculateNextRecurrenceDate(config) {
4614
4680
  }
4615
4681
  nextDate = mDate;
4616
4682
  break;
4617
- case "custom":
4683
+ }
4684
+ case "custom": {
4618
4685
  if (config.custom_date) {
4619
4686
  const parts = config.custom_date.split("/");
4620
4687
  if (parts.length === 3) {
@@ -4630,6 +4697,7 @@ function calculateNextRecurrenceDate(config) {
4630
4697
  return null;
4631
4698
  }
4632
4699
  break;
4700
+ }
4633
4701
  default:
4634
4702
  return null;
4635
4703
  }
@@ -5548,6 +5616,7 @@ function XViewSidebar({
5548
5616
  const [showList, setShowList] = useState3(false);
5549
5617
  const [selectedNodeId, setSelectedNodeId] = useState3(null);
5550
5618
  const [isSaving, setIsSaving] = useState3(false);
5619
+ const [isNavigatingBack, setIsNavigatingBack] = useState3(false);
5551
5620
  const [activeFilters, setActiveFilters] = useState3([]);
5552
5621
  const [isFilterMenuOpen, setIsFilterMenuOpen] = useState3(false);
5553
5622
  const [filterCategory, setFilterCategory] = useState3("Type");
@@ -5753,12 +5822,16 @@ function XViewSidebar({
5753
5822
  };
5754
5823
  const handleAddFilter = () => {
5755
5824
  if (!filterValue.trim()) return;
5756
- setActiveFilters((prev) => [
5757
- ...prev,
5758
- { type: filterCategory, value: filterValue.trim() }
5759
- ]);
5825
+ const exists = activeFilters.some(
5826
+ (f) => f.type === filterCategory && f.value.trim().toLowerCase() === filterValue.trim().toLowerCase()
5827
+ );
5828
+ if (!exists) {
5829
+ setActiveFilters((prev) => [
5830
+ ...prev,
5831
+ { type: filterCategory, value: filterValue.trim() }
5832
+ ]);
5833
+ }
5760
5834
  setFilterValue("");
5761
- setIsFilterMenuOpen(false);
5762
5835
  };
5763
5836
  const handleRemoveFilter = (index) => {
5764
5837
  setActiveFilters((prev) => prev.filter((_, i) => i !== index));
@@ -6292,15 +6365,63 @@ function XViewSidebar({
6292
6365
  /* @__PURE__ */ React2.createElement("polygon", { points: "22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3" })
6293
6366
  ),
6294
6367
  "Filters"
6295
- ), isFilterMenuOpen && /* @__PURE__ */ React2.createElement("div", { className: "absolute right-0 top-full mt-2 w-56 p-3 rounded-lg bg-slate-900 border border-white/10 shadow-xl z-50 flex flex-col gap-3 animate-in fade-in zoom-in-95 duration-100" }, /* @__PURE__ */ React2.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ React2.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Filtro"), /* @__PURE__ */ React2.createElement("div", { className: "flex bg-slate-800/50 p-1 rounded-md" }, ["Type", "Color", "Dataset"].map((opt) => /* @__PURE__ */ React2.createElement(
6368
+ ), isFilterMenuOpen && /* @__PURE__ */ React2.createElement("div", { className: "absolute right-0 top-full mt-2 w-64 p-3 rounded-lg bg-slate-900 border border-white/10 shadow-xl z-50 flex flex-col gap-3 animate-in fade-in zoom-in-95 duration-100" }, activeFilters.length > 0 && /* @__PURE__ */ React2.createElement("div", { className: "space-y-1.5 border-b border-white/10 pb-2 mb-0.5" }, /* @__PURE__ */ React2.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React2.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Ativos (", activeFilters.length, ")"), /* @__PURE__ */ React2.createElement(
6369
+ "button",
6370
+ {
6371
+ type: "button",
6372
+ onClick: () => setActiveFilters([]),
6373
+ className: "text-[9px] text-red-400 hover:text-red-300 transition-colors uppercase font-bold tracking-wider"
6374
+ },
6375
+ "Limpar tudo"
6376
+ )), /* @__PURE__ */ React2.createElement("div", { className: "flex flex-wrap gap-1 max-h-24 overflow-y-auto custom-scrollbar pt-1" }, activeFilters.map((filter, idx) => /* @__PURE__ */ React2.createElement(
6377
+ "span",
6378
+ {
6379
+ key: idx,
6380
+ className: "flex items-center gap-1 bg-indigo-500/20 text-indigo-200 border border-indigo-500/30 px-1.5 py-0.5 rounded text-[10px] max-w-full font-medium"
6381
+ },
6382
+ filter.type === "Color" && /* @__PURE__ */ React2.createElement(
6383
+ "span",
6384
+ {
6385
+ className: "inline-block w-2 h-2 rounded-full border border-white/20",
6386
+ style: { backgroundColor: filter.value }
6387
+ }
6388
+ ),
6389
+ /* @__PURE__ */ React2.createElement("span", { className: "truncate max-w-[100px]" }, filter.type, ": ", filter.value),
6390
+ /* @__PURE__ */ React2.createElement(
6391
+ "button",
6392
+ {
6393
+ type: "button",
6394
+ onClick: () => handleRemoveFilter(idx),
6395
+ className: "hover:text-red-400 transition-colors ml-0.5",
6396
+ title: "Remover"
6397
+ },
6398
+ /* @__PURE__ */ React2.createElement(
6399
+ "svg",
6400
+ {
6401
+ xmlns: "http://www.w3.org/2000/svg",
6402
+ width: "10",
6403
+ height: "10",
6404
+ viewBox: "0 0 24 24",
6405
+ fill: "none",
6406
+ stroke: "currentColor",
6407
+ strokeWidth: "3",
6408
+ strokeLinecap: "round",
6409
+ strokeLinejoin: "round"
6410
+ },
6411
+ /* @__PURE__ */ React2.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
6412
+ /* @__PURE__ */ React2.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
6413
+ )
6414
+ )
6415
+ )))), /* @__PURE__ */ React2.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ React2.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Filtro"), /* @__PURE__ */ React2.createElement("div", { className: "flex bg-slate-800/50 p-1 rounded-md" }, ["Type", "Color", "Dataset"].map((opt) => /* @__PURE__ */ React2.createElement(
6296
6416
  "button",
6297
6417
  {
6298
6418
  key: opt,
6419
+ type: "button",
6299
6420
  onClick: () => {
6300
6421
  setFilterCategory(opt);
6301
6422
  setFilterValue("");
6302
6423
  },
6303
- className: `flex-1 text-xs py-1 rounded transition-colors ${filterCategory === opt ? "bg-indigo-600 text-white" : "text-slate-400 hover:text-slate-200"}`
6424
+ className: `flex-1 text-[11px] py-1 rounded transition-colors ${filterCategory === opt ? "bg-indigo-600 text-white font-medium" : "text-slate-400 hover:text-slate-200"}`
6304
6425
  },
6305
6426
  opt
6306
6427
  )))), /* @__PURE__ */ React2.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ React2.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Valor"), /* @__PURE__ */ React2.createElement("div", { className: "relative", ref: typeDropdownRef }, /* @__PURE__ */ React2.createElement(
@@ -6337,11 +6458,12 @@ function XViewSidebar({
6337
6458
  )))), /* @__PURE__ */ React2.createElement(
6338
6459
  "button",
6339
6460
  {
6461
+ type: "button",
6340
6462
  onClick: handleAddFilter,
6341
6463
  disabled: !filterValue.trim(),
6342
- className: "w-full py-1.5 bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white text-xs font-medium rounded transition-colors"
6464
+ className: "w-full py-1.5 bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white text-xs font-semibold rounded transition-colors"
6343
6465
  },
6344
- "Aplicar Filtro"
6466
+ "Adicionar Filtro"
6345
6467
  ))))), /* @__PURE__ */ React2.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ React2.createElement("button", { onClick: onOpenImportModal, className: buttonBaseClass }, /* @__PURE__ */ React2.createElement(FiPlus, { size: 16 }), "Importar Datasets / Views"), importSuccessMessage && /* @__PURE__ */ React2.createElement("p", { className: "text-[10px] text-emerald-400 animate-pulse px-1 font-medium -mt-1" }, importSuccessMessage), /* @__PURE__ */ React2.createElement("section", { className: "space-y-2" }, /* @__PURE__ */ React2.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Lentes"), /* @__PURE__ */ React2.createElement("div", { className: "relative", ref: questLensRef }, /* @__PURE__ */ React2.createElement(
6346
6468
  "button",
6347
6469
  {
@@ -6443,7 +6565,45 @@ function XViewSidebar({
6443
6565
  className: isSaving ? buttonDisabledClass : buttonBaseClass
6444
6566
  },
6445
6567
  isSaving ? "Salvando..." : "Atualizar cen\xE1rio inicial"
6446
- ), /* @__PURE__ */ React2.createElement("button", { onClick: onNavigateBack, className: buttonBaseClass }, "Voltar ao Dashboard"))),
6568
+ ), /* @__PURE__ */ React2.createElement(
6569
+ "button",
6570
+ {
6571
+ onClick: () => {
6572
+ setIsNavigatingBack(true);
6573
+ onNavigateBack();
6574
+ },
6575
+ disabled: isNavigatingBack,
6576
+ className: isNavigatingBack ? buttonDisabledClass : buttonBaseClass
6577
+ },
6578
+ isNavigatingBack ? /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(
6579
+ "svg",
6580
+ {
6581
+ className: "animate-spin h-4 w-4",
6582
+ xmlns: "http://www.w3.org/2000/svg",
6583
+ fill: "none",
6584
+ viewBox: "0 0 24 24"
6585
+ },
6586
+ /* @__PURE__ */ React2.createElement(
6587
+ "circle",
6588
+ {
6589
+ className: "opacity-25",
6590
+ cx: "12",
6591
+ cy: "12",
6592
+ r: "10",
6593
+ stroke: "currentColor",
6594
+ strokeWidth: "4"
6595
+ }
6596
+ ),
6597
+ /* @__PURE__ */ React2.createElement(
6598
+ "path",
6599
+ {
6600
+ className: "opacity-75",
6601
+ fill: "currentColor",
6602
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
6603
+ }
6604
+ )
6605
+ ), "Voltar ao Dashboard") : "Voltar ao Dashboard"
6606
+ ))),
6447
6607
  contextLabel && /* @__PURE__ */ React2.createElement("div", { className: "px-4 py-3 border-t border-white/10 bg-slate-900/50 truncate text-sm font-medium text-slate-200" }, contextLabel),
6448
6608
  /* @__PURE__ */ React2.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" })
6449
6609
  ),
@@ -6512,6 +6672,11 @@ function CustomPropertyDisplay({
6512
6672
  const file = (_a = e.target.files) == null ? void 0 : _a[0];
6513
6673
  const targetIndex = currentUploadTargetRef.current;
6514
6674
  if (!file || targetIndex === null || !onUploadFile) return;
6675
+ const MAX_SIZE = 10 * 1024 * 1024;
6676
+ if (file.size > MAX_SIZE) {
6677
+ alert("O arquivo \xE9 muito grande. O limite m\xE1ximo de tamanho permitido \xE9 de 10MB.");
6678
+ return;
6679
+ }
6515
6680
  try {
6516
6681
  setUploadingItemIndex(targetIndex);
6517
6682
  const formData = new FormData();
@@ -6596,9 +6761,9 @@ function CustomPropertyDisplay({
6596
6761
  };
6597
6762
  const handleRemoveListItem = (j) => setTempProp((p) => ({ ...p, value: p.value.filter((_, k) => k !== j) }));
6598
6763
  const handleListItemChange = (j, f, v) => setTempProp((p) => {
6599
- const newValue2 = [...p.value];
6600
- newValue2[j] = { ...newValue2[j], [f]: v };
6601
- return { ...p, value: newValue2 };
6764
+ const newValue = [...p.value];
6765
+ newValue[j] = { ...newValue[j], [f]: v };
6766
+ return { ...p, value: newValue };
6602
6767
  });
6603
6768
  const baseInput = "w-full bg-slate-800/70 p-2 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-400/60 transition-all duration-150";
6604
6769
  const renderEditView = () => {
@@ -6652,14 +6817,14 @@ function CustomPropertyDisplay({
6652
6817
  const inputClass = `${baseInput} ${noSpinnerClass}`;
6653
6818
  const handleDateTypeChange = (newDateType) => {
6654
6819
  var _a3, _b2, _c2;
6655
- let newValue2 = { type: newDateType };
6820
+ let newValue = { type: newDateType };
6656
6821
  if (newDateType === "Date Interval") {
6657
- newValue2.start = ((_a3 = tempProp.value) == null ? void 0 : _a3.start) || "";
6658
- newValue2.end = ((_b2 = tempProp.value) == null ? void 0 : _b2.end) || "";
6822
+ newValue.start = ((_a3 = tempProp.value) == null ? void 0 : _a3.start) || "";
6823
+ newValue.end = ((_b2 = tempProp.value) == null ? void 0 : _b2.end) || "";
6659
6824
  } else {
6660
- newValue2.value = ((_c2 = tempProp.value) == null ? void 0 : _c2.type) === newDateType ? tempProp.value.value : "";
6825
+ newValue.value = ((_c2 = tempProp.value) == null ? void 0 : _c2.type) === newDateType ? tempProp.value.value : "";
6661
6826
  }
6662
- handlePropChange("value", newValue2);
6827
+ handlePropChange("value", newValue);
6663
6828
  };
6664
6829
  const handleDateValueChange = (dateField, dateValue) => {
6665
6830
  handlePropChange("value", { ...tempProp.value, [dateField]: dateValue });
@@ -9487,7 +9652,7 @@ function CreateAncestryPanel({
9487
9652
  }
9488
9653
  };
9489
9654
  const sideActions = useMemo8(() => {
9490
- const actions2 = { left: null, right: null };
9655
+ const actions = { left: null, right: null };
9491
9656
  const isInBranch = branchStack.length > 0;
9492
9657
  if (internalHighlightedNodeId) {
9493
9658
  const found = findNodePath2(activeTree, internalHighlightedNodeId);
@@ -9495,13 +9660,13 @@ function CreateAncestryPanel({
9495
9660
  const branches = found.node.parallel_branches || [];
9496
9661
  const leftBranch = branches.find((b) => (b.direction || "right") === "left");
9497
9662
  if (leftBranch) {
9498
- actions2.left = {
9663
+ actions.left = {
9499
9664
  type: "open",
9500
9665
  label: "Editar Branch Esq.",
9501
9666
  onClick: () => handleBranchNav(internalHighlightedNodeId, "open", "left")
9502
9667
  };
9503
9668
  } else {
9504
- actions2.left = {
9669
+ actions.left = {
9505
9670
  type: "create",
9506
9671
  label: "Criar Branch Esq.",
9507
9672
  onClick: () => handleBranchNav(internalHighlightedNodeId, "open", "left")
@@ -9509,32 +9674,32 @@ function CreateAncestryPanel({
9509
9674
  }
9510
9675
  const rightBranch = branches.find((b) => (b.direction || "right") === "right");
9511
9676
  if (rightBranch) {
9512
- actions2.right = {
9677
+ actions.right = {
9513
9678
  type: "open",
9514
9679
  label: "Editar Branch Dir.",
9515
9680
  onClick: () => handleBranchNav(internalHighlightedNodeId, "open", "right")
9516
9681
  };
9517
9682
  } else {
9518
- actions2.right = {
9683
+ actions.right = {
9519
9684
  type: "create",
9520
9685
  label: "Criar Branch Dir.",
9521
9686
  onClick: () => handleBranchNav(internalHighlightedNodeId, "open", "right")
9522
9687
  };
9523
9688
  }
9524
9689
  }
9525
- return actions2;
9690
+ return actions;
9526
9691
  }
9527
9692
  if (isInBranch && isAtStartOfBranch) {
9528
9693
  const lastStep = branchStack[branchStack.length - 1];
9529
9694
  const entryDir = lastStep.entryDirection || "right";
9530
9695
  const backSide = entryDir === "right" ? "left" : "right";
9531
- actions2[backSide] = {
9696
+ actions[backSide] = {
9532
9697
  type: "back",
9533
9698
  label: "Voltar",
9534
9699
  onClick: () => handleBranchNav(null, "back")
9535
9700
  };
9536
9701
  }
9537
- return actions2;
9702
+ return actions;
9538
9703
  }, [internalHighlightedNodeId, branchStack, activeTree, isAtStartOfBranch]);
9539
9704
  const applyDescriptionToTree = (baseTree, descText, descSections) => {
9540
9705
  const rootTreeClone = JSON.parse(JSON.stringify(baseTree));
@@ -11592,9 +11757,9 @@ function InSceneCreationForm({
11592
11757
  };
11593
11758
  const handleToggleImageMode = () => {
11594
11759
  var _a2, _b;
11595
- const newValue2 = !useImageAsTexture;
11596
- setUseImageAsTexture(newValue2);
11597
- if (newValue2) {
11760
+ const newValue = !useImageAsTexture;
11761
+ setUseImageAsTexture(newValue);
11762
+ if (newValue) {
11598
11763
  const firstImageProp = customProps.find((p) => p.type === "images");
11599
11764
  if (firstImageProp && ((_b = (_a2 = firstImageProp.value) == null ? void 0 : _a2[0]) == null ? void 0 : _b.value)) {
11600
11765
  const url = firstImageProp.value[0].value;
@@ -12069,9 +12234,9 @@ function InSceneVersionForm({
12069
12234
  };
12070
12235
  const handleToggleImageMode = () => {
12071
12236
  var _a, _b;
12072
- const newValue2 = !useImageAsTexture;
12073
- setUseImageAsTexture(newValue2);
12074
- if (newValue2) {
12237
+ const newValue = !useImageAsTexture;
12238
+ setUseImageAsTexture(newValue);
12239
+ if (newValue) {
12075
12240
  const firstImageProp = customProps.find((p) => p.type === "images");
12076
12241
  if (firstImageProp && ((_b = (_a = firstImageProp.value) == null ? void 0 : _a[0]) == null ? void 0 : _b.value)) {
12077
12242
  const url = firstImageProp.value[0].value;
@@ -13663,6 +13828,7 @@ function NodeDetailsPanel({
13663
13828
  }
13664
13829
  };
13665
13830
  const handleToggleImageMode = () => {
13831
+ const newValue = !useImageAsTexture;
13666
13832
  setUseImageAsTexture(newValue);
13667
13833
  setHasUnsavedChanges(true);
13668
13834
  let activeUrl = null;
@@ -19199,7 +19365,13 @@ function MilestoneManager({
19199
19365
  // src/components/UpgradeModal.jsx
19200
19366
  import React35 from "react";
19201
19367
  import { Sparkles, X, Rocket, Zap, ShieldCheck } from "lucide-react";
19202
- function UpgradeModal({ isOpen, onClose, nodeCounter }) {
19368
+ function UpgradeModal({
19369
+ isOpen,
19370
+ onClose,
19371
+ nodeCounter,
19372
+ nodeLimit = 100,
19373
+ onUpgrade
19374
+ }) {
19203
19375
  if (!isOpen) return null;
19204
19376
  return /* @__PURE__ */ React35.createElement("div", { className: "fixed inset-0 z-[10000] flex items-center justify-center p-4" }, /* @__PURE__ */ React35.createElement("style", null, `
19205
19377
  @keyframes modalShow {
@@ -19225,12 +19397,16 @@ function UpgradeModal({ isOpen, onClose, nodeCounter }) {
19225
19397
  className: "absolute top-6 right-6 p-2 rounded-full hover:bg-white/5 text-white/40 hover:text-white transition-all duration-300"
19226
19398
  },
19227
19399
  /* @__PURE__ */ React35.createElement(X, { size: 20 })
19228
- ), /* @__PURE__ */ React35.createElement("div", { className: "p-12 flex flex-col items-center text-center" }, /* @__PURE__ */ React35.createElement("div", { className: "w-20 h-20 rounded-[2rem] bg-gradient-to-br from-sky-400 to-indigo-600 p-[1px] mb-8 shadow-lg shadow-sky-500/20" }, /* @__PURE__ */ React35.createElement("div", { className: "w-full h-full rounded-[2rem] bg-[#0d1117] flex items-center justify-center" }, /* @__PURE__ */ React35.createElement(Zap, { className: "text-sky-400 fill-sky-400/20", size: 32 }))), /* @__PURE__ */ React35.createElement("h2", { className: "text-3xl font-bold text-white mb-4 tracking-tight" }, "Limite de Nodes", " ", /* @__PURE__ */ React35.createElement("span", { className: "bg-clip-text text-transparent bg-gradient-to-r from-sky-400 to-indigo-400" }, "Atingido")), /* @__PURE__ */ React35.createElement("p", { className: "text-white/60 text-lg leading-relaxed mb-10 max-w-md" }, "Voc\xEA atingiu o limite de", " ", /* @__PURE__ */ React35.createElement("span", { className: "text-white font-semibold" }, "50.000 nodes"), " do seu plano Free. Seu universo est\xE1 crescendo r\xE1pido!"), /* @__PURE__ */ React35.createElement("div", { className: "w-full grid grid-cols-2 gap-4 mb-10" }, /* @__PURE__ */ React35.createElement("div", { className: "bg-white/5 border border-white/10 rounded-3xl p-6 backdrop-blur-md" }, /* @__PURE__ */ React35.createElement("p", { className: "text-white/30 text-[10px] font-bold uppercase tracking-widest mb-1" }, "Status Atual"), /* @__PURE__ */ React35.createElement("p", { className: "text-2xl font-bold text-white" }, nodeCounter, " / 50000")), /* @__PURE__ */ React35.createElement("div", { className: "bg-white/5 border border-white/10 rounded-3xl p-6 backdrop-blur-md" }, /* @__PURE__ */ React35.createElement("p", { className: "text-white/30 text-[10px] font-bold uppercase tracking-widest mb-1" }, "Pr\xF3ximo Plano"), /* @__PURE__ */ React35.createElement("p", { className: "text-2xl font-bold text-sky-400" }, "Ilimitado"))), /* @__PURE__ */ React35.createElement("div", { className: "w-full space-y-4 mb-10 text-left px-4" }, /* @__PURE__ */ React35.createElement("div", { className: "flex items-center gap-3 text-white/70 text-sm" }, /* @__PURE__ */ React35.createElement("div", { className: "w-6 h-6 rounded-full bg-sky-500/10 flex items-center justify-center shrink-0" }, /* @__PURE__ */ React35.createElement(Rocket, { size: 14, className: "text-sky-400" })), /* @__PURE__ */ React35.createElement("span", null, "Nodes, Quests e Processos ilimitados")), /* @__PURE__ */ React35.createElement("div", { className: "flex items-center gap-3 text-white/70 text-sm" }, /* @__PURE__ */ React35.createElement("div", { className: "w-6 h-6 rounded-full bg-sky-500/10 flex items-center justify-center shrink-0" }, /* @__PURE__ */ React35.createElement(ShieldCheck, { size: 14, className: "text-sky-400" })), /* @__PURE__ */ React35.createElement("span", null, "Suporte priorit\xE1rio e recursos exclusivos"))), /* @__PURE__ */ React35.createElement("div", { className: "w-full flex flex-col gap-4" }, /* @__PURE__ */ React35.createElement(
19400
+ ), /* @__PURE__ */ React35.createElement("div", { className: "p-12 flex flex-col items-center text-center" }, /* @__PURE__ */ React35.createElement("div", { className: "w-20 h-20 rounded-[2rem] bg-gradient-to-br from-sky-400 to-indigo-600 p-[1px] mb-8 shadow-lg shadow-sky-500/20" }, /* @__PURE__ */ React35.createElement("div", { className: "w-full h-full rounded-[2rem] bg-[#0d1117] flex items-center justify-center" }, /* @__PURE__ */ React35.createElement(Zap, { className: "text-sky-400 fill-sky-400/20", size: 32 }))), /* @__PURE__ */ React35.createElement("h2", { className: "text-3xl font-bold text-white mb-4 tracking-tight" }, "Limite de Nodes", " ", /* @__PURE__ */ React35.createElement("span", { className: "bg-clip-text text-transparent bg-gradient-to-r from-sky-400 to-indigo-400" }, "Atingido")), /* @__PURE__ */ React35.createElement("p", { className: "text-white/60 text-lg leading-relaxed mb-10 max-w-md" }, "Voc\xEA atingiu o limite de", " ", /* @__PURE__ */ React35.createElement("span", { className: "text-white font-semibold" }, nodeLimit, " nodes"), " ", "do seu plano Free. Seu universo est\xE1 crescendo r\xE1pido!"), /* @__PURE__ */ React35.createElement("div", { className: "w-full grid grid-cols-2 gap-4 mb-10" }, /* @__PURE__ */ React35.createElement("div", { className: "bg-white/5 border border-white/10 rounded-3xl p-6 backdrop-blur-md" }, /* @__PURE__ */ React35.createElement("p", { className: "text-white/30 text-[10px] font-bold uppercase tracking-widest mb-1" }, "Status Atual"), /* @__PURE__ */ React35.createElement("p", { className: "text-2xl font-bold text-white" }, nodeCounter, " / ", nodeLimit)), /* @__PURE__ */ React35.createElement("div", { className: "bg-white/5 border border-white/10 rounded-3xl p-6 backdrop-blur-md" }, /* @__PURE__ */ React35.createElement("p", { className: "text-white/30 text-[10px] font-bold uppercase tracking-widest mb-1" }, "Pr\xF3ximo Plano"), /* @__PURE__ */ React35.createElement("p", { className: "text-2xl font-bold text-sky-400" }, "Ilimitado"))), /* @__PURE__ */ React35.createElement("div", { className: "w-full space-y-4 mb-10 text-left px-4" }, /* @__PURE__ */ React35.createElement("div", { className: "flex items-center gap-3 text-white/70 text-sm" }, /* @__PURE__ */ React35.createElement("div", { className: "w-6 h-6 rounded-full bg-sky-500/10 flex items-center justify-center shrink-0" }, /* @__PURE__ */ React35.createElement(Rocket, { size: 14, className: "text-sky-400" })), /* @__PURE__ */ React35.createElement("span", null, "Cria\xE7\xE3o de Nodes ilimitada")), /* @__PURE__ */ React35.createElement("div", { className: "flex items-center gap-3 text-white/70 text-sm" }, /* @__PURE__ */ React35.createElement("div", { className: "w-6 h-6 rounded-full bg-sky-500/10 flex items-center justify-center shrink-0" }, /* @__PURE__ */ React35.createElement(ShieldCheck, { size: 14, className: "text-sky-400" })), /* @__PURE__ */ React35.createElement("span", null, "Acesso expandido \xE0s funcionalidades colaborativas e de comunidade"))), /* @__PURE__ */ React35.createElement("div", { className: "w-full flex flex-col gap-4" }, /* @__PURE__ */ React35.createElement(
19229
19401
  "button",
19230
19402
  {
19231
19403
  className: "w-full py-5 rounded-[1.5rem] bg-gradient-to-r from-sky-500 to-indigo-600 text-white font-bold text-sm uppercase tracking-widest hover:shadow-[0_0_30px_-5px_rgba(56,189,248,0.5)] hover:scale-[1.02] active:scale-95 transition-all duration-300 flex items-center justify-center gap-2",
19232
- onClick: () => {
19233
- alert("Redirecionando para upgrade... (Em breve)");
19404
+ onClick: async () => {
19405
+ if (onUpgrade) {
19406
+ await onUpgrade();
19407
+ } else {
19408
+ alert("Redirecionando para upgrade... (Em breve)");
19409
+ }
19234
19410
  onClose();
19235
19411
  }
19236
19412
  },
@@ -19338,7 +19514,8 @@ function XViewScene({
19338
19514
  delete_process_firestore,
19339
19515
  upsert_process_link_firestore,
19340
19516
  delete_process_link_firestore,
19341
- update_node_counter
19517
+ update_node_counter,
19518
+ onUpgrade
19342
19519
  }) {
19343
19520
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
19344
19521
  const { data: session, status } = useSession();
@@ -19349,12 +19526,17 @@ function XViewScene({
19349
19526
  const viewParams = useMemo15(() => {
19350
19527
  if (encryptedConfig) {
19351
19528
  const data = decryptData(encryptedConfig);
19352
- if (data) {
19529
+ if (data && data.id && data.owner_id && data.type) {
19353
19530
  return data;
19354
19531
  }
19355
19532
  }
19356
19533
  return null;
19357
19534
  }, [encryptedConfig, session]);
19535
+ useEffect27(() => {
19536
+ if (viewParams == null ? void 0 : viewParams.name) {
19537
+ document.title = `${viewParams.name} - x.plore`;
19538
+ }
19539
+ }, [viewParams == null ? void 0 : viewParams.name]);
19358
19540
  useEffect27(() => {
19359
19541
  async function verifyPermission() {
19360
19542
  if (!viewParams || !session || !check_user_permission) return;
@@ -19518,6 +19700,7 @@ function XViewScene({
19518
19700
  const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState33(false);
19519
19701
  const [nodeCounter, setNodeCounter] = useState33(0);
19520
19702
  const [isUpgradeModalOpen, setIsUpgradeModalOpen] = useState33(false);
19703
+ const [nodeLimit, setNodeLimit] = useState33(100);
19521
19704
  const mountRef = useRef25(null);
19522
19705
  const tooltipRef = useRef25(null);
19523
19706
  const formRef = useRef25(null);
@@ -20279,6 +20462,9 @@ function XViewScene({
20279
20462
  ancestryDataRef.current
20280
20463
  );
20281
20464
  setNodeCounter(sceneResponse.data.node_counter || 0);
20465
+ if (sceneResponse.data.node_limit !== void 0) {
20466
+ setNodeLimit(sceneResponse.data.node_limit);
20467
+ }
20282
20468
  setIsInitialized(true);
20283
20469
  } else {
20284
20470
  console.error(
@@ -20306,6 +20492,7 @@ function XViewScene({
20306
20492
  console.warn(
20307
20493
  "Nenhum par\xE2metro de cena encontrado na URL ou falha na decripta\xE7\xE3o."
20308
20494
  );
20495
+ setPermissionStatus("corrupted");
20309
20496
  setIsLoading(false);
20310
20497
  }
20311
20498
  }, [
@@ -21957,7 +22144,8 @@ function XViewScene({
21957
22144
  handleRenderProcessAbstractionTree,
21958
22145
  nodeCounter,
21959
22146
  checkLimit: (countToAdd = 1) => {
21960
- if (nodeCounter + countToAdd > 5e4) {
22147
+ if (nodeLimit === -1) return false;
22148
+ if (nodeCounter + countToAdd > nodeLimit) {
21961
22149
  setIsUpgradeModalOpen(true);
21962
22150
  return true;
21963
22151
  }
@@ -22518,7 +22706,7 @@ function XViewScene({
22518
22706
  sceneDataRef: sceneDataRef2,
22519
22707
  stateRef: stateRef2,
22520
22708
  setters,
22521
- actions: actions2,
22709
+ actions,
22522
22710
  sceneSaveUrl: sceneSaveUrl2,
22523
22711
  viewType,
22524
22712
  sceneConfigId: sceneConfigId2,
@@ -22536,11 +22724,11 @@ function XViewScene({
22536
22724
  const currentCounter = sceneDataRef2.current.quest_counter || 1;
22537
22725
  const nextCounter = currentCounter + 1;
22538
22726
  try {
22539
- if (actions2.upsert_quest_firestore) {
22540
- await actions2.upsert_quest_firestore(ownerId2, sceneConfigId2, newNode);
22727
+ if (actions.upsert_quest_firestore) {
22728
+ await actions.upsert_quest_firestore(ownerId2, sceneConfigId2, newNode);
22541
22729
  }
22542
- if (actions2.update_view_counter) {
22543
- await actions2.update_view_counter(ownerId2, sceneConfigId2, nextCounter);
22730
+ if (actions.update_view_counter) {
22731
+ await actions.update_view_counter(ownerId2, sceneConfigId2, nextCounter);
22544
22732
  }
22545
22733
  sceneDataRef2.current.quest_counter = nextCounter;
22546
22734
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
@@ -22582,7 +22770,7 @@ function XViewScene({
22582
22770
  sceneDataRef: sceneDataRef2,
22583
22771
  stateRef: stateRef2,
22584
22772
  setters,
22585
- actions: actions2,
22773
+ actions,
22586
22774
  viewType,
22587
22775
  sceneConfigId: sceneConfigId2,
22588
22776
  ownerId: ownerId2,
@@ -22600,8 +22788,8 @@ function XViewScene({
22600
22788
  ]
22601
22789
  };
22602
22790
  try {
22603
- if (actions2.upsert_process_firestore) {
22604
- await actions2.upsert_process_firestore(ownerId2, sceneConfigId2, newNode);
22791
+ if (actions.upsert_process_firestore) {
22792
+ await actions.upsert_process_firestore(ownerId2, sceneConfigId2, newNode);
22605
22793
  }
22606
22794
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
22607
22795
  parentFileId: sceneConfigId2,
@@ -24740,6 +24928,53 @@ function XViewScene({
24740
24928
  transform: "translateX(30px)",
24741
24929
  transition: "all 300ms ease-in-out"
24742
24930
  } : {};
24931
+ if (permissionStatus === "corrupted") {
24932
+ return /* @__PURE__ */ React36.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ React36.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md animate-fade-in" }, /* @__PURE__ */ React36.createElement("div", { className: "mb-4 text-amber-500" }, /* @__PURE__ */ React36.createElement(
24933
+ "svg",
24934
+ {
24935
+ xmlns: "http://www.w3.org/2000/svg",
24936
+ fill: "none",
24937
+ viewBox: "0 0 24 24",
24938
+ strokeWidth: 1.5,
24939
+ stroke: "currentColor",
24940
+ className: "w-16 h-16 mx-auto"
24941
+ },
24942
+ /* @__PURE__ */ React36.createElement(
24943
+ "path",
24944
+ {
24945
+ strokeLinecap: "round",
24946
+ strokeLinejoin: "round",
24947
+ 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"
24948
+ }
24949
+ )
24950
+ )), /* @__PURE__ */ React36.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Link Inv\xE1lido"), /* @__PURE__ */ React36.createElement("p", { className: "text-slate-400 mb-6" }, "O link de acesso a este cen\xE1rio est\xE1 corrompido, incompleto ou foi alterado de forma incorreta. Por favor, verifique a URL ou retorne ao dashboard."), /* @__PURE__ */ React36.createElement(
24951
+ "button",
24952
+ {
24953
+ onClick: handleNavigateBack,
24954
+ 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 cursor-pointer"
24955
+ },
24956
+ /* @__PURE__ */ React36.createElement(
24957
+ "svg",
24958
+ {
24959
+ xmlns: "http://www.w3.org/2000/svg",
24960
+ fill: "none",
24961
+ viewBox: "0 0 24 24",
24962
+ strokeWidth: 2,
24963
+ stroke: "currentColor",
24964
+ className: "w-5 h-5"
24965
+ },
24966
+ /* @__PURE__ */ React36.createElement(
24967
+ "path",
24968
+ {
24969
+ strokeLinecap: "round",
24970
+ strokeLinejoin: "round",
24971
+ d: "M10 19l-7-7m0 0l7-7m-7 7h18"
24972
+ }
24973
+ )
24974
+ ),
24975
+ "Voltar ao Dashboard"
24976
+ )));
24977
+ }
24743
24978
  if (permissionStatus === "denied") {
24744
24979
  return /* @__PURE__ */ React36.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ React36.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ React36.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ React36.createElement(
24745
24980
  "svg",
@@ -25427,7 +25662,20 @@ function XViewScene({
25427
25662
  {
25428
25663
  isOpen: isUpgradeModalOpen,
25429
25664
  onClose: () => setIsUpgradeModalOpen(false),
25430
- nodeCounter
25665
+ nodeCounter,
25666
+ nodeLimit,
25667
+ onUpgrade: async () => {
25668
+ if (onUpgrade) {
25669
+ const res = await onUpgrade();
25670
+ if (res.success) {
25671
+ setNodeLimit(-1);
25672
+ alert("Upgrade realizado com sucesso! Sua conta agora \xE9 Premium.");
25673
+ } else {
25674
+ alert("Erro ao realizar upgrade: " + res.error);
25675
+ }
25676
+ return res;
25677
+ }
25678
+ }
25431
25679
  }
25432
25680
  )
25433
25681
  );
@@ -25543,6 +25791,16 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
25543
25791
  }
25544
25792
  })();
25545
25793
  parentResponsesPromises.push(questFetchPromise, processFetchPromise, nodeCounterPromise);
25794
+ } else {
25795
+ const nodeCounterPromise = (async () => {
25796
+ try {
25797
+ if (!db_services.get_user_node_counter) return { success: true, node_counter: 0 };
25798
+ return await db_services.get_user_node_counter(owner_id);
25799
+ } catch (err) {
25800
+ return { success: false, error: err.message };
25801
+ }
25802
+ })();
25803
+ parentResponsesPromises.push(nodeCounterPromise);
25546
25804
  }
25547
25805
  const parentResponsesResults = await Promise.allSettled(
25548
25806
  parentResponsesPromises
@@ -25551,9 +25809,10 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
25551
25809
  let questDataObj = null;
25552
25810
  let processDataObj = null;
25553
25811
  let userNodeCounter = 0;
25812
+ let userNodeLimit = 100;
25554
25813
  for (let i = 0; i < parentResponsesResults.length; i++) {
25555
25814
  const result = parentResponsesResults[i];
25556
- if (isView && i >= parentDbObjects.length) {
25815
+ if (i >= parentDbObjects.length) {
25557
25816
  if (result.status === "fulfilled" && ((_a = result.value) == null ? void 0 : _a.success)) {
25558
25817
  if (result.value.type === "processes") {
25559
25818
  processDataObj = result.value.data;
@@ -25564,6 +25823,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
25564
25823
  }
25565
25824
  } else if (result.value.node_counter !== void 0) {
25566
25825
  userNodeCounter = result.value.node_counter;
25826
+ if (result.value.node_limit !== void 0) {
25827
+ userNodeLimit = result.value.node_limit;
25828
+ }
25567
25829
  }
25568
25830
  }
25569
25831
  continue;
@@ -25929,7 +26191,8 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
25929
26191
  scene: validatedSceneData,
25930
26192
  parent: parentData,
25931
26193
  ancestry: ancestryData,
25932
- node_counter: userNodeCounter
26194
+ node_counter: userNodeCounter,
26195
+ node_limit: userNodeLimit
25933
26196
  }
25934
26197
  };
25935
26198
  } catch (error) {