@lv-x-software-house/x_view 1.2.6-dev.1 → 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);
@@ -2318,8 +2275,6 @@ var userActionHandlers = {
2318
2275
  milestones: sceneDataRef.current.milestones || [],
2319
2276
  quest_counter: sceneDataRef.current.quest_counter || 1
2320
2277
  };
2321
- sceneDataRef.current.quest_nodes = specificParentData.nodes;
2322
- sceneDataRef.current.quest_links = specificParentData.links;
2323
2278
  await context.actions.save_view_data(
2324
2279
  context.sceneSaveUrl,
2325
2280
  viewFilePayload
@@ -2332,6 +2287,10 @@ var userActionHandlers = {
2332
2287
  );
2333
2288
  }
2334
2289
  graphDataRef.current[parentFileId] = specificParentData;
2290
+ if (isView && parentFileId === context.sceneConfigId) {
2291
+ sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
2292
+ sceneDataRef.current.quest_counter = specificParentData.quest_counter || sceneDataRef.current.quest_counter;
2293
+ }
2335
2294
  updateExistingNodeVisuals(stateRef.current, nodeToSave);
2336
2295
  setters.setSceneVersion((v) => v + 1);
2337
2296
  if (!keepOpen) {
@@ -2480,15 +2439,15 @@ function createNewCustomProperty(existingProps = []) {
2480
2439
  switch (nextType) {
2481
2440
  case "links":
2482
2441
  nextKey = "Links";
2483
- nextValue = [{ id: v4_default(), name: "", value: "" }];
2442
+ nextValue = [{ id: uuidv4(), name: "", value: "" }];
2484
2443
  break;
2485
2444
  case "images":
2486
2445
  nextKey = "Images";
2487
- nextValue = [{ id: v4_default(), name: "1", value: "" }];
2446
+ nextValue = [{ id: uuidv4(), name: "1", value: "" }];
2488
2447
  break;
2489
2448
  case "documents":
2490
2449
  nextKey = "Documents";
2491
- nextValue = [{ id: v4_default(), name: "1", value: "" }];
2450
+ nextValue = [{ id: uuidv4(), name: "1", value: "" }];
2492
2451
  break;
2493
2452
  case "date":
2494
2453
  nextKey = "Date";
@@ -2498,14 +2457,14 @@ function createNewCustomProperty(existingProps = []) {
2498
2457
  nextValue = 0;
2499
2458
  break;
2500
2459
  case "list":
2501
- nextValue = [{ id: v4_default(), name: "", value: "" }];
2460
+ nextValue = [{ id: uuidv4(), name: "", value: "" }];
2502
2461
  break;
2503
2462
  default:
2504
2463
  nextValue = "";
2505
2464
  break;
2506
2465
  }
2507
2466
  return {
2508
- id: v4_default(),
2467
+ id: uuidv4(),
2509
2468
  key: nextKey,
2510
2469
  type: nextType,
2511
2470
  value: nextValue,
@@ -2750,7 +2709,7 @@ function extractCustomPropsFromNode(node) {
2750
2709
  if (val && typeof val === "object") {
2751
2710
  if ("date_interval" in val) {
2752
2711
  return {
2753
- id: v4_default(),
2712
+ id: uuidv4(),
2754
2713
  key,
2755
2714
  type: "date",
2756
2715
  value: {
@@ -2762,7 +2721,7 @@ function extractCustomPropsFromNode(node) {
2762
2721
  }
2763
2722
  if ("year" in val) {
2764
2723
  return {
2765
- id: v4_default(),
2724
+ id: uuidv4(),
2766
2725
  key,
2767
2726
  type: "date",
2768
2727
  value: { type: "Ano", value: val.year || "" }
@@ -2770,7 +2729,7 @@ function extractCustomPropsFromNode(node) {
2770
2729
  }
2771
2730
  if ("date" in val) {
2772
2731
  return {
2773
- id: v4_default(),
2732
+ id: uuidv4(),
2774
2733
  key,
2775
2734
  type: "date",
2776
2735
  value: { type: "Data", value: val.date || "" }
@@ -2778,7 +2737,7 @@ function extractCustomPropsFromNode(node) {
2778
2737
  }
2779
2738
  }
2780
2739
  return {
2781
- id: v4_default(),
2740
+ id: uuidv4(),
2782
2741
  key,
2783
2742
  type: "date",
2784
2743
  value: { type: "Data", value: "" }
@@ -2786,14 +2745,14 @@ function extractCustomPropsFromNode(node) {
2786
2745
  }
2787
2746
  if (t === "list" || t === "links" || t === "images" || t === "documents") {
2788
2747
  const safeList = (val || []).map((item) => ({
2789
- id: item.id || v4_default(),
2748
+ id: item.id || uuidv4(),
2790
2749
  name: item.name ?? "",
2791
2750
  value: item.value ?? ""
2792
2751
  }));
2793
- return { id: v4_default(), key, type: t, value: safeList };
2752
+ return { id: uuidv4(), key, type: t, value: safeList };
2794
2753
  }
2795
2754
  return {
2796
- id: v4_default(),
2755
+ id: uuidv4(),
2797
2756
  key,
2798
2757
  type: t,
2799
2758
  value: t === "number" ? Number(val) || 0 : String(val ?? "")
@@ -3066,16 +3025,16 @@ var processDescriptionForSave = (text, existingSections = []) => {
3066
3025
  if (existingMatch) {
3067
3026
  finalUuid = existingMatch.id;
3068
3027
  } else {
3069
- finalUuid = v4_default();
3028
+ finalUuid = uuidv4();
3070
3029
  }
3071
3030
  } else {
3072
3031
  finalUuid = numericMap.get(numStr);
3073
3032
  if (!finalUuid) {
3074
- finalUuid = v4_default();
3033
+ finalUuid = uuidv4();
3075
3034
  }
3076
3035
  }
3077
3036
  if (usedIds.has(finalUuid)) {
3078
- finalUuid = v4_default();
3037
+ finalUuid = uuidv4();
3079
3038
  }
3080
3039
  usedIds.add(finalUuid);
3081
3040
  processedSections.push({
@@ -3186,18 +3145,18 @@ function useResizablePanel({ initialWidth, minWidth, maxWidth }) {
3186
3145
  function createTimelineEntry(actorId, description, type = "comment", extras = {}) {
3187
3146
  const { links = [], images = [], metadata = {} } = extras;
3188
3147
  return {
3189
- id: v4_default(),
3148
+ id: uuidv4(),
3190
3149
  type,
3191
3150
  timestamp: Date.now(),
3192
3151
  actorId,
3193
3152
  description,
3194
3153
  links: links.map((l) => ({
3195
- id: l.id || v4_default(),
3154
+ id: l.id || uuidv4(),
3196
3155
  name: l.name || "",
3197
3156
  value: l.value || ""
3198
3157
  })),
3199
3158
  images: images.map((img) => ({
3200
- id: img.id || v4_default(),
3159
+ id: img.id || uuidv4(),
3201
3160
  name: img.name || "",
3202
3161
  value: img.value || ""
3203
3162
  }))
@@ -4424,6 +4383,7 @@ function XViewSidebar({
4424
4383
 
4425
4384
  // src/components/AncestryRelationshipPanel.jsx
4426
4385
  import React8, { useState as useState9, useEffect as useEffect8, useRef as useRef7 } from "react";
4386
+ import { v4 as uuidv43 } from "uuid";
4427
4387
 
4428
4388
  // src/components/CustomPropertyDisplay.jsx
4429
4389
  import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
@@ -5183,6 +5143,7 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
5183
5143
  }
5184
5144
 
5185
5145
  // src/components/DescriptionEditModal.jsx
5146
+ import { v4 as uuidv42 } from "uuid";
5186
5147
  var getNextSectionNumber = (currentText) => {
5187
5148
  const regex = /\*\/\s*(\d+)(?::[a-zA-Z0-9-]+)?\s*\//g;
5188
5149
  let max = 0;
@@ -5314,7 +5275,7 @@ function DescriptionEditModal({
5314
5275
  const el = textareaRef.current;
5315
5276
  if (!el) return;
5316
5277
  const nextNum = getNextSectionNumber(text);
5317
- const uniqueSuffix = v4_default().slice(0, 4);
5278
+ const uniqueSuffix = uuidv42().slice(0, 4);
5318
5279
  insertAtCursor(`*/${nextNum}:${uniqueSuffix}/ `);
5319
5280
  };
5320
5281
  const handleImportSelect = (tags) => {
@@ -5325,7 +5286,7 @@ function DescriptionEditModal({
5325
5286
  let currentNum = getNextSectionNumber(currentText);
5326
5287
  let blockToInsert = "";
5327
5288
  tagsArray.forEach((tag) => {
5328
- const uniqueSuffix = v4_default().slice(0, 4);
5289
+ const uniqueSuffix = uuidv42().slice(0, 4);
5329
5290
  blockToInsert += `
5330
5291
  */${currentNum}:${uniqueSuffix}/ ${tag}
5331
5292
  `;
@@ -6685,6 +6646,7 @@ import {
6685
6646
  FiLink as FiLink4,
6686
6647
  FiTrash2 as FiTrash22
6687
6648
  } from "react-icons/fi";
6649
+ import { v4 as uuidv44 } from "uuid";
6688
6650
 
6689
6651
  // src/components/AncestryPickerModal.jsx
6690
6652
  import React9, { useState as useState10, useMemo as useMemo7, useEffect as useEffect9 } from "react";
@@ -7721,7 +7683,7 @@ function CreateAncestryPanel({
7721
7683
  const nodeData = availableNodes.find((n) => String(n.id) === String(nodeId));
7722
7684
  const dirSuffix = direction === "left" ? "(Esq)" : "(Dir)";
7723
7685
  branch = {
7724
- id: v4_default(),
7686
+ id: uuidv44(),
7725
7687
  name: `Ramifica\xE7\xE3o ${dirSuffix} de ${(nodeData == null ? void 0 : nodeData.name) || "Node"}`,
7726
7688
  description: "",
7727
7689
  description_sections: [],
@@ -8500,6 +8462,7 @@ function ImageViewer({ data, onClose }) {
8500
8462
 
8501
8463
  // src/components/InSceneCreationForm.jsx
8502
8464
  import React13, { useState as useState14, useEffect as useEffect13, useRef as useRef10 } from "react";
8465
+ import { v4 as uuidv45 } from "uuid";
8503
8466
 
8504
8467
  // src/components/ColorPicker.jsx
8505
8468
  import React12, { useState as useState13, useEffect as useEffect12, useRef as useRef9 } from "react";
@@ -9084,6 +9047,7 @@ function InSceneCreationForm({
9084
9047
 
9085
9048
  // src/components/InSceneVersionForm.jsx
9086
9049
  import React14, { useState as useState15, useEffect as useEffect14, useRef as useRef11 } from "react";
9050
+ import { v4 as uuidv46 } from "uuid";
9087
9051
  import { FiPlus as FiPlus4, FiMaximize2 as FiMaximize22, FiCheck as FiCheck8, FiEdit2 as FiEdit25 } from "react-icons/fi";
9088
9052
  function InSceneVersionForm({
9089
9053
  onSave,
@@ -9106,7 +9070,7 @@ function InSceneVersionForm({
9106
9070
  const [description, setDescription] = useState15("");
9107
9071
  const [customProps, setCustomProps] = useState15([
9108
9072
  {
9109
- id: v4_default(),
9073
+ id: uuidv46(),
9110
9074
  key: "Date",
9111
9075
  type: "date",
9112
9076
  value: { type: "Data", value: "" },
@@ -9399,6 +9363,7 @@ function InSceneVersionForm({
9399
9363
 
9400
9364
  // src/components/InSceneQuestForm.jsx
9401
9365
  import React16, { useState as useState17, useRef as useRef12 } from "react";
9366
+ import { v4 as uuidv47 } from "uuid";
9402
9367
  import {
9403
9368
  FiPlus as FiPlus6,
9404
9369
  FiCheck as FiCheck9,
@@ -10323,6 +10288,7 @@ function InSceneQuestForm({
10323
10288
 
10324
10289
  // src/components/NodeDetailsPanel.jsx
10325
10290
  import React17, { useState as useState18, useEffect as useEffect15, useRef as useRef13 } from "react";
10291
+ import { v4 as uuidv48 } from "uuid";
10326
10292
  import { FiPlus as FiPlus7, FiMaximize2 as FiMaximize23, FiX as FiX6, FiCheck as FiCheck10, FiImage as FiImage3, FiEdit2 as FiEdit27, FiLoader as FiLoader2, FiBookOpen as FiBookOpen3, FiSun as FiSun2, FiLink as FiLink5, FiDatabase } from "react-icons/fi";
10327
10293
  function NodeDetailsPanel({
10328
10294
  node,
@@ -10837,6 +10803,7 @@ function NodeDetailsPanel({
10837
10803
 
10838
10804
  // src/components/QuestDetailsPanel.jsx
10839
10805
  import React19, { useState as useState19, useEffect as useEffect16, useRef as useRef14 } from "react";
10806
+ import { v4 as uuidv49 } from "uuid";
10840
10807
  import { FiPlus as FiPlus8, FiX as FiX7, FiCheck as FiCheck11, FiEdit2 as FiEdit28, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4, FiLink as FiLink7, FiTarget as FiTarget3, FiChevronDown as FiChevronDown7, FiUser as FiUser3, FiSearch as FiSearch7, FiRepeat as FiRepeat2, FiCalendar as FiCalendar2, FiImage as FiImage4 } from "react-icons/fi";
10841
10808
 
10842
10809
  // src/components/QuestTimeline.jsx
@@ -11287,7 +11254,7 @@ ${noteText}` : noteText : entry.notes,
11287
11254
  }, 100);
11288
11255
  };
11289
11256
  const addLinkToNote = () => {
11290
- setNoteLinks([...noteLinks, { id: v4_default(), name: "", value: "" }]);
11257
+ setNoteLinks([...noteLinks, { id: uuidv49(), name: "", value: "" }]);
11291
11258
  };
11292
11259
  const removeLinkFromNote = (id) => {
11293
11260
  setNoteLinks(noteLinks.filter((l) => l.id !== id));
@@ -11296,7 +11263,7 @@ ${noteText}` : noteText : entry.notes,
11296
11263
  setNoteLinks(noteLinks.map((l) => l.id === id ? { ...l, [field]: val } : l));
11297
11264
  };
11298
11265
  const addImageToNote = () => {
11299
- setNoteImages([...noteImages, { id: v4_default(), name: "Image", value: "" }]);
11266
+ setNoteImages([...noteImages, { id: uuidv49(), name: "Image", value: "" }]);
11300
11267
  };
11301
11268
  const removeImageFromNote = (id) => {
11302
11269
  setNoteImages(noteImages.filter((img) => img.id !== id));
@@ -12173,6 +12140,7 @@ function MultiNodeContextMenu({
12173
12140
 
12174
12141
  // src/components/RelationshipDetailsPanel.jsx
12175
12142
  import React21, { useState as useState21, useEffect as useEffect18, useRef as useRef16, useMemo as useMemo9 } from "react";
12143
+ import { v4 as uuidv410 } from "uuid";
12176
12144
  import { FiPlus as FiPlus9, FiEdit2 as FiEdit29, FiLoader as FiLoader4, FiBookOpen as FiBookOpen5 } from "react-icons/fi";
12177
12145
  function RelationshipDetailsPanel({
12178
12146
  link,
@@ -12982,10 +12950,10 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
12982
12950
  }
12983
12951
 
12984
12952
  // src/components/AncestryBoard.jsx
12985
- import React26, { useState as useState25, useMemo as useMemo11, useEffect as useEffect21, useRef as useRef18 } from "react";
12953
+ import React28, { useState as useState27, useMemo as useMemo12, useEffect as useEffect23 } from "react";
12986
12954
  import {
12987
12955
  FiSearch as FiSearch8,
12988
- FiLayers as FiLayers6,
12956
+ FiLayers as FiLayers7,
12989
12957
  FiCornerUpRight as FiCornerUpRight4,
12990
12958
  FiPlay,
12991
12959
  FiPlus as FiPlus10,
@@ -12995,194 +12963,418 @@ import {
12995
12963
  FiCheckCircle,
12996
12964
  FiLoader as FiLoader5,
12997
12965
  FiX as FiX8,
12998
- FiAlertTriangle,
12999
- FiCheckSquare as FiCheckSquare3,
13000
- FiBox,
13001
- FiGitBranch as FiGitBranch3
12966
+ FiBox as FiBox2,
12967
+ FiCheckSquare as FiCheckSquare4,
12968
+ FiGitBranch as FiGitBranch4
13002
12969
  } from "react-icons/fi";
12970
+ import { v4 as uuidv411 } from "uuid";
12971
+
12972
+ // src/components/RichGroupEditor.jsx
12973
+ import React27, { useEffect as useEffect22, useRef as useRef19, useState as useState26, useCallback as useCallback4 } from "react";
12974
+
12975
+ // src/components/MentionPopover.jsx
12976
+ import React26, { useEffect as useEffect21, useRef as useRef18, useState as useState25, useMemo as useMemo11 } from "react";
12977
+ import { FiLayers as FiLayers6, FiCheckSquare as FiCheckSquare3, FiGitBranch as FiGitBranch3, FiBox } from "react-icons/fi";
12978
+ var TYPE_CONFIG = {
12979
+ ancestry: { Icon: FiLayers6, color: "text-indigo-400", label: "Ancestralidade" },
12980
+ quest: { Icon: FiCheckSquare3, color: "text-emerald-400", label: "Quest" },
12981
+ version: { Icon: FiGitBranch3, color: "text-amber-400", label: "Vers\xE3o" },
12982
+ node: { Icon: FiBox, color: "text-slate-400", label: "Node" }
12983
+ };
12984
+ function MentionPopover({ query, items, position, onSelect, onClose }) {
12985
+ const [activeIndex, setActiveIndex] = useState25(0);
12986
+ const listRef = useRef18(null);
12987
+ const filtered = useMemo11(() => {
12988
+ const term = (query || "").toLowerCase().trim();
12989
+ if (!term) return items.slice(0, 8);
12990
+ return items.filter(
12991
+ (item) => (item.searchLabel || "").toLowerCase().includes(term) || (item.searchDesc || "").toLowerCase().includes(term)
12992
+ ).slice(0, 8);
12993
+ }, [items, query]);
12994
+ useEffect21(() => {
12995
+ setActiveIndex(0);
12996
+ }, [query]);
12997
+ useEffect21(() => {
12998
+ const handleKeyDown = (e) => {
12999
+ if (e.key === "ArrowDown") {
13000
+ e.preventDefault();
13001
+ setActiveIndex((i) => Math.min(i + 1, filtered.length - 1));
13002
+ } else if (e.key === "ArrowUp") {
13003
+ e.preventDefault();
13004
+ setActiveIndex((i) => Math.max(i - 1, 0));
13005
+ } else if (e.key === "Enter" || e.key === "Tab") {
13006
+ e.preventDefault();
13007
+ if (filtered[activeIndex]) onSelect(filtered[activeIndex]);
13008
+ } else if (e.key === "Escape") {
13009
+ e.preventDefault();
13010
+ onClose();
13011
+ }
13012
+ };
13013
+ window.addEventListener("keydown", handleKeyDown, true);
13014
+ return () => window.removeEventListener("keydown", handleKeyDown, true);
13015
+ }, [filtered, activeIndex, onSelect, onClose]);
13016
+ useEffect21(() => {
13017
+ if (listRef.current) {
13018
+ const el = listRef.current.children[activeIndex];
13019
+ if (el) el.scrollIntoView({ block: "nearest" });
13020
+ }
13021
+ }, [activeIndex]);
13022
+ return /* @__PURE__ */ React26.createElement(
13023
+ "div",
13024
+ {
13025
+ style: { top: position.top, left: position.left, position: "fixed", zIndex: 9999 },
13026
+ className: "bg-slate-900 border border-white/10 rounded-xl shadow-2xl py-1.5 min-w-[260px] max-h-[240px] overflow-y-auto custom-scrollbar animate-in fade-in zoom-in-95 duration-100",
13027
+ ref: listRef,
13028
+ onMouseDown: (e) => e.preventDefault()
13029
+ },
13030
+ filtered.length === 0 ? /* @__PURE__ */ React26.createElement("div", { className: "px-4 py-3 text-xs text-slate-500" }, "Nenhum resultado para", " ", /* @__PURE__ */ React26.createElement("span", { className: "text-slate-300 font-medium" }, '"', query, '"')) : filtered.map((item, idx) => {
13031
+ const config = TYPE_CONFIG[item.type] || TYPE_CONFIG.node;
13032
+ const { Icon } = config;
13033
+ return /* @__PURE__ */ React26.createElement(
13034
+ "div",
13035
+ {
13036
+ key: item.id,
13037
+ onMouseDown: (e) => {
13038
+ e.preventDefault();
13039
+ onSelect(item);
13040
+ },
13041
+ onMouseEnter: () => setActiveIndex(idx),
13042
+ className: `flex items-center gap-2.5 px-3 py-2 cursor-pointer text-sm transition-colors duration-100 ${idx === activeIndex ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5"}`
13043
+ },
13044
+ /* @__PURE__ */ React26.createElement(Icon, { size: 13, className: config.color }),
13045
+ /* @__PURE__ */ React26.createElement("span", { className: "flex-1 truncate font-medium" }, item.searchLabel || "Sem Nome"),
13046
+ /* @__PURE__ */ React26.createElement("span", { className: "text-[9px] px-1.5 py-0.5 rounded-full bg-white/5 text-slate-500 border border-white/5 uppercase tracking-wide shrink-0" }, config.label)
13047
+ );
13048
+ })
13049
+ );
13050
+ }
13051
+
13052
+ // src/components/RichGroupEditor.jsx
13053
+ var MENTION_BASE_STYLE = "display:inline-flex;align-items:center;padding:1px 7px;border-radius:5px;margin:0 2px;font-size:0.78em;font-weight:600;cursor:pointer;white-space:nowrap;vertical-align:middle;user-select:none;line-height:1.6;";
13054
+ var MENTION_TYPE_STYLE = {
13055
+ ancestry: "background:rgba(99,102,241,0.18);color:#a5b4fc;border:1px solid rgba(99,102,241,0.35);",
13056
+ quest: "background:rgba(16,185,129,0.18);color:#6ee7b7;border:1px solid rgba(16,185,129,0.35);",
13057
+ version: "background:rgba(245,158,11,0.18);color:#fcd34d;border:1px solid rgba(245,158,11,0.35);",
13058
+ node: "background:rgba(100,116,139,0.18);color:#94a3b8;border:1px solid rgba(100,116,139,0.35);"
13059
+ };
13060
+ function mentionStyle(type) {
13061
+ return MENTION_BASE_STYLE + (MENTION_TYPE_STYLE[type] || MENTION_TYPE_STYLE.node);
13062
+ }
13063
+ function escapeHtml(str) {
13064
+ return String(str || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
13065
+ }
13066
+ function contentToHTML(content) {
13067
+ if (!content || content.length === 0) return "";
13068
+ return content.map((seg) => {
13069
+ if (seg.type === "text") {
13070
+ return escapeHtml(seg.value).replace(/\n/g, "<br>");
13071
+ }
13072
+ if (seg.type === "mention") {
13073
+ const style = mentionStyle(seg.mentionType);
13074
+ return `<span contenteditable="false" data-mention="true" data-id="${escapeHtml(String(seg.id))}" data-name="${escapeHtml(seg.name || "")}" data-mention-type="${escapeHtml(seg.mentionType || "node")}" style="${style}" title="Clique para focar na cena">@${escapeHtml(seg.name || "")}</span>`;
13075
+ }
13076
+ return "";
13077
+ }).join("");
13078
+ }
13079
+ function domToContent(el) {
13080
+ const segments = [];
13081
+ function pushText(text) {
13082
+ const clean = text.replace(/\u200B/g, "");
13083
+ if (!clean) return;
13084
+ const last = segments[segments.length - 1];
13085
+ if (last && last.type === "text") {
13086
+ last.value += clean;
13087
+ } else {
13088
+ segments.push({ type: "text", value: clean });
13089
+ }
13090
+ }
13091
+ function walk(node) {
13092
+ var _a;
13093
+ if (node.nodeType === Node.TEXT_NODE) {
13094
+ pushText(node.textContent);
13095
+ } else if (node.nodeType === Node.ELEMENT_NODE) {
13096
+ if (((_a = node.dataset) == null ? void 0 : _a.mention) === "true") {
13097
+ segments.push({
13098
+ type: "mention",
13099
+ id: node.dataset.id,
13100
+ name: node.dataset.name,
13101
+ mentionType: node.dataset.mentionType
13102
+ });
13103
+ } else if (node.tagName === "BR") {
13104
+ pushText("\n");
13105
+ } else {
13106
+ if (["DIV", "P"].includes(node.tagName) && segments.length > 0) {
13107
+ pushText("\n");
13108
+ }
13109
+ node.childNodes.forEach(walk);
13110
+ }
13111
+ }
13112
+ }
13113
+ el.childNodes.forEach(walk);
13114
+ return segments;
13115
+ }
13116
+ function RichGroupEditor({
13117
+ content,
13118
+ onChange,
13119
+ onMentionClick,
13120
+ searchItems,
13121
+ readOnly,
13122
+ placeholder
13123
+ }) {
13124
+ const editorRef = useRef19(null);
13125
+ const isMountedRef = useRef19(false);
13126
+ const [mentionState, setMentionState] = useState26(null);
13127
+ const [isEmpty, setIsEmpty] = useState26(true);
13128
+ useEffect22(() => {
13129
+ if (!isMountedRef.current && editorRef.current) {
13130
+ editorRef.current.innerHTML = contentToHTML(content);
13131
+ const hasContent = !!editorRef.current.innerText.replace(/\u200B/g, "").trim();
13132
+ const hasMentions = !!editorRef.current.querySelector("[data-mention]");
13133
+ setIsEmpty(!hasContent && !hasMentions);
13134
+ isMountedRef.current = true;
13135
+ }
13136
+ }, []);
13137
+ const getMentionContext = useCallback4(() => {
13138
+ const selection = window.getSelection();
13139
+ if (!selection || selection.rangeCount === 0) return null;
13140
+ const range = selection.getRangeAt(0);
13141
+ if (range.startContainer.nodeType !== Node.TEXT_NODE) return null;
13142
+ const textBefore = range.startContainer.textContent.substring(0, range.startOffset);
13143
+ const atIndex = textBefore.lastIndexOf("@");
13144
+ if (atIndex === -1) return null;
13145
+ const query = textBefore.substring(atIndex + 1);
13146
+ if (query.includes(" ") || query.includes(".") || query.includes(",") || query.length > 40) {
13147
+ return null;
13148
+ }
13149
+ const rect = range.getBoundingClientRect();
13150
+ return {
13151
+ query,
13152
+ position: { top: rect.bottom + 6, left: rect.left }
13153
+ };
13154
+ }, []);
13155
+ const handleInput = useCallback4(() => {
13156
+ if (!editorRef.current) return;
13157
+ const serialized = domToContent(editorRef.current);
13158
+ onChange(serialized);
13159
+ const text = editorRef.current.innerText.replace(/\u200B/g, "").trim();
13160
+ const hasMentions = !!editorRef.current.querySelector("[data-mention]");
13161
+ setIsEmpty(!text && !hasMentions);
13162
+ const ctx = getMentionContext();
13163
+ setMentionState(ctx);
13164
+ }, [onChange, getMentionContext]);
13165
+ const handleKeyDown = useCallback4(
13166
+ (e) => {
13167
+ if (mentionState && ["ArrowDown", "ArrowUp", "Enter", "Tab", "Escape"].includes(e.key)) {
13168
+ return;
13169
+ }
13170
+ if (e.key === "Enter") {
13171
+ e.preventDefault();
13172
+ const sel = window.getSelection();
13173
+ const range = sel.getRangeAt(0);
13174
+ const br = document.createElement("br");
13175
+ range.deleteContents();
13176
+ range.insertNode(br);
13177
+ const afterBr = br.nextSibling || (() => {
13178
+ const zws = document.createTextNode("\u200B");
13179
+ br.parentNode.insertBefore(zws, br.nextSibling);
13180
+ return zws;
13181
+ })();
13182
+ const newRange = document.createRange();
13183
+ newRange.setStartBefore(afterBr);
13184
+ newRange.collapse(true);
13185
+ sel.removeAllRanges();
13186
+ sel.addRange(newRange);
13187
+ handleInput();
13188
+ }
13189
+ },
13190
+ [mentionState, handleInput]
13191
+ );
13192
+ const insertMention = useCallback4(
13193
+ (item) => {
13194
+ if (!editorRef.current) return;
13195
+ const sel = window.getSelection();
13196
+ if (!sel || sel.rangeCount === 0) return;
13197
+ const range = sel.getRangeAt(0);
13198
+ const textNode = range.startContainer;
13199
+ if (textNode.nodeType !== Node.TEXT_NODE) {
13200
+ setMentionState(null);
13201
+ return;
13202
+ }
13203
+ const cursorPos = range.startOffset;
13204
+ const textContent = textNode.textContent;
13205
+ const atIndex = textContent.lastIndexOf("@", cursorPos - 1);
13206
+ if (atIndex === -1) {
13207
+ setMentionState(null);
13208
+ return;
13209
+ }
13210
+ const before = textContent.substring(0, atIndex);
13211
+ const after = textContent.substring(cursorPos);
13212
+ textNode.textContent = before;
13213
+ const parent = textNode.parentNode;
13214
+ const nextSib = textNode.nextSibling;
13215
+ const span = document.createElement("span");
13216
+ span.contentEditable = "false";
13217
+ span.dataset.mention = "true";
13218
+ span.dataset.id = item.id;
13219
+ span.dataset.name = item.searchLabel || item.name || "";
13220
+ span.dataset.mentionType = item.type;
13221
+ span.style.cssText = mentionStyle(item.type);
13222
+ span.title = "Clique para focar na cena";
13223
+ span.textContent = `@${item.searchLabel || item.name || ""}`;
13224
+ parent.insertBefore(span, nextSib);
13225
+ const trailing = document.createTextNode(after || "\u200B");
13226
+ parent.insertBefore(trailing, span.nextSibling);
13227
+ const newRange = document.createRange();
13228
+ newRange.setStart(trailing, after ? 0 : 1);
13229
+ newRange.collapse(true);
13230
+ sel.removeAllRanges();
13231
+ sel.addRange(newRange);
13232
+ const serialized = domToContent(editorRef.current);
13233
+ onChange(serialized);
13234
+ setMentionState(null);
13235
+ setIsEmpty(false);
13236
+ },
13237
+ [onChange]
13238
+ );
13239
+ const handlePaste = useCallback4(
13240
+ (e) => {
13241
+ e.preventDefault();
13242
+ const text = e.clipboardData.getData("text/plain");
13243
+ if (text) {
13244
+ document.execCommand("insertText", false, text);
13245
+ handleInput();
13246
+ }
13247
+ },
13248
+ [handleInput]
13249
+ );
13250
+ const handleClick = useCallback4(
13251
+ (e) => {
13252
+ const chip = e.target.closest("[data-mention='true']");
13253
+ if (chip && onMentionClick) {
13254
+ e.stopPropagation();
13255
+ const id = chip.dataset.id;
13256
+ const full = searchItems == null ? void 0 : searchItems.find((i) => String(i.id) === String(id));
13257
+ if (full) {
13258
+ onMentionClick(full);
13259
+ } else {
13260
+ onMentionClick({
13261
+ id,
13262
+ name: chip.dataset.name,
13263
+ type: chip.dataset.mentionType,
13264
+ searchLabel: chip.dataset.name
13265
+ });
13266
+ }
13267
+ return;
13268
+ }
13269
+ setTimeout(() => {
13270
+ const ctx = getMentionContext();
13271
+ setMentionState(ctx);
13272
+ }, 0);
13273
+ },
13274
+ [onMentionClick, getMentionContext, searchItems]
13275
+ );
13276
+ const handleBlur = useCallback4(() => {
13277
+ setTimeout(() => setMentionState(null), 200);
13278
+ }, []);
13279
+ return /* @__PURE__ */ React27.createElement("div", { className: "relative" }, isEmpty && !readOnly && /* @__PURE__ */ React27.createElement("div", { className: "absolute top-0 left-0 text-sm text-slate-600 pointer-events-none select-none" }, placeholder || "Escreva sobre este grupo\u2026 ou digite @ para mencionar"), /* @__PURE__ */ React27.createElement(
13280
+ "div",
13281
+ {
13282
+ ref: editorRef,
13283
+ contentEditable: readOnly ? "false" : "true",
13284
+ suppressContentEditableWarning: true,
13285
+ onInput: handleInput,
13286
+ onKeyDown: handleKeyDown,
13287
+ onPaste: handlePaste,
13288
+ onClick: handleClick,
13289
+ onBlur: handleBlur,
13290
+ className: `w-full min-h-[1.5rem] max-h-[250px] overflow-y-auto text-sm text-slate-200 focus:outline-none leading-relaxed ${!readOnly ? "cursor-text" : "cursor-default"}`,
13291
+ style: { overflowWrap: "break-word", wordBreak: "break-word" }
13292
+ }
13293
+ ), mentionState && !readOnly && /* @__PURE__ */ React27.createElement(
13294
+ MentionPopover,
13295
+ {
13296
+ query: mentionState.query,
13297
+ items: searchItems || [],
13298
+ position: mentionState.position,
13299
+ onSelect: insertMention,
13300
+ onClose: () => setMentionState(null)
13301
+ }
13302
+ ));
13303
+ }
13304
+
13305
+ // src/components/AncestryBoard.jsx
13003
13306
  var GroupItem = ({
13004
13307
  group,
13005
13308
  index,
13006
- siblings,
13007
13309
  onUpdate,
13008
13310
  onDelete,
13009
13311
  onAddSubgroup,
13010
13312
  onIndent,
13011
13313
  onOutdent,
13012
- onRemoveAncestry,
13013
- onRequestPickAncestry,
13014
- pickingGroupId,
13015
- onPlayAncestry,
13016
- availableIds,
13314
+ searchItems,
13315
+ onMentionClick,
13017
13316
  canEdit
13018
13317
  }) => {
13019
13318
  const canIndent = index > 0;
13020
- const isPickingForThisGroup = pickingGroupId === group.id;
13021
- const textareaRef = useRef18(null);
13022
- const adjustHeight = () => {
13023
- const textarea = textareaRef.current;
13024
- if (textarea) {
13025
- textarea.style.height = "auto";
13026
- textarea.style.height = `${textarea.scrollHeight}px`;
13027
- }
13319
+ const handleContentChange = (content) => {
13320
+ onUpdate(group.id, { ...group, content });
13028
13321
  };
13029
- useEffect21(() => {
13030
- adjustHeight();
13031
- }, [group.text]);
13032
- return /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React26.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ React26.createElement(
13033
- "div",
13322
+ return /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React28.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col gap-2 py-2 px-3 transition-all duration-200 hover:bg-white/5 border-l-2 border-transparent hover:border-white/20" }, /* @__PURE__ */ React28.createElement(
13323
+ RichGroupEditor,
13034
13324
  {
13035
- className: `
13036
- flex flex-col gap-2 py-2 px-3 transition-all duration-200
13037
- ${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
13038
- `
13325
+ content: group.content,
13326
+ onChange: handleContentChange,
13327
+ onMentionClick,
13328
+ searchItems,
13329
+ readOnly: !canEdit,
13330
+ placeholder: "Escreva sobre este grupo\u2026 ou @ para mencionar"
13331
+ }
13332
+ ), canEdit && /* @__PURE__ */ React28.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(
13333
+ "button",
13334
+ {
13335
+ onClick: () => onAddSubgroup(group.id),
13336
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13337
+ title: "Criar Subgrupo"
13039
13338
  },
13040
- /* @__PURE__ */ React26.createElement(
13041
- "textarea",
13042
- {
13043
- ref: textareaRef,
13044
- className: `w-full bg-transparent text-sm text-slate-200 placeholder-slate-600 resize-none focus:outline-none focus:placeholder-slate-500 overflow-y-auto ${!canEdit ? "cursor-default" : ""}`,
13045
- rows: 1,
13046
- style: {
13047
- minHeight: "1.5rem",
13048
- maxHeight: "250px"
13049
- },
13050
- placeholder: canEdit ? "Escreva sobre este grupo..." : "",
13051
- value: group.text,
13052
- readOnly: !canEdit,
13053
- onChange: (e) => {
13054
- if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
13055
- }
13056
- }
13057
- ),
13058
- group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ React26.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
13059
- const isValid = anc.type === "ancestry" || !anc.type ? availableIds.has(String(anc.ancestry_id || anc.id)) : true;
13060
- const isAncestry = anc.type === "ancestry" || !anc.type;
13061
- const itemId = isAncestry ? anc.ancestry_id : anc.id;
13062
- let Icon = FiLayers6;
13063
- let colorClass = "text-indigo-400";
13064
- if (anc.type === "quest") {
13065
- Icon = FiCheckSquare3;
13066
- colorClass = "text-amber-400";
13067
- } else if (anc.type === "version") {
13068
- Icon = FiGitBranch3;
13069
- colorClass = "text-purple-400";
13070
- } else if (anc.type === "node") {
13071
- Icon = FiBox;
13072
- colorClass = "text-emerald-400";
13073
- }
13074
- return /* @__PURE__ */ React26.createElement(
13075
- "div",
13076
- {
13077
- key: `${anc.type || "ancestry"}-${itemId}`,
13078
- className: `
13079
- flex items-center gap-2 rounded-md px-3 py-1.5 text-xs transition-all group/card border
13080
- ${isValid ? "bg-slate-800/60 border-white/10 hover:border-indigo-500/30 text-slate-200" : "bg-red-900/10 border-red-500/30 text-red-300/70 hover:bg-red-900/20"}
13081
- `,
13082
- title: isValid ? "" : "Esta informa\xE7\xE3o n\xE3o est\xE1 mais dispon\xEDvel neste contexto."
13083
- },
13084
- isValid ? /* @__PURE__ */ React26.createElement(
13085
- "button",
13086
- {
13087
- onClick: () => onPlayAncestry(anc),
13088
- className: `${colorClass} hover:text-white hover:bg-current/20 p-1 rounded transition-colors flex items-center justify-center`,
13089
- title: "Focar no cen\xE1rio"
13090
- },
13091
- /* @__PURE__ */ React26.createElement(Icon, { size: 12 }),
13092
- /* @__PURE__ */ React26.createElement(
13093
- FiPlay,
13094
- {
13095
- size: 8,
13096
- className: "ml-0.5 fill-current opacity-0 group-hover/card:opacity-100 transition-opacity"
13097
- }
13098
- )
13099
- ) : /* @__PURE__ */ React26.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ React26.createElement(FiAlertTriangle, { size: 10 })),
13100
- /* @__PURE__ */ React26.createElement(
13101
- "span",
13102
- {
13103
- className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}`
13104
- },
13105
- anc.name
13106
- ),
13107
- canEdit && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(
13108
- "div",
13109
- {
13110
- className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}`
13111
- }
13112
- ), /* @__PURE__ */ React26.createElement(
13113
- "button",
13114
- {
13115
- onClick: () => onRemoveAncestry(group.id, itemId),
13116
- className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
13117
- title: "Remover men\xE7\xE3o"
13118
- },
13119
- /* @__PURE__ */ React26.createElement(FiX8, { size: 12 })
13120
- ))
13121
- );
13122
- })),
13123
- canEdit && /* @__PURE__ */ React26.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React26.createElement(
13124
- "button",
13125
- {
13126
- onClick: () => onRequestPickAncestry(group.id),
13127
- className: `
13128
- flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium transition-colors
13129
- ${isPickingForThisGroup ? "text-indigo-300 animate-pulse" : "text-slate-500 hover:text-indigo-300 hover:bg-indigo-500/10"}
13130
- `,
13131
- title: "Adicionar Men\xE7\xE3o a este grupo"
13132
- },
13133
- isPickingForThisGroup ? /* @__PURE__ */ React26.createElement(FiCheckCircle, { size: 12 }) : /* @__PURE__ */ React26.createElement(FiSearch8, { size: 12 }),
13134
- isPickingForThisGroup ? "Selecionando..." : "Adicionar"
13135
- ), /* @__PURE__ */ React26.createElement(
13136
- "button",
13137
- {
13138
- onClick: () => onAddSubgroup(group.id),
13139
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13140
- title: "Criar Subgrupo"
13141
- },
13142
- /* @__PURE__ */ React26.createElement(FiPlus10, { size: 14 })
13143
- )), /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React26.createElement(
13144
- "button",
13145
- {
13146
- onClick: () => onIndent(group.id),
13147
- disabled: !canIndent,
13148
- className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13149
- title: "Aninhar no grupo acima"
13150
- },
13151
- /* @__PURE__ */ React26.createElement(FiArrowRight2, { size: 14 })
13152
- ), /* @__PURE__ */ React26.createElement(
13153
- "button",
13154
- {
13155
- onClick: () => onOutdent(group.id),
13156
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13157
- title: "Desaninhar"
13158
- },
13159
- /* @__PURE__ */ React26.createElement(FiArrowLeft3, { size: 14 })
13160
- ), /* @__PURE__ */ React26.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React26.createElement(
13161
- "button",
13162
- {
13163
- onClick: () => onDelete(group.id),
13164
- className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13165
- title: "Remover Grupo"
13166
- },
13167
- /* @__PURE__ */ React26.createElement(FiTrash23, { size: 14 })
13168
- )))
13169
- ), group.children && group.children.length > 0 && /* @__PURE__ */ React26.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ React26.createElement(
13339
+ /* @__PURE__ */ React28.createElement(FiPlus10, { size: 14 })
13340
+ )), /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(
13341
+ "button",
13342
+ {
13343
+ onClick: () => onIndent(group.id),
13344
+ disabled: !canIndent,
13345
+ className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13346
+ title: "Aninhar no grupo acima"
13347
+ },
13348
+ /* @__PURE__ */ React28.createElement(FiArrowRight2, { size: 14 })
13349
+ ), /* @__PURE__ */ React28.createElement(
13350
+ "button",
13351
+ {
13352
+ onClick: () => onOutdent(group.id),
13353
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13354
+ title: "Desaninhar"
13355
+ },
13356
+ /* @__PURE__ */ React28.createElement(FiArrowLeft3, { size: 14 })
13357
+ ), /* @__PURE__ */ React28.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React28.createElement(
13358
+ "button",
13359
+ {
13360
+ onClick: () => onDelete(group.id),
13361
+ className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13362
+ title: "Remover Grupo"
13363
+ },
13364
+ /* @__PURE__ */ React28.createElement(FiTrash23, { size: 14 })
13365
+ )))), group.children && group.children.length > 0 && /* @__PURE__ */ React28.createElement("div", { className: "ml-2" }, group.children.map((child, idx) => /* @__PURE__ */ React28.createElement(
13170
13366
  GroupItem,
13171
13367
  {
13172
- key: childGroup.id,
13368
+ key: child.id,
13173
13369
  index: idx,
13174
- group: childGroup,
13175
- siblings: group.children,
13370
+ group: child,
13176
13371
  onUpdate,
13177
13372
  onDelete,
13178
13373
  onAddSubgroup,
13179
13374
  onIndent,
13180
13375
  onOutdent,
13181
- onRemoveAncestry,
13182
- onRequestPickAncestry,
13183
- pickingGroupId,
13184
- onPlayAncestry,
13185
- availableIds,
13376
+ searchItems,
13377
+ onMentionClick,
13186
13378
  canEdit
13187
13379
  }
13188
13380
  ))));
@@ -13197,168 +13389,126 @@ function AncestryBoard({
13197
13389
  onSave,
13198
13390
  userRole
13199
13391
  }) {
13200
- const [searchTerm, setSearchTerm] = useState25("");
13201
- const [groups, setGroups] = useState25([]);
13202
- const [isLoaded, setIsLoaded] = useState25(false);
13203
- const [pickingGroupId, setPickingGroupId] = useState25(null);
13204
- const [saveStatus, setSaveStatus] = useState25("idle");
13205
- const canEdit = useMemo11(() => {
13206
- return userRole !== "viewer";
13207
- }, [userRole]);
13208
- useEffect21(() => {
13392
+ const [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(() => {
13209
13398
  if (initialGroups && !isLoaded) {
13210
- 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));
13211
13406
  setIsLoaded(true);
13212
13407
  }
13213
13408
  }, [initialGroups, isLoaded]);
13214
- const nodeNamesMap = useMemo11(() => {
13409
+ const nodeNamesMap = useMemo12(() => {
13215
13410
  const map = /* @__PURE__ */ new Map();
13216
- if (availableNodes && Array.isArray(availableNodes)) {
13217
- availableNodes.forEach((node) => {
13218
- if (node && node.id) {
13219
- map.set(String(node.id), node.name);
13220
- }
13221
- });
13222
- }
13411
+ availableNodes.forEach((n) => {
13412
+ if (n == null ? void 0 : n.id) map.set(String(n.id), n.name);
13413
+ });
13223
13414
  return map;
13224
13415
  }, [availableNodes]);
13225
- const availableIds = useMemo11(() => {
13226
- return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
13227
- }, [availableAncestries]);
13228
- const allMentionableItems = useMemo11(() => {
13229
- const ancestries = availableAncestries.map((a) => ({
13230
- id: String(a.ancestry_id),
13231
- ancestry_id: a.ancestry_id,
13232
- name: a.name,
13233
- description: a.description,
13234
- type: "ancestry",
13235
- ancestral_node: a.ancestral_node,
13236
- is_private: a.is_private
13237
- }));
13238
- const nodes = availableNodes.map((n) => {
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;
13239
13429
  let type = "node";
13240
- if (n.is_quest) type = "quest";
13241
- else if (n.is_version) type = "version";
13242
- return {
13243
- id: String(n.id),
13244
- name: n.name,
13245
- description: n.description,
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),
13246
13435
  type,
13247
- raw_node: n
13248
- };
13436
+ searchLabel: node.name || node.raw_title || "",
13437
+ searchDesc: node.description || ""
13438
+ });
13249
13439
  });
13250
- return [...ancestries, ...nodes];
13440
+ return items;
13251
13441
  }, [availableAncestries, availableNodes]);
13252
- const sanitizeGroups = (groupList) => {
13253
- return groupList.map((g) => ({
13254
- id: g.id,
13255
- text: g.text || "",
13256
- ancestries: (g.ancestries || []).map((a) => ({
13257
- id: a.id || a.ancestry_id,
13258
- ancestry_id: a.ancestry_id,
13259
- name: a.name,
13260
- type: a.type || "ancestry"
13261
- })),
13262
- children: sanitizeGroups(g.children || [])
13263
- }));
13264
- };
13265
- useEffect21(() => {
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(() => {
13266
13462
  if (!isLoaded || !onSave) return;
13267
- const timeoutId = setTimeout(async () => {
13463
+ const id = setTimeout(async () => {
13268
13464
  setSaveStatus("saving");
13269
- const cleanData = sanitizeGroups(groups);
13270
13465
  try {
13271
- await onSave(cleanData);
13466
+ await onSave(sanitizeGroups(groups));
13272
13467
  setSaveStatus("saved");
13273
- setTimeout(() => {
13274
- setSaveStatus("idle");
13275
- }, 3e3);
13276
- } catch (error) {
13277
- console.error("Erro ao salvar board:", error);
13468
+ setTimeout(() => setSaveStatus("idle"), 3e3);
13469
+ } catch (err) {
13470
+ console.error("Erro ao salvar board:", err);
13278
13471
  setSaveStatus("error");
13279
13472
  }
13280
13473
  }, 3e3);
13281
- return () => clearTimeout(timeoutId);
13474
+ return () => clearTimeout(id);
13282
13475
  }, [groups, isLoaded, onSave]);
13283
- useEffect21(() => {
13476
+ useEffect23(() => {
13284
13477
  if (!isOpen) return;
13285
- const handleKeyDown = (e) => {
13478
+ const handler = (e) => {
13286
13479
  if (e.key === "Escape") {
13287
- if (pickingGroupId) {
13288
- setPickingGroupId(null);
13289
- } else {
13290
- onClose();
13291
- }
13480
+ onClose();
13292
13481
  e.preventDefault();
13293
13482
  e.stopPropagation();
13294
13483
  }
13295
13484
  };
13296
- window.addEventListener("keydown", handleKeyDown);
13297
- return () => window.removeEventListener("keydown", handleKeyDown);
13298
- }, [isOpen, onClose, pickingGroupId]);
13299
- const filtered = useMemo11(() => {
13300
- const term = searchTerm.toLowerCase().trim();
13301
- return allMentionableItems.filter((item) => {
13302
- if (!term) return true;
13303
- const nameMatch = item.name && item.name.toLowerCase().includes(term);
13304
- const descMatch = item.description && item.description.toLowerCase().includes(term);
13305
- let parentMatch = false;
13306
- if (item.type === "ancestry") {
13307
- const parentName = nodeNamesMap.get(String(item.ancestral_node)) || "";
13308
- parentMatch = parentName.toLowerCase().includes(term);
13309
- }
13310
- return nameMatch || descMatch || parentMatch;
13311
- });
13312
- }, [allMentionableItems, searchTerm, nodeNamesMap]);
13485
+ window.addEventListener("keydown", handler);
13486
+ return () => window.removeEventListener("keydown", handler);
13487
+ }, [isOpen, onClose]);
13313
13488
  const handleAddRootGroup = () => {
13314
- const newGroup = {
13315
- id: v4_default(),
13316
- text: "",
13317
- ancestries: [],
13318
- children: []
13319
- };
13320
- setGroups((prev) => [newGroup, ...prev]);
13489
+ setGroups((prev) => [{ id: uuidv411(), content: [], children: [] }, ...prev]);
13321
13490
  };
13322
13491
  const handleAddSubgroup = (parentId) => {
13323
- const newGroup = {
13324
- id: v4_default(),
13325
- text: "",
13326
- ancestries: [],
13327
- children: []
13328
- };
13329
- const addRecursive = (list) => {
13330
- return list.map((g) => {
13331
- if (g.id === parentId) {
13332
- return { ...g, children: [newGroup, ...g.children] };
13333
- }
13334
- return { ...g, children: addRecursive(g.children) };
13335
- });
13336
- };
13337
- setGroups((prev) => addRecursive(prev));
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));
13338
13497
  };
13339
13498
  const handleUpdateGroup = (id, newData) => {
13340
- const updateRecursive = (list) => {
13341
- return list.map((g) => {
13342
- if (g.id === id) return newData;
13343
- return { ...g, children: updateRecursive(g.children) };
13344
- });
13345
- };
13346
- setGroups((prev) => updateRecursive(prev));
13499
+ const update = (list) => list.map(
13500
+ (g) => g.id === id ? newData : { ...g, children: update(g.children) }
13501
+ );
13502
+ setGroups((prev) => update(prev));
13347
13503
  };
13348
13504
  const handleDeleteGroup = (id) => {
13349
- const deleteRecursive = (list) => {
13350
- return list.filter((g) => g.id !== id).map((g) => ({
13351
- ...g,
13352
- children: deleteRecursive(g.children)
13353
- }));
13354
- };
13355
- setGroups((prev) => deleteRecursive(prev));
13505
+ const del = (list) => list.filter((g) => g.id !== id).map((g) => ({ ...g, children: del(g.children) }));
13506
+ setGroups((prev) => del(prev));
13356
13507
  };
13357
13508
  const findGroupAndParent = (list, targetId, parent = null) => {
13358
13509
  for (let i = 0; i < list.length; i++) {
13359
- if (list[i].id === targetId) {
13510
+ if (list[i].id === targetId)
13360
13511
  return { group: list[i], parent, index: i, siblings: list };
13361
- }
13362
13512
  if (list[i].children.length > 0) {
13363
13513
  const found = findGroupAndParent(list[i].children, targetId, list[i]);
13364
13514
  if (found) return found;
@@ -13368,257 +13518,119 @@ function AncestryBoard({
13368
13518
  };
13369
13519
  const handleIndent = (id) => {
13370
13520
  setGroups((prev) => {
13371
- const newList = JSON.parse(JSON.stringify(prev));
13372
- const found = findGroupAndParent(newList, id);
13521
+ const next = JSON.parse(JSON.stringify(prev));
13522
+ const found = findGroupAndParent(next, id);
13373
13523
  if (!found || found.index === 0) return prev;
13374
13524
  const { group, siblings, index } = found;
13375
- const prevSibling = siblings[index - 1];
13376
13525
  siblings.splice(index, 1);
13377
- prevSibling.children.push(group);
13378
- return newList;
13526
+ siblings[index - 1].children.push(group);
13527
+ return next;
13379
13528
  });
13380
13529
  };
13381
13530
  const handleOutdent = (id) => {
13382
13531
  setGroups((prev) => {
13383
- const newList = JSON.parse(JSON.stringify(prev));
13384
- const found = findGroupAndParent(newList, id);
13532
+ const next = JSON.parse(JSON.stringify(prev));
13533
+ const found = findGroupAndParent(next, id);
13385
13534
  if (!found || !found.parent) return prev;
13386
13535
  const { group, siblings, index, parent } = found;
13387
13536
  siblings.splice(index, 1);
13388
- const parentFound = findGroupAndParent(newList, parent.id);
13537
+ const parentFound = findGroupAndParent(next, parent.id);
13389
13538
  if (parentFound) {
13390
13539
  parentFound.siblings.splice(parentFound.index + 1, 0, group);
13391
13540
  } else {
13392
- newList.push(group);
13541
+ next.push(group);
13393
13542
  }
13394
- return newList;
13543
+ return next;
13395
13544
  });
13396
13545
  };
13397
- const handleRequestPick = (groupId) => {
13398
- setPickingGroupId((prev) => prev === groupId ? null : groupId);
13399
- };
13400
- const handleSelectAncestry = (item) => {
13401
- if (pickingGroupId) {
13402
- setGroups((prev) => {
13403
- const addRecursive = (list) => {
13404
- return list.map((g) => {
13405
- if (g.id === pickingGroupId) {
13406
- const currentId = item.id;
13407
- const exists = g.ancestries.some(
13408
- (a) => (a.id || a.ancestry_id) === currentId && a.type === item.type
13409
- );
13410
- if (exists) return g;
13411
- return { ...g, ancestries: [...g.ancestries, item] };
13412
- }
13413
- return { ...g, children: addRecursive(g.children) };
13414
- });
13415
- };
13416
- return addRecursive(prev);
13417
- });
13418
- setPickingGroupId(null);
13419
- } else {
13420
- let fullItem = item;
13421
- if (item.type === "ancestry" || !item.type) {
13422
- fullItem = availableAncestries.find(
13423
- (a) => String(a.ancestry_id) === String(item.id || item.ancestry_id)
13424
- ) || item;
13425
- } else {
13426
- fullItem = availableNodes.find(
13427
- (n) => String(n.id) === String(item.id)
13428
- ) || item;
13429
- }
13430
- onSelect(fullItem);
13431
- }
13432
- };
13433
- const handlePlayFromGroup = (item) => {
13434
- let fullItem = item;
13435
- if (item.type === "ancestry" || !item.type) {
13436
- fullItem = availableAncestries.find(
13437
- (a) => String(a.ancestry_id) === String(item.id || item.ancestry_id)
13438
- ) || item;
13439
- } else {
13440
- fullItem = availableNodes.find(
13441
- (n) => String(n.id) === String(item.id)
13442
- ) || item;
13443
- }
13444
- if (fullItem && onSelect) {
13445
- onSelect(fullItem);
13446
- }
13447
- };
13448
- const handleRemoveAncestryFromGroup = (groupId, itemId) => {
13449
- setGroups((prev) => {
13450
- const removeRecursive = (list) => {
13451
- return list.map((g) => {
13452
- if (g.id === groupId) {
13453
- return {
13454
- ...g,
13455
- ancestries: g.ancestries.filter(
13456
- (a) => (a.id || a.ancestry_id) !== itemId
13457
- )
13458
- };
13459
- }
13460
- return { ...g, children: removeRecursive(g.children) };
13461
- });
13462
- };
13463
- return removeRecursive(prev);
13464
- });
13546
+ const handleMentionClick = (item) => {
13547
+ if (onSelect) onSelect(item);
13465
13548
  };
13466
13549
  if (!isOpen) return null;
13467
- return /* @__PURE__ */ React26.createElement(
13550
+ return /* @__PURE__ */ React28.createElement(
13468
13551
  "div",
13469
13552
  {
13470
13553
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
13471
13554
  onClick: onClose
13472
13555
  },
13473
- /* @__PURE__ */ React26.createElement(
13556
+ /* @__PURE__ */ React28.createElement(
13474
13557
  "div",
13475
13558
  {
13476
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",
13477
13560
  onClick: (e) => e.stopPropagation()
13478
13561
  },
13479
- /* @__PURE__ */ React26.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React26.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ React26.createElement(FiLayers6, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React26.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(
13480
- FiLoader5,
13481
- {
13482
- className: "animate-spin text-indigo-400",
13483
- size: 12
13484
- }
13485
- ), /* @__PURE__ */ React26.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ React26.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ React26.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ React26.createElement("span", { className: "text-xs text-indigo-300 font-medium animate-pulse hidden sm:inline-block mr-2" }, "Selecione na lateral..."), canEdit && /* @__PURE__ */ React26.createElement(
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(
13486
13563
  "button",
13487
13564
  {
13488
13565
  onClick: handleAddRootGroup,
13489
- className: "\n flex items-center gap-2 px-3 py-1.5 \n bg-white/5 hover:bg-white/10 \n border border-white/10 hover:border-white/20\n backdrop-blur-sm\n text-slate-200 hover:text-white\n rounded-md transition-all duration-200\n text-xs font-medium shadow-sm\n "
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"
13490
13567
  },
13491
- /* @__PURE__ */ React26.createElement(FiPlus10, { size: 14, className: "text-indigo-400" }),
13492
- /* @__PURE__ */ React26.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13493
- ), /* @__PURE__ */ React26.createElement(
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(
13494
13571
  "button",
13495
13572
  {
13496
13573
  onClick: onClose,
13497
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"
13498
13575
  },
13499
- "\xD7"
13576
+ /* @__PURE__ */ React28.createElement(FiX8, { size: 16 })
13500
13577
  ))),
13501
- /* @__PURE__ */ React26.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React26.createElement(
13502
- "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",
13503
13580
  {
13504
- className: `
13505
- flex flex-col border-r border-white/10 transition-all duration-300 flex-none
13506
- ${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
13507
- min-w-[280px] max-w-[500px] bg-slate-900
13508
- `
13509
- },
13510
- /* @__PURE__ */ React26.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ React26.createElement("div", { className: "relative group" }, /* @__PURE__ */ React26.createElement(
13511
- FiSearch8,
13512
- {
13513
- className: `absolute left-3 top-1/2 -translate-y-1/2 transition-colors ${pickingGroupId ? "text-indigo-400" : "text-slate-500 group-focus-within:text-indigo-400"}`
13514
- }
13515
- ), /* @__PURE__ */ React26.createElement(
13516
- "input",
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",
13517
13592
  {
13518
- type: "text",
13519
- placeholder: pickingGroupId ? "Pesquise para adicionar..." : "Pesquisar (Ancestralidades e Nodes)",
13520
- className: `
13521
- w-full rounded-md pl-9 pr-4 py-2 text-sm transition-all focus:outline-none focus:ring-1 focus:ring-indigo-500 border
13522
- ${pickingGroupId ? "bg-indigo-950/30 border-indigo-500/30 text-white placeholder-indigo-300/50" : "bg-slate-950 border-white/10 text-slate-200 placeholder-slate-600"}
13523
- `,
13524
- value: searchTerm,
13525
- onChange: (e) => setSearchTerm(e.target.value),
13526
- autoFocus: !pickingGroupId
13527
- }
13528
- ))),
13529
- /* @__PURE__ */ React26.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((item) => {
13530
- const isPicking = !!pickingGroupId;
13531
- const isQuest = item.type === "quest";
13532
- const isVersion = item.type === "version";
13533
- const isNode = item.type === "node";
13534
- let Icon = FiLayers6;
13535
- let colorClass = "bg-slate-800 text-indigo-400 border-white/5";
13536
- let pickingColorClass = "bg-indigo-500 text-white border-indigo-400";
13537
- let hoverClass = "hover:bg-indigo-600/10 hover:border-indigo-500/30";
13538
- let badge = null;
13539
- if (isQuest) {
13540
- Icon = FiCheckSquare3;
13541
- colorClass = "bg-slate-800 text-amber-400 border-white/5";
13542
- pickingColorClass = "bg-amber-500 text-white border-amber-400";
13543
- hoverClass = "hover:bg-amber-500/10 hover:border-amber-500/30";
13544
- badge = "Quest";
13545
- } else if (isVersion) {
13546
- Icon = FiGitBranch3;
13547
- colorClass = "bg-slate-800 text-purple-400 border-white/5";
13548
- pickingColorClass = "bg-purple-500 text-white border-purple-400";
13549
- hoverClass = "hover:bg-purple-500/10 hover:border-purple-500/30";
13550
- badge = "Ver";
13551
- } else if (isNode) {
13552
- Icon = FiBox;
13553
- colorClass = "bg-slate-800 text-emerald-400 border-white/5";
13554
- pickingColorClass = "bg-emerald-500 text-white border-emerald-400";
13555
- hoverClass = "hover:bg-emerald-500/10 hover:border-emerald-500/30";
13556
- badge = "Node";
13557
- }
13558
- return /* @__PURE__ */ React26.createElement(
13559
- "div",
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",
13560
13600
  {
13561
- key: `${item.type}-${item.id}`,
13562
- onClick: () => {
13563
- if (isPicking) handleSelectAncestry(item);
13601
+ onClick: (e) => {
13602
+ e.stopPropagation();
13603
+ if (onSelect) onSelect(anc);
13564
13604
  },
13565
- className: `
13566
- group relative flex items-start gap-3 p-3 text-left rounded-lg border transition-all duration-200
13567
- ${isPicking ? `border-indigo-500/30 bg-indigo-500/5 hover:bg-indigo-500/20 hover:border-indigo-400 cursor-pointer` : `border-white/5 bg-slate-800/40 ${hoverClass} cursor-default`}
13568
- `
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"
13569
13607
  },
13570
- /* @__PURE__ */ React26.createElement(
13571
- "div",
13572
- {
13573
- className: `
13574
- mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
13575
- ${isPicking ? pickingColorClass : `${colorClass} group-hover:bg-opacity-80`}
13576
- `
13577
- },
13578
- isPicking ? /* @__PURE__ */ React26.createElement(FiPlus10, { size: 16 }) : /* @__PURE__ */ React26.createElement(Icon, { size: 14 })
13579
- ),
13580
- /* @__PURE__ */ React26.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ React26.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, item.name || "Sem Nome"), badge && /* @__PURE__ */ React26.createElement("span", { className: `text-[9px] px-1 py-0.5 rounded ${isQuest ? "bg-amber-500/10 text-amber-400" : isVersion ? "bg-purple-500/10 text-purple-400" : "bg-emerald-500/10 text-emerald-400"} border border-current opacity-50` }, badge), item.is_private && /* @__PURE__ */ React26.createElement("span", { className: "text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-300 border border-amber-500/20" }, "Priv")), item.type === "ancestry" && /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ React26.createElement(FiCornerUpRight4, { size: 10 }), /* @__PURE__ */ React26.createElement("span", { className: "truncate max-w-[120px]" }, nodeNamesMap.get(String(item.ancestral_node)) || "Node Desconhecido")), item.description && /* @__PURE__ */ React26.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, item.description)),
13581
- !isPicking && /* @__PURE__ */ React26.createElement(
13582
- "button",
13583
- {
13584
- onClick: (e) => {
13585
- e.stopPropagation();
13586
- handleSelectAncestry(item);
13587
- },
13588
- className: "absolute right-2 bottom-2 opacity-0 group-hover:opacity-100 transition-all duration-300 transform translate-y-2 group-hover:translate-y-0 z-10",
13589
- title: "Renderizar / Focar"
13590
- },
13591
- /* @__PURE__ */ React26.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ React26.createElement(FiPlay, { size: 14, className: "ml-0.5" }))
13592
- )
13593
- );
13594
- }))
13595
- ), /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ React26.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-3 border-2 border-dashed border-white/5 rounded-xl m-4 bg-slate-900/20" }, /* @__PURE__ */ React26.createElement(FiLayers6, { size: 24, className: "opacity-20" }), /* @__PURE__ */ React26.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ React26.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ React26.createElement(React26.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ React26.createElement(
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(
13596
13612
  GroupItem,
13597
13613
  {
13598
13614
  key: group.id,
13599
13615
  index,
13600
13616
  group,
13601
- siblings: groups,
13602
13617
  onUpdate: handleUpdateGroup,
13603
13618
  onDelete: handleDeleteGroup,
13604
13619
  onAddSubgroup: handleAddSubgroup,
13605
13620
  onIndent: handleIndent,
13606
13621
  onOutdent: handleOutdent,
13607
- onRemoveAncestry: handleRemoveAncestryFromGroup,
13608
- onRequestPickAncestry: handleRequestPick,
13609
- pickingGroupId,
13610
- onPlayAncestry: handlePlayFromGroup,
13611
- availableIds,
13622
+ searchItems: allSearchableItems,
13623
+ onMentionClick: handleMentionClick,
13612
13624
  canEdit
13613
13625
  }
13614
13626
  ))))),
13615
- /* @__PURE__ */ React26.createElement("div", { className: "px-5 py-2 border-t border-white/10 bg-slate-950/50 text-xs text-slate-500 flex justify-between flex-shrink-0" }, /* @__PURE__ */ React26.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ React26.createElement("span", null, groups.length, " grupos raiz"))
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"))
13616
13628
  )
13617
13629
  );
13618
13630
  }
13619
13631
 
13620
13632
  // src/components/MilestoneManager.jsx
13621
- import React27, { useState as useState26 } from "react";
13633
+ import React29, { useState as useState28 } from "react";
13622
13634
  import { FiTarget as FiTarget4, FiPlus as FiPlus11, FiTrash2 as FiTrash24, FiX as FiX9, FiCheck as FiCheck12, FiPauseCircle, FiPlayCircle } from "react-icons/fi";
13623
13635
  function MilestoneManager({
13624
13636
  isOpen,
@@ -13627,7 +13639,7 @@ function MilestoneManager({
13627
13639
  onUpdateMilestones = () => {
13628
13640
  }
13629
13641
  }) {
13630
- const [newMilestoneName, setNewMilestoneName] = useState26("");
13642
+ const [newMilestoneName, setNewMilestoneName] = useState28("");
13631
13643
  const handleAddMilestone = () => {
13632
13644
  if (!newMilestoneName.trim()) return;
13633
13645
  const newMilestone = {
@@ -13652,27 +13664,27 @@ function MilestoneManager({
13652
13664
  };
13653
13665
  if (!isOpen) return null;
13654
13666
  const swallow = (e) => e.stopPropagation();
13655
- return /* @__PURE__ */ React27.createElement(
13667
+ return /* @__PURE__ */ React29.createElement(
13656
13668
  "div",
13657
13669
  {
13658
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",
13659
13671
  onClick: onClose
13660
13672
  },
13661
- /* @__PURE__ */ React27.createElement(
13673
+ /* @__PURE__ */ React29.createElement(
13662
13674
  "div",
13663
13675
  {
13664
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",
13665
13677
  onClick: swallow
13666
13678
  },
13667
- /* @__PURE__ */ React27.createElement("div", { className: "px-6 py-4 border-b border-white/10 flex items-center justify-between" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React27.createElement("div", { className: "p-2 rounded-lg bg-indigo-500/20 text-indigo-400" }, /* @__PURE__ */ React27.createElement(FiTarget4, { size: 20 })), /* @__PURE__ */ React27.createElement("div", null, /* @__PURE__ */ React27.createElement("h2", { className: "text-lg font-semibold text-slate-100" }, "Milestones"), /* @__PURE__ */ React27.createElement("p", { className: "text-xs text-slate-400" }, "Gerencie os marcos do seu cen\xE1rio"))), /* @__PURE__ */ React27.createElement(
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(
13668
13680
  "button",
13669
13681
  {
13670
13682
  onClick: onClose,
13671
13683
  className: "p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
13672
13684
  },
13673
- /* @__PURE__ */ React27.createElement(FiX9, { size: 20 })
13685
+ /* @__PURE__ */ React29.createElement(FiX9, { size: 20 })
13674
13686
  )),
13675
- /* @__PURE__ */ React27.createElement("div", { className: "px-6 py-5 bg-white/5 border-b border-white/5" }, /* @__PURE__ */ React27.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React27.createElement(
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(
13676
13688
  "input",
13677
13689
  {
13678
13690
  type: "text",
@@ -13682,47 +13694,47 @@ function MilestoneManager({
13682
13694
  placeholder: "Adicionar novo milestone...",
13683
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"
13684
13696
  }
13685
- ), /* @__PURE__ */ React27.createElement(
13697
+ ), /* @__PURE__ */ React29.createElement(
13686
13698
  "button",
13687
13699
  {
13688
13700
  onClick: handleAddMilestone,
13689
13701
  disabled: !newMilestoneName.trim(),
13690
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"
13691
13703
  },
13692
- /* @__PURE__ */ React27.createElement(FiPlus11, { size: 18 }),
13704
+ /* @__PURE__ */ React29.createElement(FiPlus11, { size: 18 }),
13693
13705
  "Adicionar"
13694
13706
  ))),
13695
- /* @__PURE__ */ React27.createElement("div", { className: "flex-1 overflow-y-auto px-6 py-4 custom-scrollbar" }, milestones.length > 0 ? /* @__PURE__ */ React27.createElement("div", { className: "space-y-3" }, milestones.map((ms) => /* @__PURE__ */ React27.createElement(
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(
13696
13708
  "div",
13697
13709
  {
13698
13710
  key: ms.id,
13699
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]"}`
13700
13712
  },
13701
- /* @__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(
13702
13714
  "div",
13703
13715
  {
13704
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"}`
13705
13717
  }
13706
- ), /* @__PURE__ */ React27.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React27.createElement("span", { className: `text-sm font-medium truncate ${ms.status === "active" ? "text-slate-100" : "text-slate-400 line-through"}` }, ms.name), /* @__PURE__ */ React27.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, ms.status === "active" ? "Ativo" : "Inativo"))),
13707
- /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React27.createElement(
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(
13708
13720
  "button",
13709
13721
  {
13710
13722
  onClick: () => handleToggleMilestoneStatus(ms.id),
13711
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"}`,
13712
13724
  title: ms.status === "active" ? "Inativar" : "Ativar"
13713
13725
  },
13714
- ms.status === "active" ? /* @__PURE__ */ React27.createElement(FiPauseCircle, { size: 18 }) : /* @__PURE__ */ React27.createElement(FiPlayCircle, { size: 18 })
13715
- ), /* @__PURE__ */ React27.createElement(
13726
+ ms.status === "active" ? /* @__PURE__ */ React29.createElement(FiPauseCircle, { size: 18 }) : /* @__PURE__ */ React29.createElement(FiPlayCircle, { size: 18 })
13727
+ ), /* @__PURE__ */ React29.createElement(
13716
13728
  "button",
13717
13729
  {
13718
13730
  onClick: () => handleRemoveMilestone(ms.id),
13719
13731
  className: "p-2 rounded-lg hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-all",
13720
13732
  title: "Remover"
13721
13733
  },
13722
- /* @__PURE__ */ React27.createElement(FiTrash24, { size: 18 })
13734
+ /* @__PURE__ */ React29.createElement(FiTrash24, { size: 18 })
13723
13735
  ))
13724
- ))) : /* @__PURE__ */ React27.createElement("div", { className: "flex flex-col items-center justify-center py-12 text-center" }, /* @__PURE__ */ React27.createElement("div", { className: "p-4 rounded-full bg-slate-800/30 text-slate-600 mb-4" }, /* @__PURE__ */ React27.createElement(FiTarget4, { size: 40 })), /* @__PURE__ */ React27.createElement("h3", { className: "text-slate-400 font-medium" }, "Nenhum milestone definido"), /* @__PURE__ */ React27.createElement("p", { className: "text-xs text-slate-600 max-w-[200px] mt-1 italic" }, "Defina marcos importantes para orientar o progresso do projeto."))),
13725
- /* @__PURE__ */ React27.createElement("div", { className: "px-6 py-4 border-t border-white/5 bg-slate-900/50 flex items-center justify-between rounded-b-2xl" }, /* @__PURE__ */ React27.createElement("div", { className: "flex gap-4" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React27.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Total:"), /* @__PURE__ */ React27.createElement("span", { className: "text-xs font-bold text-slate-300" }, milestones.length)), /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React27.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Ativos:"), /* @__PURE__ */ React27.createElement("span", { className: "text-xs font-bold text-indigo-400" }, milestones.filter((m) => m.status === "active").length))))
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))))
13726
13738
  )
13727
13739
  );
13728
13740
  }
@@ -13808,13 +13820,13 @@ function XViewScene({
13808
13820
  check_user_permission,
13809
13821
  get_view_members
13810
13822
  }) {
13811
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
13823
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
13812
13824
  const { data: session, status } = useSession();
13813
13825
  const router = useRouter();
13814
13826
  const searchParams = useSearchParams();
13815
13827
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
13816
13828
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
13817
- const viewParams = useMemo12(() => {
13829
+ const viewParams = useMemo13(() => {
13818
13830
  if (encryptedConfig) {
13819
13831
  const data = decryptData(encryptedConfig);
13820
13832
  if (data) {
@@ -13823,7 +13835,7 @@ function XViewScene({
13823
13835
  }
13824
13836
  return null;
13825
13837
  }, [encryptedConfig, session]);
13826
- useEffect22(() => {
13838
+ useEffect24(() => {
13827
13839
  async function verifyPermission() {
13828
13840
  if (!viewParams || !session || !check_user_permission) return;
13829
13841
  const { id, type, owner_id } = viewParams;
@@ -13860,65 +13872,65 @@ function XViewScene({
13860
13872
  setIsLoading(false);
13861
13873
  }
13862
13874
  }, [viewParams, session, status, check_user_permission]);
13863
- const sceneConfigId = useMemo12(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13864
- const ownerId = useMemo12(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13865
- const dbSaveUrl = useMemo12(() => {
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(() => {
13866
13878
  if (ownerId && sceneConfigId) {
13867
13879
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
13868
13880
  }
13869
13881
  return null;
13870
13882
  }, [ownerId, sceneConfigId]);
13871
- const sceneSaveUrl = useMemo12(() => {
13883
+ const sceneSaveUrl = useMemo13(() => {
13872
13884
  if (ownerId && sceneConfigId) {
13873
13885
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
13874
13886
  }
13875
13887
  return null;
13876
13888
  }, [ownerId, sceneConfigId]);
13877
- const ancestry_save_url = useMemo12(() => {
13889
+ const ancestry_save_url = useMemo13(() => {
13878
13890
  if (ownerId && sceneConfigId) {
13879
13891
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
13880
13892
  }
13881
13893
  return null;
13882
13894
  }, [ownerId, sceneConfigId]);
13883
- const sceneDataRef = useRef19(null);
13884
- const parentDataRef = useRef19(null);
13885
- const ancestryDataRef = useRef19(null);
13886
- const [isLoading, setIsLoading] = useState27(true);
13887
- const [permissionStatus, setPermissionStatus] = useState27("loading");
13888
- const [userPermissionRole, setUserPermissionRole] = useState27(null);
13889
- const [viewMembers, setViewMembers] = useState27([]);
13890
- const [isInitialized, setIsInitialized] = useState27(false);
13891
- const [sceneVersion, setSceneVersion] = useState27(0);
13892
- const [contextMenu, setContextMenu] = useState27({
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({
13893
13905
  visible: false,
13894
13906
  x: 0,
13895
13907
  y: 0,
13896
13908
  nodeData: null
13897
13909
  });
13898
- const [multiContextMenu, setMultiContextMenu] = useState27({
13910
+ const [multiContextMenu, setMultiContextMenu] = useState29({
13899
13911
  visible: false,
13900
13912
  x: 0,
13901
13913
  y: 0,
13902
13914
  nodeIds: null
13903
13915
  });
13904
- const [relationshipMenu, setRelationshipMenu] = useState27({
13916
+ const [relationshipMenu, setRelationshipMenu] = useState29({
13905
13917
  visible: false,
13906
13918
  x: 0,
13907
13919
  y: 0,
13908
13920
  linkObject: null
13909
13921
  });
13910
- const [creationMode, setCreationMode] = useState27({
13922
+ const [creationMode, setCreationMode] = useState29({
13911
13923
  isActive: false,
13912
13924
  sourceNodeData: null
13913
13925
  });
13914
- const [versionMode, setVersionMode] = useState27({
13926
+ const [versionMode, setVersionMode] = useState29({
13915
13927
  isActive: false,
13916
13928
  sourceNodeData: null
13917
13929
  });
13918
- const [questMode, setQuestMode] = useState27({ isActive: false });
13919
- const [hasFocusedInitial, setHasFocusedInitial] = useState27(false);
13920
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState27(false);
13921
- 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({
13922
13934
  isActive: false,
13923
13935
  tree: null,
13924
13936
  selectedParentId: null,
@@ -13929,42 +13941,42 @@ function XViewScene({
13929
13941
  ancestryDescriptionSections: [],
13930
13942
  isAddingNodes: false
13931
13943
  });
13932
- const [readingMode, setReadingMode] = useState27({
13944
+ const [readingMode, setReadingMode] = useState29({
13933
13945
  isActive: false,
13934
13946
  ancestry: null,
13935
13947
  branchStack: [],
13936
13948
  autoAbstraction: false
13937
13949
  });
13938
- const [formPosition, setFormPosition] = useState27({
13950
+ const [formPosition, setFormPosition] = useState29({
13939
13951
  left: 16,
13940
13952
  top: 16,
13941
13953
  opacity: 0
13942
13954
  });
13943
- const [detailsNode, setDetailsNode] = useState27(null);
13944
- const [detailsLink, setDetailsLink] = useState27(null);
13945
- const [ancestryLinkDetails, setAncestryLinkDetails] = useState27(null);
13946
- 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({
13947
13959
  visible: false,
13948
13960
  images: [],
13949
13961
  startIndex: 0
13950
13962
  });
13951
- const [editingAncestryRel, setEditingAncestryRel] = useState27({
13963
+ const [editingAncestryRel, setEditingAncestryRel] = useState29({
13952
13964
  visible: false,
13953
13965
  data: null,
13954
13966
  path: null
13955
13967
  });
13956
- const [isImportModalOpen, setIsImportModalOpen] = useState27(false);
13957
- const [importSuccessMessage, setImportSuccessMessage] = useState27("");
13958
- const [invalidTargetError, setInvalidTargetError] = useState27(null);
13959
- const [highlightedNodeId, setHighlightedNodeId] = useState27(null);
13960
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState27(false);
13961
- const [ancestryBoardData, setAncestryBoardData] = useState27([]);
13962
- const [isSidebarOpen, setIsSidebarOpen] = useState27(false);
13963
- const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState27(false);
13964
- const mountRef = useRef19(null);
13965
- const tooltipRef = useRef19(null);
13966
- const formRef = useRef19(null);
13967
- const stateRef = useRef19({
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({
13968
13980
  readMode: {
13969
13981
  currentMaxIndex: 0,
13970
13982
  progressMap: {}
@@ -14028,10 +14040,10 @@ function XViewScene({
14028
14040
  minWidth: 320,
14029
14041
  maxWidth: maxReadPanelW
14030
14042
  });
14031
- useEffect22(() => {
14043
+ useEffect24(() => {
14032
14044
  stateRef.current.ancestry = ancestryMode;
14033
14045
  }, [ancestryMode]);
14034
- useEffect22(() => {
14046
+ useEffect24(() => {
14035
14047
  var _a2;
14036
14048
  if (!isInitialized) return;
14037
14049
  const map = /* @__PURE__ */ new Map();
@@ -14054,10 +14066,10 @@ function XViewScene({
14054
14066
  }
14055
14067
  stateRef.current.nodeIdToParentFileMap = map;
14056
14068
  }, [isInitialized, sceneVersion]);
14057
- const handleNavigateBack = useCallback4(() => {
14069
+ const handleNavigateBack = useCallback5(() => {
14058
14070
  router.push("/dashboard/scenes");
14059
14071
  }, [router]);
14060
- const handleConfirmImport = useCallback4(
14072
+ const handleConfirmImport = useCallback5(
14061
14073
  async (importPayload) => {
14062
14074
  var _a2, _b2;
14063
14075
  let files = [];
@@ -14185,7 +14197,7 @@ function XViewScene({
14185
14197
  const handleOpenImageViewer = (images, startIndex) => {
14186
14198
  setImageViewer({ visible: true, images, startIndex });
14187
14199
  };
14188
- const tweenToTarget = useCallback4(
14200
+ const tweenToTarget = useCallback5(
14189
14201
  (target, zoomFactor = 1, forcedDirection = null) => {
14190
14202
  const { camera, controls, tweenGroup } = stateRef.current;
14191
14203
  if (!camera || !controls || !tweenGroup) return;
@@ -14211,7 +14223,7 @@ function XViewScene({
14211
14223
  if (!t || typeof t.closest !== "function") return false;
14212
14224
  return !!t.closest(".ui-overlay");
14213
14225
  };
14214
- const buildFullAncestryTree = useCallback4(
14226
+ const buildFullAncestryTree = useCallback5(
14215
14227
  (idTree, nodes, ancestries = []) => {
14216
14228
  if (!idTree) return null;
14217
14229
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
@@ -14296,7 +14308,7 @@ function XViewScene({
14296
14308
  },
14297
14309
  []
14298
14310
  );
14299
- const handleActivateTimeline = useCallback4(() => {
14311
+ const handleActivateTimeline = useCallback5(() => {
14300
14312
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
14301
14313
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
14302
14314
  while (timelineIntervalsGroup.children.length > 0) {
@@ -14456,7 +14468,7 @@ function XViewScene({
14456
14468
  }
14457
14469
  });
14458
14470
  }, []);
14459
- const handleVersionTimeline = useCallback4((sourceMesh, versionMeshes) => {
14471
+ const handleVersionTimeline = useCallback5((sourceMesh, versionMeshes) => {
14460
14472
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
14461
14473
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
14462
14474
  return;
@@ -14593,7 +14605,7 @@ function XViewScene({
14593
14605
  }
14594
14606
  });
14595
14607
  }, []);
14596
- useEffect22(() => {
14608
+ useEffect24(() => {
14597
14609
  async function fetchAllData(configPath, ownerId2) {
14598
14610
  var _a2, _b2;
14599
14611
  if (!get_scene_view_data) {
@@ -14698,12 +14710,12 @@ function XViewScene({
14698
14710
  focusNodeId,
14699
14711
  focusAncestryId
14700
14712
  ]);
14701
- const isNodeInView = useCallback4((id) => {
14713
+ const isNodeInView = useCallback5((id) => {
14702
14714
  const key = String(id);
14703
14715
  const objs = stateRef.current.nodeObjects || {};
14704
14716
  return !!objs[key];
14705
14717
  }, []);
14706
- const addOrUpdateNodeMesh = useCallback4(
14718
+ const addOrUpdateNodeMesh = useCallback5(
14707
14719
  (nodeData, position, suppressVersionUpdate = false, forceShowQuestDate = false) => {
14708
14720
  const {
14709
14721
  graphGroup,
@@ -14744,7 +14756,7 @@ function XViewScene({
14744
14756
  },
14745
14757
  []
14746
14758
  );
14747
- const handleActivateQuestLens = useCallback4(({ assigneeId, status: status2, milestoneId }) => {
14759
+ const handleActivateQuestLens = useCallback5(({ assigneeId, status: status2, milestoneId }) => {
14748
14760
  var _a2;
14749
14761
  const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
14750
14762
  if (!nodeObjects || !tweenGroup || !graphGroup) return;
@@ -14958,7 +14970,7 @@ function XViewScene({
14958
14970
  camTween.start();
14959
14971
  }
14960
14972
  }, [addOrUpdateNodeMesh]);
14961
- useEffect22(() => {
14973
+ useEffect24(() => {
14962
14974
  if (!isInitialized || !sceneDataRef.current) return;
14963
14975
  const currentMount = mountRef.current;
14964
14976
  if (!currentMount) return;
@@ -15714,7 +15726,7 @@ function XViewScene({
15714
15726
  get_scene_view_data,
15715
15727
  save_view_data
15716
15728
  ]);
15717
- const handleGhostNodeImageChange = useCallback4((useImage, imageUrl) => {
15729
+ const handleGhostNodeImageChange = useCallback5((useImage, imageUrl) => {
15718
15730
  const {
15719
15731
  node: ghostNode,
15720
15732
  line: ghostLine,
@@ -15762,7 +15774,7 @@ function XViewScene({
15762
15774
  aura: newGhostNode.getObjectByName("aura")
15763
15775
  };
15764
15776
  }, []);
15765
- const handleGhostNodeIntensityChange = useCallback4((newIntensity) => {
15777
+ const handleGhostNodeIntensityChange = useCallback5((newIntensity) => {
15766
15778
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
15767
15779
  if (!ghostNode) return;
15768
15780
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -15783,7 +15795,7 @@ function XViewScene({
15783
15795
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
15784
15796
  }
15785
15797
  }, []);
15786
- const handleDetailNodeIntensityChange = useCallback4(
15798
+ const handleDetailNodeIntensityChange = useCallback5(
15787
15799
  (nodeId, newIntensity) => {
15788
15800
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
15789
15801
  if (!mesh) return;
@@ -15939,7 +15951,7 @@ function XViewScene({
15939
15951
  mountRef.current.style.cursor = "default";
15940
15952
  }
15941
15953
  };
15942
- const handleAncestryTreeUpdate = useCallback4((newTree, extraData = null) => {
15954
+ const handleAncestryTreeUpdate = useCallback5((newTree, extraData = null) => {
15943
15955
  setAncestryMode((prev) => {
15944
15956
  const prevTreeStr = JSON.stringify(prev.tree);
15945
15957
  const newTreeStr = JSON.stringify(newTree);
@@ -15962,7 +15974,7 @@ function XViewScene({
15962
15974
  };
15963
15975
  });
15964
15976
  }, []);
15965
- const actionHandlerContext = useMemo12(
15977
+ const actionHandlerContext = useMemo13(
15966
15978
  () => {
15967
15979
  var _a2;
15968
15980
  return {
@@ -16023,7 +16035,7 @@ function XViewScene({
16023
16035
  const handleStartVersioning = (nodeData) => {
16024
16036
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
16025
16037
  };
16026
- const handleStartQuestQuick = useCallback4((questNode) => {
16038
+ const handleStartQuestQuick = useCallback5((questNode) => {
16027
16039
  var _a2, _b2, _c2;
16028
16040
  if (!questNode || !actionHandlerContext) return;
16029
16041
  const allParentNodes = Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
@@ -16058,7 +16070,7 @@ function XViewScene({
16058
16070
  }
16059
16071
  setDetailsNode(updatedNode);
16060
16072
  }, [session, actionHandlerContext]);
16061
- const handleFinishQuestQuick = useCallback4((questNode) => {
16073
+ const handleFinishQuestQuick = useCallback5((questNode) => {
16062
16074
  var _a2, _b2, _c2, _d2;
16063
16075
  if (!questNode || !actionHandlerContext) return;
16064
16076
  const {
@@ -16132,7 +16144,7 @@ function XViewScene({
16132
16144
  setDetailsNode(null);
16133
16145
  }
16134
16146
  }, [session, actionHandlerContext, viewMembers, detailsNode]);
16135
- const handleCancelQuest = useCallback4(() => {
16147
+ const handleCancelQuest = useCallback5(() => {
16136
16148
  const { graphGroup, ghostElements } = stateRef.current;
16137
16149
  if (ghostElements.node && graphGroup) {
16138
16150
  if (ghostElements.node.userData.labelObject) {
@@ -16191,13 +16203,15 @@ function XViewScene({
16191
16203
  try {
16192
16204
  await actions.save_view_data(sceneSaveUrl2, sceneFileData);
16193
16205
  sceneDataRef2.current.quest_counter = currentCounter + 1;
16194
- sceneDataRef2.current.quest_nodes = sceneFileData.quest_nodes;
16195
- sceneDataRef2.current.quest_links = sceneFileData.quest_links;
16196
16206
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
16197
16207
  parentFileId: sceneConfigId2,
16198
16208
  ownerId: ownerId2,
16199
16209
  datasetName: "Quests Internas (View)"
16200
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
+ }
16201
16215
  const finalPosition = stateRef2.current.ghostElements.node ? stateRef2.current.ghostElements.node.position.clone() : stateRef2.current.controls.target.clone();
16202
16216
  const { graphGroup, ghostElements } = stateRef2.current;
16203
16217
  if (ghostElements.node && graphGroup) {
@@ -16287,7 +16301,7 @@ function XViewScene({
16287
16301
  }
16288
16302
  userActionHandlers.handleCancelConnection(context);
16289
16303
  };
16290
- const handleClearAncestryVisuals = useCallback4((ancestryId) => {
16304
+ const handleClearAncestryVisuals = useCallback5((ancestryId) => {
16291
16305
  const { renderedAncestries, ancestryGroup } = stateRef.current;
16292
16306
  const renderIndex = renderedAncestries.findIndex(
16293
16307
  (a) => String(a.id) === String(ancestryId)
@@ -16305,7 +16319,7 @@ function XViewScene({
16305
16319
  );
16306
16320
  }
16307
16321
  }, []);
16308
- const handleRenderAncestry = useCallback4(
16322
+ const handleRenderAncestry = useCallback5(
16309
16323
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
16310
16324
  setContextMenu(
16311
16325
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16799,7 +16813,7 @@ function XViewScene({
16799
16813
  ancestryMode.isActive
16800
16814
  ]
16801
16815
  );
16802
- const handleRenderAbstractionTree = useCallback4(
16816
+ const handleRenderAbstractionTree = useCallback5(
16803
16817
  (ancestryObject, targetNodeId = null) => {
16804
16818
  setContextMenu(
16805
16819
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16887,7 +16901,7 @@ function XViewScene({
16887
16901
  handleClearAncestryVisuals
16888
16902
  ]
16889
16903
  );
16890
- const handleReadModeBranchNav = useCallback4(
16904
+ const handleReadModeBranchNav = useCallback5(
16891
16905
  (nodeId, action, direction = "right") => {
16892
16906
  const { ancestry, branchStack } = readingMode;
16893
16907
  if (!ancestry || !ancestry.tree) return;
@@ -17065,13 +17079,13 @@ function XViewScene({
17065
17079
  },
17066
17080
  [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
17067
17081
  );
17068
- const handleReadModeHighlight = useCallback4((nodeId) => {
17082
+ const handleReadModeHighlight = useCallback5((nodeId) => {
17069
17083
  if (stateRef.current.highlightedNodeId !== nodeId) {
17070
17084
  stateRef.current.highlightedNodeId = nodeId;
17071
17085
  }
17072
17086
  setHighlightedNodeId(nodeId);
17073
17087
  }, []);
17074
- const activeNodeBranches = useMemo12(() => {
17088
+ const activeNodeBranches = useMemo13(() => {
17075
17089
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
17076
17090
  return null;
17077
17091
  const fullTree = buildFullAncestryTree(
@@ -17115,7 +17129,7 @@ function XViewScene({
17115
17129
  readingMode.branchStack,
17116
17130
  ancestryDataRef.current
17117
17131
  ]);
17118
- const backNavigationInfo = useMemo12(() => {
17132
+ const backNavigationInfo = useMemo13(() => {
17119
17133
  const { branchStack } = readingMode;
17120
17134
  if (!branchStack || branchStack.length === 0) return null;
17121
17135
  const lastStep = branchStack[branchStack.length - 1];
@@ -17126,7 +17140,7 @@ function XViewScene({
17126
17140
  name: "Voltar para anterior"
17127
17141
  };
17128
17142
  }, [readingMode.branchStack]);
17129
- const getReadModeDisplayContext = useMemo12(() => {
17143
+ const getReadModeDisplayContext = useMemo13(() => {
17130
17144
  const { ancestry, branchStack } = readingMode;
17131
17145
  if (!ancestry) return null;
17132
17146
  if (branchStack.length === 0) {
@@ -17169,7 +17183,7 @@ function XViewScene({
17169
17183
  customProperties: branchProps
17170
17184
  };
17171
17185
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
17172
- const readModeAbstractionTree = useMemo12(() => {
17186
+ const readModeAbstractionTree = useMemo13(() => {
17173
17187
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
17174
17188
  return null;
17175
17189
  }
@@ -17188,7 +17202,7 @@ function XViewScene({
17188
17202
  buildFullAncestryTree,
17189
17203
  sceneVersion
17190
17204
  ]);
17191
- const handleStartReadingAncestry = useCallback4(
17205
+ const handleStartReadingAncestry = useCallback5(
17192
17206
  async (ancestryObject, renderMode = "full") => {
17193
17207
  setContextMenu(
17194
17208
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17231,7 +17245,7 @@ function XViewScene({
17231
17245
  },
17232
17246
  [handleRenderAncestry, handleRenderAbstractionTree]
17233
17247
  );
17234
- const handleReadModeSectionChange = useCallback4(
17248
+ const handleReadModeSectionChange = useCallback5(
17235
17249
  (activeSectionId) => {
17236
17250
  const { ancestry, branchStack } = readingMode;
17237
17251
  if (!ancestry || !readingMode.isActive) return;
@@ -17316,10 +17330,10 @@ function XViewScene({
17316
17330
  ancestryDataRef.current
17317
17331
  ]
17318
17332
  );
17319
- const handleCloseReadMode = useCallback4(() => {
17333
+ const handleCloseReadMode = useCallback5(() => {
17320
17334
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
17321
17335
  }, []);
17322
- const handleAncestrySectionChange = useCallback4(
17336
+ const handleAncestrySectionChange = useCallback5(
17323
17337
  (activeSectionId, ancestryOverride = null, rotation = 0) => {
17324
17338
  var _a2, _b2;
17325
17339
  const currentMode = stateRef.current.ancestry;
@@ -17381,7 +17395,7 @@ function XViewScene({
17381
17395
  },
17382
17396
  [handleRenderAncestry]
17383
17397
  );
17384
- const handleEditAncestry = useCallback4(
17398
+ const handleEditAncestry = useCallback5(
17385
17399
  async (ancestryObject) => {
17386
17400
  setContextMenu(
17387
17401
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17436,7 +17450,7 @@ function XViewScene({
17436
17450
  const handleSelectAncestryParent = (nodeId) => {
17437
17451
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
17438
17452
  };
17439
- const handleRemoveFromAncestry = useCallback4((pathToRemove) => {
17453
+ const handleRemoveFromAncestry = useCallback5((pathToRemove) => {
17440
17454
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
17441
17455
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
17442
17456
  return;
@@ -17461,7 +17475,7 @@ function XViewScene({
17461
17475
  return { ...prev, tree: newTree };
17462
17476
  });
17463
17477
  }, []);
17464
- const handleSaveAncestry = useCallback4(
17478
+ const handleSaveAncestry = useCallback5(
17465
17479
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
17466
17480
  const treeToUse = treeOverride || ancestryMode.tree;
17467
17481
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -17697,7 +17711,7 @@ function XViewScene({
17697
17711
  });
17698
17712
  setEditingAncestryRel({ visible: false, data: null, path: null });
17699
17713
  };
17700
- const handleDeleteAncestry = useCallback4(
17714
+ const handleDeleteAncestry = useCallback5(
17701
17715
  async (ancestryIdToDelete) => {
17702
17716
  if (!ancestryIdToDelete) {
17703
17717
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -17779,28 +17793,70 @@ function XViewScene({
17779
17793
  },
17780
17794
  [save_view_data, delete_file_action]
17781
17795
  );
17782
- const handleOpenAncestryBoard = useCallback4(() => {
17796
+ const handleOpenAncestryBoard = useCallback5(() => {
17783
17797
  setIsAncestryBoardOpen(true);
17784
17798
  }, []);
17785
- const handleSelectAncestryFromBoard = useCallback4(
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(
17786
17848
  (item) => {
17787
17849
  setIsAncestryBoardOpen(false);
17788
17850
  setIsSidebarOpen(false);
17789
- if (item.type === "ancestry" || !item.type) {
17851
+ if (item.type === "ancestry") {
17790
17852
  handleStartReadingAncestry(item);
17791
17853
  } else {
17792
- const nodeId = String(item.id);
17793
- const sceneMesh = stateRef.current.nodeObjects[nodeId];
17794
- if (sceneMesh) {
17795
- tweenToTarget(sceneMesh);
17796
- } else {
17797
- console.warn("Objeto n\xE3o encontrado na cena para foco:", nodeId);
17798
- }
17854
+ handleOpenReference({ type: "node", id: item.id });
17799
17855
  }
17800
17856
  },
17801
- [handleStartReadingAncestry, tweenToTarget]
17857
+ [handleStartReadingAncestry, handleOpenReference]
17802
17858
  );
17803
- const handleSaveAncestryBoard = useCallback4(
17859
+ const handleSaveAncestryBoard = useCallback5(
17804
17860
  async (groups) => {
17805
17861
  if (!sceneConfigId || !viewParams || !session) return;
17806
17862
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
@@ -17814,7 +17870,7 @@ function XViewScene({
17814
17870
  },
17815
17871
  [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
17816
17872
  );
17817
- const existingNodeTypes = useMemo12(() => {
17873
+ const existingNodeTypes = useMemo13(() => {
17818
17874
  if (!parentDataRef.current) {
17819
17875
  return [];
17820
17876
  }
@@ -17826,28 +17882,22 @@ function XViewScene({
17826
17882
  ).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
17827
17883
  return [...new Set(allTypes)];
17828
17884
  }, [parentDataRef.current, sceneVersion]);
17829
- const searchableDbNodes = useMemo12(() => {
17830
- var _a2;
17885
+ const searchableDbNodes = useMemo13(() => {
17831
17886
  if (!parentDataRef.current) {
17832
17887
  return [];
17833
17888
  }
17834
- const datasetsPool = Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17889
+ return Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17835
17890
  const datasetName = fileData.dataset_name || `Dataset #${dbId.substring(0, 6)}`;
17836
17891
  return (fileData.nodes || []).map((node) => ({
17837
17892
  ...node,
17838
17893
  dataset_name: datasetName
17839
17894
  }));
17895
+ }).filter((node) => {
17896
+ var _a2;
17897
+ return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
17840
17898
  });
17841
- const questsPool = (((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || []).map((node) => ({
17842
- ...node,
17843
- dataset_name: "Quests Internas (View)"
17844
- }));
17845
- return [...datasetsPool, ...questsPool].filter((node) => {
17846
- var _a3;
17847
- return !((_a3 = node.version_node) == null ? void 0 : _a3.is_version);
17848
- });
17849
- }, [parentDataRef.current, (_b = sceneDataRef.current) == null ? void 0 : _b.quest_nodes, sceneVersion]);
17850
- const handleAddExistingNode = useCallback4(
17899
+ }, [parentDataRef.current, sceneVersion]);
17900
+ const handleAddExistingNode = useCallback5(
17851
17901
  (nodeId) => {
17852
17902
  return userActionHandlers.handleAddExistingNodeById(
17853
17903
  actionHandlerContext,
@@ -17856,7 +17906,7 @@ function XViewScene({
17856
17906
  },
17857
17907
  [actionHandlerContext]
17858
17908
  );
17859
- const handleUpdateMilestones = useCallback4(
17909
+ const handleUpdateMilestones = useCallback5(
17860
17910
  async (newMilestones) => {
17861
17911
  var _a2, _b2, _c2;
17862
17912
  if (!sceneDataRef.current) return;
@@ -17902,7 +17952,7 @@ function XViewScene({
17902
17952
  viewParams == null ? void 0 : viewParams.type
17903
17953
  ]
17904
17954
  );
17905
- const handleSaveCurrentView = useCallback4(async () => {
17955
+ const handleSaveCurrentView = useCallback5(async () => {
17906
17956
  var _a2, _b2, _c2;
17907
17957
  const { nodeObjects, allLinks } = stateRef.current;
17908
17958
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
@@ -17945,61 +17995,13 @@ function XViewScene({
17945
17995
  console.error("Erro na chamada de save_view_data:", error);
17946
17996
  }
17947
17997
  }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
17948
- const allAvailableNodes = useMemo12(() => {
17949
- if (!parentDataRef.current) return [];
17950
- return Object.values(parentDataRef.current).flatMap(
17951
- (fileData) => fileData.nodes || []
17952
- );
17953
- }, [sceneVersion, isInitialized]);
17954
- const allAvailableAncestries = useMemo12(() => {
17955
- return ancestryDataRef.current || [];
17956
- }, [sceneVersion, isInitialized]);
17957
- const handleOpenReference = useCallback4(
17958
- (referenceData) => {
17959
- const { type, id } = referenceData;
17960
- if (type === "node") {
17961
- const targetNode = allAvailableNodes.find(
17962
- (n) => String(n.id) === String(id)
17963
- );
17964
- if (targetNode) {
17965
- setAncestryLinkDetails(null);
17966
- setDetailsLink(null);
17967
- setDetailsNode(targetNode);
17968
- const sceneMesh = stateRef.current.nodeObjects[String(id)];
17969
- if (sceneMesh) {
17970
- tweenToTarget(sceneMesh);
17971
- }
17972
- } else {
17973
- alert("Node original n\xE3o encontrado neste contexto.");
17974
- }
17975
- } else if (type === "ancestry") {
17976
- const targetAncestry = allAvailableAncestries.find(
17977
- (a) => String(a.ancestry_id) === String(id)
17978
- );
17979
- if (targetAncestry) {
17980
- setDetailsNode(null);
17981
- setDetailsLink(null);
17982
- setAncestryLinkDetails(null);
17983
- handleEditAncestry(targetAncestry);
17984
- } else {
17985
- alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17986
- }
17987
- }
17988
- },
17989
- [
17990
- allAvailableNodes,
17991
- allAvailableAncestries,
17992
- handleEditAncestry,
17993
- tweenToTarget
17994
- ]
17995
- );
17996
- const handleToggleAncestryAddMode = useCallback4(() => {
17998
+ const handleToggleAncestryAddMode = useCallback5(() => {
17997
17999
  setAncestryMode((prev) => ({
17998
18000
  ...prev,
17999
18001
  isAddingNodes: !prev.isAddingNodes
18000
18002
  }));
18001
18003
  }, []);
18002
- const handleFocusNode = useCallback4(
18004
+ const handleFocusNode = useCallback5(
18003
18005
  (nodeData) => {
18004
18006
  var _a2;
18005
18007
  if (!nodeData) return;
@@ -18015,7 +18017,7 @@ function XViewScene({
18015
18017
  },
18016
18018
  [tweenToTarget]
18017
18019
  );
18018
- const availableDatasets = useMemo12(() => {
18020
+ const availableDatasets = useMemo13(() => {
18019
18021
  if (!sceneDataRef.current || !parentDataRef.current) return [];
18020
18022
  return sceneDataRef.current.parent_dbs.map((db) => {
18021
18023
  var _a2;
@@ -18025,11 +18027,11 @@ function XViewScene({
18025
18027
  };
18026
18028
  });
18027
18029
  }, [sceneVersion, isInitialized]);
18028
- const sourceNodeDatasetId = creationMode.sourceNodeData ? (_c = stateRef.current.nodeIdToParentFileMap.get(
18030
+ const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(
18029
18031
  String(creationMode.sourceNodeData.id)
18030
- )) == null ? void 0 : _c.parentFileId : null;
18032
+ )) == null ? void 0 : _b.parentFileId : null;
18031
18033
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
18032
- useEffect22(() => {
18034
+ useEffect24(() => {
18033
18035
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
18034
18036
  const nodeObjects = stateRef.current.nodeObjects || {};
18035
18037
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -18052,7 +18054,7 @@ function XViewScene({
18052
18054
  hasFocusedInitial,
18053
18055
  tweenToTarget
18054
18056
  ]);
18055
- useEffect22(() => {
18057
+ useEffect24(() => {
18056
18058
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
18057
18059
  const ancestries = ancestryDataRef.current || [];
18058
18060
  const targetAncestry = ancestries.find(
@@ -18077,7 +18079,7 @@ function XViewScene({
18077
18079
  hasOpenedInitialAncestry,
18078
18080
  handleStartReadingAncestry
18079
18081
  ]);
18080
- useEffect22(() => {
18082
+ useEffect24(() => {
18081
18083
  function handleKeyDown(event) {
18082
18084
  var _a2, _b2, _c2;
18083
18085
  const context = actionHandlerContext;
@@ -18200,10 +18202,10 @@ function XViewScene({
18200
18202
  // <-- handleCancelQuest adicionado aqui
18201
18203
  ]);
18202
18204
  if (isLoading || status === "loading" || permissionStatus === "loading") {
18203
- return /* @__PURE__ */ React28.createElement(LoadingScreen, null);
18205
+ return /* @__PURE__ */ React30.createElement(LoadingScreen, null);
18204
18206
  }
18205
18207
  if (permissionStatus === "denied") {
18206
- return /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ React28.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ React28.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ React28.createElement(
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(
18207
18209
  "svg",
18208
18210
  {
18209
18211
  xmlns: "http://www.w3.org/2000/svg",
@@ -18213,7 +18215,7 @@ function XViewScene({
18213
18215
  stroke: "currentColor",
18214
18216
  className: "w-16 h-16 mx-auto"
18215
18217
  },
18216
- /* @__PURE__ */ React28.createElement(
18218
+ /* @__PURE__ */ React30.createElement(
18217
18219
  "path",
18218
18220
  {
18219
18221
  strokeLinecap: "round",
@@ -18221,13 +18223,13 @@ function XViewScene({
18221
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"
18222
18224
  }
18223
18225
  )
18224
- )), /* @__PURE__ */ React28.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ React28.createElement("p", { className: "text-slate-400 mb-6" }, "Voc\xEA n\xE3o tem permiss\xE3o para acessar este conte\xFAdo. Solicite acesso ao propriet\xE1rio ou verifique se est\xE1 na conta correta."), /* @__PURE__ */ React28.createElement(
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(
18225
18227
  "button",
18226
18228
  {
18227
18229
  onClick: () => router.push("/dashboard/scenes"),
18228
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"
18229
18231
  },
18230
- /* @__PURE__ */ React28.createElement(
18232
+ /* @__PURE__ */ React30.createElement(
18231
18233
  "svg",
18232
18234
  {
18233
18235
  xmlns: "http://www.w3.org/2000/svg",
@@ -18237,7 +18239,7 @@ function XViewScene({
18237
18239
  stroke: "currentColor",
18238
18240
  className: "w-5 h-5"
18239
18241
  },
18240
- /* @__PURE__ */ React28.createElement(
18242
+ /* @__PURE__ */ React30.createElement(
18241
18243
  "path",
18242
18244
  {
18243
18245
  strokeLinecap: "round",
@@ -18249,7 +18251,7 @@ function XViewScene({
18249
18251
  "Voltar para Scenes"
18250
18252
  )));
18251
18253
  }
18252
- return /* @__PURE__ */ React28.createElement(
18254
+ return /* @__PURE__ */ React30.createElement(
18253
18255
  "div",
18254
18256
  {
18255
18257
  ref: mountRef,
@@ -18261,7 +18263,7 @@ function XViewScene({
18261
18263
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
18262
18264
  }
18263
18265
  },
18264
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ React28.createElement(
18266
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ React30.createElement(
18265
18267
  XViewSidebar,
18266
18268
  {
18267
18269
  dbNodes: searchableDbNodes,
@@ -18281,11 +18283,11 @@ function XViewScene({
18281
18283
  onToggle: setIsSidebarOpen,
18282
18284
  userRole: userPermissionRole,
18283
18285
  viewMembers,
18284
- milestones: ((_d = sceneDataRef.current) == null ? void 0 : _d.milestones) || [],
18286
+ milestones: ((_c = sceneDataRef.current) == null ? void 0 : _c.milestones) || [],
18285
18287
  onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
18286
18288
  }
18287
18289
  ),
18288
- creationMode.isActive && /* @__PURE__ */ React28.createElement(
18290
+ creationMode.isActive && /* @__PURE__ */ React30.createElement(
18289
18291
  InSceneCreationForm,
18290
18292
  {
18291
18293
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -18306,8 +18308,8 @@ function XViewScene({
18306
18308
  },
18307
18309
  refEl: formRef,
18308
18310
  existingTypes: existingNodeTypes,
18309
- initialColor: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.color,
18310
- sourceTypes: (_f = creationMode.sourceNodeData) == null ? void 0 : _f.type,
18311
+ initialColor: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.color,
18312
+ sourceTypes: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.type,
18311
18313
  onIntensityChange: handleGhostNodeIntensityChange,
18312
18314
  onUploadFile: upload_file_action,
18313
18315
  availableDatasets,
@@ -18317,7 +18319,7 @@ function XViewScene({
18317
18319
  availableAncestries: allAvailableAncestries
18318
18320
  }
18319
18321
  ),
18320
- versionMode.isActive && /* @__PURE__ */ React28.createElement(
18322
+ versionMode.isActive && /* @__PURE__ */ React30.createElement(
18321
18323
  InSceneVersionForm,
18322
18324
  {
18323
18325
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -18336,14 +18338,14 @@ function XViewScene({
18336
18338
  transition: "opacity 200ms ease-out"
18337
18339
  },
18338
18340
  refEl: formRef,
18339
- fixedType: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.type,
18340
- fixedColor: (_h = versionMode.sourceNodeData) == null ? void 0 : _h.color,
18341
+ fixedType: (_f = versionMode.sourceNodeData) == null ? void 0 : _f.type,
18342
+ fixedColor: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.color,
18341
18343
  onUploadFile: upload_file_action,
18342
18344
  availableNodes: allAvailableNodes,
18343
18345
  availableAncestries: allAvailableAncestries
18344
18346
  }
18345
18347
  ),
18346
- questMode.isActive && /* @__PURE__ */ React28.createElement(
18348
+ questMode.isActive && /* @__PURE__ */ React30.createElement(
18347
18349
  InSceneQuestForm,
18348
18350
  {
18349
18351
  onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
@@ -18365,13 +18367,13 @@ function XViewScene({
18365
18367
  availableNodes: allAvailableNodes,
18366
18368
  availableAncestries: allAvailableAncestries,
18367
18369
  viewName: viewParams == null ? void 0 : viewParams.name,
18368
- questCounter: ((_i = sceneDataRef.current) == null ? void 0 : _i.quest_counter) || 1,
18370
+ questCounter: ((_h = sceneDataRef.current) == null ? void 0 : _h.quest_counter) || 1,
18369
18371
  viewMembers,
18370
- milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18372
+ milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
18371
18373
  onUpdateMilestones: handleUpdateMilestones
18372
18374
  }
18373
18375
  ),
18374
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React28.createElement(
18376
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React30.createElement(
18375
18377
  "div",
18376
18378
  {
18377
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"}`,
@@ -18384,7 +18386,7 @@ function XViewScene({
18384
18386
  maxWidth: "92vw"
18385
18387
  }
18386
18388
  },
18387
- /* @__PURE__ */ React28.createElement(
18389
+ /* @__PURE__ */ React30.createElement(
18388
18390
  "div",
18389
18391
  {
18390
18392
  onPointerDown: (e) => {
@@ -18395,7 +18397,7 @@ function XViewScene({
18395
18397
  title: "Arraste para redimensionar"
18396
18398
  }
18397
18399
  ),
18398
- /* @__PURE__ */ React28.createElement(
18400
+ /* @__PURE__ */ React30.createElement(
18399
18401
  DescriptionReadModePanel,
18400
18402
  {
18401
18403
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -18430,7 +18432,7 @@ function XViewScene({
18430
18432
  }
18431
18433
  )
18432
18434
  ),
18433
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React28.createElement(
18435
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React30.createElement(
18434
18436
  CreateAncestryPanel,
18435
18437
  {
18436
18438
  ancestryMode,
@@ -18466,7 +18468,7 @@ function XViewScene({
18466
18468
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
18467
18469
  }
18468
18470
  ),
18469
- editingAncestryRel.visible && /* @__PURE__ */ React28.createElement(
18471
+ editingAncestryRel.visible && /* @__PURE__ */ React30.createElement(
18470
18472
  AncestryRelationshipPanel,
18471
18473
  {
18472
18474
  data: editingAncestryRel.data,
@@ -18480,7 +18482,7 @@ function XViewScene({
18480
18482
  onUploadFile: upload_file_action
18481
18483
  }
18482
18484
  ),
18483
- detailsNode && detailsNode.is_quest && /* @__PURE__ */ React28.createElement(
18485
+ detailsNode && detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
18484
18486
  QuestDetailsPanel,
18485
18487
  {
18486
18488
  node: detailsNode,
@@ -18502,11 +18504,11 @@ function XViewScene({
18502
18504
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
18503
18505
  viewMembers,
18504
18506
  currentUser: session == null ? void 0 : session.user,
18505
- milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18507
+ milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18506
18508
  onUpdateMilestones: handleUpdateMilestones
18507
18509
  }
18508
18510
  ),
18509
- detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React28.createElement(
18511
+ detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
18510
18512
  NodeDetailsPanel,
18511
18513
  {
18512
18514
  node: detailsNode,
@@ -18538,7 +18540,7 @@ function XViewScene({
18538
18540
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
18539
18541
  }
18540
18542
  ),
18541
- detailsLink && /* @__PURE__ */ React28.createElement(
18543
+ detailsLink && /* @__PURE__ */ React30.createElement(
18542
18544
  RelationshipDetailsPanel,
18543
18545
  {
18544
18546
  link: detailsLink,
@@ -18552,7 +18554,7 @@ function XViewScene({
18552
18554
  userRole: userPermissionRole
18553
18555
  }
18554
18556
  ),
18555
- ancestryLinkDetails && /* @__PURE__ */ React28.createElement(
18557
+ ancestryLinkDetails && /* @__PURE__ */ React30.createElement(
18556
18558
  AncestryLinkDetailsPanel,
18557
18559
  {
18558
18560
  data: ancestryLinkDetails,
@@ -18563,7 +18565,7 @@ function XViewScene({
18563
18565
  onUploadFile: upload_file_action
18564
18566
  }
18565
18567
  ),
18566
- /* @__PURE__ */ React28.createElement(
18568
+ /* @__PURE__ */ React30.createElement(
18567
18569
  "div",
18568
18570
  {
18569
18571
  ref: tooltipRef,
@@ -18590,7 +18592,7 @@ function XViewScene({
18590
18592
  }
18591
18593
  }
18592
18594
  ),
18593
- /* @__PURE__ */ React28.createElement(
18595
+ /* @__PURE__ */ React30.createElement(
18594
18596
  ContextMenu,
18595
18597
  {
18596
18598
  data: contextMenu,
@@ -18623,7 +18625,7 @@ function XViewScene({
18623
18625
  onFinishQuest: handleFinishQuestQuick
18624
18626
  }
18625
18627
  ),
18626
- /* @__PURE__ */ React28.createElement(
18628
+ /* @__PURE__ */ React30.createElement(
18627
18629
  MultiNodeContextMenu,
18628
18630
  {
18629
18631
  data: multiContextMenu,
@@ -18643,7 +18645,7 @@ function XViewScene({
18643
18645
  )
18644
18646
  }
18645
18647
  ),
18646
- /* @__PURE__ */ React28.createElement(
18648
+ /* @__PURE__ */ React30.createElement(
18647
18649
  RelationshipContextMenu,
18648
18650
  {
18649
18651
  data: relationshipMenu,
@@ -18661,14 +18663,14 @@ function XViewScene({
18661
18663
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
18662
18664
  }
18663
18665
  ),
18664
- /* @__PURE__ */ React28.createElement(
18666
+ /* @__PURE__ */ React30.createElement(
18665
18667
  ImageViewer,
18666
18668
  {
18667
18669
  data: imageViewer,
18668
18670
  onClose: () => setImageViewer({ ...imageViewer, visible: false })
18669
18671
  }
18670
18672
  ),
18671
- /* @__PURE__ */ React28.createElement(
18673
+ /* @__PURE__ */ React30.createElement(
18672
18674
  AncestryBoard,
18673
18675
  {
18674
18676
  isOpen: isAncestryBoardOpen,
@@ -18681,29 +18683,29 @@ function XViewScene({
18681
18683
  userRole: userPermissionRole
18682
18684
  }
18683
18685
  ),
18684
- /* @__PURE__ */ React28.createElement(
18686
+ /* @__PURE__ */ React30.createElement(
18685
18687
  MilestoneManager,
18686
18688
  {
18687
18689
  isOpen: isMilestoneManagerOpen,
18688
18690
  onClose: () => setIsMilestoneManagerOpen(false),
18689
- milestones: ((_l = sceneDataRef.current) == null ? void 0 : _l.milestones) || [],
18691
+ milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18690
18692
  onUpdateMilestones: handleUpdateMilestones
18691
18693
  }
18692
18694
  ),
18693
- /* @__PURE__ */ React28.createElement(
18695
+ /* @__PURE__ */ React30.createElement(
18694
18696
  ImportParentFileModal,
18695
18697
  {
18696
18698
  isOpen: isImportModalOpen,
18697
18699
  onClose: () => setIsImportModalOpen(false),
18698
18700
  onConfirm: handleConfirmImport,
18699
18701
  session,
18700
- parentDbs: ((_m = sceneDataRef.current) == null ? void 0 : _m.parent_dbs) || [],
18702
+ parentDbs: ((_l = sceneDataRef.current) == null ? void 0 : _l.parent_dbs) || [],
18701
18703
  onFetchAvailableFiles: import_parent_file_modal_get,
18702
18704
  currentViewName: viewParams == null ? void 0 : viewParams.name,
18703
18705
  currentAncestries: ancestryDataRef.current || []
18704
18706
  }
18705
18707
  ),
18706
- invalidTargetError && /* @__PURE__ */ React28.createElement(
18708
+ invalidTargetError && /* @__PURE__ */ React30.createElement(
18707
18709
  "div",
18708
18710
  {
18709
18711
  className: "ui-overlay",
@@ -18728,13 +18730,13 @@ function XViewScene({
18728
18730
  animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
18729
18731
  }
18730
18732
  },
18731
- /* @__PURE__ */ React28.createElement("style", null, `
18733
+ /* @__PURE__ */ React30.createElement("style", null, `
18732
18734
  @keyframes fadeInDown {
18733
18735
  from { opacity: 0; transform: translate(-50%, -20px); }
18734
18736
  to { opacity: 1; transform: translate(-50%, 0); }
18735
18737
  }
18736
18738
  `),
18737
- /* @__PURE__ */ React28.createElement(
18739
+ /* @__PURE__ */ React30.createElement(
18738
18740
  "svg",
18739
18741
  {
18740
18742
  width: "20",
@@ -18746,12 +18748,12 @@ function XViewScene({
18746
18748
  strokeLinecap: "round",
18747
18749
  strokeLinejoin: "round"
18748
18750
  },
18749
- /* @__PURE__ */ React28.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18750
- /* @__PURE__ */ React28.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18751
- /* @__PURE__ */ React28.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
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" })
18752
18754
  ),
18753
- /* @__PURE__ */ React28.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18754
- /* @__PURE__ */ React28.createElement(
18755
+ /* @__PURE__ */ React30.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18756
+ /* @__PURE__ */ React30.createElement(
18755
18757
  "button",
18756
18758
  {
18757
18759
  onClick: () => setInvalidTargetError(null),