@lv-x-software-house/x_view 1.2.5 → 1.2.6-dev.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);
@@ -2330,6 +2287,10 @@ var userActionHandlers = {
2330
2287
  );
2331
2288
  }
2332
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
+ }
2333
2294
  updateExistingNodeVisuals(stateRef.current, nodeToSave);
2334
2295
  setters.setSceneVersion((v) => v + 1);
2335
2296
  if (!keepOpen) {
@@ -2478,15 +2439,15 @@ function createNewCustomProperty(existingProps = []) {
2478
2439
  switch (nextType) {
2479
2440
  case "links":
2480
2441
  nextKey = "Links";
2481
- nextValue = [{ id: v4_default(), name: "", value: "" }];
2442
+ nextValue = [{ id: uuidv4(), name: "", value: "" }];
2482
2443
  break;
2483
2444
  case "images":
2484
2445
  nextKey = "Images";
2485
- nextValue = [{ id: v4_default(), name: "1", value: "" }];
2446
+ nextValue = [{ id: uuidv4(), name: "1", value: "" }];
2486
2447
  break;
2487
2448
  case "documents":
2488
2449
  nextKey = "Documents";
2489
- nextValue = [{ id: v4_default(), name: "1", value: "" }];
2450
+ nextValue = [{ id: uuidv4(), name: "1", value: "" }];
2490
2451
  break;
2491
2452
  case "date":
2492
2453
  nextKey = "Date";
@@ -2496,14 +2457,14 @@ function createNewCustomProperty(existingProps = []) {
2496
2457
  nextValue = 0;
2497
2458
  break;
2498
2459
  case "list":
2499
- nextValue = [{ id: v4_default(), name: "", value: "" }];
2460
+ nextValue = [{ id: uuidv4(), name: "", value: "" }];
2500
2461
  break;
2501
2462
  default:
2502
2463
  nextValue = "";
2503
2464
  break;
2504
2465
  }
2505
2466
  return {
2506
- id: v4_default(),
2467
+ id: uuidv4(),
2507
2468
  key: nextKey,
2508
2469
  type: nextType,
2509
2470
  value: nextValue,
@@ -2748,7 +2709,7 @@ function extractCustomPropsFromNode(node) {
2748
2709
  if (val && typeof val === "object") {
2749
2710
  if ("date_interval" in val) {
2750
2711
  return {
2751
- id: v4_default(),
2712
+ id: uuidv4(),
2752
2713
  key,
2753
2714
  type: "date",
2754
2715
  value: {
@@ -2760,7 +2721,7 @@ function extractCustomPropsFromNode(node) {
2760
2721
  }
2761
2722
  if ("year" in val) {
2762
2723
  return {
2763
- id: v4_default(),
2724
+ id: uuidv4(),
2764
2725
  key,
2765
2726
  type: "date",
2766
2727
  value: { type: "Ano", value: val.year || "" }
@@ -2768,7 +2729,7 @@ function extractCustomPropsFromNode(node) {
2768
2729
  }
2769
2730
  if ("date" in val) {
2770
2731
  return {
2771
- id: v4_default(),
2732
+ id: uuidv4(),
2772
2733
  key,
2773
2734
  type: "date",
2774
2735
  value: { type: "Data", value: val.date || "" }
@@ -2776,7 +2737,7 @@ function extractCustomPropsFromNode(node) {
2776
2737
  }
2777
2738
  }
2778
2739
  return {
2779
- id: v4_default(),
2740
+ id: uuidv4(),
2780
2741
  key,
2781
2742
  type: "date",
2782
2743
  value: { type: "Data", value: "" }
@@ -2784,14 +2745,14 @@ function extractCustomPropsFromNode(node) {
2784
2745
  }
2785
2746
  if (t === "list" || t === "links" || t === "images" || t === "documents") {
2786
2747
  const safeList = (val || []).map((item) => ({
2787
- id: item.id || v4_default(),
2748
+ id: item.id || uuidv4(),
2788
2749
  name: item.name ?? "",
2789
2750
  value: item.value ?? ""
2790
2751
  }));
2791
- return { id: v4_default(), key, type: t, value: safeList };
2752
+ return { id: uuidv4(), key, type: t, value: safeList };
2792
2753
  }
2793
2754
  return {
2794
- id: v4_default(),
2755
+ id: uuidv4(),
2795
2756
  key,
2796
2757
  type: t,
2797
2758
  value: t === "number" ? Number(val) || 0 : String(val ?? "")
@@ -3064,16 +3025,16 @@ var processDescriptionForSave = (text, existingSections = []) => {
3064
3025
  if (existingMatch) {
3065
3026
  finalUuid = existingMatch.id;
3066
3027
  } else {
3067
- finalUuid = v4_default();
3028
+ finalUuid = uuidv4();
3068
3029
  }
3069
3030
  } else {
3070
3031
  finalUuid = numericMap.get(numStr);
3071
3032
  if (!finalUuid) {
3072
- finalUuid = v4_default();
3033
+ finalUuid = uuidv4();
3073
3034
  }
3074
3035
  }
3075
3036
  if (usedIds.has(finalUuid)) {
3076
- finalUuid = v4_default();
3037
+ finalUuid = uuidv4();
3077
3038
  }
3078
3039
  usedIds.add(finalUuid);
3079
3040
  processedSections.push({
@@ -3184,18 +3145,18 @@ function useResizablePanel({ initialWidth, minWidth, maxWidth }) {
3184
3145
  function createTimelineEntry(actorId, description, type = "comment", extras = {}) {
3185
3146
  const { links = [], images = [], metadata = {} } = extras;
3186
3147
  return {
3187
- id: v4_default(),
3148
+ id: uuidv4(),
3188
3149
  type,
3189
3150
  timestamp: Date.now(),
3190
3151
  actorId,
3191
3152
  description,
3192
3153
  links: links.map((l) => ({
3193
- id: l.id || v4_default(),
3154
+ id: l.id || uuidv4(),
3194
3155
  name: l.name || "",
3195
3156
  value: l.value || ""
3196
3157
  })),
3197
3158
  images: images.map((img) => ({
3198
- id: img.id || v4_default(),
3159
+ id: img.id || uuidv4(),
3199
3160
  name: img.name || "",
3200
3161
  value: img.value || ""
3201
3162
  }))
@@ -4422,6 +4383,7 @@ function XViewSidebar({
4422
4383
 
4423
4384
  // src/components/AncestryRelationshipPanel.jsx
4424
4385
  import React8, { useState as useState9, useEffect as useEffect8, useRef as useRef7 } from "react";
4386
+ import { v4 as uuidv43 } from "uuid";
4425
4387
 
4426
4388
  // src/components/CustomPropertyDisplay.jsx
4427
4389
  import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
@@ -5181,6 +5143,7 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
5181
5143
  }
5182
5144
 
5183
5145
  // src/components/DescriptionEditModal.jsx
5146
+ import { v4 as uuidv42 } from "uuid";
5184
5147
  var getNextSectionNumber = (currentText) => {
5185
5148
  const regex = /\*\/\s*(\d+)(?::[a-zA-Z0-9-]+)?\s*\//g;
5186
5149
  let max = 0;
@@ -5312,7 +5275,7 @@ function DescriptionEditModal({
5312
5275
  const el = textareaRef.current;
5313
5276
  if (!el) return;
5314
5277
  const nextNum = getNextSectionNumber(text);
5315
- const uniqueSuffix = v4_default().slice(0, 4);
5278
+ const uniqueSuffix = uuidv42().slice(0, 4);
5316
5279
  insertAtCursor(`*/${nextNum}:${uniqueSuffix}/ `);
5317
5280
  };
5318
5281
  const handleImportSelect = (tags) => {
@@ -5323,7 +5286,7 @@ function DescriptionEditModal({
5323
5286
  let currentNum = getNextSectionNumber(currentText);
5324
5287
  let blockToInsert = "";
5325
5288
  tagsArray.forEach((tag) => {
5326
- const uniqueSuffix = v4_default().slice(0, 4);
5289
+ const uniqueSuffix = uuidv42().slice(0, 4);
5327
5290
  blockToInsert += `
5328
5291
  */${currentNum}:${uniqueSuffix}/ ${tag}
5329
5292
  `;
@@ -6683,6 +6646,7 @@ import {
6683
6646
  FiLink as FiLink4,
6684
6647
  FiTrash2 as FiTrash22
6685
6648
  } from "react-icons/fi";
6649
+ import { v4 as uuidv44 } from "uuid";
6686
6650
 
6687
6651
  // src/components/AncestryPickerModal.jsx
6688
6652
  import React9, { useState as useState10, useMemo as useMemo7, useEffect as useEffect9 } from "react";
@@ -7719,7 +7683,7 @@ function CreateAncestryPanel({
7719
7683
  const nodeData = availableNodes.find((n) => String(n.id) === String(nodeId));
7720
7684
  const dirSuffix = direction === "left" ? "(Esq)" : "(Dir)";
7721
7685
  branch = {
7722
- id: v4_default(),
7686
+ id: uuidv44(),
7723
7687
  name: `Ramifica\xE7\xE3o ${dirSuffix} de ${(nodeData == null ? void 0 : nodeData.name) || "Node"}`,
7724
7688
  description: "",
7725
7689
  description_sections: [],
@@ -8498,6 +8462,7 @@ function ImageViewer({ data, onClose }) {
8498
8462
 
8499
8463
  // src/components/InSceneCreationForm.jsx
8500
8464
  import React13, { useState as useState14, useEffect as useEffect13, useRef as useRef10 } from "react";
8465
+ import { v4 as uuidv45 } from "uuid";
8501
8466
 
8502
8467
  // src/components/ColorPicker.jsx
8503
8468
  import React12, { useState as useState13, useEffect as useEffect12, useRef as useRef9 } from "react";
@@ -9082,6 +9047,7 @@ function InSceneCreationForm({
9082
9047
 
9083
9048
  // src/components/InSceneVersionForm.jsx
9084
9049
  import React14, { useState as useState15, useEffect as useEffect14, useRef as useRef11 } from "react";
9050
+ import { v4 as uuidv46 } from "uuid";
9085
9051
  import { FiPlus as FiPlus4, FiMaximize2 as FiMaximize22, FiCheck as FiCheck8, FiEdit2 as FiEdit25 } from "react-icons/fi";
9086
9052
  function InSceneVersionForm({
9087
9053
  onSave,
@@ -9104,7 +9070,7 @@ function InSceneVersionForm({
9104
9070
  const [description, setDescription] = useState15("");
9105
9071
  const [customProps, setCustomProps] = useState15([
9106
9072
  {
9107
- id: v4_default(),
9073
+ id: uuidv46(),
9108
9074
  key: "Date",
9109
9075
  type: "date",
9110
9076
  value: { type: "Data", value: "" },
@@ -9397,6 +9363,7 @@ function InSceneVersionForm({
9397
9363
 
9398
9364
  // src/components/InSceneQuestForm.jsx
9399
9365
  import React16, { useState as useState17, useRef as useRef12 } from "react";
9366
+ import { v4 as uuidv47 } from "uuid";
9400
9367
  import {
9401
9368
  FiPlus as FiPlus6,
9402
9369
  FiCheck as FiCheck9,
@@ -10321,6 +10288,7 @@ function InSceneQuestForm({
10321
10288
 
10322
10289
  // src/components/NodeDetailsPanel.jsx
10323
10290
  import React17, { useState as useState18, useEffect as useEffect15, useRef as useRef13 } from "react";
10291
+ import { v4 as uuidv48 } from "uuid";
10324
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";
10325
10293
  function NodeDetailsPanel({
10326
10294
  node,
@@ -10835,6 +10803,7 @@ function NodeDetailsPanel({
10835
10803
 
10836
10804
  // src/components/QuestDetailsPanel.jsx
10837
10805
  import React19, { useState as useState19, useEffect as useEffect16, useRef as useRef14 } from "react";
10806
+ import { v4 as uuidv49 } from "uuid";
10838
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";
10839
10808
 
10840
10809
  // src/components/QuestTimeline.jsx
@@ -11285,7 +11254,7 @@ ${noteText}` : noteText : entry.notes,
11285
11254
  }, 100);
11286
11255
  };
11287
11256
  const addLinkToNote = () => {
11288
- setNoteLinks([...noteLinks, { id: v4_default(), name: "", value: "" }]);
11257
+ setNoteLinks([...noteLinks, { id: uuidv49(), name: "", value: "" }]);
11289
11258
  };
11290
11259
  const removeLinkFromNote = (id) => {
11291
11260
  setNoteLinks(noteLinks.filter((l) => l.id !== id));
@@ -11294,7 +11263,7 @@ ${noteText}` : noteText : entry.notes,
11294
11263
  setNoteLinks(noteLinks.map((l) => l.id === id ? { ...l, [field]: val } : l));
11295
11264
  };
11296
11265
  const addImageToNote = () => {
11297
- setNoteImages([...noteImages, { id: v4_default(), name: "Image", value: "" }]);
11266
+ setNoteImages([...noteImages, { id: uuidv49(), name: "Image", value: "" }]);
11298
11267
  };
11299
11268
  const removeImageFromNote = (id) => {
11300
11269
  setNoteImages(noteImages.filter((img) => img.id !== id));
@@ -12171,6 +12140,7 @@ function MultiNodeContextMenu({
12171
12140
 
12172
12141
  // src/components/RelationshipDetailsPanel.jsx
12173
12142
  import React21, { useState as useState21, useEffect as useEffect18, useRef as useRef16, useMemo as useMemo9 } from "react";
12143
+ import { v4 as uuidv410 } from "uuid";
12174
12144
  import { FiPlus as FiPlus9, FiEdit2 as FiEdit29, FiLoader as FiLoader4, FiBookOpen as FiBookOpen5 } from "react-icons/fi";
12175
12145
  function RelationshipDetailsPanel({
12176
12146
  link,
@@ -12980,10 +12950,10 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
12980
12950
  }
12981
12951
 
12982
12952
  // src/components/AncestryBoard.jsx
12983
- 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";
12984
12954
  import {
12985
12955
  FiSearch as FiSearch8,
12986
- FiLayers as FiLayers6,
12956
+ FiLayers as FiLayers7,
12987
12957
  FiCornerUpRight as FiCornerUpRight4,
12988
12958
  FiPlay,
12989
12959
  FiPlus as FiPlus10,
@@ -12993,173 +12963,418 @@ import {
12993
12963
  FiCheckCircle,
12994
12964
  FiLoader as FiLoader5,
12995
12965
  FiX as FiX8,
12996
- FiAlertTriangle
12966
+ FiBox as FiBox2,
12967
+ FiCheckSquare as FiCheckSquare4,
12968
+ FiGitBranch as FiGitBranch4
12997
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
12998
13306
  var GroupItem = ({
12999
13307
  group,
13000
13308
  index,
13001
- siblings,
13002
13309
  onUpdate,
13003
13310
  onDelete,
13004
13311
  onAddSubgroup,
13005
13312
  onIndent,
13006
13313
  onOutdent,
13007
- onRemoveAncestry,
13008
- onRequestPickAncestry,
13009
- pickingGroupId,
13010
- onPlayAncestry,
13011
- availableIds,
13314
+ searchItems,
13315
+ onMentionClick,
13012
13316
  canEdit
13013
13317
  }) => {
13014
13318
  const canIndent = index > 0;
13015
- const isPickingForThisGroup = pickingGroupId === group.id;
13016
- const textareaRef = useRef18(null);
13017
- const adjustHeight = () => {
13018
- const textarea = textareaRef.current;
13019
- if (textarea) {
13020
- textarea.style.height = "auto";
13021
- textarea.style.height = `${textarea.scrollHeight}px`;
13022
- }
13319
+ const handleContentChange = (content) => {
13320
+ onUpdate(group.id, { ...group, content });
13023
13321
  };
13024
- useEffect21(() => {
13025
- adjustHeight();
13026
- }, [group.text]);
13027
- 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(
13028
- "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,
13029
13324
  {
13030
- className: `
13031
- flex flex-col gap-2 py-2 px-3 transition-all duration-200
13032
- ${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
13033
- `
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"
13034
13338
  },
13035
- /* @__PURE__ */ React26.createElement(
13036
- "textarea",
13037
- {
13038
- ref: textareaRef,
13039
- 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" : ""}`,
13040
- rows: 1,
13041
- style: {
13042
- minHeight: "1.5rem",
13043
- maxHeight: "250px"
13044
- },
13045
- placeholder: canEdit ? "Escreva sobre este grupo..." : "",
13046
- value: group.text,
13047
- readOnly: !canEdit,
13048
- onChange: (e) => {
13049
- if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
13050
- }
13051
- }
13052
- ),
13053
- group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ React26.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
13054
- const isValid = availableIds.has(String(anc.ancestry_id));
13055
- return /* @__PURE__ */ React26.createElement(
13056
- "div",
13057
- {
13058
- key: anc.ancestry_id,
13059
- className: `
13060
- flex items-center gap-2 rounded-md px-3 py-1.5 text-xs transition-all group/card border
13061
- ${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"}
13062
- `,
13063
- title: isValid ? "" : "Esta ancestralidade foi removida ou n\xE3o existe mais."
13064
- },
13065
- isValid ? (
13066
- // [MANTIDO] Botão Play visível para todos
13067
- /* @__PURE__ */ React26.createElement(
13068
- "button",
13069
- {
13070
- onClick: () => onPlayAncestry(anc.ancestry_id),
13071
- className: "text-indigo-400 hover:text-white hover:bg-indigo-500 p-1 rounded-full transition-colors",
13072
- title: "Renderizar no cen\xE1rio"
13073
- },
13074
- /* @__PURE__ */ React26.createElement(FiPlay, { size: 10, className: "ml-0.5 fill-current" })
13075
- )
13076
- ) : /* @__PURE__ */ React26.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ React26.createElement(FiAlertTriangle, { size: 10 })),
13077
- /* @__PURE__ */ React26.createElement(
13078
- "span",
13079
- {
13080
- className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}`
13081
- },
13082
- anc.name
13083
- ),
13084
- canEdit && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(
13085
- "div",
13086
- {
13087
- className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}`
13088
- }
13089
- ), /* @__PURE__ */ React26.createElement(
13090
- "button",
13091
- {
13092
- onClick: () => onRemoveAncestry(group.id, anc.ancestry_id),
13093
- className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
13094
- title: "Remover men\xE7\xE3o"
13095
- },
13096
- /* @__PURE__ */ React26.createElement(FiX8, { size: 12 })
13097
- ))
13098
- );
13099
- })),
13100
- 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(
13101
- "button",
13102
- {
13103
- onClick: () => onRequestPickAncestry(group.id),
13104
- className: `
13105
- flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium transition-colors
13106
- ${isPickingForThisGroup ? "text-indigo-300 animate-pulse" : "text-slate-500 hover:text-indigo-300 hover:bg-indigo-500/10"}
13107
- `,
13108
- title: "Adicionar Ancestralidade a este grupo"
13109
- },
13110
- isPickingForThisGroup ? /* @__PURE__ */ React26.createElement(FiCheckCircle, { size: 12 }) : /* @__PURE__ */ React26.createElement(FiSearch8, { size: 12 }),
13111
- isPickingForThisGroup ? "Selecionando..." : "Adicionar"
13112
- ), /* @__PURE__ */ React26.createElement(
13113
- "button",
13114
- {
13115
- onClick: () => onAddSubgroup(group.id),
13116
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13117
- title: "Criar Subgrupo"
13118
- },
13119
- /* @__PURE__ */ React26.createElement(FiPlus10, { size: 14 })
13120
- )), /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React26.createElement(
13121
- "button",
13122
- {
13123
- onClick: () => onIndent(group.id),
13124
- disabled: !canIndent,
13125
- className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13126
- title: "Aninhar no grupo acima"
13127
- },
13128
- /* @__PURE__ */ React26.createElement(FiArrowRight2, { size: 14 })
13129
- ), /* @__PURE__ */ React26.createElement(
13130
- "button",
13131
- {
13132
- onClick: () => onOutdent(group.id),
13133
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13134
- title: "Desaninhar"
13135
- },
13136
- /* @__PURE__ */ React26.createElement(FiArrowLeft3, { size: 14 })
13137
- ), /* @__PURE__ */ React26.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React26.createElement(
13138
- "button",
13139
- {
13140
- onClick: () => onDelete(group.id),
13141
- className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13142
- title: "Remover Grupo"
13143
- },
13144
- /* @__PURE__ */ React26.createElement(FiTrash23, { size: 14 })
13145
- )))
13146
- ), 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(
13147
13366
  GroupItem,
13148
13367
  {
13149
- key: childGroup.id,
13368
+ key: child.id,
13150
13369
  index: idx,
13151
- group: childGroup,
13152
- siblings: group.children,
13370
+ group: child,
13153
13371
  onUpdate,
13154
13372
  onDelete,
13155
13373
  onAddSubgroup,
13156
13374
  onIndent,
13157
13375
  onOutdent,
13158
- onRemoveAncestry,
13159
- onRequestPickAncestry,
13160
- pickingGroupId,
13161
- onPlayAncestry,
13162
- availableIds,
13376
+ searchItems,
13377
+ onMentionClick,
13163
13378
  canEdit
13164
13379
  }
13165
13380
  ))));
@@ -13173,141 +13388,127 @@ function AncestryBoard({
13173
13388
  initialGroups = [],
13174
13389
  onSave,
13175
13390
  userRole
13176
- // [NOVO] Recebe a role do usuário
13177
13391
  }) {
13178
- const [searchTerm, setSearchTerm] = useState25("");
13179
- const [groups, setGroups] = useState25([]);
13180
- const [isLoaded, setIsLoaded] = useState25(false);
13181
- const [pickingGroupId, setPickingGroupId] = useState25(null);
13182
- const [saveStatus, setSaveStatus] = useState25("idle");
13183
- const canEdit = useMemo11(() => {
13184
- return userRole !== "viewer";
13185
- }, [userRole]);
13186
- useEffect21(() => {
13392
+ const [searchTerm, setSearchTerm] = useState27("");
13393
+ const [groups, setGroups] = useState27([]);
13394
+ const [isLoaded, setIsLoaded] = useState27(false);
13395
+ const [saveStatus, setSaveStatus] = useState27("idle");
13396
+ const canEdit = useMemo12(() => userRole !== "viewer", [userRole]);
13397
+ useEffect23(() => {
13187
13398
  if (initialGroups && !isLoaded) {
13188
- setGroups(initialGroups);
13399
+ const migrate = (list) => list.map((g) => ({
13400
+ id: g.id || uuidv411(),
13401
+ content: Array.isArray(g.content) ? g.content : [],
13402
+ // descarta dados legados
13403
+ children: migrate(g.children || [])
13404
+ }));
13405
+ setGroups(migrate(initialGroups));
13189
13406
  setIsLoaded(true);
13190
13407
  }
13191
13408
  }, [initialGroups, isLoaded]);
13192
- const nodeNamesMap = useMemo11(() => {
13409
+ const nodeNamesMap = useMemo12(() => {
13193
13410
  const map = /* @__PURE__ */ new Map();
13194
- if (availableNodes && Array.isArray(availableNodes)) {
13195
- availableNodes.forEach((node) => {
13196
- if (node && node.id) {
13197
- map.set(String(node.id), node.name);
13198
- }
13199
- });
13200
- }
13411
+ availableNodes.forEach((n) => {
13412
+ if (n == null ? void 0 : n.id) map.set(String(n.id), n.name);
13413
+ });
13201
13414
  return map;
13202
13415
  }, [availableNodes]);
13203
- const availableIds = useMemo11(() => {
13204
- return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
13205
- }, [availableAncestries]);
13206
- const sanitizeGroups = (groupList) => {
13207
- return groupList.map((g) => ({
13208
- id: g.id,
13209
- text: g.text || "",
13210
- ancestries: (g.ancestries || []).map((a) => ({
13211
- ancestry_id: a.ancestry_id,
13212
- name: a.name
13213
- })),
13214
- children: sanitizeGroups(g.children || [])
13215
- }));
13216
- };
13217
- useEffect21(() => {
13416
+ const allSearchableItems = useMemo12(() => {
13417
+ const items = [];
13418
+ availableAncestries.forEach((anc) => {
13419
+ items.push({
13420
+ ...anc,
13421
+ id: String(anc.ancestry_id),
13422
+ type: "ancestry",
13423
+ searchLabel: anc.name || "",
13424
+ searchDesc: anc.description || ""
13425
+ });
13426
+ });
13427
+ availableNodes.forEach((node) => {
13428
+ var _a;
13429
+ let type = "node";
13430
+ if (node.is_quest) type = "quest";
13431
+ else if ((_a = node.version_node) == null ? void 0 : _a.is_version) type = "version";
13432
+ items.push({
13433
+ ...node,
13434
+ id: String(node.id),
13435
+ type,
13436
+ searchLabel: node.name || node.raw_title || "",
13437
+ searchDesc: node.description || ""
13438
+ });
13439
+ });
13440
+ return items;
13441
+ }, [availableAncestries, availableNodes]);
13442
+ const filtered = useMemo12(() => {
13443
+ const term = searchTerm.toLowerCase().trim();
13444
+ return allSearchableItems.filter((item) => {
13445
+ if (!term) return true;
13446
+ const labelMatch = (item.searchLabel || "").toLowerCase().includes(term);
13447
+ const descMatch = (item.searchDesc || "").toLowerCase().includes(term);
13448
+ let parentMatch = false;
13449
+ if (item.type === "ancestry") {
13450
+ const parentName = nodeNamesMap.get(String(item.ancestral_node)) || "";
13451
+ parentMatch = parentName.toLowerCase().includes(term);
13452
+ }
13453
+ return labelMatch || descMatch || parentMatch;
13454
+ });
13455
+ }, [allSearchableItems, searchTerm, nodeNamesMap]);
13456
+ const sanitizeGroups = (list) => list.map((g) => ({
13457
+ id: g.id,
13458
+ content: g.content || [],
13459
+ children: sanitizeGroups(g.children || [])
13460
+ }));
13461
+ useEffect23(() => {
13218
13462
  if (!isLoaded || !onSave) return;
13219
- const timeoutId = setTimeout(async () => {
13463
+ const id = setTimeout(async () => {
13220
13464
  setSaveStatus("saving");
13221
- const cleanData = sanitizeGroups(groups);
13222
13465
  try {
13223
- await onSave(cleanData);
13466
+ await onSave(sanitizeGroups(groups));
13224
13467
  setSaveStatus("saved");
13225
- setTimeout(() => {
13226
- setSaveStatus("idle");
13227
- }, 3e3);
13228
- } catch (error) {
13229
- console.error("Erro ao salvar board:", error);
13468
+ setTimeout(() => setSaveStatus("idle"), 3e3);
13469
+ } catch (err) {
13470
+ console.error("Erro ao salvar board:", err);
13230
13471
  setSaveStatus("error");
13231
13472
  }
13232
13473
  }, 3e3);
13233
- return () => clearTimeout(timeoutId);
13474
+ return () => clearTimeout(id);
13234
13475
  }, [groups, isLoaded, onSave]);
13235
- useEffect21(() => {
13476
+ useEffect23(() => {
13236
13477
  if (!isOpen) return;
13237
- const handleKeyDown = (e) => {
13478
+ const handler = (e) => {
13238
13479
  if (e.key === "Escape") {
13239
- if (pickingGroupId) {
13240
- setPickingGroupId(null);
13241
- } else {
13242
- onClose();
13243
- }
13480
+ onClose();
13244
13481
  e.preventDefault();
13245
13482
  e.stopPropagation();
13246
13483
  }
13247
13484
  };
13248
- window.addEventListener("keydown", handleKeyDown);
13249
- return () => window.removeEventListener("keydown", handleKeyDown);
13250
- }, [isOpen, onClose, pickingGroupId]);
13251
- const filtered = useMemo11(() => {
13252
- const term = searchTerm.toLowerCase().trim();
13253
- return availableAncestries.filter((a) => {
13254
- if (!term) return true;
13255
- const nameMatch = a.name && a.name.toLowerCase().includes(term);
13256
- const descMatch = a.description && a.description.toLowerCase().includes(term);
13257
- const parentName = nodeNamesMap.get(String(a.ancestral_node)) || "";
13258
- const parentMatch = parentName.toLowerCase().includes(term);
13259
- return nameMatch || descMatch || parentMatch;
13260
- });
13261
- }, [availableAncestries, searchTerm, nodeNamesMap]);
13485
+ window.addEventListener("keydown", handler);
13486
+ return () => window.removeEventListener("keydown", handler);
13487
+ }, [isOpen, onClose]);
13262
13488
  const handleAddRootGroup = () => {
13263
- const newGroup = {
13264
- id: v4_default(),
13265
- text: "",
13266
- ancestries: [],
13267
- children: []
13268
- };
13269
- setGroups((prev) => [newGroup, ...prev]);
13489
+ setGroups((prev) => [{ id: uuidv411(), content: [], children: [] }, ...prev]);
13270
13490
  };
13271
13491
  const handleAddSubgroup = (parentId) => {
13272
- const newGroup = {
13273
- id: v4_default(),
13274
- text: "",
13275
- ancestries: [],
13276
- children: []
13277
- };
13278
- const addRecursive = (list) => {
13279
- return list.map((g) => {
13280
- if (g.id === parentId) {
13281
- return { ...g, children: [newGroup, ...g.children] };
13282
- }
13283
- return { ...g, children: addRecursive(g.children) };
13284
- });
13285
- };
13286
- setGroups((prev) => addRecursive(prev));
13492
+ const newGroup = { id: uuidv411(), content: [], children: [] };
13493
+ const add = (list) => list.map(
13494
+ (g) => g.id === parentId ? { ...g, children: [newGroup, ...g.children] } : { ...g, children: add(g.children) }
13495
+ );
13496
+ setGroups((prev) => add(prev));
13287
13497
  };
13288
13498
  const handleUpdateGroup = (id, newData) => {
13289
- const updateRecursive = (list) => {
13290
- return list.map((g) => {
13291
- if (g.id === id) return newData;
13292
- return { ...g, children: updateRecursive(g.children) };
13293
- });
13294
- };
13295
- setGroups((prev) => updateRecursive(prev));
13499
+ const update = (list) => list.map(
13500
+ (g) => g.id === id ? newData : { ...g, children: update(g.children) }
13501
+ );
13502
+ setGroups((prev) => update(prev));
13296
13503
  };
13297
13504
  const handleDeleteGroup = (id) => {
13298
- const deleteRecursive = (list) => {
13299
- return list.filter((g) => g.id !== id).map((g) => ({
13300
- ...g,
13301
- children: deleteRecursive(g.children)
13302
- }));
13303
- };
13304
- setGroups((prev) => deleteRecursive(prev));
13505
+ const del = (list) => list.filter((g) => g.id !== id).map((g) => ({ ...g, children: del(g.children) }));
13506
+ setGroups((prev) => del(prev));
13305
13507
  };
13306
13508
  const findGroupAndParent = (list, targetId, parent = null) => {
13307
13509
  for (let i = 0; i < list.length; i++) {
13308
- if (list[i].id === targetId) {
13510
+ if (list[i].id === targetId)
13309
13511
  return { group: list[i], parent, index: i, siblings: list };
13310
- }
13311
13512
  if (list[i].children.length > 0) {
13312
13513
  const found = findGroupAndParent(list[i].children, targetId, list[i]);
13313
13514
  if (found) return found;
@@ -13317,216 +13518,119 @@ function AncestryBoard({
13317
13518
  };
13318
13519
  const handleIndent = (id) => {
13319
13520
  setGroups((prev) => {
13320
- const newList = JSON.parse(JSON.stringify(prev));
13321
- const found = findGroupAndParent(newList, id);
13521
+ const next = JSON.parse(JSON.stringify(prev));
13522
+ const found = findGroupAndParent(next, id);
13322
13523
  if (!found || found.index === 0) return prev;
13323
13524
  const { group, siblings, index } = found;
13324
- const prevSibling = siblings[index - 1];
13325
13525
  siblings.splice(index, 1);
13326
- prevSibling.children.push(group);
13327
- return newList;
13526
+ siblings[index - 1].children.push(group);
13527
+ return next;
13328
13528
  });
13329
13529
  };
13330
13530
  const handleOutdent = (id) => {
13331
13531
  setGroups((prev) => {
13332
- const newList = JSON.parse(JSON.stringify(prev));
13333
- const found = findGroupAndParent(newList, id);
13532
+ const next = JSON.parse(JSON.stringify(prev));
13533
+ const found = findGroupAndParent(next, id);
13334
13534
  if (!found || !found.parent) return prev;
13335
13535
  const { group, siblings, index, parent } = found;
13336
13536
  siblings.splice(index, 1);
13337
- const parentFound = findGroupAndParent(newList, parent.id);
13537
+ const parentFound = findGroupAndParent(next, parent.id);
13338
13538
  if (parentFound) {
13339
13539
  parentFound.siblings.splice(parentFound.index + 1, 0, group);
13340
13540
  } else {
13341
- newList.push(group);
13541
+ next.push(group);
13342
13542
  }
13343
- return newList;
13543
+ return next;
13344
13544
  });
13345
13545
  };
13346
- const handleRequestPick = (groupId) => {
13347
- setPickingGroupId((prev) => prev === groupId ? null : groupId);
13348
- };
13349
- const handleSelectAncestry = (ancestry) => {
13350
- if (pickingGroupId) {
13351
- setGroups((prev) => {
13352
- const addRecursive = (list) => {
13353
- return list.map((g) => {
13354
- if (g.id === pickingGroupId) {
13355
- const exists = g.ancestries.some(
13356
- (a) => a.ancestry_id === ancestry.ancestry_id
13357
- );
13358
- if (exists) return g;
13359
- return { ...g, ancestries: [...g.ancestries, ancestry] };
13360
- }
13361
- return { ...g, children: addRecursive(g.children) };
13362
- });
13363
- };
13364
- return addRecursive(prev);
13365
- });
13366
- setPickingGroupId(null);
13367
- } else {
13368
- const fullAncestry = availableAncestries.find(
13369
- (a) => a.ancestry_id === ancestry.ancestry_id
13370
- ) || ancestry;
13371
- onSelect(fullAncestry);
13372
- }
13373
- };
13374
- const handlePlayFromGroup = (ancestryId) => {
13375
- const fullAncestry = availableAncestries.find(
13376
- (a) => a.ancestry_id === ancestryId
13377
- );
13378
- if (fullAncestry && onSelect) {
13379
- onSelect(fullAncestry);
13380
- }
13381
- };
13382
- const handleRemoveAncestryFromGroup = (groupId, ancestryId) => {
13383
- setGroups((prev) => {
13384
- const removeRecursive = (list) => {
13385
- return list.map((g) => {
13386
- if (g.id === groupId) {
13387
- return {
13388
- ...g,
13389
- ancestries: g.ancestries.filter(
13390
- (a) => a.ancestry_id !== ancestryId
13391
- )
13392
- };
13393
- }
13394
- return { ...g, children: removeRecursive(g.children) };
13395
- });
13396
- };
13397
- return removeRecursive(prev);
13398
- });
13546
+ const handleMentionClick = (item) => {
13547
+ if (onSelect) onSelect(item);
13399
13548
  };
13400
13549
  if (!isOpen) return null;
13401
- return /* @__PURE__ */ React26.createElement(
13550
+ return /* @__PURE__ */ React28.createElement(
13402
13551
  "div",
13403
13552
  {
13404
13553
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
13405
13554
  onClick: onClose
13406
13555
  },
13407
- /* @__PURE__ */ React26.createElement(
13556
+ /* @__PURE__ */ React28.createElement(
13408
13557
  "div",
13409
13558
  {
13410
13559
  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",
13411
13560
  onClick: (e) => e.stopPropagation()
13412
13561
  },
13413
- /* @__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(
13414
- FiLoader5,
13415
- {
13416
- className: "animate-spin text-indigo-400",
13417
- size: 12
13418
- }
13419
- ), /* @__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(
13562
+ /* @__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(
13420
13563
  "button",
13421
13564
  {
13422
13565
  onClick: handleAddRootGroup,
13423
- 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 "
13566
+ 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"
13424
13567
  },
13425
- /* @__PURE__ */ React26.createElement(FiPlus10, { size: 14, className: "text-indigo-400" }),
13426
- /* @__PURE__ */ React26.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13427
- ), /* @__PURE__ */ React26.createElement(
13568
+ /* @__PURE__ */ React28.createElement(FiPlus10, { size: 14, className: "text-indigo-400" }),
13569
+ /* @__PURE__ */ React28.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13570
+ ), /* @__PURE__ */ React28.createElement(
13428
13571
  "button",
13429
13572
  {
13430
13573
  onClick: onClose,
13431
13574
  className: "w-8 h-8 rounded-lg flex items-center justify-center text-slate-400 hover:text-white hover:bg-white/10 transition-colors"
13432
13575
  },
13433
- "\xD7"
13576
+ /* @__PURE__ */ React28.createElement(FiX8, { size: 16 })
13434
13577
  ))),
13435
- /* @__PURE__ */ React26.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React26.createElement(
13436
- "div",
13578
+ /* @__PURE__ */ React28.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col border-r border-white/10 w-[20%] min-w-[280px] max-w-[460px] bg-slate-900 flex-none" }, /* @__PURE__ */ React28.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ React28.createElement("div", { className: "relative group" }, /* @__PURE__ */ React28.createElement(FiSearch8, { className: "absolute left-3 top-1/2 -translate-y-1/2 text-slate-500 group-focus-within:text-indigo-400 transition-colors" }), /* @__PURE__ */ React28.createElement(
13579
+ "input",
13437
13580
  {
13438
- className: `
13439
- flex flex-col border-r border-white/10 transition-all duration-300 flex-none
13440
- ${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
13441
- min-w-[280px] max-w-[500px] bg-slate-900
13442
- `
13443
- },
13444
- /* @__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(
13445
- FiSearch8,
13446
- {
13447
- 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"}`
13448
- }
13449
- ), /* @__PURE__ */ React26.createElement(
13450
- "input",
13581
+ type: "text",
13582
+ placeholder: "Navegar nas ancestralidades e nodes\u2026",
13583
+ className: "w-full rounded-md pl-9 pr-4 py-2 text-sm bg-slate-950 border border-white/10 text-slate-200 placeholder-slate-600 focus:outline-none focus:ring-1 focus:ring-indigo-500 transition-all",
13584
+ value: searchTerm,
13585
+ onChange: (e) => setSearchTerm(e.target.value),
13586
+ autoFocus: true
13587
+ }
13588
+ ))), /* @__PURE__ */ React28.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
13589
+ const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
13590
+ return /* @__PURE__ */ React28.createElement(
13591
+ "div",
13451
13592
  {
13452
- type: "text",
13453
- placeholder: pickingGroupId ? "Pesquise para adicionar..." : "Pesquisar ancestralidade...",
13454
- className: `
13455
- 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
13456
- ${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"}
13457
- `,
13458
- value: searchTerm,
13459
- onChange: (e) => setSearchTerm(e.target.value),
13460
- autoFocus: !pickingGroupId
13461
- }
13462
- ))),
13463
- /* @__PURE__ */ React26.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
13464
- const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
13465
- const isPicking = !!pickingGroupId;
13466
- return /* @__PURE__ */ React26.createElement(
13467
- "div",
13593
+ key: anc.id,
13594
+ className: "group relative flex items-start gap-3 p-3 text-left rounded-lg border border-white/5 bg-slate-800/40 hover:bg-indigo-600/10 hover:border-indigo-500/30 cursor-default transition-all duration-200"
13595
+ },
13596
+ /* @__PURE__ */ React28.createElement("div", { className: "mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border bg-slate-800 border-white/5 group-hover:bg-indigo-500 group-hover:text-white transition-all shadow-lg" }, anc.type === "quest" ? /* @__PURE__ */ React28.createElement(FiCheckSquare4, { size: 14, className: "text-emerald-400 group-hover:text-white" }) : anc.type === "version" ? /* @__PURE__ */ React28.createElement(FiGitBranch4, { size: 14, className: "text-amber-400 group-hover:text-white" }) : anc.type === "node" ? /* @__PURE__ */ React28.createElement(FiBox2, { size: 14, className: "text-slate-400 group-hover:text-white" }) : /* @__PURE__ */ React28.createElement(FiLayers7, { size: 14, className: "text-indigo-400 group-hover:text-white" })),
13597
+ /* @__PURE__ */ React28.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ React28.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ React28.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, anc.searchLabel || "Sem Nome"), /* @__PURE__ */ React28.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-tighter" }, anc.type)), anc.type === "ancestry" && /* @__PURE__ */ React28.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__ */ React28.createElement(FiCornerUpRight4, { size: 10 }), /* @__PURE__ */ React28.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.searchDesc && /* @__PURE__ */ React28.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.searchDesc)),
13598
+ /* @__PURE__ */ React28.createElement(
13599
+ "button",
13468
13600
  {
13469
- key: anc.ancestry_id,
13470
- onClick: () => {
13471
- if (isPicking) handleSelectAncestry(anc);
13601
+ onClick: (e) => {
13602
+ e.stopPropagation();
13603
+ if (onSelect) onSelect(anc);
13472
13604
  },
13473
- className: `
13474
- group relative flex items-start gap-3 p-3 text-left rounded-lg border transition-all duration-200
13475
- ${isPicking ? "border-indigo-500/30 bg-indigo-500/5 hover:bg-indigo-500/20 hover:border-indigo-400 cursor-pointer" : "border-white/5 bg-slate-800/40 hover:bg-indigo-600/10 hover:border-indigo-500/30 cursor-default"}
13476
- `
13605
+ 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",
13606
+ title: "Focar no cen\xE1rio"
13477
13607
  },
13478
- /* @__PURE__ */ React26.createElement(
13479
- "div",
13480
- {
13481
- className: `
13482
- mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
13483
- ${isPicking ? "bg-indigo-500 text-white border-indigo-400" : "bg-slate-800 text-indigo-400 border-white/5 group-hover:bg-indigo-500 group-hover:text-white"}
13484
- `
13485
- },
13486
- isPicking ? /* @__PURE__ */ React26.createElement(FiPlus10, { size: 16 }) : /* @__PURE__ */ React26.createElement(FiLayers6, { size: 14 })
13487
- ),
13488
- /* @__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" }, anc.name || "Sem Nome"), anc.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")), /* @__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]" }, parentNodeName)), anc.description && /* @__PURE__ */ React26.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
13489
- !isPicking && /* @__PURE__ */ React26.createElement(
13490
- "button",
13491
- {
13492
- onClick: (e) => {
13493
- e.stopPropagation();
13494
- handleSelectAncestry(anc);
13495
- },
13496
- 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",
13497
- title: "Renderizar Ancestralidade"
13498
- },
13499
- /* @__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" }))
13500
- )
13501
- );
13502
- }))
13503
- ), /* @__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(
13608
+ /* @__PURE__ */ React28.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ React28.createElement(FiPlay, { size: 14, className: "ml-0.5" }))
13609
+ )
13610
+ );
13611
+ }))), /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ React28.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar 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(
13504
13612
  GroupItem,
13505
13613
  {
13506
13614
  key: group.id,
13507
13615
  index,
13508
13616
  group,
13509
- siblings: groups,
13510
13617
  onUpdate: handleUpdateGroup,
13511
13618
  onDelete: handleDeleteGroup,
13512
13619
  onAddSubgroup: handleAddSubgroup,
13513
13620
  onIndent: handleIndent,
13514
13621
  onOutdent: handleOutdent,
13515
- onRemoveAncestry: handleRemoveAncestryFromGroup,
13516
- onRequestPickAncestry: handleRequestPick,
13517
- pickingGroupId,
13518
- onPlayAncestry: handlePlayFromGroup,
13519
- availableIds,
13622
+ searchItems: allSearchableItems,
13623
+ onMentionClick: handleMentionClick,
13520
13624
  canEdit
13521
13625
  }
13522
13626
  ))))),
13523
- /* @__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"))
13627
+ /* @__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-between flex-shrink-0" }, /* @__PURE__ */ React28.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ React28.createElement("span", null, groups.length, " grupos raiz"))
13524
13628
  )
13525
13629
  );
13526
13630
  }
13527
13631
 
13528
13632
  // src/components/MilestoneManager.jsx
13529
- import React27, { useState as useState26 } from "react";
13633
+ import React29, { useState as useState28 } from "react";
13530
13634
  import { FiTarget as FiTarget4, FiPlus as FiPlus11, FiTrash2 as FiTrash24, FiX as FiX9, FiCheck as FiCheck12, FiPauseCircle, FiPlayCircle } from "react-icons/fi";
13531
13635
  function MilestoneManager({
13532
13636
  isOpen,
@@ -13535,7 +13639,7 @@ function MilestoneManager({
13535
13639
  onUpdateMilestones = () => {
13536
13640
  }
13537
13641
  }) {
13538
- const [newMilestoneName, setNewMilestoneName] = useState26("");
13642
+ const [newMilestoneName, setNewMilestoneName] = useState28("");
13539
13643
  const handleAddMilestone = () => {
13540
13644
  if (!newMilestoneName.trim()) return;
13541
13645
  const newMilestone = {
@@ -13560,27 +13664,27 @@ function MilestoneManager({
13560
13664
  };
13561
13665
  if (!isOpen) return null;
13562
13666
  const swallow = (e) => e.stopPropagation();
13563
- return /* @__PURE__ */ React27.createElement(
13667
+ return /* @__PURE__ */ React29.createElement(
13564
13668
  "div",
13565
13669
  {
13566
13670
  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",
13567
13671
  onClick: onClose
13568
13672
  },
13569
- /* @__PURE__ */ React27.createElement(
13673
+ /* @__PURE__ */ React29.createElement(
13570
13674
  "div",
13571
13675
  {
13572
13676
  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",
13573
13677
  onClick: swallow
13574
13678
  },
13575
- /* @__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(
13679
+ /* @__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(
13576
13680
  "button",
13577
13681
  {
13578
13682
  onClick: onClose,
13579
13683
  className: "p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
13580
13684
  },
13581
- /* @__PURE__ */ React27.createElement(FiX9, { size: 20 })
13685
+ /* @__PURE__ */ React29.createElement(FiX9, { size: 20 })
13582
13686
  )),
13583
- /* @__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(
13687
+ /* @__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(
13584
13688
  "input",
13585
13689
  {
13586
13690
  type: "text",
@@ -13590,47 +13694,47 @@ function MilestoneManager({
13590
13694
  placeholder: "Adicionar novo milestone...",
13591
13695
  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"
13592
13696
  }
13593
- ), /* @__PURE__ */ React27.createElement(
13697
+ ), /* @__PURE__ */ React29.createElement(
13594
13698
  "button",
13595
13699
  {
13596
13700
  onClick: handleAddMilestone,
13597
13701
  disabled: !newMilestoneName.trim(),
13598
13702
  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"
13599
13703
  },
13600
- /* @__PURE__ */ React27.createElement(FiPlus11, { size: 18 }),
13704
+ /* @__PURE__ */ React29.createElement(FiPlus11, { size: 18 }),
13601
13705
  "Adicionar"
13602
13706
  ))),
13603
- /* @__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(
13707
+ /* @__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(
13604
13708
  "div",
13605
13709
  {
13606
13710
  key: ms.id,
13607
13711
  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]"}`
13608
13712
  },
13609
- /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ React27.createElement(
13713
+ /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ React29.createElement(
13610
13714
  "div",
13611
13715
  {
13612
13716
  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"}`
13613
13717
  }
13614
- ), /* @__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"))),
13615
- /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React27.createElement(
13718
+ ), /* @__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"))),
13719
+ /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React29.createElement(
13616
13720
  "button",
13617
13721
  {
13618
13722
  onClick: () => handleToggleMilestoneStatus(ms.id),
13619
13723
  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"}`,
13620
13724
  title: ms.status === "active" ? "Inativar" : "Ativar"
13621
13725
  },
13622
- ms.status === "active" ? /* @__PURE__ */ React27.createElement(FiPauseCircle, { size: 18 }) : /* @__PURE__ */ React27.createElement(FiPlayCircle, { size: 18 })
13623
- ), /* @__PURE__ */ React27.createElement(
13726
+ ms.status === "active" ? /* @__PURE__ */ React29.createElement(FiPauseCircle, { size: 18 }) : /* @__PURE__ */ React29.createElement(FiPlayCircle, { size: 18 })
13727
+ ), /* @__PURE__ */ React29.createElement(
13624
13728
  "button",
13625
13729
  {
13626
13730
  onClick: () => handleRemoveMilestone(ms.id),
13627
13731
  className: "p-2 rounded-lg hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-all",
13628
13732
  title: "Remover"
13629
13733
  },
13630
- /* @__PURE__ */ React27.createElement(FiTrash24, { size: 18 })
13734
+ /* @__PURE__ */ React29.createElement(FiTrash24, { size: 18 })
13631
13735
  ))
13632
- ))) : /* @__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."))),
13633
- /* @__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))))
13736
+ ))) : /* @__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."))),
13737
+ /* @__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))))
13634
13738
  )
13635
13739
  );
13636
13740
  }
@@ -13722,7 +13826,7 @@ function XViewScene({
13722
13826
  const searchParams = useSearchParams();
13723
13827
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
13724
13828
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
13725
- const viewParams = useMemo12(() => {
13829
+ const viewParams = useMemo13(() => {
13726
13830
  if (encryptedConfig) {
13727
13831
  const data = decryptData(encryptedConfig);
13728
13832
  if (data) {
@@ -13731,7 +13835,7 @@ function XViewScene({
13731
13835
  }
13732
13836
  return null;
13733
13837
  }, [encryptedConfig, session]);
13734
- useEffect22(() => {
13838
+ useEffect24(() => {
13735
13839
  async function verifyPermission() {
13736
13840
  if (!viewParams || !session || !check_user_permission) return;
13737
13841
  const { id, type, owner_id } = viewParams;
@@ -13768,65 +13872,65 @@ function XViewScene({
13768
13872
  setIsLoading(false);
13769
13873
  }
13770
13874
  }, [viewParams, session, status, check_user_permission]);
13771
- const sceneConfigId = useMemo12(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13772
- const ownerId = useMemo12(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13773
- const dbSaveUrl = useMemo12(() => {
13875
+ const sceneConfigId = useMemo13(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13876
+ const ownerId = useMemo13(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13877
+ const dbSaveUrl = useMemo13(() => {
13774
13878
  if (ownerId && sceneConfigId) {
13775
13879
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
13776
13880
  }
13777
13881
  return null;
13778
13882
  }, [ownerId, sceneConfigId]);
13779
- const sceneSaveUrl = useMemo12(() => {
13883
+ const sceneSaveUrl = useMemo13(() => {
13780
13884
  if (ownerId && sceneConfigId) {
13781
13885
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
13782
13886
  }
13783
13887
  return null;
13784
13888
  }, [ownerId, sceneConfigId]);
13785
- const ancestry_save_url = useMemo12(() => {
13889
+ const ancestry_save_url = useMemo13(() => {
13786
13890
  if (ownerId && sceneConfigId) {
13787
13891
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
13788
13892
  }
13789
13893
  return null;
13790
13894
  }, [ownerId, sceneConfigId]);
13791
- const sceneDataRef = useRef19(null);
13792
- const parentDataRef = useRef19(null);
13793
- const ancestryDataRef = useRef19(null);
13794
- const [isLoading, setIsLoading] = useState27(true);
13795
- const [permissionStatus, setPermissionStatus] = useState27("loading");
13796
- const [userPermissionRole, setUserPermissionRole] = useState27(null);
13797
- const [viewMembers, setViewMembers] = useState27([]);
13798
- const [isInitialized, setIsInitialized] = useState27(false);
13799
- const [sceneVersion, setSceneVersion] = useState27(0);
13800
- const [contextMenu, setContextMenu] = useState27({
13895
+ const sceneDataRef = useRef20(null);
13896
+ const parentDataRef = useRef20(null);
13897
+ const ancestryDataRef = useRef20(null);
13898
+ const [isLoading, setIsLoading] = useState29(true);
13899
+ const [permissionStatus, setPermissionStatus] = useState29("loading");
13900
+ const [userPermissionRole, setUserPermissionRole] = useState29(null);
13901
+ const [viewMembers, setViewMembers] = useState29([]);
13902
+ const [isInitialized, setIsInitialized] = useState29(false);
13903
+ const [sceneVersion, setSceneVersion] = useState29(0);
13904
+ const [contextMenu, setContextMenu] = useState29({
13801
13905
  visible: false,
13802
13906
  x: 0,
13803
13907
  y: 0,
13804
13908
  nodeData: null
13805
13909
  });
13806
- const [multiContextMenu, setMultiContextMenu] = useState27({
13910
+ const [multiContextMenu, setMultiContextMenu] = useState29({
13807
13911
  visible: false,
13808
13912
  x: 0,
13809
13913
  y: 0,
13810
13914
  nodeIds: null
13811
13915
  });
13812
- const [relationshipMenu, setRelationshipMenu] = useState27({
13916
+ const [relationshipMenu, setRelationshipMenu] = useState29({
13813
13917
  visible: false,
13814
13918
  x: 0,
13815
13919
  y: 0,
13816
13920
  linkObject: null
13817
13921
  });
13818
- const [creationMode, setCreationMode] = useState27({
13922
+ const [creationMode, setCreationMode] = useState29({
13819
13923
  isActive: false,
13820
13924
  sourceNodeData: null
13821
13925
  });
13822
- const [versionMode, setVersionMode] = useState27({
13926
+ const [versionMode, setVersionMode] = useState29({
13823
13927
  isActive: false,
13824
13928
  sourceNodeData: null
13825
13929
  });
13826
- const [questMode, setQuestMode] = useState27({ isActive: false });
13827
- const [hasFocusedInitial, setHasFocusedInitial] = useState27(false);
13828
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState27(false);
13829
- const [ancestryMode, setAncestryMode] = useState27({
13930
+ const [questMode, setQuestMode] = useState29({ isActive: false });
13931
+ const [hasFocusedInitial, setHasFocusedInitial] = useState29(false);
13932
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState29(false);
13933
+ const [ancestryMode, setAncestryMode] = useState29({
13830
13934
  isActive: false,
13831
13935
  tree: null,
13832
13936
  selectedParentId: null,
@@ -13837,42 +13941,42 @@ function XViewScene({
13837
13941
  ancestryDescriptionSections: [],
13838
13942
  isAddingNodes: false
13839
13943
  });
13840
- const [readingMode, setReadingMode] = useState27({
13944
+ const [readingMode, setReadingMode] = useState29({
13841
13945
  isActive: false,
13842
13946
  ancestry: null,
13843
13947
  branchStack: [],
13844
13948
  autoAbstraction: false
13845
13949
  });
13846
- const [formPosition, setFormPosition] = useState27({
13950
+ const [formPosition, setFormPosition] = useState29({
13847
13951
  left: 16,
13848
13952
  top: 16,
13849
13953
  opacity: 0
13850
13954
  });
13851
- const [detailsNode, setDetailsNode] = useState27(null);
13852
- const [detailsLink, setDetailsLink] = useState27(null);
13853
- const [ancestryLinkDetails, setAncestryLinkDetails] = useState27(null);
13854
- const [imageViewer, setImageViewer] = useState27({
13955
+ const [detailsNode, setDetailsNode] = useState29(null);
13956
+ const [detailsLink, setDetailsLink] = useState29(null);
13957
+ const [ancestryLinkDetails, setAncestryLinkDetails] = useState29(null);
13958
+ const [imageViewer, setImageViewer] = useState29({
13855
13959
  visible: false,
13856
13960
  images: [],
13857
13961
  startIndex: 0
13858
13962
  });
13859
- const [editingAncestryRel, setEditingAncestryRel] = useState27({
13963
+ const [editingAncestryRel, setEditingAncestryRel] = useState29({
13860
13964
  visible: false,
13861
13965
  data: null,
13862
13966
  path: null
13863
13967
  });
13864
- const [isImportModalOpen, setIsImportModalOpen] = useState27(false);
13865
- const [importSuccessMessage, setImportSuccessMessage] = useState27("");
13866
- const [invalidTargetError, setInvalidTargetError] = useState27(null);
13867
- const [highlightedNodeId, setHighlightedNodeId] = useState27(null);
13868
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState27(false);
13869
- const [ancestryBoardData, setAncestryBoardData] = useState27([]);
13870
- const [isSidebarOpen, setIsSidebarOpen] = useState27(false);
13871
- const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState27(false);
13872
- const mountRef = useRef19(null);
13873
- const tooltipRef = useRef19(null);
13874
- const formRef = useRef19(null);
13875
- const stateRef = useRef19({
13968
+ const [isImportModalOpen, setIsImportModalOpen] = useState29(false);
13969
+ const [importSuccessMessage, setImportSuccessMessage] = useState29("");
13970
+ const [invalidTargetError, setInvalidTargetError] = useState29(null);
13971
+ const [highlightedNodeId, setHighlightedNodeId] = useState29(null);
13972
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState29(false);
13973
+ const [ancestryBoardData, setAncestryBoardData] = useState29([]);
13974
+ const [isSidebarOpen, setIsSidebarOpen] = useState29(false);
13975
+ const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState29(false);
13976
+ const mountRef = useRef20(null);
13977
+ const tooltipRef = useRef20(null);
13978
+ const formRef = useRef20(null);
13979
+ const stateRef = useRef20({
13876
13980
  readMode: {
13877
13981
  currentMaxIndex: 0,
13878
13982
  progressMap: {}
@@ -13936,10 +14040,10 @@ function XViewScene({
13936
14040
  minWidth: 320,
13937
14041
  maxWidth: maxReadPanelW
13938
14042
  });
13939
- useEffect22(() => {
14043
+ useEffect24(() => {
13940
14044
  stateRef.current.ancestry = ancestryMode;
13941
14045
  }, [ancestryMode]);
13942
- useEffect22(() => {
14046
+ useEffect24(() => {
13943
14047
  var _a2;
13944
14048
  if (!isInitialized) return;
13945
14049
  const map = /* @__PURE__ */ new Map();
@@ -13962,10 +14066,10 @@ function XViewScene({
13962
14066
  }
13963
14067
  stateRef.current.nodeIdToParentFileMap = map;
13964
14068
  }, [isInitialized, sceneVersion]);
13965
- const handleNavigateBack = useCallback4(() => {
14069
+ const handleNavigateBack = useCallback5(() => {
13966
14070
  router.push("/dashboard/scenes");
13967
14071
  }, [router]);
13968
- const handleConfirmImport = useCallback4(
14072
+ const handleConfirmImport = useCallback5(
13969
14073
  async (importPayload) => {
13970
14074
  var _a2, _b2;
13971
14075
  let files = [];
@@ -14093,7 +14197,7 @@ function XViewScene({
14093
14197
  const handleOpenImageViewer = (images, startIndex) => {
14094
14198
  setImageViewer({ visible: true, images, startIndex });
14095
14199
  };
14096
- const tweenToTarget = useCallback4(
14200
+ const tweenToTarget = useCallback5(
14097
14201
  (target, zoomFactor = 1, forcedDirection = null) => {
14098
14202
  const { camera, controls, tweenGroup } = stateRef.current;
14099
14203
  if (!camera || !controls || !tweenGroup) return;
@@ -14119,7 +14223,7 @@ function XViewScene({
14119
14223
  if (!t || typeof t.closest !== "function") return false;
14120
14224
  return !!t.closest(".ui-overlay");
14121
14225
  };
14122
- const buildFullAncestryTree = useCallback4(
14226
+ const buildFullAncestryTree = useCallback5(
14123
14227
  (idTree, nodes, ancestries = []) => {
14124
14228
  if (!idTree) return null;
14125
14229
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
@@ -14204,7 +14308,7 @@ function XViewScene({
14204
14308
  },
14205
14309
  []
14206
14310
  );
14207
- const handleActivateTimeline = useCallback4(() => {
14311
+ const handleActivateTimeline = useCallback5(() => {
14208
14312
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
14209
14313
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
14210
14314
  while (timelineIntervalsGroup.children.length > 0) {
@@ -14364,7 +14468,7 @@ function XViewScene({
14364
14468
  }
14365
14469
  });
14366
14470
  }, []);
14367
- const handleVersionTimeline = useCallback4((sourceMesh, versionMeshes) => {
14471
+ const handleVersionTimeline = useCallback5((sourceMesh, versionMeshes) => {
14368
14472
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
14369
14473
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
14370
14474
  return;
@@ -14501,7 +14605,7 @@ function XViewScene({
14501
14605
  }
14502
14606
  });
14503
14607
  }, []);
14504
- useEffect22(() => {
14608
+ useEffect24(() => {
14505
14609
  async function fetchAllData(configPath, ownerId2) {
14506
14610
  var _a2, _b2;
14507
14611
  if (!get_scene_view_data) {
@@ -14606,12 +14710,12 @@ function XViewScene({
14606
14710
  focusNodeId,
14607
14711
  focusAncestryId
14608
14712
  ]);
14609
- const isNodeInView = useCallback4((id) => {
14713
+ const isNodeInView = useCallback5((id) => {
14610
14714
  const key = String(id);
14611
14715
  const objs = stateRef.current.nodeObjects || {};
14612
14716
  return !!objs[key];
14613
14717
  }, []);
14614
- const addOrUpdateNodeMesh = useCallback4(
14718
+ const addOrUpdateNodeMesh = useCallback5(
14615
14719
  (nodeData, position, suppressVersionUpdate = false, forceShowQuestDate = false) => {
14616
14720
  const {
14617
14721
  graphGroup,
@@ -14652,7 +14756,7 @@ function XViewScene({
14652
14756
  },
14653
14757
  []
14654
14758
  );
14655
- const handleActivateQuestLens = useCallback4(({ assigneeId, status: status2, milestoneId }) => {
14759
+ const handleActivateQuestLens = useCallback5(({ assigneeId, status: status2, milestoneId }) => {
14656
14760
  var _a2;
14657
14761
  const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
14658
14762
  if (!nodeObjects || !tweenGroup || !graphGroup) return;
@@ -14866,7 +14970,7 @@ function XViewScene({
14866
14970
  camTween.start();
14867
14971
  }
14868
14972
  }, [addOrUpdateNodeMesh]);
14869
- useEffect22(() => {
14973
+ useEffect24(() => {
14870
14974
  if (!isInitialized || !sceneDataRef.current) return;
14871
14975
  const currentMount = mountRef.current;
14872
14976
  if (!currentMount) return;
@@ -15622,7 +15726,7 @@ function XViewScene({
15622
15726
  get_scene_view_data,
15623
15727
  save_view_data
15624
15728
  ]);
15625
- const handleGhostNodeImageChange = useCallback4((useImage, imageUrl) => {
15729
+ const handleGhostNodeImageChange = useCallback5((useImage, imageUrl) => {
15626
15730
  const {
15627
15731
  node: ghostNode,
15628
15732
  line: ghostLine,
@@ -15670,7 +15774,7 @@ function XViewScene({
15670
15774
  aura: newGhostNode.getObjectByName("aura")
15671
15775
  };
15672
15776
  }, []);
15673
- const handleGhostNodeIntensityChange = useCallback4((newIntensity) => {
15777
+ const handleGhostNodeIntensityChange = useCallback5((newIntensity) => {
15674
15778
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
15675
15779
  if (!ghostNode) return;
15676
15780
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -15691,7 +15795,7 @@ function XViewScene({
15691
15795
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
15692
15796
  }
15693
15797
  }, []);
15694
- const handleDetailNodeIntensityChange = useCallback4(
15798
+ const handleDetailNodeIntensityChange = useCallback5(
15695
15799
  (nodeId, newIntensity) => {
15696
15800
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
15697
15801
  if (!mesh) return;
@@ -15847,7 +15951,7 @@ function XViewScene({
15847
15951
  mountRef.current.style.cursor = "default";
15848
15952
  }
15849
15953
  };
15850
- const handleAncestryTreeUpdate = useCallback4((newTree, extraData = null) => {
15954
+ const handleAncestryTreeUpdate = useCallback5((newTree, extraData = null) => {
15851
15955
  setAncestryMode((prev) => {
15852
15956
  const prevTreeStr = JSON.stringify(prev.tree);
15853
15957
  const newTreeStr = JSON.stringify(newTree);
@@ -15870,7 +15974,7 @@ function XViewScene({
15870
15974
  };
15871
15975
  });
15872
15976
  }, []);
15873
- const actionHandlerContext = useMemo12(
15977
+ const actionHandlerContext = useMemo13(
15874
15978
  () => {
15875
15979
  var _a2;
15876
15980
  return {
@@ -15931,7 +16035,7 @@ function XViewScene({
15931
16035
  const handleStartVersioning = (nodeData) => {
15932
16036
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
15933
16037
  };
15934
- const handleStartQuestQuick = useCallback4((questNode) => {
16038
+ const handleStartQuestQuick = useCallback5((questNode) => {
15935
16039
  var _a2, _b2, _c2;
15936
16040
  if (!questNode || !actionHandlerContext) return;
15937
16041
  const allParentNodes = Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
@@ -15966,7 +16070,7 @@ function XViewScene({
15966
16070
  }
15967
16071
  setDetailsNode(updatedNode);
15968
16072
  }, [session, actionHandlerContext]);
15969
- const handleFinishQuestQuick = useCallback4((questNode) => {
16073
+ const handleFinishQuestQuick = useCallback5((questNode) => {
15970
16074
  var _a2, _b2, _c2, _d2;
15971
16075
  if (!questNode || !actionHandlerContext) return;
15972
16076
  const {
@@ -16040,7 +16144,7 @@ function XViewScene({
16040
16144
  setDetailsNode(null);
16041
16145
  }
16042
16146
  }, [session, actionHandlerContext, viewMembers, detailsNode]);
16043
- const handleCancelQuest = useCallback4(() => {
16147
+ const handleCancelQuest = useCallback5(() => {
16044
16148
  const { graphGroup, ghostElements } = stateRef.current;
16045
16149
  if (ghostElements.node && graphGroup) {
16046
16150
  if (ghostElements.node.userData.labelObject) {
@@ -16104,6 +16208,10 @@ function XViewScene({
16104
16208
  ownerId: ownerId2,
16105
16209
  datasetName: "Quests Internas (View)"
16106
16210
  });
16211
+ sceneDataRef2.current.quest_nodes = [...graphDataRef.current[sceneConfigId2].nodes];
16212
+ if (parentDataRef.current[sceneConfigId2]) {
16213
+ parentDataRef.current[sceneConfigId2].nodes = [...graphDataRef.current[sceneConfigId2].nodes];
16214
+ }
16107
16215
  const finalPosition = stateRef2.current.ghostElements.node ? stateRef2.current.ghostElements.node.position.clone() : stateRef2.current.controls.target.clone();
16108
16216
  const { graphGroup, ghostElements } = stateRef2.current;
16109
16217
  if (ghostElements.node && graphGroup) {
@@ -16193,7 +16301,7 @@ function XViewScene({
16193
16301
  }
16194
16302
  userActionHandlers.handleCancelConnection(context);
16195
16303
  };
16196
- const handleClearAncestryVisuals = useCallback4((ancestryId) => {
16304
+ const handleClearAncestryVisuals = useCallback5((ancestryId) => {
16197
16305
  const { renderedAncestries, ancestryGroup } = stateRef.current;
16198
16306
  const renderIndex = renderedAncestries.findIndex(
16199
16307
  (a) => String(a.id) === String(ancestryId)
@@ -16211,7 +16319,7 @@ function XViewScene({
16211
16319
  );
16212
16320
  }
16213
16321
  }, []);
16214
- const handleRenderAncestry = useCallback4(
16322
+ const handleRenderAncestry = useCallback5(
16215
16323
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
16216
16324
  setContextMenu(
16217
16325
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16705,7 +16813,7 @@ function XViewScene({
16705
16813
  ancestryMode.isActive
16706
16814
  ]
16707
16815
  );
16708
- const handleRenderAbstractionTree = useCallback4(
16816
+ const handleRenderAbstractionTree = useCallback5(
16709
16817
  (ancestryObject, targetNodeId = null) => {
16710
16818
  setContextMenu(
16711
16819
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16793,7 +16901,7 @@ function XViewScene({
16793
16901
  handleClearAncestryVisuals
16794
16902
  ]
16795
16903
  );
16796
- const handleReadModeBranchNav = useCallback4(
16904
+ const handleReadModeBranchNav = useCallback5(
16797
16905
  (nodeId, action, direction = "right") => {
16798
16906
  const { ancestry, branchStack } = readingMode;
16799
16907
  if (!ancestry || !ancestry.tree) return;
@@ -16971,13 +17079,13 @@ function XViewScene({
16971
17079
  },
16972
17080
  [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
16973
17081
  );
16974
- const handleReadModeHighlight = useCallback4((nodeId) => {
17082
+ const handleReadModeHighlight = useCallback5((nodeId) => {
16975
17083
  if (stateRef.current.highlightedNodeId !== nodeId) {
16976
17084
  stateRef.current.highlightedNodeId = nodeId;
16977
17085
  }
16978
17086
  setHighlightedNodeId(nodeId);
16979
17087
  }, []);
16980
- const activeNodeBranches = useMemo12(() => {
17088
+ const activeNodeBranches = useMemo13(() => {
16981
17089
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
16982
17090
  return null;
16983
17091
  const fullTree = buildFullAncestryTree(
@@ -17021,7 +17129,7 @@ function XViewScene({
17021
17129
  readingMode.branchStack,
17022
17130
  ancestryDataRef.current
17023
17131
  ]);
17024
- const backNavigationInfo = useMemo12(() => {
17132
+ const backNavigationInfo = useMemo13(() => {
17025
17133
  const { branchStack } = readingMode;
17026
17134
  if (!branchStack || branchStack.length === 0) return null;
17027
17135
  const lastStep = branchStack[branchStack.length - 1];
@@ -17032,7 +17140,7 @@ function XViewScene({
17032
17140
  name: "Voltar para anterior"
17033
17141
  };
17034
17142
  }, [readingMode.branchStack]);
17035
- const getReadModeDisplayContext = useMemo12(() => {
17143
+ const getReadModeDisplayContext = useMemo13(() => {
17036
17144
  const { ancestry, branchStack } = readingMode;
17037
17145
  if (!ancestry) return null;
17038
17146
  if (branchStack.length === 0) {
@@ -17075,7 +17183,7 @@ function XViewScene({
17075
17183
  customProperties: branchProps
17076
17184
  };
17077
17185
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
17078
- const readModeAbstractionTree = useMemo12(() => {
17186
+ const readModeAbstractionTree = useMemo13(() => {
17079
17187
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
17080
17188
  return null;
17081
17189
  }
@@ -17094,7 +17202,7 @@ function XViewScene({
17094
17202
  buildFullAncestryTree,
17095
17203
  sceneVersion
17096
17204
  ]);
17097
- const handleStartReadingAncestry = useCallback4(
17205
+ const handleStartReadingAncestry = useCallback5(
17098
17206
  async (ancestryObject, renderMode = "full") => {
17099
17207
  setContextMenu(
17100
17208
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17137,7 +17245,7 @@ function XViewScene({
17137
17245
  },
17138
17246
  [handleRenderAncestry, handleRenderAbstractionTree]
17139
17247
  );
17140
- const handleReadModeSectionChange = useCallback4(
17248
+ const handleReadModeSectionChange = useCallback5(
17141
17249
  (activeSectionId) => {
17142
17250
  const { ancestry, branchStack } = readingMode;
17143
17251
  if (!ancestry || !readingMode.isActive) return;
@@ -17222,10 +17330,10 @@ function XViewScene({
17222
17330
  ancestryDataRef.current
17223
17331
  ]
17224
17332
  );
17225
- const handleCloseReadMode = useCallback4(() => {
17333
+ const handleCloseReadMode = useCallback5(() => {
17226
17334
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
17227
17335
  }, []);
17228
- const handleAncestrySectionChange = useCallback4(
17336
+ const handleAncestrySectionChange = useCallback5(
17229
17337
  (activeSectionId, ancestryOverride = null, rotation = 0) => {
17230
17338
  var _a2, _b2;
17231
17339
  const currentMode = stateRef.current.ancestry;
@@ -17287,7 +17395,7 @@ function XViewScene({
17287
17395
  },
17288
17396
  [handleRenderAncestry]
17289
17397
  );
17290
- const handleEditAncestry = useCallback4(
17398
+ const handleEditAncestry = useCallback5(
17291
17399
  async (ancestryObject) => {
17292
17400
  setContextMenu(
17293
17401
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17342,7 +17450,7 @@ function XViewScene({
17342
17450
  const handleSelectAncestryParent = (nodeId) => {
17343
17451
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
17344
17452
  };
17345
- const handleRemoveFromAncestry = useCallback4((pathToRemove) => {
17453
+ const handleRemoveFromAncestry = useCallback5((pathToRemove) => {
17346
17454
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
17347
17455
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
17348
17456
  return;
@@ -17367,7 +17475,7 @@ function XViewScene({
17367
17475
  return { ...prev, tree: newTree };
17368
17476
  });
17369
17477
  }, []);
17370
- const handleSaveAncestry = useCallback4(
17478
+ const handleSaveAncestry = useCallback5(
17371
17479
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
17372
17480
  const treeToUse = treeOverride || ancestryMode.tree;
17373
17481
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -17603,7 +17711,7 @@ function XViewScene({
17603
17711
  });
17604
17712
  setEditingAncestryRel({ visible: false, data: null, path: null });
17605
17713
  };
17606
- const handleDeleteAncestry = useCallback4(
17714
+ const handleDeleteAncestry = useCallback5(
17607
17715
  async (ancestryIdToDelete) => {
17608
17716
  if (!ancestryIdToDelete) {
17609
17717
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -17685,18 +17793,70 @@ function XViewScene({
17685
17793
  },
17686
17794
  [save_view_data, delete_file_action]
17687
17795
  );
17688
- const handleOpenAncestryBoard = useCallback4(() => {
17796
+ const handleOpenAncestryBoard = useCallback5(() => {
17689
17797
  setIsAncestryBoardOpen(true);
17690
17798
  }, []);
17691
- const handleSelectAncestryFromBoard = useCallback4(
17692
- (ancestry) => {
17799
+ const allAvailableNodes = useMemo13(() => {
17800
+ if (!parentDataRef.current) return [];
17801
+ return Object.values(parentDataRef.current).flatMap(
17802
+ (fileData) => fileData.nodes || []
17803
+ );
17804
+ }, [sceneVersion, isInitialized]);
17805
+ const allAvailableAncestries = useMemo13(() => {
17806
+ return ancestryDataRef.current || [];
17807
+ }, [sceneVersion, isInitialized]);
17808
+ const handleOpenReference = useCallback5(
17809
+ (referenceData) => {
17810
+ const { type, id } = referenceData;
17811
+ if (type === "node") {
17812
+ const targetNode = allAvailableNodes.find(
17813
+ (n) => String(n.id) === String(id)
17814
+ );
17815
+ if (targetNode) {
17816
+ setAncestryLinkDetails(null);
17817
+ setDetailsLink(null);
17818
+ setDetailsNode(targetNode);
17819
+ const sceneMesh = stateRef.current.nodeObjects[String(id)];
17820
+ if (sceneMesh) {
17821
+ tweenToTarget(sceneMesh);
17822
+ }
17823
+ } else {
17824
+ alert("Node original n\xE3o encontrado neste contexto.");
17825
+ }
17826
+ } else if (type === "ancestry") {
17827
+ const targetAncestry = allAvailableAncestries.find(
17828
+ (a) => String(a.ancestry_id) === String(id)
17829
+ );
17830
+ if (targetAncestry) {
17831
+ setDetailsNode(null);
17832
+ setDetailsLink(null);
17833
+ setAncestryLinkDetails(null);
17834
+ handleEditAncestry(targetAncestry);
17835
+ } else {
17836
+ alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17837
+ }
17838
+ }
17839
+ },
17840
+ [
17841
+ allAvailableNodes,
17842
+ allAvailableAncestries,
17843
+ handleEditAncestry,
17844
+ tweenToTarget
17845
+ ]
17846
+ );
17847
+ const handleSelectAncestryFromBoard = useCallback5(
17848
+ (item) => {
17693
17849
  setIsAncestryBoardOpen(false);
17694
17850
  setIsSidebarOpen(false);
17695
- handleStartReadingAncestry(ancestry);
17851
+ if (item.type === "ancestry") {
17852
+ handleStartReadingAncestry(item);
17853
+ } else {
17854
+ handleOpenReference({ type: "node", id: item.id });
17855
+ }
17696
17856
  },
17697
- [handleStartReadingAncestry]
17857
+ [handleStartReadingAncestry, handleOpenReference]
17698
17858
  );
17699
- const handleSaveAncestryBoard = useCallback4(
17859
+ const handleSaveAncestryBoard = useCallback5(
17700
17860
  async (groups) => {
17701
17861
  if (!sceneConfigId || !viewParams || !session) return;
17702
17862
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
@@ -17710,7 +17870,7 @@ function XViewScene({
17710
17870
  },
17711
17871
  [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
17712
17872
  );
17713
- const existingNodeTypes = useMemo12(() => {
17873
+ const existingNodeTypes = useMemo13(() => {
17714
17874
  if (!parentDataRef.current) {
17715
17875
  return [];
17716
17876
  }
@@ -17722,7 +17882,7 @@ function XViewScene({
17722
17882
  ).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
17723
17883
  return [...new Set(allTypes)];
17724
17884
  }, [parentDataRef.current, sceneVersion]);
17725
- const searchableDbNodes = useMemo12(() => {
17885
+ const searchableDbNodes = useMemo13(() => {
17726
17886
  if (!parentDataRef.current) {
17727
17887
  return [];
17728
17888
  }
@@ -17737,7 +17897,7 @@ function XViewScene({
17737
17897
  return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
17738
17898
  });
17739
17899
  }, [parentDataRef.current, sceneVersion]);
17740
- const handleAddExistingNode = useCallback4(
17900
+ const handleAddExistingNode = useCallback5(
17741
17901
  (nodeId) => {
17742
17902
  return userActionHandlers.handleAddExistingNodeById(
17743
17903
  actionHandlerContext,
@@ -17746,7 +17906,7 @@ function XViewScene({
17746
17906
  },
17747
17907
  [actionHandlerContext]
17748
17908
  );
17749
- const handleUpdateMilestones = useCallback4(
17909
+ const handleUpdateMilestones = useCallback5(
17750
17910
  async (newMilestones) => {
17751
17911
  var _a2, _b2, _c2;
17752
17912
  if (!sceneDataRef.current) return;
@@ -17792,7 +17952,7 @@ function XViewScene({
17792
17952
  viewParams == null ? void 0 : viewParams.type
17793
17953
  ]
17794
17954
  );
17795
- const handleSaveCurrentView = useCallback4(async () => {
17955
+ const handleSaveCurrentView = useCallback5(async () => {
17796
17956
  var _a2, _b2, _c2;
17797
17957
  const { nodeObjects, allLinks } = stateRef.current;
17798
17958
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
@@ -17835,61 +17995,13 @@ function XViewScene({
17835
17995
  console.error("Erro na chamada de save_view_data:", error);
17836
17996
  }
17837
17997
  }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
17838
- const allAvailableNodes = useMemo12(() => {
17839
- if (!parentDataRef.current) return [];
17840
- return Object.values(parentDataRef.current).flatMap(
17841
- (fileData) => fileData.nodes || []
17842
- );
17843
- }, [sceneVersion, isInitialized]);
17844
- const allAvailableAncestries = useMemo12(() => {
17845
- return ancestryDataRef.current || [];
17846
- }, [sceneVersion, isInitialized]);
17847
- const handleOpenReference = useCallback4(
17848
- (referenceData) => {
17849
- const { type, id } = referenceData;
17850
- if (type === "node") {
17851
- const targetNode = allAvailableNodes.find(
17852
- (n) => String(n.id) === String(id)
17853
- );
17854
- if (targetNode) {
17855
- setAncestryLinkDetails(null);
17856
- setDetailsLink(null);
17857
- setDetailsNode(targetNode);
17858
- const sceneMesh = stateRef.current.nodeObjects[String(id)];
17859
- if (sceneMesh) {
17860
- tweenToTarget(sceneMesh);
17861
- }
17862
- } else {
17863
- alert("Node original n\xE3o encontrado neste contexto.");
17864
- }
17865
- } else if (type === "ancestry") {
17866
- const targetAncestry = allAvailableAncestries.find(
17867
- (a) => String(a.ancestry_id) === String(id)
17868
- );
17869
- if (targetAncestry) {
17870
- setDetailsNode(null);
17871
- setDetailsLink(null);
17872
- setAncestryLinkDetails(null);
17873
- handleEditAncestry(targetAncestry);
17874
- } else {
17875
- alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17876
- }
17877
- }
17878
- },
17879
- [
17880
- allAvailableNodes,
17881
- allAvailableAncestries,
17882
- handleEditAncestry,
17883
- tweenToTarget
17884
- ]
17885
- );
17886
- const handleToggleAncestryAddMode = useCallback4(() => {
17998
+ const handleToggleAncestryAddMode = useCallback5(() => {
17887
17999
  setAncestryMode((prev) => ({
17888
18000
  ...prev,
17889
18001
  isAddingNodes: !prev.isAddingNodes
17890
18002
  }));
17891
18003
  }, []);
17892
- const handleFocusNode = useCallback4(
18004
+ const handleFocusNode = useCallback5(
17893
18005
  (nodeData) => {
17894
18006
  var _a2;
17895
18007
  if (!nodeData) return;
@@ -17905,7 +18017,7 @@ function XViewScene({
17905
18017
  },
17906
18018
  [tweenToTarget]
17907
18019
  );
17908
- const availableDatasets = useMemo12(() => {
18020
+ const availableDatasets = useMemo13(() => {
17909
18021
  if (!sceneDataRef.current || !parentDataRef.current) return [];
17910
18022
  return sceneDataRef.current.parent_dbs.map((db) => {
17911
18023
  var _a2;
@@ -17919,7 +18031,7 @@ function XViewScene({
17919
18031
  String(creationMode.sourceNodeData.id)
17920
18032
  )) == null ? void 0 : _b.parentFileId : null;
17921
18033
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
17922
- useEffect22(() => {
18034
+ useEffect24(() => {
17923
18035
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
17924
18036
  const nodeObjects = stateRef.current.nodeObjects || {};
17925
18037
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -17942,7 +18054,7 @@ function XViewScene({
17942
18054
  hasFocusedInitial,
17943
18055
  tweenToTarget
17944
18056
  ]);
17945
- useEffect22(() => {
18057
+ useEffect24(() => {
17946
18058
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
17947
18059
  const ancestries = ancestryDataRef.current || [];
17948
18060
  const targetAncestry = ancestries.find(
@@ -17967,7 +18079,7 @@ function XViewScene({
17967
18079
  hasOpenedInitialAncestry,
17968
18080
  handleStartReadingAncestry
17969
18081
  ]);
17970
- useEffect22(() => {
18082
+ useEffect24(() => {
17971
18083
  function handleKeyDown(event) {
17972
18084
  var _a2, _b2, _c2;
17973
18085
  const context = actionHandlerContext;
@@ -18090,10 +18202,10 @@ function XViewScene({
18090
18202
  // <-- handleCancelQuest adicionado aqui
18091
18203
  ]);
18092
18204
  if (isLoading || status === "loading" || permissionStatus === "loading") {
18093
- return /* @__PURE__ */ React28.createElement(LoadingScreen, null);
18205
+ return /* @__PURE__ */ React30.createElement(LoadingScreen, null);
18094
18206
  }
18095
18207
  if (permissionStatus === "denied") {
18096
- 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(
18208
+ 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(
18097
18209
  "svg",
18098
18210
  {
18099
18211
  xmlns: "http://www.w3.org/2000/svg",
@@ -18103,7 +18215,7 @@ function XViewScene({
18103
18215
  stroke: "currentColor",
18104
18216
  className: "w-16 h-16 mx-auto"
18105
18217
  },
18106
- /* @__PURE__ */ React28.createElement(
18218
+ /* @__PURE__ */ React30.createElement(
18107
18219
  "path",
18108
18220
  {
18109
18221
  strokeLinecap: "round",
@@ -18111,13 +18223,13 @@ function XViewScene({
18111
18223
  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"
18112
18224
  }
18113
18225
  )
18114
- )), /* @__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(
18226
+ )), /* @__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(
18115
18227
  "button",
18116
18228
  {
18117
18229
  onClick: () => router.push("/dashboard/scenes"),
18118
18230
  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"
18119
18231
  },
18120
- /* @__PURE__ */ React28.createElement(
18232
+ /* @__PURE__ */ React30.createElement(
18121
18233
  "svg",
18122
18234
  {
18123
18235
  xmlns: "http://www.w3.org/2000/svg",
@@ -18127,7 +18239,7 @@ function XViewScene({
18127
18239
  stroke: "currentColor",
18128
18240
  className: "w-5 h-5"
18129
18241
  },
18130
- /* @__PURE__ */ React28.createElement(
18242
+ /* @__PURE__ */ React30.createElement(
18131
18243
  "path",
18132
18244
  {
18133
18245
  strokeLinecap: "round",
@@ -18139,7 +18251,7 @@ function XViewScene({
18139
18251
  "Voltar para Scenes"
18140
18252
  )));
18141
18253
  }
18142
- return /* @__PURE__ */ React28.createElement(
18254
+ return /* @__PURE__ */ React30.createElement(
18143
18255
  "div",
18144
18256
  {
18145
18257
  ref: mountRef,
@@ -18151,7 +18263,7 @@ function XViewScene({
18151
18263
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
18152
18264
  }
18153
18265
  },
18154
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ React28.createElement(
18266
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ React30.createElement(
18155
18267
  XViewSidebar,
18156
18268
  {
18157
18269
  dbNodes: searchableDbNodes,
@@ -18175,7 +18287,7 @@ function XViewScene({
18175
18287
  onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
18176
18288
  }
18177
18289
  ),
18178
- creationMode.isActive && /* @__PURE__ */ React28.createElement(
18290
+ creationMode.isActive && /* @__PURE__ */ React30.createElement(
18179
18291
  InSceneCreationForm,
18180
18292
  {
18181
18293
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -18207,7 +18319,7 @@ function XViewScene({
18207
18319
  availableAncestries: allAvailableAncestries
18208
18320
  }
18209
18321
  ),
18210
- versionMode.isActive && /* @__PURE__ */ React28.createElement(
18322
+ versionMode.isActive && /* @__PURE__ */ React30.createElement(
18211
18323
  InSceneVersionForm,
18212
18324
  {
18213
18325
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -18233,7 +18345,7 @@ function XViewScene({
18233
18345
  availableAncestries: allAvailableAncestries
18234
18346
  }
18235
18347
  ),
18236
- questMode.isActive && /* @__PURE__ */ React28.createElement(
18348
+ questMode.isActive && /* @__PURE__ */ React30.createElement(
18237
18349
  InSceneQuestForm,
18238
18350
  {
18239
18351
  onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
@@ -18261,7 +18373,7 @@ function XViewScene({
18261
18373
  onUpdateMilestones: handleUpdateMilestones
18262
18374
  }
18263
18375
  ),
18264
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React28.createElement(
18376
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React30.createElement(
18265
18377
  "div",
18266
18378
  {
18267
18379
  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"}`,
@@ -18274,7 +18386,7 @@ function XViewScene({
18274
18386
  maxWidth: "92vw"
18275
18387
  }
18276
18388
  },
18277
- /* @__PURE__ */ React28.createElement(
18389
+ /* @__PURE__ */ React30.createElement(
18278
18390
  "div",
18279
18391
  {
18280
18392
  onPointerDown: (e) => {
@@ -18285,7 +18397,7 @@ function XViewScene({
18285
18397
  title: "Arraste para redimensionar"
18286
18398
  }
18287
18399
  ),
18288
- /* @__PURE__ */ React28.createElement(
18400
+ /* @__PURE__ */ React30.createElement(
18289
18401
  DescriptionReadModePanel,
18290
18402
  {
18291
18403
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -18320,7 +18432,7 @@ function XViewScene({
18320
18432
  }
18321
18433
  )
18322
18434
  ),
18323
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React28.createElement(
18435
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React30.createElement(
18324
18436
  CreateAncestryPanel,
18325
18437
  {
18326
18438
  ancestryMode,
@@ -18356,7 +18468,7 @@ function XViewScene({
18356
18468
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
18357
18469
  }
18358
18470
  ),
18359
- editingAncestryRel.visible && /* @__PURE__ */ React28.createElement(
18471
+ editingAncestryRel.visible && /* @__PURE__ */ React30.createElement(
18360
18472
  AncestryRelationshipPanel,
18361
18473
  {
18362
18474
  data: editingAncestryRel.data,
@@ -18370,7 +18482,7 @@ function XViewScene({
18370
18482
  onUploadFile: upload_file_action
18371
18483
  }
18372
18484
  ),
18373
- detailsNode && detailsNode.is_quest && /* @__PURE__ */ React28.createElement(
18485
+ detailsNode && detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
18374
18486
  QuestDetailsPanel,
18375
18487
  {
18376
18488
  node: detailsNode,
@@ -18396,7 +18508,7 @@ function XViewScene({
18396
18508
  onUpdateMilestones: handleUpdateMilestones
18397
18509
  }
18398
18510
  ),
18399
- detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React28.createElement(
18511
+ detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
18400
18512
  NodeDetailsPanel,
18401
18513
  {
18402
18514
  node: detailsNode,
@@ -18428,7 +18540,7 @@ function XViewScene({
18428
18540
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
18429
18541
  }
18430
18542
  ),
18431
- detailsLink && /* @__PURE__ */ React28.createElement(
18543
+ detailsLink && /* @__PURE__ */ React30.createElement(
18432
18544
  RelationshipDetailsPanel,
18433
18545
  {
18434
18546
  link: detailsLink,
@@ -18442,7 +18554,7 @@ function XViewScene({
18442
18554
  userRole: userPermissionRole
18443
18555
  }
18444
18556
  ),
18445
- ancestryLinkDetails && /* @__PURE__ */ React28.createElement(
18557
+ ancestryLinkDetails && /* @__PURE__ */ React30.createElement(
18446
18558
  AncestryLinkDetailsPanel,
18447
18559
  {
18448
18560
  data: ancestryLinkDetails,
@@ -18453,7 +18565,7 @@ function XViewScene({
18453
18565
  onUploadFile: upload_file_action
18454
18566
  }
18455
18567
  ),
18456
- /* @__PURE__ */ React28.createElement(
18568
+ /* @__PURE__ */ React30.createElement(
18457
18569
  "div",
18458
18570
  {
18459
18571
  ref: tooltipRef,
@@ -18480,7 +18592,7 @@ function XViewScene({
18480
18592
  }
18481
18593
  }
18482
18594
  ),
18483
- /* @__PURE__ */ React28.createElement(
18595
+ /* @__PURE__ */ React30.createElement(
18484
18596
  ContextMenu,
18485
18597
  {
18486
18598
  data: contextMenu,
@@ -18513,7 +18625,7 @@ function XViewScene({
18513
18625
  onFinishQuest: handleFinishQuestQuick
18514
18626
  }
18515
18627
  ),
18516
- /* @__PURE__ */ React28.createElement(
18628
+ /* @__PURE__ */ React30.createElement(
18517
18629
  MultiNodeContextMenu,
18518
18630
  {
18519
18631
  data: multiContextMenu,
@@ -18533,7 +18645,7 @@ function XViewScene({
18533
18645
  )
18534
18646
  }
18535
18647
  ),
18536
- /* @__PURE__ */ React28.createElement(
18648
+ /* @__PURE__ */ React30.createElement(
18537
18649
  RelationshipContextMenu,
18538
18650
  {
18539
18651
  data: relationshipMenu,
@@ -18551,14 +18663,14 @@ function XViewScene({
18551
18663
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
18552
18664
  }
18553
18665
  ),
18554
- /* @__PURE__ */ React28.createElement(
18666
+ /* @__PURE__ */ React30.createElement(
18555
18667
  ImageViewer,
18556
18668
  {
18557
18669
  data: imageViewer,
18558
18670
  onClose: () => setImageViewer({ ...imageViewer, visible: false })
18559
18671
  }
18560
18672
  ),
18561
- /* @__PURE__ */ React28.createElement(
18673
+ /* @__PURE__ */ React30.createElement(
18562
18674
  AncestryBoard,
18563
18675
  {
18564
18676
  isOpen: isAncestryBoardOpen,
@@ -18571,7 +18683,7 @@ function XViewScene({
18571
18683
  userRole: userPermissionRole
18572
18684
  }
18573
18685
  ),
18574
- /* @__PURE__ */ React28.createElement(
18686
+ /* @__PURE__ */ React30.createElement(
18575
18687
  MilestoneManager,
18576
18688
  {
18577
18689
  isOpen: isMilestoneManagerOpen,
@@ -18580,7 +18692,7 @@ function XViewScene({
18580
18692
  onUpdateMilestones: handleUpdateMilestones
18581
18693
  }
18582
18694
  ),
18583
- /* @__PURE__ */ React28.createElement(
18695
+ /* @__PURE__ */ React30.createElement(
18584
18696
  ImportParentFileModal,
18585
18697
  {
18586
18698
  isOpen: isImportModalOpen,
@@ -18593,7 +18705,7 @@ function XViewScene({
18593
18705
  currentAncestries: ancestryDataRef.current || []
18594
18706
  }
18595
18707
  ),
18596
- invalidTargetError && /* @__PURE__ */ React28.createElement(
18708
+ invalidTargetError && /* @__PURE__ */ React30.createElement(
18597
18709
  "div",
18598
18710
  {
18599
18711
  className: "ui-overlay",
@@ -18618,13 +18730,13 @@ function XViewScene({
18618
18730
  animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
18619
18731
  }
18620
18732
  },
18621
- /* @__PURE__ */ React28.createElement("style", null, `
18733
+ /* @__PURE__ */ React30.createElement("style", null, `
18622
18734
  @keyframes fadeInDown {
18623
18735
  from { opacity: 0; transform: translate(-50%, -20px); }
18624
18736
  to { opacity: 1; transform: translate(-50%, 0); }
18625
18737
  }
18626
18738
  `),
18627
- /* @__PURE__ */ React28.createElement(
18739
+ /* @__PURE__ */ React30.createElement(
18628
18740
  "svg",
18629
18741
  {
18630
18742
  width: "20",
@@ -18636,12 +18748,12 @@ function XViewScene({
18636
18748
  strokeLinecap: "round",
18637
18749
  strokeLinejoin: "round"
18638
18750
  },
18639
- /* @__PURE__ */ React28.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18640
- /* @__PURE__ */ React28.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18641
- /* @__PURE__ */ React28.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18751
+ /* @__PURE__ */ React30.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18752
+ /* @__PURE__ */ React30.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18753
+ /* @__PURE__ */ React30.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18642
18754
  ),
18643
- /* @__PURE__ */ React28.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18644
- /* @__PURE__ */ React28.createElement(
18755
+ /* @__PURE__ */ React30.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18756
+ /* @__PURE__ */ React30.createElement(
18645
18757
  "button",
18646
18758
  {
18647
18759
  onClick: () => setInvalidTargetError(null),