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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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,126 @@ 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 [searchTerm, setSearchTerm] = (0, import_react29.useState)("");
13347
+ const [groups, setGroups] = (0, import_react29.useState)([]);
13348
+ const [isLoaded, setIsLoaded] = (0, import_react29.useState)(false);
13349
+ const [saveStatus, setSaveStatus] = (0, import_react29.useState)("idle");
13350
+ const canEdit = (0, import_react29.useMemo)(() => userRole !== "viewer", [userRole]);
13351
+ (0, import_react29.useEffect)(() => {
13162
13352
  if (initialGroups && !isLoaded) {
13163
- setGroups(initialGroups);
13353
+ const migrate = (list) => list.map((g) => ({
13354
+ id: g.id || (0, import_uuid11.v4)(),
13355
+ content: Array.isArray(g.content) ? g.content : [],
13356
+ // descarta dados legados
13357
+ children: migrate(g.children || [])
13358
+ }));
13359
+ setGroups(migrate(initialGroups));
13164
13360
  setIsLoaded(true);
13165
13361
  }
13166
13362
  }, [initialGroups, isLoaded]);
13167
- const nodeNamesMap = (0, import_react27.useMemo)(() => {
13363
+ const nodeNamesMap = (0, import_react29.useMemo)(() => {
13168
13364
  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
- }
13174
- });
13175
- }
13365
+ availableNodes.forEach((n) => {
13366
+ if (n == null ? void 0 : n.id) map.set(String(n.id), n.name);
13367
+ });
13176
13368
  return map;
13177
13369
  }, [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) => {
13370
+ const allSearchableItems = (0, import_react29.useMemo)(() => {
13371
+ const items = [];
13372
+ availableAncestries.forEach((anc) => {
13373
+ items.push({
13374
+ ...anc,
13375
+ id: String(anc.ancestry_id),
13376
+ type: "ancestry",
13377
+ searchLabel: anc.name || "",
13378
+ searchDesc: anc.description || ""
13379
+ });
13380
+ });
13381
+ availableNodes.forEach((node) => {
13382
+ var _a;
13192
13383
  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,
13384
+ if (node.is_quest) type = "quest";
13385
+ else if ((_a = node.version_node) == null ? void 0 : _a.is_version) type = "version";
13386
+ items.push({
13387
+ ...node,
13388
+ id: String(node.id),
13199
13389
  type,
13200
- raw_node: n
13201
- };
13390
+ searchLabel: node.name || node.raw_title || "",
13391
+ searchDesc: node.description || ""
13392
+ });
13202
13393
  });
13203
- return [...ancestries, ...nodes];
13394
+ return items;
13204
13395
  }, [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)(() => {
13396
+ const filtered = (0, import_react29.useMemo)(() => {
13397
+ const term = searchTerm.toLowerCase().trim();
13398
+ return allSearchableItems.filter((item) => {
13399
+ if (!term) return true;
13400
+ const labelMatch = (item.searchLabel || "").toLowerCase().includes(term);
13401
+ const descMatch = (item.searchDesc || "").toLowerCase().includes(term);
13402
+ let parentMatch = false;
13403
+ if (item.type === "ancestry") {
13404
+ const parentName = nodeNamesMap.get(String(item.ancestral_node)) || "";
13405
+ parentMatch = parentName.toLowerCase().includes(term);
13406
+ }
13407
+ return labelMatch || descMatch || parentMatch;
13408
+ });
13409
+ }, [allSearchableItems, searchTerm, nodeNamesMap]);
13410
+ const sanitizeGroups = (list) => list.map((g) => ({
13411
+ id: g.id,
13412
+ content: g.content || [],
13413
+ children: sanitizeGroups(g.children || [])
13414
+ }));
13415
+ (0, import_react29.useEffect)(() => {
13219
13416
  if (!isLoaded || !onSave) return;
13220
- const timeoutId = setTimeout(async () => {
13417
+ const id = setTimeout(async () => {
13221
13418
  setSaveStatus("saving");
13222
- const cleanData = sanitizeGroups(groups);
13223
13419
  try {
13224
- await onSave(cleanData);
13420
+ await onSave(sanitizeGroups(groups));
13225
13421
  setSaveStatus("saved");
13226
- setTimeout(() => {
13227
- setSaveStatus("idle");
13228
- }, 3e3);
13229
- } catch (error) {
13230
- console.error("Erro ao salvar board:", error);
13422
+ setTimeout(() => setSaveStatus("idle"), 3e3);
13423
+ } catch (err) {
13424
+ console.error("Erro ao salvar board:", err);
13231
13425
  setSaveStatus("error");
13232
13426
  }
13233
13427
  }, 3e3);
13234
- return () => clearTimeout(timeoutId);
13428
+ return () => clearTimeout(id);
13235
13429
  }, [groups, isLoaded, onSave]);
13236
- (0, import_react27.useEffect)(() => {
13430
+ (0, import_react29.useEffect)(() => {
13237
13431
  if (!isOpen) return;
13238
- const handleKeyDown = (e) => {
13432
+ const handler = (e) => {
13239
13433
  if (e.key === "Escape") {
13240
- if (pickingGroupId) {
13241
- setPickingGroupId(null);
13242
- } else {
13243
- onClose();
13244
- }
13434
+ onClose();
13245
13435
  e.preventDefault();
13246
13436
  e.stopPropagation();
13247
13437
  }
13248
13438
  };
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]);
13439
+ window.addEventListener("keydown", handler);
13440
+ return () => window.removeEventListener("keydown", handler);
13441
+ }, [isOpen, onClose]);
13266
13442
  const handleAddRootGroup = () => {
13267
- const newGroup = {
13268
- id: v4_default(),
13269
- text: "",
13270
- ancestries: [],
13271
- children: []
13272
- };
13273
- setGroups((prev) => [newGroup, ...prev]);
13443
+ setGroups((prev) => [{ id: (0, import_uuid11.v4)(), content: [], children: [] }, ...prev]);
13274
13444
  };
13275
13445
  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));
13446
+ const newGroup = { id: (0, import_uuid11.v4)(), content: [], children: [] };
13447
+ const add = (list) => list.map(
13448
+ (g) => g.id === parentId ? { ...g, children: [newGroup, ...g.children] } : { ...g, children: add(g.children) }
13449
+ );
13450
+ setGroups((prev) => add(prev));
13291
13451
  };
13292
13452
  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));
13453
+ const update = (list) => list.map(
13454
+ (g) => g.id === id ? newData : { ...g, children: update(g.children) }
13455
+ );
13456
+ setGroups((prev) => update(prev));
13300
13457
  };
13301
13458
  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));
13459
+ const del = (list) => list.filter((g) => g.id !== id).map((g) => ({ ...g, children: del(g.children) }));
13460
+ setGroups((prev) => del(prev));
13309
13461
  };
13310
13462
  const findGroupAndParent = (list, targetId, parent = null) => {
13311
13463
  for (let i = 0; i < list.length; i++) {
13312
- if (list[i].id === targetId) {
13464
+ if (list[i].id === targetId)
13313
13465
  return { group: list[i], parent, index: i, siblings: list };
13314
- }
13315
13466
  if (list[i].children.length > 0) {
13316
13467
  const found = findGroupAndParent(list[i].children, targetId, list[i]);
13317
13468
  if (found) return found;
@@ -13321,258 +13472,120 @@ function AncestryBoard({
13321
13472
  };
13322
13473
  const handleIndent = (id) => {
13323
13474
  setGroups((prev) => {
13324
- const newList = JSON.parse(JSON.stringify(prev));
13325
- const found = findGroupAndParent(newList, id);
13475
+ const next = JSON.parse(JSON.stringify(prev));
13476
+ const found = findGroupAndParent(next, id);
13326
13477
  if (!found || found.index === 0) return prev;
13327
13478
  const { group, siblings, index } = found;
13328
- const prevSibling = siblings[index - 1];
13329
13479
  siblings.splice(index, 1);
13330
- prevSibling.children.push(group);
13331
- return newList;
13480
+ siblings[index - 1].children.push(group);
13481
+ return next;
13332
13482
  });
13333
13483
  };
13334
13484
  const handleOutdent = (id) => {
13335
13485
  setGroups((prev) => {
13336
- const newList = JSON.parse(JSON.stringify(prev));
13337
- const found = findGroupAndParent(newList, id);
13486
+ const next = JSON.parse(JSON.stringify(prev));
13487
+ const found = findGroupAndParent(next, id);
13338
13488
  if (!found || !found.parent) return prev;
13339
13489
  const { group, siblings, index, parent } = found;
13340
13490
  siblings.splice(index, 1);
13341
- const parentFound = findGroupAndParent(newList, parent.id);
13491
+ const parentFound = findGroupAndParent(next, parent.id);
13342
13492
  if (parentFound) {
13343
13493
  parentFound.siblings.splice(parentFound.index + 1, 0, group);
13344
13494
  } else {
13345
- newList.push(group);
13495
+ next.push(group);
13346
13496
  }
13347
- return newList;
13497
+ return next;
13348
13498
  });
13349
13499
  };
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
- });
13500
+ const handleMentionClick = (item) => {
13501
+ if (onSelect) onSelect(item);
13418
13502
  };
13419
13503
  if (!isOpen) return null;
13420
- return /* @__PURE__ */ import_react27.default.createElement(
13504
+ return /* @__PURE__ */ import_react29.default.createElement(
13421
13505
  "div",
13422
13506
  {
13423
13507
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
13424
13508
  onClick: onClose
13425
13509
  },
13426
- /* @__PURE__ */ import_react27.default.createElement(
13510
+ /* @__PURE__ */ import_react29.default.createElement(
13427
13511
  "div",
13428
13512
  {
13429
13513
  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
13514
  onClick: (e) => e.stopPropagation()
13431
13515
  },
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(
13516
+ /* @__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
13517
  "button",
13440
13518
  {
13441
13519
  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 "
13520
+ 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
13521
  },
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(
13522
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiPlus, { size: 14, className: "text-indigo-400" }),
13523
+ /* @__PURE__ */ import_react29.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13524
+ ), /* @__PURE__ */ import_react29.default.createElement(
13447
13525
  "button",
13448
13526
  {
13449
13527
  onClick: onClose,
13450
13528
  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
13529
  },
13452
- "\xD7"
13530
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiX, { size: 16 })
13453
13531
  ))),
13454
- /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react27.default.createElement(
13455
- "div",
13532
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col border-r border-white/10 w-[20%] min-w-[280px] max-w-[460px] bg-slate-900 flex-none" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "relative group" }, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiSearch, { className: "absolute left-3 top-1/2 -translate-y-1/2 text-slate-500 group-focus-within:text-indigo-400 transition-colors" }), /* @__PURE__ */ import_react29.default.createElement(
13533
+ "input",
13456
13534
  {
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",
13535
+ type: "text",
13536
+ placeholder: "Navegar nas ancestralidades e nodes\u2026",
13537
+ className: "w-full rounded-md pl-9 pr-4 py-2 text-sm bg-slate-950 border border-white/10 text-slate-200 placeholder-slate-600 focus:outline-none focus:ring-1 focus:ring-indigo-500 transition-all",
13538
+ value: searchTerm,
13539
+ onChange: (e) => setSearchTerm(e.target.value),
13540
+ autoFocus: true
13541
+ }
13542
+ ))), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
13543
+ const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
13544
+ return /* @__PURE__ */ import_react29.default.createElement(
13545
+ "div",
13470
13546
  {
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",
13547
+ key: anc.id,
13548
+ className: "group relative flex items-start gap-3 p-3 text-left rounded-lg border border-white/5 bg-slate-800/40 hover:bg-indigo-600/10 hover:border-indigo-500/30 cursor-default transition-all duration-200"
13549
+ },
13550
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border bg-slate-800 border-white/5 group-hover:bg-indigo-500 group-hover:text-white transition-all shadow-lg" }, anc.type === "quest" ? /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiCheckSquare, { size: 14, className: "text-emerald-400 group-hover:text-white" }) : anc.type === "version" ? /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiGitBranch, { size: 14, className: "text-amber-400 group-hover:text-white" }) : anc.type === "node" ? /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiBox, { size: 14, className: "text-slate-400 group-hover:text-white" }) : /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiLayers, { size: 14, className: "text-indigo-400 group-hover:text-white" })),
13551
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react29.default.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, anc.searchLabel || "Sem Nome"), /* @__PURE__ */ import_react29.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-tighter" }, anc.type)), anc.type === "ancestry" && /* @__PURE__ */ import_react29.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_react29.default.createElement(import_fi23.FiCornerUpRight, { size: 10 }), /* @__PURE__ */ import_react29.default.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.searchDesc && /* @__PURE__ */ import_react29.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.searchDesc)),
13552
+ /* @__PURE__ */ import_react29.default.createElement(
13553
+ "button",
13513
13554
  {
13514
- key: `${item.type}-${item.id}`,
13515
- onClick: () => {
13516
- if (isPicking) handleSelectAncestry(item);
13555
+ onClick: (e) => {
13556
+ e.stopPropagation();
13557
+ if (onSelect) onSelect(anc);
13517
13558
  },
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
- `
13559
+ 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",
13560
+ title: "Focar no cen\xE1rio"
13522
13561
  },
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(
13562
+ /* @__PURE__ */ import_react29.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_react29.default.createElement(import_fi23.FiPlay, { size: 14, className: "ml-0.5" }))
13563
+ )
13564
+ );
13565
+ }))), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar 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
13566
  GroupItem,
13550
13567
  {
13551
13568
  key: group.id,
13552
13569
  index,
13553
13570
  group,
13554
- siblings: groups,
13555
13571
  onUpdate: handleUpdateGroup,
13556
13572
  onDelete: handleDeleteGroup,
13557
13573
  onAddSubgroup: handleAddSubgroup,
13558
13574
  onIndent: handleIndent,
13559
13575
  onOutdent: handleOutdent,
13560
- onRemoveAncestry: handleRemoveAncestryFromGroup,
13561
- onRequestPickAncestry: handleRequestPick,
13562
- pickingGroupId,
13563
- onPlayAncestry: handlePlayFromGroup,
13564
- availableIds,
13576
+ searchItems: allSearchableItems,
13577
+ onMentionClick: handleMentionClick,
13565
13578
  canEdit
13566
13579
  }
13567
13580
  ))))),
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"))
13581
+ /* @__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-between flex-shrink-0" }, /* @__PURE__ */ import_react29.default.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ import_react29.default.createElement("span", null, groups.length, " grupos raiz"))
13569
13582
  )
13570
13583
  );
13571
13584
  }
13572
13585
 
13573
13586
  // src/components/MilestoneManager.jsx
13574
- var import_react28 = __toESM(require("react"));
13575
- var import_fi23 = require("react-icons/fi");
13587
+ var import_react30 = __toESM(require("react"));
13588
+ var import_fi24 = require("react-icons/fi");
13576
13589
  function MilestoneManager({
13577
13590
  isOpen,
13578
13591
  onClose,
@@ -13580,7 +13593,7 @@ function MilestoneManager({
13580
13593
  onUpdateMilestones = () => {
13581
13594
  }
13582
13595
  }) {
13583
- const [newMilestoneName, setNewMilestoneName] = (0, import_react28.useState)("");
13596
+ const [newMilestoneName, setNewMilestoneName] = (0, import_react30.useState)("");
13584
13597
  const handleAddMilestone = () => {
13585
13598
  if (!newMilestoneName.trim()) return;
13586
13599
  const newMilestone = {
@@ -13605,27 +13618,27 @@ function MilestoneManager({
13605
13618
  };
13606
13619
  if (!isOpen) return null;
13607
13620
  const swallow = (e) => e.stopPropagation();
13608
- return /* @__PURE__ */ import_react28.default.createElement(
13621
+ return /* @__PURE__ */ import_react30.default.createElement(
13609
13622
  "div",
13610
13623
  {
13611
13624
  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
13625
  onClick: onClose
13613
13626
  },
13614
- /* @__PURE__ */ import_react28.default.createElement(
13627
+ /* @__PURE__ */ import_react30.default.createElement(
13615
13628
  "div",
13616
13629
  {
13617
13630
  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
13631
  onClick: swallow
13619
13632
  },
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(
13633
+ /* @__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
13634
  "button",
13622
13635
  {
13623
13636
  onClick: onClose,
13624
13637
  className: "p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
13625
13638
  },
13626
- /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiX, { size: 20 })
13639
+ /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiX, { size: 20 })
13627
13640
  )),
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(
13641
+ /* @__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
13642
  "input",
13630
13643
  {
13631
13644
  type: "text",
@@ -13635,47 +13648,47 @@ function MilestoneManager({
13635
13648
  placeholder: "Adicionar novo milestone...",
13636
13649
  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
13650
  }
13638
- ), /* @__PURE__ */ import_react28.default.createElement(
13651
+ ), /* @__PURE__ */ import_react30.default.createElement(
13639
13652
  "button",
13640
13653
  {
13641
13654
  onClick: handleAddMilestone,
13642
13655
  disabled: !newMilestoneName.trim(),
13643
13656
  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
13657
  },
13645
- /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiPlus, { size: 18 }),
13658
+ /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiPlus, { size: 18 }),
13646
13659
  "Adicionar"
13647
13660
  ))),
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(
13661
+ /* @__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
13662
  "div",
13650
13663
  {
13651
13664
  key: ms.id,
13652
13665
  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
13666
  },
13654
- /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ import_react28.default.createElement(
13667
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ import_react30.default.createElement(
13655
13668
  "div",
13656
13669
  {
13657
13670
  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
13671
  }
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(
13672
+ ), /* @__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"))),
13673
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react30.default.createElement(
13661
13674
  "button",
13662
13675
  {
13663
13676
  onClick: () => handleToggleMilestoneStatus(ms.id),
13664
13677
  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
13678
  title: ms.status === "active" ? "Inativar" : "Ativar"
13666
13679
  },
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(
13680
+ ms.status === "active" ? /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiPauseCircle, { size: 18 }) : /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiPlayCircle, { size: 18 })
13681
+ ), /* @__PURE__ */ import_react30.default.createElement(
13669
13682
  "button",
13670
13683
  {
13671
13684
  onClick: () => handleRemoveMilestone(ms.id),
13672
13685
  className: "p-2 rounded-lg hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-all",
13673
13686
  title: "Remover"
13674
13687
  },
13675
- /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiTrash2, { size: 18 })
13688
+ /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiTrash2, { size: 18 })
13676
13689
  ))
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))))
13690
+ ))) : /* @__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."))),
13691
+ /* @__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
13692
  )
13680
13693
  );
13681
13694
  }
@@ -13761,13 +13774,13 @@ function XViewScene({
13761
13774
  check_user_permission,
13762
13775
  get_view_members
13763
13776
  }) {
13764
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
13765
- const { data: session, status } = (0, import_react30.useSession)();
13777
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
13778
+ const { data: session, status } = (0, import_react32.useSession)();
13766
13779
  const router = (0, import_navigation.useRouter)();
13767
13780
  const searchParams = (0, import_navigation.useSearchParams)();
13768
13781
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
13769
13782
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
13770
- const viewParams = (0, import_react29.useMemo)(() => {
13783
+ const viewParams = (0, import_react31.useMemo)(() => {
13771
13784
  if (encryptedConfig) {
13772
13785
  const data = decryptData(encryptedConfig);
13773
13786
  if (data) {
@@ -13776,7 +13789,7 @@ function XViewScene({
13776
13789
  }
13777
13790
  return null;
13778
13791
  }, [encryptedConfig, session]);
13779
- (0, import_react29.useEffect)(() => {
13792
+ (0, import_react31.useEffect)(() => {
13780
13793
  async function verifyPermission() {
13781
13794
  if (!viewParams || !session || !check_user_permission) return;
13782
13795
  const { id, type, owner_id } = viewParams;
@@ -13813,65 +13826,65 @@ function XViewScene({
13813
13826
  setIsLoading(false);
13814
13827
  }
13815
13828
  }, [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)(() => {
13829
+ const sceneConfigId = (0, import_react31.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13830
+ const ownerId = (0, import_react31.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13831
+ const dbSaveUrl = (0, import_react31.useMemo)(() => {
13819
13832
  if (ownerId && sceneConfigId) {
13820
13833
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
13821
13834
  }
13822
13835
  return null;
13823
13836
  }, [ownerId, sceneConfigId]);
13824
- const sceneSaveUrl = (0, import_react29.useMemo)(() => {
13837
+ const sceneSaveUrl = (0, import_react31.useMemo)(() => {
13825
13838
  if (ownerId && sceneConfigId) {
13826
13839
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
13827
13840
  }
13828
13841
  return null;
13829
13842
  }, [ownerId, sceneConfigId]);
13830
- const ancestry_save_url = (0, import_react29.useMemo)(() => {
13843
+ const ancestry_save_url = (0, import_react31.useMemo)(() => {
13831
13844
  if (ownerId && sceneConfigId) {
13832
13845
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
13833
13846
  }
13834
13847
  return null;
13835
13848
  }, [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)({
13849
+ const sceneDataRef = (0, import_react31.useRef)(null);
13850
+ const parentDataRef = (0, import_react31.useRef)(null);
13851
+ const ancestryDataRef = (0, import_react31.useRef)(null);
13852
+ const [isLoading, setIsLoading] = (0, import_react31.useState)(true);
13853
+ const [permissionStatus, setPermissionStatus] = (0, import_react31.useState)("loading");
13854
+ const [userPermissionRole, setUserPermissionRole] = (0, import_react31.useState)(null);
13855
+ const [viewMembers, setViewMembers] = (0, import_react31.useState)([]);
13856
+ const [isInitialized, setIsInitialized] = (0, import_react31.useState)(false);
13857
+ const [sceneVersion, setSceneVersion] = (0, import_react31.useState)(0);
13858
+ const [contextMenu, setContextMenu] = (0, import_react31.useState)({
13846
13859
  visible: false,
13847
13860
  x: 0,
13848
13861
  y: 0,
13849
13862
  nodeData: null
13850
13863
  });
13851
- const [multiContextMenu, setMultiContextMenu] = (0, import_react29.useState)({
13864
+ const [multiContextMenu, setMultiContextMenu] = (0, import_react31.useState)({
13852
13865
  visible: false,
13853
13866
  x: 0,
13854
13867
  y: 0,
13855
13868
  nodeIds: null
13856
13869
  });
13857
- const [relationshipMenu, setRelationshipMenu] = (0, import_react29.useState)({
13870
+ const [relationshipMenu, setRelationshipMenu] = (0, import_react31.useState)({
13858
13871
  visible: false,
13859
13872
  x: 0,
13860
13873
  y: 0,
13861
13874
  linkObject: null
13862
13875
  });
13863
- const [creationMode, setCreationMode] = (0, import_react29.useState)({
13876
+ const [creationMode, setCreationMode] = (0, import_react31.useState)({
13864
13877
  isActive: false,
13865
13878
  sourceNodeData: null
13866
13879
  });
13867
- const [versionMode, setVersionMode] = (0, import_react29.useState)({
13880
+ const [versionMode, setVersionMode] = (0, import_react31.useState)({
13868
13881
  isActive: false,
13869
13882
  sourceNodeData: null
13870
13883
  });
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)({
13884
+ const [questMode, setQuestMode] = (0, import_react31.useState)({ isActive: false });
13885
+ const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react31.useState)(false);
13886
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react31.useState)(false);
13887
+ const [ancestryMode, setAncestryMode] = (0, import_react31.useState)({
13875
13888
  isActive: false,
13876
13889
  tree: null,
13877
13890
  selectedParentId: null,
@@ -13882,42 +13895,42 @@ function XViewScene({
13882
13895
  ancestryDescriptionSections: [],
13883
13896
  isAddingNodes: false
13884
13897
  });
13885
- const [readingMode, setReadingMode] = (0, import_react29.useState)({
13898
+ const [readingMode, setReadingMode] = (0, import_react31.useState)({
13886
13899
  isActive: false,
13887
13900
  ancestry: null,
13888
13901
  branchStack: [],
13889
13902
  autoAbstraction: false
13890
13903
  });
13891
- const [formPosition, setFormPosition] = (0, import_react29.useState)({
13904
+ const [formPosition, setFormPosition] = (0, import_react31.useState)({
13892
13905
  left: 16,
13893
13906
  top: 16,
13894
13907
  opacity: 0
13895
13908
  });
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)({
13909
+ const [detailsNode, setDetailsNode] = (0, import_react31.useState)(null);
13910
+ const [detailsLink, setDetailsLink] = (0, import_react31.useState)(null);
13911
+ const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react31.useState)(null);
13912
+ const [imageViewer, setImageViewer] = (0, import_react31.useState)({
13900
13913
  visible: false,
13901
13914
  images: [],
13902
13915
  startIndex: 0
13903
13916
  });
13904
- const [editingAncestryRel, setEditingAncestryRel] = (0, import_react29.useState)({
13917
+ const [editingAncestryRel, setEditingAncestryRel] = (0, import_react31.useState)({
13905
13918
  visible: false,
13906
13919
  data: null,
13907
13920
  path: null
13908
13921
  });
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)({
13922
+ const [isImportModalOpen, setIsImportModalOpen] = (0, import_react31.useState)(false);
13923
+ const [importSuccessMessage, setImportSuccessMessage] = (0, import_react31.useState)("");
13924
+ const [invalidTargetError, setInvalidTargetError] = (0, import_react31.useState)(null);
13925
+ const [highlightedNodeId, setHighlightedNodeId] = (0, import_react31.useState)(null);
13926
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react31.useState)(false);
13927
+ const [ancestryBoardData, setAncestryBoardData] = (0, import_react31.useState)([]);
13928
+ const [isSidebarOpen, setIsSidebarOpen] = (0, import_react31.useState)(false);
13929
+ const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = (0, import_react31.useState)(false);
13930
+ const mountRef = (0, import_react31.useRef)(null);
13931
+ const tooltipRef = (0, import_react31.useRef)(null);
13932
+ const formRef = (0, import_react31.useRef)(null);
13933
+ const stateRef = (0, import_react31.useRef)({
13921
13934
  readMode: {
13922
13935
  currentMaxIndex: 0,
13923
13936
  progressMap: {}
@@ -13981,10 +13994,10 @@ function XViewScene({
13981
13994
  minWidth: 320,
13982
13995
  maxWidth: maxReadPanelW
13983
13996
  });
13984
- (0, import_react29.useEffect)(() => {
13997
+ (0, import_react31.useEffect)(() => {
13985
13998
  stateRef.current.ancestry = ancestryMode;
13986
13999
  }, [ancestryMode]);
13987
- (0, import_react29.useEffect)(() => {
14000
+ (0, import_react31.useEffect)(() => {
13988
14001
  var _a2;
13989
14002
  if (!isInitialized) return;
13990
14003
  const map = /* @__PURE__ */ new Map();
@@ -14007,10 +14020,10 @@ function XViewScene({
14007
14020
  }
14008
14021
  stateRef.current.nodeIdToParentFileMap = map;
14009
14022
  }, [isInitialized, sceneVersion]);
14010
- const handleNavigateBack = (0, import_react29.useCallback)(() => {
14023
+ const handleNavigateBack = (0, import_react31.useCallback)(() => {
14011
14024
  router.push("/dashboard/scenes");
14012
14025
  }, [router]);
14013
- const handleConfirmImport = (0, import_react29.useCallback)(
14026
+ const handleConfirmImport = (0, import_react31.useCallback)(
14014
14027
  async (importPayload) => {
14015
14028
  var _a2, _b2;
14016
14029
  let files = [];
@@ -14138,7 +14151,7 @@ function XViewScene({
14138
14151
  const handleOpenImageViewer = (images, startIndex) => {
14139
14152
  setImageViewer({ visible: true, images, startIndex });
14140
14153
  };
14141
- const tweenToTarget = (0, import_react29.useCallback)(
14154
+ const tweenToTarget = (0, import_react31.useCallback)(
14142
14155
  (target, zoomFactor = 1, forcedDirection = null) => {
14143
14156
  const { camera, controls, tweenGroup } = stateRef.current;
14144
14157
  if (!camera || !controls || !tweenGroup) return;
@@ -14164,7 +14177,7 @@ function XViewScene({
14164
14177
  if (!t || typeof t.closest !== "function") return false;
14165
14178
  return !!t.closest(".ui-overlay");
14166
14179
  };
14167
- const buildFullAncestryTree = (0, import_react29.useCallback)(
14180
+ const buildFullAncestryTree = (0, import_react31.useCallback)(
14168
14181
  (idTree, nodes, ancestries = []) => {
14169
14182
  if (!idTree) return null;
14170
14183
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
@@ -14249,7 +14262,7 @@ function XViewScene({
14249
14262
  },
14250
14263
  []
14251
14264
  );
14252
- const handleActivateTimeline = (0, import_react29.useCallback)(() => {
14265
+ const handleActivateTimeline = (0, import_react31.useCallback)(() => {
14253
14266
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
14254
14267
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
14255
14268
  while (timelineIntervalsGroup.children.length > 0) {
@@ -14409,7 +14422,7 @@ function XViewScene({
14409
14422
  }
14410
14423
  });
14411
14424
  }, []);
14412
- const handleVersionTimeline = (0, import_react29.useCallback)((sourceMesh, versionMeshes) => {
14425
+ const handleVersionTimeline = (0, import_react31.useCallback)((sourceMesh, versionMeshes) => {
14413
14426
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
14414
14427
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
14415
14428
  return;
@@ -14546,7 +14559,7 @@ function XViewScene({
14546
14559
  }
14547
14560
  });
14548
14561
  }, []);
14549
- (0, import_react29.useEffect)(() => {
14562
+ (0, import_react31.useEffect)(() => {
14550
14563
  async function fetchAllData(configPath, ownerId2) {
14551
14564
  var _a2, _b2;
14552
14565
  if (!get_scene_view_data) {
@@ -14651,12 +14664,12 @@ function XViewScene({
14651
14664
  focusNodeId,
14652
14665
  focusAncestryId
14653
14666
  ]);
14654
- const isNodeInView = (0, import_react29.useCallback)((id) => {
14667
+ const isNodeInView = (0, import_react31.useCallback)((id) => {
14655
14668
  const key = String(id);
14656
14669
  const objs = stateRef.current.nodeObjects || {};
14657
14670
  return !!objs[key];
14658
14671
  }, []);
14659
- const addOrUpdateNodeMesh = (0, import_react29.useCallback)(
14672
+ const addOrUpdateNodeMesh = (0, import_react31.useCallback)(
14660
14673
  (nodeData, position, suppressVersionUpdate = false, forceShowQuestDate = false) => {
14661
14674
  const {
14662
14675
  graphGroup,
@@ -14697,7 +14710,7 @@ function XViewScene({
14697
14710
  },
14698
14711
  []
14699
14712
  );
14700
- const handleActivateQuestLens = (0, import_react29.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
14713
+ const handleActivateQuestLens = (0, import_react31.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
14701
14714
  var _a2;
14702
14715
  const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
14703
14716
  if (!nodeObjects || !tweenGroup || !graphGroup) return;
@@ -14911,7 +14924,7 @@ function XViewScene({
14911
14924
  camTween.start();
14912
14925
  }
14913
14926
  }, [addOrUpdateNodeMesh]);
14914
- (0, import_react29.useEffect)(() => {
14927
+ (0, import_react31.useEffect)(() => {
14915
14928
  if (!isInitialized || !sceneDataRef.current) return;
14916
14929
  const currentMount = mountRef.current;
14917
14930
  if (!currentMount) return;
@@ -15667,7 +15680,7 @@ function XViewScene({
15667
15680
  get_scene_view_data,
15668
15681
  save_view_data
15669
15682
  ]);
15670
- const handleGhostNodeImageChange = (0, import_react29.useCallback)((useImage, imageUrl) => {
15683
+ const handleGhostNodeImageChange = (0, import_react31.useCallback)((useImage, imageUrl) => {
15671
15684
  const {
15672
15685
  node: ghostNode,
15673
15686
  line: ghostLine,
@@ -15715,7 +15728,7 @@ function XViewScene({
15715
15728
  aura: newGhostNode.getObjectByName("aura")
15716
15729
  };
15717
15730
  }, []);
15718
- const handleGhostNodeIntensityChange = (0, import_react29.useCallback)((newIntensity) => {
15731
+ const handleGhostNodeIntensityChange = (0, import_react31.useCallback)((newIntensity) => {
15719
15732
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
15720
15733
  if (!ghostNode) return;
15721
15734
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -15736,7 +15749,7 @@ function XViewScene({
15736
15749
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
15737
15750
  }
15738
15751
  }, []);
15739
- const handleDetailNodeIntensityChange = (0, import_react29.useCallback)(
15752
+ const handleDetailNodeIntensityChange = (0, import_react31.useCallback)(
15740
15753
  (nodeId, newIntensity) => {
15741
15754
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
15742
15755
  if (!mesh) return;
@@ -15892,7 +15905,7 @@ function XViewScene({
15892
15905
  mountRef.current.style.cursor = "default";
15893
15906
  }
15894
15907
  };
15895
- const handleAncestryTreeUpdate = (0, import_react29.useCallback)((newTree, extraData = null) => {
15908
+ const handleAncestryTreeUpdate = (0, import_react31.useCallback)((newTree, extraData = null) => {
15896
15909
  setAncestryMode((prev) => {
15897
15910
  const prevTreeStr = JSON.stringify(prev.tree);
15898
15911
  const newTreeStr = JSON.stringify(newTree);
@@ -15915,7 +15928,7 @@ function XViewScene({
15915
15928
  };
15916
15929
  });
15917
15930
  }, []);
15918
- const actionHandlerContext = (0, import_react29.useMemo)(
15931
+ const actionHandlerContext = (0, import_react31.useMemo)(
15919
15932
  () => {
15920
15933
  var _a2;
15921
15934
  return {
@@ -15976,7 +15989,7 @@ function XViewScene({
15976
15989
  const handleStartVersioning = (nodeData) => {
15977
15990
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
15978
15991
  };
15979
- const handleStartQuestQuick = (0, import_react29.useCallback)((questNode) => {
15992
+ const handleStartQuestQuick = (0, import_react31.useCallback)((questNode) => {
15980
15993
  var _a2, _b2, _c2;
15981
15994
  if (!questNode || !actionHandlerContext) return;
15982
15995
  const allParentNodes = Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
@@ -16011,7 +16024,7 @@ function XViewScene({
16011
16024
  }
16012
16025
  setDetailsNode(updatedNode);
16013
16026
  }, [session, actionHandlerContext]);
16014
- const handleFinishQuestQuick = (0, import_react29.useCallback)((questNode) => {
16027
+ const handleFinishQuestQuick = (0, import_react31.useCallback)((questNode) => {
16015
16028
  var _a2, _b2, _c2, _d2;
16016
16029
  if (!questNode || !actionHandlerContext) return;
16017
16030
  const {
@@ -16085,7 +16098,7 @@ function XViewScene({
16085
16098
  setDetailsNode(null);
16086
16099
  }
16087
16100
  }, [session, actionHandlerContext, viewMembers, detailsNode]);
16088
- const handleCancelQuest = (0, import_react29.useCallback)(() => {
16101
+ const handleCancelQuest = (0, import_react31.useCallback)(() => {
16089
16102
  const { graphGroup, ghostElements } = stateRef.current;
16090
16103
  if (ghostElements.node && graphGroup) {
16091
16104
  if (ghostElements.node.userData.labelObject) {
@@ -16144,13 +16157,15 @@ function XViewScene({
16144
16157
  try {
16145
16158
  await actions.save_view_data(sceneSaveUrl2, sceneFileData);
16146
16159
  sceneDataRef2.current.quest_counter = currentCounter + 1;
16147
- sceneDataRef2.current.quest_nodes = sceneFileData.quest_nodes;
16148
- sceneDataRef2.current.quest_links = sceneFileData.quest_links;
16149
16160
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
16150
16161
  parentFileId: sceneConfigId2,
16151
16162
  ownerId: ownerId2,
16152
16163
  datasetName: "Quests Internas (View)"
16153
16164
  });
16165
+ sceneDataRef2.current.quest_nodes = [...graphDataRef.current[sceneConfigId2].nodes];
16166
+ if (parentDataRef.current[sceneConfigId2]) {
16167
+ parentDataRef.current[sceneConfigId2].nodes = [...graphDataRef.current[sceneConfigId2].nodes];
16168
+ }
16154
16169
  const finalPosition = stateRef2.current.ghostElements.node ? stateRef2.current.ghostElements.node.position.clone() : stateRef2.current.controls.target.clone();
16155
16170
  const { graphGroup, ghostElements } = stateRef2.current;
16156
16171
  if (ghostElements.node && graphGroup) {
@@ -16240,7 +16255,7 @@ function XViewScene({
16240
16255
  }
16241
16256
  userActionHandlers.handleCancelConnection(context);
16242
16257
  };
16243
- const handleClearAncestryVisuals = (0, import_react29.useCallback)((ancestryId) => {
16258
+ const handleClearAncestryVisuals = (0, import_react31.useCallback)((ancestryId) => {
16244
16259
  const { renderedAncestries, ancestryGroup } = stateRef.current;
16245
16260
  const renderIndex = renderedAncestries.findIndex(
16246
16261
  (a) => String(a.id) === String(ancestryId)
@@ -16258,7 +16273,7 @@ function XViewScene({
16258
16273
  );
16259
16274
  }
16260
16275
  }, []);
16261
- const handleRenderAncestry = (0, import_react29.useCallback)(
16276
+ const handleRenderAncestry = (0, import_react31.useCallback)(
16262
16277
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
16263
16278
  setContextMenu(
16264
16279
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16752,7 +16767,7 @@ function XViewScene({
16752
16767
  ancestryMode.isActive
16753
16768
  ]
16754
16769
  );
16755
- const handleRenderAbstractionTree = (0, import_react29.useCallback)(
16770
+ const handleRenderAbstractionTree = (0, import_react31.useCallback)(
16756
16771
  (ancestryObject, targetNodeId = null) => {
16757
16772
  setContextMenu(
16758
16773
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16840,7 +16855,7 @@ function XViewScene({
16840
16855
  handleClearAncestryVisuals
16841
16856
  ]
16842
16857
  );
16843
- const handleReadModeBranchNav = (0, import_react29.useCallback)(
16858
+ const handleReadModeBranchNav = (0, import_react31.useCallback)(
16844
16859
  (nodeId, action, direction = "right") => {
16845
16860
  const { ancestry, branchStack } = readingMode;
16846
16861
  if (!ancestry || !ancestry.tree) return;
@@ -17018,13 +17033,13 @@ function XViewScene({
17018
17033
  },
17019
17034
  [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
17020
17035
  );
17021
- const handleReadModeHighlight = (0, import_react29.useCallback)((nodeId) => {
17036
+ const handleReadModeHighlight = (0, import_react31.useCallback)((nodeId) => {
17022
17037
  if (stateRef.current.highlightedNodeId !== nodeId) {
17023
17038
  stateRef.current.highlightedNodeId = nodeId;
17024
17039
  }
17025
17040
  setHighlightedNodeId(nodeId);
17026
17041
  }, []);
17027
- const activeNodeBranches = (0, import_react29.useMemo)(() => {
17042
+ const activeNodeBranches = (0, import_react31.useMemo)(() => {
17028
17043
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
17029
17044
  return null;
17030
17045
  const fullTree = buildFullAncestryTree(
@@ -17068,7 +17083,7 @@ function XViewScene({
17068
17083
  readingMode.branchStack,
17069
17084
  ancestryDataRef.current
17070
17085
  ]);
17071
- const backNavigationInfo = (0, import_react29.useMemo)(() => {
17086
+ const backNavigationInfo = (0, import_react31.useMemo)(() => {
17072
17087
  const { branchStack } = readingMode;
17073
17088
  if (!branchStack || branchStack.length === 0) return null;
17074
17089
  const lastStep = branchStack[branchStack.length - 1];
@@ -17079,7 +17094,7 @@ function XViewScene({
17079
17094
  name: "Voltar para anterior"
17080
17095
  };
17081
17096
  }, [readingMode.branchStack]);
17082
- const getReadModeDisplayContext = (0, import_react29.useMemo)(() => {
17097
+ const getReadModeDisplayContext = (0, import_react31.useMemo)(() => {
17083
17098
  const { ancestry, branchStack } = readingMode;
17084
17099
  if (!ancestry) return null;
17085
17100
  if (branchStack.length === 0) {
@@ -17122,7 +17137,7 @@ function XViewScene({
17122
17137
  customProperties: branchProps
17123
17138
  };
17124
17139
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
17125
- const readModeAbstractionTree = (0, import_react29.useMemo)(() => {
17140
+ const readModeAbstractionTree = (0, import_react31.useMemo)(() => {
17126
17141
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
17127
17142
  return null;
17128
17143
  }
@@ -17141,7 +17156,7 @@ function XViewScene({
17141
17156
  buildFullAncestryTree,
17142
17157
  sceneVersion
17143
17158
  ]);
17144
- const handleStartReadingAncestry = (0, import_react29.useCallback)(
17159
+ const handleStartReadingAncestry = (0, import_react31.useCallback)(
17145
17160
  async (ancestryObject, renderMode = "full") => {
17146
17161
  setContextMenu(
17147
17162
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17184,7 +17199,7 @@ function XViewScene({
17184
17199
  },
17185
17200
  [handleRenderAncestry, handleRenderAbstractionTree]
17186
17201
  );
17187
- const handleReadModeSectionChange = (0, import_react29.useCallback)(
17202
+ const handleReadModeSectionChange = (0, import_react31.useCallback)(
17188
17203
  (activeSectionId) => {
17189
17204
  const { ancestry, branchStack } = readingMode;
17190
17205
  if (!ancestry || !readingMode.isActive) return;
@@ -17269,10 +17284,10 @@ function XViewScene({
17269
17284
  ancestryDataRef.current
17270
17285
  ]
17271
17286
  );
17272
- const handleCloseReadMode = (0, import_react29.useCallback)(() => {
17287
+ const handleCloseReadMode = (0, import_react31.useCallback)(() => {
17273
17288
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
17274
17289
  }, []);
17275
- const handleAncestrySectionChange = (0, import_react29.useCallback)(
17290
+ const handleAncestrySectionChange = (0, import_react31.useCallback)(
17276
17291
  (activeSectionId, ancestryOverride = null, rotation = 0) => {
17277
17292
  var _a2, _b2;
17278
17293
  const currentMode = stateRef.current.ancestry;
@@ -17334,7 +17349,7 @@ function XViewScene({
17334
17349
  },
17335
17350
  [handleRenderAncestry]
17336
17351
  );
17337
- const handleEditAncestry = (0, import_react29.useCallback)(
17352
+ const handleEditAncestry = (0, import_react31.useCallback)(
17338
17353
  async (ancestryObject) => {
17339
17354
  setContextMenu(
17340
17355
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17389,7 +17404,7 @@ function XViewScene({
17389
17404
  const handleSelectAncestryParent = (nodeId) => {
17390
17405
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
17391
17406
  };
17392
- const handleRemoveFromAncestry = (0, import_react29.useCallback)((pathToRemove) => {
17407
+ const handleRemoveFromAncestry = (0, import_react31.useCallback)((pathToRemove) => {
17393
17408
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
17394
17409
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
17395
17410
  return;
@@ -17414,7 +17429,7 @@ function XViewScene({
17414
17429
  return { ...prev, tree: newTree };
17415
17430
  });
17416
17431
  }, []);
17417
- const handleSaveAncestry = (0, import_react29.useCallback)(
17432
+ const handleSaveAncestry = (0, import_react31.useCallback)(
17418
17433
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
17419
17434
  const treeToUse = treeOverride || ancestryMode.tree;
17420
17435
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -17650,7 +17665,7 @@ function XViewScene({
17650
17665
  });
17651
17666
  setEditingAncestryRel({ visible: false, data: null, path: null });
17652
17667
  };
17653
- const handleDeleteAncestry = (0, import_react29.useCallback)(
17668
+ const handleDeleteAncestry = (0, import_react31.useCallback)(
17654
17669
  async (ancestryIdToDelete) => {
17655
17670
  if (!ancestryIdToDelete) {
17656
17671
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -17732,28 +17747,70 @@ function XViewScene({
17732
17747
  },
17733
17748
  [save_view_data, delete_file_action]
17734
17749
  );
17735
- const handleOpenAncestryBoard = (0, import_react29.useCallback)(() => {
17750
+ const handleOpenAncestryBoard = (0, import_react31.useCallback)(() => {
17736
17751
  setIsAncestryBoardOpen(true);
17737
17752
  }, []);
17738
- const handleSelectAncestryFromBoard = (0, import_react29.useCallback)(
17753
+ const allAvailableNodes = (0, import_react31.useMemo)(() => {
17754
+ if (!parentDataRef.current) return [];
17755
+ return Object.values(parentDataRef.current).flatMap(
17756
+ (fileData) => fileData.nodes || []
17757
+ );
17758
+ }, [sceneVersion, isInitialized]);
17759
+ const allAvailableAncestries = (0, import_react31.useMemo)(() => {
17760
+ return ancestryDataRef.current || [];
17761
+ }, [sceneVersion, isInitialized]);
17762
+ const handleOpenReference = (0, import_react31.useCallback)(
17763
+ (referenceData) => {
17764
+ const { type, id } = referenceData;
17765
+ if (type === "node") {
17766
+ const targetNode = allAvailableNodes.find(
17767
+ (n) => String(n.id) === String(id)
17768
+ );
17769
+ if (targetNode) {
17770
+ setAncestryLinkDetails(null);
17771
+ setDetailsLink(null);
17772
+ setDetailsNode(targetNode);
17773
+ const sceneMesh = stateRef.current.nodeObjects[String(id)];
17774
+ if (sceneMesh) {
17775
+ tweenToTarget(sceneMesh);
17776
+ }
17777
+ } else {
17778
+ alert("Node original n\xE3o encontrado neste contexto.");
17779
+ }
17780
+ } else if (type === "ancestry") {
17781
+ const targetAncestry = allAvailableAncestries.find(
17782
+ (a) => String(a.ancestry_id) === String(id)
17783
+ );
17784
+ if (targetAncestry) {
17785
+ setDetailsNode(null);
17786
+ setDetailsLink(null);
17787
+ setAncestryLinkDetails(null);
17788
+ handleEditAncestry(targetAncestry);
17789
+ } else {
17790
+ alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17791
+ }
17792
+ }
17793
+ },
17794
+ [
17795
+ allAvailableNodes,
17796
+ allAvailableAncestries,
17797
+ handleEditAncestry,
17798
+ tweenToTarget
17799
+ ]
17800
+ );
17801
+ const handleSelectAncestryFromBoard = (0, import_react31.useCallback)(
17739
17802
  (item) => {
17740
17803
  setIsAncestryBoardOpen(false);
17741
17804
  setIsSidebarOpen(false);
17742
- if (item.type === "ancestry" || !item.type) {
17805
+ if (item.type === "ancestry") {
17743
17806
  handleStartReadingAncestry(item);
17744
17807
  } 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
- }
17808
+ handleOpenReference({ type: "node", id: item.id });
17752
17809
  }
17753
17810
  },
17754
- [handleStartReadingAncestry, tweenToTarget]
17811
+ [handleStartReadingAncestry, handleOpenReference]
17755
17812
  );
17756
- const handleSaveAncestryBoard = (0, import_react29.useCallback)(
17813
+ const handleSaveAncestryBoard = (0, import_react31.useCallback)(
17757
17814
  async (groups) => {
17758
17815
  if (!sceneConfigId || !viewParams || !session) return;
17759
17816
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
@@ -17767,7 +17824,7 @@ function XViewScene({
17767
17824
  },
17768
17825
  [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
17769
17826
  );
17770
- const existingNodeTypes = (0, import_react29.useMemo)(() => {
17827
+ const existingNodeTypes = (0, import_react31.useMemo)(() => {
17771
17828
  if (!parentDataRef.current) {
17772
17829
  return [];
17773
17830
  }
@@ -17779,28 +17836,22 @@ function XViewScene({
17779
17836
  ).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
17780
17837
  return [...new Set(allTypes)];
17781
17838
  }, [parentDataRef.current, sceneVersion]);
17782
- const searchableDbNodes = (0, import_react29.useMemo)(() => {
17783
- var _a2;
17839
+ const searchableDbNodes = (0, import_react31.useMemo)(() => {
17784
17840
  if (!parentDataRef.current) {
17785
17841
  return [];
17786
17842
  }
17787
- const datasetsPool = Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17843
+ return Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17788
17844
  const datasetName = fileData.dataset_name || `Dataset #${dbId.substring(0, 6)}`;
17789
17845
  return (fileData.nodes || []).map((node) => ({
17790
17846
  ...node,
17791
17847
  dataset_name: datasetName
17792
17848
  }));
17849
+ }).filter((node) => {
17850
+ var _a2;
17851
+ return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
17793
17852
  });
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)(
17853
+ }, [parentDataRef.current, sceneVersion]);
17854
+ const handleAddExistingNode = (0, import_react31.useCallback)(
17804
17855
  (nodeId) => {
17805
17856
  return userActionHandlers.handleAddExistingNodeById(
17806
17857
  actionHandlerContext,
@@ -17809,7 +17860,7 @@ function XViewScene({
17809
17860
  },
17810
17861
  [actionHandlerContext]
17811
17862
  );
17812
- const handleUpdateMilestones = (0, import_react29.useCallback)(
17863
+ const handleUpdateMilestones = (0, import_react31.useCallback)(
17813
17864
  async (newMilestones) => {
17814
17865
  var _a2, _b2, _c2;
17815
17866
  if (!sceneDataRef.current) return;
@@ -17855,7 +17906,7 @@ function XViewScene({
17855
17906
  viewParams == null ? void 0 : viewParams.type
17856
17907
  ]
17857
17908
  );
17858
- const handleSaveCurrentView = (0, import_react29.useCallback)(async () => {
17909
+ const handleSaveCurrentView = (0, import_react31.useCallback)(async () => {
17859
17910
  var _a2, _b2, _c2;
17860
17911
  const { nodeObjects, allLinks } = stateRef.current;
17861
17912
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
@@ -17898,61 +17949,13 @@ function XViewScene({
17898
17949
  console.error("Erro na chamada de save_view_data:", error);
17899
17950
  }
17900
17951
  }, [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)(() => {
17952
+ const handleToggleAncestryAddMode = (0, import_react31.useCallback)(() => {
17950
17953
  setAncestryMode((prev) => ({
17951
17954
  ...prev,
17952
17955
  isAddingNodes: !prev.isAddingNodes
17953
17956
  }));
17954
17957
  }, []);
17955
- const handleFocusNode = (0, import_react29.useCallback)(
17958
+ const handleFocusNode = (0, import_react31.useCallback)(
17956
17959
  (nodeData) => {
17957
17960
  var _a2;
17958
17961
  if (!nodeData) return;
@@ -17968,7 +17971,7 @@ function XViewScene({
17968
17971
  },
17969
17972
  [tweenToTarget]
17970
17973
  );
17971
- const availableDatasets = (0, import_react29.useMemo)(() => {
17974
+ const availableDatasets = (0, import_react31.useMemo)(() => {
17972
17975
  if (!sceneDataRef.current || !parentDataRef.current) return [];
17973
17976
  return sceneDataRef.current.parent_dbs.map((db) => {
17974
17977
  var _a2;
@@ -17978,11 +17981,11 @@ function XViewScene({
17978
17981
  };
17979
17982
  });
17980
17983
  }, [sceneVersion, isInitialized]);
17981
- const sourceNodeDatasetId = creationMode.sourceNodeData ? (_c = stateRef.current.nodeIdToParentFileMap.get(
17984
+ const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(
17982
17985
  String(creationMode.sourceNodeData.id)
17983
- )) == null ? void 0 : _c.parentFileId : null;
17986
+ )) == null ? void 0 : _b.parentFileId : null;
17984
17987
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
17985
- (0, import_react29.useEffect)(() => {
17988
+ (0, import_react31.useEffect)(() => {
17986
17989
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
17987
17990
  const nodeObjects = stateRef.current.nodeObjects || {};
17988
17991
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -18005,7 +18008,7 @@ function XViewScene({
18005
18008
  hasFocusedInitial,
18006
18009
  tweenToTarget
18007
18010
  ]);
18008
- (0, import_react29.useEffect)(() => {
18011
+ (0, import_react31.useEffect)(() => {
18009
18012
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
18010
18013
  const ancestries = ancestryDataRef.current || [];
18011
18014
  const targetAncestry = ancestries.find(
@@ -18030,7 +18033,7 @@ function XViewScene({
18030
18033
  hasOpenedInitialAncestry,
18031
18034
  handleStartReadingAncestry
18032
18035
  ]);
18033
- (0, import_react29.useEffect)(() => {
18036
+ (0, import_react31.useEffect)(() => {
18034
18037
  function handleKeyDown(event) {
18035
18038
  var _a2, _b2, _c2;
18036
18039
  const context = actionHandlerContext;
@@ -18153,10 +18156,10 @@ function XViewScene({
18153
18156
  // <-- handleCancelQuest adicionado aqui
18154
18157
  ]);
18155
18158
  if (isLoading || status === "loading" || permissionStatus === "loading") {
18156
- return /* @__PURE__ */ import_react29.default.createElement(LoadingScreen, null);
18159
+ return /* @__PURE__ */ import_react31.default.createElement(LoadingScreen, null);
18157
18160
  }
18158
18161
  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(
18162
+ 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
18163
  "svg",
18161
18164
  {
18162
18165
  xmlns: "http://www.w3.org/2000/svg",
@@ -18166,7 +18169,7 @@ function XViewScene({
18166
18169
  stroke: "currentColor",
18167
18170
  className: "w-16 h-16 mx-auto"
18168
18171
  },
18169
- /* @__PURE__ */ import_react29.default.createElement(
18172
+ /* @__PURE__ */ import_react31.default.createElement(
18170
18173
  "path",
18171
18174
  {
18172
18175
  strokeLinecap: "round",
@@ -18174,13 +18177,13 @@ function XViewScene({
18174
18177
  d: "M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
18175
18178
  }
18176
18179
  )
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(
18180
+ )), /* @__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
18181
  "button",
18179
18182
  {
18180
18183
  onClick: () => router.push("/dashboard/scenes"),
18181
18184
  className: "flex items-center justify-center gap-2 w-full py-3 px-4 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors font-medium"
18182
18185
  },
18183
- /* @__PURE__ */ import_react29.default.createElement(
18186
+ /* @__PURE__ */ import_react31.default.createElement(
18184
18187
  "svg",
18185
18188
  {
18186
18189
  xmlns: "http://www.w3.org/2000/svg",
@@ -18190,7 +18193,7 @@ function XViewScene({
18190
18193
  stroke: "currentColor",
18191
18194
  className: "w-5 h-5"
18192
18195
  },
18193
- /* @__PURE__ */ import_react29.default.createElement(
18196
+ /* @__PURE__ */ import_react31.default.createElement(
18194
18197
  "path",
18195
18198
  {
18196
18199
  strokeLinecap: "round",
@@ -18202,7 +18205,7 @@ function XViewScene({
18202
18205
  "Voltar para Scenes"
18203
18206
  )));
18204
18207
  }
18205
- return /* @__PURE__ */ import_react29.default.createElement(
18208
+ return /* @__PURE__ */ import_react31.default.createElement(
18206
18209
  "div",
18207
18210
  {
18208
18211
  ref: mountRef,
@@ -18214,7 +18217,7 @@ function XViewScene({
18214
18217
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
18215
18218
  }
18216
18219
  },
18217
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react29.default.createElement(
18220
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react31.default.createElement(
18218
18221
  XViewSidebar,
18219
18222
  {
18220
18223
  dbNodes: searchableDbNodes,
@@ -18234,11 +18237,11 @@ function XViewScene({
18234
18237
  onToggle: setIsSidebarOpen,
18235
18238
  userRole: userPermissionRole,
18236
18239
  viewMembers,
18237
- milestones: ((_d = sceneDataRef.current) == null ? void 0 : _d.milestones) || [],
18240
+ milestones: ((_c = sceneDataRef.current) == null ? void 0 : _c.milestones) || [],
18238
18241
  onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
18239
18242
  }
18240
18243
  ),
18241
- creationMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18244
+ creationMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
18242
18245
  InSceneCreationForm,
18243
18246
  {
18244
18247
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -18259,8 +18262,8 @@ function XViewScene({
18259
18262
  },
18260
18263
  refEl: formRef,
18261
18264
  existingTypes: existingNodeTypes,
18262
- initialColor: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.color,
18263
- sourceTypes: (_f = creationMode.sourceNodeData) == null ? void 0 : _f.type,
18265
+ initialColor: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.color,
18266
+ sourceTypes: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.type,
18264
18267
  onIntensityChange: handleGhostNodeIntensityChange,
18265
18268
  onUploadFile: upload_file_action,
18266
18269
  availableDatasets,
@@ -18270,7 +18273,7 @@ function XViewScene({
18270
18273
  availableAncestries: allAvailableAncestries
18271
18274
  }
18272
18275
  ),
18273
- versionMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18276
+ versionMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
18274
18277
  InSceneVersionForm,
18275
18278
  {
18276
18279
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -18289,14 +18292,14 @@ function XViewScene({
18289
18292
  transition: "opacity 200ms ease-out"
18290
18293
  },
18291
18294
  refEl: formRef,
18292
- fixedType: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.type,
18293
- fixedColor: (_h = versionMode.sourceNodeData) == null ? void 0 : _h.color,
18295
+ fixedType: (_f = versionMode.sourceNodeData) == null ? void 0 : _f.type,
18296
+ fixedColor: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.color,
18294
18297
  onUploadFile: upload_file_action,
18295
18298
  availableNodes: allAvailableNodes,
18296
18299
  availableAncestries: allAvailableAncestries
18297
18300
  }
18298
18301
  ),
18299
- questMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18302
+ questMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
18300
18303
  InSceneQuestForm,
18301
18304
  {
18302
18305
  onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
@@ -18318,13 +18321,13 @@ function XViewScene({
18318
18321
  availableNodes: allAvailableNodes,
18319
18322
  availableAncestries: allAvailableAncestries,
18320
18323
  viewName: viewParams == null ? void 0 : viewParams.name,
18321
- questCounter: ((_i = sceneDataRef.current) == null ? void 0 : _i.quest_counter) || 1,
18324
+ questCounter: ((_h = sceneDataRef.current) == null ? void 0 : _h.quest_counter) || 1,
18322
18325
  viewMembers,
18323
- milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18326
+ milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
18324
18327
  onUpdateMilestones: handleUpdateMilestones
18325
18328
  }
18326
18329
  ),
18327
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react29.default.createElement(
18330
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react31.default.createElement(
18328
18331
  "div",
18329
18332
  {
18330
18333
  className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col ${isReadModeResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
@@ -18337,7 +18340,7 @@ function XViewScene({
18337
18340
  maxWidth: "92vw"
18338
18341
  }
18339
18342
  },
18340
- /* @__PURE__ */ import_react29.default.createElement(
18343
+ /* @__PURE__ */ import_react31.default.createElement(
18341
18344
  "div",
18342
18345
  {
18343
18346
  onPointerDown: (e) => {
@@ -18348,7 +18351,7 @@ function XViewScene({
18348
18351
  title: "Arraste para redimensionar"
18349
18352
  }
18350
18353
  ),
18351
- /* @__PURE__ */ import_react29.default.createElement(
18354
+ /* @__PURE__ */ import_react31.default.createElement(
18352
18355
  DescriptionReadModePanel,
18353
18356
  {
18354
18357
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -18383,7 +18386,7 @@ function XViewScene({
18383
18386
  }
18384
18387
  )
18385
18388
  ),
18386
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react29.default.createElement(
18389
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react31.default.createElement(
18387
18390
  CreateAncestryPanel,
18388
18391
  {
18389
18392
  ancestryMode,
@@ -18419,7 +18422,7 @@ function XViewScene({
18419
18422
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
18420
18423
  }
18421
18424
  ),
18422
- editingAncestryRel.visible && /* @__PURE__ */ import_react29.default.createElement(
18425
+ editingAncestryRel.visible && /* @__PURE__ */ import_react31.default.createElement(
18423
18426
  AncestryRelationshipPanel,
18424
18427
  {
18425
18428
  data: editingAncestryRel.data,
@@ -18433,7 +18436,7 @@ function XViewScene({
18433
18436
  onUploadFile: upload_file_action
18434
18437
  }
18435
18438
  ),
18436
- detailsNode && detailsNode.is_quest && /* @__PURE__ */ import_react29.default.createElement(
18439
+ detailsNode && detailsNode.is_quest && /* @__PURE__ */ import_react31.default.createElement(
18437
18440
  QuestDetailsPanel,
18438
18441
  {
18439
18442
  node: detailsNode,
@@ -18455,11 +18458,11 @@ function XViewScene({
18455
18458
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
18456
18459
  viewMembers,
18457
18460
  currentUser: session == null ? void 0 : session.user,
18458
- milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18461
+ milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18459
18462
  onUpdateMilestones: handleUpdateMilestones
18460
18463
  }
18461
18464
  ),
18462
- detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react29.default.createElement(
18465
+ detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react31.default.createElement(
18463
18466
  NodeDetailsPanel,
18464
18467
  {
18465
18468
  node: detailsNode,
@@ -18491,7 +18494,7 @@ function XViewScene({
18491
18494
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
18492
18495
  }
18493
18496
  ),
18494
- detailsLink && /* @__PURE__ */ import_react29.default.createElement(
18497
+ detailsLink && /* @__PURE__ */ import_react31.default.createElement(
18495
18498
  RelationshipDetailsPanel,
18496
18499
  {
18497
18500
  link: detailsLink,
@@ -18505,7 +18508,7 @@ function XViewScene({
18505
18508
  userRole: userPermissionRole
18506
18509
  }
18507
18510
  ),
18508
- ancestryLinkDetails && /* @__PURE__ */ import_react29.default.createElement(
18511
+ ancestryLinkDetails && /* @__PURE__ */ import_react31.default.createElement(
18509
18512
  AncestryLinkDetailsPanel,
18510
18513
  {
18511
18514
  data: ancestryLinkDetails,
@@ -18516,7 +18519,7 @@ function XViewScene({
18516
18519
  onUploadFile: upload_file_action
18517
18520
  }
18518
18521
  ),
18519
- /* @__PURE__ */ import_react29.default.createElement(
18522
+ /* @__PURE__ */ import_react31.default.createElement(
18520
18523
  "div",
18521
18524
  {
18522
18525
  ref: tooltipRef,
@@ -18543,7 +18546,7 @@ function XViewScene({
18543
18546
  }
18544
18547
  }
18545
18548
  ),
18546
- /* @__PURE__ */ import_react29.default.createElement(
18549
+ /* @__PURE__ */ import_react31.default.createElement(
18547
18550
  ContextMenu,
18548
18551
  {
18549
18552
  data: contextMenu,
@@ -18576,7 +18579,7 @@ function XViewScene({
18576
18579
  onFinishQuest: handleFinishQuestQuick
18577
18580
  }
18578
18581
  ),
18579
- /* @__PURE__ */ import_react29.default.createElement(
18582
+ /* @__PURE__ */ import_react31.default.createElement(
18580
18583
  MultiNodeContextMenu,
18581
18584
  {
18582
18585
  data: multiContextMenu,
@@ -18596,7 +18599,7 @@ function XViewScene({
18596
18599
  )
18597
18600
  }
18598
18601
  ),
18599
- /* @__PURE__ */ import_react29.default.createElement(
18602
+ /* @__PURE__ */ import_react31.default.createElement(
18600
18603
  RelationshipContextMenu,
18601
18604
  {
18602
18605
  data: relationshipMenu,
@@ -18614,14 +18617,14 @@ function XViewScene({
18614
18617
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
18615
18618
  }
18616
18619
  ),
18617
- /* @__PURE__ */ import_react29.default.createElement(
18620
+ /* @__PURE__ */ import_react31.default.createElement(
18618
18621
  ImageViewer,
18619
18622
  {
18620
18623
  data: imageViewer,
18621
18624
  onClose: () => setImageViewer({ ...imageViewer, visible: false })
18622
18625
  }
18623
18626
  ),
18624
- /* @__PURE__ */ import_react29.default.createElement(
18627
+ /* @__PURE__ */ import_react31.default.createElement(
18625
18628
  AncestryBoard,
18626
18629
  {
18627
18630
  isOpen: isAncestryBoardOpen,
@@ -18634,29 +18637,29 @@ function XViewScene({
18634
18637
  userRole: userPermissionRole
18635
18638
  }
18636
18639
  ),
18637
- /* @__PURE__ */ import_react29.default.createElement(
18640
+ /* @__PURE__ */ import_react31.default.createElement(
18638
18641
  MilestoneManager,
18639
18642
  {
18640
18643
  isOpen: isMilestoneManagerOpen,
18641
18644
  onClose: () => setIsMilestoneManagerOpen(false),
18642
- milestones: ((_l = sceneDataRef.current) == null ? void 0 : _l.milestones) || [],
18645
+ milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18643
18646
  onUpdateMilestones: handleUpdateMilestones
18644
18647
  }
18645
18648
  ),
18646
- /* @__PURE__ */ import_react29.default.createElement(
18649
+ /* @__PURE__ */ import_react31.default.createElement(
18647
18650
  ImportParentFileModal,
18648
18651
  {
18649
18652
  isOpen: isImportModalOpen,
18650
18653
  onClose: () => setIsImportModalOpen(false),
18651
18654
  onConfirm: handleConfirmImport,
18652
18655
  session,
18653
- parentDbs: ((_m = sceneDataRef.current) == null ? void 0 : _m.parent_dbs) || [],
18656
+ parentDbs: ((_l = sceneDataRef.current) == null ? void 0 : _l.parent_dbs) || [],
18654
18657
  onFetchAvailableFiles: import_parent_file_modal_get,
18655
18658
  currentViewName: viewParams == null ? void 0 : viewParams.name,
18656
18659
  currentAncestries: ancestryDataRef.current || []
18657
18660
  }
18658
18661
  ),
18659
- invalidTargetError && /* @__PURE__ */ import_react29.default.createElement(
18662
+ invalidTargetError && /* @__PURE__ */ import_react31.default.createElement(
18660
18663
  "div",
18661
18664
  {
18662
18665
  className: "ui-overlay",
@@ -18681,13 +18684,13 @@ function XViewScene({
18681
18684
  animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
18682
18685
  }
18683
18686
  },
18684
- /* @__PURE__ */ import_react29.default.createElement("style", null, `
18687
+ /* @__PURE__ */ import_react31.default.createElement("style", null, `
18685
18688
  @keyframes fadeInDown {
18686
18689
  from { opacity: 0; transform: translate(-50%, -20px); }
18687
18690
  to { opacity: 1; transform: translate(-50%, 0); }
18688
18691
  }
18689
18692
  `),
18690
- /* @__PURE__ */ import_react29.default.createElement(
18693
+ /* @__PURE__ */ import_react31.default.createElement(
18691
18694
  "svg",
18692
18695
  {
18693
18696
  width: "20",
@@ -18699,12 +18702,12 @@ function XViewScene({
18699
18702
  strokeLinecap: "round",
18700
18703
  strokeLinejoin: "round"
18701
18704
  },
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" })
18705
+ /* @__PURE__ */ import_react31.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18706
+ /* @__PURE__ */ import_react31.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18707
+ /* @__PURE__ */ import_react31.default.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18705
18708
  ),
18706
- /* @__PURE__ */ import_react29.default.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18707
- /* @__PURE__ */ import_react29.default.createElement(
18709
+ /* @__PURE__ */ import_react31.default.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18710
+ /* @__PURE__ */ import_react31.default.createElement(
18708
18711
  "button",
18709
18712
  {
18710
18713
  onClick: () => setInvalidTargetError(null),