@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.js CHANGED
@@ -936,7 +936,7 @@ var getParentFileInfoForNode = (allParentData, sceneData, nodeId, sceneConfigId
936
936
  };
937
937
  async function instantiateSubProcess(context, templateProcess, versionedProcess, startCounter) {
938
938
  var _a, _b, _c;
939
- const { graphDataRef, sceneDataRef, actions: actions2 } = context;
939
+ const { graphDataRef, sceneDataRef, actions } = context;
940
940
  const ownerId = context.ownerId;
941
941
  const parentFileId = context.sceneConfigId;
942
942
  const viewName = context.viewName || "View";
@@ -991,7 +991,7 @@ async function instantiateSubProcess(context, templateProcess, versionedProcess,
991
991
  }
992
992
  ] : originalChildNode.timeline || []
993
993
  };
994
- if (actions2.copy_google_doc_action && versionedChildNode.Links) {
994
+ if (actions.copy_google_doc_action && versionedChildNode.Links) {
995
995
  const docIdx = versionedChildNode.Links.findIndex((l) => l.name === "Google docs");
996
996
  if (docIdx !== -1) {
997
997
  const url = versionedChildNode.Links[docIdx].value;
@@ -999,7 +999,7 @@ async function instantiateSubProcess(context, templateProcess, versionedProcess,
999
999
  const match = url.match(/\/d\/([a-zA-Z0-9-_]+)/);
1000
1000
  if (match == null ? void 0 : match[1]) {
1001
1001
  try {
1002
- const res = await actions2.copy_google_doc_action(
1002
+ const res = await actions.copy_google_doc_action(
1003
1003
  match[1],
1004
1004
  nextName,
1005
1005
  (_c = sceneDataRef.current) == null ? void 0 : _c.view_google_folder_id
@@ -1038,14 +1038,14 @@ async function instantiateSubProcess(context, templateProcess, versionedProcess,
1038
1038
  childRef.node.version_node = versionedChildNode.version_node;
1039
1039
  }
1040
1040
  childRef.node_id = versionedChildId;
1041
- if (versionedChildNode.is_quest && actions2.upsert_quest_firestore) {
1042
- savePromises.push(actions2.upsert_quest_firestore(ownerId, parentFileId, versionedChildNode));
1043
- if (actions2.upsert_quest_link_firestore)
1044
- savePromises.push(actions2.upsert_quest_link_firestore(ownerId, parentFileId, childVersionLink));
1045
- } else if (versionedChildNode.is_process && actions2.upsert_process_firestore) {
1046
- savePromises.push(actions2.upsert_process_firestore(ownerId, parentFileId, versionedChildNode));
1047
- if (actions2.upsert_process_link_firestore)
1048
- savePromises.push(actions2.upsert_process_link_firestore(ownerId, parentFileId, childVersionLink));
1041
+ if (versionedChildNode.is_quest && actions.upsert_quest_firestore) {
1042
+ savePromises.push(actions.upsert_quest_firestore(ownerId, parentFileId, versionedChildNode));
1043
+ if (actions.upsert_quest_link_firestore)
1044
+ savePromises.push(actions.upsert_quest_link_firestore(ownerId, parentFileId, childVersionLink));
1045
+ } else if (versionedChildNode.is_process && actions.upsert_process_firestore) {
1046
+ savePromises.push(actions.upsert_process_firestore(ownerId, parentFileId, versionedChildNode));
1047
+ if (actions.upsert_process_link_firestore)
1048
+ savePromises.push(actions.upsert_process_link_firestore(ownerId, parentFileId, childVersionLink));
1049
1049
  }
1050
1050
  }
1051
1051
  if (versionedProcess.process_abstraction_tree) {
@@ -1177,7 +1177,7 @@ var userActionHandlers = {
1177
1177
  stateRef,
1178
1178
  creationMode,
1179
1179
  setters,
1180
- actions: actions2,
1180
+ actions,
1181
1181
  checkLimit
1182
1182
  } = context;
1183
1183
  if (!graphDataRef.current || !sceneDataRef.current) return;
@@ -1211,20 +1211,20 @@ var userActionHandlers = {
1211
1211
  const savePromises = [];
1212
1212
  if (isCrossDataset) {
1213
1213
  savePromises.push(
1214
- actions2.save_view_data(
1214
+ actions.save_view_data(
1215
1215
  `x_view_dbs/${sourceParentInfo.ownerId}/${sourceParentInfo.parentFileId}`,
1216
1216
  sourceDataToUpdate
1217
1217
  )
1218
1218
  );
1219
1219
  savePromises.push(
1220
- actions2.save_view_data(
1220
+ actions.save_view_data(
1221
1221
  `x_view_dbs/${targetParentInfo.owner_id}/${finalTargetDatasetId}`,
1222
1222
  targetDataToUpdate
1223
1223
  )
1224
1224
  );
1225
1225
  } else {
1226
1226
  savePromises.push(
1227
- actions2.save_view_data(
1227
+ actions.save_view_data(
1228
1228
  `x_view_dbs/${sourceParentInfo.ownerId}/${sourceParentInfo.parentFileId}`,
1229
1229
  sourceDataToUpdate
1230
1230
  )
@@ -1247,8 +1247,8 @@ var userActionHandlers = {
1247
1247
  ownerId: targetParentInfo.owner_id,
1248
1248
  datasetName: targetDataToUpdate.dataset_name || "Dataset Desconhecido"
1249
1249
  });
1250
- if (actions2.update_node_counter) {
1251
- await actions2.update_node_counter(targetParentInfo.owner_id, 1);
1250
+ if (actions.update_node_counter) {
1251
+ await actions.update_node_counter(targetParentInfo.owner_id, 1);
1252
1252
  }
1253
1253
  setters.setSceneVersion((v) => v + 1);
1254
1254
  } catch (error) {
@@ -1382,7 +1382,7 @@ var userActionHandlers = {
1382
1382
  },
1383
1383
  handleSaveVersionNode: async (context, newNodeData) => {
1384
1384
  var _a;
1385
- const { graphDataRef, sceneDataRef, stateRef, versionMode, setters, checkLimit } = context;
1385
+ const { graphDataRef, sceneDataRef, stateRef, versionMode, setters, checkLimit, actions } = context;
1386
1386
  if (!graphDataRef.current || !sceneDataRef.current) return;
1387
1387
  if (checkLimit && checkLimit()) return;
1388
1388
  const { sourceNodeData } = versionMode;
@@ -1493,8 +1493,8 @@ var userActionHandlers = {
1493
1493
  );
1494
1494
  const targetFinalPositions = [];
1495
1495
  const newVersionMeshes = [];
1496
+ const newNodesToCreate = [];
1496
1497
  linksToExpand.forEach((link) => {
1497
- var _a;
1498
1498
  const isSource = String(link.source) === String(sourceNode.id);
1499
1499
  const targetNodeId = isSource ? link.target : link.source;
1500
1500
  if (!nodeObjects[String(targetNodeId)]) {
@@ -1504,44 +1504,93 @@ var userActionHandlers = {
1504
1504
  const nodeData = allParentNodes.find(
1505
1505
  (n) => String(n.id) === String(targetNodeId)
1506
1506
  );
1507
- if (!nodeData) {
1508
- console.warn(
1509
- `Dados do Node com ID ${targetNodeId} n\xE3o encontrados no cache.`
1510
- );
1511
- return;
1507
+ if (nodeData) {
1508
+ newNodesToCreate.push({ link, nodeData, targetNodeId });
1512
1509
  }
1513
- const startPosition = sourceNodeMesh.position.clone();
1514
- const endPosition = startPosition.clone().add(
1515
- new THREE.Vector3(
1516
- (Math.random() - 0.5) * 60,
1517
- (Math.random() - 0.5) * 15,
1518
- (Math.random() - 0.5) * 60
1519
- )
1520
- );
1521
- targetFinalPositions.push(endPosition);
1522
- const targetMesh = createNodeMesh(
1523
- nodeData,
1524
- startPosition,
1525
- glowTexture,
1526
- !!nodeData.is_quest
1527
- );
1528
- targetMesh.scale.set(0.01, 0.01, 0.01);
1529
- graphGroup.add(targetMesh);
1530
- if (targetMesh.userData.labelObject) {
1531
- graphGroup.add(targetMesh.userData.labelObject);
1532
- }
1533
- nodeObjects[String(targetNodeId)] = targetMesh;
1534
- clickableNodes.push(targetMesh);
1535
- const posTween = new import_tween.Tween(targetMesh.position).to(endPosition, 1200).easing(import_tween.Easing.Quadratic.Out);
1536
- tweenGroup.add(posTween);
1537
- posTween.start();
1538
- const targetScale = NODE_SCALE_FACTORS[nodeData.size || "medium"] || 1;
1539
- const scaleTween = new import_tween.Tween(targetMesh.scale).to({ x: targetScale, y: targetScale, z: targetScale }, 1e3).easing(import_tween.Easing.Elastic.Out);
1540
- tweenGroup.add(scaleTween);
1541
- scaleTween.start();
1542
- if (((_a = nodeData.version_node) == null ? void 0 : _a.is_version) && String(nodeData.version_node.parent_node) === String(sourceNode.id)) {
1543
- newVersionMeshes.push(targetMesh);
1510
+ }
1511
+ });
1512
+ const N = newNodesToCreate.length;
1513
+ let referenceDir = new THREE.Vector3(0, 0, 1);
1514
+ if (N > 0) {
1515
+ const incomingVectors = [];
1516
+ allLinks.forEach((l) => {
1517
+ const srcId = String(l.userData.source);
1518
+ const tgtId = String(l.userData.target);
1519
+ if (srcId === String(sourceNode.id) || tgtId === String(sourceNode.id)) {
1520
+ const otherId = srcId === String(sourceNode.id) ? tgtId : srcId;
1521
+ const otherMesh = nodeObjects[otherId];
1522
+ if (otherMesh) {
1523
+ const dir = new THREE.Vector3().subVectors(
1524
+ sourceNodeMesh.position,
1525
+ otherMesh.position
1526
+ );
1527
+ if (dir.lengthSq() > 1e-3) {
1528
+ dir.normalize();
1529
+ incomingVectors.push(dir);
1530
+ }
1531
+ }
1532
+ }
1533
+ });
1534
+ if (incomingVectors.length > 0) {
1535
+ referenceDir.set(0, 0, 0);
1536
+ incomingVectors.forEach((v) => referenceDir.add(v));
1537
+ if (referenceDir.lengthSq() > 1e-3) {
1538
+ referenceDir.normalize();
1539
+ } else {
1540
+ referenceDir.set(0, 0, 1);
1544
1541
  }
1542
+ } else {
1543
+ const toSource = sourceNodeMesh.position.clone();
1544
+ if (toSource.lengthSq() > 1e-3) {
1545
+ referenceDir.copy(toSource).normalize();
1546
+ }
1547
+ }
1548
+ }
1549
+ const up = new THREE.Vector3(0, 1, 0);
1550
+ if (Math.abs(referenceDir.y) > 0.95) {
1551
+ up.set(1, 0, 0);
1552
+ }
1553
+ const right = new THREE.Vector3().crossVectors(up, referenceDir).normalize();
1554
+ const upActual = new THREE.Vector3().crossVectors(referenceDir, right).normalize();
1555
+ const maxSpread = N <= 1 ? 0 : Math.min(Math.PI * 0.4 + (N - 2) * 0.15, Math.PI * 0.8);
1556
+ const baseDistance = 40;
1557
+ newNodesToCreate.forEach((item, i) => {
1558
+ var _a;
1559
+ const { link, nodeData, targetNodeId } = item;
1560
+ let phi = 0;
1561
+ if (N > 1) {
1562
+ phi = -maxSpread / 2 + i / (N - 1) * maxSpread;
1563
+ }
1564
+ const angleY = N > 1 ? Math.sin(i * Math.PI) * 0.12 : 0;
1565
+ const nodeDir = referenceDir.clone().multiplyScalar(Math.cos(phi)).add(right.clone().multiplyScalar(Math.sin(phi))).add(upActual.clone().multiplyScalar(angleY)).normalize();
1566
+ const distFactor = N > 1 ? 1 + (i % 2 === 0 ? 0 : 0.15) : 1;
1567
+ const distance = baseDistance * distFactor;
1568
+ const startPosition = sourceNodeMesh.position.clone();
1569
+ const endPosition = startPosition.clone().add(nodeDir.multiplyScalar(distance));
1570
+ targetFinalPositions.push(endPosition);
1571
+ const targetMesh = createNodeMesh(
1572
+ nodeData,
1573
+ startPosition,
1574
+ glowTexture,
1575
+ !!nodeData.is_quest
1576
+ );
1577
+ targetMesh.scale.set(0.01, 0.01, 0.01);
1578
+ graphGroup.add(targetMesh);
1579
+ if (targetMesh.userData.labelObject) {
1580
+ graphGroup.add(targetMesh.userData.labelObject);
1581
+ }
1582
+ nodeObjects[String(targetNodeId)] = targetMesh;
1583
+ clickableNodes.push(targetMesh);
1584
+ const delay = i * 60;
1585
+ const posTween = new import_tween.Tween(targetMesh.position).to(endPosition, 1200).delay(delay).easing(import_tween.Easing.Quadratic.Out);
1586
+ tweenGroup.add(posTween);
1587
+ posTween.start();
1588
+ const targetScale = NODE_SCALE_FACTORS[nodeData.size || "medium"] || 1;
1589
+ const scaleTween = new import_tween.Tween(targetMesh.scale).to({ x: targetScale, y: targetScale, z: targetScale }, 1e3).delay(delay).easing(import_tween.Easing.Elastic.Out);
1590
+ tweenGroup.add(scaleTween);
1591
+ scaleTween.start();
1592
+ if (((_a = nodeData.version_node) == null ? void 0 : _a.is_version) && String(nodeData.version_node.parent_node) === String(sourceNode.id)) {
1593
+ newVersionMeshes.push(targetMesh);
1545
1594
  }
1546
1595
  });
1547
1596
  linksToExpand.forEach((link) => {
@@ -1574,7 +1623,12 @@ var userActionHandlers = {
1574
1623
  newLine.material.opacity = 0;
1575
1624
  graphGroup.add(newLine);
1576
1625
  allLinks.push(newLine);
1577
- const opacityTween = new import_tween.Tween(newLine.material).to({ opacity: 0.3 }, 800).delay(500);
1626
+ const targetId = String(newLine.userData.target);
1627
+ const newNodeIndex = newNodesToCreate.findIndex(
1628
+ (item) => String(item.targetNodeId) === targetId
1629
+ );
1630
+ const delay = newNodeIndex !== -1 ? newNodeIndex * 60 : 0;
1631
+ const opacityTween = new import_tween.Tween(newLine.material).to({ opacity: 0.3 }, 800).delay(delay);
1578
1632
  tweenGroup.add(opacityTween);
1579
1633
  opacityTween.start();
1580
1634
  });
@@ -2071,7 +2125,7 @@ var userActionHandlers = {
2071
2125
  },
2072
2126
  syncQuestTemplateFlags: async (context) => {
2073
2127
  var _a, _b;
2074
- const { sceneDataRef, graphDataRef, actions: actions2, setters, sceneConfigId, ownerId, stateRef } = context;
2128
+ const { sceneDataRef, graphDataRef, actions, setters, sceneConfigId, ownerId, stateRef } = context;
2075
2129
  if (!((_a = sceneDataRef.current) == null ? void 0 : _a.process_nodes)) return;
2076
2130
  const allTemplateQuestIds = /* @__PURE__ */ new Set();
2077
2131
  sceneDataRef.current.process_nodes.forEach((proc) => {
@@ -2106,8 +2160,8 @@ var userActionHandlers = {
2106
2160
  const pIdx = graphDataRef.current[sceneConfigId].nodes.findIndex((n) => String(n.id) === String(quest.id));
2107
2161
  if (pIdx !== -1) graphDataRef.current[sceneConfigId].nodes[pIdx] = quest;
2108
2162
  }
2109
- if (actions2.upsert_quest_firestore) {
2110
- await actions2.upsert_quest_firestore(ownerId, sceneConfigId, quest);
2163
+ if (actions.upsert_quest_firestore) {
2164
+ await actions.upsert_quest_firestore(ownerId, sceneConfigId, quest);
2111
2165
  }
2112
2166
  const mesh = (_b = stateRef.current.nodeObjects) == null ? void 0 : _b[String(quest.id)];
2113
2167
  if (mesh) {
@@ -2242,19 +2296,19 @@ var userActionHandlers = {
2242
2296
  },
2243
2297
  handleDeleteMultipleNodes: async (context, nodeIds) => {
2244
2298
  var _a;
2245
- const { stateRef, graphDataRef, sceneDataRef, setters, actions: actions2 } = context;
2299
+ const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
2246
2300
  setters.setMultiContextMenu({ visible: false });
2247
2301
  if (!nodeIds || nodeIds.size === 0 || !graphDataRef.current || !sceneDataRef.current)
2248
2302
  return;
2249
2303
  const strNodeIdsToDelete = Array.from(nodeIds).map(String);
2250
- if (actions2.delete_file) {
2304
+ if (actions.delete_file) {
2251
2305
  strNodeIdsToDelete.forEach((id) => {
2252
2306
  const nodeMesh = stateRef.current.nodeObjects[id];
2253
2307
  const nodeData = nodeMesh ? nodeMesh.userData : null;
2254
2308
  if (nodeData) {
2255
2309
  const urls = extractFileUrlsFromProperties(nodeData);
2256
2310
  if (urls.length > 0) {
2257
- Promise.all(urls.map((url) => actions2.delete_file(url))).catch(
2311
+ Promise.all(urls.map((url) => actions.delete_file(url))).catch(
2258
2312
  (err) => console.error(`Erro ao deletar arquivos do node ${id}:`, err)
2259
2313
  );
2260
2314
  }
@@ -2385,9 +2439,9 @@ var userActionHandlers = {
2385
2439
  } else {
2386
2440
  filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2387
2441
  payloadToSave = originalData;
2388
- if (actions2.update_node_counter) {
2442
+ if (actions.update_node_counter) {
2389
2443
  savePromises.push(
2390
- actions2.update_node_counter(ownerId, -nodesToDelete.size)
2444
+ actions.update_node_counter(ownerId, -nodesToDelete.size)
2391
2445
  );
2392
2446
  }
2393
2447
  }
@@ -2432,11 +2486,11 @@ var userActionHandlers = {
2432
2486
  },
2433
2487
  handleDeleteNode: async (context, nodeData) => {
2434
2488
  var _a;
2435
- const { stateRef, graphDataRef, sceneDataRef, setters, actions: actions2 } = context;
2436
- if (actions2.delete_file && nodeData) {
2489
+ const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
2490
+ if (actions.delete_file && nodeData) {
2437
2491
  const urls = extractFileUrlsFromProperties(nodeData);
2438
2492
  if (urls.length > 0) {
2439
- Promise.all(urls.map((url) => actions2.delete_file(url))).then(() => console.log("Arquivos do node deletados.")).catch(
2493
+ Promise.all(urls.map((url) => actions.delete_file(url))).then(() => console.log("Arquivos do node deletados.")).catch(
2440
2494
  (err) => console.error("Erro ao deletar arquivos do node:", err)
2441
2495
  );
2442
2496
  }
@@ -2540,8 +2594,8 @@ var userActionHandlers = {
2540
2594
  setters.setSceneVersion((v) => v + 1);
2541
2595
  if (nodeData.is_process) {
2542
2596
  await userActionHandlers.syncQuestTemplateFlags(context);
2543
- } else if (!nodeData.is_quest && actions2.update_node_counter) {
2544
- await actions2.update_node_counter(ownerId, -1);
2597
+ } else if (!nodeData.is_quest && actions.update_node_counter) {
2598
+ await actions.update_node_counter(ownerId, -1);
2545
2599
  }
2546
2600
  } catch (e) {
2547
2601
  console.error("Falha ao salvar remo\xE7\xE3o do Node:", e);
@@ -2559,8 +2613,8 @@ var userActionHandlers = {
2559
2613
  (prev) => String(prev == null ? void 0 : prev.id) === String(nodeIdToDelete) ? null : prev
2560
2614
  );
2561
2615
  removeNodeFromScene(stateRef.current, nodeIdToDelete);
2562
- if (!isQuestOrProcess && actions2.update_node_counter) {
2563
- await actions2.update_node_counter(ownerId, -1);
2616
+ if (!isQuestOrProcess && actions.update_node_counter) {
2617
+ await actions.update_node_counter(ownerId, -1);
2564
2618
  } else if (isQuestOrProcess && setters.setNodeCounter) {
2565
2619
  setters.setNodeCounter((prev) => prev - 1);
2566
2620
  }
@@ -3210,16 +3264,26 @@ var userActionHandlers = {
3210
3264
  links: specificParentData.links,
3211
3265
  milestones: sceneDataRef.current.milestones || []
3212
3266
  };
3213
- await context.actions.save_view_data(
3214
- context.sceneSaveUrl,
3215
- viewFilePayload
3216
- );
3217
- if (context.actions.upsert_quest_firestore) {
3267
+ const isQuestNode = nodeToSave.is_quest || (Array.isArray(nodeToSave.type) ? nodeToSave.type.includes("quest") : nodeToSave.type === "quest");
3268
+ const isProcessNode = nodeToSave.is_process || (Array.isArray(nodeToSave.type) ? nodeToSave.type.includes("process") : nodeToSave.type === "process");
3269
+ if (!isQuestNode && !isProcessNode) {
3270
+ await context.actions.save_view_data(
3271
+ context.sceneSaveUrl,
3272
+ viewFilePayload
3273
+ );
3274
+ }
3275
+ if (isQuestNode && context.actions.upsert_quest_firestore) {
3218
3276
  await context.actions.upsert_quest_firestore(
3219
3277
  context.ownerId,
3220
3278
  context.sceneConfigId,
3221
3279
  nodeToSave
3222
3280
  );
3281
+ } else if (isProcessNode && context.actions.upsert_process_firestore) {
3282
+ await context.actions.upsert_process_firestore(
3283
+ context.ownerId,
3284
+ context.sceneConfigId,
3285
+ nodeToSave
3286
+ );
3223
3287
  }
3224
3288
  } else {
3225
3289
  const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
@@ -3252,7 +3316,7 @@ var userActionHandlers = {
3252
3316
  },
3253
3317
  handleTriggerProcessBranch: async (context, parentProcess, selectedTemplateChild, triggeringQuestId) => {
3254
3318
  var _a, _b, _c;
3255
- const { graphDataRef, sceneDataRef, stateRef, setters, actions: actions2 } = context;
3319
+ const { graphDataRef, sceneDataRef, stateRef, setters, actions } = context;
3256
3320
  if (!graphDataRef.current || !sceneDataRef.current) return;
3257
3321
  try {
3258
3322
  setters.setIsProcessing(true);
@@ -3314,7 +3378,7 @@ var userActionHandlers = {
3314
3378
  }
3315
3379
  ] : originalChildNode.timeline || []
3316
3380
  };
3317
- if (actions2.copy_google_doc_action && versionedChildNode.Links) {
3381
+ if (actions.copy_google_doc_action && versionedChildNode.Links) {
3318
3382
  const docLinkIndex = versionedChildNode.Links.findIndex((l) => l.name === "Google docs");
3319
3383
  if (docLinkIndex !== -1) {
3320
3384
  const originalUrl = versionedChildNode.Links[docLinkIndex].value;
@@ -3322,7 +3386,7 @@ var userActionHandlers = {
3322
3386
  const docIdMatch = originalUrl.match(/\/d\/([a-zA-Z0-9-_]+)/);
3323
3387
  if (docIdMatch && docIdMatch[1]) {
3324
3388
  try {
3325
- const copyRes = await actions2.copy_google_doc_action(
3389
+ const copyRes = await actions.copy_google_doc_action(
3326
3390
  docIdMatch[1],
3327
3391
  nextName,
3328
3392
  (_c = sceneDataRef.current) == null ? void 0 : _c.view_google_folder_id
@@ -3385,15 +3449,15 @@ var userActionHandlers = {
3385
3449
  }
3386
3450
  }
3387
3451
  if (versionedChildNode.is_quest) {
3388
- savePromises.push(actions2.upsert_quest_firestore(ownerId, parentFileId, versionedChildNode));
3389
- savePromises.push(actions2.upsert_quest_link_firestore(ownerId, parentFileId, childVersionLink));
3452
+ savePromises.push(actions.upsert_quest_firestore(ownerId, parentFileId, versionedChildNode));
3453
+ savePromises.push(actions.upsert_quest_link_firestore(ownerId, parentFileId, childVersionLink));
3390
3454
  } else {
3391
- savePromises.push(actions2.upsert_process_firestore(ownerId, parentFileId, versionedChildNode));
3392
- savePromises.push(actions2.upsert_process_link_firestore(ownerId, parentFileId, childVersionLink));
3455
+ savePromises.push(actions.upsert_process_firestore(ownerId, parentFileId, versionedChildNode));
3456
+ savePromises.push(actions.upsert_process_link_firestore(ownerId, parentFileId, childVersionLink));
3393
3457
  }
3394
3458
  sceneDataRef.current.quest_counter = currentCounter;
3395
- savePromises.push(actions2.update_view_counter(ownerId, parentFileId, currentCounter));
3396
- savePromises.push(actions2.upsert_process_firestore(ownerId, parentFileId, parentProcess));
3459
+ savePromises.push(actions.update_view_counter(ownerId, parentFileId, currentCounter));
3460
+ savePromises.push(actions.upsert_process_firestore(ownerId, parentFileId, parentProcess));
3397
3461
  const specificParentData = graphDataRef.current[parentFileId];
3398
3462
  if (specificParentData) {
3399
3463
  specificParentData.nodes.push(...newNodes);
@@ -3560,7 +3624,7 @@ var userActionHandlers = {
3560
3624
  },
3561
3625
  handleInitiateProcess: async (context, processNode) => {
3562
3626
  var _a, _b, _c, _d, _e;
3563
- const { graphDataRef, sceneDataRef, stateRef, setters, actions: actions2 } = context;
3627
+ const { graphDataRef, sceneDataRef, stateRef, setters, actions } = context;
3564
3628
  if (!graphDataRef.current || !sceneDataRef.current) return;
3565
3629
  try {
3566
3630
  setters.setIsProcessing(true);
@@ -3598,9 +3662,9 @@ var userActionHandlers = {
3598
3662
  target: versionedProcessId
3599
3663
  };
3600
3664
  newLinks.push(processVersionLink);
3601
- if (actions2.upsert_process_link_firestore) {
3665
+ if (actions.upsert_process_link_firestore) {
3602
3666
  savePromises.push(
3603
- actions2.upsert_process_link_firestore(
3667
+ actions.upsert_process_link_firestore(
3604
3668
  ownerId,
3605
3669
  parentFileId,
3606
3670
  processVersionLink
@@ -3660,7 +3724,7 @@ var userActionHandlers = {
3660
3724
  }
3661
3725
  ] : originalChildNode.timeline || []
3662
3726
  };
3663
- if (actions2.copy_google_doc_action && versionedChildNode.Links) {
3727
+ if (actions.copy_google_doc_action && versionedChildNode.Links) {
3664
3728
  const docLinkIndex = versionedChildNode.Links.findIndex(
3665
3729
  (l) => l.name === "Google docs"
3666
3730
  );
@@ -3670,7 +3734,7 @@ var userActionHandlers = {
3670
3734
  const docIdMatch = originalUrl.match(/\/d\/([a-zA-Z0-9-_]+)/);
3671
3735
  if (docIdMatch && docIdMatch[1]) {
3672
3736
  try {
3673
- const copyRes = await actions2.copy_google_doc_action(
3737
+ const copyRes = await actions.copy_google_doc_action(
3674
3738
  docIdMatch[1],
3675
3739
  nextName,
3676
3740
  (_d = sceneDataRef.current) == null ? void 0 : _d.view_google_folder_id
@@ -3719,34 +3783,34 @@ var userActionHandlers = {
3719
3783
  newLinks.push(...subResult.newLinks);
3720
3784
  savePromises.push(...subResult.savePromises);
3721
3785
  }
3722
- if (versionedChildNode.is_quest && actions2.upsert_quest_firestore) {
3786
+ if (versionedChildNode.is_quest && actions.upsert_quest_firestore) {
3723
3787
  savePromises.push(
3724
- actions2.upsert_quest_firestore(
3788
+ actions.upsert_quest_firestore(
3725
3789
  ownerId,
3726
3790
  parentFileId,
3727
3791
  versionedChildNode
3728
3792
  )
3729
3793
  );
3730
- if (actions2.upsert_quest_link_firestore) {
3794
+ if (actions.upsert_quest_link_firestore) {
3731
3795
  savePromises.push(
3732
- actions2.upsert_quest_link_firestore(
3796
+ actions.upsert_quest_link_firestore(
3733
3797
  ownerId,
3734
3798
  parentFileId,
3735
3799
  childVersionLink
3736
3800
  )
3737
3801
  );
3738
3802
  }
3739
- } else if (versionedChildNode.is_process && actions2.upsert_process_firestore) {
3803
+ } else if (versionedChildNode.is_process && actions.upsert_process_firestore) {
3740
3804
  savePromises.push(
3741
- actions2.upsert_process_firestore(
3805
+ actions.upsert_process_firestore(
3742
3806
  ownerId,
3743
3807
  parentFileId,
3744
3808
  versionedChildNode
3745
3809
  )
3746
3810
  );
3747
- if (actions2.upsert_process_link_firestore) {
3811
+ if (actions.upsert_process_link_firestore) {
3748
3812
  savePromises.push(
3749
- actions2.upsert_process_link_firestore(
3813
+ actions.upsert_process_link_firestore(
3750
3814
  ownerId,
3751
3815
  parentFileId,
3752
3816
  childVersionLink
@@ -3763,14 +3827,14 @@ var userActionHandlers = {
3763
3827
  versionedProcess.process_abstraction_tree.node_id = versionedProcessId;
3764
3828
  }
3765
3829
  sceneDataRef.current.quest_counter = currentCounter;
3766
- if (actions2.update_view_counter) {
3830
+ if (actions.update_view_counter) {
3767
3831
  savePromises.push(
3768
- actions2.update_view_counter(ownerId, parentFileId, currentCounter)
3832
+ actions.update_view_counter(ownerId, parentFileId, currentCounter)
3769
3833
  );
3770
3834
  }
3771
- if (actions2.upsert_process_firestore) {
3835
+ if (actions.upsert_process_firestore) {
3772
3836
  savePromises.push(
3773
- actions2.upsert_process_firestore(
3837
+ actions.upsert_process_firestore(
3774
3838
  ownerId,
3775
3839
  parentFileId,
3776
3840
  versionedProcess
@@ -3811,7 +3875,7 @@ var userActionHandlers = {
3811
3875
  );
3812
3876
  } else {
3813
3877
  savePromises.push(
3814
- actions2.save_view_data(
3878
+ actions.save_view_data(
3815
3879
  `x_view_dbs/${ownerId}/${parentFileId}`,
3816
3880
  specificParentData
3817
3881
  )
@@ -3862,7 +3926,7 @@ var userActionHandlers = {
3862
3926
  var SECTION_SPLIT_REGEX = /\*\/\s*(\d+)(?::([a-zA-Z0-9-]+))?\s*\//;
3863
3927
  var MENTION_REGEX = /\[\[MENTION:node:([a-zA-Z0-9\-_]+)\]\]/g;
3864
3928
  var IMAGE_MENTION_REGEX = /\[\[MENTION:image:([^|\]]+)\|?([^\]]*)\]\]/g;
3865
- var LINK_REGEX = /\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g;
3929
+ var LINK_REGEX = /\[([^\]]+)\]\((https?:\/\/[^)]+)\)/g;
3866
3930
  var UNIQUE_PROP_TYPES = ["links", "images", "date", "documents"];
3867
3931
  var QUEST_STATUS_COLORS = {
3868
3932
  Backlog: "#64748b",
@@ -3925,7 +3989,7 @@ var resolveDescriptionReference = (refString, availableNodes = [], availableAnce
3925
3989
  /\[\[REF:(node|ancestry):([a-zA-Z0-9\-_]+):([a-zA-Z0-9\-_]+)\]\]/
3926
3990
  );
3927
3991
  if (!match) return null;
3928
- const [_, type, itemId, sectionId] = match;
3992
+ const [, type, itemId, sectionId] = match;
3929
3993
  let sourceItem = null;
3930
3994
  if (type === "node") {
3931
3995
  sourceItem = availableNodes.find((n) => String(n.id) === String(itemId));
@@ -3957,7 +4021,7 @@ function formatDescriptionForTooltip(rawText, parentData, ancestryData) {
3957
4021
  const allAncestries = ancestryData || [];
3958
4022
  text = text.replace(
3959
4023
  /\[\[REF:(node|ancestry):([a-zA-Z0-9\-_]+):([a-zA-Z0-9\-_]+)\]\]/g,
3960
- (match, type, itemId, sectionId) => {
4024
+ (match) => {
3961
4025
  const resolved = resolveDescriptionReference(
3962
4026
  match,
3963
4027
  allNodes,
@@ -3986,7 +4050,7 @@ function formatDescriptionForTooltip(rawText, parentData, ancestryData) {
3986
4050
  text = text.replace(/^#+\s*/gm, "");
3987
4051
  text = text.replace(/```[\s\S]*?```/g, "[C\xF3digo]");
3988
4052
  text = text.replace(/-\s\[[xX ]\]\s*/g, "\u2022 ");
3989
- text = text.replace(/\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g, "$1");
4053
+ text = text.replace(/\[([^\]]+)\]\((https?:\/\/[^)]+)\)/g, "$1");
3990
4054
  return text.trim();
3991
4055
  }
3992
4056
  function generateTooltipHtml(data, parentData, ancestryData) {
@@ -4622,7 +4686,8 @@ function createTimelineEntry(actorId, description, type = "comment", extras = {}
4622
4686
  id: img.id || (0, import_uuid.v4)(),
4623
4687
  name: img.name || "",
4624
4688
  value: img.value || ""
4625
- }))
4689
+ })),
4690
+ metadata
4626
4691
  };
4627
4692
  }
4628
4693
  function calculateNextRecurrenceDate(config) {
@@ -4633,14 +4698,15 @@ function calculateNextRecurrenceDate(config) {
4633
4698
  case "daily":
4634
4699
  nextDate.setDate(now.getDate() + 1);
4635
4700
  break;
4636
- case "weekly":
4701
+ case "weekly": {
4637
4702
  const targetDay = parseInt(config.day_of_week, 10);
4638
4703
  const currentDay = now.getDay();
4639
4704
  let daysUntilNext = targetDay - currentDay;
4640
4705
  if (daysUntilNext <= 0) daysUntilNext += 7;
4641
4706
  nextDate.setDate(now.getDate() + daysUntilNext);
4642
4707
  break;
4643
- case "monthly":
4708
+ }
4709
+ case "monthly": {
4644
4710
  const dayOfMonth = parseInt(config.day_of_month || 1, 10);
4645
4711
  let mYear = now.getFullYear();
4646
4712
  let mMonth = now.getMonth();
@@ -4653,7 +4719,8 @@ function calculateNextRecurrenceDate(config) {
4653
4719
  }
4654
4720
  nextDate = mDate;
4655
4721
  break;
4656
- case "custom":
4722
+ }
4723
+ case "custom": {
4657
4724
  if (config.custom_date) {
4658
4725
  const parts = config.custom_date.split("/");
4659
4726
  if (parts.length === 3) {
@@ -4669,6 +4736,7 @@ function calculateNextRecurrenceDate(config) {
4669
4736
  return null;
4670
4737
  }
4671
4738
  break;
4739
+ }
4672
4740
  default:
4673
4741
  return null;
4674
4742
  }
@@ -5587,6 +5655,7 @@ function XViewSidebar({
5587
5655
  const [showList, setShowList] = (0, import_react3.useState)(false);
5588
5656
  const [selectedNodeId, setSelectedNodeId] = (0, import_react3.useState)(null);
5589
5657
  const [isSaving, setIsSaving] = (0, import_react3.useState)(false);
5658
+ const [isNavigatingBack, setIsNavigatingBack] = (0, import_react3.useState)(false);
5590
5659
  const [activeFilters, setActiveFilters] = (0, import_react3.useState)([]);
5591
5660
  const [isFilterMenuOpen, setIsFilterMenuOpen] = (0, import_react3.useState)(false);
5592
5661
  const [filterCategory, setFilterCategory] = (0, import_react3.useState)("Type");
@@ -5792,12 +5861,16 @@ function XViewSidebar({
5792
5861
  };
5793
5862
  const handleAddFilter = () => {
5794
5863
  if (!filterValue.trim()) return;
5795
- setActiveFilters((prev) => [
5796
- ...prev,
5797
- { type: filterCategory, value: filterValue.trim() }
5798
- ]);
5864
+ const exists = activeFilters.some(
5865
+ (f) => f.type === filterCategory && f.value.trim().toLowerCase() === filterValue.trim().toLowerCase()
5866
+ );
5867
+ if (!exists) {
5868
+ setActiveFilters((prev) => [
5869
+ ...prev,
5870
+ { type: filterCategory, value: filterValue.trim() }
5871
+ ]);
5872
+ }
5799
5873
  setFilterValue("");
5800
- setIsFilterMenuOpen(false);
5801
5874
  };
5802
5875
  const handleRemoveFilter = (index) => {
5803
5876
  setActiveFilters((prev) => prev.filter((_, i) => i !== index));
@@ -6331,15 +6404,63 @@ function XViewSidebar({
6331
6404
  /* @__PURE__ */ import_react3.default.createElement("polygon", { points: "22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3" })
6332
6405
  ),
6333
6406
  "Filters"
6334
- ), isFilterMenuOpen && /* @__PURE__ */ import_react3.default.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__ */ import_react3.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react3.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Filtro"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex bg-slate-800/50 p-1 rounded-md" }, ["Type", "Color", "Dataset"].map((opt) => /* @__PURE__ */ import_react3.default.createElement(
6407
+ ), isFilterMenuOpen && /* @__PURE__ */ import_react3.default.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__ */ import_react3.default.createElement("div", { className: "space-y-1.5 border-b border-white/10 pb-2 mb-0.5" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react3.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Ativos (", activeFilters.length, ")"), /* @__PURE__ */ import_react3.default.createElement(
6408
+ "button",
6409
+ {
6410
+ type: "button",
6411
+ onClick: () => setActiveFilters([]),
6412
+ className: "text-[9px] text-red-400 hover:text-red-300 transition-colors uppercase font-bold tracking-wider"
6413
+ },
6414
+ "Limpar tudo"
6415
+ )), /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex flex-wrap gap-1 max-h-24 overflow-y-auto custom-scrollbar pt-1" }, activeFilters.map((filter, idx) => /* @__PURE__ */ import_react3.default.createElement(
6416
+ "span",
6417
+ {
6418
+ key: idx,
6419
+ 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"
6420
+ },
6421
+ filter.type === "Color" && /* @__PURE__ */ import_react3.default.createElement(
6422
+ "span",
6423
+ {
6424
+ className: "inline-block w-2 h-2 rounded-full border border-white/20",
6425
+ style: { backgroundColor: filter.value }
6426
+ }
6427
+ ),
6428
+ /* @__PURE__ */ import_react3.default.createElement("span", { className: "truncate max-w-[100px]" }, filter.type, ": ", filter.value),
6429
+ /* @__PURE__ */ import_react3.default.createElement(
6430
+ "button",
6431
+ {
6432
+ type: "button",
6433
+ onClick: () => handleRemoveFilter(idx),
6434
+ className: "hover:text-red-400 transition-colors ml-0.5",
6435
+ title: "Remover"
6436
+ },
6437
+ /* @__PURE__ */ import_react3.default.createElement(
6438
+ "svg",
6439
+ {
6440
+ xmlns: "http://www.w3.org/2000/svg",
6441
+ width: "10",
6442
+ height: "10",
6443
+ viewBox: "0 0 24 24",
6444
+ fill: "none",
6445
+ stroke: "currentColor",
6446
+ strokeWidth: "3",
6447
+ strokeLinecap: "round",
6448
+ strokeLinejoin: "round"
6449
+ },
6450
+ /* @__PURE__ */ import_react3.default.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
6451
+ /* @__PURE__ */ import_react3.default.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
6452
+ )
6453
+ )
6454
+ )))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react3.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Filtro"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex bg-slate-800/50 p-1 rounded-md" }, ["Type", "Color", "Dataset"].map((opt) => /* @__PURE__ */ import_react3.default.createElement(
6335
6455
  "button",
6336
6456
  {
6337
6457
  key: opt,
6458
+ type: "button",
6338
6459
  onClick: () => {
6339
6460
  setFilterCategory(opt);
6340
6461
  setFilterValue("");
6341
6462
  },
6342
- className: `flex-1 text-xs py-1 rounded transition-colors ${filterCategory === opt ? "bg-indigo-600 text-white" : "text-slate-400 hover:text-slate-200"}`
6463
+ 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"}`
6343
6464
  },
6344
6465
  opt
6345
6466
  )))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react3.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Valor"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative", ref: typeDropdownRef }, /* @__PURE__ */ import_react3.default.createElement(
@@ -6376,11 +6497,12 @@ function XViewSidebar({
6376
6497
  )))), /* @__PURE__ */ import_react3.default.createElement(
6377
6498
  "button",
6378
6499
  {
6500
+ type: "button",
6379
6501
  onClick: handleAddFilter,
6380
6502
  disabled: !filterValue.trim(),
6381
- 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"
6503
+ 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"
6382
6504
  },
6383
- "Aplicar Filtro"
6505
+ "Adicionar Filtro"
6384
6506
  ))))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: onOpenImportModal, className: buttonBaseClass }, /* @__PURE__ */ import_react3.default.createElement(import_fi2.FiPlus, { size: 16 }), "Importar Datasets / Views"), importSuccessMessage && /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[10px] text-emerald-400 animate-pulse px-1 font-medium -mt-1" }, importSuccessMessage), /* @__PURE__ */ import_react3.default.createElement("section", { className: "space-y-2" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Lentes"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative", ref: questLensRef }, /* @__PURE__ */ import_react3.default.createElement(
6385
6507
  "button",
6386
6508
  {
@@ -6482,7 +6604,45 @@ function XViewSidebar({
6482
6604
  className: isSaving ? buttonDisabledClass : buttonBaseClass
6483
6605
  },
6484
6606
  isSaving ? "Salvando..." : "Atualizar cen\xE1rio inicial"
6485
- ), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: onNavigateBack, className: buttonBaseClass }, "Voltar ao Dashboard"))),
6607
+ ), /* @__PURE__ */ import_react3.default.createElement(
6608
+ "button",
6609
+ {
6610
+ onClick: () => {
6611
+ setIsNavigatingBack(true);
6612
+ onNavigateBack();
6613
+ },
6614
+ disabled: isNavigatingBack,
6615
+ className: isNavigatingBack ? buttonDisabledClass : buttonBaseClass
6616
+ },
6617
+ isNavigatingBack ? /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement(
6618
+ "svg",
6619
+ {
6620
+ className: "animate-spin h-4 w-4",
6621
+ xmlns: "http://www.w3.org/2000/svg",
6622
+ fill: "none",
6623
+ viewBox: "0 0 24 24"
6624
+ },
6625
+ /* @__PURE__ */ import_react3.default.createElement(
6626
+ "circle",
6627
+ {
6628
+ className: "opacity-25",
6629
+ cx: "12",
6630
+ cy: "12",
6631
+ r: "10",
6632
+ stroke: "currentColor",
6633
+ strokeWidth: "4"
6634
+ }
6635
+ ),
6636
+ /* @__PURE__ */ import_react3.default.createElement(
6637
+ "path",
6638
+ {
6639
+ className: "opacity-75",
6640
+ fill: "currentColor",
6641
+ 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"
6642
+ }
6643
+ )
6644
+ ), "Voltar ao Dashboard") : "Voltar ao Dashboard"
6645
+ ))),
6486
6646
  contextLabel && /* @__PURE__ */ import_react3.default.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),
6487
6647
  /* @__PURE__ */ import_react3.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" })
6488
6648
  ),
@@ -6551,6 +6711,11 @@ function CustomPropertyDisplay({
6551
6711
  const file = (_a = e.target.files) == null ? void 0 : _a[0];
6552
6712
  const targetIndex = currentUploadTargetRef.current;
6553
6713
  if (!file || targetIndex === null || !onUploadFile) return;
6714
+ const MAX_SIZE = 10 * 1024 * 1024;
6715
+ if (file.size > MAX_SIZE) {
6716
+ alert("O arquivo \xE9 muito grande. O limite m\xE1ximo de tamanho permitido \xE9 de 10MB.");
6717
+ return;
6718
+ }
6554
6719
  try {
6555
6720
  setUploadingItemIndex(targetIndex);
6556
6721
  const formData = new FormData();
@@ -6635,9 +6800,9 @@ function CustomPropertyDisplay({
6635
6800
  };
6636
6801
  const handleRemoveListItem = (j) => setTempProp((p) => ({ ...p, value: p.value.filter((_, k) => k !== j) }));
6637
6802
  const handleListItemChange = (j, f, v) => setTempProp((p) => {
6638
- const newValue2 = [...p.value];
6639
- newValue2[j] = { ...newValue2[j], [f]: v };
6640
- return { ...p, value: newValue2 };
6803
+ const newValue = [...p.value];
6804
+ newValue[j] = { ...newValue[j], [f]: v };
6805
+ return { ...p, value: newValue };
6641
6806
  });
6642
6807
  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";
6643
6808
  const renderEditView = () => {
@@ -6691,14 +6856,14 @@ function CustomPropertyDisplay({
6691
6856
  const inputClass = `${baseInput} ${noSpinnerClass}`;
6692
6857
  const handleDateTypeChange = (newDateType) => {
6693
6858
  var _a3, _b2, _c2;
6694
- let newValue2 = { type: newDateType };
6859
+ let newValue = { type: newDateType };
6695
6860
  if (newDateType === "Date Interval") {
6696
- newValue2.start = ((_a3 = tempProp.value) == null ? void 0 : _a3.start) || "";
6697
- newValue2.end = ((_b2 = tempProp.value) == null ? void 0 : _b2.end) || "";
6861
+ newValue.start = ((_a3 = tempProp.value) == null ? void 0 : _a3.start) || "";
6862
+ newValue.end = ((_b2 = tempProp.value) == null ? void 0 : _b2.end) || "";
6698
6863
  } else {
6699
- newValue2.value = ((_c2 = tempProp.value) == null ? void 0 : _c2.type) === newDateType ? tempProp.value.value : "";
6864
+ newValue.value = ((_c2 = tempProp.value) == null ? void 0 : _c2.type) === newDateType ? tempProp.value.value : "";
6700
6865
  }
6701
- handlePropChange("value", newValue2);
6866
+ handlePropChange("value", newValue);
6702
6867
  };
6703
6868
  const handleDateValueChange = (dateField, dateValue) => {
6704
6869
  handlePropChange("value", { ...tempProp.value, [dateField]: dateValue });
@@ -9495,7 +9660,7 @@ function CreateAncestryPanel({
9495
9660
  }
9496
9661
  };
9497
9662
  const sideActions = (0, import_react11.useMemo)(() => {
9498
- const actions2 = { left: null, right: null };
9663
+ const actions = { left: null, right: null };
9499
9664
  const isInBranch = branchStack.length > 0;
9500
9665
  if (internalHighlightedNodeId) {
9501
9666
  const found = findNodePath2(activeTree, internalHighlightedNodeId);
@@ -9503,13 +9668,13 @@ function CreateAncestryPanel({
9503
9668
  const branches = found.node.parallel_branches || [];
9504
9669
  const leftBranch = branches.find((b) => (b.direction || "right") === "left");
9505
9670
  if (leftBranch) {
9506
- actions2.left = {
9671
+ actions.left = {
9507
9672
  type: "open",
9508
9673
  label: "Editar Branch Esq.",
9509
9674
  onClick: () => handleBranchNav(internalHighlightedNodeId, "open", "left")
9510
9675
  };
9511
9676
  } else {
9512
- actions2.left = {
9677
+ actions.left = {
9513
9678
  type: "create",
9514
9679
  label: "Criar Branch Esq.",
9515
9680
  onClick: () => handleBranchNav(internalHighlightedNodeId, "open", "left")
@@ -9517,32 +9682,32 @@ function CreateAncestryPanel({
9517
9682
  }
9518
9683
  const rightBranch = branches.find((b) => (b.direction || "right") === "right");
9519
9684
  if (rightBranch) {
9520
- actions2.right = {
9685
+ actions.right = {
9521
9686
  type: "open",
9522
9687
  label: "Editar Branch Dir.",
9523
9688
  onClick: () => handleBranchNav(internalHighlightedNodeId, "open", "right")
9524
9689
  };
9525
9690
  } else {
9526
- actions2.right = {
9691
+ actions.right = {
9527
9692
  type: "create",
9528
9693
  label: "Criar Branch Dir.",
9529
9694
  onClick: () => handleBranchNav(internalHighlightedNodeId, "open", "right")
9530
9695
  };
9531
9696
  }
9532
9697
  }
9533
- return actions2;
9698
+ return actions;
9534
9699
  }
9535
9700
  if (isInBranch && isAtStartOfBranch) {
9536
9701
  const lastStep = branchStack[branchStack.length - 1];
9537
9702
  const entryDir = lastStep.entryDirection || "right";
9538
9703
  const backSide = entryDir === "right" ? "left" : "right";
9539
- actions2[backSide] = {
9704
+ actions[backSide] = {
9540
9705
  type: "back",
9541
9706
  label: "Voltar",
9542
9707
  onClick: () => handleBranchNav(null, "back")
9543
9708
  };
9544
9709
  }
9545
- return actions2;
9710
+ return actions;
9546
9711
  }, [internalHighlightedNodeId, branchStack, activeTree, isAtStartOfBranch]);
9547
9712
  const applyDescriptionToTree = (baseTree, descText, descSections) => {
9548
9713
  const rootTreeClone = JSON.parse(JSON.stringify(baseTree));
@@ -11580,9 +11745,9 @@ function InSceneCreationForm({
11580
11745
  };
11581
11746
  const handleToggleImageMode = () => {
11582
11747
  var _a2, _b;
11583
- const newValue2 = !useImageAsTexture;
11584
- setUseImageAsTexture(newValue2);
11585
- if (newValue2) {
11748
+ const newValue = !useImageAsTexture;
11749
+ setUseImageAsTexture(newValue);
11750
+ if (newValue) {
11586
11751
  const firstImageProp = customProps.find((p) => p.type === "images");
11587
11752
  if (firstImageProp && ((_b = (_a2 = firstImageProp.value) == null ? void 0 : _a2[0]) == null ? void 0 : _b.value)) {
11588
11753
  const url = firstImageProp.value[0].value;
@@ -12057,9 +12222,9 @@ function InSceneVersionForm({
12057
12222
  };
12058
12223
  const handleToggleImageMode = () => {
12059
12224
  var _a, _b;
12060
- const newValue2 = !useImageAsTexture;
12061
- setUseImageAsTexture(newValue2);
12062
- if (newValue2) {
12225
+ const newValue = !useImageAsTexture;
12226
+ setUseImageAsTexture(newValue);
12227
+ if (newValue) {
12063
12228
  const firstImageProp = customProps.find((p) => p.type === "images");
12064
12229
  if (firstImageProp && ((_b = (_a = firstImageProp.value) == null ? void 0 : _a[0]) == null ? void 0 : _b.value)) {
12065
12230
  const url = firstImageProp.value[0].value;
@@ -13631,6 +13796,7 @@ function NodeDetailsPanel({
13631
13796
  }
13632
13797
  };
13633
13798
  const handleToggleImageMode = () => {
13799
+ const newValue = !useImageAsTexture;
13634
13800
  setUseImageAsTexture(newValue);
13635
13801
  setHasUnsavedChanges(true);
13636
13802
  let activeUrl = null;
@@ -19107,7 +19273,13 @@ function MilestoneManager({
19107
19273
  // src/components/UpgradeModal.jsx
19108
19274
  var import_react36 = __toESM(require("react"));
19109
19275
  var import_lucide_react = require("lucide-react");
19110
- function UpgradeModal({ isOpen, onClose, nodeCounter }) {
19276
+ function UpgradeModal({
19277
+ isOpen,
19278
+ onClose,
19279
+ nodeCounter,
19280
+ nodeLimit = 100,
19281
+ onUpgrade
19282
+ }) {
19111
19283
  if (!isOpen) return null;
19112
19284
  return /* @__PURE__ */ import_react36.default.createElement("div", { className: "fixed inset-0 z-[10000] flex items-center justify-center p-4" }, /* @__PURE__ */ import_react36.default.createElement("style", null, `
19113
19285
  @keyframes modalShow {
@@ -19133,12 +19305,16 @@ function UpgradeModal({ isOpen, onClose, nodeCounter }) {
19133
19305
  className: "absolute top-6 right-6 p-2 rounded-full hover:bg-white/5 text-white/40 hover:text-white transition-all duration-300"
19134
19306
  },
19135
19307
  /* @__PURE__ */ import_react36.default.createElement(import_lucide_react.X, { size: 20 })
19136
- ), /* @__PURE__ */ import_react36.default.createElement("div", { className: "p-12 flex flex-col items-center text-center" }, /* @__PURE__ */ import_react36.default.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__ */ import_react36.default.createElement("div", { className: "w-full h-full rounded-[2rem] bg-[#0d1117] flex items-center justify-center" }, /* @__PURE__ */ import_react36.default.createElement(import_lucide_react.Zap, { className: "text-sky-400 fill-sky-400/20", size: 32 }))), /* @__PURE__ */ import_react36.default.createElement("h2", { className: "text-3xl font-bold text-white mb-4 tracking-tight" }, "Limite de Nodes", " ", /* @__PURE__ */ import_react36.default.createElement("span", { className: "bg-clip-text text-transparent bg-gradient-to-r from-sky-400 to-indigo-400" }, "Atingido")), /* @__PURE__ */ import_react36.default.createElement("p", { className: "text-white/60 text-lg leading-relaxed mb-10 max-w-md" }, "Voc\xEA atingiu o limite de", " ", /* @__PURE__ */ import_react36.default.createElement("span", { className: "text-white font-semibold" }, "50.000 nodes"), " do seu plano Free. Seu universo est\xE1 crescendo r\xE1pido!"), /* @__PURE__ */ import_react36.default.createElement("div", { className: "w-full grid grid-cols-2 gap-4 mb-10" }, /* @__PURE__ */ import_react36.default.createElement("div", { className: "bg-white/5 border border-white/10 rounded-3xl p-6 backdrop-blur-md" }, /* @__PURE__ */ import_react36.default.createElement("p", { className: "text-white/30 text-[10px] font-bold uppercase tracking-widest mb-1" }, "Status Atual"), /* @__PURE__ */ import_react36.default.createElement("p", { className: "text-2xl font-bold text-white" }, nodeCounter, " / 50000")), /* @__PURE__ */ import_react36.default.createElement("div", { className: "bg-white/5 border border-white/10 rounded-3xl p-6 backdrop-blur-md" }, /* @__PURE__ */ import_react36.default.createElement("p", { className: "text-white/30 text-[10px] font-bold uppercase tracking-widest mb-1" }, "Pr\xF3ximo Plano"), /* @__PURE__ */ import_react36.default.createElement("p", { className: "text-2xl font-bold text-sky-400" }, "Ilimitado"))), /* @__PURE__ */ import_react36.default.createElement("div", { className: "w-full space-y-4 mb-10 text-left px-4" }, /* @__PURE__ */ import_react36.default.createElement("div", { className: "flex items-center gap-3 text-white/70 text-sm" }, /* @__PURE__ */ import_react36.default.createElement("div", { className: "w-6 h-6 rounded-full bg-sky-500/10 flex items-center justify-center shrink-0" }, /* @__PURE__ */ import_react36.default.createElement(import_lucide_react.Rocket, { size: 14, className: "text-sky-400" })), /* @__PURE__ */ import_react36.default.createElement("span", null, "Nodes, Quests e Processos ilimitados")), /* @__PURE__ */ import_react36.default.createElement("div", { className: "flex items-center gap-3 text-white/70 text-sm" }, /* @__PURE__ */ import_react36.default.createElement("div", { className: "w-6 h-6 rounded-full bg-sky-500/10 flex items-center justify-center shrink-0" }, /* @__PURE__ */ import_react36.default.createElement(import_lucide_react.ShieldCheck, { size: 14, className: "text-sky-400" })), /* @__PURE__ */ import_react36.default.createElement("span", null, "Suporte priorit\xE1rio e recursos exclusivos"))), /* @__PURE__ */ import_react36.default.createElement("div", { className: "w-full flex flex-col gap-4" }, /* @__PURE__ */ import_react36.default.createElement(
19308
+ ), /* @__PURE__ */ import_react36.default.createElement("div", { className: "p-12 flex flex-col items-center text-center" }, /* @__PURE__ */ import_react36.default.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__ */ import_react36.default.createElement("div", { className: "w-full h-full rounded-[2rem] bg-[#0d1117] flex items-center justify-center" }, /* @__PURE__ */ import_react36.default.createElement(import_lucide_react.Zap, { className: "text-sky-400 fill-sky-400/20", size: 32 }))), /* @__PURE__ */ import_react36.default.createElement("h2", { className: "text-3xl font-bold text-white mb-4 tracking-tight" }, "Limite de Nodes", " ", /* @__PURE__ */ import_react36.default.createElement("span", { className: "bg-clip-text text-transparent bg-gradient-to-r from-sky-400 to-indigo-400" }, "Atingido")), /* @__PURE__ */ import_react36.default.createElement("p", { className: "text-white/60 text-lg leading-relaxed mb-10 max-w-md" }, "Voc\xEA atingiu o limite de", " ", /* @__PURE__ */ import_react36.default.createElement("span", { className: "text-white font-semibold" }, nodeLimit, " nodes"), " ", "do seu plano Free. Seu universo est\xE1 crescendo r\xE1pido!"), /* @__PURE__ */ import_react36.default.createElement("div", { className: "w-full grid grid-cols-2 gap-4 mb-10" }, /* @__PURE__ */ import_react36.default.createElement("div", { className: "bg-white/5 border border-white/10 rounded-3xl p-6 backdrop-blur-md" }, /* @__PURE__ */ import_react36.default.createElement("p", { className: "text-white/30 text-[10px] font-bold uppercase tracking-widest mb-1" }, "Status Atual"), /* @__PURE__ */ import_react36.default.createElement("p", { className: "text-2xl font-bold text-white" }, nodeCounter, " / ", nodeLimit)), /* @__PURE__ */ import_react36.default.createElement("div", { className: "bg-white/5 border border-white/10 rounded-3xl p-6 backdrop-blur-md" }, /* @__PURE__ */ import_react36.default.createElement("p", { className: "text-white/30 text-[10px] font-bold uppercase tracking-widest mb-1" }, "Pr\xF3ximo Plano"), /* @__PURE__ */ import_react36.default.createElement("p", { className: "text-2xl font-bold text-sky-400" }, "Ilimitado"))), /* @__PURE__ */ import_react36.default.createElement("div", { className: "w-full space-y-4 mb-10 text-left px-4" }, /* @__PURE__ */ import_react36.default.createElement("div", { className: "flex items-center gap-3 text-white/70 text-sm" }, /* @__PURE__ */ import_react36.default.createElement("div", { className: "w-6 h-6 rounded-full bg-sky-500/10 flex items-center justify-center shrink-0" }, /* @__PURE__ */ import_react36.default.createElement(import_lucide_react.Rocket, { size: 14, className: "text-sky-400" })), /* @__PURE__ */ import_react36.default.createElement("span", null, "Cria\xE7\xE3o de Nodes ilimitada")), /* @__PURE__ */ import_react36.default.createElement("div", { className: "flex items-center gap-3 text-white/70 text-sm" }, /* @__PURE__ */ import_react36.default.createElement("div", { className: "w-6 h-6 rounded-full bg-sky-500/10 flex items-center justify-center shrink-0" }, /* @__PURE__ */ import_react36.default.createElement(import_lucide_react.ShieldCheck, { size: 14, className: "text-sky-400" })), /* @__PURE__ */ import_react36.default.createElement("span", null, "Acesso expandido \xE0s funcionalidades colaborativas e de comunidade"))), /* @__PURE__ */ import_react36.default.createElement("div", { className: "w-full flex flex-col gap-4" }, /* @__PURE__ */ import_react36.default.createElement(
19137
19309
  "button",
19138
19310
  {
19139
19311
  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",
19140
- onClick: () => {
19141
- alert("Redirecionando para upgrade... (Em breve)");
19312
+ onClick: async () => {
19313
+ if (onUpgrade) {
19314
+ await onUpgrade();
19315
+ } else {
19316
+ alert("Redirecionando para upgrade... (Em breve)");
19317
+ }
19142
19318
  onClose();
19143
19319
  }
19144
19320
  },
@@ -19246,7 +19422,8 @@ function XViewScene({
19246
19422
  delete_process_firestore,
19247
19423
  upsert_process_link_firestore,
19248
19424
  delete_process_link_firestore,
19249
- update_node_counter
19425
+ update_node_counter,
19426
+ onUpgrade
19250
19427
  }) {
19251
19428
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
19252
19429
  const { data: session, status } = (0, import_react38.useSession)();
@@ -19257,12 +19434,17 @@ function XViewScene({
19257
19434
  const viewParams = (0, import_react37.useMemo)(() => {
19258
19435
  if (encryptedConfig) {
19259
19436
  const data = decryptData(encryptedConfig);
19260
- if (data) {
19437
+ if (data && data.id && data.owner_id && data.type) {
19261
19438
  return data;
19262
19439
  }
19263
19440
  }
19264
19441
  return null;
19265
19442
  }, [encryptedConfig, session]);
19443
+ (0, import_react37.useEffect)(() => {
19444
+ if (viewParams == null ? void 0 : viewParams.name) {
19445
+ document.title = `${viewParams.name} - x.plore`;
19446
+ }
19447
+ }, [viewParams == null ? void 0 : viewParams.name]);
19266
19448
  (0, import_react37.useEffect)(() => {
19267
19449
  async function verifyPermission() {
19268
19450
  if (!viewParams || !session || !check_user_permission) return;
@@ -19426,6 +19608,7 @@ function XViewScene({
19426
19608
  const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = (0, import_react37.useState)(false);
19427
19609
  const [nodeCounter, setNodeCounter] = (0, import_react37.useState)(0);
19428
19610
  const [isUpgradeModalOpen, setIsUpgradeModalOpen] = (0, import_react37.useState)(false);
19611
+ const [nodeLimit, setNodeLimit] = (0, import_react37.useState)(100);
19429
19612
  const mountRef = (0, import_react37.useRef)(null);
19430
19613
  const tooltipRef = (0, import_react37.useRef)(null);
19431
19614
  const formRef = (0, import_react37.useRef)(null);
@@ -20187,6 +20370,9 @@ function XViewScene({
20187
20370
  ancestryDataRef.current
20188
20371
  );
20189
20372
  setNodeCounter(sceneResponse.data.node_counter || 0);
20373
+ if (sceneResponse.data.node_limit !== void 0) {
20374
+ setNodeLimit(sceneResponse.data.node_limit);
20375
+ }
20190
20376
  setIsInitialized(true);
20191
20377
  } else {
20192
20378
  console.error(
@@ -20214,6 +20400,7 @@ function XViewScene({
20214
20400
  console.warn(
20215
20401
  "Nenhum par\xE2metro de cena encontrado na URL ou falha na decripta\xE7\xE3o."
20216
20402
  );
20403
+ setPermissionStatus("corrupted");
20217
20404
  setIsLoading(false);
20218
20405
  }
20219
20406
  }, [
@@ -21865,7 +22052,8 @@ function XViewScene({
21865
22052
  handleRenderProcessAbstractionTree,
21866
22053
  nodeCounter,
21867
22054
  checkLimit: (countToAdd = 1) => {
21868
- if (nodeCounter + countToAdd > 5e4) {
22055
+ if (nodeLimit === -1) return false;
22056
+ if (nodeCounter + countToAdd > nodeLimit) {
21869
22057
  setIsUpgradeModalOpen(true);
21870
22058
  return true;
21871
22059
  }
@@ -22426,7 +22614,7 @@ function XViewScene({
22426
22614
  sceneDataRef: sceneDataRef2,
22427
22615
  stateRef: stateRef2,
22428
22616
  setters,
22429
- actions: actions2,
22617
+ actions,
22430
22618
  sceneSaveUrl: sceneSaveUrl2,
22431
22619
  viewType,
22432
22620
  sceneConfigId: sceneConfigId2,
@@ -22444,11 +22632,11 @@ function XViewScene({
22444
22632
  const currentCounter = sceneDataRef2.current.quest_counter || 1;
22445
22633
  const nextCounter = currentCounter + 1;
22446
22634
  try {
22447
- if (actions2.upsert_quest_firestore) {
22448
- await actions2.upsert_quest_firestore(ownerId2, sceneConfigId2, newNode);
22635
+ if (actions.upsert_quest_firestore) {
22636
+ await actions.upsert_quest_firestore(ownerId2, sceneConfigId2, newNode);
22449
22637
  }
22450
- if (actions2.update_view_counter) {
22451
- await actions2.update_view_counter(ownerId2, sceneConfigId2, nextCounter);
22638
+ if (actions.update_view_counter) {
22639
+ await actions.update_view_counter(ownerId2, sceneConfigId2, nextCounter);
22452
22640
  }
22453
22641
  sceneDataRef2.current.quest_counter = nextCounter;
22454
22642
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
@@ -22490,7 +22678,7 @@ function XViewScene({
22490
22678
  sceneDataRef: sceneDataRef2,
22491
22679
  stateRef: stateRef2,
22492
22680
  setters,
22493
- actions: actions2,
22681
+ actions,
22494
22682
  viewType,
22495
22683
  sceneConfigId: sceneConfigId2,
22496
22684
  ownerId: ownerId2,
@@ -22508,8 +22696,8 @@ function XViewScene({
22508
22696
  ]
22509
22697
  };
22510
22698
  try {
22511
- if (actions2.upsert_process_firestore) {
22512
- await actions2.upsert_process_firestore(ownerId2, sceneConfigId2, newNode);
22699
+ if (actions.upsert_process_firestore) {
22700
+ await actions.upsert_process_firestore(ownerId2, sceneConfigId2, newNode);
22513
22701
  }
22514
22702
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
22515
22703
  parentFileId: sceneConfigId2,
@@ -24648,6 +24836,53 @@ function XViewScene({
24648
24836
  transform: "translateX(30px)",
24649
24837
  transition: "all 300ms ease-in-out"
24650
24838
  } : {};
24839
+ if (permissionStatus === "corrupted") {
24840
+ return /* @__PURE__ */ import_react37.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react37.default.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__ */ import_react37.default.createElement("div", { className: "mb-4 text-amber-500" }, /* @__PURE__ */ import_react37.default.createElement(
24841
+ "svg",
24842
+ {
24843
+ xmlns: "http://www.w3.org/2000/svg",
24844
+ fill: "none",
24845
+ viewBox: "0 0 24 24",
24846
+ strokeWidth: 1.5,
24847
+ stroke: "currentColor",
24848
+ className: "w-16 h-16 mx-auto"
24849
+ },
24850
+ /* @__PURE__ */ import_react37.default.createElement(
24851
+ "path",
24852
+ {
24853
+ strokeLinecap: "round",
24854
+ strokeLinejoin: "round",
24855
+ 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"
24856
+ }
24857
+ )
24858
+ )), /* @__PURE__ */ import_react37.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Link Inv\xE1lido"), /* @__PURE__ */ import_react37.default.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__ */ import_react37.default.createElement(
24859
+ "button",
24860
+ {
24861
+ onClick: handleNavigateBack,
24862
+ 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"
24863
+ },
24864
+ /* @__PURE__ */ import_react37.default.createElement(
24865
+ "svg",
24866
+ {
24867
+ xmlns: "http://www.w3.org/2000/svg",
24868
+ fill: "none",
24869
+ viewBox: "0 0 24 24",
24870
+ strokeWidth: 2,
24871
+ stroke: "currentColor",
24872
+ className: "w-5 h-5"
24873
+ },
24874
+ /* @__PURE__ */ import_react37.default.createElement(
24875
+ "path",
24876
+ {
24877
+ strokeLinecap: "round",
24878
+ strokeLinejoin: "round",
24879
+ d: "M10 19l-7-7m0 0l7-7m-7 7h18"
24880
+ }
24881
+ )
24882
+ ),
24883
+ "Voltar ao Dashboard"
24884
+ )));
24885
+ }
24651
24886
  if (permissionStatus === "denied") {
24652
24887
  return /* @__PURE__ */ import_react37.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react37.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_react37.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react37.default.createElement(
24653
24888
  "svg",
@@ -25335,7 +25570,20 @@ function XViewScene({
25335
25570
  {
25336
25571
  isOpen: isUpgradeModalOpen,
25337
25572
  onClose: () => setIsUpgradeModalOpen(false),
25338
- nodeCounter
25573
+ nodeCounter,
25574
+ nodeLimit,
25575
+ onUpgrade: async () => {
25576
+ if (onUpgrade) {
25577
+ const res = await onUpgrade();
25578
+ if (res.success) {
25579
+ setNodeLimit(-1);
25580
+ alert("Upgrade realizado com sucesso! Sua conta agora \xE9 Premium.");
25581
+ } else {
25582
+ alert("Erro ao realizar upgrade: " + res.error);
25583
+ }
25584
+ return res;
25585
+ }
25586
+ }
25339
25587
  }
25340
25588
  )
25341
25589
  );
@@ -25451,6 +25699,16 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
25451
25699
  }
25452
25700
  })();
25453
25701
  parentResponsesPromises.push(questFetchPromise, processFetchPromise, nodeCounterPromise);
25702
+ } else {
25703
+ const nodeCounterPromise = (async () => {
25704
+ try {
25705
+ if (!db_services.get_user_node_counter) return { success: true, node_counter: 0 };
25706
+ return await db_services.get_user_node_counter(owner_id);
25707
+ } catch (err) {
25708
+ return { success: false, error: err.message };
25709
+ }
25710
+ })();
25711
+ parentResponsesPromises.push(nodeCounterPromise);
25454
25712
  }
25455
25713
  const parentResponsesResults = await Promise.allSettled(
25456
25714
  parentResponsesPromises
@@ -25459,9 +25717,10 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
25459
25717
  let questDataObj = null;
25460
25718
  let processDataObj = null;
25461
25719
  let userNodeCounter = 0;
25720
+ let userNodeLimit = 100;
25462
25721
  for (let i = 0; i < parentResponsesResults.length; i++) {
25463
25722
  const result = parentResponsesResults[i];
25464
- if (isView && i >= parentDbObjects.length) {
25723
+ if (i >= parentDbObjects.length) {
25465
25724
  if (result.status === "fulfilled" && ((_a = result.value) == null ? void 0 : _a.success)) {
25466
25725
  if (result.value.type === "processes") {
25467
25726
  processDataObj = result.value.data;
@@ -25472,6 +25731,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
25472
25731
  }
25473
25732
  } else if (result.value.node_counter !== void 0) {
25474
25733
  userNodeCounter = result.value.node_counter;
25734
+ if (result.value.node_limit !== void 0) {
25735
+ userNodeLimit = result.value.node_limit;
25736
+ }
25475
25737
  }
25476
25738
  }
25477
25739
  continue;
@@ -25837,7 +26099,8 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
25837
26099
  scene: validatedSceneData,
25838
26100
  parent: parentData,
25839
26101
  ancestry: ancestryData,
25840
- node_counter: userNodeCounter
26102
+ node_counter: userNodeCounter,
26103
+ node_limit: userNodeLimit
25841
26104
  }
25842
26105
  };
25843
26106
  } catch (error) {