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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -44,9 +44,9 @@ __export(index_exports, {
44
44
  module.exports = __toCommonJS(index_exports);
45
45
 
46
46
  // src/XViewScene.jsx
47
- var import_react29 = __toESM(require("react"));
47
+ var import_react31 = __toESM(require("react"));
48
48
  var import_navigation = require("next/navigation");
49
- var import_react30 = require("next-auth/react");
49
+ var import_react32 = require("next-auth/react");
50
50
  var import_crypto_js = __toESM(require("crypto-js"));
51
51
  var THREE3 = __toESM(require("three"));
52
52
  var import_OrbitControls = require("three/examples/jsm/controls/OrbitControls.js");
@@ -118,55 +118,7 @@ function defineAbilityFor(role) {
118
118
 
119
119
  // src/logic/x_view_utils.js
120
120
  var import_react = require("react");
121
-
122
- // node_modules/uuid/dist/esm-node/rng.js
123
- var import_crypto = __toESM(require("crypto"));
124
- var rnds8Pool = new Uint8Array(256);
125
- var poolPtr = rnds8Pool.length;
126
- function rng() {
127
- if (poolPtr > rnds8Pool.length - 16) {
128
- import_crypto.default.randomFillSync(rnds8Pool);
129
- poolPtr = 0;
130
- }
131
- return rnds8Pool.slice(poolPtr, poolPtr += 16);
132
- }
133
-
134
- // node_modules/uuid/dist/esm-node/stringify.js
135
- var byteToHex = [];
136
- for (let i = 0; i < 256; ++i) {
137
- byteToHex.push((i + 256).toString(16).slice(1));
138
- }
139
- function unsafeStringify(arr, offset = 0) {
140
- 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]];
141
- }
142
-
143
- // node_modules/uuid/dist/esm-node/native.js
144
- var import_crypto2 = __toESM(require("crypto"));
145
- var native_default = {
146
- randomUUID: import_crypto2.default.randomUUID
147
- };
148
-
149
- // node_modules/uuid/dist/esm-node/v4.js
150
- function v4(options, buf, offset) {
151
- if (native_default.randomUUID && !buf && !options) {
152
- return native_default.randomUUID();
153
- }
154
- options = options || {};
155
- const rnds = options.random || (options.rng || rng)();
156
- rnds[6] = rnds[6] & 15 | 64;
157
- rnds[8] = rnds[8] & 63 | 128;
158
- if (buf) {
159
- offset = offset || 0;
160
- for (let i = 0; i < 16; ++i) {
161
- buf[offset + i] = rnds[i];
162
- }
163
- return buf;
164
- }
165
- return unsafeStringify(rnds);
166
- }
167
- var v4_default = v4;
168
-
169
- // src/logic/x_view_utils.js
121
+ var import_uuid = require("uuid");
170
122
  var THREE2 = __toESM(require("three"));
171
123
 
172
124
  // src/logic/x_view_config.js
@@ -1140,6 +1092,8 @@ var userActionHandlers = {
1140
1092
  if (isCrossDataset) {
1141
1093
  graphDataRef.current[finalTargetDatasetId] = targetDataToUpdate;
1142
1094
  }
1095
+ if (sceneDataRef.current.parent_dbs.some((db) => String(db.db_id) === String(sourceParentInfo.parentFileId))) {
1096
+ }
1143
1097
  const finalPosition = stateRef.current.ghostElements.node.position.clone();
1144
1098
  addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
1145
1099
  stateRef.current.nodeIdToParentFileMap.set(String(newNode.id), {
@@ -1338,6 +1292,9 @@ var userActionHandlers = {
1338
1292
  );
1339
1293
  }
1340
1294
  graphDataRef.current[parentFileId] = specificParentData;
1295
+ if (isView && parentFileId === context.sceneConfigId) {
1296
+ sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
1297
+ }
1341
1298
  const finalPosition = stateRef.current.ghostElements.node.position.clone();
1342
1299
  addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
1343
1300
  setters.setSceneVersion((v) => v + 1);
@@ -2357,8 +2314,6 @@ var userActionHandlers = {
2357
2314
  milestones: sceneDataRef.current.milestones || [],
2358
2315
  quest_counter: sceneDataRef.current.quest_counter || 1
2359
2316
  };
2360
- sceneDataRef.current.quest_nodes = specificParentData.nodes;
2361
- sceneDataRef.current.quest_links = specificParentData.links;
2362
2317
  await context.actions.save_view_data(
2363
2318
  context.sceneSaveUrl,
2364
2319
  viewFilePayload
@@ -2371,6 +2326,10 @@ var userActionHandlers = {
2371
2326
  );
2372
2327
  }
2373
2328
  graphDataRef.current[parentFileId] = specificParentData;
2329
+ if (isView && parentFileId === context.sceneConfigId) {
2330
+ sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
2331
+ sceneDataRef.current.quest_counter = specificParentData.quest_counter || sceneDataRef.current.quest_counter;
2332
+ }
2374
2333
  updateExistingNodeVisuals(stateRef.current, nodeToSave);
2375
2334
  setters.setSceneVersion((v) => v + 1);
2376
2335
  if (!keepOpen) {
@@ -2519,15 +2478,15 @@ function createNewCustomProperty(existingProps = []) {
2519
2478
  switch (nextType) {
2520
2479
  case "links":
2521
2480
  nextKey = "Links";
2522
- nextValue = [{ id: v4_default(), name: "", value: "" }];
2481
+ nextValue = [{ id: (0, import_uuid.v4)(), name: "", value: "" }];
2523
2482
  break;
2524
2483
  case "images":
2525
2484
  nextKey = "Images";
2526
- nextValue = [{ id: v4_default(), name: "1", value: "" }];
2485
+ nextValue = [{ id: (0, import_uuid.v4)(), name: "1", value: "" }];
2527
2486
  break;
2528
2487
  case "documents":
2529
2488
  nextKey = "Documents";
2530
- nextValue = [{ id: v4_default(), name: "1", value: "" }];
2489
+ nextValue = [{ id: (0, import_uuid.v4)(), name: "1", value: "" }];
2531
2490
  break;
2532
2491
  case "date":
2533
2492
  nextKey = "Date";
@@ -2537,14 +2496,14 @@ function createNewCustomProperty(existingProps = []) {
2537
2496
  nextValue = 0;
2538
2497
  break;
2539
2498
  case "list":
2540
- nextValue = [{ id: v4_default(), name: "", value: "" }];
2499
+ nextValue = [{ id: (0, import_uuid.v4)(), name: "", value: "" }];
2541
2500
  break;
2542
2501
  default:
2543
2502
  nextValue = "";
2544
2503
  break;
2545
2504
  }
2546
2505
  return {
2547
- id: v4_default(),
2506
+ id: (0, import_uuid.v4)(),
2548
2507
  key: nextKey,
2549
2508
  type: nextType,
2550
2509
  value: nextValue,
@@ -2789,7 +2748,7 @@ function extractCustomPropsFromNode(node) {
2789
2748
  if (val && typeof val === "object") {
2790
2749
  if ("date_interval" in val) {
2791
2750
  return {
2792
- id: v4_default(),
2751
+ id: (0, import_uuid.v4)(),
2793
2752
  key,
2794
2753
  type: "date",
2795
2754
  value: {
@@ -2801,7 +2760,7 @@ function extractCustomPropsFromNode(node) {
2801
2760
  }
2802
2761
  if ("year" in val) {
2803
2762
  return {
2804
- id: v4_default(),
2763
+ id: (0, import_uuid.v4)(),
2805
2764
  key,
2806
2765
  type: "date",
2807
2766
  value: { type: "Ano", value: val.year || "" }
@@ -2809,7 +2768,7 @@ function extractCustomPropsFromNode(node) {
2809
2768
  }
2810
2769
  if ("date" in val) {
2811
2770
  return {
2812
- id: v4_default(),
2771
+ id: (0, import_uuid.v4)(),
2813
2772
  key,
2814
2773
  type: "date",
2815
2774
  value: { type: "Data", value: val.date || "" }
@@ -2817,7 +2776,7 @@ function extractCustomPropsFromNode(node) {
2817
2776
  }
2818
2777
  }
2819
2778
  return {
2820
- id: v4_default(),
2779
+ id: (0, import_uuid.v4)(),
2821
2780
  key,
2822
2781
  type: "date",
2823
2782
  value: { type: "Data", value: "" }
@@ -2825,14 +2784,14 @@ function extractCustomPropsFromNode(node) {
2825
2784
  }
2826
2785
  if (t === "list" || t === "links" || t === "images" || t === "documents") {
2827
2786
  const safeList = (val || []).map((item) => ({
2828
- id: item.id || v4_default(),
2787
+ id: item.id || (0, import_uuid.v4)(),
2829
2788
  name: item.name ?? "",
2830
2789
  value: item.value ?? ""
2831
2790
  }));
2832
- return { id: v4_default(), key, type: t, value: safeList };
2791
+ return { id: (0, import_uuid.v4)(), key, type: t, value: safeList };
2833
2792
  }
2834
2793
  return {
2835
- id: v4_default(),
2794
+ id: (0, import_uuid.v4)(),
2836
2795
  key,
2837
2796
  type: t,
2838
2797
  value: t === "number" ? Number(val) || 0 : String(val ?? "")
@@ -3105,16 +3064,16 @@ var processDescriptionForSave = (text, existingSections = []) => {
3105
3064
  if (existingMatch) {
3106
3065
  finalUuid = existingMatch.id;
3107
3066
  } else {
3108
- finalUuid = v4_default();
3067
+ finalUuid = (0, import_uuid.v4)();
3109
3068
  }
3110
3069
  } else {
3111
3070
  finalUuid = numericMap.get(numStr);
3112
3071
  if (!finalUuid) {
3113
- finalUuid = v4_default();
3072
+ finalUuid = (0, import_uuid.v4)();
3114
3073
  }
3115
3074
  }
3116
3075
  if (usedIds.has(finalUuid)) {
3117
- finalUuid = v4_default();
3076
+ finalUuid = (0, import_uuid.v4)();
3118
3077
  }
3119
3078
  usedIds.add(finalUuid);
3120
3079
  processedSections.push({
@@ -3225,18 +3184,18 @@ function useResizablePanel({ initialWidth, minWidth, maxWidth }) {
3225
3184
  function createTimelineEntry(actorId, description, type = "comment", extras = {}) {
3226
3185
  const { links = [], images = [], metadata = {} } = extras;
3227
3186
  return {
3228
- id: v4_default(),
3187
+ id: (0, import_uuid.v4)(),
3229
3188
  type,
3230
3189
  timestamp: Date.now(),
3231
3190
  actorId,
3232
3191
  description,
3233
3192
  links: links.map((l) => ({
3234
- id: l.id || v4_default(),
3193
+ id: l.id || (0, import_uuid.v4)(),
3235
3194
  name: l.name || "",
3236
3195
  value: l.value || ""
3237
3196
  })),
3238
3197
  images: images.map((img) => ({
3239
- id: img.id || v4_default(),
3198
+ id: img.id || (0, import_uuid.v4)(),
3240
3199
  name: img.name || "",
3241
3200
  value: img.value || ""
3242
3201
  }))
@@ -4463,6 +4422,7 @@ function XViewSidebar({
4463
4422
 
4464
4423
  // src/components/AncestryRelationshipPanel.jsx
4465
4424
  var import_react9 = __toESM(require("react"));
4425
+ var import_uuid3 = require("uuid");
4466
4426
 
4467
4427
  // src/components/CustomPropertyDisplay.jsx
4468
4428
  var import_react4 = __toESM(require("react"));
@@ -5222,6 +5182,7 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
5222
5182
  }
5223
5183
 
5224
5184
  // src/components/DescriptionEditModal.jsx
5185
+ var import_uuid2 = require("uuid");
5225
5186
  var getNextSectionNumber = (currentText) => {
5226
5187
  const regex = /\*\/\s*(\d+)(?::[a-zA-Z0-9-]+)?\s*\//g;
5227
5188
  let max = 0;
@@ -5353,7 +5314,7 @@ function DescriptionEditModal({
5353
5314
  const el = textareaRef.current;
5354
5315
  if (!el) return;
5355
5316
  const nextNum = getNextSectionNumber(text);
5356
- const uniqueSuffix = v4_default().slice(0, 4);
5317
+ const uniqueSuffix = (0, import_uuid2.v4)().slice(0, 4);
5357
5318
  insertAtCursor(`*/${nextNum}:${uniqueSuffix}/ `);
5358
5319
  };
5359
5320
  const handleImportSelect = (tags) => {
@@ -5364,7 +5325,7 @@ function DescriptionEditModal({
5364
5325
  let currentNum = getNextSectionNumber(currentText);
5365
5326
  let blockToInsert = "";
5366
5327
  tagsArray.forEach((tag) => {
5367
- const uniqueSuffix = v4_default().slice(0, 4);
5328
+ const uniqueSuffix = (0, import_uuid2.v4)().slice(0, 4);
5368
5329
  blockToInsert += `
5369
5330
  */${currentNum}:${uniqueSuffix}/ ${tag}
5370
5331
  `;
@@ -6693,6 +6654,7 @@ function AncestryRelationshipPanel({
6693
6654
  // src/components/CreateAncestryPanel.jsx
6694
6655
  var import_react11 = __toESM(require("react"));
6695
6656
  var import_fi10 = require("react-icons/fi");
6657
+ var import_uuid4 = require("uuid");
6696
6658
 
6697
6659
  // src/components/AncestryPickerModal.jsx
6698
6660
  var import_react10 = __toESM(require("react"));
@@ -7729,7 +7691,7 @@ function CreateAncestryPanel({
7729
7691
  const nodeData = availableNodes.find((n) => String(n.id) === String(nodeId));
7730
7692
  const dirSuffix = direction === "left" ? "(Esq)" : "(Dir)";
7731
7693
  branch = {
7732
- id: v4_default(),
7694
+ id: (0, import_uuid4.v4)(),
7733
7695
  name: `Ramifica\xE7\xE3o ${dirSuffix} de ${(nodeData == null ? void 0 : nodeData.name) || "Node"}`,
7734
7696
  description: "",
7735
7697
  description_sections: [],
@@ -8508,6 +8470,7 @@ function ImageViewer({ data, onClose }) {
8508
8470
 
8509
8471
  // src/components/InSceneCreationForm.jsx
8510
8472
  var import_react14 = __toESM(require("react"));
8473
+ var import_uuid5 = require("uuid");
8511
8474
 
8512
8475
  // src/components/ColorPicker.jsx
8513
8476
  var import_react13 = __toESM(require("react"));
@@ -9084,6 +9047,7 @@ function InSceneCreationForm({
9084
9047
 
9085
9048
  // src/components/InSceneVersionForm.jsx
9086
9049
  var import_react15 = __toESM(require("react"));
9050
+ var import_uuid6 = require("uuid");
9087
9051
  var import_fi14 = require("react-icons/fi");
9088
9052
  function InSceneVersionForm({
9089
9053
  onSave,
@@ -9106,7 +9070,7 @@ function InSceneVersionForm({
9106
9070
  const [description, setDescription] = (0, import_react15.useState)("");
9107
9071
  const [customProps, setCustomProps] = (0, import_react15.useState)([
9108
9072
  {
9109
- id: v4_default(),
9073
+ id: (0, import_uuid6.v4)(),
9110
9074
  key: "Date",
9111
9075
  type: "date",
9112
9076
  value: { type: "Data", value: "" },
@@ -9399,6 +9363,7 @@ function InSceneVersionForm({
9399
9363
 
9400
9364
  // src/components/InSceneQuestForm.jsx
9401
9365
  var import_react17 = __toESM(require("react"));
9366
+ var import_uuid7 = require("uuid");
9402
9367
  var import_fi16 = require("react-icons/fi");
9403
9368
 
9404
9369
  // src/components/QuestReviewStackEditor.jsx
@@ -10304,6 +10269,7 @@ function InSceneQuestForm({
10304
10269
 
10305
10270
  // src/components/NodeDetailsPanel.jsx
10306
10271
  var import_react18 = __toESM(require("react"));
10272
+ var import_uuid8 = require("uuid");
10307
10273
  var import_fi17 = require("react-icons/fi");
10308
10274
  function NodeDetailsPanel({
10309
10275
  node,
@@ -10818,6 +10784,7 @@ function NodeDetailsPanel({
10818
10784
 
10819
10785
  // src/components/QuestDetailsPanel.jsx
10820
10786
  var import_react20 = __toESM(require("react"));
10787
+ var import_uuid9 = require("uuid");
10821
10788
  var import_fi19 = require("react-icons/fi");
10822
10789
 
10823
10790
  // src/components/QuestTimeline.jsx
@@ -11256,7 +11223,7 @@ ${noteText}` : noteText : entry.notes,
11256
11223
  }, 100);
11257
11224
  };
11258
11225
  const addLinkToNote = () => {
11259
- setNoteLinks([...noteLinks, { id: v4_default(), name: "", value: "" }]);
11226
+ setNoteLinks([...noteLinks, { id: (0, import_uuid9.v4)(), name: "", value: "" }]);
11260
11227
  };
11261
11228
  const removeLinkFromNote = (id) => {
11262
11229
  setNoteLinks(noteLinks.filter((l) => l.id !== id));
@@ -11265,7 +11232,7 @@ ${noteText}` : noteText : entry.notes,
11265
11232
  setNoteLinks(noteLinks.map((l) => l.id === id ? { ...l, [field]: val } : l));
11266
11233
  };
11267
11234
  const addImageToNote = () => {
11268
- setNoteImages([...noteImages, { id: v4_default(), name: "Image", value: "" }]);
11235
+ setNoteImages([...noteImages, { id: (0, import_uuid9.v4)(), name: "Image", value: "" }]);
11269
11236
  };
11270
11237
  const removeImageFromNote = (id) => {
11271
11238
  setNoteImages(noteImages.filter((img) => img.id !== id));
@@ -12142,6 +12109,7 @@ function MultiNodeContextMenu({
12142
12109
 
12143
12110
  // src/components/RelationshipDetailsPanel.jsx
12144
12111
  var import_react22 = __toESM(require("react"));
12112
+ var import_uuid10 = require("uuid");
12145
12113
  var import_fi20 = require("react-icons/fi");
12146
12114
  function RelationshipDetailsPanel({
12147
12115
  link,
@@ -12951,191 +12919,416 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
12951
12919
  }
12952
12920
 
12953
12921
  // src/components/AncestryBoard.jsx
12922
+ var import_react29 = __toESM(require("react"));
12923
+ var import_fi23 = require("react-icons/fi");
12924
+ var import_uuid11 = require("uuid");
12925
+
12926
+ // src/components/RichGroupEditor.jsx
12927
+ var import_react28 = __toESM(require("react"));
12928
+
12929
+ // src/components/MentionPopover.jsx
12954
12930
  var import_react27 = __toESM(require("react"));
12955
12931
  var import_fi22 = require("react-icons/fi");
12932
+ var TYPE_CONFIG = {
12933
+ ancestry: { Icon: import_fi22.FiLayers, color: "text-indigo-400", label: "Ancestralidade" },
12934
+ quest: { Icon: import_fi22.FiCheckSquare, color: "text-emerald-400", label: "Quest" },
12935
+ version: { Icon: import_fi22.FiGitBranch, color: "text-amber-400", label: "Vers\xE3o" },
12936
+ node: { Icon: import_fi22.FiBox, color: "text-slate-400", label: "Node" }
12937
+ };
12938
+ function MentionPopover({ query, items, position, onSelect, onClose }) {
12939
+ const [activeIndex, setActiveIndex] = (0, import_react27.useState)(0);
12940
+ const listRef = (0, import_react27.useRef)(null);
12941
+ const filtered = (0, import_react27.useMemo)(() => {
12942
+ const term = (query || "").toLowerCase().trim();
12943
+ if (!term) return items.slice(0, 8);
12944
+ return items.filter(
12945
+ (item) => (item.searchLabel || "").toLowerCase().includes(term) || (item.searchDesc || "").toLowerCase().includes(term)
12946
+ ).slice(0, 8);
12947
+ }, [items, query]);
12948
+ (0, import_react27.useEffect)(() => {
12949
+ setActiveIndex(0);
12950
+ }, [query]);
12951
+ (0, import_react27.useEffect)(() => {
12952
+ const handleKeyDown = (e) => {
12953
+ if (e.key === "ArrowDown") {
12954
+ e.preventDefault();
12955
+ setActiveIndex((i) => Math.min(i + 1, filtered.length - 1));
12956
+ } else if (e.key === "ArrowUp") {
12957
+ e.preventDefault();
12958
+ setActiveIndex((i) => Math.max(i - 1, 0));
12959
+ } else if (e.key === "Enter" || e.key === "Tab") {
12960
+ e.preventDefault();
12961
+ if (filtered[activeIndex]) onSelect(filtered[activeIndex]);
12962
+ } else if (e.key === "Escape") {
12963
+ e.preventDefault();
12964
+ onClose();
12965
+ }
12966
+ };
12967
+ window.addEventListener("keydown", handleKeyDown, true);
12968
+ return () => window.removeEventListener("keydown", handleKeyDown, true);
12969
+ }, [filtered, activeIndex, onSelect, onClose]);
12970
+ (0, import_react27.useEffect)(() => {
12971
+ if (listRef.current) {
12972
+ const el = listRef.current.children[activeIndex];
12973
+ if (el) el.scrollIntoView({ block: "nearest" });
12974
+ }
12975
+ }, [activeIndex]);
12976
+ return /* @__PURE__ */ import_react27.default.createElement(
12977
+ "div",
12978
+ {
12979
+ style: { top: position.top, left: position.left, position: "fixed", zIndex: 9999 },
12980
+ className: "bg-slate-900 border border-white/10 rounded-xl shadow-2xl py-1.5 min-w-[260px] max-h-[240px] overflow-y-auto custom-scrollbar animate-in fade-in zoom-in-95 duration-100",
12981
+ ref: listRef,
12982
+ onMouseDown: (e) => e.preventDefault()
12983
+ },
12984
+ filtered.length === 0 ? /* @__PURE__ */ import_react27.default.createElement("div", { className: "px-4 py-3 text-xs text-slate-500" }, "Nenhum resultado para", " ", /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-slate-300 font-medium" }, '"', query, '"')) : filtered.map((item, idx) => {
12985
+ const config = TYPE_CONFIG[item.type] || TYPE_CONFIG.node;
12986
+ const { Icon } = config;
12987
+ return /* @__PURE__ */ import_react27.default.createElement(
12988
+ "div",
12989
+ {
12990
+ key: item.id,
12991
+ onMouseDown: (e) => {
12992
+ e.preventDefault();
12993
+ onSelect(item);
12994
+ },
12995
+ onMouseEnter: () => setActiveIndex(idx),
12996
+ className: `flex items-center gap-2.5 px-3 py-2 cursor-pointer text-sm transition-colors duration-100 ${idx === activeIndex ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5"}`
12997
+ },
12998
+ /* @__PURE__ */ import_react27.default.createElement(Icon, { size: 13, className: config.color }),
12999
+ /* @__PURE__ */ import_react27.default.createElement("span", { className: "flex-1 truncate font-medium" }, item.searchLabel || "Sem Nome"),
13000
+ /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-[9px] px-1.5 py-0.5 rounded-full bg-white/5 text-slate-500 border border-white/5 uppercase tracking-wide shrink-0" }, config.label)
13001
+ );
13002
+ })
13003
+ );
13004
+ }
13005
+
13006
+ // src/components/RichGroupEditor.jsx
13007
+ var MENTION_BASE_STYLE = "display:inline-flex;align-items:center;padding:1px 7px;border-radius:5px;margin:0 2px;font-size:0.78em;font-weight:600;cursor:pointer;white-space:nowrap;vertical-align:middle;user-select:none;line-height:1.6;";
13008
+ var MENTION_TYPE_STYLE = {
13009
+ ancestry: "background:rgba(99,102,241,0.18);color:#a5b4fc;border:1px solid rgba(99,102,241,0.35);",
13010
+ quest: "background:rgba(16,185,129,0.18);color:#6ee7b7;border:1px solid rgba(16,185,129,0.35);",
13011
+ version: "background:rgba(245,158,11,0.18);color:#fcd34d;border:1px solid rgba(245,158,11,0.35);",
13012
+ node: "background:rgba(100,116,139,0.18);color:#94a3b8;border:1px solid rgba(100,116,139,0.35);"
13013
+ };
13014
+ function mentionStyle(type) {
13015
+ return MENTION_BASE_STYLE + (MENTION_TYPE_STYLE[type] || MENTION_TYPE_STYLE.node);
13016
+ }
13017
+ function escapeHtml(str) {
13018
+ return String(str || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
13019
+ }
13020
+ function contentToHTML(content) {
13021
+ if (!content || content.length === 0) return "";
13022
+ return content.map((seg) => {
13023
+ if (seg.type === "text") {
13024
+ return escapeHtml(seg.value).replace(/\n/g, "<br>");
13025
+ }
13026
+ if (seg.type === "mention") {
13027
+ const style = mentionStyle(seg.mentionType);
13028
+ return `<span contenteditable="false" data-mention="true" data-id="${escapeHtml(String(seg.id))}" data-name="${escapeHtml(seg.name || "")}" data-mention-type="${escapeHtml(seg.mentionType || "node")}" style="${style}" title="Clique para focar na cena">@${escapeHtml(seg.name || "")}</span>`;
13029
+ }
13030
+ return "";
13031
+ }).join("");
13032
+ }
13033
+ function domToContent(el) {
13034
+ const segments = [];
13035
+ function pushText(text) {
13036
+ const clean = text.replace(/\u200B/g, "");
13037
+ if (!clean) return;
13038
+ const last = segments[segments.length - 1];
13039
+ if (last && last.type === "text") {
13040
+ last.value += clean;
13041
+ } else {
13042
+ segments.push({ type: "text", value: clean });
13043
+ }
13044
+ }
13045
+ function walk(node) {
13046
+ var _a;
13047
+ if (node.nodeType === Node.TEXT_NODE) {
13048
+ pushText(node.textContent);
13049
+ } else if (node.nodeType === Node.ELEMENT_NODE) {
13050
+ if (((_a = node.dataset) == null ? void 0 : _a.mention) === "true") {
13051
+ segments.push({
13052
+ type: "mention",
13053
+ id: node.dataset.id,
13054
+ name: node.dataset.name,
13055
+ mentionType: node.dataset.mentionType
13056
+ });
13057
+ } else if (node.tagName === "BR") {
13058
+ pushText("\n");
13059
+ } else {
13060
+ if (["DIV", "P"].includes(node.tagName) && segments.length > 0) {
13061
+ pushText("\n");
13062
+ }
13063
+ node.childNodes.forEach(walk);
13064
+ }
13065
+ }
13066
+ }
13067
+ el.childNodes.forEach(walk);
13068
+ return segments;
13069
+ }
13070
+ function RichGroupEditor({
13071
+ content,
13072
+ onChange,
13073
+ onMentionClick,
13074
+ searchItems,
13075
+ readOnly,
13076
+ placeholder
13077
+ }) {
13078
+ const editorRef = (0, import_react28.useRef)(null);
13079
+ const isMountedRef = (0, import_react28.useRef)(false);
13080
+ const [mentionState, setMentionState] = (0, import_react28.useState)(null);
13081
+ const [isEmpty, setIsEmpty] = (0, import_react28.useState)(true);
13082
+ (0, import_react28.useEffect)(() => {
13083
+ if (!isMountedRef.current && editorRef.current) {
13084
+ editorRef.current.innerHTML = contentToHTML(content);
13085
+ const hasContent = !!editorRef.current.innerText.replace(/\u200B/g, "").trim();
13086
+ const hasMentions = !!editorRef.current.querySelector("[data-mention]");
13087
+ setIsEmpty(!hasContent && !hasMentions);
13088
+ isMountedRef.current = true;
13089
+ }
13090
+ }, []);
13091
+ const getMentionContext = (0, import_react28.useCallback)(() => {
13092
+ const selection = window.getSelection();
13093
+ if (!selection || selection.rangeCount === 0) return null;
13094
+ const range = selection.getRangeAt(0);
13095
+ if (range.startContainer.nodeType !== Node.TEXT_NODE) return null;
13096
+ const textBefore = range.startContainer.textContent.substring(0, range.startOffset);
13097
+ const atIndex = textBefore.lastIndexOf("@");
13098
+ if (atIndex === -1) return null;
13099
+ const query = textBefore.substring(atIndex + 1);
13100
+ if (query.includes(" ") || query.includes(".") || query.includes(",") || query.length > 40) {
13101
+ return null;
13102
+ }
13103
+ const rect = range.getBoundingClientRect();
13104
+ return {
13105
+ query,
13106
+ position: { top: rect.bottom + 6, left: rect.left }
13107
+ };
13108
+ }, []);
13109
+ const handleInput = (0, import_react28.useCallback)(() => {
13110
+ if (!editorRef.current) return;
13111
+ const serialized = domToContent(editorRef.current);
13112
+ onChange(serialized);
13113
+ const text = editorRef.current.innerText.replace(/\u200B/g, "").trim();
13114
+ const hasMentions = !!editorRef.current.querySelector("[data-mention]");
13115
+ setIsEmpty(!text && !hasMentions);
13116
+ const ctx = getMentionContext();
13117
+ setMentionState(ctx);
13118
+ }, [onChange, getMentionContext]);
13119
+ const handleKeyDown = (0, import_react28.useCallback)(
13120
+ (e) => {
13121
+ if (mentionState && ["ArrowDown", "ArrowUp", "Enter", "Tab", "Escape"].includes(e.key)) {
13122
+ return;
13123
+ }
13124
+ if (e.key === "Enter") {
13125
+ e.preventDefault();
13126
+ const sel = window.getSelection();
13127
+ const range = sel.getRangeAt(0);
13128
+ const br = document.createElement("br");
13129
+ range.deleteContents();
13130
+ range.insertNode(br);
13131
+ const afterBr = br.nextSibling || (() => {
13132
+ const zws = document.createTextNode("\u200B");
13133
+ br.parentNode.insertBefore(zws, br.nextSibling);
13134
+ return zws;
13135
+ })();
13136
+ const newRange = document.createRange();
13137
+ newRange.setStartBefore(afterBr);
13138
+ newRange.collapse(true);
13139
+ sel.removeAllRanges();
13140
+ sel.addRange(newRange);
13141
+ handleInput();
13142
+ }
13143
+ },
13144
+ [mentionState, handleInput]
13145
+ );
13146
+ const insertMention = (0, import_react28.useCallback)(
13147
+ (item) => {
13148
+ if (!editorRef.current) return;
13149
+ const sel = window.getSelection();
13150
+ if (!sel || sel.rangeCount === 0) return;
13151
+ const range = sel.getRangeAt(0);
13152
+ const textNode = range.startContainer;
13153
+ if (textNode.nodeType !== Node.TEXT_NODE) {
13154
+ setMentionState(null);
13155
+ return;
13156
+ }
13157
+ const cursorPos = range.startOffset;
13158
+ const textContent = textNode.textContent;
13159
+ const atIndex = textContent.lastIndexOf("@", cursorPos - 1);
13160
+ if (atIndex === -1) {
13161
+ setMentionState(null);
13162
+ return;
13163
+ }
13164
+ const before = textContent.substring(0, atIndex);
13165
+ const after = textContent.substring(cursorPos);
13166
+ textNode.textContent = before;
13167
+ const parent = textNode.parentNode;
13168
+ const nextSib = textNode.nextSibling;
13169
+ const span = document.createElement("span");
13170
+ span.contentEditable = "false";
13171
+ span.dataset.mention = "true";
13172
+ span.dataset.id = item.id;
13173
+ span.dataset.name = item.searchLabel || item.name || "";
13174
+ span.dataset.mentionType = item.type;
13175
+ span.style.cssText = mentionStyle(item.type);
13176
+ span.title = "Clique para focar na cena";
13177
+ span.textContent = `@${item.searchLabel || item.name || ""}`;
13178
+ parent.insertBefore(span, nextSib);
13179
+ const trailing = document.createTextNode(after || "\u200B");
13180
+ parent.insertBefore(trailing, span.nextSibling);
13181
+ const newRange = document.createRange();
13182
+ newRange.setStart(trailing, after ? 0 : 1);
13183
+ newRange.collapse(true);
13184
+ sel.removeAllRanges();
13185
+ sel.addRange(newRange);
13186
+ const serialized = domToContent(editorRef.current);
13187
+ onChange(serialized);
13188
+ setMentionState(null);
13189
+ setIsEmpty(false);
13190
+ },
13191
+ [onChange]
13192
+ );
13193
+ const handlePaste = (0, import_react28.useCallback)(
13194
+ (e) => {
13195
+ e.preventDefault();
13196
+ const text = e.clipboardData.getData("text/plain");
13197
+ if (text) {
13198
+ document.execCommand("insertText", false, text);
13199
+ handleInput();
13200
+ }
13201
+ },
13202
+ [handleInput]
13203
+ );
13204
+ const handleClick = (0, import_react28.useCallback)(
13205
+ (e) => {
13206
+ const chip = e.target.closest("[data-mention='true']");
13207
+ if (chip && onMentionClick) {
13208
+ e.stopPropagation();
13209
+ const id = chip.dataset.id;
13210
+ const full = searchItems == null ? void 0 : searchItems.find((i) => String(i.id) === String(id));
13211
+ if (full) {
13212
+ onMentionClick(full);
13213
+ } else {
13214
+ onMentionClick({
13215
+ id,
13216
+ name: chip.dataset.name,
13217
+ type: chip.dataset.mentionType,
13218
+ searchLabel: chip.dataset.name
13219
+ });
13220
+ }
13221
+ return;
13222
+ }
13223
+ setTimeout(() => {
13224
+ const ctx = getMentionContext();
13225
+ setMentionState(ctx);
13226
+ }, 0);
13227
+ },
13228
+ [onMentionClick, getMentionContext, searchItems]
13229
+ );
13230
+ const handleBlur = (0, import_react28.useCallback)(() => {
13231
+ setTimeout(() => setMentionState(null), 200);
13232
+ }, []);
13233
+ return /* @__PURE__ */ import_react28.default.createElement("div", { className: "relative" }, isEmpty && !readOnly && /* @__PURE__ */ import_react28.default.createElement("div", { className: "absolute top-0 left-0 text-sm text-slate-600 pointer-events-none select-none" }, placeholder || "Escreva sobre este grupo\u2026 ou digite @ para mencionar"), /* @__PURE__ */ import_react28.default.createElement(
13234
+ "div",
13235
+ {
13236
+ ref: editorRef,
13237
+ contentEditable: readOnly ? "false" : "true",
13238
+ suppressContentEditableWarning: true,
13239
+ onInput: handleInput,
13240
+ onKeyDown: handleKeyDown,
13241
+ onPaste: handlePaste,
13242
+ onClick: handleClick,
13243
+ onBlur: handleBlur,
13244
+ className: `w-full min-h-[1.5rem] max-h-[250px] overflow-y-auto text-sm text-slate-200 focus:outline-none leading-relaxed ${!readOnly ? "cursor-text" : "cursor-default"}`,
13245
+ style: { overflowWrap: "break-word", wordBreak: "break-word" }
13246
+ }
13247
+ ), mentionState && !readOnly && /* @__PURE__ */ import_react28.default.createElement(
13248
+ MentionPopover,
13249
+ {
13250
+ query: mentionState.query,
13251
+ items: searchItems || [],
13252
+ position: mentionState.position,
13253
+ onSelect: insertMention,
13254
+ onClose: () => setMentionState(null)
13255
+ }
13256
+ ));
13257
+ }
13258
+
13259
+ // src/components/AncestryBoard.jsx
12956
13260
  var GroupItem = ({
12957
13261
  group,
12958
13262
  index,
12959
- siblings,
12960
13263
  onUpdate,
12961
13264
  onDelete,
12962
13265
  onAddSubgroup,
12963
13266
  onIndent,
12964
13267
  onOutdent,
12965
- onRemoveAncestry,
12966
- onRequestPickAncestry,
12967
- pickingGroupId,
12968
- onPlayAncestry,
12969
- availableIds,
13268
+ searchItems,
13269
+ onMentionClick,
12970
13270
  canEdit
12971
13271
  }) => {
12972
13272
  const canIndent = index > 0;
12973
- const isPickingForThisGroup = pickingGroupId === group.id;
12974
- const textareaRef = (0, import_react27.useRef)(null);
12975
- const adjustHeight = () => {
12976
- const textarea = textareaRef.current;
12977
- if (textarea) {
12978
- textarea.style.height = "auto";
12979
- textarea.style.height = `${textarea.scrollHeight}px`;
12980
- }
13273
+ const handleContentChange = (content) => {
13274
+ onUpdate(group.id, { ...group, content });
12981
13275
  };
12982
- (0, import_react27.useEffect)(() => {
12983
- adjustHeight();
12984
- }, [group.text]);
12985
- return /* @__PURE__ */ import_react27.default.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__ */ import_react27.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react27.default.createElement(
12986
- "div",
13276
+ return /* @__PURE__ */ import_react29.default.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__ */ import_react29.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col gap-2 py-2 px-3 transition-all duration-200 hover:bg-white/5 border-l-2 border-transparent hover:border-white/20" }, /* @__PURE__ */ import_react29.default.createElement(
13277
+ RichGroupEditor,
12987
13278
  {
12988
- className: `
12989
- flex flex-col gap-2 py-2 px-3 transition-all duration-200
12990
- ${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
12991
- `
13279
+ content: group.content,
13280
+ onChange: handleContentChange,
13281
+ onMentionClick,
13282
+ searchItems,
13283
+ readOnly: !canEdit,
13284
+ placeholder: "Escreva sobre este grupo\u2026 ou @ para mencionar"
13285
+ }
13286
+ ), canEdit && /* @__PURE__ */ import_react29.default.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__ */ import_react29.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react29.default.createElement(
13287
+ "button",
13288
+ {
13289
+ onClick: () => onAddSubgroup(group.id),
13290
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13291
+ title: "Criar Subgrupo"
12992
13292
  },
12993
- /* @__PURE__ */ import_react27.default.createElement(
12994
- "textarea",
12995
- {
12996
- ref: textareaRef,
12997
- 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" : ""}`,
12998
- rows: 1,
12999
- style: {
13000
- minHeight: "1.5rem",
13001
- maxHeight: "250px"
13002
- },
13003
- placeholder: canEdit ? "Escreva sobre este grupo..." : "",
13004
- value: group.text,
13005
- readOnly: !canEdit,
13006
- onChange: (e) => {
13007
- if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
13008
- }
13009
- }
13010
- ),
13011
- group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
13012
- const isValid = anc.type === "ancestry" || !anc.type ? availableIds.has(String(anc.ancestry_id || anc.id)) : true;
13013
- const isAncestry = anc.type === "ancestry" || !anc.type;
13014
- const itemId = isAncestry ? anc.ancestry_id : anc.id;
13015
- let Icon = import_fi22.FiLayers;
13016
- let colorClass = "text-indigo-400";
13017
- if (anc.type === "quest") {
13018
- Icon = import_fi22.FiCheckSquare;
13019
- colorClass = "text-amber-400";
13020
- } else if (anc.type === "version") {
13021
- Icon = import_fi22.FiGitBranch;
13022
- colorClass = "text-purple-400";
13023
- } else if (anc.type === "node") {
13024
- Icon = import_fi22.FiBox;
13025
- colorClass = "text-emerald-400";
13026
- }
13027
- return /* @__PURE__ */ import_react27.default.createElement(
13028
- "div",
13029
- {
13030
- key: `${anc.type || "ancestry"}-${itemId}`,
13031
- className: `
13032
- flex items-center gap-2 rounded-md px-3 py-1.5 text-xs transition-all group/card border
13033
- ${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"}
13034
- `,
13035
- title: isValid ? "" : "Esta informa\xE7\xE3o n\xE3o est\xE1 mais dispon\xEDvel neste contexto."
13036
- },
13037
- isValid ? /* @__PURE__ */ import_react27.default.createElement(
13038
- "button",
13039
- {
13040
- onClick: () => onPlayAncestry(anc),
13041
- className: `${colorClass} hover:text-white hover:bg-current/20 p-1 rounded transition-colors flex items-center justify-center`,
13042
- title: "Focar no cen\xE1rio"
13043
- },
13044
- /* @__PURE__ */ import_react27.default.createElement(Icon, { size: 12 }),
13045
- /* @__PURE__ */ import_react27.default.createElement(
13046
- import_fi22.FiPlay,
13047
- {
13048
- size: 8,
13049
- className: "ml-0.5 fill-current opacity-0 group-hover/card:opacity-100 transition-opacity"
13050
- }
13051
- )
13052
- ) : /* @__PURE__ */ import_react27.default.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiAlertTriangle, { size: 10 })),
13053
- /* @__PURE__ */ import_react27.default.createElement(
13054
- "span",
13055
- {
13056
- className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}`
13057
- },
13058
- anc.name
13059
- ),
13060
- canEdit && /* @__PURE__ */ import_react27.default.createElement(import_react27.default.Fragment, null, /* @__PURE__ */ import_react27.default.createElement(
13061
- "div",
13062
- {
13063
- className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}`
13064
- }
13065
- ), /* @__PURE__ */ import_react27.default.createElement(
13066
- "button",
13067
- {
13068
- onClick: () => onRemoveAncestry(group.id, itemId),
13069
- className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
13070
- title: "Remover men\xE7\xE3o"
13071
- },
13072
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiX, { size: 12 })
13073
- ))
13074
- );
13075
- })),
13076
- canEdit && /* @__PURE__ */ import_react27.default.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__ */ import_react27.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react27.default.createElement(
13077
- "button",
13078
- {
13079
- onClick: () => onRequestPickAncestry(group.id),
13080
- className: `
13081
- flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium transition-colors
13082
- ${isPickingForThisGroup ? "text-indigo-300 animate-pulse" : "text-slate-500 hover:text-indigo-300 hover:bg-indigo-500/10"}
13083
- `,
13084
- title: "Adicionar Men\xE7\xE3o a este grupo"
13085
- },
13086
- isPickingForThisGroup ? /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiCheckCircle, { size: 12 }) : /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiSearch, { size: 12 }),
13087
- isPickingForThisGroup ? "Selecionando..." : "Adicionar"
13088
- ), /* @__PURE__ */ import_react27.default.createElement(
13089
- "button",
13090
- {
13091
- onClick: () => onAddSubgroup(group.id),
13092
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13093
- title: "Criar Subgrupo"
13094
- },
13095
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiPlus, { size: 14 })
13096
- )), /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react27.default.createElement(
13097
- "button",
13098
- {
13099
- onClick: () => onIndent(group.id),
13100
- disabled: !canIndent,
13101
- className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13102
- title: "Aninhar no grupo acima"
13103
- },
13104
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiArrowRight, { size: 14 })
13105
- ), /* @__PURE__ */ import_react27.default.createElement(
13106
- "button",
13107
- {
13108
- onClick: () => onOutdent(group.id),
13109
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13110
- title: "Desaninhar"
13111
- },
13112
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiArrowLeft, { size: 14 })
13113
- ), /* @__PURE__ */ import_react27.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react27.default.createElement(
13114
- "button",
13115
- {
13116
- onClick: () => onDelete(group.id),
13117
- className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13118
- title: "Remover Grupo"
13119
- },
13120
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiTrash2, { size: 14 })
13121
- )))
13122
- ), group.children && group.children.length > 0 && /* @__PURE__ */ import_react27.default.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ import_react27.default.createElement(
13293
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiPlus, { size: 14 })
13294
+ )), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react29.default.createElement(
13295
+ "button",
13296
+ {
13297
+ onClick: () => onIndent(group.id),
13298
+ disabled: !canIndent,
13299
+ className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13300
+ title: "Aninhar no grupo acima"
13301
+ },
13302
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowRight, { size: 14 })
13303
+ ), /* @__PURE__ */ import_react29.default.createElement(
13304
+ "button",
13305
+ {
13306
+ onClick: () => onOutdent(group.id),
13307
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13308
+ title: "Desaninhar"
13309
+ },
13310
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowLeft, { size: 14 })
13311
+ ), /* @__PURE__ */ import_react29.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react29.default.createElement(
13312
+ "button",
13313
+ {
13314
+ onClick: () => onDelete(group.id),
13315
+ className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13316
+ title: "Remover Grupo"
13317
+ },
13318
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiTrash2, { size: 14 })
13319
+ )))), group.children && group.children.length > 0 && /* @__PURE__ */ import_react29.default.createElement("div", { className: "ml-2" }, group.children.map((child, idx) => /* @__PURE__ */ import_react29.default.createElement(
13123
13320
  GroupItem,
13124
13321
  {
13125
- key: childGroup.id,
13322
+ key: child.id,
13126
13323
  index: idx,
13127
- group: childGroup,
13128
- siblings: group.children,
13324
+ group: child,
13129
13325
  onUpdate,
13130
13326
  onDelete,
13131
13327
  onAddSubgroup,
13132
13328
  onIndent,
13133
13329
  onOutdent,
13134
- onRemoveAncestry,
13135
- onRequestPickAncestry,
13136
- pickingGroupId,
13137
- onPlayAncestry,
13138
- availableIds,
13330
+ searchItems,
13331
+ onMentionClick,
13139
13332
  canEdit
13140
13333
  }
13141
13334
  ))));
@@ -13150,168 +13343,104 @@ function AncestryBoard({
13150
13343
  onSave,
13151
13344
  userRole
13152
13345
  }) {
13153
- const [searchTerm, setSearchTerm] = (0, import_react27.useState)("");
13154
- const [groups, setGroups] = (0, import_react27.useState)([]);
13155
- const [isLoaded, setIsLoaded] = (0, import_react27.useState)(false);
13156
- const [pickingGroupId, setPickingGroupId] = (0, import_react27.useState)(null);
13157
- const [saveStatus, setSaveStatus] = (0, import_react27.useState)("idle");
13158
- const canEdit = (0, import_react27.useMemo)(() => {
13159
- return userRole !== "viewer";
13160
- }, [userRole]);
13161
- (0, import_react27.useEffect)(() => {
13346
+ const [groups, setGroups] = (0, import_react29.useState)([]);
13347
+ const [isLoaded, setIsLoaded] = (0, import_react29.useState)(false);
13348
+ const [saveStatus, setSaveStatus] = (0, import_react29.useState)("idle");
13349
+ const canEdit = (0, import_react29.useMemo)(() => userRole !== "viewer", [userRole]);
13350
+ (0, import_react29.useEffect)(() => {
13162
13351
  if (initialGroups && !isLoaded) {
13163
- setGroups(initialGroups);
13352
+ const migrate = (list) => list.map((g) => ({
13353
+ id: g.id || (0, import_uuid11.v4)(),
13354
+ content: Array.isArray(g.content) ? g.content : [],
13355
+ // descarta dados legados
13356
+ children: migrate(g.children || [])
13357
+ }));
13358
+ setGroups(migrate(initialGroups));
13164
13359
  setIsLoaded(true);
13165
13360
  }
13166
13361
  }, [initialGroups, isLoaded]);
13167
- const nodeNamesMap = (0, import_react27.useMemo)(() => {
13168
- const map = /* @__PURE__ */ new Map();
13169
- if (availableNodes && Array.isArray(availableNodes)) {
13170
- availableNodes.forEach((node) => {
13171
- if (node && node.id) {
13172
- map.set(String(node.id), node.name);
13173
- }
13362
+ const allSearchableItems = (0, import_react29.useMemo)(() => {
13363
+ const items = [];
13364
+ availableAncestries.forEach((anc) => {
13365
+ items.push({
13366
+ ...anc,
13367
+ id: String(anc.ancestry_id),
13368
+ type: "ancestry",
13369
+ searchLabel: anc.name || "",
13370
+ searchDesc: anc.description || ""
13174
13371
  });
13175
- }
13176
- return map;
13177
- }, [availableNodes]);
13178
- const availableIds = (0, import_react27.useMemo)(() => {
13179
- return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
13180
- }, [availableAncestries]);
13181
- const allMentionableItems = (0, import_react27.useMemo)(() => {
13182
- const ancestries = availableAncestries.map((a) => ({
13183
- id: String(a.ancestry_id),
13184
- ancestry_id: a.ancestry_id,
13185
- name: a.name,
13186
- description: a.description,
13187
- type: "ancestry",
13188
- ancestral_node: a.ancestral_node,
13189
- is_private: a.is_private
13190
- }));
13191
- const nodes = availableNodes.map((n) => {
13372
+ });
13373
+ availableNodes.forEach((node) => {
13374
+ var _a;
13192
13375
  let type = "node";
13193
- if (n.is_quest) type = "quest";
13194
- else if (n.is_version) type = "version";
13195
- return {
13196
- id: String(n.id),
13197
- name: n.name,
13198
- description: n.description,
13376
+ if (node.is_quest) type = "quest";
13377
+ else if ((_a = node.version_node) == null ? void 0 : _a.is_version) type = "version";
13378
+ items.push({
13379
+ ...node,
13380
+ id: String(node.id),
13199
13381
  type,
13200
- raw_node: n
13201
- };
13382
+ searchLabel: node.name || node.raw_title || "",
13383
+ searchDesc: node.description || ""
13384
+ });
13202
13385
  });
13203
- return [...ancestries, ...nodes];
13386
+ return items;
13204
13387
  }, [availableAncestries, availableNodes]);
13205
- const sanitizeGroups = (groupList) => {
13206
- return groupList.map((g) => ({
13207
- id: g.id,
13208
- text: g.text || "",
13209
- ancestries: (g.ancestries || []).map((a) => ({
13210
- id: a.id || a.ancestry_id,
13211
- ancestry_id: a.ancestry_id,
13212
- name: a.name,
13213
- type: a.type || "ancestry"
13214
- })),
13215
- children: sanitizeGroups(g.children || [])
13216
- }));
13217
- };
13218
- (0, import_react27.useEffect)(() => {
13388
+ const sanitizeGroups = (list) => list.map((g) => ({
13389
+ id: g.id,
13390
+ content: g.content || [],
13391
+ children: sanitizeGroups(g.children || [])
13392
+ }));
13393
+ (0, import_react29.useEffect)(() => {
13219
13394
  if (!isLoaded || !onSave) return;
13220
- const timeoutId = setTimeout(async () => {
13395
+ const id = setTimeout(async () => {
13221
13396
  setSaveStatus("saving");
13222
- const cleanData = sanitizeGroups(groups);
13223
13397
  try {
13224
- await onSave(cleanData);
13398
+ await onSave(sanitizeGroups(groups));
13225
13399
  setSaveStatus("saved");
13226
- setTimeout(() => {
13227
- setSaveStatus("idle");
13228
- }, 3e3);
13229
- } catch (error) {
13230
- console.error("Erro ao salvar board:", error);
13400
+ setTimeout(() => setSaveStatus("idle"), 3e3);
13401
+ } catch (err) {
13402
+ console.error("Erro ao salvar board:", err);
13231
13403
  setSaveStatus("error");
13232
13404
  }
13233
13405
  }, 3e3);
13234
- return () => clearTimeout(timeoutId);
13406
+ return () => clearTimeout(id);
13235
13407
  }, [groups, isLoaded, onSave]);
13236
- (0, import_react27.useEffect)(() => {
13408
+ (0, import_react29.useEffect)(() => {
13237
13409
  if (!isOpen) return;
13238
- const handleKeyDown = (e) => {
13410
+ const handler = (e) => {
13239
13411
  if (e.key === "Escape") {
13240
- if (pickingGroupId) {
13241
- setPickingGroupId(null);
13242
- } else {
13243
- onClose();
13244
- }
13412
+ onClose();
13245
13413
  e.preventDefault();
13246
13414
  e.stopPropagation();
13247
13415
  }
13248
13416
  };
13249
- window.addEventListener("keydown", handleKeyDown);
13250
- return () => window.removeEventListener("keydown", handleKeyDown);
13251
- }, [isOpen, onClose, pickingGroupId]);
13252
- const filtered = (0, import_react27.useMemo)(() => {
13253
- const term = searchTerm.toLowerCase().trim();
13254
- return allMentionableItems.filter((item) => {
13255
- if (!term) return true;
13256
- const nameMatch = item.name && item.name.toLowerCase().includes(term);
13257
- const descMatch = item.description && item.description.toLowerCase().includes(term);
13258
- let parentMatch = false;
13259
- if (item.type === "ancestry") {
13260
- const parentName = nodeNamesMap.get(String(item.ancestral_node)) || "";
13261
- parentMatch = parentName.toLowerCase().includes(term);
13262
- }
13263
- return nameMatch || descMatch || parentMatch;
13264
- });
13265
- }, [allMentionableItems, searchTerm, nodeNamesMap]);
13417
+ window.addEventListener("keydown", handler);
13418
+ return () => window.removeEventListener("keydown", handler);
13419
+ }, [isOpen, onClose]);
13266
13420
  const handleAddRootGroup = () => {
13267
- const newGroup = {
13268
- id: v4_default(),
13269
- text: "",
13270
- ancestries: [],
13271
- children: []
13272
- };
13273
- setGroups((prev) => [newGroup, ...prev]);
13421
+ setGroups((prev) => [{ id: (0, import_uuid11.v4)(), content: [], children: [] }, ...prev]);
13274
13422
  };
13275
13423
  const handleAddSubgroup = (parentId) => {
13276
- const newGroup = {
13277
- id: v4_default(),
13278
- text: "",
13279
- ancestries: [],
13280
- children: []
13281
- };
13282
- const addRecursive = (list) => {
13283
- return list.map((g) => {
13284
- if (g.id === parentId) {
13285
- return { ...g, children: [newGroup, ...g.children] };
13286
- }
13287
- return { ...g, children: addRecursive(g.children) };
13288
- });
13289
- };
13290
- setGroups((prev) => addRecursive(prev));
13424
+ const newGroup = { id: (0, import_uuid11.v4)(), content: [], children: [] };
13425
+ const add = (list) => list.map(
13426
+ (g) => g.id === parentId ? { ...g, children: [newGroup, ...g.children] } : { ...g, children: add(g.children) }
13427
+ );
13428
+ setGroups((prev) => add(prev));
13291
13429
  };
13292
13430
  const handleUpdateGroup = (id, newData) => {
13293
- const updateRecursive = (list) => {
13294
- return list.map((g) => {
13295
- if (g.id === id) return newData;
13296
- return { ...g, children: updateRecursive(g.children) };
13297
- });
13298
- };
13299
- setGroups((prev) => updateRecursive(prev));
13431
+ const update = (list) => list.map(
13432
+ (g) => g.id === id ? newData : { ...g, children: update(g.children) }
13433
+ );
13434
+ setGroups((prev) => update(prev));
13300
13435
  };
13301
13436
  const handleDeleteGroup = (id) => {
13302
- const deleteRecursive = (list) => {
13303
- return list.filter((g) => g.id !== id).map((g) => ({
13304
- ...g,
13305
- children: deleteRecursive(g.children)
13306
- }));
13307
- };
13308
- setGroups((prev) => deleteRecursive(prev));
13437
+ const del = (list) => list.filter((g) => g.id !== id).map((g) => ({ ...g, children: del(g.children) }));
13438
+ setGroups((prev) => del(prev));
13309
13439
  };
13310
13440
  const findGroupAndParent = (list, targetId, parent = null) => {
13311
13441
  for (let i = 0; i < list.length; i++) {
13312
- if (list[i].id === targetId) {
13442
+ if (list[i].id === targetId)
13313
13443
  return { group: list[i], parent, index: i, siblings: list };
13314
- }
13315
13444
  if (list[i].children.length > 0) {
13316
13445
  const found = findGroupAndParent(list[i].children, targetId, list[i]);
13317
13446
  if (found) return found;
@@ -13321,258 +13450,87 @@ function AncestryBoard({
13321
13450
  };
13322
13451
  const handleIndent = (id) => {
13323
13452
  setGroups((prev) => {
13324
- const newList = JSON.parse(JSON.stringify(prev));
13325
- const found = findGroupAndParent(newList, id);
13453
+ const next = JSON.parse(JSON.stringify(prev));
13454
+ const found = findGroupAndParent(next, id);
13326
13455
  if (!found || found.index === 0) return prev;
13327
13456
  const { group, siblings, index } = found;
13328
- const prevSibling = siblings[index - 1];
13329
13457
  siblings.splice(index, 1);
13330
- prevSibling.children.push(group);
13331
- return newList;
13458
+ siblings[index - 1].children.push(group);
13459
+ return next;
13332
13460
  });
13333
13461
  };
13334
13462
  const handleOutdent = (id) => {
13335
13463
  setGroups((prev) => {
13336
- const newList = JSON.parse(JSON.stringify(prev));
13337
- const found = findGroupAndParent(newList, id);
13464
+ const next = JSON.parse(JSON.stringify(prev));
13465
+ const found = findGroupAndParent(next, id);
13338
13466
  if (!found || !found.parent) return prev;
13339
13467
  const { group, siblings, index, parent } = found;
13340
13468
  siblings.splice(index, 1);
13341
- const parentFound = findGroupAndParent(newList, parent.id);
13469
+ const parentFound = findGroupAndParent(next, parent.id);
13342
13470
  if (parentFound) {
13343
13471
  parentFound.siblings.splice(parentFound.index + 1, 0, group);
13344
13472
  } else {
13345
- newList.push(group);
13473
+ next.push(group);
13346
13474
  }
13347
- return newList;
13475
+ return next;
13348
13476
  });
13349
13477
  };
13350
- const handleRequestPick = (groupId) => {
13351
- setPickingGroupId((prev) => prev === groupId ? null : groupId);
13352
- };
13353
- const handleSelectAncestry = (item) => {
13354
- if (pickingGroupId) {
13355
- setGroups((prev) => {
13356
- const addRecursive = (list) => {
13357
- return list.map((g) => {
13358
- if (g.id === pickingGroupId) {
13359
- const currentId = item.id;
13360
- const exists = g.ancestries.some(
13361
- (a) => (a.id || a.ancestry_id) === currentId && a.type === item.type
13362
- );
13363
- if (exists) return g;
13364
- return { ...g, ancestries: [...g.ancestries, item] };
13365
- }
13366
- return { ...g, children: addRecursive(g.children) };
13367
- });
13368
- };
13369
- return addRecursive(prev);
13370
- });
13371
- setPickingGroupId(null);
13372
- } else {
13373
- let fullItem = item;
13374
- if (item.type === "ancestry" || !item.type) {
13375
- fullItem = availableAncestries.find(
13376
- (a) => String(a.ancestry_id) === String(item.id || item.ancestry_id)
13377
- ) || item;
13378
- } else {
13379
- fullItem = availableNodes.find(
13380
- (n) => String(n.id) === String(item.id)
13381
- ) || item;
13382
- }
13383
- onSelect(fullItem);
13384
- }
13385
- };
13386
- const handlePlayFromGroup = (item) => {
13387
- let fullItem = item;
13388
- if (item.type === "ancestry" || !item.type) {
13389
- fullItem = availableAncestries.find(
13390
- (a) => String(a.ancestry_id) === String(item.id || item.ancestry_id)
13391
- ) || item;
13392
- } else {
13393
- fullItem = availableNodes.find(
13394
- (n) => String(n.id) === String(item.id)
13395
- ) || item;
13396
- }
13397
- if (fullItem && onSelect) {
13398
- onSelect(fullItem);
13399
- }
13400
- };
13401
- const handleRemoveAncestryFromGroup = (groupId, itemId) => {
13402
- setGroups((prev) => {
13403
- const removeRecursive = (list) => {
13404
- return list.map((g) => {
13405
- if (g.id === groupId) {
13406
- return {
13407
- ...g,
13408
- ancestries: g.ancestries.filter(
13409
- (a) => (a.id || a.ancestry_id) !== itemId
13410
- )
13411
- };
13412
- }
13413
- return { ...g, children: removeRecursive(g.children) };
13414
- });
13415
- };
13416
- return removeRecursive(prev);
13417
- });
13478
+ const handleMentionClick = (item) => {
13479
+ if (onSelect) onSelect(item);
13418
13480
  };
13419
13481
  if (!isOpen) return null;
13420
- return /* @__PURE__ */ import_react27.default.createElement(
13482
+ return /* @__PURE__ */ import_react29.default.createElement(
13421
13483
  "div",
13422
13484
  {
13423
13485
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
13424
13486
  onClick: onClose
13425
13487
  },
13426
- /* @__PURE__ */ import_react27.default.createElement(
13488
+ /* @__PURE__ */ import_react29.default.createElement(
13427
13489
  "div",
13428
13490
  {
13429
13491
  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",
13430
13492
  onClick: (e) => e.stopPropagation()
13431
13493
  },
13432
- /* @__PURE__ */ import_react27.default.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react27.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react27.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react27.default.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__ */ import_react27.default.createElement(import_react27.default.Fragment, null, /* @__PURE__ */ import_react27.default.createElement(
13433
- import_fi22.FiLoader,
13434
- {
13435
- className: "animate-spin text-indigo-400",
13436
- size: 12
13437
- }
13438
- ), /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ import_react27.default.createElement(import_react27.default.Fragment, null, /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ import_react27.default.createElement(import_react27.default.Fragment, null, /* @__PURE__ */ import_react27.default.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-xs text-indigo-300 font-medium animate-pulse hidden sm:inline-block mr-2" }, "Selecione na lateral..."), canEdit && /* @__PURE__ */ import_react27.default.createElement(
13494
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react29.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react29.default.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__ */ import_react29.default.createElement(import_react29.default.Fragment, null, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiLoader, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ import_react29.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ import_react29.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, /* @__PURE__ */ import_react29.default.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ import_react29.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-3" }, canEdit && /* @__PURE__ */ import_react29.default.createElement(
13439
13495
  "button",
13440
13496
  {
13441
13497
  onClick: handleAddRootGroup,
13442
- 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 "
13498
+ className: "flex items-center gap-2 px-3 py-1.5 bg-white/5 hover:bg-white/10 border border-white/10 hover:border-white/20 backdrop-blur-sm text-slate-200 hover:text-white rounded-md transition-all duration-200 text-xs font-medium shadow-sm"
13443
13499
  },
13444
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiPlus, { size: 14, className: "text-indigo-400" }),
13445
- /* @__PURE__ */ import_react27.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13446
- ), /* @__PURE__ */ import_react27.default.createElement(
13500
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiPlus, { size: 14, className: "text-indigo-400" }),
13501
+ /* @__PURE__ */ import_react29.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13502
+ ), /* @__PURE__ */ import_react29.default.createElement(
13447
13503
  "button",
13448
13504
  {
13449
13505
  onClick: onClose,
13450
13506
  className: "w-8 h-8 rounded-lg flex items-center justify-center text-slate-400 hover:text-white hover:bg-white/10 transition-colors"
13451
13507
  },
13452
- "\xD7"
13508
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiX, { size: 16 })
13453
13509
  ))),
13454
- /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react27.default.createElement(
13455
- "div",
13456
- {
13457
- className: `
13458
- flex flex-col border-r border-white/10 transition-all duration-300 flex-none
13459
- ${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
13460
- min-w-[280px] max-w-[500px] bg-slate-900
13461
- `
13462
- },
13463
- /* @__PURE__ */ import_react27.default.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ import_react27.default.createElement("div", { className: "relative group" }, /* @__PURE__ */ import_react27.default.createElement(
13464
- import_fi22.FiSearch,
13465
- {
13466
- 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"}`
13467
- }
13468
- ), /* @__PURE__ */ import_react27.default.createElement(
13469
- "input",
13470
- {
13471
- type: "text",
13472
- placeholder: pickingGroupId ? "Pesquise para adicionar..." : "Pesquisar (Ancestralidades e Nodes)",
13473
- className: `
13474
- 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
13475
- ${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"}
13476
- `,
13477
- value: searchTerm,
13478
- onChange: (e) => setSearchTerm(e.target.value),
13479
- autoFocus: !pickingGroupId
13480
- }
13481
- ))),
13482
- /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((item) => {
13483
- const isPicking = !!pickingGroupId;
13484
- const isQuest = item.type === "quest";
13485
- const isVersion = item.type === "version";
13486
- const isNode = item.type === "node";
13487
- let Icon = import_fi22.FiLayers;
13488
- let colorClass = "bg-slate-800 text-indigo-400 border-white/5";
13489
- let pickingColorClass = "bg-indigo-500 text-white border-indigo-400";
13490
- let hoverClass = "hover:bg-indigo-600/10 hover:border-indigo-500/30";
13491
- let badge = null;
13492
- if (isQuest) {
13493
- Icon = import_fi22.FiCheckSquare;
13494
- colorClass = "bg-slate-800 text-amber-400 border-white/5";
13495
- pickingColorClass = "bg-amber-500 text-white border-amber-400";
13496
- hoverClass = "hover:bg-amber-500/10 hover:border-amber-500/30";
13497
- badge = "Quest";
13498
- } else if (isVersion) {
13499
- Icon = import_fi22.FiGitBranch;
13500
- colorClass = "bg-slate-800 text-purple-400 border-white/5";
13501
- pickingColorClass = "bg-purple-500 text-white border-purple-400";
13502
- hoverClass = "hover:bg-purple-500/10 hover:border-purple-500/30";
13503
- badge = "Ver";
13504
- } else if (isNode) {
13505
- Icon = import_fi22.FiBox;
13506
- colorClass = "bg-slate-800 text-emerald-400 border-white/5";
13507
- pickingColorClass = "bg-emerald-500 text-white border-emerald-400";
13508
- hoverClass = "hover:bg-emerald-500/10 hover:border-emerald-500/30";
13509
- badge = "Node";
13510
- }
13511
- return /* @__PURE__ */ import_react27.default.createElement(
13512
- "div",
13513
- {
13514
- key: `${item.type}-${item.id}`,
13515
- onClick: () => {
13516
- if (isPicking) handleSelectAncestry(item);
13517
- },
13518
- className: `
13519
- group relative flex items-start gap-3 p-3 text-left rounded-lg border transition-all duration-200
13520
- ${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`}
13521
- `
13522
- },
13523
- /* @__PURE__ */ import_react27.default.createElement(
13524
- "div",
13525
- {
13526
- className: `
13527
- mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
13528
- ${isPicking ? pickingColorClass : `${colorClass} group-hover:bg-opacity-80`}
13529
- `
13530
- },
13531
- isPicking ? /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiPlus, { size: 16 }) : /* @__PURE__ */ import_react27.default.createElement(Icon, { size: 14 })
13532
- ),
13533
- /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react27.default.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, item.name || "Sem Nome"), badge && /* @__PURE__ */ import_react27.default.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__ */ import_react27.default.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__ */ import_react27.default.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__ */ import_react27.default.createElement(import_fi22.FiCornerUpRight, { size: 10 }), /* @__PURE__ */ import_react27.default.createElement("span", { className: "truncate max-w-[120px]" }, nodeNamesMap.get(String(item.ancestral_node)) || "Node Desconhecido")), item.description && /* @__PURE__ */ import_react27.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, item.description)),
13534
- !isPicking && /* @__PURE__ */ import_react27.default.createElement(
13535
- "button",
13536
- {
13537
- onClick: (e) => {
13538
- e.stopPropagation();
13539
- handleSelectAncestry(item);
13540
- },
13541
- 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",
13542
- title: "Renderizar / Focar"
13543
- },
13544
- /* @__PURE__ */ import_react27.default.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiPlay, { size: 14, className: "ml-0.5" }))
13545
- )
13546
- );
13547
- }))
13548
- ), /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ import_react27.default.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__ */ import_react27.default.createElement(import_fi22.FiLayers, { size: 24, className: "opacity-20" }), /* @__PURE__ */ import_react27.default.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ import_react27.default.createElement(import_react27.default.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ import_react27.default.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ import_react27.default.createElement(import_react27.default.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ import_react27.default.createElement(
13510
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar bg-slate-950/30 p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ import_react29.default.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__ */ import_react29.default.createElement(import_fi23.FiLayers, { size: 24, className: "opacity-20" }), /* @__PURE__ */ import_react29.default.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ import_react29.default.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ import_react29.default.createElement(
13549
13511
  GroupItem,
13550
13512
  {
13551
13513
  key: group.id,
13552
13514
  index,
13553
13515
  group,
13554
- siblings: groups,
13555
13516
  onUpdate: handleUpdateGroup,
13556
13517
  onDelete: handleDeleteGroup,
13557
13518
  onAddSubgroup: handleAddSubgroup,
13558
13519
  onIndent: handleIndent,
13559
13520
  onOutdent: handleOutdent,
13560
- onRemoveAncestry: handleRemoveAncestryFromGroup,
13561
- onRequestPickAncestry: handleRequestPick,
13562
- pickingGroupId,
13563
- onPlayAncestry: handlePlayFromGroup,
13564
- availableIds,
13521
+ searchItems: allSearchableItems,
13522
+ onMentionClick: handleMentionClick,
13565
13523
  canEdit
13566
13524
  }
13567
- ))))),
13568
- /* @__PURE__ */ import_react27.default.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__ */ import_react27.default.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ import_react27.default.createElement("span", null, groups.length, " grupos raiz"))
13525
+ ))),
13526
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "px-5 py-2 border-t border-white/10 bg-slate-950/50 text-xs text-slate-500 flex justify-end flex-shrink-0" }, /* @__PURE__ */ import_react29.default.createElement("span", null, groups.length, " grupos raiz"))
13569
13527
  )
13570
13528
  );
13571
13529
  }
13572
13530
 
13573
13531
  // src/components/MilestoneManager.jsx
13574
- var import_react28 = __toESM(require("react"));
13575
- var import_fi23 = require("react-icons/fi");
13532
+ var import_react30 = __toESM(require("react"));
13533
+ var import_fi24 = require("react-icons/fi");
13576
13534
  function MilestoneManager({
13577
13535
  isOpen,
13578
13536
  onClose,
@@ -13580,7 +13538,7 @@ function MilestoneManager({
13580
13538
  onUpdateMilestones = () => {
13581
13539
  }
13582
13540
  }) {
13583
- const [newMilestoneName, setNewMilestoneName] = (0, import_react28.useState)("");
13541
+ const [newMilestoneName, setNewMilestoneName] = (0, import_react30.useState)("");
13584
13542
  const handleAddMilestone = () => {
13585
13543
  if (!newMilestoneName.trim()) return;
13586
13544
  const newMilestone = {
@@ -13605,27 +13563,27 @@ function MilestoneManager({
13605
13563
  };
13606
13564
  if (!isOpen) return null;
13607
13565
  const swallow = (e) => e.stopPropagation();
13608
- return /* @__PURE__ */ import_react28.default.createElement(
13566
+ return /* @__PURE__ */ import_react30.default.createElement(
13609
13567
  "div",
13610
13568
  {
13611
13569
  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",
13612
13570
  onClick: onClose
13613
13571
  },
13614
- /* @__PURE__ */ import_react28.default.createElement(
13572
+ /* @__PURE__ */ import_react30.default.createElement(
13615
13573
  "div",
13616
13574
  {
13617
13575
  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",
13618
13576
  onClick: swallow
13619
13577
  },
13620
- /* @__PURE__ */ import_react28.default.createElement("div", { className: "px-6 py-4 border-b border-white/10 flex items-center justify-between" }, /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ import_react28.default.createElement("div", { className: "p-2 rounded-lg bg-indigo-500/20 text-indigo-400" }, /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiTarget, { size: 20 })), /* @__PURE__ */ import_react28.default.createElement("div", null, /* @__PURE__ */ import_react28.default.createElement("h2", { className: "text-lg font-semibold text-slate-100" }, "Milestones"), /* @__PURE__ */ import_react28.default.createElement("p", { className: "text-xs text-slate-400" }, "Gerencie os marcos do seu cen\xE1rio"))), /* @__PURE__ */ import_react28.default.createElement(
13578
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "px-6 py-4 border-b border-white/10 flex items-center justify-between" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "p-2 rounded-lg bg-indigo-500/20 text-indigo-400" }, /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiTarget, { size: 20 })), /* @__PURE__ */ import_react30.default.createElement("div", null, /* @__PURE__ */ import_react30.default.createElement("h2", { className: "text-lg font-semibold text-slate-100" }, "Milestones"), /* @__PURE__ */ import_react30.default.createElement("p", { className: "text-xs text-slate-400" }, "Gerencie os marcos do seu cen\xE1rio"))), /* @__PURE__ */ import_react30.default.createElement(
13621
13579
  "button",
13622
13580
  {
13623
13581
  onClick: onClose,
13624
13582
  className: "p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
13625
13583
  },
13626
- /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiX, { size: 20 })
13584
+ /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiX, { size: 20 })
13627
13585
  )),
13628
- /* @__PURE__ */ import_react28.default.createElement("div", { className: "px-6 py-5 bg-white/5 border-b border-white/5" }, /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ import_react28.default.createElement(
13586
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "px-6 py-5 bg-white/5 border-b border-white/5" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ import_react30.default.createElement(
13629
13587
  "input",
13630
13588
  {
13631
13589
  type: "text",
@@ -13635,47 +13593,47 @@ function MilestoneManager({
13635
13593
  placeholder: "Adicionar novo milestone...",
13636
13594
  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"
13637
13595
  }
13638
- ), /* @__PURE__ */ import_react28.default.createElement(
13596
+ ), /* @__PURE__ */ import_react30.default.createElement(
13639
13597
  "button",
13640
13598
  {
13641
13599
  onClick: handleAddMilestone,
13642
13600
  disabled: !newMilestoneName.trim(),
13643
13601
  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"
13644
13602
  },
13645
- /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiPlus, { size: 18 }),
13603
+ /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiPlus, { size: 18 }),
13646
13604
  "Adicionar"
13647
13605
  ))),
13648
- /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex-1 overflow-y-auto px-6 py-4 custom-scrollbar" }, milestones.length > 0 ? /* @__PURE__ */ import_react28.default.createElement("div", { className: "space-y-3" }, milestones.map((ms) => /* @__PURE__ */ import_react28.default.createElement(
13606
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex-1 overflow-y-auto px-6 py-4 custom-scrollbar" }, milestones.length > 0 ? /* @__PURE__ */ import_react30.default.createElement("div", { className: "space-y-3" }, milestones.map((ms) => /* @__PURE__ */ import_react30.default.createElement(
13649
13607
  "div",
13650
13608
  {
13651
13609
  key: ms.id,
13652
13610
  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]"}`
13653
13611
  },
13654
- /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ import_react28.default.createElement(
13612
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ import_react30.default.createElement(
13655
13613
  "div",
13656
13614
  {
13657
13615
  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"}`
13658
13616
  }
13659
- ), /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ import_react28.default.createElement("span", { className: `text-sm font-medium truncate ${ms.status === "active" ? "text-slate-100" : "text-slate-400 line-through"}` }, ms.name), /* @__PURE__ */ import_react28.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, ms.status === "active" ? "Ativo" : "Inativo"))),
13660
- /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react28.default.createElement(
13617
+ ), /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ import_react30.default.createElement("span", { className: `text-sm font-medium truncate ${ms.status === "active" ? "text-slate-100" : "text-slate-400 line-through"}` }, ms.name), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, ms.status === "active" ? "Ativo" : "Inativo"))),
13618
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react30.default.createElement(
13661
13619
  "button",
13662
13620
  {
13663
13621
  onClick: () => handleToggleMilestoneStatus(ms.id),
13664
13622
  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"}`,
13665
13623
  title: ms.status === "active" ? "Inativar" : "Ativar"
13666
13624
  },
13667
- ms.status === "active" ? /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiPauseCircle, { size: 18 }) : /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiPlayCircle, { size: 18 })
13668
- ), /* @__PURE__ */ import_react28.default.createElement(
13625
+ ms.status === "active" ? /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiPauseCircle, { size: 18 }) : /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiPlayCircle, { size: 18 })
13626
+ ), /* @__PURE__ */ import_react30.default.createElement(
13669
13627
  "button",
13670
13628
  {
13671
13629
  onClick: () => handleRemoveMilestone(ms.id),
13672
13630
  className: "p-2 rounded-lg hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-all",
13673
13631
  title: "Remover"
13674
13632
  },
13675
- /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiTrash2, { size: 18 })
13633
+ /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiTrash2, { size: 18 })
13676
13634
  ))
13677
- ))) : /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex flex-col items-center justify-center py-12 text-center" }, /* @__PURE__ */ import_react28.default.createElement("div", { className: "p-4 rounded-full bg-slate-800/30 text-slate-600 mb-4" }, /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiTarget, { size: 40 })), /* @__PURE__ */ import_react28.default.createElement("h3", { className: "text-slate-400 font-medium" }, "Nenhum milestone definido"), /* @__PURE__ */ import_react28.default.createElement("p", { className: "text-xs text-slate-600 max-w-[200px] mt-1 italic" }, "Defina marcos importantes para orientar o progresso do projeto."))),
13678
- /* @__PURE__ */ import_react28.default.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__ */ import_react28.default.createElement("div", { className: "flex gap-4" }, /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react28.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Total:"), /* @__PURE__ */ import_react28.default.createElement("span", { className: "text-xs font-bold text-slate-300" }, milestones.length)), /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react28.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Ativos:"), /* @__PURE__ */ import_react28.default.createElement("span", { className: "text-xs font-bold text-indigo-400" }, milestones.filter((m) => m.status === "active").length))))
13635
+ ))) : /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-col items-center justify-center py-12 text-center" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "p-4 rounded-full bg-slate-800/30 text-slate-600 mb-4" }, /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiTarget, { size: 40 })), /* @__PURE__ */ import_react30.default.createElement("h3", { className: "text-slate-400 font-medium" }, "Nenhum milestone definido"), /* @__PURE__ */ import_react30.default.createElement("p", { className: "text-xs text-slate-600 max-w-[200px] mt-1 italic" }, "Defina marcos importantes para orientar o progresso do projeto."))),
13636
+ /* @__PURE__ */ import_react30.default.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__ */ import_react30.default.createElement("div", { className: "flex gap-4" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Total:"), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-xs font-bold text-slate-300" }, milestones.length)), /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Ativos:"), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-xs font-bold text-indigo-400" }, milestones.filter((m) => m.status === "active").length))))
13679
13637
  )
13680
13638
  );
13681
13639
  }
@@ -13761,13 +13719,13 @@ function XViewScene({
13761
13719
  check_user_permission,
13762
13720
  get_view_members
13763
13721
  }) {
13764
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
13765
- const { data: session, status } = (0, import_react30.useSession)();
13722
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
13723
+ const { data: session, status } = (0, import_react32.useSession)();
13766
13724
  const router = (0, import_navigation.useRouter)();
13767
13725
  const searchParams = (0, import_navigation.useSearchParams)();
13768
13726
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
13769
13727
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
13770
- const viewParams = (0, import_react29.useMemo)(() => {
13728
+ const viewParams = (0, import_react31.useMemo)(() => {
13771
13729
  if (encryptedConfig) {
13772
13730
  const data = decryptData(encryptedConfig);
13773
13731
  if (data) {
@@ -13776,7 +13734,7 @@ function XViewScene({
13776
13734
  }
13777
13735
  return null;
13778
13736
  }, [encryptedConfig, session]);
13779
- (0, import_react29.useEffect)(() => {
13737
+ (0, import_react31.useEffect)(() => {
13780
13738
  async function verifyPermission() {
13781
13739
  if (!viewParams || !session || !check_user_permission) return;
13782
13740
  const { id, type, owner_id } = viewParams;
@@ -13813,65 +13771,65 @@ function XViewScene({
13813
13771
  setIsLoading(false);
13814
13772
  }
13815
13773
  }, [viewParams, session, status, check_user_permission]);
13816
- const sceneConfigId = (0, import_react29.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13817
- const ownerId = (0, import_react29.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13818
- const dbSaveUrl = (0, import_react29.useMemo)(() => {
13774
+ const sceneConfigId = (0, import_react31.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13775
+ const ownerId = (0, import_react31.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13776
+ const dbSaveUrl = (0, import_react31.useMemo)(() => {
13819
13777
  if (ownerId && sceneConfigId) {
13820
13778
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
13821
13779
  }
13822
13780
  return null;
13823
13781
  }, [ownerId, sceneConfigId]);
13824
- const sceneSaveUrl = (0, import_react29.useMemo)(() => {
13782
+ const sceneSaveUrl = (0, import_react31.useMemo)(() => {
13825
13783
  if (ownerId && sceneConfigId) {
13826
13784
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
13827
13785
  }
13828
13786
  return null;
13829
13787
  }, [ownerId, sceneConfigId]);
13830
- const ancestry_save_url = (0, import_react29.useMemo)(() => {
13788
+ const ancestry_save_url = (0, import_react31.useMemo)(() => {
13831
13789
  if (ownerId && sceneConfigId) {
13832
13790
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
13833
13791
  }
13834
13792
  return null;
13835
13793
  }, [ownerId, sceneConfigId]);
13836
- const sceneDataRef = (0, import_react29.useRef)(null);
13837
- const parentDataRef = (0, import_react29.useRef)(null);
13838
- const ancestryDataRef = (0, import_react29.useRef)(null);
13839
- const [isLoading, setIsLoading] = (0, import_react29.useState)(true);
13840
- const [permissionStatus, setPermissionStatus] = (0, import_react29.useState)("loading");
13841
- const [userPermissionRole, setUserPermissionRole] = (0, import_react29.useState)(null);
13842
- const [viewMembers, setViewMembers] = (0, import_react29.useState)([]);
13843
- const [isInitialized, setIsInitialized] = (0, import_react29.useState)(false);
13844
- const [sceneVersion, setSceneVersion] = (0, import_react29.useState)(0);
13845
- const [contextMenu, setContextMenu] = (0, import_react29.useState)({
13794
+ const sceneDataRef = (0, import_react31.useRef)(null);
13795
+ const parentDataRef = (0, import_react31.useRef)(null);
13796
+ const ancestryDataRef = (0, import_react31.useRef)(null);
13797
+ const [isLoading, setIsLoading] = (0, import_react31.useState)(true);
13798
+ const [permissionStatus, setPermissionStatus] = (0, import_react31.useState)("loading");
13799
+ const [userPermissionRole, setUserPermissionRole] = (0, import_react31.useState)(null);
13800
+ const [viewMembers, setViewMembers] = (0, import_react31.useState)([]);
13801
+ const [isInitialized, setIsInitialized] = (0, import_react31.useState)(false);
13802
+ const [sceneVersion, setSceneVersion] = (0, import_react31.useState)(0);
13803
+ const [contextMenu, setContextMenu] = (0, import_react31.useState)({
13846
13804
  visible: false,
13847
13805
  x: 0,
13848
13806
  y: 0,
13849
13807
  nodeData: null
13850
13808
  });
13851
- const [multiContextMenu, setMultiContextMenu] = (0, import_react29.useState)({
13809
+ const [multiContextMenu, setMultiContextMenu] = (0, import_react31.useState)({
13852
13810
  visible: false,
13853
13811
  x: 0,
13854
13812
  y: 0,
13855
13813
  nodeIds: null
13856
13814
  });
13857
- const [relationshipMenu, setRelationshipMenu] = (0, import_react29.useState)({
13815
+ const [relationshipMenu, setRelationshipMenu] = (0, import_react31.useState)({
13858
13816
  visible: false,
13859
13817
  x: 0,
13860
13818
  y: 0,
13861
13819
  linkObject: null
13862
13820
  });
13863
- const [creationMode, setCreationMode] = (0, import_react29.useState)({
13821
+ const [creationMode, setCreationMode] = (0, import_react31.useState)({
13864
13822
  isActive: false,
13865
13823
  sourceNodeData: null
13866
13824
  });
13867
- const [versionMode, setVersionMode] = (0, import_react29.useState)({
13825
+ const [versionMode, setVersionMode] = (0, import_react31.useState)({
13868
13826
  isActive: false,
13869
13827
  sourceNodeData: null
13870
13828
  });
13871
- const [questMode, setQuestMode] = (0, import_react29.useState)({ isActive: false });
13872
- const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react29.useState)(false);
13873
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react29.useState)(false);
13874
- const [ancestryMode, setAncestryMode] = (0, import_react29.useState)({
13829
+ const [questMode, setQuestMode] = (0, import_react31.useState)({ isActive: false });
13830
+ const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react31.useState)(false);
13831
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react31.useState)(false);
13832
+ const [ancestryMode, setAncestryMode] = (0, import_react31.useState)({
13875
13833
  isActive: false,
13876
13834
  tree: null,
13877
13835
  selectedParentId: null,
@@ -13882,42 +13840,42 @@ function XViewScene({
13882
13840
  ancestryDescriptionSections: [],
13883
13841
  isAddingNodes: false
13884
13842
  });
13885
- const [readingMode, setReadingMode] = (0, import_react29.useState)({
13843
+ const [readingMode, setReadingMode] = (0, import_react31.useState)({
13886
13844
  isActive: false,
13887
13845
  ancestry: null,
13888
13846
  branchStack: [],
13889
13847
  autoAbstraction: false
13890
13848
  });
13891
- const [formPosition, setFormPosition] = (0, import_react29.useState)({
13849
+ const [formPosition, setFormPosition] = (0, import_react31.useState)({
13892
13850
  left: 16,
13893
13851
  top: 16,
13894
13852
  opacity: 0
13895
13853
  });
13896
- const [detailsNode, setDetailsNode] = (0, import_react29.useState)(null);
13897
- const [detailsLink, setDetailsLink] = (0, import_react29.useState)(null);
13898
- const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react29.useState)(null);
13899
- const [imageViewer, setImageViewer] = (0, import_react29.useState)({
13854
+ const [detailsNode, setDetailsNode] = (0, import_react31.useState)(null);
13855
+ const [detailsLink, setDetailsLink] = (0, import_react31.useState)(null);
13856
+ const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react31.useState)(null);
13857
+ const [imageViewer, setImageViewer] = (0, import_react31.useState)({
13900
13858
  visible: false,
13901
13859
  images: [],
13902
13860
  startIndex: 0
13903
13861
  });
13904
- const [editingAncestryRel, setEditingAncestryRel] = (0, import_react29.useState)({
13862
+ const [editingAncestryRel, setEditingAncestryRel] = (0, import_react31.useState)({
13905
13863
  visible: false,
13906
13864
  data: null,
13907
13865
  path: null
13908
13866
  });
13909
- const [isImportModalOpen, setIsImportModalOpen] = (0, import_react29.useState)(false);
13910
- const [importSuccessMessage, setImportSuccessMessage] = (0, import_react29.useState)("");
13911
- const [invalidTargetError, setInvalidTargetError] = (0, import_react29.useState)(null);
13912
- const [highlightedNodeId, setHighlightedNodeId] = (0, import_react29.useState)(null);
13913
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react29.useState)(false);
13914
- const [ancestryBoardData, setAncestryBoardData] = (0, import_react29.useState)([]);
13915
- const [isSidebarOpen, setIsSidebarOpen] = (0, import_react29.useState)(false);
13916
- const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = (0, import_react29.useState)(false);
13917
- const mountRef = (0, import_react29.useRef)(null);
13918
- const tooltipRef = (0, import_react29.useRef)(null);
13919
- const formRef = (0, import_react29.useRef)(null);
13920
- const stateRef = (0, import_react29.useRef)({
13867
+ const [isImportModalOpen, setIsImportModalOpen] = (0, import_react31.useState)(false);
13868
+ const [importSuccessMessage, setImportSuccessMessage] = (0, import_react31.useState)("");
13869
+ const [invalidTargetError, setInvalidTargetError] = (0, import_react31.useState)(null);
13870
+ const [highlightedNodeId, setHighlightedNodeId] = (0, import_react31.useState)(null);
13871
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react31.useState)(false);
13872
+ const [ancestryBoardData, setAncestryBoardData] = (0, import_react31.useState)([]);
13873
+ const [isSidebarOpen, setIsSidebarOpen] = (0, import_react31.useState)(false);
13874
+ const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = (0, import_react31.useState)(false);
13875
+ const mountRef = (0, import_react31.useRef)(null);
13876
+ const tooltipRef = (0, import_react31.useRef)(null);
13877
+ const formRef = (0, import_react31.useRef)(null);
13878
+ const stateRef = (0, import_react31.useRef)({
13921
13879
  readMode: {
13922
13880
  currentMaxIndex: 0,
13923
13881
  progressMap: {}
@@ -13981,10 +13939,10 @@ function XViewScene({
13981
13939
  minWidth: 320,
13982
13940
  maxWidth: maxReadPanelW
13983
13941
  });
13984
- (0, import_react29.useEffect)(() => {
13942
+ (0, import_react31.useEffect)(() => {
13985
13943
  stateRef.current.ancestry = ancestryMode;
13986
13944
  }, [ancestryMode]);
13987
- (0, import_react29.useEffect)(() => {
13945
+ (0, import_react31.useEffect)(() => {
13988
13946
  var _a2;
13989
13947
  if (!isInitialized) return;
13990
13948
  const map = /* @__PURE__ */ new Map();
@@ -14007,10 +13965,10 @@ function XViewScene({
14007
13965
  }
14008
13966
  stateRef.current.nodeIdToParentFileMap = map;
14009
13967
  }, [isInitialized, sceneVersion]);
14010
- const handleNavigateBack = (0, import_react29.useCallback)(() => {
13968
+ const handleNavigateBack = (0, import_react31.useCallback)(() => {
14011
13969
  router.push("/dashboard/scenes");
14012
13970
  }, [router]);
14013
- const handleConfirmImport = (0, import_react29.useCallback)(
13971
+ const handleConfirmImport = (0, import_react31.useCallback)(
14014
13972
  async (importPayload) => {
14015
13973
  var _a2, _b2;
14016
13974
  let files = [];
@@ -14138,7 +14096,7 @@ function XViewScene({
14138
14096
  const handleOpenImageViewer = (images, startIndex) => {
14139
14097
  setImageViewer({ visible: true, images, startIndex });
14140
14098
  };
14141
- const tweenToTarget = (0, import_react29.useCallback)(
14099
+ const tweenToTarget = (0, import_react31.useCallback)(
14142
14100
  (target, zoomFactor = 1, forcedDirection = null) => {
14143
14101
  const { camera, controls, tweenGroup } = stateRef.current;
14144
14102
  if (!camera || !controls || !tweenGroup) return;
@@ -14164,7 +14122,7 @@ function XViewScene({
14164
14122
  if (!t || typeof t.closest !== "function") return false;
14165
14123
  return !!t.closest(".ui-overlay");
14166
14124
  };
14167
- const buildFullAncestryTree = (0, import_react29.useCallback)(
14125
+ const buildFullAncestryTree = (0, import_react31.useCallback)(
14168
14126
  (idTree, nodes, ancestries = []) => {
14169
14127
  if (!idTree) return null;
14170
14128
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
@@ -14249,7 +14207,7 @@ function XViewScene({
14249
14207
  },
14250
14208
  []
14251
14209
  );
14252
- const handleActivateTimeline = (0, import_react29.useCallback)(() => {
14210
+ const handleActivateTimeline = (0, import_react31.useCallback)(() => {
14253
14211
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
14254
14212
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
14255
14213
  while (timelineIntervalsGroup.children.length > 0) {
@@ -14409,7 +14367,7 @@ function XViewScene({
14409
14367
  }
14410
14368
  });
14411
14369
  }, []);
14412
- const handleVersionTimeline = (0, import_react29.useCallback)((sourceMesh, versionMeshes) => {
14370
+ const handleVersionTimeline = (0, import_react31.useCallback)((sourceMesh, versionMeshes) => {
14413
14371
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
14414
14372
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
14415
14373
  return;
@@ -14546,7 +14504,7 @@ function XViewScene({
14546
14504
  }
14547
14505
  });
14548
14506
  }, []);
14549
- (0, import_react29.useEffect)(() => {
14507
+ (0, import_react31.useEffect)(() => {
14550
14508
  async function fetchAllData(configPath, ownerId2) {
14551
14509
  var _a2, _b2;
14552
14510
  if (!get_scene_view_data) {
@@ -14651,12 +14609,12 @@ function XViewScene({
14651
14609
  focusNodeId,
14652
14610
  focusAncestryId
14653
14611
  ]);
14654
- const isNodeInView = (0, import_react29.useCallback)((id) => {
14612
+ const isNodeInView = (0, import_react31.useCallback)((id) => {
14655
14613
  const key = String(id);
14656
14614
  const objs = stateRef.current.nodeObjects || {};
14657
14615
  return !!objs[key];
14658
14616
  }, []);
14659
- const addOrUpdateNodeMesh = (0, import_react29.useCallback)(
14617
+ const addOrUpdateNodeMesh = (0, import_react31.useCallback)(
14660
14618
  (nodeData, position, suppressVersionUpdate = false, forceShowQuestDate = false) => {
14661
14619
  const {
14662
14620
  graphGroup,
@@ -14697,7 +14655,7 @@ function XViewScene({
14697
14655
  },
14698
14656
  []
14699
14657
  );
14700
- const handleActivateQuestLens = (0, import_react29.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
14658
+ const handleActivateQuestLens = (0, import_react31.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
14701
14659
  var _a2;
14702
14660
  const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
14703
14661
  if (!nodeObjects || !tweenGroup || !graphGroup) return;
@@ -14911,7 +14869,7 @@ function XViewScene({
14911
14869
  camTween.start();
14912
14870
  }
14913
14871
  }, [addOrUpdateNodeMesh]);
14914
- (0, import_react29.useEffect)(() => {
14872
+ (0, import_react31.useEffect)(() => {
14915
14873
  if (!isInitialized || !sceneDataRef.current) return;
14916
14874
  const currentMount = mountRef.current;
14917
14875
  if (!currentMount) return;
@@ -15667,7 +15625,7 @@ function XViewScene({
15667
15625
  get_scene_view_data,
15668
15626
  save_view_data
15669
15627
  ]);
15670
- const handleGhostNodeImageChange = (0, import_react29.useCallback)((useImage, imageUrl) => {
15628
+ const handleGhostNodeImageChange = (0, import_react31.useCallback)((useImage, imageUrl) => {
15671
15629
  const {
15672
15630
  node: ghostNode,
15673
15631
  line: ghostLine,
@@ -15715,7 +15673,7 @@ function XViewScene({
15715
15673
  aura: newGhostNode.getObjectByName("aura")
15716
15674
  };
15717
15675
  }, []);
15718
- const handleGhostNodeIntensityChange = (0, import_react29.useCallback)((newIntensity) => {
15676
+ const handleGhostNodeIntensityChange = (0, import_react31.useCallback)((newIntensity) => {
15719
15677
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
15720
15678
  if (!ghostNode) return;
15721
15679
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -15736,7 +15694,7 @@ function XViewScene({
15736
15694
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
15737
15695
  }
15738
15696
  }, []);
15739
- const handleDetailNodeIntensityChange = (0, import_react29.useCallback)(
15697
+ const handleDetailNodeIntensityChange = (0, import_react31.useCallback)(
15740
15698
  (nodeId, newIntensity) => {
15741
15699
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
15742
15700
  if (!mesh) return;
@@ -15892,7 +15850,7 @@ function XViewScene({
15892
15850
  mountRef.current.style.cursor = "default";
15893
15851
  }
15894
15852
  };
15895
- const handleAncestryTreeUpdate = (0, import_react29.useCallback)((newTree, extraData = null) => {
15853
+ const handleAncestryTreeUpdate = (0, import_react31.useCallback)((newTree, extraData = null) => {
15896
15854
  setAncestryMode((prev) => {
15897
15855
  const prevTreeStr = JSON.stringify(prev.tree);
15898
15856
  const newTreeStr = JSON.stringify(newTree);
@@ -15915,7 +15873,7 @@ function XViewScene({
15915
15873
  };
15916
15874
  });
15917
15875
  }, []);
15918
- const actionHandlerContext = (0, import_react29.useMemo)(
15876
+ const actionHandlerContext = (0, import_react31.useMemo)(
15919
15877
  () => {
15920
15878
  var _a2;
15921
15879
  return {
@@ -15976,7 +15934,7 @@ function XViewScene({
15976
15934
  const handleStartVersioning = (nodeData) => {
15977
15935
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
15978
15936
  };
15979
- const handleStartQuestQuick = (0, import_react29.useCallback)((questNode) => {
15937
+ const handleStartQuestQuick = (0, import_react31.useCallback)((questNode) => {
15980
15938
  var _a2, _b2, _c2;
15981
15939
  if (!questNode || !actionHandlerContext) return;
15982
15940
  const allParentNodes = Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
@@ -16011,7 +15969,7 @@ function XViewScene({
16011
15969
  }
16012
15970
  setDetailsNode(updatedNode);
16013
15971
  }, [session, actionHandlerContext]);
16014
- const handleFinishQuestQuick = (0, import_react29.useCallback)((questNode) => {
15972
+ const handleFinishQuestQuick = (0, import_react31.useCallback)((questNode) => {
16015
15973
  var _a2, _b2, _c2, _d2;
16016
15974
  if (!questNode || !actionHandlerContext) return;
16017
15975
  const {
@@ -16085,7 +16043,7 @@ function XViewScene({
16085
16043
  setDetailsNode(null);
16086
16044
  }
16087
16045
  }, [session, actionHandlerContext, viewMembers, detailsNode]);
16088
- const handleCancelQuest = (0, import_react29.useCallback)(() => {
16046
+ const handleCancelQuest = (0, import_react31.useCallback)(() => {
16089
16047
  const { graphGroup, ghostElements } = stateRef.current;
16090
16048
  if (ghostElements.node && graphGroup) {
16091
16049
  if (ghostElements.node.userData.labelObject) {
@@ -16144,13 +16102,15 @@ function XViewScene({
16144
16102
  try {
16145
16103
  await actions.save_view_data(sceneSaveUrl2, sceneFileData);
16146
16104
  sceneDataRef2.current.quest_counter = currentCounter + 1;
16147
- sceneDataRef2.current.quest_nodes = sceneFileData.quest_nodes;
16148
- sceneDataRef2.current.quest_links = sceneFileData.quest_links;
16149
16105
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
16150
16106
  parentFileId: sceneConfigId2,
16151
16107
  ownerId: ownerId2,
16152
16108
  datasetName: "Quests Internas (View)"
16153
16109
  });
16110
+ sceneDataRef2.current.quest_nodes = [...graphDataRef.current[sceneConfigId2].nodes];
16111
+ if (parentDataRef.current[sceneConfigId2]) {
16112
+ parentDataRef.current[sceneConfigId2].nodes = [...graphDataRef.current[sceneConfigId2].nodes];
16113
+ }
16154
16114
  const finalPosition = stateRef2.current.ghostElements.node ? stateRef2.current.ghostElements.node.position.clone() : stateRef2.current.controls.target.clone();
16155
16115
  const { graphGroup, ghostElements } = stateRef2.current;
16156
16116
  if (ghostElements.node && graphGroup) {
@@ -16240,7 +16200,7 @@ function XViewScene({
16240
16200
  }
16241
16201
  userActionHandlers.handleCancelConnection(context);
16242
16202
  };
16243
- const handleClearAncestryVisuals = (0, import_react29.useCallback)((ancestryId) => {
16203
+ const handleClearAncestryVisuals = (0, import_react31.useCallback)((ancestryId) => {
16244
16204
  const { renderedAncestries, ancestryGroup } = stateRef.current;
16245
16205
  const renderIndex = renderedAncestries.findIndex(
16246
16206
  (a) => String(a.id) === String(ancestryId)
@@ -16258,7 +16218,7 @@ function XViewScene({
16258
16218
  );
16259
16219
  }
16260
16220
  }, []);
16261
- const handleRenderAncestry = (0, import_react29.useCallback)(
16221
+ const handleRenderAncestry = (0, import_react31.useCallback)(
16262
16222
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
16263
16223
  setContextMenu(
16264
16224
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16752,7 +16712,7 @@ function XViewScene({
16752
16712
  ancestryMode.isActive
16753
16713
  ]
16754
16714
  );
16755
- const handleRenderAbstractionTree = (0, import_react29.useCallback)(
16715
+ const handleRenderAbstractionTree = (0, import_react31.useCallback)(
16756
16716
  (ancestryObject, targetNodeId = null) => {
16757
16717
  setContextMenu(
16758
16718
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16840,7 +16800,7 @@ function XViewScene({
16840
16800
  handleClearAncestryVisuals
16841
16801
  ]
16842
16802
  );
16843
- const handleReadModeBranchNav = (0, import_react29.useCallback)(
16803
+ const handleReadModeBranchNav = (0, import_react31.useCallback)(
16844
16804
  (nodeId, action, direction = "right") => {
16845
16805
  const { ancestry, branchStack } = readingMode;
16846
16806
  if (!ancestry || !ancestry.tree) return;
@@ -17018,13 +16978,13 @@ function XViewScene({
17018
16978
  },
17019
16979
  [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
17020
16980
  );
17021
- const handleReadModeHighlight = (0, import_react29.useCallback)((nodeId) => {
16981
+ const handleReadModeHighlight = (0, import_react31.useCallback)((nodeId) => {
17022
16982
  if (stateRef.current.highlightedNodeId !== nodeId) {
17023
16983
  stateRef.current.highlightedNodeId = nodeId;
17024
16984
  }
17025
16985
  setHighlightedNodeId(nodeId);
17026
16986
  }, []);
17027
- const activeNodeBranches = (0, import_react29.useMemo)(() => {
16987
+ const activeNodeBranches = (0, import_react31.useMemo)(() => {
17028
16988
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
17029
16989
  return null;
17030
16990
  const fullTree = buildFullAncestryTree(
@@ -17068,7 +17028,7 @@ function XViewScene({
17068
17028
  readingMode.branchStack,
17069
17029
  ancestryDataRef.current
17070
17030
  ]);
17071
- const backNavigationInfo = (0, import_react29.useMemo)(() => {
17031
+ const backNavigationInfo = (0, import_react31.useMemo)(() => {
17072
17032
  const { branchStack } = readingMode;
17073
17033
  if (!branchStack || branchStack.length === 0) return null;
17074
17034
  const lastStep = branchStack[branchStack.length - 1];
@@ -17079,7 +17039,7 @@ function XViewScene({
17079
17039
  name: "Voltar para anterior"
17080
17040
  };
17081
17041
  }, [readingMode.branchStack]);
17082
- const getReadModeDisplayContext = (0, import_react29.useMemo)(() => {
17042
+ const getReadModeDisplayContext = (0, import_react31.useMemo)(() => {
17083
17043
  const { ancestry, branchStack } = readingMode;
17084
17044
  if (!ancestry) return null;
17085
17045
  if (branchStack.length === 0) {
@@ -17122,7 +17082,7 @@ function XViewScene({
17122
17082
  customProperties: branchProps
17123
17083
  };
17124
17084
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
17125
- const readModeAbstractionTree = (0, import_react29.useMemo)(() => {
17085
+ const readModeAbstractionTree = (0, import_react31.useMemo)(() => {
17126
17086
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
17127
17087
  return null;
17128
17088
  }
@@ -17141,7 +17101,7 @@ function XViewScene({
17141
17101
  buildFullAncestryTree,
17142
17102
  sceneVersion
17143
17103
  ]);
17144
- const handleStartReadingAncestry = (0, import_react29.useCallback)(
17104
+ const handleStartReadingAncestry = (0, import_react31.useCallback)(
17145
17105
  async (ancestryObject, renderMode = "full") => {
17146
17106
  setContextMenu(
17147
17107
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17184,7 +17144,7 @@ function XViewScene({
17184
17144
  },
17185
17145
  [handleRenderAncestry, handleRenderAbstractionTree]
17186
17146
  );
17187
- const handleReadModeSectionChange = (0, import_react29.useCallback)(
17147
+ const handleReadModeSectionChange = (0, import_react31.useCallback)(
17188
17148
  (activeSectionId) => {
17189
17149
  const { ancestry, branchStack } = readingMode;
17190
17150
  if (!ancestry || !readingMode.isActive) return;
@@ -17269,10 +17229,10 @@ function XViewScene({
17269
17229
  ancestryDataRef.current
17270
17230
  ]
17271
17231
  );
17272
- const handleCloseReadMode = (0, import_react29.useCallback)(() => {
17232
+ const handleCloseReadMode = (0, import_react31.useCallback)(() => {
17273
17233
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
17274
17234
  }, []);
17275
- const handleAncestrySectionChange = (0, import_react29.useCallback)(
17235
+ const handleAncestrySectionChange = (0, import_react31.useCallback)(
17276
17236
  (activeSectionId, ancestryOverride = null, rotation = 0) => {
17277
17237
  var _a2, _b2;
17278
17238
  const currentMode = stateRef.current.ancestry;
@@ -17334,7 +17294,7 @@ function XViewScene({
17334
17294
  },
17335
17295
  [handleRenderAncestry]
17336
17296
  );
17337
- const handleEditAncestry = (0, import_react29.useCallback)(
17297
+ const handleEditAncestry = (0, import_react31.useCallback)(
17338
17298
  async (ancestryObject) => {
17339
17299
  setContextMenu(
17340
17300
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17389,7 +17349,7 @@ function XViewScene({
17389
17349
  const handleSelectAncestryParent = (nodeId) => {
17390
17350
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
17391
17351
  };
17392
- const handleRemoveFromAncestry = (0, import_react29.useCallback)((pathToRemove) => {
17352
+ const handleRemoveFromAncestry = (0, import_react31.useCallback)((pathToRemove) => {
17393
17353
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
17394
17354
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
17395
17355
  return;
@@ -17414,7 +17374,7 @@ function XViewScene({
17414
17374
  return { ...prev, tree: newTree };
17415
17375
  });
17416
17376
  }, []);
17417
- const handleSaveAncestry = (0, import_react29.useCallback)(
17377
+ const handleSaveAncestry = (0, import_react31.useCallback)(
17418
17378
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
17419
17379
  const treeToUse = treeOverride || ancestryMode.tree;
17420
17380
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -17650,7 +17610,7 @@ function XViewScene({
17650
17610
  });
17651
17611
  setEditingAncestryRel({ visible: false, data: null, path: null });
17652
17612
  };
17653
- const handleDeleteAncestry = (0, import_react29.useCallback)(
17613
+ const handleDeleteAncestry = (0, import_react31.useCallback)(
17654
17614
  async (ancestryIdToDelete) => {
17655
17615
  if (!ancestryIdToDelete) {
17656
17616
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -17732,28 +17692,70 @@ function XViewScene({
17732
17692
  },
17733
17693
  [save_view_data, delete_file_action]
17734
17694
  );
17735
- const handleOpenAncestryBoard = (0, import_react29.useCallback)(() => {
17695
+ const handleOpenAncestryBoard = (0, import_react31.useCallback)(() => {
17736
17696
  setIsAncestryBoardOpen(true);
17737
17697
  }, []);
17738
- const handleSelectAncestryFromBoard = (0, import_react29.useCallback)(
17698
+ const allAvailableNodes = (0, import_react31.useMemo)(() => {
17699
+ if (!parentDataRef.current) return [];
17700
+ return Object.values(parentDataRef.current).flatMap(
17701
+ (fileData) => fileData.nodes || []
17702
+ );
17703
+ }, [sceneVersion, isInitialized]);
17704
+ const allAvailableAncestries = (0, import_react31.useMemo)(() => {
17705
+ return ancestryDataRef.current || [];
17706
+ }, [sceneVersion, isInitialized]);
17707
+ const handleOpenReference = (0, import_react31.useCallback)(
17708
+ (referenceData) => {
17709
+ const { type, id } = referenceData;
17710
+ if (type === "node") {
17711
+ const targetNode = allAvailableNodes.find(
17712
+ (n) => String(n.id) === String(id)
17713
+ );
17714
+ if (targetNode) {
17715
+ setAncestryLinkDetails(null);
17716
+ setDetailsLink(null);
17717
+ setDetailsNode(targetNode);
17718
+ const sceneMesh = stateRef.current.nodeObjects[String(id)];
17719
+ if (sceneMesh) {
17720
+ tweenToTarget(sceneMesh);
17721
+ }
17722
+ } else {
17723
+ alert("Node original n\xE3o encontrado neste contexto.");
17724
+ }
17725
+ } else if (type === "ancestry") {
17726
+ const targetAncestry = allAvailableAncestries.find(
17727
+ (a) => String(a.ancestry_id) === String(id)
17728
+ );
17729
+ if (targetAncestry) {
17730
+ setDetailsNode(null);
17731
+ setDetailsLink(null);
17732
+ setAncestryLinkDetails(null);
17733
+ handleEditAncestry(targetAncestry);
17734
+ } else {
17735
+ alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17736
+ }
17737
+ }
17738
+ },
17739
+ [
17740
+ allAvailableNodes,
17741
+ allAvailableAncestries,
17742
+ handleEditAncestry,
17743
+ tweenToTarget
17744
+ ]
17745
+ );
17746
+ const handleSelectAncestryFromBoard = (0, import_react31.useCallback)(
17739
17747
  (item) => {
17740
17748
  setIsAncestryBoardOpen(false);
17741
17749
  setIsSidebarOpen(false);
17742
- if (item.type === "ancestry" || !item.type) {
17750
+ if (item.type === "ancestry") {
17743
17751
  handleStartReadingAncestry(item);
17744
17752
  } else {
17745
- const nodeId = String(item.id);
17746
- const sceneMesh = stateRef.current.nodeObjects[nodeId];
17747
- if (sceneMesh) {
17748
- tweenToTarget(sceneMesh);
17749
- } else {
17750
- console.warn("Objeto n\xE3o encontrado na cena para foco:", nodeId);
17751
- }
17753
+ handleOpenReference({ type: "node", id: item.id });
17752
17754
  }
17753
17755
  },
17754
- [handleStartReadingAncestry, tweenToTarget]
17756
+ [handleStartReadingAncestry, handleOpenReference]
17755
17757
  );
17756
- const handleSaveAncestryBoard = (0, import_react29.useCallback)(
17758
+ const handleSaveAncestryBoard = (0, import_react31.useCallback)(
17757
17759
  async (groups) => {
17758
17760
  if (!sceneConfigId || !viewParams || !session) return;
17759
17761
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
@@ -17767,7 +17769,7 @@ function XViewScene({
17767
17769
  },
17768
17770
  [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
17769
17771
  );
17770
- const existingNodeTypes = (0, import_react29.useMemo)(() => {
17772
+ const existingNodeTypes = (0, import_react31.useMemo)(() => {
17771
17773
  if (!parentDataRef.current) {
17772
17774
  return [];
17773
17775
  }
@@ -17779,28 +17781,22 @@ function XViewScene({
17779
17781
  ).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
17780
17782
  return [...new Set(allTypes)];
17781
17783
  }, [parentDataRef.current, sceneVersion]);
17782
- const searchableDbNodes = (0, import_react29.useMemo)(() => {
17783
- var _a2;
17784
+ const searchableDbNodes = (0, import_react31.useMemo)(() => {
17784
17785
  if (!parentDataRef.current) {
17785
17786
  return [];
17786
17787
  }
17787
- const datasetsPool = Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17788
+ return Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17788
17789
  const datasetName = fileData.dataset_name || `Dataset #${dbId.substring(0, 6)}`;
17789
17790
  return (fileData.nodes || []).map((node) => ({
17790
17791
  ...node,
17791
17792
  dataset_name: datasetName
17792
17793
  }));
17794
+ }).filter((node) => {
17795
+ var _a2;
17796
+ return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
17793
17797
  });
17794
- const questsPool = (((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || []).map((node) => ({
17795
- ...node,
17796
- dataset_name: "Quests Internas (View)"
17797
- }));
17798
- return [...datasetsPool, ...questsPool].filter((node) => {
17799
- var _a3;
17800
- return !((_a3 = node.version_node) == null ? void 0 : _a3.is_version);
17801
- });
17802
- }, [parentDataRef.current, (_b = sceneDataRef.current) == null ? void 0 : _b.quest_nodes, sceneVersion]);
17803
- const handleAddExistingNode = (0, import_react29.useCallback)(
17798
+ }, [parentDataRef.current, sceneVersion]);
17799
+ const handleAddExistingNode = (0, import_react31.useCallback)(
17804
17800
  (nodeId) => {
17805
17801
  return userActionHandlers.handleAddExistingNodeById(
17806
17802
  actionHandlerContext,
@@ -17809,7 +17805,7 @@ function XViewScene({
17809
17805
  },
17810
17806
  [actionHandlerContext]
17811
17807
  );
17812
- const handleUpdateMilestones = (0, import_react29.useCallback)(
17808
+ const handleUpdateMilestones = (0, import_react31.useCallback)(
17813
17809
  async (newMilestones) => {
17814
17810
  var _a2, _b2, _c2;
17815
17811
  if (!sceneDataRef.current) return;
@@ -17855,7 +17851,7 @@ function XViewScene({
17855
17851
  viewParams == null ? void 0 : viewParams.type
17856
17852
  ]
17857
17853
  );
17858
- const handleSaveCurrentView = (0, import_react29.useCallback)(async () => {
17854
+ const handleSaveCurrentView = (0, import_react31.useCallback)(async () => {
17859
17855
  var _a2, _b2, _c2;
17860
17856
  const { nodeObjects, allLinks } = stateRef.current;
17861
17857
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
@@ -17898,61 +17894,13 @@ function XViewScene({
17898
17894
  console.error("Erro na chamada de save_view_data:", error);
17899
17895
  }
17900
17896
  }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
17901
- const allAvailableNodes = (0, import_react29.useMemo)(() => {
17902
- if (!parentDataRef.current) return [];
17903
- return Object.values(parentDataRef.current).flatMap(
17904
- (fileData) => fileData.nodes || []
17905
- );
17906
- }, [sceneVersion, isInitialized]);
17907
- const allAvailableAncestries = (0, import_react29.useMemo)(() => {
17908
- return ancestryDataRef.current || [];
17909
- }, [sceneVersion, isInitialized]);
17910
- const handleOpenReference = (0, import_react29.useCallback)(
17911
- (referenceData) => {
17912
- const { type, id } = referenceData;
17913
- if (type === "node") {
17914
- const targetNode = allAvailableNodes.find(
17915
- (n) => String(n.id) === String(id)
17916
- );
17917
- if (targetNode) {
17918
- setAncestryLinkDetails(null);
17919
- setDetailsLink(null);
17920
- setDetailsNode(targetNode);
17921
- const sceneMesh = stateRef.current.nodeObjects[String(id)];
17922
- if (sceneMesh) {
17923
- tweenToTarget(sceneMesh);
17924
- }
17925
- } else {
17926
- alert("Node original n\xE3o encontrado neste contexto.");
17927
- }
17928
- } else if (type === "ancestry") {
17929
- const targetAncestry = allAvailableAncestries.find(
17930
- (a) => String(a.ancestry_id) === String(id)
17931
- );
17932
- if (targetAncestry) {
17933
- setDetailsNode(null);
17934
- setDetailsLink(null);
17935
- setAncestryLinkDetails(null);
17936
- handleEditAncestry(targetAncestry);
17937
- } else {
17938
- alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17939
- }
17940
- }
17941
- },
17942
- [
17943
- allAvailableNodes,
17944
- allAvailableAncestries,
17945
- handleEditAncestry,
17946
- tweenToTarget
17947
- ]
17948
- );
17949
- const handleToggleAncestryAddMode = (0, import_react29.useCallback)(() => {
17897
+ const handleToggleAncestryAddMode = (0, import_react31.useCallback)(() => {
17950
17898
  setAncestryMode((prev) => ({
17951
17899
  ...prev,
17952
17900
  isAddingNodes: !prev.isAddingNodes
17953
17901
  }));
17954
17902
  }, []);
17955
- const handleFocusNode = (0, import_react29.useCallback)(
17903
+ const handleFocusNode = (0, import_react31.useCallback)(
17956
17904
  (nodeData) => {
17957
17905
  var _a2;
17958
17906
  if (!nodeData) return;
@@ -17968,7 +17916,7 @@ function XViewScene({
17968
17916
  },
17969
17917
  [tweenToTarget]
17970
17918
  );
17971
- const availableDatasets = (0, import_react29.useMemo)(() => {
17919
+ const availableDatasets = (0, import_react31.useMemo)(() => {
17972
17920
  if (!sceneDataRef.current || !parentDataRef.current) return [];
17973
17921
  return sceneDataRef.current.parent_dbs.map((db) => {
17974
17922
  var _a2;
@@ -17978,11 +17926,11 @@ function XViewScene({
17978
17926
  };
17979
17927
  });
17980
17928
  }, [sceneVersion, isInitialized]);
17981
- const sourceNodeDatasetId = creationMode.sourceNodeData ? (_c = stateRef.current.nodeIdToParentFileMap.get(
17929
+ const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(
17982
17930
  String(creationMode.sourceNodeData.id)
17983
- )) == null ? void 0 : _c.parentFileId : null;
17931
+ )) == null ? void 0 : _b.parentFileId : null;
17984
17932
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
17985
- (0, import_react29.useEffect)(() => {
17933
+ (0, import_react31.useEffect)(() => {
17986
17934
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
17987
17935
  const nodeObjects = stateRef.current.nodeObjects || {};
17988
17936
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -18005,7 +17953,7 @@ function XViewScene({
18005
17953
  hasFocusedInitial,
18006
17954
  tweenToTarget
18007
17955
  ]);
18008
- (0, import_react29.useEffect)(() => {
17956
+ (0, import_react31.useEffect)(() => {
18009
17957
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
18010
17958
  const ancestries = ancestryDataRef.current || [];
18011
17959
  const targetAncestry = ancestries.find(
@@ -18030,7 +17978,7 @@ function XViewScene({
18030
17978
  hasOpenedInitialAncestry,
18031
17979
  handleStartReadingAncestry
18032
17980
  ]);
18033
- (0, import_react29.useEffect)(() => {
17981
+ (0, import_react31.useEffect)(() => {
18034
17982
  function handleKeyDown(event) {
18035
17983
  var _a2, _b2, _c2;
18036
17984
  const context = actionHandlerContext;
@@ -18153,10 +18101,10 @@ function XViewScene({
18153
18101
  // <-- handleCancelQuest adicionado aqui
18154
18102
  ]);
18155
18103
  if (isLoading || status === "loading" || permissionStatus === "loading") {
18156
- return /* @__PURE__ */ import_react29.default.createElement(LoadingScreen, null);
18104
+ return /* @__PURE__ */ import_react31.default.createElement(LoadingScreen, null);
18157
18105
  }
18158
18106
  if (permissionStatus === "denied") {
18159
- return /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react29.default.createElement(
18107
+ return /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react31.default.createElement(
18160
18108
  "svg",
18161
18109
  {
18162
18110
  xmlns: "http://www.w3.org/2000/svg",
@@ -18166,7 +18114,7 @@ function XViewScene({
18166
18114
  stroke: "currentColor",
18167
18115
  className: "w-16 h-16 mx-auto"
18168
18116
  },
18169
- /* @__PURE__ */ import_react29.default.createElement(
18117
+ /* @__PURE__ */ import_react31.default.createElement(
18170
18118
  "path",
18171
18119
  {
18172
18120
  strokeLinecap: "round",
@@ -18174,13 +18122,13 @@ function XViewScene({
18174
18122
  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"
18175
18123
  }
18176
18124
  )
18177
- )), /* @__PURE__ */ import_react29.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ import_react29.default.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__ */ import_react29.default.createElement(
18125
+ )), /* @__PURE__ */ import_react31.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ import_react31.default.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__ */ import_react31.default.createElement(
18178
18126
  "button",
18179
18127
  {
18180
18128
  onClick: () => router.push("/dashboard/scenes"),
18181
18129
  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"
18182
18130
  },
18183
- /* @__PURE__ */ import_react29.default.createElement(
18131
+ /* @__PURE__ */ import_react31.default.createElement(
18184
18132
  "svg",
18185
18133
  {
18186
18134
  xmlns: "http://www.w3.org/2000/svg",
@@ -18190,7 +18138,7 @@ function XViewScene({
18190
18138
  stroke: "currentColor",
18191
18139
  className: "w-5 h-5"
18192
18140
  },
18193
- /* @__PURE__ */ import_react29.default.createElement(
18141
+ /* @__PURE__ */ import_react31.default.createElement(
18194
18142
  "path",
18195
18143
  {
18196
18144
  strokeLinecap: "round",
@@ -18202,7 +18150,7 @@ function XViewScene({
18202
18150
  "Voltar para Scenes"
18203
18151
  )));
18204
18152
  }
18205
- return /* @__PURE__ */ import_react29.default.createElement(
18153
+ return /* @__PURE__ */ import_react31.default.createElement(
18206
18154
  "div",
18207
18155
  {
18208
18156
  ref: mountRef,
@@ -18214,7 +18162,7 @@ function XViewScene({
18214
18162
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
18215
18163
  }
18216
18164
  },
18217
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react29.default.createElement(
18165
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react31.default.createElement(
18218
18166
  XViewSidebar,
18219
18167
  {
18220
18168
  dbNodes: searchableDbNodes,
@@ -18234,11 +18182,11 @@ function XViewScene({
18234
18182
  onToggle: setIsSidebarOpen,
18235
18183
  userRole: userPermissionRole,
18236
18184
  viewMembers,
18237
- milestones: ((_d = sceneDataRef.current) == null ? void 0 : _d.milestones) || [],
18185
+ milestones: ((_c = sceneDataRef.current) == null ? void 0 : _c.milestones) || [],
18238
18186
  onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
18239
18187
  }
18240
18188
  ),
18241
- creationMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18189
+ creationMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
18242
18190
  InSceneCreationForm,
18243
18191
  {
18244
18192
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -18259,8 +18207,8 @@ function XViewScene({
18259
18207
  },
18260
18208
  refEl: formRef,
18261
18209
  existingTypes: existingNodeTypes,
18262
- initialColor: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.color,
18263
- sourceTypes: (_f = creationMode.sourceNodeData) == null ? void 0 : _f.type,
18210
+ initialColor: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.color,
18211
+ sourceTypes: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.type,
18264
18212
  onIntensityChange: handleGhostNodeIntensityChange,
18265
18213
  onUploadFile: upload_file_action,
18266
18214
  availableDatasets,
@@ -18270,7 +18218,7 @@ function XViewScene({
18270
18218
  availableAncestries: allAvailableAncestries
18271
18219
  }
18272
18220
  ),
18273
- versionMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18221
+ versionMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
18274
18222
  InSceneVersionForm,
18275
18223
  {
18276
18224
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -18289,14 +18237,14 @@ function XViewScene({
18289
18237
  transition: "opacity 200ms ease-out"
18290
18238
  },
18291
18239
  refEl: formRef,
18292
- fixedType: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.type,
18293
- fixedColor: (_h = versionMode.sourceNodeData) == null ? void 0 : _h.color,
18240
+ fixedType: (_f = versionMode.sourceNodeData) == null ? void 0 : _f.type,
18241
+ fixedColor: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.color,
18294
18242
  onUploadFile: upload_file_action,
18295
18243
  availableNodes: allAvailableNodes,
18296
18244
  availableAncestries: allAvailableAncestries
18297
18245
  }
18298
18246
  ),
18299
- questMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18247
+ questMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
18300
18248
  InSceneQuestForm,
18301
18249
  {
18302
18250
  onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
@@ -18318,13 +18266,13 @@ function XViewScene({
18318
18266
  availableNodes: allAvailableNodes,
18319
18267
  availableAncestries: allAvailableAncestries,
18320
18268
  viewName: viewParams == null ? void 0 : viewParams.name,
18321
- questCounter: ((_i = sceneDataRef.current) == null ? void 0 : _i.quest_counter) || 1,
18269
+ questCounter: ((_h = sceneDataRef.current) == null ? void 0 : _h.quest_counter) || 1,
18322
18270
  viewMembers,
18323
- milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18271
+ milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
18324
18272
  onUpdateMilestones: handleUpdateMilestones
18325
18273
  }
18326
18274
  ),
18327
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react29.default.createElement(
18275
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react31.default.createElement(
18328
18276
  "div",
18329
18277
  {
18330
18278
  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"}`,
@@ -18337,7 +18285,7 @@ function XViewScene({
18337
18285
  maxWidth: "92vw"
18338
18286
  }
18339
18287
  },
18340
- /* @__PURE__ */ import_react29.default.createElement(
18288
+ /* @__PURE__ */ import_react31.default.createElement(
18341
18289
  "div",
18342
18290
  {
18343
18291
  onPointerDown: (e) => {
@@ -18348,7 +18296,7 @@ function XViewScene({
18348
18296
  title: "Arraste para redimensionar"
18349
18297
  }
18350
18298
  ),
18351
- /* @__PURE__ */ import_react29.default.createElement(
18299
+ /* @__PURE__ */ import_react31.default.createElement(
18352
18300
  DescriptionReadModePanel,
18353
18301
  {
18354
18302
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -18383,7 +18331,7 @@ function XViewScene({
18383
18331
  }
18384
18332
  )
18385
18333
  ),
18386
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react29.default.createElement(
18334
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react31.default.createElement(
18387
18335
  CreateAncestryPanel,
18388
18336
  {
18389
18337
  ancestryMode,
@@ -18419,7 +18367,7 @@ function XViewScene({
18419
18367
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
18420
18368
  }
18421
18369
  ),
18422
- editingAncestryRel.visible && /* @__PURE__ */ import_react29.default.createElement(
18370
+ editingAncestryRel.visible && /* @__PURE__ */ import_react31.default.createElement(
18423
18371
  AncestryRelationshipPanel,
18424
18372
  {
18425
18373
  data: editingAncestryRel.data,
@@ -18433,7 +18381,7 @@ function XViewScene({
18433
18381
  onUploadFile: upload_file_action
18434
18382
  }
18435
18383
  ),
18436
- detailsNode && detailsNode.is_quest && /* @__PURE__ */ import_react29.default.createElement(
18384
+ detailsNode && detailsNode.is_quest && /* @__PURE__ */ import_react31.default.createElement(
18437
18385
  QuestDetailsPanel,
18438
18386
  {
18439
18387
  node: detailsNode,
@@ -18455,11 +18403,11 @@ function XViewScene({
18455
18403
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
18456
18404
  viewMembers,
18457
18405
  currentUser: session == null ? void 0 : session.user,
18458
- milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18406
+ milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18459
18407
  onUpdateMilestones: handleUpdateMilestones
18460
18408
  }
18461
18409
  ),
18462
- detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react29.default.createElement(
18410
+ detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react31.default.createElement(
18463
18411
  NodeDetailsPanel,
18464
18412
  {
18465
18413
  node: detailsNode,
@@ -18491,7 +18439,7 @@ function XViewScene({
18491
18439
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
18492
18440
  }
18493
18441
  ),
18494
- detailsLink && /* @__PURE__ */ import_react29.default.createElement(
18442
+ detailsLink && /* @__PURE__ */ import_react31.default.createElement(
18495
18443
  RelationshipDetailsPanel,
18496
18444
  {
18497
18445
  link: detailsLink,
@@ -18505,7 +18453,7 @@ function XViewScene({
18505
18453
  userRole: userPermissionRole
18506
18454
  }
18507
18455
  ),
18508
- ancestryLinkDetails && /* @__PURE__ */ import_react29.default.createElement(
18456
+ ancestryLinkDetails && /* @__PURE__ */ import_react31.default.createElement(
18509
18457
  AncestryLinkDetailsPanel,
18510
18458
  {
18511
18459
  data: ancestryLinkDetails,
@@ -18516,7 +18464,7 @@ function XViewScene({
18516
18464
  onUploadFile: upload_file_action
18517
18465
  }
18518
18466
  ),
18519
- /* @__PURE__ */ import_react29.default.createElement(
18467
+ /* @__PURE__ */ import_react31.default.createElement(
18520
18468
  "div",
18521
18469
  {
18522
18470
  ref: tooltipRef,
@@ -18543,7 +18491,7 @@ function XViewScene({
18543
18491
  }
18544
18492
  }
18545
18493
  ),
18546
- /* @__PURE__ */ import_react29.default.createElement(
18494
+ /* @__PURE__ */ import_react31.default.createElement(
18547
18495
  ContextMenu,
18548
18496
  {
18549
18497
  data: contextMenu,
@@ -18576,7 +18524,7 @@ function XViewScene({
18576
18524
  onFinishQuest: handleFinishQuestQuick
18577
18525
  }
18578
18526
  ),
18579
- /* @__PURE__ */ import_react29.default.createElement(
18527
+ /* @__PURE__ */ import_react31.default.createElement(
18580
18528
  MultiNodeContextMenu,
18581
18529
  {
18582
18530
  data: multiContextMenu,
@@ -18596,7 +18544,7 @@ function XViewScene({
18596
18544
  )
18597
18545
  }
18598
18546
  ),
18599
- /* @__PURE__ */ import_react29.default.createElement(
18547
+ /* @__PURE__ */ import_react31.default.createElement(
18600
18548
  RelationshipContextMenu,
18601
18549
  {
18602
18550
  data: relationshipMenu,
@@ -18614,14 +18562,14 @@ function XViewScene({
18614
18562
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
18615
18563
  }
18616
18564
  ),
18617
- /* @__PURE__ */ import_react29.default.createElement(
18565
+ /* @__PURE__ */ import_react31.default.createElement(
18618
18566
  ImageViewer,
18619
18567
  {
18620
18568
  data: imageViewer,
18621
18569
  onClose: () => setImageViewer({ ...imageViewer, visible: false })
18622
18570
  }
18623
18571
  ),
18624
- /* @__PURE__ */ import_react29.default.createElement(
18572
+ /* @__PURE__ */ import_react31.default.createElement(
18625
18573
  AncestryBoard,
18626
18574
  {
18627
18575
  isOpen: isAncestryBoardOpen,
@@ -18634,29 +18582,29 @@ function XViewScene({
18634
18582
  userRole: userPermissionRole
18635
18583
  }
18636
18584
  ),
18637
- /* @__PURE__ */ import_react29.default.createElement(
18585
+ /* @__PURE__ */ import_react31.default.createElement(
18638
18586
  MilestoneManager,
18639
18587
  {
18640
18588
  isOpen: isMilestoneManagerOpen,
18641
18589
  onClose: () => setIsMilestoneManagerOpen(false),
18642
- milestones: ((_l = sceneDataRef.current) == null ? void 0 : _l.milestones) || [],
18590
+ milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18643
18591
  onUpdateMilestones: handleUpdateMilestones
18644
18592
  }
18645
18593
  ),
18646
- /* @__PURE__ */ import_react29.default.createElement(
18594
+ /* @__PURE__ */ import_react31.default.createElement(
18647
18595
  ImportParentFileModal,
18648
18596
  {
18649
18597
  isOpen: isImportModalOpen,
18650
18598
  onClose: () => setIsImportModalOpen(false),
18651
18599
  onConfirm: handleConfirmImport,
18652
18600
  session,
18653
- parentDbs: ((_m = sceneDataRef.current) == null ? void 0 : _m.parent_dbs) || [],
18601
+ parentDbs: ((_l = sceneDataRef.current) == null ? void 0 : _l.parent_dbs) || [],
18654
18602
  onFetchAvailableFiles: import_parent_file_modal_get,
18655
18603
  currentViewName: viewParams == null ? void 0 : viewParams.name,
18656
18604
  currentAncestries: ancestryDataRef.current || []
18657
18605
  }
18658
18606
  ),
18659
- invalidTargetError && /* @__PURE__ */ import_react29.default.createElement(
18607
+ invalidTargetError && /* @__PURE__ */ import_react31.default.createElement(
18660
18608
  "div",
18661
18609
  {
18662
18610
  className: "ui-overlay",
@@ -18681,13 +18629,13 @@ function XViewScene({
18681
18629
  animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
18682
18630
  }
18683
18631
  },
18684
- /* @__PURE__ */ import_react29.default.createElement("style", null, `
18632
+ /* @__PURE__ */ import_react31.default.createElement("style", null, `
18685
18633
  @keyframes fadeInDown {
18686
18634
  from { opacity: 0; transform: translate(-50%, -20px); }
18687
18635
  to { opacity: 1; transform: translate(-50%, 0); }
18688
18636
  }
18689
18637
  `),
18690
- /* @__PURE__ */ import_react29.default.createElement(
18638
+ /* @__PURE__ */ import_react31.default.createElement(
18691
18639
  "svg",
18692
18640
  {
18693
18641
  width: "20",
@@ -18699,12 +18647,12 @@ function XViewScene({
18699
18647
  strokeLinecap: "round",
18700
18648
  strokeLinejoin: "round"
18701
18649
  },
18702
- /* @__PURE__ */ import_react29.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18703
- /* @__PURE__ */ import_react29.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18704
- /* @__PURE__ */ import_react29.default.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18650
+ /* @__PURE__ */ import_react31.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18651
+ /* @__PURE__ */ import_react31.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18652
+ /* @__PURE__ */ import_react31.default.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18705
18653
  ),
18706
- /* @__PURE__ */ import_react29.default.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18707
- /* @__PURE__ */ import_react29.default.createElement(
18654
+ /* @__PURE__ */ import_react31.default.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18655
+ /* @__PURE__ */ import_react31.default.createElement(
18708
18656
  "button",
18709
18657
  {
18710
18658
  onClick: () => setInvalidTargetError(null),