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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  // src/XViewScene.jsx
2
- import React28, {
3
- useCallback as useCallback4,
4
- useEffect as useEffect22,
5
- useRef as useRef19,
6
- useState as useState27,
7
- useMemo as useMemo12
2
+ import React30, {
3
+ useCallback as useCallback5,
4
+ useEffect as useEffect24,
5
+ useRef as useRef20,
6
+ useState as useState29,
7
+ useMemo as useMemo13
8
8
  } from "react";
9
9
  import { useRouter, useSearchParams } from "next/navigation";
10
10
  import { useSession } from "next-auth/react";
@@ -79,55 +79,7 @@ function defineAbilityFor(role) {
79
79
 
80
80
  // src/logic/x_view_utils.js
81
81
  import { useState, useCallback } from "react";
82
-
83
- // node_modules/uuid/dist/esm-node/rng.js
84
- import crypto from "crypto";
85
- var rnds8Pool = new Uint8Array(256);
86
- var poolPtr = rnds8Pool.length;
87
- function rng() {
88
- if (poolPtr > rnds8Pool.length - 16) {
89
- crypto.randomFillSync(rnds8Pool);
90
- poolPtr = 0;
91
- }
92
- return rnds8Pool.slice(poolPtr, poolPtr += 16);
93
- }
94
-
95
- // node_modules/uuid/dist/esm-node/stringify.js
96
- var byteToHex = [];
97
- for (let i = 0; i < 256; ++i) {
98
- byteToHex.push((i + 256).toString(16).slice(1));
99
- }
100
- function unsafeStringify(arr, offset = 0) {
101
- return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
102
- }
103
-
104
- // node_modules/uuid/dist/esm-node/native.js
105
- import crypto2 from "crypto";
106
- var native_default = {
107
- randomUUID: crypto2.randomUUID
108
- };
109
-
110
- // node_modules/uuid/dist/esm-node/v4.js
111
- function v4(options, buf, offset) {
112
- if (native_default.randomUUID && !buf && !options) {
113
- return native_default.randomUUID();
114
- }
115
- options = options || {};
116
- const rnds = options.random || (options.rng || rng)();
117
- rnds[6] = rnds[6] & 15 | 64;
118
- rnds[8] = rnds[8] & 63 | 128;
119
- if (buf) {
120
- offset = offset || 0;
121
- for (let i = 0; i < 16; ++i) {
122
- buf[offset + i] = rnds[i];
123
- }
124
- return buf;
125
- }
126
- return unsafeStringify(rnds);
127
- }
128
- var v4_default = v4;
129
-
130
- // src/logic/x_view_utils.js
82
+ import { v4 as uuidv4 } from "uuid";
131
83
  import * as THREE2 from "three";
132
84
 
133
85
  // src/logic/x_view_config.js
@@ -1101,6 +1053,8 @@ var userActionHandlers = {
1101
1053
  if (isCrossDataset) {
1102
1054
  graphDataRef.current[finalTargetDatasetId] = targetDataToUpdate;
1103
1055
  }
1056
+ if (sceneDataRef.current.parent_dbs.some((db) => String(db.db_id) === String(sourceParentInfo.parentFileId))) {
1057
+ }
1104
1058
  const finalPosition = stateRef.current.ghostElements.node.position.clone();
1105
1059
  addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
1106
1060
  stateRef.current.nodeIdToParentFileMap.set(String(newNode.id), {
@@ -1299,6 +1253,9 @@ var userActionHandlers = {
1299
1253
  );
1300
1254
  }
1301
1255
  graphDataRef.current[parentFileId] = specificParentData;
1256
+ if (isView && parentFileId === context.sceneConfigId) {
1257
+ sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
1258
+ }
1302
1259
  const finalPosition = stateRef.current.ghostElements.node.position.clone();
1303
1260
  addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
1304
1261
  setters.setSceneVersion((v) => v + 1);
@@ -2318,8 +2275,6 @@ var userActionHandlers = {
2318
2275
  milestones: sceneDataRef.current.milestones || [],
2319
2276
  quest_counter: sceneDataRef.current.quest_counter || 1
2320
2277
  };
2321
- sceneDataRef.current.quest_nodes = specificParentData.nodes;
2322
- sceneDataRef.current.quest_links = specificParentData.links;
2323
2278
  await context.actions.save_view_data(
2324
2279
  context.sceneSaveUrl,
2325
2280
  viewFilePayload
@@ -2332,6 +2287,10 @@ var userActionHandlers = {
2332
2287
  );
2333
2288
  }
2334
2289
  graphDataRef.current[parentFileId] = specificParentData;
2290
+ if (isView && parentFileId === context.sceneConfigId) {
2291
+ sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
2292
+ sceneDataRef.current.quest_counter = specificParentData.quest_counter || sceneDataRef.current.quest_counter;
2293
+ }
2335
2294
  updateExistingNodeVisuals(stateRef.current, nodeToSave);
2336
2295
  setters.setSceneVersion((v) => v + 1);
2337
2296
  if (!keepOpen) {
@@ -2480,15 +2439,15 @@ function createNewCustomProperty(existingProps = []) {
2480
2439
  switch (nextType) {
2481
2440
  case "links":
2482
2441
  nextKey = "Links";
2483
- nextValue = [{ id: v4_default(), name: "", value: "" }];
2442
+ nextValue = [{ id: uuidv4(), name: "", value: "" }];
2484
2443
  break;
2485
2444
  case "images":
2486
2445
  nextKey = "Images";
2487
- nextValue = [{ id: v4_default(), name: "1", value: "" }];
2446
+ nextValue = [{ id: uuidv4(), name: "1", value: "" }];
2488
2447
  break;
2489
2448
  case "documents":
2490
2449
  nextKey = "Documents";
2491
- nextValue = [{ id: v4_default(), name: "1", value: "" }];
2450
+ nextValue = [{ id: uuidv4(), name: "1", value: "" }];
2492
2451
  break;
2493
2452
  case "date":
2494
2453
  nextKey = "Date";
@@ -2498,14 +2457,14 @@ function createNewCustomProperty(existingProps = []) {
2498
2457
  nextValue = 0;
2499
2458
  break;
2500
2459
  case "list":
2501
- nextValue = [{ id: v4_default(), name: "", value: "" }];
2460
+ nextValue = [{ id: uuidv4(), name: "", value: "" }];
2502
2461
  break;
2503
2462
  default:
2504
2463
  nextValue = "";
2505
2464
  break;
2506
2465
  }
2507
2466
  return {
2508
- id: v4_default(),
2467
+ id: uuidv4(),
2509
2468
  key: nextKey,
2510
2469
  type: nextType,
2511
2470
  value: nextValue,
@@ -2750,7 +2709,7 @@ function extractCustomPropsFromNode(node) {
2750
2709
  if (val && typeof val === "object") {
2751
2710
  if ("date_interval" in val) {
2752
2711
  return {
2753
- id: v4_default(),
2712
+ id: uuidv4(),
2754
2713
  key,
2755
2714
  type: "date",
2756
2715
  value: {
@@ -2762,7 +2721,7 @@ function extractCustomPropsFromNode(node) {
2762
2721
  }
2763
2722
  if ("year" in val) {
2764
2723
  return {
2765
- id: v4_default(),
2724
+ id: uuidv4(),
2766
2725
  key,
2767
2726
  type: "date",
2768
2727
  value: { type: "Ano", value: val.year || "" }
@@ -2770,7 +2729,7 @@ function extractCustomPropsFromNode(node) {
2770
2729
  }
2771
2730
  if ("date" in val) {
2772
2731
  return {
2773
- id: v4_default(),
2732
+ id: uuidv4(),
2774
2733
  key,
2775
2734
  type: "date",
2776
2735
  value: { type: "Data", value: val.date || "" }
@@ -2778,7 +2737,7 @@ function extractCustomPropsFromNode(node) {
2778
2737
  }
2779
2738
  }
2780
2739
  return {
2781
- id: v4_default(),
2740
+ id: uuidv4(),
2782
2741
  key,
2783
2742
  type: "date",
2784
2743
  value: { type: "Data", value: "" }
@@ -2786,14 +2745,14 @@ function extractCustomPropsFromNode(node) {
2786
2745
  }
2787
2746
  if (t === "list" || t === "links" || t === "images" || t === "documents") {
2788
2747
  const safeList = (val || []).map((item) => ({
2789
- id: item.id || v4_default(),
2748
+ id: item.id || uuidv4(),
2790
2749
  name: item.name ?? "",
2791
2750
  value: item.value ?? ""
2792
2751
  }));
2793
- return { id: v4_default(), key, type: t, value: safeList };
2752
+ return { id: uuidv4(), key, type: t, value: safeList };
2794
2753
  }
2795
2754
  return {
2796
- id: v4_default(),
2755
+ id: uuidv4(),
2797
2756
  key,
2798
2757
  type: t,
2799
2758
  value: t === "number" ? Number(val) || 0 : String(val ?? "")
@@ -3066,16 +3025,16 @@ var processDescriptionForSave = (text, existingSections = []) => {
3066
3025
  if (existingMatch) {
3067
3026
  finalUuid = existingMatch.id;
3068
3027
  } else {
3069
- finalUuid = v4_default();
3028
+ finalUuid = uuidv4();
3070
3029
  }
3071
3030
  } else {
3072
3031
  finalUuid = numericMap.get(numStr);
3073
3032
  if (!finalUuid) {
3074
- finalUuid = v4_default();
3033
+ finalUuid = uuidv4();
3075
3034
  }
3076
3035
  }
3077
3036
  if (usedIds.has(finalUuid)) {
3078
- finalUuid = v4_default();
3037
+ finalUuid = uuidv4();
3079
3038
  }
3080
3039
  usedIds.add(finalUuid);
3081
3040
  processedSections.push({
@@ -3186,18 +3145,18 @@ function useResizablePanel({ initialWidth, minWidth, maxWidth }) {
3186
3145
  function createTimelineEntry(actorId, description, type = "comment", extras = {}) {
3187
3146
  const { links = [], images = [], metadata = {} } = extras;
3188
3147
  return {
3189
- id: v4_default(),
3148
+ id: uuidv4(),
3190
3149
  type,
3191
3150
  timestamp: Date.now(),
3192
3151
  actorId,
3193
3152
  description,
3194
3153
  links: links.map((l) => ({
3195
- id: l.id || v4_default(),
3154
+ id: l.id || uuidv4(),
3196
3155
  name: l.name || "",
3197
3156
  value: l.value || ""
3198
3157
  })),
3199
3158
  images: images.map((img) => ({
3200
- id: img.id || v4_default(),
3159
+ id: img.id || uuidv4(),
3201
3160
  name: img.name || "",
3202
3161
  value: img.value || ""
3203
3162
  }))
@@ -4424,6 +4383,7 @@ function XViewSidebar({
4424
4383
 
4425
4384
  // src/components/AncestryRelationshipPanel.jsx
4426
4385
  import React8, { useState as useState9, useEffect as useEffect8, useRef as useRef7 } from "react";
4386
+ import { v4 as uuidv43 } from "uuid";
4427
4387
 
4428
4388
  // src/components/CustomPropertyDisplay.jsx
4429
4389
  import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
@@ -5183,6 +5143,7 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
5183
5143
  }
5184
5144
 
5185
5145
  // src/components/DescriptionEditModal.jsx
5146
+ import { v4 as uuidv42 } from "uuid";
5186
5147
  var getNextSectionNumber = (currentText) => {
5187
5148
  const regex = /\*\/\s*(\d+)(?::[a-zA-Z0-9-]+)?\s*\//g;
5188
5149
  let max = 0;
@@ -5314,7 +5275,7 @@ function DescriptionEditModal({
5314
5275
  const el = textareaRef.current;
5315
5276
  if (!el) return;
5316
5277
  const nextNum = getNextSectionNumber(text);
5317
- const uniqueSuffix = v4_default().slice(0, 4);
5278
+ const uniqueSuffix = uuidv42().slice(0, 4);
5318
5279
  insertAtCursor(`*/${nextNum}:${uniqueSuffix}/ `);
5319
5280
  };
5320
5281
  const handleImportSelect = (tags) => {
@@ -5325,7 +5286,7 @@ function DescriptionEditModal({
5325
5286
  let currentNum = getNextSectionNumber(currentText);
5326
5287
  let blockToInsert = "";
5327
5288
  tagsArray.forEach((tag) => {
5328
- const uniqueSuffix = v4_default().slice(0, 4);
5289
+ const uniqueSuffix = uuidv42().slice(0, 4);
5329
5290
  blockToInsert += `
5330
5291
  */${currentNum}:${uniqueSuffix}/ ${tag}
5331
5292
  `;
@@ -6685,6 +6646,7 @@ import {
6685
6646
  FiLink as FiLink4,
6686
6647
  FiTrash2 as FiTrash22
6687
6648
  } from "react-icons/fi";
6649
+ import { v4 as uuidv44 } from "uuid";
6688
6650
 
6689
6651
  // src/components/AncestryPickerModal.jsx
6690
6652
  import React9, { useState as useState10, useMemo as useMemo7, useEffect as useEffect9 } from "react";
@@ -7721,7 +7683,7 @@ function CreateAncestryPanel({
7721
7683
  const nodeData = availableNodes.find((n) => String(n.id) === String(nodeId));
7722
7684
  const dirSuffix = direction === "left" ? "(Esq)" : "(Dir)";
7723
7685
  branch = {
7724
- id: v4_default(),
7686
+ id: uuidv44(),
7725
7687
  name: `Ramifica\xE7\xE3o ${dirSuffix} de ${(nodeData == null ? void 0 : nodeData.name) || "Node"}`,
7726
7688
  description: "",
7727
7689
  description_sections: [],
@@ -8500,6 +8462,7 @@ function ImageViewer({ data, onClose }) {
8500
8462
 
8501
8463
  // src/components/InSceneCreationForm.jsx
8502
8464
  import React13, { useState as useState14, useEffect as useEffect13, useRef as useRef10 } from "react";
8465
+ import { v4 as uuidv45 } from "uuid";
8503
8466
 
8504
8467
  // src/components/ColorPicker.jsx
8505
8468
  import React12, { useState as useState13, useEffect as useEffect12, useRef as useRef9 } from "react";
@@ -9084,6 +9047,7 @@ function InSceneCreationForm({
9084
9047
 
9085
9048
  // src/components/InSceneVersionForm.jsx
9086
9049
  import React14, { useState as useState15, useEffect as useEffect14, useRef as useRef11 } from "react";
9050
+ import { v4 as uuidv46 } from "uuid";
9087
9051
  import { FiPlus as FiPlus4, FiMaximize2 as FiMaximize22, FiCheck as FiCheck8, FiEdit2 as FiEdit25 } from "react-icons/fi";
9088
9052
  function InSceneVersionForm({
9089
9053
  onSave,
@@ -9106,7 +9070,7 @@ function InSceneVersionForm({
9106
9070
  const [description, setDescription] = useState15("");
9107
9071
  const [customProps, setCustomProps] = useState15([
9108
9072
  {
9109
- id: v4_default(),
9073
+ id: uuidv46(),
9110
9074
  key: "Date",
9111
9075
  type: "date",
9112
9076
  value: { type: "Data", value: "" },
@@ -9399,6 +9363,7 @@ function InSceneVersionForm({
9399
9363
 
9400
9364
  // src/components/InSceneQuestForm.jsx
9401
9365
  import React16, { useState as useState17, useRef as useRef12 } from "react";
9366
+ import { v4 as uuidv47 } from "uuid";
9402
9367
  import {
9403
9368
  FiPlus as FiPlus6,
9404
9369
  FiCheck as FiCheck9,
@@ -10323,6 +10288,7 @@ function InSceneQuestForm({
10323
10288
 
10324
10289
  // src/components/NodeDetailsPanel.jsx
10325
10290
  import React17, { useState as useState18, useEffect as useEffect15, useRef as useRef13 } from "react";
10291
+ import { v4 as uuidv48 } from "uuid";
10326
10292
  import { FiPlus as FiPlus7, FiMaximize2 as FiMaximize23, FiX as FiX6, FiCheck as FiCheck10, FiImage as FiImage3, FiEdit2 as FiEdit27, FiLoader as FiLoader2, FiBookOpen as FiBookOpen3, FiSun as FiSun2, FiLink as FiLink5, FiDatabase } from "react-icons/fi";
10327
10293
  function NodeDetailsPanel({
10328
10294
  node,
@@ -10837,6 +10803,7 @@ function NodeDetailsPanel({
10837
10803
 
10838
10804
  // src/components/QuestDetailsPanel.jsx
10839
10805
  import React19, { useState as useState19, useEffect as useEffect16, useRef as useRef14 } from "react";
10806
+ import { v4 as uuidv49 } from "uuid";
10840
10807
  import { FiPlus as FiPlus8, FiX as FiX7, FiCheck as FiCheck11, FiEdit2 as FiEdit28, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4, FiLink as FiLink7, FiTarget as FiTarget3, FiChevronDown as FiChevronDown7, FiUser as FiUser3, FiSearch as FiSearch7, FiRepeat as FiRepeat2, FiCalendar as FiCalendar2, FiImage as FiImage4 } from "react-icons/fi";
10841
10808
 
10842
10809
  // src/components/QuestTimeline.jsx
@@ -11287,7 +11254,7 @@ ${noteText}` : noteText : entry.notes,
11287
11254
  }, 100);
11288
11255
  };
11289
11256
  const addLinkToNote = () => {
11290
- setNoteLinks([...noteLinks, { id: v4_default(), name: "", value: "" }]);
11257
+ setNoteLinks([...noteLinks, { id: uuidv49(), name: "", value: "" }]);
11291
11258
  };
11292
11259
  const removeLinkFromNote = (id) => {
11293
11260
  setNoteLinks(noteLinks.filter((l) => l.id !== id));
@@ -11296,7 +11263,7 @@ ${noteText}` : noteText : entry.notes,
11296
11263
  setNoteLinks(noteLinks.map((l) => l.id === id ? { ...l, [field]: val } : l));
11297
11264
  };
11298
11265
  const addImageToNote = () => {
11299
- setNoteImages([...noteImages, { id: v4_default(), name: "Image", value: "" }]);
11266
+ setNoteImages([...noteImages, { id: uuidv49(), name: "Image", value: "" }]);
11300
11267
  };
11301
11268
  const removeImageFromNote = (id) => {
11302
11269
  setNoteImages(noteImages.filter((img) => img.id !== id));
@@ -12173,6 +12140,7 @@ function MultiNodeContextMenu({
12173
12140
 
12174
12141
  // src/components/RelationshipDetailsPanel.jsx
12175
12142
  import React21, { useState as useState21, useEffect as useEffect18, useRef as useRef16, useMemo as useMemo9 } from "react";
12143
+ import { v4 as uuidv410 } from "uuid";
12176
12144
  import { FiPlus as FiPlus9, FiEdit2 as FiEdit29, FiLoader as FiLoader4, FiBookOpen as FiBookOpen5 } from "react-icons/fi";
12177
12145
  function RelationshipDetailsPanel({
12178
12146
  link,
@@ -12982,10 +12950,10 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
12982
12950
  }
12983
12951
 
12984
12952
  // src/components/AncestryBoard.jsx
12985
- import React26, { useState as useState25, useMemo as useMemo11, useEffect as useEffect21, useRef as useRef18 } from "react";
12953
+ import React28, { useState as useState27, useMemo as useMemo12, useEffect as useEffect23 } from "react";
12986
12954
  import {
12987
12955
  FiSearch as FiSearch8,
12988
- FiLayers as FiLayers6,
12956
+ FiLayers as FiLayers7,
12989
12957
  FiCornerUpRight as FiCornerUpRight4,
12990
12958
  FiPlay,
12991
12959
  FiPlus as FiPlus10,
@@ -12995,194 +12963,418 @@ import {
12995
12963
  FiCheckCircle,
12996
12964
  FiLoader as FiLoader5,
12997
12965
  FiX as FiX8,
12998
- FiAlertTriangle,
12999
- FiCheckSquare as FiCheckSquare3,
13000
- FiBox,
13001
- FiGitBranch as FiGitBranch3
12966
+ FiBox as FiBox2,
12967
+ FiCheckSquare as FiCheckSquare4,
12968
+ FiGitBranch as FiGitBranch4
13002
12969
  } from "react-icons/fi";
12970
+ import { v4 as uuidv411 } from "uuid";
12971
+
12972
+ // src/components/RichGroupEditor.jsx
12973
+ import React27, { useEffect as useEffect22, useRef as useRef19, useState as useState26, useCallback as useCallback4 } from "react";
12974
+
12975
+ // src/components/MentionPopover.jsx
12976
+ import React26, { useEffect as useEffect21, useRef as useRef18, useState as useState25, useMemo as useMemo11 } from "react";
12977
+ import { FiLayers as FiLayers6, FiCheckSquare as FiCheckSquare3, FiGitBranch as FiGitBranch3, FiBox } from "react-icons/fi";
12978
+ var TYPE_CONFIG = {
12979
+ ancestry: { Icon: FiLayers6, color: "text-indigo-400", label: "Ancestralidade" },
12980
+ quest: { Icon: FiCheckSquare3, color: "text-emerald-400", label: "Quest" },
12981
+ version: { Icon: FiGitBranch3, color: "text-amber-400", label: "Vers\xE3o" },
12982
+ node: { Icon: FiBox, color: "text-slate-400", label: "Node" }
12983
+ };
12984
+ function MentionPopover({ query, items, position, onSelect, onClose }) {
12985
+ const [activeIndex, setActiveIndex] = useState25(0);
12986
+ const listRef = useRef18(null);
12987
+ const filtered = useMemo11(() => {
12988
+ const term = (query || "").toLowerCase().trim();
12989
+ if (!term) return items.slice(0, 8);
12990
+ return items.filter(
12991
+ (item) => (item.searchLabel || "").toLowerCase().includes(term) || (item.searchDesc || "").toLowerCase().includes(term)
12992
+ ).slice(0, 8);
12993
+ }, [items, query]);
12994
+ useEffect21(() => {
12995
+ setActiveIndex(0);
12996
+ }, [query]);
12997
+ useEffect21(() => {
12998
+ const handleKeyDown = (e) => {
12999
+ if (e.key === "ArrowDown") {
13000
+ e.preventDefault();
13001
+ setActiveIndex((i) => Math.min(i + 1, filtered.length - 1));
13002
+ } else if (e.key === "ArrowUp") {
13003
+ e.preventDefault();
13004
+ setActiveIndex((i) => Math.max(i - 1, 0));
13005
+ } else if (e.key === "Enter" || e.key === "Tab") {
13006
+ e.preventDefault();
13007
+ if (filtered[activeIndex]) onSelect(filtered[activeIndex]);
13008
+ } else if (e.key === "Escape") {
13009
+ e.preventDefault();
13010
+ onClose();
13011
+ }
13012
+ };
13013
+ window.addEventListener("keydown", handleKeyDown, true);
13014
+ return () => window.removeEventListener("keydown", handleKeyDown, true);
13015
+ }, [filtered, activeIndex, onSelect, onClose]);
13016
+ useEffect21(() => {
13017
+ if (listRef.current) {
13018
+ const el = listRef.current.children[activeIndex];
13019
+ if (el) el.scrollIntoView({ block: "nearest" });
13020
+ }
13021
+ }, [activeIndex]);
13022
+ return /* @__PURE__ */ React26.createElement(
13023
+ "div",
13024
+ {
13025
+ style: { top: position.top, left: position.left, position: "fixed", zIndex: 9999 },
13026
+ className: "bg-slate-900 border border-white/10 rounded-xl shadow-2xl py-1.5 min-w-[260px] max-h-[240px] overflow-y-auto custom-scrollbar animate-in fade-in zoom-in-95 duration-100",
13027
+ ref: listRef,
13028
+ onMouseDown: (e) => e.preventDefault()
13029
+ },
13030
+ filtered.length === 0 ? /* @__PURE__ */ React26.createElement("div", { className: "px-4 py-3 text-xs text-slate-500" }, "Nenhum resultado para", " ", /* @__PURE__ */ React26.createElement("span", { className: "text-slate-300 font-medium" }, '"', query, '"')) : filtered.map((item, idx) => {
13031
+ const config = TYPE_CONFIG[item.type] || TYPE_CONFIG.node;
13032
+ const { Icon } = config;
13033
+ return /* @__PURE__ */ React26.createElement(
13034
+ "div",
13035
+ {
13036
+ key: item.id,
13037
+ onMouseDown: (e) => {
13038
+ e.preventDefault();
13039
+ onSelect(item);
13040
+ },
13041
+ onMouseEnter: () => setActiveIndex(idx),
13042
+ className: `flex items-center gap-2.5 px-3 py-2 cursor-pointer text-sm transition-colors duration-100 ${idx === activeIndex ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5"}`
13043
+ },
13044
+ /* @__PURE__ */ React26.createElement(Icon, { size: 13, className: config.color }),
13045
+ /* @__PURE__ */ React26.createElement("span", { className: "flex-1 truncate font-medium" }, item.searchLabel || "Sem Nome"),
13046
+ /* @__PURE__ */ React26.createElement("span", { className: "text-[9px] px-1.5 py-0.5 rounded-full bg-white/5 text-slate-500 border border-white/5 uppercase tracking-wide shrink-0" }, config.label)
13047
+ );
13048
+ })
13049
+ );
13050
+ }
13051
+
13052
+ // src/components/RichGroupEditor.jsx
13053
+ var MENTION_BASE_STYLE = "display:inline-flex;align-items:center;padding:1px 7px;border-radius:5px;margin:0 2px;font-size:0.78em;font-weight:600;cursor:pointer;white-space:nowrap;vertical-align:middle;user-select:none;line-height:1.6;";
13054
+ var MENTION_TYPE_STYLE = {
13055
+ ancestry: "background:rgba(99,102,241,0.18);color:#a5b4fc;border:1px solid rgba(99,102,241,0.35);",
13056
+ quest: "background:rgba(16,185,129,0.18);color:#6ee7b7;border:1px solid rgba(16,185,129,0.35);",
13057
+ version: "background:rgba(245,158,11,0.18);color:#fcd34d;border:1px solid rgba(245,158,11,0.35);",
13058
+ node: "background:rgba(100,116,139,0.18);color:#94a3b8;border:1px solid rgba(100,116,139,0.35);"
13059
+ };
13060
+ function mentionStyle(type) {
13061
+ return MENTION_BASE_STYLE + (MENTION_TYPE_STYLE[type] || MENTION_TYPE_STYLE.node);
13062
+ }
13063
+ function escapeHtml(str) {
13064
+ return String(str || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
13065
+ }
13066
+ function contentToHTML(content) {
13067
+ if (!content || content.length === 0) return "";
13068
+ return content.map((seg) => {
13069
+ if (seg.type === "text") {
13070
+ return escapeHtml(seg.value).replace(/\n/g, "<br>");
13071
+ }
13072
+ if (seg.type === "mention") {
13073
+ const style = mentionStyle(seg.mentionType);
13074
+ return `<span contenteditable="false" data-mention="true" data-id="${escapeHtml(String(seg.id))}" data-name="${escapeHtml(seg.name || "")}" data-mention-type="${escapeHtml(seg.mentionType || "node")}" style="${style}" title="Clique para focar na cena">@${escapeHtml(seg.name || "")}</span>`;
13075
+ }
13076
+ return "";
13077
+ }).join("");
13078
+ }
13079
+ function domToContent(el) {
13080
+ const segments = [];
13081
+ function pushText(text) {
13082
+ const clean = text.replace(/\u200B/g, "");
13083
+ if (!clean) return;
13084
+ const last = segments[segments.length - 1];
13085
+ if (last && last.type === "text") {
13086
+ last.value += clean;
13087
+ } else {
13088
+ segments.push({ type: "text", value: clean });
13089
+ }
13090
+ }
13091
+ function walk(node) {
13092
+ var _a;
13093
+ if (node.nodeType === Node.TEXT_NODE) {
13094
+ pushText(node.textContent);
13095
+ } else if (node.nodeType === Node.ELEMENT_NODE) {
13096
+ if (((_a = node.dataset) == null ? void 0 : _a.mention) === "true") {
13097
+ segments.push({
13098
+ type: "mention",
13099
+ id: node.dataset.id,
13100
+ name: node.dataset.name,
13101
+ mentionType: node.dataset.mentionType
13102
+ });
13103
+ } else if (node.tagName === "BR") {
13104
+ pushText("\n");
13105
+ } else {
13106
+ if (["DIV", "P"].includes(node.tagName) && segments.length > 0) {
13107
+ pushText("\n");
13108
+ }
13109
+ node.childNodes.forEach(walk);
13110
+ }
13111
+ }
13112
+ }
13113
+ el.childNodes.forEach(walk);
13114
+ return segments;
13115
+ }
13116
+ function RichGroupEditor({
13117
+ content,
13118
+ onChange,
13119
+ onMentionClick,
13120
+ searchItems,
13121
+ readOnly,
13122
+ placeholder
13123
+ }) {
13124
+ const editorRef = useRef19(null);
13125
+ const isMountedRef = useRef19(false);
13126
+ const [mentionState, setMentionState] = useState26(null);
13127
+ const [isEmpty, setIsEmpty] = useState26(true);
13128
+ useEffect22(() => {
13129
+ if (!isMountedRef.current && editorRef.current) {
13130
+ editorRef.current.innerHTML = contentToHTML(content);
13131
+ const hasContent = !!editorRef.current.innerText.replace(/\u200B/g, "").trim();
13132
+ const hasMentions = !!editorRef.current.querySelector("[data-mention]");
13133
+ setIsEmpty(!hasContent && !hasMentions);
13134
+ isMountedRef.current = true;
13135
+ }
13136
+ }, []);
13137
+ const getMentionContext = useCallback4(() => {
13138
+ const selection = window.getSelection();
13139
+ if (!selection || selection.rangeCount === 0) return null;
13140
+ const range = selection.getRangeAt(0);
13141
+ if (range.startContainer.nodeType !== Node.TEXT_NODE) return null;
13142
+ const textBefore = range.startContainer.textContent.substring(0, range.startOffset);
13143
+ const atIndex = textBefore.lastIndexOf("@");
13144
+ if (atIndex === -1) return null;
13145
+ const query = textBefore.substring(atIndex + 1);
13146
+ if (query.includes(" ") || query.includes(".") || query.includes(",") || query.length > 40) {
13147
+ return null;
13148
+ }
13149
+ const rect = range.getBoundingClientRect();
13150
+ return {
13151
+ query,
13152
+ position: { top: rect.bottom + 6, left: rect.left }
13153
+ };
13154
+ }, []);
13155
+ const handleInput = useCallback4(() => {
13156
+ if (!editorRef.current) return;
13157
+ const serialized = domToContent(editorRef.current);
13158
+ onChange(serialized);
13159
+ const text = editorRef.current.innerText.replace(/\u200B/g, "").trim();
13160
+ const hasMentions = !!editorRef.current.querySelector("[data-mention]");
13161
+ setIsEmpty(!text && !hasMentions);
13162
+ const ctx = getMentionContext();
13163
+ setMentionState(ctx);
13164
+ }, [onChange, getMentionContext]);
13165
+ const handleKeyDown = useCallback4(
13166
+ (e) => {
13167
+ if (mentionState && ["ArrowDown", "ArrowUp", "Enter", "Tab", "Escape"].includes(e.key)) {
13168
+ return;
13169
+ }
13170
+ if (e.key === "Enter") {
13171
+ e.preventDefault();
13172
+ const sel = window.getSelection();
13173
+ const range = sel.getRangeAt(0);
13174
+ const br = document.createElement("br");
13175
+ range.deleteContents();
13176
+ range.insertNode(br);
13177
+ const afterBr = br.nextSibling || (() => {
13178
+ const zws = document.createTextNode("\u200B");
13179
+ br.parentNode.insertBefore(zws, br.nextSibling);
13180
+ return zws;
13181
+ })();
13182
+ const newRange = document.createRange();
13183
+ newRange.setStartBefore(afterBr);
13184
+ newRange.collapse(true);
13185
+ sel.removeAllRanges();
13186
+ sel.addRange(newRange);
13187
+ handleInput();
13188
+ }
13189
+ },
13190
+ [mentionState, handleInput]
13191
+ );
13192
+ const insertMention = useCallback4(
13193
+ (item) => {
13194
+ if (!editorRef.current) return;
13195
+ const sel = window.getSelection();
13196
+ if (!sel || sel.rangeCount === 0) return;
13197
+ const range = sel.getRangeAt(0);
13198
+ const textNode = range.startContainer;
13199
+ if (textNode.nodeType !== Node.TEXT_NODE) {
13200
+ setMentionState(null);
13201
+ return;
13202
+ }
13203
+ const cursorPos = range.startOffset;
13204
+ const textContent = textNode.textContent;
13205
+ const atIndex = textContent.lastIndexOf("@", cursorPos - 1);
13206
+ if (atIndex === -1) {
13207
+ setMentionState(null);
13208
+ return;
13209
+ }
13210
+ const before = textContent.substring(0, atIndex);
13211
+ const after = textContent.substring(cursorPos);
13212
+ textNode.textContent = before;
13213
+ const parent = textNode.parentNode;
13214
+ const nextSib = textNode.nextSibling;
13215
+ const span = document.createElement("span");
13216
+ span.contentEditable = "false";
13217
+ span.dataset.mention = "true";
13218
+ span.dataset.id = item.id;
13219
+ span.dataset.name = item.searchLabel || item.name || "";
13220
+ span.dataset.mentionType = item.type;
13221
+ span.style.cssText = mentionStyle(item.type);
13222
+ span.title = "Clique para focar na cena";
13223
+ span.textContent = `@${item.searchLabel || item.name || ""}`;
13224
+ parent.insertBefore(span, nextSib);
13225
+ const trailing = document.createTextNode(after || "\u200B");
13226
+ parent.insertBefore(trailing, span.nextSibling);
13227
+ const newRange = document.createRange();
13228
+ newRange.setStart(trailing, after ? 0 : 1);
13229
+ newRange.collapse(true);
13230
+ sel.removeAllRanges();
13231
+ sel.addRange(newRange);
13232
+ const serialized = domToContent(editorRef.current);
13233
+ onChange(serialized);
13234
+ setMentionState(null);
13235
+ setIsEmpty(false);
13236
+ },
13237
+ [onChange]
13238
+ );
13239
+ const handlePaste = useCallback4(
13240
+ (e) => {
13241
+ e.preventDefault();
13242
+ const text = e.clipboardData.getData("text/plain");
13243
+ if (text) {
13244
+ document.execCommand("insertText", false, text);
13245
+ handleInput();
13246
+ }
13247
+ },
13248
+ [handleInput]
13249
+ );
13250
+ const handleClick = useCallback4(
13251
+ (e) => {
13252
+ const chip = e.target.closest("[data-mention='true']");
13253
+ if (chip && onMentionClick) {
13254
+ e.stopPropagation();
13255
+ const id = chip.dataset.id;
13256
+ const full = searchItems == null ? void 0 : searchItems.find((i) => String(i.id) === String(id));
13257
+ if (full) {
13258
+ onMentionClick(full);
13259
+ } else {
13260
+ onMentionClick({
13261
+ id,
13262
+ name: chip.dataset.name,
13263
+ type: chip.dataset.mentionType,
13264
+ searchLabel: chip.dataset.name
13265
+ });
13266
+ }
13267
+ return;
13268
+ }
13269
+ setTimeout(() => {
13270
+ const ctx = getMentionContext();
13271
+ setMentionState(ctx);
13272
+ }, 0);
13273
+ },
13274
+ [onMentionClick, getMentionContext, searchItems]
13275
+ );
13276
+ const handleBlur = useCallback4(() => {
13277
+ setTimeout(() => setMentionState(null), 200);
13278
+ }, []);
13279
+ return /* @__PURE__ */ React27.createElement("div", { className: "relative" }, isEmpty && !readOnly && /* @__PURE__ */ React27.createElement("div", { className: "absolute top-0 left-0 text-sm text-slate-600 pointer-events-none select-none" }, placeholder || "Escreva sobre este grupo\u2026 ou digite @ para mencionar"), /* @__PURE__ */ React27.createElement(
13280
+ "div",
13281
+ {
13282
+ ref: editorRef,
13283
+ contentEditable: readOnly ? "false" : "true",
13284
+ suppressContentEditableWarning: true,
13285
+ onInput: handleInput,
13286
+ onKeyDown: handleKeyDown,
13287
+ onPaste: handlePaste,
13288
+ onClick: handleClick,
13289
+ onBlur: handleBlur,
13290
+ className: `w-full min-h-[1.5rem] max-h-[250px] overflow-y-auto text-sm text-slate-200 focus:outline-none leading-relaxed ${!readOnly ? "cursor-text" : "cursor-default"}`,
13291
+ style: { overflowWrap: "break-word", wordBreak: "break-word" }
13292
+ }
13293
+ ), mentionState && !readOnly && /* @__PURE__ */ React27.createElement(
13294
+ MentionPopover,
13295
+ {
13296
+ query: mentionState.query,
13297
+ items: searchItems || [],
13298
+ position: mentionState.position,
13299
+ onSelect: insertMention,
13300
+ onClose: () => setMentionState(null)
13301
+ }
13302
+ ));
13303
+ }
13304
+
13305
+ // src/components/AncestryBoard.jsx
13003
13306
  var GroupItem = ({
13004
13307
  group,
13005
13308
  index,
13006
- siblings,
13007
13309
  onUpdate,
13008
13310
  onDelete,
13009
13311
  onAddSubgroup,
13010
13312
  onIndent,
13011
13313
  onOutdent,
13012
- onRemoveAncestry,
13013
- onRequestPickAncestry,
13014
- pickingGroupId,
13015
- onPlayAncestry,
13016
- availableIds,
13314
+ searchItems,
13315
+ onMentionClick,
13017
13316
  canEdit
13018
13317
  }) => {
13019
13318
  const canIndent = index > 0;
13020
- const isPickingForThisGroup = pickingGroupId === group.id;
13021
- const textareaRef = useRef18(null);
13022
- const adjustHeight = () => {
13023
- const textarea = textareaRef.current;
13024
- if (textarea) {
13025
- textarea.style.height = "auto";
13026
- textarea.style.height = `${textarea.scrollHeight}px`;
13027
- }
13319
+ const handleContentChange = (content) => {
13320
+ onUpdate(group.id, { ...group, content });
13028
13321
  };
13029
- useEffect21(() => {
13030
- adjustHeight();
13031
- }, [group.text]);
13032
- return /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React26.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ React26.createElement(
13033
- "div",
13322
+ return /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React28.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col gap-2 py-2 px-3 transition-all duration-200 hover:bg-white/5 border-l-2 border-transparent hover:border-white/20" }, /* @__PURE__ */ React28.createElement(
13323
+ RichGroupEditor,
13034
13324
  {
13035
- className: `
13036
- flex flex-col gap-2 py-2 px-3 transition-all duration-200
13037
- ${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
13038
- `
13325
+ content: group.content,
13326
+ onChange: handleContentChange,
13327
+ onMentionClick,
13328
+ searchItems,
13329
+ readOnly: !canEdit,
13330
+ placeholder: "Escreva sobre este grupo\u2026 ou @ para mencionar"
13331
+ }
13332
+ ), canEdit && /* @__PURE__ */ React28.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(
13333
+ "button",
13334
+ {
13335
+ onClick: () => onAddSubgroup(group.id),
13336
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13337
+ title: "Criar Subgrupo"
13039
13338
  },
13040
- /* @__PURE__ */ React26.createElement(
13041
- "textarea",
13042
- {
13043
- ref: textareaRef,
13044
- className: `w-full bg-transparent text-sm text-slate-200 placeholder-slate-600 resize-none focus:outline-none focus:placeholder-slate-500 overflow-y-auto ${!canEdit ? "cursor-default" : ""}`,
13045
- rows: 1,
13046
- style: {
13047
- minHeight: "1.5rem",
13048
- maxHeight: "250px"
13049
- },
13050
- placeholder: canEdit ? "Escreva sobre este grupo..." : "",
13051
- value: group.text,
13052
- readOnly: !canEdit,
13053
- onChange: (e) => {
13054
- if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
13055
- }
13056
- }
13057
- ),
13058
- group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ React26.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
13059
- const isValid = anc.type === "ancestry" || !anc.type ? availableIds.has(String(anc.ancestry_id || anc.id)) : true;
13060
- const isAncestry = anc.type === "ancestry" || !anc.type;
13061
- const itemId = isAncestry ? anc.ancestry_id : anc.id;
13062
- let Icon = FiLayers6;
13063
- let colorClass = "text-indigo-400";
13064
- if (anc.type === "quest") {
13065
- Icon = FiCheckSquare3;
13066
- colorClass = "text-amber-400";
13067
- } else if (anc.type === "version") {
13068
- Icon = FiGitBranch3;
13069
- colorClass = "text-purple-400";
13070
- } else if (anc.type === "node") {
13071
- Icon = FiBox;
13072
- colorClass = "text-emerald-400";
13073
- }
13074
- return /* @__PURE__ */ React26.createElement(
13075
- "div",
13076
- {
13077
- key: `${anc.type || "ancestry"}-${itemId}`,
13078
- className: `
13079
- flex items-center gap-2 rounded-md px-3 py-1.5 text-xs transition-all group/card border
13080
- ${isValid ? "bg-slate-800/60 border-white/10 hover:border-indigo-500/30 text-slate-200" : "bg-red-900/10 border-red-500/30 text-red-300/70 hover:bg-red-900/20"}
13081
- `,
13082
- title: isValid ? "" : "Esta informa\xE7\xE3o n\xE3o est\xE1 mais dispon\xEDvel neste contexto."
13083
- },
13084
- isValid ? /* @__PURE__ */ React26.createElement(
13085
- "button",
13086
- {
13087
- onClick: () => onPlayAncestry(anc),
13088
- className: `${colorClass} hover:text-white hover:bg-current/20 p-1 rounded transition-colors flex items-center justify-center`,
13089
- title: "Focar no cen\xE1rio"
13090
- },
13091
- /* @__PURE__ */ React26.createElement(Icon, { size: 12 }),
13092
- /* @__PURE__ */ React26.createElement(
13093
- FiPlay,
13094
- {
13095
- size: 8,
13096
- className: "ml-0.5 fill-current opacity-0 group-hover/card:opacity-100 transition-opacity"
13097
- }
13098
- )
13099
- ) : /* @__PURE__ */ React26.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ React26.createElement(FiAlertTriangle, { size: 10 })),
13100
- /* @__PURE__ */ React26.createElement(
13101
- "span",
13102
- {
13103
- className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}`
13104
- },
13105
- anc.name
13106
- ),
13107
- canEdit && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(
13108
- "div",
13109
- {
13110
- className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}`
13111
- }
13112
- ), /* @__PURE__ */ React26.createElement(
13113
- "button",
13114
- {
13115
- onClick: () => onRemoveAncestry(group.id, itemId),
13116
- className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
13117
- title: "Remover men\xE7\xE3o"
13118
- },
13119
- /* @__PURE__ */ React26.createElement(FiX8, { size: 12 })
13120
- ))
13121
- );
13122
- })),
13123
- canEdit && /* @__PURE__ */ React26.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React26.createElement(
13124
- "button",
13125
- {
13126
- onClick: () => onRequestPickAncestry(group.id),
13127
- className: `
13128
- flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium transition-colors
13129
- ${isPickingForThisGroup ? "text-indigo-300 animate-pulse" : "text-slate-500 hover:text-indigo-300 hover:bg-indigo-500/10"}
13130
- `,
13131
- title: "Adicionar Men\xE7\xE3o a este grupo"
13132
- },
13133
- isPickingForThisGroup ? /* @__PURE__ */ React26.createElement(FiCheckCircle, { size: 12 }) : /* @__PURE__ */ React26.createElement(FiSearch8, { size: 12 }),
13134
- isPickingForThisGroup ? "Selecionando..." : "Adicionar"
13135
- ), /* @__PURE__ */ React26.createElement(
13136
- "button",
13137
- {
13138
- onClick: () => onAddSubgroup(group.id),
13139
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13140
- title: "Criar Subgrupo"
13141
- },
13142
- /* @__PURE__ */ React26.createElement(FiPlus10, { size: 14 })
13143
- )), /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React26.createElement(
13144
- "button",
13145
- {
13146
- onClick: () => onIndent(group.id),
13147
- disabled: !canIndent,
13148
- className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13149
- title: "Aninhar no grupo acima"
13150
- },
13151
- /* @__PURE__ */ React26.createElement(FiArrowRight2, { size: 14 })
13152
- ), /* @__PURE__ */ React26.createElement(
13153
- "button",
13154
- {
13155
- onClick: () => onOutdent(group.id),
13156
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13157
- title: "Desaninhar"
13158
- },
13159
- /* @__PURE__ */ React26.createElement(FiArrowLeft3, { size: 14 })
13160
- ), /* @__PURE__ */ React26.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React26.createElement(
13161
- "button",
13162
- {
13163
- onClick: () => onDelete(group.id),
13164
- className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13165
- title: "Remover Grupo"
13166
- },
13167
- /* @__PURE__ */ React26.createElement(FiTrash23, { size: 14 })
13168
- )))
13169
- ), group.children && group.children.length > 0 && /* @__PURE__ */ React26.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ React26.createElement(
13339
+ /* @__PURE__ */ React28.createElement(FiPlus10, { size: 14 })
13340
+ )), /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(
13341
+ "button",
13342
+ {
13343
+ onClick: () => onIndent(group.id),
13344
+ disabled: !canIndent,
13345
+ className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13346
+ title: "Aninhar no grupo acima"
13347
+ },
13348
+ /* @__PURE__ */ React28.createElement(FiArrowRight2, { size: 14 })
13349
+ ), /* @__PURE__ */ React28.createElement(
13350
+ "button",
13351
+ {
13352
+ onClick: () => onOutdent(group.id),
13353
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13354
+ title: "Desaninhar"
13355
+ },
13356
+ /* @__PURE__ */ React28.createElement(FiArrowLeft3, { size: 14 })
13357
+ ), /* @__PURE__ */ React28.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React28.createElement(
13358
+ "button",
13359
+ {
13360
+ onClick: () => onDelete(group.id),
13361
+ className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13362
+ title: "Remover Grupo"
13363
+ },
13364
+ /* @__PURE__ */ React28.createElement(FiTrash23, { size: 14 })
13365
+ )))), group.children && group.children.length > 0 && /* @__PURE__ */ React28.createElement("div", { className: "ml-2" }, group.children.map((child, idx) => /* @__PURE__ */ React28.createElement(
13170
13366
  GroupItem,
13171
13367
  {
13172
- key: childGroup.id,
13368
+ key: child.id,
13173
13369
  index: idx,
13174
- group: childGroup,
13175
- siblings: group.children,
13370
+ group: child,
13176
13371
  onUpdate,
13177
13372
  onDelete,
13178
13373
  onAddSubgroup,
13179
13374
  onIndent,
13180
13375
  onOutdent,
13181
- onRemoveAncestry,
13182
- onRequestPickAncestry,
13183
- pickingGroupId,
13184
- onPlayAncestry,
13185
- availableIds,
13376
+ searchItems,
13377
+ onMentionClick,
13186
13378
  canEdit
13187
13379
  }
13188
13380
  ))));
@@ -13197,168 +13389,104 @@ function AncestryBoard({
13197
13389
  onSave,
13198
13390
  userRole
13199
13391
  }) {
13200
- const [searchTerm, setSearchTerm] = useState25("");
13201
- const [groups, setGroups] = useState25([]);
13202
- const [isLoaded, setIsLoaded] = useState25(false);
13203
- const [pickingGroupId, setPickingGroupId] = useState25(null);
13204
- const [saveStatus, setSaveStatus] = useState25("idle");
13205
- const canEdit = useMemo11(() => {
13206
- return userRole !== "viewer";
13207
- }, [userRole]);
13208
- useEffect21(() => {
13392
+ const [groups, setGroups] = useState27([]);
13393
+ const [isLoaded, setIsLoaded] = useState27(false);
13394
+ const [saveStatus, setSaveStatus] = useState27("idle");
13395
+ const canEdit = useMemo12(() => userRole !== "viewer", [userRole]);
13396
+ useEffect23(() => {
13209
13397
  if (initialGroups && !isLoaded) {
13210
- setGroups(initialGroups);
13398
+ const migrate = (list) => list.map((g) => ({
13399
+ id: g.id || uuidv411(),
13400
+ content: Array.isArray(g.content) ? g.content : [],
13401
+ // descarta dados legados
13402
+ children: migrate(g.children || [])
13403
+ }));
13404
+ setGroups(migrate(initialGroups));
13211
13405
  setIsLoaded(true);
13212
13406
  }
13213
13407
  }, [initialGroups, isLoaded]);
13214
- const nodeNamesMap = useMemo11(() => {
13215
- const map = /* @__PURE__ */ new Map();
13216
- if (availableNodes && Array.isArray(availableNodes)) {
13217
- availableNodes.forEach((node) => {
13218
- if (node && node.id) {
13219
- map.set(String(node.id), node.name);
13220
- }
13408
+ const allSearchableItems = useMemo12(() => {
13409
+ const items = [];
13410
+ availableAncestries.forEach((anc) => {
13411
+ items.push({
13412
+ ...anc,
13413
+ id: String(anc.ancestry_id),
13414
+ type: "ancestry",
13415
+ searchLabel: anc.name || "",
13416
+ searchDesc: anc.description || ""
13221
13417
  });
13222
- }
13223
- return map;
13224
- }, [availableNodes]);
13225
- const availableIds = useMemo11(() => {
13226
- return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
13227
- }, [availableAncestries]);
13228
- const allMentionableItems = useMemo11(() => {
13229
- const ancestries = availableAncestries.map((a) => ({
13230
- id: String(a.ancestry_id),
13231
- ancestry_id: a.ancestry_id,
13232
- name: a.name,
13233
- description: a.description,
13234
- type: "ancestry",
13235
- ancestral_node: a.ancestral_node,
13236
- is_private: a.is_private
13237
- }));
13238
- const nodes = availableNodes.map((n) => {
13418
+ });
13419
+ availableNodes.forEach((node) => {
13420
+ var _a;
13239
13421
  let type = "node";
13240
- if (n.is_quest) type = "quest";
13241
- else if (n.is_version) type = "version";
13242
- return {
13243
- id: String(n.id),
13244
- name: n.name,
13245
- description: n.description,
13422
+ if (node.is_quest) type = "quest";
13423
+ else if ((_a = node.version_node) == null ? void 0 : _a.is_version) type = "version";
13424
+ items.push({
13425
+ ...node,
13426
+ id: String(node.id),
13246
13427
  type,
13247
- raw_node: n
13248
- };
13428
+ searchLabel: node.name || node.raw_title || "",
13429
+ searchDesc: node.description || ""
13430
+ });
13249
13431
  });
13250
- return [...ancestries, ...nodes];
13432
+ return items;
13251
13433
  }, [availableAncestries, availableNodes]);
13252
- const sanitizeGroups = (groupList) => {
13253
- return groupList.map((g) => ({
13254
- id: g.id,
13255
- text: g.text || "",
13256
- ancestries: (g.ancestries || []).map((a) => ({
13257
- id: a.id || a.ancestry_id,
13258
- ancestry_id: a.ancestry_id,
13259
- name: a.name,
13260
- type: a.type || "ancestry"
13261
- })),
13262
- children: sanitizeGroups(g.children || [])
13263
- }));
13264
- };
13265
- useEffect21(() => {
13434
+ const sanitizeGroups = (list) => list.map((g) => ({
13435
+ id: g.id,
13436
+ content: g.content || [],
13437
+ children: sanitizeGroups(g.children || [])
13438
+ }));
13439
+ useEffect23(() => {
13266
13440
  if (!isLoaded || !onSave) return;
13267
- const timeoutId = setTimeout(async () => {
13441
+ const id = setTimeout(async () => {
13268
13442
  setSaveStatus("saving");
13269
- const cleanData = sanitizeGroups(groups);
13270
13443
  try {
13271
- await onSave(cleanData);
13444
+ await onSave(sanitizeGroups(groups));
13272
13445
  setSaveStatus("saved");
13273
- setTimeout(() => {
13274
- setSaveStatus("idle");
13275
- }, 3e3);
13276
- } catch (error) {
13277
- console.error("Erro ao salvar board:", error);
13446
+ setTimeout(() => setSaveStatus("idle"), 3e3);
13447
+ } catch (err) {
13448
+ console.error("Erro ao salvar board:", err);
13278
13449
  setSaveStatus("error");
13279
13450
  }
13280
13451
  }, 3e3);
13281
- return () => clearTimeout(timeoutId);
13452
+ return () => clearTimeout(id);
13282
13453
  }, [groups, isLoaded, onSave]);
13283
- useEffect21(() => {
13454
+ useEffect23(() => {
13284
13455
  if (!isOpen) return;
13285
- const handleKeyDown = (e) => {
13456
+ const handler = (e) => {
13286
13457
  if (e.key === "Escape") {
13287
- if (pickingGroupId) {
13288
- setPickingGroupId(null);
13289
- } else {
13290
- onClose();
13291
- }
13458
+ onClose();
13292
13459
  e.preventDefault();
13293
13460
  e.stopPropagation();
13294
13461
  }
13295
13462
  };
13296
- window.addEventListener("keydown", handleKeyDown);
13297
- return () => window.removeEventListener("keydown", handleKeyDown);
13298
- }, [isOpen, onClose, pickingGroupId]);
13299
- const filtered = useMemo11(() => {
13300
- const term = searchTerm.toLowerCase().trim();
13301
- return allMentionableItems.filter((item) => {
13302
- if (!term) return true;
13303
- const nameMatch = item.name && item.name.toLowerCase().includes(term);
13304
- const descMatch = item.description && item.description.toLowerCase().includes(term);
13305
- let parentMatch = false;
13306
- if (item.type === "ancestry") {
13307
- const parentName = nodeNamesMap.get(String(item.ancestral_node)) || "";
13308
- parentMatch = parentName.toLowerCase().includes(term);
13309
- }
13310
- return nameMatch || descMatch || parentMatch;
13311
- });
13312
- }, [allMentionableItems, searchTerm, nodeNamesMap]);
13463
+ window.addEventListener("keydown", handler);
13464
+ return () => window.removeEventListener("keydown", handler);
13465
+ }, [isOpen, onClose]);
13313
13466
  const handleAddRootGroup = () => {
13314
- const newGroup = {
13315
- id: v4_default(),
13316
- text: "",
13317
- ancestries: [],
13318
- children: []
13319
- };
13320
- setGroups((prev) => [newGroup, ...prev]);
13467
+ setGroups((prev) => [{ id: uuidv411(), content: [], children: [] }, ...prev]);
13321
13468
  };
13322
13469
  const handleAddSubgroup = (parentId) => {
13323
- const newGroup = {
13324
- id: v4_default(),
13325
- text: "",
13326
- ancestries: [],
13327
- children: []
13328
- };
13329
- const addRecursive = (list) => {
13330
- return list.map((g) => {
13331
- if (g.id === parentId) {
13332
- return { ...g, children: [newGroup, ...g.children] };
13333
- }
13334
- return { ...g, children: addRecursive(g.children) };
13335
- });
13336
- };
13337
- setGroups((prev) => addRecursive(prev));
13470
+ const newGroup = { id: uuidv411(), content: [], children: [] };
13471
+ const add = (list) => list.map(
13472
+ (g) => g.id === parentId ? { ...g, children: [newGroup, ...g.children] } : { ...g, children: add(g.children) }
13473
+ );
13474
+ setGroups((prev) => add(prev));
13338
13475
  };
13339
13476
  const handleUpdateGroup = (id, newData) => {
13340
- const updateRecursive = (list) => {
13341
- return list.map((g) => {
13342
- if (g.id === id) return newData;
13343
- return { ...g, children: updateRecursive(g.children) };
13344
- });
13345
- };
13346
- setGroups((prev) => updateRecursive(prev));
13477
+ const update = (list) => list.map(
13478
+ (g) => g.id === id ? newData : { ...g, children: update(g.children) }
13479
+ );
13480
+ setGroups((prev) => update(prev));
13347
13481
  };
13348
13482
  const handleDeleteGroup = (id) => {
13349
- const deleteRecursive = (list) => {
13350
- return list.filter((g) => g.id !== id).map((g) => ({
13351
- ...g,
13352
- children: deleteRecursive(g.children)
13353
- }));
13354
- };
13355
- setGroups((prev) => deleteRecursive(prev));
13483
+ const del = (list) => list.filter((g) => g.id !== id).map((g) => ({ ...g, children: del(g.children) }));
13484
+ setGroups((prev) => del(prev));
13356
13485
  };
13357
13486
  const findGroupAndParent = (list, targetId, parent = null) => {
13358
13487
  for (let i = 0; i < list.length; i++) {
13359
- if (list[i].id === targetId) {
13488
+ if (list[i].id === targetId)
13360
13489
  return { group: list[i], parent, index: i, siblings: list };
13361
- }
13362
13490
  if (list[i].children.length > 0) {
13363
13491
  const found = findGroupAndParent(list[i].children, targetId, list[i]);
13364
13492
  if (found) return found;
@@ -13368,257 +13496,86 @@ function AncestryBoard({
13368
13496
  };
13369
13497
  const handleIndent = (id) => {
13370
13498
  setGroups((prev) => {
13371
- const newList = JSON.parse(JSON.stringify(prev));
13372
- const found = findGroupAndParent(newList, id);
13499
+ const next = JSON.parse(JSON.stringify(prev));
13500
+ const found = findGroupAndParent(next, id);
13373
13501
  if (!found || found.index === 0) return prev;
13374
13502
  const { group, siblings, index } = found;
13375
- const prevSibling = siblings[index - 1];
13376
13503
  siblings.splice(index, 1);
13377
- prevSibling.children.push(group);
13378
- return newList;
13504
+ siblings[index - 1].children.push(group);
13505
+ return next;
13379
13506
  });
13380
13507
  };
13381
13508
  const handleOutdent = (id) => {
13382
13509
  setGroups((prev) => {
13383
- const newList = JSON.parse(JSON.stringify(prev));
13384
- const found = findGroupAndParent(newList, id);
13510
+ const next = JSON.parse(JSON.stringify(prev));
13511
+ const found = findGroupAndParent(next, id);
13385
13512
  if (!found || !found.parent) return prev;
13386
13513
  const { group, siblings, index, parent } = found;
13387
13514
  siblings.splice(index, 1);
13388
- const parentFound = findGroupAndParent(newList, parent.id);
13515
+ const parentFound = findGroupAndParent(next, parent.id);
13389
13516
  if (parentFound) {
13390
13517
  parentFound.siblings.splice(parentFound.index + 1, 0, group);
13391
13518
  } else {
13392
- newList.push(group);
13519
+ next.push(group);
13393
13520
  }
13394
- return newList;
13521
+ return next;
13395
13522
  });
13396
13523
  };
13397
- const handleRequestPick = (groupId) => {
13398
- setPickingGroupId((prev) => prev === groupId ? null : groupId);
13399
- };
13400
- const handleSelectAncestry = (item) => {
13401
- if (pickingGroupId) {
13402
- setGroups((prev) => {
13403
- const addRecursive = (list) => {
13404
- return list.map((g) => {
13405
- if (g.id === pickingGroupId) {
13406
- const currentId = item.id;
13407
- const exists = g.ancestries.some(
13408
- (a) => (a.id || a.ancestry_id) === currentId && a.type === item.type
13409
- );
13410
- if (exists) return g;
13411
- return { ...g, ancestries: [...g.ancestries, item] };
13412
- }
13413
- return { ...g, children: addRecursive(g.children) };
13414
- });
13415
- };
13416
- return addRecursive(prev);
13417
- });
13418
- setPickingGroupId(null);
13419
- } else {
13420
- let fullItem = item;
13421
- if (item.type === "ancestry" || !item.type) {
13422
- fullItem = availableAncestries.find(
13423
- (a) => String(a.ancestry_id) === String(item.id || item.ancestry_id)
13424
- ) || item;
13425
- } else {
13426
- fullItem = availableNodes.find(
13427
- (n) => String(n.id) === String(item.id)
13428
- ) || item;
13429
- }
13430
- onSelect(fullItem);
13431
- }
13432
- };
13433
- const handlePlayFromGroup = (item) => {
13434
- let fullItem = item;
13435
- if (item.type === "ancestry" || !item.type) {
13436
- fullItem = availableAncestries.find(
13437
- (a) => String(a.ancestry_id) === String(item.id || item.ancestry_id)
13438
- ) || item;
13439
- } else {
13440
- fullItem = availableNodes.find(
13441
- (n) => String(n.id) === String(item.id)
13442
- ) || item;
13443
- }
13444
- if (fullItem && onSelect) {
13445
- onSelect(fullItem);
13446
- }
13447
- };
13448
- const handleRemoveAncestryFromGroup = (groupId, itemId) => {
13449
- setGroups((prev) => {
13450
- const removeRecursive = (list) => {
13451
- return list.map((g) => {
13452
- if (g.id === groupId) {
13453
- return {
13454
- ...g,
13455
- ancestries: g.ancestries.filter(
13456
- (a) => (a.id || a.ancestry_id) !== itemId
13457
- )
13458
- };
13459
- }
13460
- return { ...g, children: removeRecursive(g.children) };
13461
- });
13462
- };
13463
- return removeRecursive(prev);
13464
- });
13524
+ const handleMentionClick = (item) => {
13525
+ if (onSelect) onSelect(item);
13465
13526
  };
13466
13527
  if (!isOpen) return null;
13467
- return /* @__PURE__ */ React26.createElement(
13528
+ return /* @__PURE__ */ React28.createElement(
13468
13529
  "div",
13469
13530
  {
13470
13531
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
13471
13532
  onClick: onClose
13472
13533
  },
13473
- /* @__PURE__ */ React26.createElement(
13534
+ /* @__PURE__ */ React28.createElement(
13474
13535
  "div",
13475
13536
  {
13476
13537
  className: "bg-slate-950 border border-white/10 rounded-xl w-[98vw] h-[97vh] flex flex-col shadow-2xl overflow-hidden animate-in fade-in zoom-in-95 duration-200",
13477
13538
  onClick: (e) => e.stopPropagation()
13478
13539
  },
13479
- /* @__PURE__ */ React26.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React26.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ React26.createElement(FiLayers6, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React26.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(
13480
- FiLoader5,
13481
- {
13482
- className: "animate-spin text-indigo-400",
13483
- size: 12
13484
- }
13485
- ), /* @__PURE__ */ React26.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ React26.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ React26.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ React26.createElement("span", { className: "text-xs text-indigo-300 font-medium animate-pulse hidden sm:inline-block mr-2" }, "Selecione na lateral..."), canEdit && /* @__PURE__ */ React26.createElement(
13540
+ /* @__PURE__ */ React28.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React28.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ React28.createElement(FiLayers7, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React28.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(FiLoader5, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ React28.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ React28.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ React28.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-3" }, canEdit && /* @__PURE__ */ React28.createElement(
13486
13541
  "button",
13487
13542
  {
13488
13543
  onClick: handleAddRootGroup,
13489
- className: "\n flex items-center gap-2 px-3 py-1.5 \n bg-white/5 hover:bg-white/10 \n border border-white/10 hover:border-white/20\n backdrop-blur-sm\n text-slate-200 hover:text-white\n rounded-md transition-all duration-200\n text-xs font-medium shadow-sm\n "
13544
+ className: "flex items-center gap-2 px-3 py-1.5 bg-white/5 hover:bg-white/10 border border-white/10 hover:border-white/20 backdrop-blur-sm text-slate-200 hover:text-white rounded-md transition-all duration-200 text-xs font-medium shadow-sm"
13490
13545
  },
13491
- /* @__PURE__ */ React26.createElement(FiPlus10, { size: 14, className: "text-indigo-400" }),
13492
- /* @__PURE__ */ React26.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13493
- ), /* @__PURE__ */ React26.createElement(
13546
+ /* @__PURE__ */ React28.createElement(FiPlus10, { size: 14, className: "text-indigo-400" }),
13547
+ /* @__PURE__ */ React28.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13548
+ ), /* @__PURE__ */ React28.createElement(
13494
13549
  "button",
13495
13550
  {
13496
13551
  onClick: onClose,
13497
13552
  className: "w-8 h-8 rounded-lg flex items-center justify-center text-slate-400 hover:text-white hover:bg-white/10 transition-colors"
13498
13553
  },
13499
- "\xD7"
13554
+ /* @__PURE__ */ React28.createElement(FiX8, { size: 16 })
13500
13555
  ))),
13501
- /* @__PURE__ */ React26.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React26.createElement(
13502
- "div",
13503
- {
13504
- className: `
13505
- flex flex-col border-r border-white/10 transition-all duration-300 flex-none
13506
- ${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
13507
- min-w-[280px] max-w-[500px] bg-slate-900
13508
- `
13509
- },
13510
- /* @__PURE__ */ React26.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ React26.createElement("div", { className: "relative group" }, /* @__PURE__ */ React26.createElement(
13511
- FiSearch8,
13512
- {
13513
- className: `absolute left-3 top-1/2 -translate-y-1/2 transition-colors ${pickingGroupId ? "text-indigo-400" : "text-slate-500 group-focus-within:text-indigo-400"}`
13514
- }
13515
- ), /* @__PURE__ */ React26.createElement(
13516
- "input",
13517
- {
13518
- type: "text",
13519
- placeholder: pickingGroupId ? "Pesquise para adicionar..." : "Pesquisar (Ancestralidades e Nodes)",
13520
- className: `
13521
- w-full rounded-md pl-9 pr-4 py-2 text-sm transition-all focus:outline-none focus:ring-1 focus:ring-indigo-500 border
13522
- ${pickingGroupId ? "bg-indigo-950/30 border-indigo-500/30 text-white placeholder-indigo-300/50" : "bg-slate-950 border-white/10 text-slate-200 placeholder-slate-600"}
13523
- `,
13524
- value: searchTerm,
13525
- onChange: (e) => setSearchTerm(e.target.value),
13526
- autoFocus: !pickingGroupId
13527
- }
13528
- ))),
13529
- /* @__PURE__ */ React26.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((item) => {
13530
- const isPicking = !!pickingGroupId;
13531
- const isQuest = item.type === "quest";
13532
- const isVersion = item.type === "version";
13533
- const isNode = item.type === "node";
13534
- let Icon = FiLayers6;
13535
- let colorClass = "bg-slate-800 text-indigo-400 border-white/5";
13536
- let pickingColorClass = "bg-indigo-500 text-white border-indigo-400";
13537
- let hoverClass = "hover:bg-indigo-600/10 hover:border-indigo-500/30";
13538
- let badge = null;
13539
- if (isQuest) {
13540
- Icon = FiCheckSquare3;
13541
- colorClass = "bg-slate-800 text-amber-400 border-white/5";
13542
- pickingColorClass = "bg-amber-500 text-white border-amber-400";
13543
- hoverClass = "hover:bg-amber-500/10 hover:border-amber-500/30";
13544
- badge = "Quest";
13545
- } else if (isVersion) {
13546
- Icon = FiGitBranch3;
13547
- colorClass = "bg-slate-800 text-purple-400 border-white/5";
13548
- pickingColorClass = "bg-purple-500 text-white border-purple-400";
13549
- hoverClass = "hover:bg-purple-500/10 hover:border-purple-500/30";
13550
- badge = "Ver";
13551
- } else if (isNode) {
13552
- Icon = FiBox;
13553
- colorClass = "bg-slate-800 text-emerald-400 border-white/5";
13554
- pickingColorClass = "bg-emerald-500 text-white border-emerald-400";
13555
- hoverClass = "hover:bg-emerald-500/10 hover:border-emerald-500/30";
13556
- badge = "Node";
13557
- }
13558
- return /* @__PURE__ */ React26.createElement(
13559
- "div",
13560
- {
13561
- key: `${item.type}-${item.id}`,
13562
- onClick: () => {
13563
- if (isPicking) handleSelectAncestry(item);
13564
- },
13565
- className: `
13566
- group relative flex items-start gap-3 p-3 text-left rounded-lg border transition-all duration-200
13567
- ${isPicking ? `border-indigo-500/30 bg-indigo-500/5 hover:bg-indigo-500/20 hover:border-indigo-400 cursor-pointer` : `border-white/5 bg-slate-800/40 ${hoverClass} cursor-default`}
13568
- `
13569
- },
13570
- /* @__PURE__ */ React26.createElement(
13571
- "div",
13572
- {
13573
- className: `
13574
- mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
13575
- ${isPicking ? pickingColorClass : `${colorClass} group-hover:bg-opacity-80`}
13576
- `
13577
- },
13578
- isPicking ? /* @__PURE__ */ React26.createElement(FiPlus10, { size: 16 }) : /* @__PURE__ */ React26.createElement(Icon, { size: 14 })
13579
- ),
13580
- /* @__PURE__ */ React26.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ React26.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, item.name || "Sem Nome"), badge && /* @__PURE__ */ React26.createElement("span", { className: `text-[9px] px-1 py-0.5 rounded ${isQuest ? "bg-amber-500/10 text-amber-400" : isVersion ? "bg-purple-500/10 text-purple-400" : "bg-emerald-500/10 text-emerald-400"} border border-current opacity-50` }, badge), item.is_private && /* @__PURE__ */ React26.createElement("span", { className: "text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-300 border border-amber-500/20" }, "Priv")), item.type === "ancestry" && /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ React26.createElement(FiCornerUpRight4, { size: 10 }), /* @__PURE__ */ React26.createElement("span", { className: "truncate max-w-[120px]" }, nodeNamesMap.get(String(item.ancestral_node)) || "Node Desconhecido")), item.description && /* @__PURE__ */ React26.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, item.description)),
13581
- !isPicking && /* @__PURE__ */ React26.createElement(
13582
- "button",
13583
- {
13584
- onClick: (e) => {
13585
- e.stopPropagation();
13586
- handleSelectAncestry(item);
13587
- },
13588
- className: "absolute right-2 bottom-2 opacity-0 group-hover:opacity-100 transition-all duration-300 transform translate-y-2 group-hover:translate-y-0 z-10",
13589
- title: "Renderizar / Focar"
13590
- },
13591
- /* @__PURE__ */ React26.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ React26.createElement(FiPlay, { size: 14, className: "ml-0.5" }))
13592
- )
13593
- );
13594
- }))
13595
- ), /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ React26.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-3 border-2 border-dashed border-white/5 rounded-xl m-4 bg-slate-900/20" }, /* @__PURE__ */ React26.createElement(FiLayers6, { size: 24, className: "opacity-20" }), /* @__PURE__ */ React26.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ React26.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ React26.createElement(React26.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ React26.createElement(
13556
+ /* @__PURE__ */ React28.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar bg-slate-950/30 p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-3 border-2 border-dashed border-white/5 rounded-xl m-4 bg-slate-900/20" }, /* @__PURE__ */ React28.createElement(FiLayers7, { size: 24, className: "opacity-20" }), /* @__PURE__ */ React28.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ React28.createElement(React28.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ React28.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ React28.createElement(React28.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ React28.createElement(
13596
13557
  GroupItem,
13597
13558
  {
13598
13559
  key: group.id,
13599
13560
  index,
13600
13561
  group,
13601
- siblings: groups,
13602
13562
  onUpdate: handleUpdateGroup,
13603
13563
  onDelete: handleDeleteGroup,
13604
13564
  onAddSubgroup: handleAddSubgroup,
13605
13565
  onIndent: handleIndent,
13606
13566
  onOutdent: handleOutdent,
13607
- onRemoveAncestry: handleRemoveAncestryFromGroup,
13608
- onRequestPickAncestry: handleRequestPick,
13609
- pickingGroupId,
13610
- onPlayAncestry: handlePlayFromGroup,
13611
- availableIds,
13567
+ searchItems: allSearchableItems,
13568
+ onMentionClick: handleMentionClick,
13612
13569
  canEdit
13613
13570
  }
13614
- ))))),
13615
- /* @__PURE__ */ React26.createElement("div", { className: "px-5 py-2 border-t border-white/10 bg-slate-950/50 text-xs text-slate-500 flex justify-between flex-shrink-0" }, /* @__PURE__ */ React26.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ React26.createElement("span", null, groups.length, " grupos raiz"))
13571
+ ))),
13572
+ /* @__PURE__ */ React28.createElement("div", { className: "px-5 py-2 border-t border-white/10 bg-slate-950/50 text-xs text-slate-500 flex justify-end flex-shrink-0" }, /* @__PURE__ */ React28.createElement("span", null, groups.length, " grupos raiz"))
13616
13573
  )
13617
13574
  );
13618
13575
  }
13619
13576
 
13620
13577
  // src/components/MilestoneManager.jsx
13621
- import React27, { useState as useState26 } from "react";
13578
+ import React29, { useState as useState28 } from "react";
13622
13579
  import { FiTarget as FiTarget4, FiPlus as FiPlus11, FiTrash2 as FiTrash24, FiX as FiX9, FiCheck as FiCheck12, FiPauseCircle, FiPlayCircle } from "react-icons/fi";
13623
13580
  function MilestoneManager({
13624
13581
  isOpen,
@@ -13627,7 +13584,7 @@ function MilestoneManager({
13627
13584
  onUpdateMilestones = () => {
13628
13585
  }
13629
13586
  }) {
13630
- const [newMilestoneName, setNewMilestoneName] = useState26("");
13587
+ const [newMilestoneName, setNewMilestoneName] = useState28("");
13631
13588
  const handleAddMilestone = () => {
13632
13589
  if (!newMilestoneName.trim()) return;
13633
13590
  const newMilestone = {
@@ -13652,27 +13609,27 @@ function MilestoneManager({
13652
13609
  };
13653
13610
  if (!isOpen) return null;
13654
13611
  const swallow = (e) => e.stopPropagation();
13655
- return /* @__PURE__ */ React27.createElement(
13612
+ return /* @__PURE__ */ React29.createElement(
13656
13613
  "div",
13657
13614
  {
13658
13615
  className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-slate-950/40 backdrop-blur-sm animate-in fade-in duration-300",
13659
13616
  onClick: onClose
13660
13617
  },
13661
- /* @__PURE__ */ React27.createElement(
13618
+ /* @__PURE__ */ React29.createElement(
13662
13619
  "div",
13663
13620
  {
13664
13621
  className: "w-full max-w-lg bg-slate-900/90 backdrop-blur-xl border border-white/10 rounded-2xl shadow-2xl flex flex-col max-h-[85vh] animate-in zoom-in-95 duration-300",
13665
13622
  onClick: swallow
13666
13623
  },
13667
- /* @__PURE__ */ React27.createElement("div", { className: "px-6 py-4 border-b border-white/10 flex items-center justify-between" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React27.createElement("div", { className: "p-2 rounded-lg bg-indigo-500/20 text-indigo-400" }, /* @__PURE__ */ React27.createElement(FiTarget4, { size: 20 })), /* @__PURE__ */ React27.createElement("div", null, /* @__PURE__ */ React27.createElement("h2", { className: "text-lg font-semibold text-slate-100" }, "Milestones"), /* @__PURE__ */ React27.createElement("p", { className: "text-xs text-slate-400" }, "Gerencie os marcos do seu cen\xE1rio"))), /* @__PURE__ */ React27.createElement(
13624
+ /* @__PURE__ */ React29.createElement("div", { className: "px-6 py-4 border-b border-white/10 flex items-center justify-between" }, /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React29.createElement("div", { className: "p-2 rounded-lg bg-indigo-500/20 text-indigo-400" }, /* @__PURE__ */ React29.createElement(FiTarget4, { size: 20 })), /* @__PURE__ */ React29.createElement("div", null, /* @__PURE__ */ React29.createElement("h2", { className: "text-lg font-semibold text-slate-100" }, "Milestones"), /* @__PURE__ */ React29.createElement("p", { className: "text-xs text-slate-400" }, "Gerencie os marcos do seu cen\xE1rio"))), /* @__PURE__ */ React29.createElement(
13668
13625
  "button",
13669
13626
  {
13670
13627
  onClick: onClose,
13671
13628
  className: "p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
13672
13629
  },
13673
- /* @__PURE__ */ React27.createElement(FiX9, { size: 20 })
13630
+ /* @__PURE__ */ React29.createElement(FiX9, { size: 20 })
13674
13631
  )),
13675
- /* @__PURE__ */ React27.createElement("div", { className: "px-6 py-5 bg-white/5 border-b border-white/5" }, /* @__PURE__ */ React27.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React27.createElement(
13632
+ /* @__PURE__ */ React29.createElement("div", { className: "px-6 py-5 bg-white/5 border-b border-white/5" }, /* @__PURE__ */ React29.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React29.createElement(
13676
13633
  "input",
13677
13634
  {
13678
13635
  type: "text",
@@ -13682,47 +13639,47 @@ function MilestoneManager({
13682
13639
  placeholder: "Adicionar novo milestone...",
13683
13640
  className: "flex-1 bg-slate-800/50 border border-white/10 rounded-xl px-4 py-2.5 text-sm text-slate-100 placeholder:text-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/40 focus:border-indigo-500/50 transition-all shadow-inner"
13684
13641
  }
13685
- ), /* @__PURE__ */ React27.createElement(
13642
+ ), /* @__PURE__ */ React29.createElement(
13686
13643
  "button",
13687
13644
  {
13688
13645
  onClick: handleAddMilestone,
13689
13646
  disabled: !newMilestoneName.trim(),
13690
13647
  className: "px-4 py-2.5 rounded-xl bg-indigo-600 hover:bg-indigo-500 disabled:opacity-30 disabled:cursor-not-allowed text-white text-sm font-medium transition-all flex items-center gap-2 shadow-lg shadow-indigo-500/20 active:scale-95"
13691
13648
  },
13692
- /* @__PURE__ */ React27.createElement(FiPlus11, { size: 18 }),
13649
+ /* @__PURE__ */ React29.createElement(FiPlus11, { size: 18 }),
13693
13650
  "Adicionar"
13694
13651
  ))),
13695
- /* @__PURE__ */ React27.createElement("div", { className: "flex-1 overflow-y-auto px-6 py-4 custom-scrollbar" }, milestones.length > 0 ? /* @__PURE__ */ React27.createElement("div", { className: "space-y-3" }, milestones.map((ms) => /* @__PURE__ */ React27.createElement(
13652
+ /* @__PURE__ */ React29.createElement("div", { className: "flex-1 overflow-y-auto px-6 py-4 custom-scrollbar" }, milestones.length > 0 ? /* @__PURE__ */ React29.createElement("div", { className: "space-y-3" }, milestones.map((ms) => /* @__PURE__ */ React29.createElement(
13696
13653
  "div",
13697
13654
  {
13698
13655
  key: ms.id,
13699
13656
  className: `group flex items-center justify-between p-4 rounded-xl border transition-all duration-200 ${ms.status === "active" ? "bg-slate-800/40 border-indigo-500/20 hover:border-indigo-500/40" : "bg-slate-900/40 border-white/5 opacity-60 grayscale-[0.3]"}`
13700
13657
  },
13701
- /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ React27.createElement(
13658
+ /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ React29.createElement(
13702
13659
  "div",
13703
13660
  {
13704
13661
  className: `w-2 h-2 rounded-full shrink-0 ${ms.status === "active" ? "bg-indigo-400 shadow-[0_0_8px_rgba(129,140,248,0.6)]" : "bg-slate-600"}`
13705
13662
  }
13706
- ), /* @__PURE__ */ React27.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React27.createElement("span", { className: `text-sm font-medium truncate ${ms.status === "active" ? "text-slate-100" : "text-slate-400 line-through"}` }, ms.name), /* @__PURE__ */ React27.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, ms.status === "active" ? "Ativo" : "Inativo"))),
13707
- /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React27.createElement(
13663
+ ), /* @__PURE__ */ React29.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React29.createElement("span", { className: `text-sm font-medium truncate ${ms.status === "active" ? "text-slate-100" : "text-slate-400 line-through"}` }, ms.name), /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, ms.status === "active" ? "Ativo" : "Inativo"))),
13664
+ /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React29.createElement(
13708
13665
  "button",
13709
13666
  {
13710
13667
  onClick: () => handleToggleMilestoneStatus(ms.id),
13711
13668
  className: `p-2 rounded-lg transition-all ${ms.status === "active" ? "hover:bg-slate-700 text-slate-400" : "hover:bg-indigo-500/20 text-indigo-400"}`,
13712
13669
  title: ms.status === "active" ? "Inativar" : "Ativar"
13713
13670
  },
13714
- ms.status === "active" ? /* @__PURE__ */ React27.createElement(FiPauseCircle, { size: 18 }) : /* @__PURE__ */ React27.createElement(FiPlayCircle, { size: 18 })
13715
- ), /* @__PURE__ */ React27.createElement(
13671
+ ms.status === "active" ? /* @__PURE__ */ React29.createElement(FiPauseCircle, { size: 18 }) : /* @__PURE__ */ React29.createElement(FiPlayCircle, { size: 18 })
13672
+ ), /* @__PURE__ */ React29.createElement(
13716
13673
  "button",
13717
13674
  {
13718
13675
  onClick: () => handleRemoveMilestone(ms.id),
13719
13676
  className: "p-2 rounded-lg hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-all",
13720
13677
  title: "Remover"
13721
13678
  },
13722
- /* @__PURE__ */ React27.createElement(FiTrash24, { size: 18 })
13679
+ /* @__PURE__ */ React29.createElement(FiTrash24, { size: 18 })
13723
13680
  ))
13724
- ))) : /* @__PURE__ */ React27.createElement("div", { className: "flex flex-col items-center justify-center py-12 text-center" }, /* @__PURE__ */ React27.createElement("div", { className: "p-4 rounded-full bg-slate-800/30 text-slate-600 mb-4" }, /* @__PURE__ */ React27.createElement(FiTarget4, { size: 40 })), /* @__PURE__ */ React27.createElement("h3", { className: "text-slate-400 font-medium" }, "Nenhum milestone definido"), /* @__PURE__ */ React27.createElement("p", { className: "text-xs text-slate-600 max-w-[200px] mt-1 italic" }, "Defina marcos importantes para orientar o progresso do projeto."))),
13725
- /* @__PURE__ */ React27.createElement("div", { className: "px-6 py-4 border-t border-white/5 bg-slate-900/50 flex items-center justify-between rounded-b-2xl" }, /* @__PURE__ */ React27.createElement("div", { className: "flex gap-4" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React27.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Total:"), /* @__PURE__ */ React27.createElement("span", { className: "text-xs font-bold text-slate-300" }, milestones.length)), /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React27.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Ativos:"), /* @__PURE__ */ React27.createElement("span", { className: "text-xs font-bold text-indigo-400" }, milestones.filter((m) => m.status === "active").length))))
13681
+ ))) : /* @__PURE__ */ React29.createElement("div", { className: "flex flex-col items-center justify-center py-12 text-center" }, /* @__PURE__ */ React29.createElement("div", { className: "p-4 rounded-full bg-slate-800/30 text-slate-600 mb-4" }, /* @__PURE__ */ React29.createElement(FiTarget4, { size: 40 })), /* @__PURE__ */ React29.createElement("h3", { className: "text-slate-400 font-medium" }, "Nenhum milestone definido"), /* @__PURE__ */ React29.createElement("p", { className: "text-xs text-slate-600 max-w-[200px] mt-1 italic" }, "Defina marcos importantes para orientar o progresso do projeto."))),
13682
+ /* @__PURE__ */ React29.createElement("div", { className: "px-6 py-4 border-t border-white/5 bg-slate-900/50 flex items-center justify-between rounded-b-2xl" }, /* @__PURE__ */ React29.createElement("div", { className: "flex gap-4" }, /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Total:"), /* @__PURE__ */ React29.createElement("span", { className: "text-xs font-bold text-slate-300" }, milestones.length)), /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Ativos:"), /* @__PURE__ */ React29.createElement("span", { className: "text-xs font-bold text-indigo-400" }, milestones.filter((m) => m.status === "active").length))))
13726
13683
  )
13727
13684
  );
13728
13685
  }
@@ -13808,13 +13765,13 @@ function XViewScene({
13808
13765
  check_user_permission,
13809
13766
  get_view_members
13810
13767
  }) {
13811
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
13768
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
13812
13769
  const { data: session, status } = useSession();
13813
13770
  const router = useRouter();
13814
13771
  const searchParams = useSearchParams();
13815
13772
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
13816
13773
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
13817
- const viewParams = useMemo12(() => {
13774
+ const viewParams = useMemo13(() => {
13818
13775
  if (encryptedConfig) {
13819
13776
  const data = decryptData(encryptedConfig);
13820
13777
  if (data) {
@@ -13823,7 +13780,7 @@ function XViewScene({
13823
13780
  }
13824
13781
  return null;
13825
13782
  }, [encryptedConfig, session]);
13826
- useEffect22(() => {
13783
+ useEffect24(() => {
13827
13784
  async function verifyPermission() {
13828
13785
  if (!viewParams || !session || !check_user_permission) return;
13829
13786
  const { id, type, owner_id } = viewParams;
@@ -13860,65 +13817,65 @@ function XViewScene({
13860
13817
  setIsLoading(false);
13861
13818
  }
13862
13819
  }, [viewParams, session, status, check_user_permission]);
13863
- const sceneConfigId = useMemo12(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13864
- const ownerId = useMemo12(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13865
- const dbSaveUrl = useMemo12(() => {
13820
+ const sceneConfigId = useMemo13(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13821
+ const ownerId = useMemo13(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13822
+ const dbSaveUrl = useMemo13(() => {
13866
13823
  if (ownerId && sceneConfigId) {
13867
13824
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
13868
13825
  }
13869
13826
  return null;
13870
13827
  }, [ownerId, sceneConfigId]);
13871
- const sceneSaveUrl = useMemo12(() => {
13828
+ const sceneSaveUrl = useMemo13(() => {
13872
13829
  if (ownerId && sceneConfigId) {
13873
13830
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
13874
13831
  }
13875
13832
  return null;
13876
13833
  }, [ownerId, sceneConfigId]);
13877
- const ancestry_save_url = useMemo12(() => {
13834
+ const ancestry_save_url = useMemo13(() => {
13878
13835
  if (ownerId && sceneConfigId) {
13879
13836
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
13880
13837
  }
13881
13838
  return null;
13882
13839
  }, [ownerId, sceneConfigId]);
13883
- const sceneDataRef = useRef19(null);
13884
- const parentDataRef = useRef19(null);
13885
- const ancestryDataRef = useRef19(null);
13886
- const [isLoading, setIsLoading] = useState27(true);
13887
- const [permissionStatus, setPermissionStatus] = useState27("loading");
13888
- const [userPermissionRole, setUserPermissionRole] = useState27(null);
13889
- const [viewMembers, setViewMembers] = useState27([]);
13890
- const [isInitialized, setIsInitialized] = useState27(false);
13891
- const [sceneVersion, setSceneVersion] = useState27(0);
13892
- const [contextMenu, setContextMenu] = useState27({
13840
+ const sceneDataRef = useRef20(null);
13841
+ const parentDataRef = useRef20(null);
13842
+ const ancestryDataRef = useRef20(null);
13843
+ const [isLoading, setIsLoading] = useState29(true);
13844
+ const [permissionStatus, setPermissionStatus] = useState29("loading");
13845
+ const [userPermissionRole, setUserPermissionRole] = useState29(null);
13846
+ const [viewMembers, setViewMembers] = useState29([]);
13847
+ const [isInitialized, setIsInitialized] = useState29(false);
13848
+ const [sceneVersion, setSceneVersion] = useState29(0);
13849
+ const [contextMenu, setContextMenu] = useState29({
13893
13850
  visible: false,
13894
13851
  x: 0,
13895
13852
  y: 0,
13896
13853
  nodeData: null
13897
13854
  });
13898
- const [multiContextMenu, setMultiContextMenu] = useState27({
13855
+ const [multiContextMenu, setMultiContextMenu] = useState29({
13899
13856
  visible: false,
13900
13857
  x: 0,
13901
13858
  y: 0,
13902
13859
  nodeIds: null
13903
13860
  });
13904
- const [relationshipMenu, setRelationshipMenu] = useState27({
13861
+ const [relationshipMenu, setRelationshipMenu] = useState29({
13905
13862
  visible: false,
13906
13863
  x: 0,
13907
13864
  y: 0,
13908
13865
  linkObject: null
13909
13866
  });
13910
- const [creationMode, setCreationMode] = useState27({
13867
+ const [creationMode, setCreationMode] = useState29({
13911
13868
  isActive: false,
13912
13869
  sourceNodeData: null
13913
13870
  });
13914
- const [versionMode, setVersionMode] = useState27({
13871
+ const [versionMode, setVersionMode] = useState29({
13915
13872
  isActive: false,
13916
13873
  sourceNodeData: null
13917
13874
  });
13918
- const [questMode, setQuestMode] = useState27({ isActive: false });
13919
- const [hasFocusedInitial, setHasFocusedInitial] = useState27(false);
13920
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState27(false);
13921
- const [ancestryMode, setAncestryMode] = useState27({
13875
+ const [questMode, setQuestMode] = useState29({ isActive: false });
13876
+ const [hasFocusedInitial, setHasFocusedInitial] = useState29(false);
13877
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState29(false);
13878
+ const [ancestryMode, setAncestryMode] = useState29({
13922
13879
  isActive: false,
13923
13880
  tree: null,
13924
13881
  selectedParentId: null,
@@ -13929,42 +13886,42 @@ function XViewScene({
13929
13886
  ancestryDescriptionSections: [],
13930
13887
  isAddingNodes: false
13931
13888
  });
13932
- const [readingMode, setReadingMode] = useState27({
13889
+ const [readingMode, setReadingMode] = useState29({
13933
13890
  isActive: false,
13934
13891
  ancestry: null,
13935
13892
  branchStack: [],
13936
13893
  autoAbstraction: false
13937
13894
  });
13938
- const [formPosition, setFormPosition] = useState27({
13895
+ const [formPosition, setFormPosition] = useState29({
13939
13896
  left: 16,
13940
13897
  top: 16,
13941
13898
  opacity: 0
13942
13899
  });
13943
- const [detailsNode, setDetailsNode] = useState27(null);
13944
- const [detailsLink, setDetailsLink] = useState27(null);
13945
- const [ancestryLinkDetails, setAncestryLinkDetails] = useState27(null);
13946
- const [imageViewer, setImageViewer] = useState27({
13900
+ const [detailsNode, setDetailsNode] = useState29(null);
13901
+ const [detailsLink, setDetailsLink] = useState29(null);
13902
+ const [ancestryLinkDetails, setAncestryLinkDetails] = useState29(null);
13903
+ const [imageViewer, setImageViewer] = useState29({
13947
13904
  visible: false,
13948
13905
  images: [],
13949
13906
  startIndex: 0
13950
13907
  });
13951
- const [editingAncestryRel, setEditingAncestryRel] = useState27({
13908
+ const [editingAncestryRel, setEditingAncestryRel] = useState29({
13952
13909
  visible: false,
13953
13910
  data: null,
13954
13911
  path: null
13955
13912
  });
13956
- const [isImportModalOpen, setIsImportModalOpen] = useState27(false);
13957
- const [importSuccessMessage, setImportSuccessMessage] = useState27("");
13958
- const [invalidTargetError, setInvalidTargetError] = useState27(null);
13959
- const [highlightedNodeId, setHighlightedNodeId] = useState27(null);
13960
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState27(false);
13961
- const [ancestryBoardData, setAncestryBoardData] = useState27([]);
13962
- const [isSidebarOpen, setIsSidebarOpen] = useState27(false);
13963
- const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState27(false);
13964
- const mountRef = useRef19(null);
13965
- const tooltipRef = useRef19(null);
13966
- const formRef = useRef19(null);
13967
- const stateRef = useRef19({
13913
+ const [isImportModalOpen, setIsImportModalOpen] = useState29(false);
13914
+ const [importSuccessMessage, setImportSuccessMessage] = useState29("");
13915
+ const [invalidTargetError, setInvalidTargetError] = useState29(null);
13916
+ const [highlightedNodeId, setHighlightedNodeId] = useState29(null);
13917
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState29(false);
13918
+ const [ancestryBoardData, setAncestryBoardData] = useState29([]);
13919
+ const [isSidebarOpen, setIsSidebarOpen] = useState29(false);
13920
+ const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState29(false);
13921
+ const mountRef = useRef20(null);
13922
+ const tooltipRef = useRef20(null);
13923
+ const formRef = useRef20(null);
13924
+ const stateRef = useRef20({
13968
13925
  readMode: {
13969
13926
  currentMaxIndex: 0,
13970
13927
  progressMap: {}
@@ -14028,10 +13985,10 @@ function XViewScene({
14028
13985
  minWidth: 320,
14029
13986
  maxWidth: maxReadPanelW
14030
13987
  });
14031
- useEffect22(() => {
13988
+ useEffect24(() => {
14032
13989
  stateRef.current.ancestry = ancestryMode;
14033
13990
  }, [ancestryMode]);
14034
- useEffect22(() => {
13991
+ useEffect24(() => {
14035
13992
  var _a2;
14036
13993
  if (!isInitialized) return;
14037
13994
  const map = /* @__PURE__ */ new Map();
@@ -14054,10 +14011,10 @@ function XViewScene({
14054
14011
  }
14055
14012
  stateRef.current.nodeIdToParentFileMap = map;
14056
14013
  }, [isInitialized, sceneVersion]);
14057
- const handleNavigateBack = useCallback4(() => {
14014
+ const handleNavigateBack = useCallback5(() => {
14058
14015
  router.push("/dashboard/scenes");
14059
14016
  }, [router]);
14060
- const handleConfirmImport = useCallback4(
14017
+ const handleConfirmImport = useCallback5(
14061
14018
  async (importPayload) => {
14062
14019
  var _a2, _b2;
14063
14020
  let files = [];
@@ -14185,7 +14142,7 @@ function XViewScene({
14185
14142
  const handleOpenImageViewer = (images, startIndex) => {
14186
14143
  setImageViewer({ visible: true, images, startIndex });
14187
14144
  };
14188
- const tweenToTarget = useCallback4(
14145
+ const tweenToTarget = useCallback5(
14189
14146
  (target, zoomFactor = 1, forcedDirection = null) => {
14190
14147
  const { camera, controls, tweenGroup } = stateRef.current;
14191
14148
  if (!camera || !controls || !tweenGroup) return;
@@ -14211,7 +14168,7 @@ function XViewScene({
14211
14168
  if (!t || typeof t.closest !== "function") return false;
14212
14169
  return !!t.closest(".ui-overlay");
14213
14170
  };
14214
- const buildFullAncestryTree = useCallback4(
14171
+ const buildFullAncestryTree = useCallback5(
14215
14172
  (idTree, nodes, ancestries = []) => {
14216
14173
  if (!idTree) return null;
14217
14174
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
@@ -14296,7 +14253,7 @@ function XViewScene({
14296
14253
  },
14297
14254
  []
14298
14255
  );
14299
- const handleActivateTimeline = useCallback4(() => {
14256
+ const handleActivateTimeline = useCallback5(() => {
14300
14257
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
14301
14258
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
14302
14259
  while (timelineIntervalsGroup.children.length > 0) {
@@ -14456,7 +14413,7 @@ function XViewScene({
14456
14413
  }
14457
14414
  });
14458
14415
  }, []);
14459
- const handleVersionTimeline = useCallback4((sourceMesh, versionMeshes) => {
14416
+ const handleVersionTimeline = useCallback5((sourceMesh, versionMeshes) => {
14460
14417
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
14461
14418
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
14462
14419
  return;
@@ -14593,7 +14550,7 @@ function XViewScene({
14593
14550
  }
14594
14551
  });
14595
14552
  }, []);
14596
- useEffect22(() => {
14553
+ useEffect24(() => {
14597
14554
  async function fetchAllData(configPath, ownerId2) {
14598
14555
  var _a2, _b2;
14599
14556
  if (!get_scene_view_data) {
@@ -14698,12 +14655,12 @@ function XViewScene({
14698
14655
  focusNodeId,
14699
14656
  focusAncestryId
14700
14657
  ]);
14701
- const isNodeInView = useCallback4((id) => {
14658
+ const isNodeInView = useCallback5((id) => {
14702
14659
  const key = String(id);
14703
14660
  const objs = stateRef.current.nodeObjects || {};
14704
14661
  return !!objs[key];
14705
14662
  }, []);
14706
- const addOrUpdateNodeMesh = useCallback4(
14663
+ const addOrUpdateNodeMesh = useCallback5(
14707
14664
  (nodeData, position, suppressVersionUpdate = false, forceShowQuestDate = false) => {
14708
14665
  const {
14709
14666
  graphGroup,
@@ -14744,7 +14701,7 @@ function XViewScene({
14744
14701
  },
14745
14702
  []
14746
14703
  );
14747
- const handleActivateQuestLens = useCallback4(({ assigneeId, status: status2, milestoneId }) => {
14704
+ const handleActivateQuestLens = useCallback5(({ assigneeId, status: status2, milestoneId }) => {
14748
14705
  var _a2;
14749
14706
  const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
14750
14707
  if (!nodeObjects || !tweenGroup || !graphGroup) return;
@@ -14958,7 +14915,7 @@ function XViewScene({
14958
14915
  camTween.start();
14959
14916
  }
14960
14917
  }, [addOrUpdateNodeMesh]);
14961
- useEffect22(() => {
14918
+ useEffect24(() => {
14962
14919
  if (!isInitialized || !sceneDataRef.current) return;
14963
14920
  const currentMount = mountRef.current;
14964
14921
  if (!currentMount) return;
@@ -15714,7 +15671,7 @@ function XViewScene({
15714
15671
  get_scene_view_data,
15715
15672
  save_view_data
15716
15673
  ]);
15717
- const handleGhostNodeImageChange = useCallback4((useImage, imageUrl) => {
15674
+ const handleGhostNodeImageChange = useCallback5((useImage, imageUrl) => {
15718
15675
  const {
15719
15676
  node: ghostNode,
15720
15677
  line: ghostLine,
@@ -15762,7 +15719,7 @@ function XViewScene({
15762
15719
  aura: newGhostNode.getObjectByName("aura")
15763
15720
  };
15764
15721
  }, []);
15765
- const handleGhostNodeIntensityChange = useCallback4((newIntensity) => {
15722
+ const handleGhostNodeIntensityChange = useCallback5((newIntensity) => {
15766
15723
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
15767
15724
  if (!ghostNode) return;
15768
15725
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -15783,7 +15740,7 @@ function XViewScene({
15783
15740
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
15784
15741
  }
15785
15742
  }, []);
15786
- const handleDetailNodeIntensityChange = useCallback4(
15743
+ const handleDetailNodeIntensityChange = useCallback5(
15787
15744
  (nodeId, newIntensity) => {
15788
15745
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
15789
15746
  if (!mesh) return;
@@ -15939,7 +15896,7 @@ function XViewScene({
15939
15896
  mountRef.current.style.cursor = "default";
15940
15897
  }
15941
15898
  };
15942
- const handleAncestryTreeUpdate = useCallback4((newTree, extraData = null) => {
15899
+ const handleAncestryTreeUpdate = useCallback5((newTree, extraData = null) => {
15943
15900
  setAncestryMode((prev) => {
15944
15901
  const prevTreeStr = JSON.stringify(prev.tree);
15945
15902
  const newTreeStr = JSON.stringify(newTree);
@@ -15962,7 +15919,7 @@ function XViewScene({
15962
15919
  };
15963
15920
  });
15964
15921
  }, []);
15965
- const actionHandlerContext = useMemo12(
15922
+ const actionHandlerContext = useMemo13(
15966
15923
  () => {
15967
15924
  var _a2;
15968
15925
  return {
@@ -16023,7 +15980,7 @@ function XViewScene({
16023
15980
  const handleStartVersioning = (nodeData) => {
16024
15981
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
16025
15982
  };
16026
- const handleStartQuestQuick = useCallback4((questNode) => {
15983
+ const handleStartQuestQuick = useCallback5((questNode) => {
16027
15984
  var _a2, _b2, _c2;
16028
15985
  if (!questNode || !actionHandlerContext) return;
16029
15986
  const allParentNodes = Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
@@ -16058,7 +16015,7 @@ function XViewScene({
16058
16015
  }
16059
16016
  setDetailsNode(updatedNode);
16060
16017
  }, [session, actionHandlerContext]);
16061
- const handleFinishQuestQuick = useCallback4((questNode) => {
16018
+ const handleFinishQuestQuick = useCallback5((questNode) => {
16062
16019
  var _a2, _b2, _c2, _d2;
16063
16020
  if (!questNode || !actionHandlerContext) return;
16064
16021
  const {
@@ -16132,7 +16089,7 @@ function XViewScene({
16132
16089
  setDetailsNode(null);
16133
16090
  }
16134
16091
  }, [session, actionHandlerContext, viewMembers, detailsNode]);
16135
- const handleCancelQuest = useCallback4(() => {
16092
+ const handleCancelQuest = useCallback5(() => {
16136
16093
  const { graphGroup, ghostElements } = stateRef.current;
16137
16094
  if (ghostElements.node && graphGroup) {
16138
16095
  if (ghostElements.node.userData.labelObject) {
@@ -16191,13 +16148,15 @@ function XViewScene({
16191
16148
  try {
16192
16149
  await actions.save_view_data(sceneSaveUrl2, sceneFileData);
16193
16150
  sceneDataRef2.current.quest_counter = currentCounter + 1;
16194
- sceneDataRef2.current.quest_nodes = sceneFileData.quest_nodes;
16195
- sceneDataRef2.current.quest_links = sceneFileData.quest_links;
16196
16151
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
16197
16152
  parentFileId: sceneConfigId2,
16198
16153
  ownerId: ownerId2,
16199
16154
  datasetName: "Quests Internas (View)"
16200
16155
  });
16156
+ sceneDataRef2.current.quest_nodes = [...graphDataRef.current[sceneConfigId2].nodes];
16157
+ if (parentDataRef.current[sceneConfigId2]) {
16158
+ parentDataRef.current[sceneConfigId2].nodes = [...graphDataRef.current[sceneConfigId2].nodes];
16159
+ }
16201
16160
  const finalPosition = stateRef2.current.ghostElements.node ? stateRef2.current.ghostElements.node.position.clone() : stateRef2.current.controls.target.clone();
16202
16161
  const { graphGroup, ghostElements } = stateRef2.current;
16203
16162
  if (ghostElements.node && graphGroup) {
@@ -16287,7 +16246,7 @@ function XViewScene({
16287
16246
  }
16288
16247
  userActionHandlers.handleCancelConnection(context);
16289
16248
  };
16290
- const handleClearAncestryVisuals = useCallback4((ancestryId) => {
16249
+ const handleClearAncestryVisuals = useCallback5((ancestryId) => {
16291
16250
  const { renderedAncestries, ancestryGroup } = stateRef.current;
16292
16251
  const renderIndex = renderedAncestries.findIndex(
16293
16252
  (a) => String(a.id) === String(ancestryId)
@@ -16305,7 +16264,7 @@ function XViewScene({
16305
16264
  );
16306
16265
  }
16307
16266
  }, []);
16308
- const handleRenderAncestry = useCallback4(
16267
+ const handleRenderAncestry = useCallback5(
16309
16268
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
16310
16269
  setContextMenu(
16311
16270
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16799,7 +16758,7 @@ function XViewScene({
16799
16758
  ancestryMode.isActive
16800
16759
  ]
16801
16760
  );
16802
- const handleRenderAbstractionTree = useCallback4(
16761
+ const handleRenderAbstractionTree = useCallback5(
16803
16762
  (ancestryObject, targetNodeId = null) => {
16804
16763
  setContextMenu(
16805
16764
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16887,7 +16846,7 @@ function XViewScene({
16887
16846
  handleClearAncestryVisuals
16888
16847
  ]
16889
16848
  );
16890
- const handleReadModeBranchNav = useCallback4(
16849
+ const handleReadModeBranchNav = useCallback5(
16891
16850
  (nodeId, action, direction = "right") => {
16892
16851
  const { ancestry, branchStack } = readingMode;
16893
16852
  if (!ancestry || !ancestry.tree) return;
@@ -17065,13 +17024,13 @@ function XViewScene({
17065
17024
  },
17066
17025
  [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
17067
17026
  );
17068
- const handleReadModeHighlight = useCallback4((nodeId) => {
17027
+ const handleReadModeHighlight = useCallback5((nodeId) => {
17069
17028
  if (stateRef.current.highlightedNodeId !== nodeId) {
17070
17029
  stateRef.current.highlightedNodeId = nodeId;
17071
17030
  }
17072
17031
  setHighlightedNodeId(nodeId);
17073
17032
  }, []);
17074
- const activeNodeBranches = useMemo12(() => {
17033
+ const activeNodeBranches = useMemo13(() => {
17075
17034
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
17076
17035
  return null;
17077
17036
  const fullTree = buildFullAncestryTree(
@@ -17115,7 +17074,7 @@ function XViewScene({
17115
17074
  readingMode.branchStack,
17116
17075
  ancestryDataRef.current
17117
17076
  ]);
17118
- const backNavigationInfo = useMemo12(() => {
17077
+ const backNavigationInfo = useMemo13(() => {
17119
17078
  const { branchStack } = readingMode;
17120
17079
  if (!branchStack || branchStack.length === 0) return null;
17121
17080
  const lastStep = branchStack[branchStack.length - 1];
@@ -17126,7 +17085,7 @@ function XViewScene({
17126
17085
  name: "Voltar para anterior"
17127
17086
  };
17128
17087
  }, [readingMode.branchStack]);
17129
- const getReadModeDisplayContext = useMemo12(() => {
17088
+ const getReadModeDisplayContext = useMemo13(() => {
17130
17089
  const { ancestry, branchStack } = readingMode;
17131
17090
  if (!ancestry) return null;
17132
17091
  if (branchStack.length === 0) {
@@ -17169,7 +17128,7 @@ function XViewScene({
17169
17128
  customProperties: branchProps
17170
17129
  };
17171
17130
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
17172
- const readModeAbstractionTree = useMemo12(() => {
17131
+ const readModeAbstractionTree = useMemo13(() => {
17173
17132
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
17174
17133
  return null;
17175
17134
  }
@@ -17188,7 +17147,7 @@ function XViewScene({
17188
17147
  buildFullAncestryTree,
17189
17148
  sceneVersion
17190
17149
  ]);
17191
- const handleStartReadingAncestry = useCallback4(
17150
+ const handleStartReadingAncestry = useCallback5(
17192
17151
  async (ancestryObject, renderMode = "full") => {
17193
17152
  setContextMenu(
17194
17153
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17231,7 +17190,7 @@ function XViewScene({
17231
17190
  },
17232
17191
  [handleRenderAncestry, handleRenderAbstractionTree]
17233
17192
  );
17234
- const handleReadModeSectionChange = useCallback4(
17193
+ const handleReadModeSectionChange = useCallback5(
17235
17194
  (activeSectionId) => {
17236
17195
  const { ancestry, branchStack } = readingMode;
17237
17196
  if (!ancestry || !readingMode.isActive) return;
@@ -17316,10 +17275,10 @@ function XViewScene({
17316
17275
  ancestryDataRef.current
17317
17276
  ]
17318
17277
  );
17319
- const handleCloseReadMode = useCallback4(() => {
17278
+ const handleCloseReadMode = useCallback5(() => {
17320
17279
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
17321
17280
  }, []);
17322
- const handleAncestrySectionChange = useCallback4(
17281
+ const handleAncestrySectionChange = useCallback5(
17323
17282
  (activeSectionId, ancestryOverride = null, rotation = 0) => {
17324
17283
  var _a2, _b2;
17325
17284
  const currentMode = stateRef.current.ancestry;
@@ -17381,7 +17340,7 @@ function XViewScene({
17381
17340
  },
17382
17341
  [handleRenderAncestry]
17383
17342
  );
17384
- const handleEditAncestry = useCallback4(
17343
+ const handleEditAncestry = useCallback5(
17385
17344
  async (ancestryObject) => {
17386
17345
  setContextMenu(
17387
17346
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17436,7 +17395,7 @@ function XViewScene({
17436
17395
  const handleSelectAncestryParent = (nodeId) => {
17437
17396
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
17438
17397
  };
17439
- const handleRemoveFromAncestry = useCallback4((pathToRemove) => {
17398
+ const handleRemoveFromAncestry = useCallback5((pathToRemove) => {
17440
17399
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
17441
17400
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
17442
17401
  return;
@@ -17461,7 +17420,7 @@ function XViewScene({
17461
17420
  return { ...prev, tree: newTree };
17462
17421
  });
17463
17422
  }, []);
17464
- const handleSaveAncestry = useCallback4(
17423
+ const handleSaveAncestry = useCallback5(
17465
17424
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
17466
17425
  const treeToUse = treeOverride || ancestryMode.tree;
17467
17426
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -17697,7 +17656,7 @@ function XViewScene({
17697
17656
  });
17698
17657
  setEditingAncestryRel({ visible: false, data: null, path: null });
17699
17658
  };
17700
- const handleDeleteAncestry = useCallback4(
17659
+ const handleDeleteAncestry = useCallback5(
17701
17660
  async (ancestryIdToDelete) => {
17702
17661
  if (!ancestryIdToDelete) {
17703
17662
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -17779,28 +17738,70 @@ function XViewScene({
17779
17738
  },
17780
17739
  [save_view_data, delete_file_action]
17781
17740
  );
17782
- const handleOpenAncestryBoard = useCallback4(() => {
17741
+ const handleOpenAncestryBoard = useCallback5(() => {
17783
17742
  setIsAncestryBoardOpen(true);
17784
17743
  }, []);
17785
- const handleSelectAncestryFromBoard = useCallback4(
17744
+ const allAvailableNodes = useMemo13(() => {
17745
+ if (!parentDataRef.current) return [];
17746
+ return Object.values(parentDataRef.current).flatMap(
17747
+ (fileData) => fileData.nodes || []
17748
+ );
17749
+ }, [sceneVersion, isInitialized]);
17750
+ const allAvailableAncestries = useMemo13(() => {
17751
+ return ancestryDataRef.current || [];
17752
+ }, [sceneVersion, isInitialized]);
17753
+ const handleOpenReference = useCallback5(
17754
+ (referenceData) => {
17755
+ const { type, id } = referenceData;
17756
+ if (type === "node") {
17757
+ const targetNode = allAvailableNodes.find(
17758
+ (n) => String(n.id) === String(id)
17759
+ );
17760
+ if (targetNode) {
17761
+ setAncestryLinkDetails(null);
17762
+ setDetailsLink(null);
17763
+ setDetailsNode(targetNode);
17764
+ const sceneMesh = stateRef.current.nodeObjects[String(id)];
17765
+ if (sceneMesh) {
17766
+ tweenToTarget(sceneMesh);
17767
+ }
17768
+ } else {
17769
+ alert("Node original n\xE3o encontrado neste contexto.");
17770
+ }
17771
+ } else if (type === "ancestry") {
17772
+ const targetAncestry = allAvailableAncestries.find(
17773
+ (a) => String(a.ancestry_id) === String(id)
17774
+ );
17775
+ if (targetAncestry) {
17776
+ setDetailsNode(null);
17777
+ setDetailsLink(null);
17778
+ setAncestryLinkDetails(null);
17779
+ handleEditAncestry(targetAncestry);
17780
+ } else {
17781
+ alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17782
+ }
17783
+ }
17784
+ },
17785
+ [
17786
+ allAvailableNodes,
17787
+ allAvailableAncestries,
17788
+ handleEditAncestry,
17789
+ tweenToTarget
17790
+ ]
17791
+ );
17792
+ const handleSelectAncestryFromBoard = useCallback5(
17786
17793
  (item) => {
17787
17794
  setIsAncestryBoardOpen(false);
17788
17795
  setIsSidebarOpen(false);
17789
- if (item.type === "ancestry" || !item.type) {
17796
+ if (item.type === "ancestry") {
17790
17797
  handleStartReadingAncestry(item);
17791
17798
  } else {
17792
- const nodeId = String(item.id);
17793
- const sceneMesh = stateRef.current.nodeObjects[nodeId];
17794
- if (sceneMesh) {
17795
- tweenToTarget(sceneMesh);
17796
- } else {
17797
- console.warn("Objeto n\xE3o encontrado na cena para foco:", nodeId);
17798
- }
17799
+ handleOpenReference({ type: "node", id: item.id });
17799
17800
  }
17800
17801
  },
17801
- [handleStartReadingAncestry, tweenToTarget]
17802
+ [handleStartReadingAncestry, handleOpenReference]
17802
17803
  );
17803
- const handleSaveAncestryBoard = useCallback4(
17804
+ const handleSaveAncestryBoard = useCallback5(
17804
17805
  async (groups) => {
17805
17806
  if (!sceneConfigId || !viewParams || !session) return;
17806
17807
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
@@ -17814,7 +17815,7 @@ function XViewScene({
17814
17815
  },
17815
17816
  [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
17816
17817
  );
17817
- const existingNodeTypes = useMemo12(() => {
17818
+ const existingNodeTypes = useMemo13(() => {
17818
17819
  if (!parentDataRef.current) {
17819
17820
  return [];
17820
17821
  }
@@ -17826,28 +17827,22 @@ function XViewScene({
17826
17827
  ).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
17827
17828
  return [...new Set(allTypes)];
17828
17829
  }, [parentDataRef.current, sceneVersion]);
17829
- const searchableDbNodes = useMemo12(() => {
17830
- var _a2;
17830
+ const searchableDbNodes = useMemo13(() => {
17831
17831
  if (!parentDataRef.current) {
17832
17832
  return [];
17833
17833
  }
17834
- const datasetsPool = Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17834
+ return Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17835
17835
  const datasetName = fileData.dataset_name || `Dataset #${dbId.substring(0, 6)}`;
17836
17836
  return (fileData.nodes || []).map((node) => ({
17837
17837
  ...node,
17838
17838
  dataset_name: datasetName
17839
17839
  }));
17840
+ }).filter((node) => {
17841
+ var _a2;
17842
+ return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
17840
17843
  });
17841
- const questsPool = (((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || []).map((node) => ({
17842
- ...node,
17843
- dataset_name: "Quests Internas (View)"
17844
- }));
17845
- return [...datasetsPool, ...questsPool].filter((node) => {
17846
- var _a3;
17847
- return !((_a3 = node.version_node) == null ? void 0 : _a3.is_version);
17848
- });
17849
- }, [parentDataRef.current, (_b = sceneDataRef.current) == null ? void 0 : _b.quest_nodes, sceneVersion]);
17850
- const handleAddExistingNode = useCallback4(
17844
+ }, [parentDataRef.current, sceneVersion]);
17845
+ const handleAddExistingNode = useCallback5(
17851
17846
  (nodeId) => {
17852
17847
  return userActionHandlers.handleAddExistingNodeById(
17853
17848
  actionHandlerContext,
@@ -17856,7 +17851,7 @@ function XViewScene({
17856
17851
  },
17857
17852
  [actionHandlerContext]
17858
17853
  );
17859
- const handleUpdateMilestones = useCallback4(
17854
+ const handleUpdateMilestones = useCallback5(
17860
17855
  async (newMilestones) => {
17861
17856
  var _a2, _b2, _c2;
17862
17857
  if (!sceneDataRef.current) return;
@@ -17902,7 +17897,7 @@ function XViewScene({
17902
17897
  viewParams == null ? void 0 : viewParams.type
17903
17898
  ]
17904
17899
  );
17905
- const handleSaveCurrentView = useCallback4(async () => {
17900
+ const handleSaveCurrentView = useCallback5(async () => {
17906
17901
  var _a2, _b2, _c2;
17907
17902
  const { nodeObjects, allLinks } = stateRef.current;
17908
17903
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
@@ -17945,61 +17940,13 @@ function XViewScene({
17945
17940
  console.error("Erro na chamada de save_view_data:", error);
17946
17941
  }
17947
17942
  }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
17948
- const allAvailableNodes = useMemo12(() => {
17949
- if (!parentDataRef.current) return [];
17950
- return Object.values(parentDataRef.current).flatMap(
17951
- (fileData) => fileData.nodes || []
17952
- );
17953
- }, [sceneVersion, isInitialized]);
17954
- const allAvailableAncestries = useMemo12(() => {
17955
- return ancestryDataRef.current || [];
17956
- }, [sceneVersion, isInitialized]);
17957
- const handleOpenReference = useCallback4(
17958
- (referenceData) => {
17959
- const { type, id } = referenceData;
17960
- if (type === "node") {
17961
- const targetNode = allAvailableNodes.find(
17962
- (n) => String(n.id) === String(id)
17963
- );
17964
- if (targetNode) {
17965
- setAncestryLinkDetails(null);
17966
- setDetailsLink(null);
17967
- setDetailsNode(targetNode);
17968
- const sceneMesh = stateRef.current.nodeObjects[String(id)];
17969
- if (sceneMesh) {
17970
- tweenToTarget(sceneMesh);
17971
- }
17972
- } else {
17973
- alert("Node original n\xE3o encontrado neste contexto.");
17974
- }
17975
- } else if (type === "ancestry") {
17976
- const targetAncestry = allAvailableAncestries.find(
17977
- (a) => String(a.ancestry_id) === String(id)
17978
- );
17979
- if (targetAncestry) {
17980
- setDetailsNode(null);
17981
- setDetailsLink(null);
17982
- setAncestryLinkDetails(null);
17983
- handleEditAncestry(targetAncestry);
17984
- } else {
17985
- alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17986
- }
17987
- }
17988
- },
17989
- [
17990
- allAvailableNodes,
17991
- allAvailableAncestries,
17992
- handleEditAncestry,
17993
- tweenToTarget
17994
- ]
17995
- );
17996
- const handleToggleAncestryAddMode = useCallback4(() => {
17943
+ const handleToggleAncestryAddMode = useCallback5(() => {
17997
17944
  setAncestryMode((prev) => ({
17998
17945
  ...prev,
17999
17946
  isAddingNodes: !prev.isAddingNodes
18000
17947
  }));
18001
17948
  }, []);
18002
- const handleFocusNode = useCallback4(
17949
+ const handleFocusNode = useCallback5(
18003
17950
  (nodeData) => {
18004
17951
  var _a2;
18005
17952
  if (!nodeData) return;
@@ -18015,7 +17962,7 @@ function XViewScene({
18015
17962
  },
18016
17963
  [tweenToTarget]
18017
17964
  );
18018
- const availableDatasets = useMemo12(() => {
17965
+ const availableDatasets = useMemo13(() => {
18019
17966
  if (!sceneDataRef.current || !parentDataRef.current) return [];
18020
17967
  return sceneDataRef.current.parent_dbs.map((db) => {
18021
17968
  var _a2;
@@ -18025,11 +17972,11 @@ function XViewScene({
18025
17972
  };
18026
17973
  });
18027
17974
  }, [sceneVersion, isInitialized]);
18028
- const sourceNodeDatasetId = creationMode.sourceNodeData ? (_c = stateRef.current.nodeIdToParentFileMap.get(
17975
+ const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(
18029
17976
  String(creationMode.sourceNodeData.id)
18030
- )) == null ? void 0 : _c.parentFileId : null;
17977
+ )) == null ? void 0 : _b.parentFileId : null;
18031
17978
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
18032
- useEffect22(() => {
17979
+ useEffect24(() => {
18033
17980
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
18034
17981
  const nodeObjects = stateRef.current.nodeObjects || {};
18035
17982
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -18052,7 +17999,7 @@ function XViewScene({
18052
17999
  hasFocusedInitial,
18053
18000
  tweenToTarget
18054
18001
  ]);
18055
- useEffect22(() => {
18002
+ useEffect24(() => {
18056
18003
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
18057
18004
  const ancestries = ancestryDataRef.current || [];
18058
18005
  const targetAncestry = ancestries.find(
@@ -18077,7 +18024,7 @@ function XViewScene({
18077
18024
  hasOpenedInitialAncestry,
18078
18025
  handleStartReadingAncestry
18079
18026
  ]);
18080
- useEffect22(() => {
18027
+ useEffect24(() => {
18081
18028
  function handleKeyDown(event) {
18082
18029
  var _a2, _b2, _c2;
18083
18030
  const context = actionHandlerContext;
@@ -18200,10 +18147,10 @@ function XViewScene({
18200
18147
  // <-- handleCancelQuest adicionado aqui
18201
18148
  ]);
18202
18149
  if (isLoading || status === "loading" || permissionStatus === "loading") {
18203
- return /* @__PURE__ */ React28.createElement(LoadingScreen, null);
18150
+ return /* @__PURE__ */ React30.createElement(LoadingScreen, null);
18204
18151
  }
18205
18152
  if (permissionStatus === "denied") {
18206
- return /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ React28.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ React28.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ React28.createElement(
18153
+ return /* @__PURE__ */ React30.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ React30.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ React30.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ React30.createElement(
18207
18154
  "svg",
18208
18155
  {
18209
18156
  xmlns: "http://www.w3.org/2000/svg",
@@ -18213,7 +18160,7 @@ function XViewScene({
18213
18160
  stroke: "currentColor",
18214
18161
  className: "w-16 h-16 mx-auto"
18215
18162
  },
18216
- /* @__PURE__ */ React28.createElement(
18163
+ /* @__PURE__ */ React30.createElement(
18217
18164
  "path",
18218
18165
  {
18219
18166
  strokeLinecap: "round",
@@ -18221,13 +18168,13 @@ function XViewScene({
18221
18168
  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"
18222
18169
  }
18223
18170
  )
18224
- )), /* @__PURE__ */ React28.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ React28.createElement("p", { className: "text-slate-400 mb-6" }, "Voc\xEA n\xE3o tem permiss\xE3o para acessar este conte\xFAdo. Solicite acesso ao propriet\xE1rio ou verifique se est\xE1 na conta correta."), /* @__PURE__ */ React28.createElement(
18171
+ )), /* @__PURE__ */ React30.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ React30.createElement("p", { className: "text-slate-400 mb-6" }, "Voc\xEA n\xE3o tem permiss\xE3o para acessar este conte\xFAdo. Solicite acesso ao propriet\xE1rio ou verifique se est\xE1 na conta correta."), /* @__PURE__ */ React30.createElement(
18225
18172
  "button",
18226
18173
  {
18227
18174
  onClick: () => router.push("/dashboard/scenes"),
18228
18175
  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"
18229
18176
  },
18230
- /* @__PURE__ */ React28.createElement(
18177
+ /* @__PURE__ */ React30.createElement(
18231
18178
  "svg",
18232
18179
  {
18233
18180
  xmlns: "http://www.w3.org/2000/svg",
@@ -18237,7 +18184,7 @@ function XViewScene({
18237
18184
  stroke: "currentColor",
18238
18185
  className: "w-5 h-5"
18239
18186
  },
18240
- /* @__PURE__ */ React28.createElement(
18187
+ /* @__PURE__ */ React30.createElement(
18241
18188
  "path",
18242
18189
  {
18243
18190
  strokeLinecap: "round",
@@ -18249,7 +18196,7 @@ function XViewScene({
18249
18196
  "Voltar para Scenes"
18250
18197
  )));
18251
18198
  }
18252
- return /* @__PURE__ */ React28.createElement(
18199
+ return /* @__PURE__ */ React30.createElement(
18253
18200
  "div",
18254
18201
  {
18255
18202
  ref: mountRef,
@@ -18261,7 +18208,7 @@ function XViewScene({
18261
18208
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
18262
18209
  }
18263
18210
  },
18264
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ React28.createElement(
18211
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ React30.createElement(
18265
18212
  XViewSidebar,
18266
18213
  {
18267
18214
  dbNodes: searchableDbNodes,
@@ -18281,11 +18228,11 @@ function XViewScene({
18281
18228
  onToggle: setIsSidebarOpen,
18282
18229
  userRole: userPermissionRole,
18283
18230
  viewMembers,
18284
- milestones: ((_d = sceneDataRef.current) == null ? void 0 : _d.milestones) || [],
18231
+ milestones: ((_c = sceneDataRef.current) == null ? void 0 : _c.milestones) || [],
18285
18232
  onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
18286
18233
  }
18287
18234
  ),
18288
- creationMode.isActive && /* @__PURE__ */ React28.createElement(
18235
+ creationMode.isActive && /* @__PURE__ */ React30.createElement(
18289
18236
  InSceneCreationForm,
18290
18237
  {
18291
18238
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -18306,8 +18253,8 @@ function XViewScene({
18306
18253
  },
18307
18254
  refEl: formRef,
18308
18255
  existingTypes: existingNodeTypes,
18309
- initialColor: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.color,
18310
- sourceTypes: (_f = creationMode.sourceNodeData) == null ? void 0 : _f.type,
18256
+ initialColor: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.color,
18257
+ sourceTypes: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.type,
18311
18258
  onIntensityChange: handleGhostNodeIntensityChange,
18312
18259
  onUploadFile: upload_file_action,
18313
18260
  availableDatasets,
@@ -18317,7 +18264,7 @@ function XViewScene({
18317
18264
  availableAncestries: allAvailableAncestries
18318
18265
  }
18319
18266
  ),
18320
- versionMode.isActive && /* @__PURE__ */ React28.createElement(
18267
+ versionMode.isActive && /* @__PURE__ */ React30.createElement(
18321
18268
  InSceneVersionForm,
18322
18269
  {
18323
18270
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -18336,14 +18283,14 @@ function XViewScene({
18336
18283
  transition: "opacity 200ms ease-out"
18337
18284
  },
18338
18285
  refEl: formRef,
18339
- fixedType: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.type,
18340
- fixedColor: (_h = versionMode.sourceNodeData) == null ? void 0 : _h.color,
18286
+ fixedType: (_f = versionMode.sourceNodeData) == null ? void 0 : _f.type,
18287
+ fixedColor: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.color,
18341
18288
  onUploadFile: upload_file_action,
18342
18289
  availableNodes: allAvailableNodes,
18343
18290
  availableAncestries: allAvailableAncestries
18344
18291
  }
18345
18292
  ),
18346
- questMode.isActive && /* @__PURE__ */ React28.createElement(
18293
+ questMode.isActive && /* @__PURE__ */ React30.createElement(
18347
18294
  InSceneQuestForm,
18348
18295
  {
18349
18296
  onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
@@ -18365,13 +18312,13 @@ function XViewScene({
18365
18312
  availableNodes: allAvailableNodes,
18366
18313
  availableAncestries: allAvailableAncestries,
18367
18314
  viewName: viewParams == null ? void 0 : viewParams.name,
18368
- questCounter: ((_i = sceneDataRef.current) == null ? void 0 : _i.quest_counter) || 1,
18315
+ questCounter: ((_h = sceneDataRef.current) == null ? void 0 : _h.quest_counter) || 1,
18369
18316
  viewMembers,
18370
- milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18317
+ milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
18371
18318
  onUpdateMilestones: handleUpdateMilestones
18372
18319
  }
18373
18320
  ),
18374
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React28.createElement(
18321
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React30.createElement(
18375
18322
  "div",
18376
18323
  {
18377
18324
  className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col ${isReadModeResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
@@ -18384,7 +18331,7 @@ function XViewScene({
18384
18331
  maxWidth: "92vw"
18385
18332
  }
18386
18333
  },
18387
- /* @__PURE__ */ React28.createElement(
18334
+ /* @__PURE__ */ React30.createElement(
18388
18335
  "div",
18389
18336
  {
18390
18337
  onPointerDown: (e) => {
@@ -18395,7 +18342,7 @@ function XViewScene({
18395
18342
  title: "Arraste para redimensionar"
18396
18343
  }
18397
18344
  ),
18398
- /* @__PURE__ */ React28.createElement(
18345
+ /* @__PURE__ */ React30.createElement(
18399
18346
  DescriptionReadModePanel,
18400
18347
  {
18401
18348
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -18430,7 +18377,7 @@ function XViewScene({
18430
18377
  }
18431
18378
  )
18432
18379
  ),
18433
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React28.createElement(
18380
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React30.createElement(
18434
18381
  CreateAncestryPanel,
18435
18382
  {
18436
18383
  ancestryMode,
@@ -18466,7 +18413,7 @@ function XViewScene({
18466
18413
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
18467
18414
  }
18468
18415
  ),
18469
- editingAncestryRel.visible && /* @__PURE__ */ React28.createElement(
18416
+ editingAncestryRel.visible && /* @__PURE__ */ React30.createElement(
18470
18417
  AncestryRelationshipPanel,
18471
18418
  {
18472
18419
  data: editingAncestryRel.data,
@@ -18480,7 +18427,7 @@ function XViewScene({
18480
18427
  onUploadFile: upload_file_action
18481
18428
  }
18482
18429
  ),
18483
- detailsNode && detailsNode.is_quest && /* @__PURE__ */ React28.createElement(
18430
+ detailsNode && detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
18484
18431
  QuestDetailsPanel,
18485
18432
  {
18486
18433
  node: detailsNode,
@@ -18502,11 +18449,11 @@ function XViewScene({
18502
18449
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
18503
18450
  viewMembers,
18504
18451
  currentUser: session == null ? void 0 : session.user,
18505
- milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18452
+ milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18506
18453
  onUpdateMilestones: handleUpdateMilestones
18507
18454
  }
18508
18455
  ),
18509
- detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React28.createElement(
18456
+ detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
18510
18457
  NodeDetailsPanel,
18511
18458
  {
18512
18459
  node: detailsNode,
@@ -18538,7 +18485,7 @@ function XViewScene({
18538
18485
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
18539
18486
  }
18540
18487
  ),
18541
- detailsLink && /* @__PURE__ */ React28.createElement(
18488
+ detailsLink && /* @__PURE__ */ React30.createElement(
18542
18489
  RelationshipDetailsPanel,
18543
18490
  {
18544
18491
  link: detailsLink,
@@ -18552,7 +18499,7 @@ function XViewScene({
18552
18499
  userRole: userPermissionRole
18553
18500
  }
18554
18501
  ),
18555
- ancestryLinkDetails && /* @__PURE__ */ React28.createElement(
18502
+ ancestryLinkDetails && /* @__PURE__ */ React30.createElement(
18556
18503
  AncestryLinkDetailsPanel,
18557
18504
  {
18558
18505
  data: ancestryLinkDetails,
@@ -18563,7 +18510,7 @@ function XViewScene({
18563
18510
  onUploadFile: upload_file_action
18564
18511
  }
18565
18512
  ),
18566
- /* @__PURE__ */ React28.createElement(
18513
+ /* @__PURE__ */ React30.createElement(
18567
18514
  "div",
18568
18515
  {
18569
18516
  ref: tooltipRef,
@@ -18590,7 +18537,7 @@ function XViewScene({
18590
18537
  }
18591
18538
  }
18592
18539
  ),
18593
- /* @__PURE__ */ React28.createElement(
18540
+ /* @__PURE__ */ React30.createElement(
18594
18541
  ContextMenu,
18595
18542
  {
18596
18543
  data: contextMenu,
@@ -18623,7 +18570,7 @@ function XViewScene({
18623
18570
  onFinishQuest: handleFinishQuestQuick
18624
18571
  }
18625
18572
  ),
18626
- /* @__PURE__ */ React28.createElement(
18573
+ /* @__PURE__ */ React30.createElement(
18627
18574
  MultiNodeContextMenu,
18628
18575
  {
18629
18576
  data: multiContextMenu,
@@ -18643,7 +18590,7 @@ function XViewScene({
18643
18590
  )
18644
18591
  }
18645
18592
  ),
18646
- /* @__PURE__ */ React28.createElement(
18593
+ /* @__PURE__ */ React30.createElement(
18647
18594
  RelationshipContextMenu,
18648
18595
  {
18649
18596
  data: relationshipMenu,
@@ -18661,14 +18608,14 @@ function XViewScene({
18661
18608
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
18662
18609
  }
18663
18610
  ),
18664
- /* @__PURE__ */ React28.createElement(
18611
+ /* @__PURE__ */ React30.createElement(
18665
18612
  ImageViewer,
18666
18613
  {
18667
18614
  data: imageViewer,
18668
18615
  onClose: () => setImageViewer({ ...imageViewer, visible: false })
18669
18616
  }
18670
18617
  ),
18671
- /* @__PURE__ */ React28.createElement(
18618
+ /* @__PURE__ */ React30.createElement(
18672
18619
  AncestryBoard,
18673
18620
  {
18674
18621
  isOpen: isAncestryBoardOpen,
@@ -18681,29 +18628,29 @@ function XViewScene({
18681
18628
  userRole: userPermissionRole
18682
18629
  }
18683
18630
  ),
18684
- /* @__PURE__ */ React28.createElement(
18631
+ /* @__PURE__ */ React30.createElement(
18685
18632
  MilestoneManager,
18686
18633
  {
18687
18634
  isOpen: isMilestoneManagerOpen,
18688
18635
  onClose: () => setIsMilestoneManagerOpen(false),
18689
- milestones: ((_l = sceneDataRef.current) == null ? void 0 : _l.milestones) || [],
18636
+ milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18690
18637
  onUpdateMilestones: handleUpdateMilestones
18691
18638
  }
18692
18639
  ),
18693
- /* @__PURE__ */ React28.createElement(
18640
+ /* @__PURE__ */ React30.createElement(
18694
18641
  ImportParentFileModal,
18695
18642
  {
18696
18643
  isOpen: isImportModalOpen,
18697
18644
  onClose: () => setIsImportModalOpen(false),
18698
18645
  onConfirm: handleConfirmImport,
18699
18646
  session,
18700
- parentDbs: ((_m = sceneDataRef.current) == null ? void 0 : _m.parent_dbs) || [],
18647
+ parentDbs: ((_l = sceneDataRef.current) == null ? void 0 : _l.parent_dbs) || [],
18701
18648
  onFetchAvailableFiles: import_parent_file_modal_get,
18702
18649
  currentViewName: viewParams == null ? void 0 : viewParams.name,
18703
18650
  currentAncestries: ancestryDataRef.current || []
18704
18651
  }
18705
18652
  ),
18706
- invalidTargetError && /* @__PURE__ */ React28.createElement(
18653
+ invalidTargetError && /* @__PURE__ */ React30.createElement(
18707
18654
  "div",
18708
18655
  {
18709
18656
  className: "ui-overlay",
@@ -18728,13 +18675,13 @@ function XViewScene({
18728
18675
  animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
18729
18676
  }
18730
18677
  },
18731
- /* @__PURE__ */ React28.createElement("style", null, `
18678
+ /* @__PURE__ */ React30.createElement("style", null, `
18732
18679
  @keyframes fadeInDown {
18733
18680
  from { opacity: 0; transform: translate(-50%, -20px); }
18734
18681
  to { opacity: 1; transform: translate(-50%, 0); }
18735
18682
  }
18736
18683
  `),
18737
- /* @__PURE__ */ React28.createElement(
18684
+ /* @__PURE__ */ React30.createElement(
18738
18685
  "svg",
18739
18686
  {
18740
18687
  width: "20",
@@ -18746,12 +18693,12 @@ function XViewScene({
18746
18693
  strokeLinecap: "round",
18747
18694
  strokeLinejoin: "round"
18748
18695
  },
18749
- /* @__PURE__ */ React28.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18750
- /* @__PURE__ */ React28.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18751
- /* @__PURE__ */ React28.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18696
+ /* @__PURE__ */ React30.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18697
+ /* @__PURE__ */ React30.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18698
+ /* @__PURE__ */ React30.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18752
18699
  ),
18753
- /* @__PURE__ */ React28.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18754
- /* @__PURE__ */ React28.createElement(
18700
+ /* @__PURE__ */ React30.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18701
+ /* @__PURE__ */ React30.createElement(
18755
18702
  "button",
18756
18703
  {
18757
18704
  onClick: () => setInvalidTargetError(null),