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

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.
Files changed (3) hide show
  1. package/dist/index.js +506 -561
  2. package/dist/index.mjs +475 -519
  3. package/package.json +12 -3
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  // src/XViewScene.jsx
2
- import React28, {
2
+ import React30, {
3
3
  useCallback as useCallback4,
4
- useEffect as useEffect22,
4
+ useEffect as useEffect24,
5
5
  useRef as useRef19,
6
- useState as useState27,
7
- useMemo as useMemo12
6
+ useState as useState28,
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
@@ -2480,15 +2432,15 @@ function createNewCustomProperty(existingProps = []) {
2480
2432
  switch (nextType) {
2481
2433
  case "links":
2482
2434
  nextKey = "Links";
2483
- nextValue = [{ id: v4_default(), name: "", value: "" }];
2435
+ nextValue = [{ id: uuidv4(), name: "", value: "" }];
2484
2436
  break;
2485
2437
  case "images":
2486
2438
  nextKey = "Images";
2487
- nextValue = [{ id: v4_default(), name: "1", value: "" }];
2439
+ nextValue = [{ id: uuidv4(), name: "1", value: "" }];
2488
2440
  break;
2489
2441
  case "documents":
2490
2442
  nextKey = "Documents";
2491
- nextValue = [{ id: v4_default(), name: "1", value: "" }];
2443
+ nextValue = [{ id: uuidv4(), name: "1", value: "" }];
2492
2444
  break;
2493
2445
  case "date":
2494
2446
  nextKey = "Date";
@@ -2498,14 +2450,14 @@ function createNewCustomProperty(existingProps = []) {
2498
2450
  nextValue = 0;
2499
2451
  break;
2500
2452
  case "list":
2501
- nextValue = [{ id: v4_default(), name: "", value: "" }];
2453
+ nextValue = [{ id: uuidv4(), name: "", value: "" }];
2502
2454
  break;
2503
2455
  default:
2504
2456
  nextValue = "";
2505
2457
  break;
2506
2458
  }
2507
2459
  return {
2508
- id: v4_default(),
2460
+ id: uuidv4(),
2509
2461
  key: nextKey,
2510
2462
  type: nextType,
2511
2463
  value: nextValue,
@@ -2750,7 +2702,7 @@ function extractCustomPropsFromNode(node) {
2750
2702
  if (val && typeof val === "object") {
2751
2703
  if ("date_interval" in val) {
2752
2704
  return {
2753
- id: v4_default(),
2705
+ id: uuidv4(),
2754
2706
  key,
2755
2707
  type: "date",
2756
2708
  value: {
@@ -2762,7 +2714,7 @@ function extractCustomPropsFromNode(node) {
2762
2714
  }
2763
2715
  if ("year" in val) {
2764
2716
  return {
2765
- id: v4_default(),
2717
+ id: uuidv4(),
2766
2718
  key,
2767
2719
  type: "date",
2768
2720
  value: { type: "Ano", value: val.year || "" }
@@ -2770,7 +2722,7 @@ function extractCustomPropsFromNode(node) {
2770
2722
  }
2771
2723
  if ("date" in val) {
2772
2724
  return {
2773
- id: v4_default(),
2725
+ id: uuidv4(),
2774
2726
  key,
2775
2727
  type: "date",
2776
2728
  value: { type: "Data", value: val.date || "" }
@@ -2778,7 +2730,7 @@ function extractCustomPropsFromNode(node) {
2778
2730
  }
2779
2731
  }
2780
2732
  return {
2781
- id: v4_default(),
2733
+ id: uuidv4(),
2782
2734
  key,
2783
2735
  type: "date",
2784
2736
  value: { type: "Data", value: "" }
@@ -2786,14 +2738,14 @@ function extractCustomPropsFromNode(node) {
2786
2738
  }
2787
2739
  if (t === "list" || t === "links" || t === "images" || t === "documents") {
2788
2740
  const safeList = (val || []).map((item) => ({
2789
- id: item.id || v4_default(),
2741
+ id: item.id || uuidv4(),
2790
2742
  name: item.name ?? "",
2791
2743
  value: item.value ?? ""
2792
2744
  }));
2793
- return { id: v4_default(), key, type: t, value: safeList };
2745
+ return { id: uuidv4(), key, type: t, value: safeList };
2794
2746
  }
2795
2747
  return {
2796
- id: v4_default(),
2748
+ id: uuidv4(),
2797
2749
  key,
2798
2750
  type: t,
2799
2751
  value: t === "number" ? Number(val) || 0 : String(val ?? "")
@@ -3066,16 +3018,16 @@ var processDescriptionForSave = (text, existingSections = []) => {
3066
3018
  if (existingMatch) {
3067
3019
  finalUuid = existingMatch.id;
3068
3020
  } else {
3069
- finalUuid = v4_default();
3021
+ finalUuid = uuidv4();
3070
3022
  }
3071
3023
  } else {
3072
3024
  finalUuid = numericMap.get(numStr);
3073
3025
  if (!finalUuid) {
3074
- finalUuid = v4_default();
3026
+ finalUuid = uuidv4();
3075
3027
  }
3076
3028
  }
3077
3029
  if (usedIds.has(finalUuid)) {
3078
- finalUuid = v4_default();
3030
+ finalUuid = uuidv4();
3079
3031
  }
3080
3032
  usedIds.add(finalUuid);
3081
3033
  processedSections.push({
@@ -3186,18 +3138,18 @@ function useResizablePanel({ initialWidth, minWidth, maxWidth }) {
3186
3138
  function createTimelineEntry(actorId, description, type = "comment", extras = {}) {
3187
3139
  const { links = [], images = [], metadata = {} } = extras;
3188
3140
  return {
3189
- id: v4_default(),
3141
+ id: uuidv4(),
3190
3142
  type,
3191
3143
  timestamp: Date.now(),
3192
3144
  actorId,
3193
3145
  description,
3194
3146
  links: links.map((l) => ({
3195
- id: l.id || v4_default(),
3147
+ id: l.id || uuidv4(),
3196
3148
  name: l.name || "",
3197
3149
  value: l.value || ""
3198
3150
  })),
3199
3151
  images: images.map((img) => ({
3200
- id: img.id || v4_default(),
3152
+ id: img.id || uuidv4(),
3201
3153
  name: img.name || "",
3202
3154
  value: img.value || ""
3203
3155
  }))
@@ -4424,6 +4376,7 @@ function XViewSidebar({
4424
4376
 
4425
4377
  // src/components/AncestryRelationshipPanel.jsx
4426
4378
  import React8, { useState as useState9, useEffect as useEffect8, useRef as useRef7 } from "react";
4379
+ import { v4 as uuidv43 } from "uuid";
4427
4380
 
4428
4381
  // src/components/CustomPropertyDisplay.jsx
4429
4382
  import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
@@ -5183,6 +5136,7 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
5183
5136
  }
5184
5137
 
5185
5138
  // src/components/DescriptionEditModal.jsx
5139
+ import { v4 as uuidv42 } from "uuid";
5186
5140
  var getNextSectionNumber = (currentText) => {
5187
5141
  const regex = /\*\/\s*(\d+)(?::[a-zA-Z0-9-]+)?\s*\//g;
5188
5142
  let max = 0;
@@ -5314,7 +5268,7 @@ function DescriptionEditModal({
5314
5268
  const el = textareaRef.current;
5315
5269
  if (!el) return;
5316
5270
  const nextNum = getNextSectionNumber(text);
5317
- const uniqueSuffix = v4_default().slice(0, 4);
5271
+ const uniqueSuffix = uuidv42().slice(0, 4);
5318
5272
  insertAtCursor(`*/${nextNum}:${uniqueSuffix}/ `);
5319
5273
  };
5320
5274
  const handleImportSelect = (tags) => {
@@ -5325,7 +5279,7 @@ function DescriptionEditModal({
5325
5279
  let currentNum = getNextSectionNumber(currentText);
5326
5280
  let blockToInsert = "";
5327
5281
  tagsArray.forEach((tag) => {
5328
- const uniqueSuffix = v4_default().slice(0, 4);
5282
+ const uniqueSuffix = uuidv42().slice(0, 4);
5329
5283
  blockToInsert += `
5330
5284
  */${currentNum}:${uniqueSuffix}/ ${tag}
5331
5285
  `;
@@ -6685,6 +6639,7 @@ import {
6685
6639
  FiLink as FiLink4,
6686
6640
  FiTrash2 as FiTrash22
6687
6641
  } from "react-icons/fi";
6642
+ import { v4 as uuidv44 } from "uuid";
6688
6643
 
6689
6644
  // src/components/AncestryPickerModal.jsx
6690
6645
  import React9, { useState as useState10, useMemo as useMemo7, useEffect as useEffect9 } from "react";
@@ -7721,7 +7676,7 @@ function CreateAncestryPanel({
7721
7676
  const nodeData = availableNodes.find((n) => String(n.id) === String(nodeId));
7722
7677
  const dirSuffix = direction === "left" ? "(Esq)" : "(Dir)";
7723
7678
  branch = {
7724
- id: v4_default(),
7679
+ id: uuidv44(),
7725
7680
  name: `Ramifica\xE7\xE3o ${dirSuffix} de ${(nodeData == null ? void 0 : nodeData.name) || "Node"}`,
7726
7681
  description: "",
7727
7682
  description_sections: [],
@@ -8500,6 +8455,7 @@ function ImageViewer({ data, onClose }) {
8500
8455
 
8501
8456
  // src/components/InSceneCreationForm.jsx
8502
8457
  import React13, { useState as useState14, useEffect as useEffect13, useRef as useRef10 } from "react";
8458
+ import { v4 as uuidv45 } from "uuid";
8503
8459
 
8504
8460
  // src/components/ColorPicker.jsx
8505
8461
  import React12, { useState as useState13, useEffect as useEffect12, useRef as useRef9 } from "react";
@@ -9084,6 +9040,7 @@ function InSceneCreationForm({
9084
9040
 
9085
9041
  // src/components/InSceneVersionForm.jsx
9086
9042
  import React14, { useState as useState15, useEffect as useEffect14, useRef as useRef11 } from "react";
9043
+ import { v4 as uuidv46 } from "uuid";
9087
9044
  import { FiPlus as FiPlus4, FiMaximize2 as FiMaximize22, FiCheck as FiCheck8, FiEdit2 as FiEdit25 } from "react-icons/fi";
9088
9045
  function InSceneVersionForm({
9089
9046
  onSave,
@@ -9106,7 +9063,7 @@ function InSceneVersionForm({
9106
9063
  const [description, setDescription] = useState15("");
9107
9064
  const [customProps, setCustomProps] = useState15([
9108
9065
  {
9109
- id: v4_default(),
9066
+ id: uuidv46(),
9110
9067
  key: "Date",
9111
9068
  type: "date",
9112
9069
  value: { type: "Data", value: "" },
@@ -9399,6 +9356,7 @@ function InSceneVersionForm({
9399
9356
 
9400
9357
  // src/components/InSceneQuestForm.jsx
9401
9358
  import React16, { useState as useState17, useRef as useRef12 } from "react";
9359
+ import { v4 as uuidv47 } from "uuid";
9402
9360
  import {
9403
9361
  FiPlus as FiPlus6,
9404
9362
  FiCheck as FiCheck9,
@@ -10323,6 +10281,7 @@ function InSceneQuestForm({
10323
10281
 
10324
10282
  // src/components/NodeDetailsPanel.jsx
10325
10283
  import React17, { useState as useState18, useEffect as useEffect15, useRef as useRef13 } from "react";
10284
+ import { v4 as uuidv48 } from "uuid";
10326
10285
  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
10286
  function NodeDetailsPanel({
10328
10287
  node,
@@ -10837,6 +10796,7 @@ function NodeDetailsPanel({
10837
10796
 
10838
10797
  // src/components/QuestDetailsPanel.jsx
10839
10798
  import React19, { useState as useState19, useEffect as useEffect16, useRef as useRef14 } from "react";
10799
+ import { v4 as uuidv49 } from "uuid";
10840
10800
  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
10801
 
10842
10802
  // src/components/QuestTimeline.jsx
@@ -11287,7 +11247,7 @@ ${noteText}` : noteText : entry.notes,
11287
11247
  }, 100);
11288
11248
  };
11289
11249
  const addLinkToNote = () => {
11290
- setNoteLinks([...noteLinks, { id: v4_default(), name: "", value: "" }]);
11250
+ setNoteLinks([...noteLinks, { id: uuidv49(), name: "", value: "" }]);
11291
11251
  };
11292
11252
  const removeLinkFromNote = (id) => {
11293
11253
  setNoteLinks(noteLinks.filter((l) => l.id !== id));
@@ -11296,7 +11256,7 @@ ${noteText}` : noteText : entry.notes,
11296
11256
  setNoteLinks(noteLinks.map((l) => l.id === id ? { ...l, [field]: val } : l));
11297
11257
  };
11298
11258
  const addImageToNote = () => {
11299
- setNoteImages([...noteImages, { id: v4_default(), name: "Image", value: "" }]);
11259
+ setNoteImages([...noteImages, { id: uuidv49(), name: "Image", value: "" }]);
11300
11260
  };
11301
11261
  const removeImageFromNote = (id) => {
11302
11262
  setNoteImages(noteImages.filter((img) => img.id !== id));
@@ -12173,6 +12133,7 @@ function MultiNodeContextMenu({
12173
12133
 
12174
12134
  // src/components/RelationshipDetailsPanel.jsx
12175
12135
  import React21, { useState as useState21, useEffect as useEffect18, useRef as useRef16, useMemo as useMemo9 } from "react";
12136
+ import { v4 as uuidv410 } from "uuid";
12176
12137
  import { FiPlus as FiPlus9, FiEdit2 as FiEdit29, FiLoader as FiLoader4, FiBookOpen as FiBookOpen5 } from "react-icons/fi";
12177
12138
  function RelationshipDetailsPanel({
12178
12139
  link,
@@ -12982,10 +12943,10 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
12982
12943
  }
12983
12944
 
12984
12945
  // src/components/AncestryBoard.jsx
12985
- import React26, { useState as useState25, useMemo as useMemo11, useEffect as useEffect21, useRef as useRef18 } from "react";
12946
+ import React28, { useState as useState26, useMemo as useMemo12, useEffect as useEffect23, useRef as useRef18 } from "react";
12986
12947
  import {
12987
- FiSearch as FiSearch8,
12988
- FiLayers as FiLayers6,
12948
+ FiSearch as FiSearch9,
12949
+ FiLayers as FiLayers7,
12989
12950
  FiCornerUpRight as FiCornerUpRight4,
12990
12951
  FiPlay,
12991
12952
  FiPlus as FiPlus10,
@@ -12996,151 +12957,322 @@ import {
12996
12957
  FiLoader as FiLoader5,
12997
12958
  FiX as FiX8,
12998
12959
  FiAlertTriangle,
12960
+ FiCheckSquare as FiCheckSquare4,
12961
+ FiBox as FiBox2,
12962
+ FiGitBranch as FiGitBranch4
12963
+ } from "react-icons/fi";
12964
+ import { v4 as uuidv411 } from "uuid";
12965
+
12966
+ // src/components/MentionEditor.jsx
12967
+ import React27, { useMemo as useMemo11, useEffect as useEffect22 } from "react";
12968
+ import { useEditor, EditorContent, ReactRenderer } from "@tiptap/react";
12969
+ import StarterKit from "@tiptap/starter-kit";
12970
+ import Mention from "@tiptap/extension-mention";
12971
+ import tippy from "tippy.js";
12972
+
12973
+ // src/components/MentionList.jsx
12974
+ import React26, {
12975
+ forwardRef,
12976
+ useEffect as useEffect21,
12977
+ useImperativeHandle,
12978
+ useState as useState25
12979
+ } from "react";
12980
+ import {
12981
+ FiLayers as FiLayers6,
12999
12982
  FiCheckSquare as FiCheckSquare3,
13000
12983
  FiBox,
13001
- FiGitBranch as FiGitBranch3
12984
+ FiGitBranch as FiGitBranch3,
12985
+ FiSearch as FiSearch8
13002
12986
  } from "react-icons/fi";
12987
+ var MentionList = forwardRef((props, ref) => {
12988
+ const [selectedIndex, setSelectedIndex] = useState25(0);
12989
+ const selectItem = (index) => {
12990
+ const item = props.items[index];
12991
+ if (item) {
12992
+ props.command({ id: item.id, label: item.name, type: item.type });
12993
+ }
12994
+ };
12995
+ const upHandler = () => {
12996
+ setSelectedIndex(
12997
+ (selectedIndex + props.items.length - 1) % props.items.length
12998
+ );
12999
+ };
13000
+ const downHandler = () => {
13001
+ setSelectedIndex((selectedIndex + 1) % props.items.length);
13002
+ };
13003
+ const enterHandler = () => {
13004
+ selectItem(selectedIndex);
13005
+ };
13006
+ useEffect21(() => setSelectedIndex(0), [props.items]);
13007
+ useImperativeHandle(ref, () => ({
13008
+ onKeyDown: ({ event }) => {
13009
+ if (event.key === "ArrowUp") {
13010
+ upHandler();
13011
+ return true;
13012
+ }
13013
+ if (event.key === "ArrowDown") {
13014
+ downHandler();
13015
+ return true;
13016
+ }
13017
+ if (event.key === "Enter") {
13018
+ enterHandler();
13019
+ return true;
13020
+ }
13021
+ return false;
13022
+ }
13023
+ }));
13024
+ return /* @__PURE__ */ React26.createElement("div", { className: "z-[3000] bg-slate-900 border border-white/10 rounded-lg shadow-2xl overflow-hidden min-w-[280px] max-w-[400px] animate-in fade-in zoom-in-95 duration-200" }, /* @__PURE__ */ React26.createElement("div", { className: "p-2 border-b border-white/5 bg-slate-950/50 flex items-center gap-2" }, /* @__PURE__ */ React26.createElement(FiSearch8, { className: "text-indigo-400", size: 14 }), /* @__PURE__ */ React26.createElement("span", { className: "text-[10px] uppercase tracking-wider font-bold text-slate-500" }, "Mencionar Recurso")), /* @__PURE__ */ React26.createElement("div", { className: "p-1 max-h-[300px] overflow-y-auto custom-scrollbar" }, props.items.length ? props.items.map((item, index) => {
13025
+ const isQuest = item.type === "quest";
13026
+ const isVersion = item.type === "version";
13027
+ const isNode = item.type === "node";
13028
+ let Icon = FiLayers6;
13029
+ let colorClass = "text-indigo-400";
13030
+ let badgeText = "Ancestralidade";
13031
+ if (isQuest) {
13032
+ Icon = FiCheckSquare3;
13033
+ colorClass = "text-amber-400";
13034
+ badgeText = "Quest";
13035
+ } else if (isVersion) {
13036
+ Icon = FiGitBranch3;
13037
+ colorClass = "text-purple-400";
13038
+ badgeText = "Vers\xE3o";
13039
+ } else if (isNode) {
13040
+ Icon = FiBox;
13041
+ colorClass = "text-emerald-400";
13042
+ badgeText = "Node";
13043
+ }
13044
+ return /* @__PURE__ */ React26.createElement(
13045
+ "button",
13046
+ {
13047
+ className: `
13048
+ w-full flex items-center gap-3 px-3 py-2 text-left rounded-md transition-all
13049
+ ${index === selectedIndex ? "bg-indigo-500/20 border border-indigo-500/30 text-white" : "text-slate-400 hover:bg-white/5 border border-transparent"}
13050
+ `,
13051
+ key: item.id,
13052
+ onClick: () => selectItem(index)
13053
+ },
13054
+ /* @__PURE__ */ React26.createElement("div", { className: `shrink-0 w-8 h-8 rounded border border-white/5 flex items-center justify-center bg-slate-800/50 ${colorClass}` }, /* @__PURE__ */ React26.createElement(Icon, { size: 14 })),
13055
+ /* @__PURE__ */ React26.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ React26.createElement("span", { className: "text-sm font-medium truncate" }, item.name), /* @__PURE__ */ React26.createElement("span", { className: `text-[9px] px-1 py-0.5 rounded border border-current opacity-60 ${colorClass}` }, badgeText)))
13056
+ );
13057
+ }) : /* @__PURE__ */ React26.createElement("div", { className: "p-4 text-center text-slate-500 text-sm italic" }, "Nenhum resultado encontrado...")));
13058
+ });
13059
+ MentionList.displayName = "MentionList";
13060
+ var MentionList_default = MentionList;
13061
+
13062
+ // src/components/MentionEditor.jsx
13063
+ var CustomMention = Mention.extend({
13064
+ addAttributes() {
13065
+ var _a;
13066
+ return {
13067
+ ...(_a = this.parent) == null ? void 0 : _a.call(this),
13068
+ type: {
13069
+ default: null,
13070
+ parseHTML: (element) => element.getAttribute("data-mention-type"),
13071
+ renderHTML: (attributes) => {
13072
+ if (!attributes.type) {
13073
+ return {};
13074
+ }
13075
+ return {
13076
+ "data-mention-type": attributes.type
13077
+ };
13078
+ }
13079
+ }
13080
+ };
13081
+ }
13082
+ });
13083
+ var MentionEditor = ({
13084
+ initialValue = "",
13085
+ onChange,
13086
+ onPlay,
13087
+ // Mantido para futura expansão se quisermos badges clicáveis reais no editor
13088
+ availableItems = [],
13089
+ canEdit = true,
13090
+ placeholder = "Escreva algo... use @ para mencionar"
13091
+ }) => {
13092
+ const parseInitialContent = (text) => {
13093
+ if (!text) return "<p></p>";
13094
+ const parts = text.split(/(\[\[MENTION:[^\]]+\]\])/g);
13095
+ return parts.map((part) => {
13096
+ const match = part.match(/\[\[MENTION:([^:]+):([^:]+):([^\]]+)\]\]/);
13097
+ if (match) {
13098
+ const [, type, id, label] = match;
13099
+ return `<span data-type="mention" data-id="${id}" data-mention-type="${type}" data-label="${label}">@${label}</span>`;
13100
+ }
13101
+ return part;
13102
+ }).join("");
13103
+ };
13104
+ const content = useMemo11(() => parseInitialContent(initialValue), [initialValue]);
13105
+ const editor = useEditor({
13106
+ extensions: [
13107
+ StarterKit.configure({
13108
+ heading: false,
13109
+ bulletList: false,
13110
+ orderedList: false,
13111
+ codeBlock: false,
13112
+ blockquote: false
13113
+ }),
13114
+ CustomMention.configure({
13115
+ HTMLAttributes: {
13116
+ class: "mention"
13117
+ },
13118
+ suggestion: {
13119
+ items: ({ query }) => {
13120
+ return availableItems.filter(
13121
+ (item) => item.name.toLowerCase().includes(query.toLowerCase())
13122
+ ).slice(0, 10);
13123
+ },
13124
+ render: () => {
13125
+ let component;
13126
+ let popup;
13127
+ return {
13128
+ onStart: (props) => {
13129
+ component = new ReactRenderer(MentionList_default, {
13130
+ props,
13131
+ editor: props.editor
13132
+ });
13133
+ if (!props.clientRect) {
13134
+ return;
13135
+ }
13136
+ popup = tippy("body", {
13137
+ getReferenceClientRect: props.clientRect,
13138
+ appendTo: () => document.body,
13139
+ content: component.element,
13140
+ showOnCreate: true,
13141
+ interactive: true,
13142
+ trigger: "manual",
13143
+ placement: "bottom-start"
13144
+ });
13145
+ },
13146
+ onUpdate(props) {
13147
+ component.updateProps(props);
13148
+ if (!props.clientRect) {
13149
+ return;
13150
+ }
13151
+ popup[0].setProps({
13152
+ getReferenceClientRect: props.clientRect
13153
+ });
13154
+ },
13155
+ onKeyDown(props) {
13156
+ var _a;
13157
+ if (props.event.key === "Escape") {
13158
+ popup[0].hide();
13159
+ return true;
13160
+ }
13161
+ return (_a = component == null ? void 0 : component.ref) == null ? void 0 : _a.onKeyDown(props);
13162
+ },
13163
+ onExit() {
13164
+ if (popup && popup[0]) popup[0].destroy();
13165
+ if (component) component.destroy();
13166
+ }
13167
+ };
13168
+ }
13169
+ }
13170
+ })
13171
+ ],
13172
+ content,
13173
+ editable: canEdit,
13174
+ onUpdate: ({ editor: editor2 }) => {
13175
+ const serialize = (json) => {
13176
+ if (!json.content) return "";
13177
+ return json.content.map((block) => {
13178
+ if (block.type === "paragraph") {
13179
+ const inner = block.content ? block.content.map((node) => {
13180
+ if (node.type === "text") return node.text;
13181
+ if (node.type === "mention") {
13182
+ return `[[MENTION:${node.attrs.type}:${node.attrs.id}:${node.attrs.label}]]`;
13183
+ }
13184
+ return "";
13185
+ }).join("") : "";
13186
+ return inner;
13187
+ }
13188
+ return "";
13189
+ }).join("\n").trim();
13190
+ };
13191
+ const serialized = serialize(editor2.getJSON());
13192
+ onChange(serialized);
13193
+ }
13194
+ });
13195
+ if (!editor) {
13196
+ return null;
13197
+ }
13198
+ return /* @__PURE__ */ React27.createElement("div", { className: "relative group/editor min-h-[1.5rem] w-full" }, /* @__PURE__ */ React27.createElement(
13199
+ EditorContent,
13200
+ {
13201
+ editor,
13202
+ className: "text-sm text-slate-200 placeholder-slate-600 focus:outline-none"
13203
+ }
13204
+ ), /* @__PURE__ */ React27.createElement("style", null, `
13205
+ .tiptap p {
13206
+ margin: 0;
13207
+ min-height: 1.2em;
13208
+ }
13209
+ .tiptap .mention {
13210
+ display: inline-flex;
13211
+ align-items: center;
13212
+ background-color: rgba(99, 102, 241, 0.15);
13213
+ border: 1px solid rgba(99, 102, 241, 0.3);
13214
+ border-radius: 4px;
13215
+ padding: 0 4px;
13216
+ color: #a5b4fc;
13217
+ font-weight: 500;
13218
+ cursor: pointer;
13219
+ margin: 0 2px;
13220
+ transition: all 0.2s;
13221
+ }
13222
+ .tiptap .mention:hover {
13223
+ background-color: rgba(99, 102, 241, 0.25);
13224
+ border-color: rgba(99, 102, 241, 0.5);
13225
+ color: white;
13226
+ }
13227
+ .tiptap:focus {
13228
+ outline: none;
13229
+ }
13230
+ `));
13231
+ };
13232
+ var MentionEditor_default = MentionEditor;
13233
+
13234
+ // src/components/AncestryBoard.jsx
13003
13235
  var GroupItem = ({
13004
13236
  group,
13005
13237
  index,
13006
- siblings,
13007
13238
  onUpdate,
13008
13239
  onDelete,
13009
13240
  onAddSubgroup,
13010
13241
  onIndent,
13011
13242
  onOutdent,
13012
- onRemoveAncestry,
13013
- onRequestPickAncestry,
13014
- pickingGroupId,
13015
13243
  onPlayAncestry,
13016
- availableIds,
13244
+ availableMentionItems,
13017
13245
  canEdit
13018
13246
  }) => {
13019
13247
  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
- }
13028
- };
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(
13248
+ 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(
13033
13249
  "div",
13034
13250
  {
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
- `
13251
+ 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"
13039
13252
  },
13040
- /* @__PURE__ */ React26.createElement(
13041
- "textarea",
13253
+ /* @__PURE__ */ React28.createElement(
13254
+ MentionEditor_default,
13042
13255
  {
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"
13256
+ initialValue: group.text,
13257
+ onChange: (newText) => {
13258
+ if (canEdit) onUpdate(group.id, { ...group, text: newText });
13049
13259
  },
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
- }
13260
+ onPlay: onPlayAncestry,
13261
+ availableItems: availableMentionItems,
13262
+ canEdit,
13263
+ placeholder: "Escreva sobre este grupo... use @ para mencionar"
13056
13264
  }
13057
13265
  ),
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(
13266
+ canEdit && /* @__PURE__ */ React28.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-0 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(
13136
13267
  "button",
13137
13268
  {
13138
13269
  onClick: () => onAddSubgroup(group.id),
13139
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13270
+ className: "flex items-center gap-1.5 px-3 py-1.5 text-xs text-slate-500 hover:text-white hover:bg-white/10 rounded-md transition-colors",
13140
13271
  title: "Criar Subgrupo"
13141
13272
  },
13142
- /* @__PURE__ */ React26.createElement(FiPlus10, { size: 14 })
13143
- )), /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React26.createElement(
13273
+ /* @__PURE__ */ React28.createElement(FiPlus10, { size: 14 }),
13274
+ /* @__PURE__ */ React28.createElement("span", null, "Adicionar Subgrupo")
13275
+ )), /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(
13144
13276
  "button",
13145
13277
  {
13146
13278
  onClick: () => onIndent(group.id),
@@ -13148,25 +13280,25 @@ var GroupItem = ({
13148
13280
  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
13281
  title: "Aninhar no grupo acima"
13150
13282
  },
13151
- /* @__PURE__ */ React26.createElement(FiArrowRight2, { size: 14 })
13152
- ), /* @__PURE__ */ React26.createElement(
13283
+ /* @__PURE__ */ React28.createElement(FiArrowRight2, { size: 14 })
13284
+ ), /* @__PURE__ */ React28.createElement(
13153
13285
  "button",
13154
13286
  {
13155
13287
  onClick: () => onOutdent(group.id),
13156
13288
  className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13157
13289
  title: "Desaninhar"
13158
13290
  },
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(
13291
+ /* @__PURE__ */ React28.createElement(FiArrowLeft3, { size: 14 })
13292
+ ), /* @__PURE__ */ React28.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React28.createElement(
13161
13293
  "button",
13162
13294
  {
13163
13295
  onClick: () => onDelete(group.id),
13164
13296
  className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13165
13297
  title: "Remover Grupo"
13166
13298
  },
13167
- /* @__PURE__ */ React26.createElement(FiTrash23, { size: 14 })
13299
+ /* @__PURE__ */ React28.createElement(FiTrash23, { size: 14 })
13168
13300
  )))
13169
- ), group.children && group.children.length > 0 && /* @__PURE__ */ React26.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ React26.createElement(
13301
+ ), group.children && group.children.length > 0 && /* @__PURE__ */ React28.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ React28.createElement(
13170
13302
  GroupItem,
13171
13303
  {
13172
13304
  key: childGroup.id,
@@ -13178,11 +13310,8 @@ var GroupItem = ({
13178
13310
  onAddSubgroup,
13179
13311
  onIndent,
13180
13312
  onOutdent,
13181
- onRemoveAncestry,
13182
- onRequestPickAncestry,
13183
- pickingGroupId,
13184
13313
  onPlayAncestry,
13185
- availableIds,
13314
+ availableMentionItems,
13186
13315
  canEdit
13187
13316
  }
13188
13317
  ))));
@@ -13197,21 +13326,19 @@ function AncestryBoard({
13197
13326
  onSave,
13198
13327
  userRole
13199
13328
  }) {
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(() => {
13329
+ const [groups, setGroups] = useState26([]);
13330
+ const [isLoaded, setIsLoaded] = useState26(false);
13331
+ const [saveStatus, setSaveStatus] = useState26("idle");
13332
+ const canEdit = useMemo12(() => {
13206
13333
  return userRole !== "viewer";
13207
13334
  }, [userRole]);
13208
- useEffect21(() => {
13335
+ useEffect23(() => {
13209
13336
  if (initialGroups && !isLoaded) {
13210
13337
  setGroups(initialGroups);
13211
13338
  setIsLoaded(true);
13212
13339
  }
13213
13340
  }, [initialGroups, isLoaded]);
13214
- const nodeNamesMap = useMemo11(() => {
13341
+ const nodeNamesMap = useMemo12(() => {
13215
13342
  const map = /* @__PURE__ */ new Map();
13216
13343
  if (availableNodes && Array.isArray(availableNodes)) {
13217
13344
  availableNodes.forEach((node) => {
@@ -13222,10 +13349,10 @@ function AncestryBoard({
13222
13349
  }
13223
13350
  return map;
13224
13351
  }, [availableNodes]);
13225
- const availableIds = useMemo11(() => {
13352
+ const availableIds = useMemo12(() => {
13226
13353
  return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
13227
13354
  }, [availableAncestries]);
13228
- const allMentionableItems = useMemo11(() => {
13355
+ const availableMentionItems = useMemo12(() => {
13229
13356
  const ancestries = availableAncestries.map((a) => ({
13230
13357
  id: String(a.ancestry_id),
13231
13358
  ancestry_id: a.ancestry_id,
@@ -13253,16 +13380,10 @@ function AncestryBoard({
13253
13380
  return groupList.map((g) => ({
13254
13381
  id: g.id,
13255
13382
  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
13383
  children: sanitizeGroups(g.children || [])
13263
13384
  }));
13264
13385
  };
13265
- useEffect21(() => {
13386
+ useEffect23(() => {
13266
13387
  if (!isLoaded || !onSave) return;
13267
13388
  const timeoutId = setTimeout(async () => {
13268
13389
  setSaveStatus("saving");
@@ -13280,50 +13401,30 @@ function AncestryBoard({
13280
13401
  }, 3e3);
13281
13402
  return () => clearTimeout(timeoutId);
13282
13403
  }, [groups, isLoaded, onSave]);
13283
- useEffect21(() => {
13404
+ useEffect23(() => {
13284
13405
  if (!isOpen) return;
13285
13406
  const handleKeyDown = (e) => {
13286
13407
  if (e.key === "Escape") {
13287
- if (pickingGroupId) {
13288
- setPickingGroupId(null);
13289
- } else {
13290
- onClose();
13291
- }
13408
+ onClose();
13292
13409
  e.preventDefault();
13293
13410
  e.stopPropagation();
13294
13411
  }
13295
13412
  };
13296
13413
  window.addEventListener("keydown", handleKeyDown);
13297
13414
  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]);
13415
+ }, [isOpen, onClose]);
13313
13416
  const handleAddRootGroup = () => {
13314
13417
  const newGroup = {
13315
- id: v4_default(),
13418
+ id: uuidv411(),
13316
13419
  text: "",
13317
- ancestries: [],
13318
13420
  children: []
13319
13421
  };
13320
13422
  setGroups((prev) => [newGroup, ...prev]);
13321
13423
  };
13322
13424
  const handleAddSubgroup = (parentId) => {
13323
13425
  const newGroup = {
13324
- id: v4_default(),
13426
+ id: uuidv411(),
13325
13427
  text: "",
13326
- ancestries: [],
13327
13428
  children: []
13328
13429
  };
13329
13430
  const addRecursive = (list) => {
@@ -13394,42 +13495,6 @@ function AncestryBoard({
13394
13495
  return newList;
13395
13496
  });
13396
13497
  };
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
13498
  const handlePlayFromGroup = (item) => {
13434
13499
  let fullItem = item;
13435
13500
  if (item.type === "ancestry" || !item.type) {
@@ -13445,52 +13510,34 @@ function AncestryBoard({
13445
13510
  onSelect(fullItem);
13446
13511
  }
13447
13512
  };
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
- });
13465
- };
13466
13513
  if (!isOpen) return null;
13467
- return /* @__PURE__ */ React26.createElement(
13514
+ return /* @__PURE__ */ React28.createElement(
13468
13515
  "div",
13469
13516
  {
13470
13517
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
13471
13518
  onClick: onClose
13472
13519
  },
13473
- /* @__PURE__ */ React26.createElement(
13520
+ /* @__PURE__ */ React28.createElement(
13474
13521
  "div",
13475
13522
  {
13476
- 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",
13523
+ className: "bg-slate-950 border border-white/10 rounded-xl w-[90vw] max-w-[1200px] h-[90vh] flex flex-col shadow-2xl overflow-hidden animate-in fade-in zoom-in-95 duration-200",
13477
13524
  onClick: (e) => e.stopPropagation()
13478
13525
  },
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(
13526
+ /* @__PURE__ */ React28.createElement("div", { className: "h-14 px-6 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(
13480
13527
  FiLoader5,
13481
13528
  {
13482
13529
  className: "animate-spin text-indigo-400",
13483
13530
  size: 12
13484
13531
  }
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(
13532
+ ), /* @__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
13533
  "button",
13487
13534
  {
13488
13535
  onClick: handleAddRootGroup,
13489
13536
  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 "
13490
13537
  },
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(
13538
+ /* @__PURE__ */ React28.createElement(FiPlus10, { size: 14, className: "text-indigo-400" }),
13539
+ /* @__PURE__ */ React28.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13540
+ ), /* @__PURE__ */ React28.createElement(
13494
13541
  "button",
13495
13542
  {
13496
13543
  onClick: onClose,
@@ -13498,127 +13545,36 @@ function AncestryBoard({
13498
13545
  },
13499
13546
  "\xD7"
13500
13547
  ))),
13501
- /* @__PURE__ */ React26.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React26.createElement(
13502
- "div",
13548
+ /* @__PURE__ */ React28.createElement("div", { className: "flex flex-1 overflow-hidden bg-slate-900/20" }, /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React28.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-8 max-w-[900px] mx-auto w-full space-y-6" }, groups.length === 0 ? /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-4 border-2 border-dashed border-white/5 rounded-2xl bg-slate-900/40 p-12" }, /* @__PURE__ */ React28.createElement(FiLayers7, { size: 40, className: "opacity-10 text-indigo-400" }), /* @__PURE__ */ React28.createElement("div", { className: "text-center space-y-1" }, /* @__PURE__ */ React28.createElement("p", { className: "text-sm font-medium text-slate-300" }, "Nenhum grupo criado"), /* @__PURE__ */ React28.createElement("p", { className: "text-xs text-slate-500 max-w-[200px]" }, canEdit ? "Comece organizando sua narrativa criando o primeiro grupo." : "Este board ainda n\xE3o possui conte\xFAdo.")), canEdit && /* @__PURE__ */ React28.createElement(
13549
+ "button",
13503
13550
  {
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
- `
13551
+ onClick: handleAddRootGroup,
13552
+ className: "mt-2 px-4 py-2 bg-indigo-500/10 hover:bg-indigo-500/20 text-indigo-400 rounded-lg border border-indigo-500/20 transition-all text-xs font-bold uppercase tracking-wider"
13509
13553
  },
13510
- /* @__PURE__ */ React26.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ React26.createElement("div", { className: "relative group" }, /* @__PURE__ */ React26.createElement(
13511
- FiSearch8,
13512
- {
13513
- className: `absolute left-3 top-1/2 -translate-y-1/2 transition-colors ${pickingGroupId ? "text-indigo-400" : "text-slate-500 group-focus-within:text-indigo-400"}`
13514
- }
13515
- ), /* @__PURE__ */ React26.createElement(
13516
- "input",
13517
- {
13518
- type: "text",
13519
- placeholder: pickingGroupId ? "Pesquise para adicionar..." : "Pesquisar (Ancestralidades e Nodes)",
13520
- className: `
13521
- w-full rounded-md pl-9 pr-4 py-2 text-sm transition-all focus:outline-none focus:ring-1 focus:ring-indigo-500 border
13522
- ${pickingGroupId ? "bg-indigo-950/30 border-indigo-500/30 text-white placeholder-indigo-300/50" : "bg-slate-950 border-white/10 text-slate-200 placeholder-slate-600"}
13523
- `,
13524
- value: searchTerm,
13525
- onChange: (e) => setSearchTerm(e.target.value),
13526
- autoFocus: !pickingGroupId
13527
- }
13528
- ))),
13529
- /* @__PURE__ */ React26.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((item) => {
13530
- const isPicking = !!pickingGroupId;
13531
- const isQuest = item.type === "quest";
13532
- const isVersion = item.type === "version";
13533
- const isNode = item.type === "node";
13534
- let Icon = FiLayers6;
13535
- let colorClass = "bg-slate-800 text-indigo-400 border-white/5";
13536
- let pickingColorClass = "bg-indigo-500 text-white border-indigo-400";
13537
- let hoverClass = "hover:bg-indigo-600/10 hover:border-indigo-500/30";
13538
- let badge = null;
13539
- if (isQuest) {
13540
- Icon = FiCheckSquare3;
13541
- colorClass = "bg-slate-800 text-amber-400 border-white/5";
13542
- pickingColorClass = "bg-amber-500 text-white border-amber-400";
13543
- hoverClass = "hover:bg-amber-500/10 hover:border-amber-500/30";
13544
- badge = "Quest";
13545
- } else if (isVersion) {
13546
- Icon = FiGitBranch3;
13547
- colorClass = "bg-slate-800 text-purple-400 border-white/5";
13548
- pickingColorClass = "bg-purple-500 text-white border-purple-400";
13549
- hoverClass = "hover:bg-purple-500/10 hover:border-purple-500/30";
13550
- badge = "Ver";
13551
- } else if (isNode) {
13552
- Icon = FiBox;
13553
- colorClass = "bg-slate-800 text-emerald-400 border-white/5";
13554
- pickingColorClass = "bg-emerald-500 text-white border-emerald-400";
13555
- hoverClass = "hover:bg-emerald-500/10 hover:border-emerald-500/30";
13556
- badge = "Node";
13557
- }
13558
- return /* @__PURE__ */ React26.createElement(
13559
- "div",
13560
- {
13561
- key: `${item.type}-${item.id}`,
13562
- onClick: () => {
13563
- if (isPicking) handleSelectAncestry(item);
13564
- },
13565
- className: `
13566
- group relative flex items-start gap-3 p-3 text-left rounded-lg border transition-all duration-200
13567
- ${isPicking ? `border-indigo-500/30 bg-indigo-500/5 hover:bg-indigo-500/20 hover:border-indigo-400 cursor-pointer` : `border-white/5 bg-slate-800/40 ${hoverClass} cursor-default`}
13568
- `
13569
- },
13570
- /* @__PURE__ */ React26.createElement(
13571
- "div",
13572
- {
13573
- className: `
13574
- mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
13575
- ${isPicking ? pickingColorClass : `${colorClass} group-hover:bg-opacity-80`}
13576
- `
13577
- },
13578
- isPicking ? /* @__PURE__ */ React26.createElement(FiPlus10, { size: 16 }) : /* @__PURE__ */ React26.createElement(Icon, { size: 14 })
13579
- ),
13580
- /* @__PURE__ */ React26.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ React26.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, item.name || "Sem Nome"), badge && /* @__PURE__ */ React26.createElement("span", { className: `text-[9px] px-1 py-0.5 rounded ${isQuest ? "bg-amber-500/10 text-amber-400" : isVersion ? "bg-purple-500/10 text-purple-400" : "bg-emerald-500/10 text-emerald-400"} border border-current opacity-50` }, badge), item.is_private && /* @__PURE__ */ React26.createElement("span", { className: "text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-300 border border-amber-500/20" }, "Priv")), item.type === "ancestry" && /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ React26.createElement(FiCornerUpRight4, { size: 10 }), /* @__PURE__ */ React26.createElement("span", { className: "truncate max-w-[120px]" }, nodeNamesMap.get(String(item.ancestral_node)) || "Node Desconhecido")), item.description && /* @__PURE__ */ React26.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, item.description)),
13581
- !isPicking && /* @__PURE__ */ React26.createElement(
13582
- "button",
13583
- {
13584
- onClick: (e) => {
13585
- e.stopPropagation();
13586
- handleSelectAncestry(item);
13587
- },
13588
- className: "absolute right-2 bottom-2 opacity-0 group-hover:opacity-100 transition-all duration-300 transform translate-y-2 group-hover:translate-y-0 z-10",
13589
- title: "Renderizar / Focar"
13590
- },
13591
- /* @__PURE__ */ React26.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ React26.createElement(FiPlay, { size: 14, className: "ml-0.5" }))
13592
- )
13593
- );
13594
- }))
13595
- ), /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ React26.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-3 border-2 border-dashed border-white/5 rounded-xl m-4 bg-slate-900/20" }, /* @__PURE__ */ React26.createElement(FiLayers6, { size: 24, className: "opacity-20" }), /* @__PURE__ */ React26.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ React26.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ React26.createElement(React26.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ React26.createElement(
13554
+ "Criar Primeiro Grupo"
13555
+ )) : groups.map((group, index) => /* @__PURE__ */ React28.createElement(
13596
13556
  GroupItem,
13597
13557
  {
13598
13558
  key: group.id,
13599
13559
  index,
13600
13560
  group,
13601
- siblings: groups,
13602
13561
  onUpdate: handleUpdateGroup,
13603
13562
  onDelete: handleDeleteGroup,
13604
13563
  onAddSubgroup: handleAddSubgroup,
13605
13564
  onIndent: handleIndent,
13606
13565
  onOutdent: handleOutdent,
13607
- onRemoveAncestry: handleRemoveAncestryFromGroup,
13608
- onRequestPickAncestry: handleRequestPick,
13609
- pickingGroupId,
13610
13566
  onPlayAncestry: handlePlayFromGroup,
13611
- availableIds,
13567
+ availableMentionItems,
13612
13568
  canEdit
13613
13569
  }
13614
13570
  ))))),
13615
- /* @__PURE__ */ React26.createElement("div", { className: "px-5 py-2 border-t border-white/10 bg-slate-950/50 text-xs text-slate-500 flex justify-between flex-shrink-0" }, /* @__PURE__ */ React26.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ React26.createElement("span", null, groups.length, " grupos raiz"))
13571
+ /* @__PURE__ */ React28.createElement("div", { className: "px-6 py-3 border-t border-white/10 bg-slate-950/50 text-[10px] uppercase tracking-widest font-bold text-slate-600 flex justify-between items-center flex-shrink-0" }, /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React28.createElement("span", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React28.createElement("div", { className: "w-1.5 h-1.5 rounded-full bg-indigo-500" }), " ", availableMentionItems.length, " RECURSOS DISPON\xCDVEIS"), /* @__PURE__ */ React28.createElement("span", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React28.createElement("div", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500" }), " ", groups.length, " GRUPOS PRINCIPAIS")), /* @__PURE__ */ React28.createElement("span", { className: "text-slate-700" }, "X.VIEW :: ANCESTRY BOARD ENGINE"))
13616
13572
  )
13617
13573
  );
13618
13574
  }
13619
13575
 
13620
13576
  // src/components/MilestoneManager.jsx
13621
- import React27, { useState as useState26 } from "react";
13577
+ import React29, { useState as useState27 } from "react";
13622
13578
  import { FiTarget as FiTarget4, FiPlus as FiPlus11, FiTrash2 as FiTrash24, FiX as FiX9, FiCheck as FiCheck12, FiPauseCircle, FiPlayCircle } from "react-icons/fi";
13623
13579
  function MilestoneManager({
13624
13580
  isOpen,
@@ -13627,7 +13583,7 @@ function MilestoneManager({
13627
13583
  onUpdateMilestones = () => {
13628
13584
  }
13629
13585
  }) {
13630
- const [newMilestoneName, setNewMilestoneName] = useState26("");
13586
+ const [newMilestoneName, setNewMilestoneName] = useState27("");
13631
13587
  const handleAddMilestone = () => {
13632
13588
  if (!newMilestoneName.trim()) return;
13633
13589
  const newMilestone = {
@@ -13652,27 +13608,27 @@ function MilestoneManager({
13652
13608
  };
13653
13609
  if (!isOpen) return null;
13654
13610
  const swallow = (e) => e.stopPropagation();
13655
- return /* @__PURE__ */ React27.createElement(
13611
+ return /* @__PURE__ */ React29.createElement(
13656
13612
  "div",
13657
13613
  {
13658
13614
  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
13615
  onClick: onClose
13660
13616
  },
13661
- /* @__PURE__ */ React27.createElement(
13617
+ /* @__PURE__ */ React29.createElement(
13662
13618
  "div",
13663
13619
  {
13664
13620
  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
13621
  onClick: swallow
13666
13622
  },
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(
13623
+ /* @__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
13624
  "button",
13669
13625
  {
13670
13626
  onClick: onClose,
13671
13627
  className: "p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
13672
13628
  },
13673
- /* @__PURE__ */ React27.createElement(FiX9, { size: 20 })
13629
+ /* @__PURE__ */ React29.createElement(FiX9, { size: 20 })
13674
13630
  )),
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(
13631
+ /* @__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
13632
  "input",
13677
13633
  {
13678
13634
  type: "text",
@@ -13682,47 +13638,47 @@ function MilestoneManager({
13682
13638
  placeholder: "Adicionar novo milestone...",
13683
13639
  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
13640
  }
13685
- ), /* @__PURE__ */ React27.createElement(
13641
+ ), /* @__PURE__ */ React29.createElement(
13686
13642
  "button",
13687
13643
  {
13688
13644
  onClick: handleAddMilestone,
13689
13645
  disabled: !newMilestoneName.trim(),
13690
13646
  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
13647
  },
13692
- /* @__PURE__ */ React27.createElement(FiPlus11, { size: 18 }),
13648
+ /* @__PURE__ */ React29.createElement(FiPlus11, { size: 18 }),
13693
13649
  "Adicionar"
13694
13650
  ))),
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(
13651
+ /* @__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
13652
  "div",
13697
13653
  {
13698
13654
  key: ms.id,
13699
13655
  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
13656
  },
13701
- /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ React27.createElement(
13657
+ /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ React29.createElement(
13702
13658
  "div",
13703
13659
  {
13704
13660
  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
13661
  }
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(
13662
+ ), /* @__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"))),
13663
+ /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React29.createElement(
13708
13664
  "button",
13709
13665
  {
13710
13666
  onClick: () => handleToggleMilestoneStatus(ms.id),
13711
13667
  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
13668
  title: ms.status === "active" ? "Inativar" : "Ativar"
13713
13669
  },
13714
- ms.status === "active" ? /* @__PURE__ */ React27.createElement(FiPauseCircle, { size: 18 }) : /* @__PURE__ */ React27.createElement(FiPlayCircle, { size: 18 })
13715
- ), /* @__PURE__ */ React27.createElement(
13670
+ ms.status === "active" ? /* @__PURE__ */ React29.createElement(FiPauseCircle, { size: 18 }) : /* @__PURE__ */ React29.createElement(FiPlayCircle, { size: 18 })
13671
+ ), /* @__PURE__ */ React29.createElement(
13716
13672
  "button",
13717
13673
  {
13718
13674
  onClick: () => handleRemoveMilestone(ms.id),
13719
13675
  className: "p-2 rounded-lg hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-all",
13720
13676
  title: "Remover"
13721
13677
  },
13722
- /* @__PURE__ */ React27.createElement(FiTrash24, { size: 18 })
13678
+ /* @__PURE__ */ React29.createElement(FiTrash24, { size: 18 })
13723
13679
  ))
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))))
13680
+ ))) : /* @__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."))),
13681
+ /* @__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
13682
  )
13727
13683
  );
13728
13684
  }
@@ -13814,7 +13770,7 @@ function XViewScene({
13814
13770
  const searchParams = useSearchParams();
13815
13771
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
13816
13772
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
13817
- const viewParams = useMemo12(() => {
13773
+ const viewParams = useMemo13(() => {
13818
13774
  if (encryptedConfig) {
13819
13775
  const data = decryptData(encryptedConfig);
13820
13776
  if (data) {
@@ -13823,7 +13779,7 @@ function XViewScene({
13823
13779
  }
13824
13780
  return null;
13825
13781
  }, [encryptedConfig, session]);
13826
- useEffect22(() => {
13782
+ useEffect24(() => {
13827
13783
  async function verifyPermission() {
13828
13784
  if (!viewParams || !session || !check_user_permission) return;
13829
13785
  const { id, type, owner_id } = viewParams;
@@ -13860,21 +13816,21 @@ function XViewScene({
13860
13816
  setIsLoading(false);
13861
13817
  }
13862
13818
  }, [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(() => {
13819
+ const sceneConfigId = useMemo13(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13820
+ const ownerId = useMemo13(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13821
+ const dbSaveUrl = useMemo13(() => {
13866
13822
  if (ownerId && sceneConfigId) {
13867
13823
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
13868
13824
  }
13869
13825
  return null;
13870
13826
  }, [ownerId, sceneConfigId]);
13871
- const sceneSaveUrl = useMemo12(() => {
13827
+ const sceneSaveUrl = useMemo13(() => {
13872
13828
  if (ownerId && sceneConfigId) {
13873
13829
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
13874
13830
  }
13875
13831
  return null;
13876
13832
  }, [ownerId, sceneConfigId]);
13877
- const ancestry_save_url = useMemo12(() => {
13833
+ const ancestry_save_url = useMemo13(() => {
13878
13834
  if (ownerId && sceneConfigId) {
13879
13835
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
13880
13836
  }
@@ -13883,42 +13839,42 @@ function XViewScene({
13883
13839
  const sceneDataRef = useRef19(null);
13884
13840
  const parentDataRef = useRef19(null);
13885
13841
  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({
13842
+ const [isLoading, setIsLoading] = useState28(true);
13843
+ const [permissionStatus, setPermissionStatus] = useState28("loading");
13844
+ const [userPermissionRole, setUserPermissionRole] = useState28(null);
13845
+ const [viewMembers, setViewMembers] = useState28([]);
13846
+ const [isInitialized, setIsInitialized] = useState28(false);
13847
+ const [sceneVersion, setSceneVersion] = useState28(0);
13848
+ const [contextMenu, setContextMenu] = useState28({
13893
13849
  visible: false,
13894
13850
  x: 0,
13895
13851
  y: 0,
13896
13852
  nodeData: null
13897
13853
  });
13898
- const [multiContextMenu, setMultiContextMenu] = useState27({
13854
+ const [multiContextMenu, setMultiContextMenu] = useState28({
13899
13855
  visible: false,
13900
13856
  x: 0,
13901
13857
  y: 0,
13902
13858
  nodeIds: null
13903
13859
  });
13904
- const [relationshipMenu, setRelationshipMenu] = useState27({
13860
+ const [relationshipMenu, setRelationshipMenu] = useState28({
13905
13861
  visible: false,
13906
13862
  x: 0,
13907
13863
  y: 0,
13908
13864
  linkObject: null
13909
13865
  });
13910
- const [creationMode, setCreationMode] = useState27({
13866
+ const [creationMode, setCreationMode] = useState28({
13911
13867
  isActive: false,
13912
13868
  sourceNodeData: null
13913
13869
  });
13914
- const [versionMode, setVersionMode] = useState27({
13870
+ const [versionMode, setVersionMode] = useState28({
13915
13871
  isActive: false,
13916
13872
  sourceNodeData: null
13917
13873
  });
13918
- const [questMode, setQuestMode] = useState27({ isActive: false });
13919
- const [hasFocusedInitial, setHasFocusedInitial] = useState27(false);
13920
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState27(false);
13921
- const [ancestryMode, setAncestryMode] = useState27({
13874
+ const [questMode, setQuestMode] = useState28({ isActive: false });
13875
+ const [hasFocusedInitial, setHasFocusedInitial] = useState28(false);
13876
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState28(false);
13877
+ const [ancestryMode, setAncestryMode] = useState28({
13922
13878
  isActive: false,
13923
13879
  tree: null,
13924
13880
  selectedParentId: null,
@@ -13929,38 +13885,38 @@ function XViewScene({
13929
13885
  ancestryDescriptionSections: [],
13930
13886
  isAddingNodes: false
13931
13887
  });
13932
- const [readingMode, setReadingMode] = useState27({
13888
+ const [readingMode, setReadingMode] = useState28({
13933
13889
  isActive: false,
13934
13890
  ancestry: null,
13935
13891
  branchStack: [],
13936
13892
  autoAbstraction: false
13937
13893
  });
13938
- const [formPosition, setFormPosition] = useState27({
13894
+ const [formPosition, setFormPosition] = useState28({
13939
13895
  left: 16,
13940
13896
  top: 16,
13941
13897
  opacity: 0
13942
13898
  });
13943
- const [detailsNode, setDetailsNode] = useState27(null);
13944
- const [detailsLink, setDetailsLink] = useState27(null);
13945
- const [ancestryLinkDetails, setAncestryLinkDetails] = useState27(null);
13946
- const [imageViewer, setImageViewer] = useState27({
13899
+ const [detailsNode, setDetailsNode] = useState28(null);
13900
+ const [detailsLink, setDetailsLink] = useState28(null);
13901
+ const [ancestryLinkDetails, setAncestryLinkDetails] = useState28(null);
13902
+ const [imageViewer, setImageViewer] = useState28({
13947
13903
  visible: false,
13948
13904
  images: [],
13949
13905
  startIndex: 0
13950
13906
  });
13951
- const [editingAncestryRel, setEditingAncestryRel] = useState27({
13907
+ const [editingAncestryRel, setEditingAncestryRel] = useState28({
13952
13908
  visible: false,
13953
13909
  data: null,
13954
13910
  path: null
13955
13911
  });
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);
13912
+ const [isImportModalOpen, setIsImportModalOpen] = useState28(false);
13913
+ const [importSuccessMessage, setImportSuccessMessage] = useState28("");
13914
+ const [invalidTargetError, setInvalidTargetError] = useState28(null);
13915
+ const [highlightedNodeId, setHighlightedNodeId] = useState28(null);
13916
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState28(false);
13917
+ const [ancestryBoardData, setAncestryBoardData] = useState28([]);
13918
+ const [isSidebarOpen, setIsSidebarOpen] = useState28(false);
13919
+ const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState28(false);
13964
13920
  const mountRef = useRef19(null);
13965
13921
  const tooltipRef = useRef19(null);
13966
13922
  const formRef = useRef19(null);
@@ -14028,10 +13984,10 @@ function XViewScene({
14028
13984
  minWidth: 320,
14029
13985
  maxWidth: maxReadPanelW
14030
13986
  });
14031
- useEffect22(() => {
13987
+ useEffect24(() => {
14032
13988
  stateRef.current.ancestry = ancestryMode;
14033
13989
  }, [ancestryMode]);
14034
- useEffect22(() => {
13990
+ useEffect24(() => {
14035
13991
  var _a2;
14036
13992
  if (!isInitialized) return;
14037
13993
  const map = /* @__PURE__ */ new Map();
@@ -14593,7 +14549,7 @@ function XViewScene({
14593
14549
  }
14594
14550
  });
14595
14551
  }, []);
14596
- useEffect22(() => {
14552
+ useEffect24(() => {
14597
14553
  async function fetchAllData(configPath, ownerId2) {
14598
14554
  var _a2, _b2;
14599
14555
  if (!get_scene_view_data) {
@@ -14958,7 +14914,7 @@ function XViewScene({
14958
14914
  camTween.start();
14959
14915
  }
14960
14916
  }, [addOrUpdateNodeMesh]);
14961
- useEffect22(() => {
14917
+ useEffect24(() => {
14962
14918
  if (!isInitialized || !sceneDataRef.current) return;
14963
14919
  const currentMount = mountRef.current;
14964
14920
  if (!currentMount) return;
@@ -15962,7 +15918,7 @@ function XViewScene({
15962
15918
  };
15963
15919
  });
15964
15920
  }, []);
15965
- const actionHandlerContext = useMemo12(
15921
+ const actionHandlerContext = useMemo13(
15966
15922
  () => {
15967
15923
  var _a2;
15968
15924
  return {
@@ -17071,7 +17027,7 @@ function XViewScene({
17071
17027
  }
17072
17028
  setHighlightedNodeId(nodeId);
17073
17029
  }, []);
17074
- const activeNodeBranches = useMemo12(() => {
17030
+ const activeNodeBranches = useMemo13(() => {
17075
17031
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
17076
17032
  return null;
17077
17033
  const fullTree = buildFullAncestryTree(
@@ -17115,7 +17071,7 @@ function XViewScene({
17115
17071
  readingMode.branchStack,
17116
17072
  ancestryDataRef.current
17117
17073
  ]);
17118
- const backNavigationInfo = useMemo12(() => {
17074
+ const backNavigationInfo = useMemo13(() => {
17119
17075
  const { branchStack } = readingMode;
17120
17076
  if (!branchStack || branchStack.length === 0) return null;
17121
17077
  const lastStep = branchStack[branchStack.length - 1];
@@ -17126,7 +17082,7 @@ function XViewScene({
17126
17082
  name: "Voltar para anterior"
17127
17083
  };
17128
17084
  }, [readingMode.branchStack]);
17129
- const getReadModeDisplayContext = useMemo12(() => {
17085
+ const getReadModeDisplayContext = useMemo13(() => {
17130
17086
  const { ancestry, branchStack } = readingMode;
17131
17087
  if (!ancestry) return null;
17132
17088
  if (branchStack.length === 0) {
@@ -17169,7 +17125,7 @@ function XViewScene({
17169
17125
  customProperties: branchProps
17170
17126
  };
17171
17127
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
17172
- const readModeAbstractionTree = useMemo12(() => {
17128
+ const readModeAbstractionTree = useMemo13(() => {
17173
17129
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
17174
17130
  return null;
17175
17131
  }
@@ -17814,7 +17770,7 @@ function XViewScene({
17814
17770
  },
17815
17771
  [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
17816
17772
  );
17817
- const existingNodeTypes = useMemo12(() => {
17773
+ const existingNodeTypes = useMemo13(() => {
17818
17774
  if (!parentDataRef.current) {
17819
17775
  return [];
17820
17776
  }
@@ -17826,7 +17782,7 @@ function XViewScene({
17826
17782
  ).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
17827
17783
  return [...new Set(allTypes)];
17828
17784
  }, [parentDataRef.current, sceneVersion]);
17829
- const searchableDbNodes = useMemo12(() => {
17785
+ const searchableDbNodes = useMemo13(() => {
17830
17786
  var _a2;
17831
17787
  if (!parentDataRef.current) {
17832
17788
  return [];
@@ -17945,13 +17901,13 @@ function XViewScene({
17945
17901
  console.error("Erro na chamada de save_view_data:", error);
17946
17902
  }
17947
17903
  }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
17948
- const allAvailableNodes = useMemo12(() => {
17904
+ const allAvailableNodes = useMemo13(() => {
17949
17905
  if (!parentDataRef.current) return [];
17950
17906
  return Object.values(parentDataRef.current).flatMap(
17951
17907
  (fileData) => fileData.nodes || []
17952
17908
  );
17953
17909
  }, [sceneVersion, isInitialized]);
17954
- const allAvailableAncestries = useMemo12(() => {
17910
+ const allAvailableAncestries = useMemo13(() => {
17955
17911
  return ancestryDataRef.current || [];
17956
17912
  }, [sceneVersion, isInitialized]);
17957
17913
  const handleOpenReference = useCallback4(
@@ -18015,7 +17971,7 @@ function XViewScene({
18015
17971
  },
18016
17972
  [tweenToTarget]
18017
17973
  );
18018
- const availableDatasets = useMemo12(() => {
17974
+ const availableDatasets = useMemo13(() => {
18019
17975
  if (!sceneDataRef.current || !parentDataRef.current) return [];
18020
17976
  return sceneDataRef.current.parent_dbs.map((db) => {
18021
17977
  var _a2;
@@ -18029,7 +17985,7 @@ function XViewScene({
18029
17985
  String(creationMode.sourceNodeData.id)
18030
17986
  )) == null ? void 0 : _c.parentFileId : null;
18031
17987
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
18032
- useEffect22(() => {
17988
+ useEffect24(() => {
18033
17989
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
18034
17990
  const nodeObjects = stateRef.current.nodeObjects || {};
18035
17991
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -18052,7 +18008,7 @@ function XViewScene({
18052
18008
  hasFocusedInitial,
18053
18009
  tweenToTarget
18054
18010
  ]);
18055
- useEffect22(() => {
18011
+ useEffect24(() => {
18056
18012
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
18057
18013
  const ancestries = ancestryDataRef.current || [];
18058
18014
  const targetAncestry = ancestries.find(
@@ -18077,7 +18033,7 @@ function XViewScene({
18077
18033
  hasOpenedInitialAncestry,
18078
18034
  handleStartReadingAncestry
18079
18035
  ]);
18080
- useEffect22(() => {
18036
+ useEffect24(() => {
18081
18037
  function handleKeyDown(event) {
18082
18038
  var _a2, _b2, _c2;
18083
18039
  const context = actionHandlerContext;
@@ -18200,10 +18156,10 @@ function XViewScene({
18200
18156
  // <-- handleCancelQuest adicionado aqui
18201
18157
  ]);
18202
18158
  if (isLoading || status === "loading" || permissionStatus === "loading") {
18203
- return /* @__PURE__ */ React28.createElement(LoadingScreen, null);
18159
+ return /* @__PURE__ */ React30.createElement(LoadingScreen, null);
18204
18160
  }
18205
18161
  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(
18162
+ 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
18163
  "svg",
18208
18164
  {
18209
18165
  xmlns: "http://www.w3.org/2000/svg",
@@ -18213,7 +18169,7 @@ function XViewScene({
18213
18169
  stroke: "currentColor",
18214
18170
  className: "w-16 h-16 mx-auto"
18215
18171
  },
18216
- /* @__PURE__ */ React28.createElement(
18172
+ /* @__PURE__ */ React30.createElement(
18217
18173
  "path",
18218
18174
  {
18219
18175
  strokeLinecap: "round",
@@ -18221,13 +18177,13 @@ function XViewScene({
18221
18177
  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
18178
  }
18223
18179
  )
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(
18180
+ )), /* @__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
18181
  "button",
18226
18182
  {
18227
18183
  onClick: () => router.push("/dashboard/scenes"),
18228
18184
  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
18185
  },
18230
- /* @__PURE__ */ React28.createElement(
18186
+ /* @__PURE__ */ React30.createElement(
18231
18187
  "svg",
18232
18188
  {
18233
18189
  xmlns: "http://www.w3.org/2000/svg",
@@ -18237,7 +18193,7 @@ function XViewScene({
18237
18193
  stroke: "currentColor",
18238
18194
  className: "w-5 h-5"
18239
18195
  },
18240
- /* @__PURE__ */ React28.createElement(
18196
+ /* @__PURE__ */ React30.createElement(
18241
18197
  "path",
18242
18198
  {
18243
18199
  strokeLinecap: "round",
@@ -18249,7 +18205,7 @@ function XViewScene({
18249
18205
  "Voltar para Scenes"
18250
18206
  )));
18251
18207
  }
18252
- return /* @__PURE__ */ React28.createElement(
18208
+ return /* @__PURE__ */ React30.createElement(
18253
18209
  "div",
18254
18210
  {
18255
18211
  ref: mountRef,
@@ -18261,7 +18217,7 @@ function XViewScene({
18261
18217
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
18262
18218
  }
18263
18219
  },
18264
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ React28.createElement(
18220
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ React30.createElement(
18265
18221
  XViewSidebar,
18266
18222
  {
18267
18223
  dbNodes: searchableDbNodes,
@@ -18285,7 +18241,7 @@ function XViewScene({
18285
18241
  onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
18286
18242
  }
18287
18243
  ),
18288
- creationMode.isActive && /* @__PURE__ */ React28.createElement(
18244
+ creationMode.isActive && /* @__PURE__ */ React30.createElement(
18289
18245
  InSceneCreationForm,
18290
18246
  {
18291
18247
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -18317,7 +18273,7 @@ function XViewScene({
18317
18273
  availableAncestries: allAvailableAncestries
18318
18274
  }
18319
18275
  ),
18320
- versionMode.isActive && /* @__PURE__ */ React28.createElement(
18276
+ versionMode.isActive && /* @__PURE__ */ React30.createElement(
18321
18277
  InSceneVersionForm,
18322
18278
  {
18323
18279
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -18343,7 +18299,7 @@ function XViewScene({
18343
18299
  availableAncestries: allAvailableAncestries
18344
18300
  }
18345
18301
  ),
18346
- questMode.isActive && /* @__PURE__ */ React28.createElement(
18302
+ questMode.isActive && /* @__PURE__ */ React30.createElement(
18347
18303
  InSceneQuestForm,
18348
18304
  {
18349
18305
  onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
@@ -18371,7 +18327,7 @@ function XViewScene({
18371
18327
  onUpdateMilestones: handleUpdateMilestones
18372
18328
  }
18373
18329
  ),
18374
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React28.createElement(
18330
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React30.createElement(
18375
18331
  "div",
18376
18332
  {
18377
18333
  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 +18340,7 @@ function XViewScene({
18384
18340
  maxWidth: "92vw"
18385
18341
  }
18386
18342
  },
18387
- /* @__PURE__ */ React28.createElement(
18343
+ /* @__PURE__ */ React30.createElement(
18388
18344
  "div",
18389
18345
  {
18390
18346
  onPointerDown: (e) => {
@@ -18395,7 +18351,7 @@ function XViewScene({
18395
18351
  title: "Arraste para redimensionar"
18396
18352
  }
18397
18353
  ),
18398
- /* @__PURE__ */ React28.createElement(
18354
+ /* @__PURE__ */ React30.createElement(
18399
18355
  DescriptionReadModePanel,
18400
18356
  {
18401
18357
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -18430,7 +18386,7 @@ function XViewScene({
18430
18386
  }
18431
18387
  )
18432
18388
  ),
18433
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React28.createElement(
18389
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React30.createElement(
18434
18390
  CreateAncestryPanel,
18435
18391
  {
18436
18392
  ancestryMode,
@@ -18466,7 +18422,7 @@ function XViewScene({
18466
18422
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
18467
18423
  }
18468
18424
  ),
18469
- editingAncestryRel.visible && /* @__PURE__ */ React28.createElement(
18425
+ editingAncestryRel.visible && /* @__PURE__ */ React30.createElement(
18470
18426
  AncestryRelationshipPanel,
18471
18427
  {
18472
18428
  data: editingAncestryRel.data,
@@ -18480,7 +18436,7 @@ function XViewScene({
18480
18436
  onUploadFile: upload_file_action
18481
18437
  }
18482
18438
  ),
18483
- detailsNode && detailsNode.is_quest && /* @__PURE__ */ React28.createElement(
18439
+ detailsNode && detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
18484
18440
  QuestDetailsPanel,
18485
18441
  {
18486
18442
  node: detailsNode,
@@ -18506,7 +18462,7 @@ function XViewScene({
18506
18462
  onUpdateMilestones: handleUpdateMilestones
18507
18463
  }
18508
18464
  ),
18509
- detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React28.createElement(
18465
+ detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
18510
18466
  NodeDetailsPanel,
18511
18467
  {
18512
18468
  node: detailsNode,
@@ -18538,7 +18494,7 @@ function XViewScene({
18538
18494
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
18539
18495
  }
18540
18496
  ),
18541
- detailsLink && /* @__PURE__ */ React28.createElement(
18497
+ detailsLink && /* @__PURE__ */ React30.createElement(
18542
18498
  RelationshipDetailsPanel,
18543
18499
  {
18544
18500
  link: detailsLink,
@@ -18552,7 +18508,7 @@ function XViewScene({
18552
18508
  userRole: userPermissionRole
18553
18509
  }
18554
18510
  ),
18555
- ancestryLinkDetails && /* @__PURE__ */ React28.createElement(
18511
+ ancestryLinkDetails && /* @__PURE__ */ React30.createElement(
18556
18512
  AncestryLinkDetailsPanel,
18557
18513
  {
18558
18514
  data: ancestryLinkDetails,
@@ -18563,7 +18519,7 @@ function XViewScene({
18563
18519
  onUploadFile: upload_file_action
18564
18520
  }
18565
18521
  ),
18566
- /* @__PURE__ */ React28.createElement(
18522
+ /* @__PURE__ */ React30.createElement(
18567
18523
  "div",
18568
18524
  {
18569
18525
  ref: tooltipRef,
@@ -18590,7 +18546,7 @@ function XViewScene({
18590
18546
  }
18591
18547
  }
18592
18548
  ),
18593
- /* @__PURE__ */ React28.createElement(
18549
+ /* @__PURE__ */ React30.createElement(
18594
18550
  ContextMenu,
18595
18551
  {
18596
18552
  data: contextMenu,
@@ -18623,7 +18579,7 @@ function XViewScene({
18623
18579
  onFinishQuest: handleFinishQuestQuick
18624
18580
  }
18625
18581
  ),
18626
- /* @__PURE__ */ React28.createElement(
18582
+ /* @__PURE__ */ React30.createElement(
18627
18583
  MultiNodeContextMenu,
18628
18584
  {
18629
18585
  data: multiContextMenu,
@@ -18643,7 +18599,7 @@ function XViewScene({
18643
18599
  )
18644
18600
  }
18645
18601
  ),
18646
- /* @__PURE__ */ React28.createElement(
18602
+ /* @__PURE__ */ React30.createElement(
18647
18603
  RelationshipContextMenu,
18648
18604
  {
18649
18605
  data: relationshipMenu,
@@ -18661,14 +18617,14 @@ function XViewScene({
18661
18617
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
18662
18618
  }
18663
18619
  ),
18664
- /* @__PURE__ */ React28.createElement(
18620
+ /* @__PURE__ */ React30.createElement(
18665
18621
  ImageViewer,
18666
18622
  {
18667
18623
  data: imageViewer,
18668
18624
  onClose: () => setImageViewer({ ...imageViewer, visible: false })
18669
18625
  }
18670
18626
  ),
18671
- /* @__PURE__ */ React28.createElement(
18627
+ /* @__PURE__ */ React30.createElement(
18672
18628
  AncestryBoard,
18673
18629
  {
18674
18630
  isOpen: isAncestryBoardOpen,
@@ -18681,7 +18637,7 @@ function XViewScene({
18681
18637
  userRole: userPermissionRole
18682
18638
  }
18683
18639
  ),
18684
- /* @__PURE__ */ React28.createElement(
18640
+ /* @__PURE__ */ React30.createElement(
18685
18641
  MilestoneManager,
18686
18642
  {
18687
18643
  isOpen: isMilestoneManagerOpen,
@@ -18690,7 +18646,7 @@ function XViewScene({
18690
18646
  onUpdateMilestones: handleUpdateMilestones
18691
18647
  }
18692
18648
  ),
18693
- /* @__PURE__ */ React28.createElement(
18649
+ /* @__PURE__ */ React30.createElement(
18694
18650
  ImportParentFileModal,
18695
18651
  {
18696
18652
  isOpen: isImportModalOpen,
@@ -18703,7 +18659,7 @@ function XViewScene({
18703
18659
  currentAncestries: ancestryDataRef.current || []
18704
18660
  }
18705
18661
  ),
18706
- invalidTargetError && /* @__PURE__ */ React28.createElement(
18662
+ invalidTargetError && /* @__PURE__ */ React30.createElement(
18707
18663
  "div",
18708
18664
  {
18709
18665
  className: "ui-overlay",
@@ -18728,13 +18684,13 @@ function XViewScene({
18728
18684
  animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
18729
18685
  }
18730
18686
  },
18731
- /* @__PURE__ */ React28.createElement("style", null, `
18687
+ /* @__PURE__ */ React30.createElement("style", null, `
18732
18688
  @keyframes fadeInDown {
18733
18689
  from { opacity: 0; transform: translate(-50%, -20px); }
18734
18690
  to { opacity: 1; transform: translate(-50%, 0); }
18735
18691
  }
18736
18692
  `),
18737
- /* @__PURE__ */ React28.createElement(
18693
+ /* @__PURE__ */ React30.createElement(
18738
18694
  "svg",
18739
18695
  {
18740
18696
  width: "20",
@@ -18746,12 +18702,12 @@ function XViewScene({
18746
18702
  strokeLinecap: "round",
18747
18703
  strokeLinejoin: "round"
18748
18704
  },
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" })
18705
+ /* @__PURE__ */ React30.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18706
+ /* @__PURE__ */ React30.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18707
+ /* @__PURE__ */ React30.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18752
18708
  ),
18753
- /* @__PURE__ */ React28.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18754
- /* @__PURE__ */ React28.createElement(
18709
+ /* @__PURE__ */ React30.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18710
+ /* @__PURE__ */ React30.createElement(
18755
18711
  "button",
18756
18712
  {
18757
18713
  onClick: () => setInvalidTargetError(null),