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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.js +581 -529
  2. package/dist/index.mjs +553 -487
  3. package/package.json +12 -3
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_react32 = __toESM(require("react"));
48
48
  var import_navigation = require("next/navigation");
49
- var import_react30 = require("next-auth/react");
49
+ var import_react33 = 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
@@ -2357,6 +2309,8 @@ var userActionHandlers = {
2357
2309
  milestones: sceneDataRef.current.milestones || [],
2358
2310
  quest_counter: sceneDataRef.current.quest_counter || 1
2359
2311
  };
2312
+ sceneDataRef.current.quest_nodes = specificParentData.nodes;
2313
+ sceneDataRef.current.quest_links = specificParentData.links;
2360
2314
  await context.actions.save_view_data(
2361
2315
  context.sceneSaveUrl,
2362
2316
  viewFilePayload
@@ -2517,15 +2471,15 @@ function createNewCustomProperty(existingProps = []) {
2517
2471
  switch (nextType) {
2518
2472
  case "links":
2519
2473
  nextKey = "Links";
2520
- nextValue = [{ id: v4_default(), name: "", value: "" }];
2474
+ nextValue = [{ id: (0, import_uuid.v4)(), name: "", value: "" }];
2521
2475
  break;
2522
2476
  case "images":
2523
2477
  nextKey = "Images";
2524
- nextValue = [{ id: v4_default(), name: "1", value: "" }];
2478
+ nextValue = [{ id: (0, import_uuid.v4)(), name: "1", value: "" }];
2525
2479
  break;
2526
2480
  case "documents":
2527
2481
  nextKey = "Documents";
2528
- nextValue = [{ id: v4_default(), name: "1", value: "" }];
2482
+ nextValue = [{ id: (0, import_uuid.v4)(), name: "1", value: "" }];
2529
2483
  break;
2530
2484
  case "date":
2531
2485
  nextKey = "Date";
@@ -2535,14 +2489,14 @@ function createNewCustomProperty(existingProps = []) {
2535
2489
  nextValue = 0;
2536
2490
  break;
2537
2491
  case "list":
2538
- nextValue = [{ id: v4_default(), name: "", value: "" }];
2492
+ nextValue = [{ id: (0, import_uuid.v4)(), name: "", value: "" }];
2539
2493
  break;
2540
2494
  default:
2541
2495
  nextValue = "";
2542
2496
  break;
2543
2497
  }
2544
2498
  return {
2545
- id: v4_default(),
2499
+ id: (0, import_uuid.v4)(),
2546
2500
  key: nextKey,
2547
2501
  type: nextType,
2548
2502
  value: nextValue,
@@ -2787,7 +2741,7 @@ function extractCustomPropsFromNode(node) {
2787
2741
  if (val && typeof val === "object") {
2788
2742
  if ("date_interval" in val) {
2789
2743
  return {
2790
- id: v4_default(),
2744
+ id: (0, import_uuid.v4)(),
2791
2745
  key,
2792
2746
  type: "date",
2793
2747
  value: {
@@ -2799,7 +2753,7 @@ function extractCustomPropsFromNode(node) {
2799
2753
  }
2800
2754
  if ("year" in val) {
2801
2755
  return {
2802
- id: v4_default(),
2756
+ id: (0, import_uuid.v4)(),
2803
2757
  key,
2804
2758
  type: "date",
2805
2759
  value: { type: "Ano", value: val.year || "" }
@@ -2807,7 +2761,7 @@ function extractCustomPropsFromNode(node) {
2807
2761
  }
2808
2762
  if ("date" in val) {
2809
2763
  return {
2810
- id: v4_default(),
2764
+ id: (0, import_uuid.v4)(),
2811
2765
  key,
2812
2766
  type: "date",
2813
2767
  value: { type: "Data", value: val.date || "" }
@@ -2815,7 +2769,7 @@ function extractCustomPropsFromNode(node) {
2815
2769
  }
2816
2770
  }
2817
2771
  return {
2818
- id: v4_default(),
2772
+ id: (0, import_uuid.v4)(),
2819
2773
  key,
2820
2774
  type: "date",
2821
2775
  value: { type: "Data", value: "" }
@@ -2823,14 +2777,14 @@ function extractCustomPropsFromNode(node) {
2823
2777
  }
2824
2778
  if (t === "list" || t === "links" || t === "images" || t === "documents") {
2825
2779
  const safeList = (val || []).map((item) => ({
2826
- id: item.id || v4_default(),
2780
+ id: item.id || (0, import_uuid.v4)(),
2827
2781
  name: item.name ?? "",
2828
2782
  value: item.value ?? ""
2829
2783
  }));
2830
- return { id: v4_default(), key, type: t, value: safeList };
2784
+ return { id: (0, import_uuid.v4)(), key, type: t, value: safeList };
2831
2785
  }
2832
2786
  return {
2833
- id: v4_default(),
2787
+ id: (0, import_uuid.v4)(),
2834
2788
  key,
2835
2789
  type: t,
2836
2790
  value: t === "number" ? Number(val) || 0 : String(val ?? "")
@@ -3103,16 +3057,16 @@ var processDescriptionForSave = (text, existingSections = []) => {
3103
3057
  if (existingMatch) {
3104
3058
  finalUuid = existingMatch.id;
3105
3059
  } else {
3106
- finalUuid = v4_default();
3060
+ finalUuid = (0, import_uuid.v4)();
3107
3061
  }
3108
3062
  } else {
3109
3063
  finalUuid = numericMap.get(numStr);
3110
3064
  if (!finalUuid) {
3111
- finalUuid = v4_default();
3065
+ finalUuid = (0, import_uuid.v4)();
3112
3066
  }
3113
3067
  }
3114
3068
  if (usedIds.has(finalUuid)) {
3115
- finalUuid = v4_default();
3069
+ finalUuid = (0, import_uuid.v4)();
3116
3070
  }
3117
3071
  usedIds.add(finalUuid);
3118
3072
  processedSections.push({
@@ -3223,18 +3177,18 @@ function useResizablePanel({ initialWidth, minWidth, maxWidth }) {
3223
3177
  function createTimelineEntry(actorId, description, type = "comment", extras = {}) {
3224
3178
  const { links = [], images = [], metadata = {} } = extras;
3225
3179
  return {
3226
- id: v4_default(),
3180
+ id: (0, import_uuid.v4)(),
3227
3181
  type,
3228
3182
  timestamp: Date.now(),
3229
3183
  actorId,
3230
3184
  description,
3231
3185
  links: links.map((l) => ({
3232
- id: l.id || v4_default(),
3186
+ id: l.id || (0, import_uuid.v4)(),
3233
3187
  name: l.name || "",
3234
3188
  value: l.value || ""
3235
3189
  })),
3236
3190
  images: images.map((img) => ({
3237
- id: img.id || v4_default(),
3191
+ id: img.id || (0, import_uuid.v4)(),
3238
3192
  name: img.name || "",
3239
3193
  value: img.value || ""
3240
3194
  }))
@@ -4461,6 +4415,7 @@ function XViewSidebar({
4461
4415
 
4462
4416
  // src/components/AncestryRelationshipPanel.jsx
4463
4417
  var import_react9 = __toESM(require("react"));
4418
+ var import_uuid3 = require("uuid");
4464
4419
 
4465
4420
  // src/components/CustomPropertyDisplay.jsx
4466
4421
  var import_react4 = __toESM(require("react"));
@@ -5220,6 +5175,7 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
5220
5175
  }
5221
5176
 
5222
5177
  // src/components/DescriptionEditModal.jsx
5178
+ var import_uuid2 = require("uuid");
5223
5179
  var getNextSectionNumber = (currentText) => {
5224
5180
  const regex = /\*\/\s*(\d+)(?::[a-zA-Z0-9-]+)?\s*\//g;
5225
5181
  let max = 0;
@@ -5351,7 +5307,7 @@ function DescriptionEditModal({
5351
5307
  const el = textareaRef.current;
5352
5308
  if (!el) return;
5353
5309
  const nextNum = getNextSectionNumber(text);
5354
- const uniqueSuffix = v4_default().slice(0, 4);
5310
+ const uniqueSuffix = (0, import_uuid2.v4)().slice(0, 4);
5355
5311
  insertAtCursor(`*/${nextNum}:${uniqueSuffix}/ `);
5356
5312
  };
5357
5313
  const handleImportSelect = (tags) => {
@@ -5362,7 +5318,7 @@ function DescriptionEditModal({
5362
5318
  let currentNum = getNextSectionNumber(currentText);
5363
5319
  let blockToInsert = "";
5364
5320
  tagsArray.forEach((tag) => {
5365
- const uniqueSuffix = v4_default().slice(0, 4);
5321
+ const uniqueSuffix = (0, import_uuid2.v4)().slice(0, 4);
5366
5322
  blockToInsert += `
5367
5323
  */${currentNum}:${uniqueSuffix}/ ${tag}
5368
5324
  `;
@@ -6691,6 +6647,7 @@ function AncestryRelationshipPanel({
6691
6647
  // src/components/CreateAncestryPanel.jsx
6692
6648
  var import_react11 = __toESM(require("react"));
6693
6649
  var import_fi10 = require("react-icons/fi");
6650
+ var import_uuid4 = require("uuid");
6694
6651
 
6695
6652
  // src/components/AncestryPickerModal.jsx
6696
6653
  var import_react10 = __toESM(require("react"));
@@ -7727,7 +7684,7 @@ function CreateAncestryPanel({
7727
7684
  const nodeData = availableNodes.find((n) => String(n.id) === String(nodeId));
7728
7685
  const dirSuffix = direction === "left" ? "(Esq)" : "(Dir)";
7729
7686
  branch = {
7730
- id: v4_default(),
7687
+ id: (0, import_uuid4.v4)(),
7731
7688
  name: `Ramifica\xE7\xE3o ${dirSuffix} de ${(nodeData == null ? void 0 : nodeData.name) || "Node"}`,
7732
7689
  description: "",
7733
7690
  description_sections: [],
@@ -8506,6 +8463,7 @@ function ImageViewer({ data, onClose }) {
8506
8463
 
8507
8464
  // src/components/InSceneCreationForm.jsx
8508
8465
  var import_react14 = __toESM(require("react"));
8466
+ var import_uuid5 = require("uuid");
8509
8467
 
8510
8468
  // src/components/ColorPicker.jsx
8511
8469
  var import_react13 = __toESM(require("react"));
@@ -9082,6 +9040,7 @@ function InSceneCreationForm({
9082
9040
 
9083
9041
  // src/components/InSceneVersionForm.jsx
9084
9042
  var import_react15 = __toESM(require("react"));
9043
+ var import_uuid6 = require("uuid");
9085
9044
  var import_fi14 = require("react-icons/fi");
9086
9045
  function InSceneVersionForm({
9087
9046
  onSave,
@@ -9104,7 +9063,7 @@ function InSceneVersionForm({
9104
9063
  const [description, setDescription] = (0, import_react15.useState)("");
9105
9064
  const [customProps, setCustomProps] = (0, import_react15.useState)([
9106
9065
  {
9107
- id: v4_default(),
9066
+ id: (0, import_uuid6.v4)(),
9108
9067
  key: "Date",
9109
9068
  type: "date",
9110
9069
  value: { type: "Data", value: "" },
@@ -9397,6 +9356,7 @@ function InSceneVersionForm({
9397
9356
 
9398
9357
  // src/components/InSceneQuestForm.jsx
9399
9358
  var import_react17 = __toESM(require("react"));
9359
+ var import_uuid7 = require("uuid");
9400
9360
  var import_fi16 = require("react-icons/fi");
9401
9361
 
9402
9362
  // src/components/QuestReviewStackEditor.jsx
@@ -10302,6 +10262,7 @@ function InSceneQuestForm({
10302
10262
 
10303
10263
  // src/components/NodeDetailsPanel.jsx
10304
10264
  var import_react18 = __toESM(require("react"));
10265
+ var import_uuid8 = require("uuid");
10305
10266
  var import_fi17 = require("react-icons/fi");
10306
10267
  function NodeDetailsPanel({
10307
10268
  node,
@@ -10816,6 +10777,7 @@ function NodeDetailsPanel({
10816
10777
 
10817
10778
  // src/components/QuestDetailsPanel.jsx
10818
10779
  var import_react20 = __toESM(require("react"));
10780
+ var import_uuid9 = require("uuid");
10819
10781
  var import_fi19 = require("react-icons/fi");
10820
10782
 
10821
10783
  // src/components/QuestTimeline.jsx
@@ -11254,7 +11216,7 @@ ${noteText}` : noteText : entry.notes,
11254
11216
  }, 100);
11255
11217
  };
11256
11218
  const addLinkToNote = () => {
11257
- setNoteLinks([...noteLinks, { id: v4_default(), name: "", value: "" }]);
11219
+ setNoteLinks([...noteLinks, { id: (0, import_uuid9.v4)(), name: "", value: "" }]);
11258
11220
  };
11259
11221
  const removeLinkFromNote = (id) => {
11260
11222
  setNoteLinks(noteLinks.filter((l) => l.id !== id));
@@ -11263,7 +11225,7 @@ ${noteText}` : noteText : entry.notes,
11263
11225
  setNoteLinks(noteLinks.map((l) => l.id === id ? { ...l, [field]: val } : l));
11264
11226
  };
11265
11227
  const addImageToNote = () => {
11266
- setNoteImages([...noteImages, { id: v4_default(), name: "Image", value: "" }]);
11228
+ setNoteImages([...noteImages, { id: (0, import_uuid9.v4)(), name: "Image", value: "" }]);
11267
11229
  };
11268
11230
  const removeImageFromNote = (id) => {
11269
11231
  setNoteImages(noteImages.filter((img) => img.id !== id));
@@ -12140,6 +12102,7 @@ function MultiNodeContextMenu({
12140
12102
 
12141
12103
  // src/components/RelationshipDetailsPanel.jsx
12142
12104
  var import_react22 = __toESM(require("react"));
12105
+ var import_uuid10 = require("uuid");
12143
12106
  var import_fi20 = require("react-icons/fi");
12144
12107
  function RelationshipDetailsPanel({
12145
12108
  link,
@@ -12949,131 +12912,309 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
12949
12912
  }
12950
12913
 
12951
12914
  // src/components/AncestryBoard.jsx
12915
+ var import_react30 = __toESM(require("react"));
12916
+ var import_fi23 = require("react-icons/fi");
12917
+ var import_uuid11 = require("uuid");
12918
+
12919
+ // src/components/MentionEditor.jsx
12920
+ var import_react28 = __toESM(require("react"));
12921
+ var import_react29 = require("@tiptap/react");
12922
+ var import_starter_kit = __toESM(require("@tiptap/starter-kit"));
12923
+ var import_extension_mention = __toESM(require("@tiptap/extension-mention"));
12924
+ var import_tippy = __toESM(require("tippy.js"));
12925
+
12926
+ // src/components/MentionList.jsx
12952
12927
  var import_react27 = __toESM(require("react"));
12953
12928
  var import_fi22 = require("react-icons/fi");
12929
+ var MentionList = (0, import_react27.forwardRef)((props, ref) => {
12930
+ const [selectedIndex, setSelectedIndex] = (0, import_react27.useState)(0);
12931
+ const selectItem = (index) => {
12932
+ const item = props.items[index];
12933
+ if (item) {
12934
+ props.command({ id: item.id, label: item.name, type: item.type });
12935
+ }
12936
+ };
12937
+ const upHandler = () => {
12938
+ setSelectedIndex(
12939
+ (selectedIndex + props.items.length - 1) % props.items.length
12940
+ );
12941
+ };
12942
+ const downHandler = () => {
12943
+ setSelectedIndex((selectedIndex + 1) % props.items.length);
12944
+ };
12945
+ const enterHandler = () => {
12946
+ selectItem(selectedIndex);
12947
+ };
12948
+ (0, import_react27.useEffect)(() => setSelectedIndex(0), [props.items]);
12949
+ (0, import_react27.useImperativeHandle)(ref, () => ({
12950
+ onKeyDown: ({ event }) => {
12951
+ if (event.key === "ArrowUp") {
12952
+ upHandler();
12953
+ return true;
12954
+ }
12955
+ if (event.key === "ArrowDown") {
12956
+ downHandler();
12957
+ return true;
12958
+ }
12959
+ if (event.key === "Enter") {
12960
+ enterHandler();
12961
+ return true;
12962
+ }
12963
+ return false;
12964
+ }
12965
+ }));
12966
+ return /* @__PURE__ */ import_react27.default.createElement("div", { className: "z-[3000] bg-slate-900 border border-white/10 rounded-lg shadow-2xl overflow-hidden min-w-[280px] max-w-[400px] animate-in fade-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react27.default.createElement("div", { className: "p-2 border-b border-white/5 bg-slate-950/50 flex items-center gap-2" }, /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiSearch, { className: "text-indigo-400", size: 14 }), /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-[10px] uppercase tracking-wider font-bold text-slate-500" }, "Mencionar Recurso")), /* @__PURE__ */ import_react27.default.createElement("div", { className: "p-1 max-h-[300px] overflow-y-auto custom-scrollbar" }, props.items.length ? props.items.map((item, index) => {
12967
+ const isQuest = item.type === "quest";
12968
+ const isVersion = item.type === "version";
12969
+ const isNode = item.type === "node";
12970
+ let Icon = import_fi22.FiLayers;
12971
+ let colorClass = "text-indigo-400";
12972
+ let badgeText = "Ancestralidade";
12973
+ if (isQuest) {
12974
+ Icon = import_fi22.FiCheckSquare;
12975
+ colorClass = "text-amber-400";
12976
+ badgeText = "Quest";
12977
+ } else if (isVersion) {
12978
+ Icon = import_fi22.FiGitBranch;
12979
+ colorClass = "text-purple-400";
12980
+ badgeText = "Vers\xE3o";
12981
+ } else if (isNode) {
12982
+ Icon = import_fi22.FiBox;
12983
+ colorClass = "text-emerald-400";
12984
+ badgeText = "Node";
12985
+ }
12986
+ return /* @__PURE__ */ import_react27.default.createElement(
12987
+ "button",
12988
+ {
12989
+ className: `
12990
+ w-full flex items-center gap-3 px-3 py-2 text-left rounded-md transition-all
12991
+ ${index === selectedIndex ? "bg-indigo-500/20 border border-indigo-500/30 text-white" : "text-slate-400 hover:bg-white/5 border border-transparent"}
12992
+ `,
12993
+ key: item.id,
12994
+ onClick: () => selectItem(index)
12995
+ },
12996
+ /* @__PURE__ */ import_react27.default.createElement("div", { className: `shrink-0 w-8 h-8 rounded border border-white/5 flex items-center justify-center bg-slate-800/50 ${colorClass}` }, /* @__PURE__ */ import_react27.default.createElement(Icon, { size: 14 })),
12997
+ /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-sm font-medium truncate" }, item.name), /* @__PURE__ */ import_react27.default.createElement("span", { className: `text-[9px] px-1 py-0.5 rounded border border-current opacity-60 ${colorClass}` }, badgeText)))
12998
+ );
12999
+ }) : /* @__PURE__ */ import_react27.default.createElement("div", { className: "p-4 text-center text-slate-500 text-sm italic" }, "Nenhum resultado encontrado...")));
13000
+ });
13001
+ MentionList.displayName = "MentionList";
13002
+ var MentionList_default = MentionList;
13003
+
13004
+ // src/components/MentionEditor.jsx
13005
+ var CustomMention = import_extension_mention.default.extend({
13006
+ addAttributes() {
13007
+ var _a;
13008
+ return {
13009
+ ...(_a = this.parent) == null ? void 0 : _a.call(this),
13010
+ type: {
13011
+ default: null,
13012
+ parseHTML: (element) => element.getAttribute("data-mention-type"),
13013
+ renderHTML: (attributes) => {
13014
+ if (!attributes.type) {
13015
+ return {};
13016
+ }
13017
+ return {
13018
+ "data-mention-type": attributes.type
13019
+ };
13020
+ }
13021
+ }
13022
+ };
13023
+ }
13024
+ });
13025
+ var MentionEditor = ({
13026
+ initialValue = "",
13027
+ onChange,
13028
+ onPlay,
13029
+ // Mantido para futura expansão se quisermos badges clicáveis reais no editor
13030
+ availableItems = [],
13031
+ canEdit = true,
13032
+ placeholder = "Escreva algo... use @ para mencionar"
13033
+ }) => {
13034
+ const parseInitialContent = (text) => {
13035
+ if (!text) return "<p></p>";
13036
+ const parts = text.split(/(\[\[MENTION:[^\]]+\]\])/g);
13037
+ return parts.map((part) => {
13038
+ const match = part.match(/\[\[MENTION:([^:]+):([^:]+):([^\]]+)\]\]/);
13039
+ if (match) {
13040
+ const [, type, id, label] = match;
13041
+ return `<span data-type="mention" data-id="${id}" data-mention-type="${type}" data-label="${label}">@${label}</span>`;
13042
+ }
13043
+ return part;
13044
+ }).join("");
13045
+ };
13046
+ const content = (0, import_react28.useMemo)(() => parseInitialContent(initialValue), [initialValue]);
13047
+ const editor = (0, import_react29.useEditor)({
13048
+ extensions: [
13049
+ import_starter_kit.default.configure({
13050
+ heading: false,
13051
+ bulletList: false,
13052
+ orderedList: false,
13053
+ codeBlock: false,
13054
+ blockquote: false
13055
+ }),
13056
+ CustomMention.configure({
13057
+ HTMLAttributes: {
13058
+ class: "mention"
13059
+ },
13060
+ suggestion: {
13061
+ items: ({ query }) => {
13062
+ return availableItems.filter(
13063
+ (item) => item.name.toLowerCase().includes(query.toLowerCase())
13064
+ ).slice(0, 10);
13065
+ },
13066
+ render: () => {
13067
+ let component;
13068
+ let popup;
13069
+ return {
13070
+ onStart: (props) => {
13071
+ component = new import_react29.ReactRenderer(MentionList_default, {
13072
+ props,
13073
+ editor: props.editor
13074
+ });
13075
+ if (!props.clientRect) {
13076
+ return;
13077
+ }
13078
+ popup = (0, import_tippy.default)("body", {
13079
+ getReferenceClientRect: props.clientRect,
13080
+ appendTo: () => document.body,
13081
+ content: component.element,
13082
+ showOnCreate: true,
13083
+ interactive: true,
13084
+ trigger: "manual",
13085
+ placement: "bottom-start"
13086
+ });
13087
+ },
13088
+ onUpdate(props) {
13089
+ component.updateProps(props);
13090
+ if (!props.clientRect) {
13091
+ return;
13092
+ }
13093
+ popup[0].setProps({
13094
+ getReferenceClientRect: props.clientRect
13095
+ });
13096
+ },
13097
+ onKeyDown(props) {
13098
+ var _a;
13099
+ if (props.event.key === "Escape") {
13100
+ popup[0].hide();
13101
+ return true;
13102
+ }
13103
+ return (_a = component == null ? void 0 : component.ref) == null ? void 0 : _a.onKeyDown(props);
13104
+ },
13105
+ onExit() {
13106
+ if (popup && popup[0]) popup[0].destroy();
13107
+ if (component) component.destroy();
13108
+ }
13109
+ };
13110
+ }
13111
+ }
13112
+ })
13113
+ ],
13114
+ content,
13115
+ editable: canEdit,
13116
+ onUpdate: ({ editor: editor2 }) => {
13117
+ const serialize = (json) => {
13118
+ if (!json.content) return "";
13119
+ return json.content.map((block) => {
13120
+ if (block.type === "paragraph") {
13121
+ const inner = block.content ? block.content.map((node) => {
13122
+ if (node.type === "text") return node.text;
13123
+ if (node.type === "mention") {
13124
+ return `[[MENTION:${node.attrs.type}:${node.attrs.id}:${node.attrs.label}]]`;
13125
+ }
13126
+ return "";
13127
+ }).join("") : "";
13128
+ return inner;
13129
+ }
13130
+ return "";
13131
+ }).join("\n").trim();
13132
+ };
13133
+ const serialized = serialize(editor2.getJSON());
13134
+ onChange(serialized);
13135
+ }
13136
+ });
13137
+ if (!editor) {
13138
+ return null;
13139
+ }
13140
+ return /* @__PURE__ */ import_react28.default.createElement("div", { className: "relative group/editor min-h-[1.5rem] w-full" }, /* @__PURE__ */ import_react28.default.createElement(
13141
+ import_react29.EditorContent,
13142
+ {
13143
+ editor,
13144
+ className: "text-sm text-slate-200 placeholder-slate-600 focus:outline-none"
13145
+ }
13146
+ ), /* @__PURE__ */ import_react28.default.createElement("style", null, `
13147
+ .tiptap p {
13148
+ margin: 0;
13149
+ min-height: 1.2em;
13150
+ }
13151
+ .tiptap .mention {
13152
+ display: inline-flex;
13153
+ align-items: center;
13154
+ background-color: rgba(99, 102, 241, 0.15);
13155
+ border: 1px solid rgba(99, 102, 241, 0.3);
13156
+ border-radius: 4px;
13157
+ padding: 0 4px;
13158
+ color: #a5b4fc;
13159
+ font-weight: 500;
13160
+ cursor: pointer;
13161
+ margin: 0 2px;
13162
+ transition: all 0.2s;
13163
+ }
13164
+ .tiptap .mention:hover {
13165
+ background-color: rgba(99, 102, 241, 0.25);
13166
+ border-color: rgba(99, 102, 241, 0.5);
13167
+ color: white;
13168
+ }
13169
+ .tiptap:focus {
13170
+ outline: none;
13171
+ }
13172
+ `));
13173
+ };
13174
+ var MentionEditor_default = MentionEditor;
13175
+
13176
+ // src/components/AncestryBoard.jsx
12954
13177
  var GroupItem = ({
12955
13178
  group,
12956
13179
  index,
12957
- siblings,
12958
13180
  onUpdate,
12959
13181
  onDelete,
12960
13182
  onAddSubgroup,
12961
13183
  onIndent,
12962
13184
  onOutdent,
12963
- onRemoveAncestry,
12964
- onRequestPickAncestry,
12965
- pickingGroupId,
12966
13185
  onPlayAncestry,
12967
- availableIds,
13186
+ availableMentionItems,
12968
13187
  canEdit
12969
13188
  }) => {
12970
13189
  const canIndent = index > 0;
12971
- const isPickingForThisGroup = pickingGroupId === group.id;
12972
- const textareaRef = (0, import_react27.useRef)(null);
12973
- const adjustHeight = () => {
12974
- const textarea = textareaRef.current;
12975
- if (textarea) {
12976
- textarea.style.height = "auto";
12977
- textarea.style.height = `${textarea.scrollHeight}px`;
12978
- }
12979
- };
12980
- (0, import_react27.useEffect)(() => {
12981
- adjustHeight();
12982
- }, [group.text]);
12983
- 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(
13190
+ return /* @__PURE__ */ import_react30.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_react30.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react30.default.createElement(
12984
13191
  "div",
12985
13192
  {
12986
- className: `
12987
- flex flex-col gap-2 py-2 px-3 transition-all duration-200
12988
- ${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
12989
- `
13193
+ 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"
12990
13194
  },
12991
- /* @__PURE__ */ import_react27.default.createElement(
12992
- "textarea",
13195
+ /* @__PURE__ */ import_react30.default.createElement(
13196
+ MentionEditor_default,
12993
13197
  {
12994
- ref: textareaRef,
12995
- 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" : ""}`,
12996
- rows: 1,
12997
- style: {
12998
- minHeight: "1.5rem",
12999
- maxHeight: "250px"
13198
+ initialValue: group.text,
13199
+ onChange: (newText) => {
13200
+ if (canEdit) onUpdate(group.id, { ...group, text: newText });
13000
13201
  },
13001
- placeholder: canEdit ? "Escreva sobre este grupo..." : "",
13002
- value: group.text,
13003
- readOnly: !canEdit,
13004
- onChange: (e) => {
13005
- if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
13006
- }
13202
+ onPlay: onPlayAncestry,
13203
+ availableItems: availableMentionItems,
13204
+ canEdit,
13205
+ placeholder: "Escreva sobre este grupo... use @ para mencionar"
13007
13206
  }
13008
13207
  ),
13009
- group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
13010
- const isValid = availableIds.has(String(anc.ancestry_id));
13011
- return /* @__PURE__ */ import_react27.default.createElement(
13012
- "div",
13013
- {
13014
- key: anc.ancestry_id,
13015
- className: `
13016
- flex items-center gap-2 rounded-md px-3 py-1.5 text-xs transition-all group/card border
13017
- ${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"}
13018
- `,
13019
- title: isValid ? "" : "Esta ancestralidade foi removida ou n\xE3o existe mais."
13020
- },
13021
- isValid ? (
13022
- // [MANTIDO] Botão Play visível para todos
13023
- /* @__PURE__ */ import_react27.default.createElement(
13024
- "button",
13025
- {
13026
- onClick: () => onPlayAncestry(anc.ancestry_id),
13027
- className: "text-indigo-400 hover:text-white hover:bg-indigo-500 p-1 rounded-full transition-colors",
13028
- title: "Renderizar no cen\xE1rio"
13029
- },
13030
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiPlay, { size: 10, className: "ml-0.5 fill-current" })
13031
- )
13032
- ) : /* @__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 })),
13033
- /* @__PURE__ */ import_react27.default.createElement(
13034
- "span",
13035
- {
13036
- className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}`
13037
- },
13038
- anc.name
13039
- ),
13040
- canEdit && /* @__PURE__ */ import_react27.default.createElement(import_react27.default.Fragment, null, /* @__PURE__ */ import_react27.default.createElement(
13041
- "div",
13042
- {
13043
- className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}`
13044
- }
13045
- ), /* @__PURE__ */ import_react27.default.createElement(
13046
- "button",
13047
- {
13048
- onClick: () => onRemoveAncestry(group.id, anc.ancestry_id),
13049
- className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
13050
- title: "Remover men\xE7\xE3o"
13051
- },
13052
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiX, { size: 12 })
13053
- ))
13054
- );
13055
- })),
13056
- 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(
13057
- "button",
13058
- {
13059
- onClick: () => onRequestPickAncestry(group.id),
13060
- className: `
13061
- flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium transition-colors
13062
- ${isPickingForThisGroup ? "text-indigo-300 animate-pulse" : "text-slate-500 hover:text-indigo-300 hover:bg-indigo-500/10"}
13063
- `,
13064
- title: "Adicionar Ancestralidade a este grupo"
13065
- },
13066
- isPickingForThisGroup ? /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiCheckCircle, { size: 12 }) : /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiSearch, { size: 12 }),
13067
- isPickingForThisGroup ? "Selecionando..." : "Adicionar"
13068
- ), /* @__PURE__ */ import_react27.default.createElement(
13208
+ canEdit && /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-0 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react30.default.createElement(
13069
13209
  "button",
13070
13210
  {
13071
13211
  onClick: () => onAddSubgroup(group.id),
13072
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13212
+ className: "flex items-center gap-1.5 px-3 py-1.5 text-xs text-slate-500 hover:text-white hover:bg-white/10 rounded-md transition-colors",
13073
13213
  title: "Criar Subgrupo"
13074
13214
  },
13075
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiPlus, { size: 14 })
13076
- )), /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react27.default.createElement(
13215
+ /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiPlus, { size: 14 }),
13216
+ /* @__PURE__ */ import_react30.default.createElement("span", null, "Adicionar Subgrupo")
13217
+ )), /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react30.default.createElement(
13077
13218
  "button",
13078
13219
  {
13079
13220
  onClick: () => onIndent(group.id),
@@ -13081,25 +13222,25 @@ var GroupItem = ({
13081
13222
  className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13082
13223
  title: "Aninhar no grupo acima"
13083
13224
  },
13084
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiArrowRight, { size: 14 })
13085
- ), /* @__PURE__ */ import_react27.default.createElement(
13225
+ /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiArrowRight, { size: 14 })
13226
+ ), /* @__PURE__ */ import_react30.default.createElement(
13086
13227
  "button",
13087
13228
  {
13088
13229
  onClick: () => onOutdent(group.id),
13089
13230
  className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13090
13231
  title: "Desaninhar"
13091
13232
  },
13092
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiArrowLeft, { size: 14 })
13093
- ), /* @__PURE__ */ import_react27.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react27.default.createElement(
13233
+ /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiArrowLeft, { size: 14 })
13234
+ ), /* @__PURE__ */ import_react30.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react30.default.createElement(
13094
13235
  "button",
13095
13236
  {
13096
13237
  onClick: () => onDelete(group.id),
13097
13238
  className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13098
13239
  title: "Remover Grupo"
13099
13240
  },
13100
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiTrash2, { size: 14 })
13241
+ /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiTrash2, { size: 14 })
13101
13242
  )))
13102
- ), 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(
13243
+ ), group.children && group.children.length > 0 && /* @__PURE__ */ import_react30.default.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ import_react30.default.createElement(
13103
13244
  GroupItem,
13104
13245
  {
13105
13246
  key: childGroup.id,
@@ -13111,11 +13252,8 @@ var GroupItem = ({
13111
13252
  onAddSubgroup,
13112
13253
  onIndent,
13113
13254
  onOutdent,
13114
- onRemoveAncestry,
13115
- onRequestPickAncestry,
13116
- pickingGroupId,
13117
13255
  onPlayAncestry,
13118
- availableIds,
13256
+ availableMentionItems,
13119
13257
  canEdit
13120
13258
  }
13121
13259
  ))));
@@ -13129,23 +13267,20 @@ function AncestryBoard({
13129
13267
  initialGroups = [],
13130
13268
  onSave,
13131
13269
  userRole
13132
- // [NOVO] Recebe a role do usuário
13133
13270
  }) {
13134
- const [searchTerm, setSearchTerm] = (0, import_react27.useState)("");
13135
- const [groups, setGroups] = (0, import_react27.useState)([]);
13136
- const [isLoaded, setIsLoaded] = (0, import_react27.useState)(false);
13137
- const [pickingGroupId, setPickingGroupId] = (0, import_react27.useState)(null);
13138
- const [saveStatus, setSaveStatus] = (0, import_react27.useState)("idle");
13139
- const canEdit = (0, import_react27.useMemo)(() => {
13271
+ const [groups, setGroups] = (0, import_react30.useState)([]);
13272
+ const [isLoaded, setIsLoaded] = (0, import_react30.useState)(false);
13273
+ const [saveStatus, setSaveStatus] = (0, import_react30.useState)("idle");
13274
+ const canEdit = (0, import_react30.useMemo)(() => {
13140
13275
  return userRole !== "viewer";
13141
13276
  }, [userRole]);
13142
- (0, import_react27.useEffect)(() => {
13277
+ (0, import_react30.useEffect)(() => {
13143
13278
  if (initialGroups && !isLoaded) {
13144
13279
  setGroups(initialGroups);
13145
13280
  setIsLoaded(true);
13146
13281
  }
13147
13282
  }, [initialGroups, isLoaded]);
13148
- const nodeNamesMap = (0, import_react27.useMemo)(() => {
13283
+ const nodeNamesMap = (0, import_react30.useMemo)(() => {
13149
13284
  const map = /* @__PURE__ */ new Map();
13150
13285
  if (availableNodes && Array.isArray(availableNodes)) {
13151
13286
  availableNodes.forEach((node) => {
@@ -13156,21 +13291,41 @@ function AncestryBoard({
13156
13291
  }
13157
13292
  return map;
13158
13293
  }, [availableNodes]);
13159
- const availableIds = (0, import_react27.useMemo)(() => {
13294
+ const availableIds = (0, import_react30.useMemo)(() => {
13160
13295
  return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
13161
13296
  }, [availableAncestries]);
13297
+ const availableMentionItems = (0, import_react30.useMemo)(() => {
13298
+ const ancestries = availableAncestries.map((a) => ({
13299
+ id: String(a.ancestry_id),
13300
+ ancestry_id: a.ancestry_id,
13301
+ name: a.name,
13302
+ description: a.description,
13303
+ type: "ancestry",
13304
+ ancestral_node: a.ancestral_node,
13305
+ is_private: a.is_private
13306
+ }));
13307
+ const nodes = availableNodes.map((n) => {
13308
+ let type = "node";
13309
+ if (n.is_quest) type = "quest";
13310
+ else if (n.is_version) type = "version";
13311
+ return {
13312
+ id: String(n.id),
13313
+ name: n.name,
13314
+ description: n.description,
13315
+ type,
13316
+ raw_node: n
13317
+ };
13318
+ });
13319
+ return [...ancestries, ...nodes];
13320
+ }, [availableAncestries, availableNodes]);
13162
13321
  const sanitizeGroups = (groupList) => {
13163
13322
  return groupList.map((g) => ({
13164
13323
  id: g.id,
13165
13324
  text: g.text || "",
13166
- ancestries: (g.ancestries || []).map((a) => ({
13167
- ancestry_id: a.ancestry_id,
13168
- name: a.name
13169
- })),
13170
13325
  children: sanitizeGroups(g.children || [])
13171
13326
  }));
13172
13327
  };
13173
- (0, import_react27.useEffect)(() => {
13328
+ (0, import_react30.useEffect)(() => {
13174
13329
  if (!isLoaded || !onSave) return;
13175
13330
  const timeoutId = setTimeout(async () => {
13176
13331
  setSaveStatus("saving");
@@ -13188,47 +13343,30 @@ function AncestryBoard({
13188
13343
  }, 3e3);
13189
13344
  return () => clearTimeout(timeoutId);
13190
13345
  }, [groups, isLoaded, onSave]);
13191
- (0, import_react27.useEffect)(() => {
13346
+ (0, import_react30.useEffect)(() => {
13192
13347
  if (!isOpen) return;
13193
13348
  const handleKeyDown = (e) => {
13194
13349
  if (e.key === "Escape") {
13195
- if (pickingGroupId) {
13196
- setPickingGroupId(null);
13197
- } else {
13198
- onClose();
13199
- }
13350
+ onClose();
13200
13351
  e.preventDefault();
13201
13352
  e.stopPropagation();
13202
13353
  }
13203
13354
  };
13204
13355
  window.addEventListener("keydown", handleKeyDown);
13205
13356
  return () => window.removeEventListener("keydown", handleKeyDown);
13206
- }, [isOpen, onClose, pickingGroupId]);
13207
- const filtered = (0, import_react27.useMemo)(() => {
13208
- const term = searchTerm.toLowerCase().trim();
13209
- return availableAncestries.filter((a) => {
13210
- if (!term) return true;
13211
- const nameMatch = a.name && a.name.toLowerCase().includes(term);
13212
- const descMatch = a.description && a.description.toLowerCase().includes(term);
13213
- const parentName = nodeNamesMap.get(String(a.ancestral_node)) || "";
13214
- const parentMatch = parentName.toLowerCase().includes(term);
13215
- return nameMatch || descMatch || parentMatch;
13216
- });
13217
- }, [availableAncestries, searchTerm, nodeNamesMap]);
13357
+ }, [isOpen, onClose]);
13218
13358
  const handleAddRootGroup = () => {
13219
13359
  const newGroup = {
13220
- id: v4_default(),
13360
+ id: (0, import_uuid11.v4)(),
13221
13361
  text: "",
13222
- ancestries: [],
13223
13362
  children: []
13224
13363
  };
13225
13364
  setGroups((prev) => [newGroup, ...prev]);
13226
13365
  };
13227
13366
  const handleAddSubgroup = (parentId) => {
13228
13367
  const newGroup = {
13229
- id: v4_default(),
13368
+ id: (0, import_uuid11.v4)(),
13230
13369
  text: "",
13231
- ancestries: [],
13232
13370
  children: []
13233
13371
  };
13234
13372
  const addRecursive = (list) => {
@@ -13299,88 +13437,49 @@ function AncestryBoard({
13299
13437
  return newList;
13300
13438
  });
13301
13439
  };
13302
- const handleRequestPick = (groupId) => {
13303
- setPickingGroupId((prev) => prev === groupId ? null : groupId);
13304
- };
13305
- const handleSelectAncestry = (ancestry) => {
13306
- if (pickingGroupId) {
13307
- setGroups((prev) => {
13308
- const addRecursive = (list) => {
13309
- return list.map((g) => {
13310
- if (g.id === pickingGroupId) {
13311
- const exists = g.ancestries.some(
13312
- (a) => a.ancestry_id === ancestry.ancestry_id
13313
- );
13314
- if (exists) return g;
13315
- return { ...g, ancestries: [...g.ancestries, ancestry] };
13316
- }
13317
- return { ...g, children: addRecursive(g.children) };
13318
- });
13319
- };
13320
- return addRecursive(prev);
13321
- });
13322
- setPickingGroupId(null);
13440
+ const handlePlayFromGroup = (item) => {
13441
+ let fullItem = item;
13442
+ if (item.type === "ancestry" || !item.type) {
13443
+ fullItem = availableAncestries.find(
13444
+ (a) => String(a.ancestry_id) === String(item.id || item.ancestry_id)
13445
+ ) || item;
13323
13446
  } else {
13324
- const fullAncestry = availableAncestries.find(
13325
- (a) => a.ancestry_id === ancestry.ancestry_id
13326
- ) || ancestry;
13327
- onSelect(fullAncestry);
13447
+ fullItem = availableNodes.find(
13448
+ (n) => String(n.id) === String(item.id)
13449
+ ) || item;
13328
13450
  }
13329
- };
13330
- const handlePlayFromGroup = (ancestryId) => {
13331
- const fullAncestry = availableAncestries.find(
13332
- (a) => a.ancestry_id === ancestryId
13333
- );
13334
- if (fullAncestry && onSelect) {
13335
- onSelect(fullAncestry);
13451
+ if (fullItem && onSelect) {
13452
+ onSelect(fullItem);
13336
13453
  }
13337
13454
  };
13338
- const handleRemoveAncestryFromGroup = (groupId, ancestryId) => {
13339
- setGroups((prev) => {
13340
- const removeRecursive = (list) => {
13341
- return list.map((g) => {
13342
- if (g.id === groupId) {
13343
- return {
13344
- ...g,
13345
- ancestries: g.ancestries.filter(
13346
- (a) => a.ancestry_id !== ancestryId
13347
- )
13348
- };
13349
- }
13350
- return { ...g, children: removeRecursive(g.children) };
13351
- });
13352
- };
13353
- return removeRecursive(prev);
13354
- });
13355
- };
13356
13455
  if (!isOpen) return null;
13357
- return /* @__PURE__ */ import_react27.default.createElement(
13456
+ return /* @__PURE__ */ import_react30.default.createElement(
13358
13457
  "div",
13359
13458
  {
13360
13459
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
13361
13460
  onClick: onClose
13362
13461
  },
13363
- /* @__PURE__ */ import_react27.default.createElement(
13462
+ /* @__PURE__ */ import_react30.default.createElement(
13364
13463
  "div",
13365
13464
  {
13366
- 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",
13465
+ className: "bg-slate-950 border border-white/10 rounded-xl w-[90vw] max-w-[1200px] h-[90vh] flex flex-col shadow-2xl overflow-hidden animate-in fade-in zoom-in-95 duration-200",
13367
13466
  onClick: (e) => e.stopPropagation()
13368
13467
  },
13369
- /* @__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(
13370
- import_fi22.FiLoader,
13468
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "h-14 px-6 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react30.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react30.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_react30.default.createElement(import_react30.default.Fragment, null, /* @__PURE__ */ import_react30.default.createElement(
13469
+ import_fi23.FiLoader,
13371
13470
  {
13372
13471
  className: "animate-spin text-indigo-400",
13373
13472
  size: 12
13374
13473
  }
13375
- ), /* @__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(
13474
+ ), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ import_react30.default.createElement(import_react30.default.Fragment, null, /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ import_react30.default.createElement(import_react30.default.Fragment, null, /* @__PURE__ */ import_react30.default.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-3" }, canEdit && /* @__PURE__ */ import_react30.default.createElement(
13376
13475
  "button",
13377
13476
  {
13378
13477
  onClick: handleAddRootGroup,
13379
13478
  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 "
13380
13479
  },
13381
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiPlus, { size: 14, className: "text-indigo-400" }),
13382
- /* @__PURE__ */ import_react27.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13383
- ), /* @__PURE__ */ import_react27.default.createElement(
13480
+ /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiPlus, { size: 14, className: "text-indigo-400" }),
13481
+ /* @__PURE__ */ import_react30.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13482
+ ), /* @__PURE__ */ import_react30.default.createElement(
13384
13483
  "button",
13385
13484
  {
13386
13485
  onClick: onClose,
@@ -13388,102 +13487,37 @@ function AncestryBoard({
13388
13487
  },
13389
13488
  "\xD7"
13390
13489
  ))),
13391
- /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react27.default.createElement(
13392
- "div",
13490
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-1 overflow-hidden bg-slate-900/20" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-8 max-w-[900px] mx-auto w-full space-y-6" }, groups.length === 0 ? /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-4 border-2 border-dashed border-white/5 rounded-2xl bg-slate-900/40 p-12" }, /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiLayers, { size: 40, className: "opacity-10 text-indigo-400" }), /* @__PURE__ */ import_react30.default.createElement("div", { className: "text-center space-y-1" }, /* @__PURE__ */ import_react30.default.createElement("p", { className: "text-sm font-medium text-slate-300" }, "Nenhum grupo criado"), /* @__PURE__ */ import_react30.default.createElement("p", { className: "text-xs text-slate-500 max-w-[200px]" }, canEdit ? "Comece organizando sua narrativa criando o primeiro grupo." : "Este board ainda n\xE3o possui conte\xFAdo.")), canEdit && /* @__PURE__ */ import_react30.default.createElement(
13491
+ "button",
13393
13492
  {
13394
- className: `
13395
- flex flex-col border-r border-white/10 transition-all duration-300 flex-none
13396
- ${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
13397
- min-w-[280px] max-w-[500px] bg-slate-900
13398
- `
13493
+ onClick: handleAddRootGroup,
13494
+ className: "mt-2 px-4 py-2 bg-indigo-500/10 hover:bg-indigo-500/20 text-indigo-400 rounded-lg border border-indigo-500/20 transition-all text-xs font-bold uppercase tracking-wider"
13399
13495
  },
13400
- /* @__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(
13401
- import_fi22.FiSearch,
13402
- {
13403
- 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"}`
13404
- }
13405
- ), /* @__PURE__ */ import_react27.default.createElement(
13406
- "input",
13407
- {
13408
- type: "text",
13409
- placeholder: pickingGroupId ? "Pesquise para adicionar..." : "Pesquisar ancestralidade...",
13410
- className: `
13411
- 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
13412
- ${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"}
13413
- `,
13414
- value: searchTerm,
13415
- onChange: (e) => setSearchTerm(e.target.value),
13416
- autoFocus: !pickingGroupId
13417
- }
13418
- ))),
13419
- /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
13420
- const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
13421
- const isPicking = !!pickingGroupId;
13422
- return /* @__PURE__ */ import_react27.default.createElement(
13423
- "div",
13424
- {
13425
- key: anc.ancestry_id,
13426
- onClick: () => {
13427
- if (isPicking) handleSelectAncestry(anc);
13428
- },
13429
- className: `
13430
- group relative flex items-start gap-3 p-3 text-left rounded-lg border transition-all duration-200
13431
- ${isPicking ? "border-indigo-500/30 bg-indigo-500/5 hover:bg-indigo-500/20 hover:border-indigo-400 cursor-pointer" : "border-white/5 bg-slate-800/40 hover:bg-indigo-600/10 hover:border-indigo-500/30 cursor-default"}
13432
- `
13433
- },
13434
- /* @__PURE__ */ import_react27.default.createElement(
13435
- "div",
13436
- {
13437
- className: `
13438
- mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
13439
- ${isPicking ? "bg-indigo-500 text-white border-indigo-400" : "bg-slate-800 text-indigo-400 border-white/5 group-hover:bg-indigo-500 group-hover:text-white"}
13440
- `
13441
- },
13442
- isPicking ? /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiPlus, { size: 16 }) : /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiLayers, { size: 14 })
13443
- ),
13444
- /* @__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" }, anc.name || "Sem Nome"), anc.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")), /* @__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]" }, parentNodeName)), anc.description && /* @__PURE__ */ import_react27.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
13445
- !isPicking && /* @__PURE__ */ import_react27.default.createElement(
13446
- "button",
13447
- {
13448
- onClick: (e) => {
13449
- e.stopPropagation();
13450
- handleSelectAncestry(anc);
13451
- },
13452
- 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",
13453
- title: "Renderizar Ancestralidade"
13454
- },
13455
- /* @__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" }))
13456
- )
13457
- );
13458
- }))
13459
- ), /* @__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(
13496
+ "Criar Primeiro Grupo"
13497
+ )) : groups.map((group, index) => /* @__PURE__ */ import_react30.default.createElement(
13460
13498
  GroupItem,
13461
13499
  {
13462
13500
  key: group.id,
13463
13501
  index,
13464
13502
  group,
13465
- siblings: groups,
13466
13503
  onUpdate: handleUpdateGroup,
13467
13504
  onDelete: handleDeleteGroup,
13468
13505
  onAddSubgroup: handleAddSubgroup,
13469
13506
  onIndent: handleIndent,
13470
13507
  onOutdent: handleOutdent,
13471
- onRemoveAncestry: handleRemoveAncestryFromGroup,
13472
- onRequestPickAncestry: handleRequestPick,
13473
- pickingGroupId,
13474
13508
  onPlayAncestry: handlePlayFromGroup,
13475
- availableIds,
13509
+ availableMentionItems,
13476
13510
  canEdit
13477
13511
  }
13478
13512
  ))))),
13479
- /* @__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"))
13513
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "px-6 py-3 border-t border-white/10 bg-slate-950/50 text-[10px] uppercase tracking-widest font-bold text-slate-600 flex justify-between items-center flex-shrink-0" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react30.default.createElement("span", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "w-1.5 h-1.5 rounded-full bg-indigo-500" }), " ", availableMentionItems.length, " RECURSOS DISPON\xCDVEIS"), /* @__PURE__ */ import_react30.default.createElement("span", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500" }), " ", groups.length, " GRUPOS PRINCIPAIS")), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-slate-700" }, "X.VIEW :: ANCESTRY BOARD ENGINE"))
13480
13514
  )
13481
13515
  );
13482
13516
  }
13483
13517
 
13484
13518
  // src/components/MilestoneManager.jsx
13485
- var import_react28 = __toESM(require("react"));
13486
- var import_fi23 = require("react-icons/fi");
13519
+ var import_react31 = __toESM(require("react"));
13520
+ var import_fi24 = require("react-icons/fi");
13487
13521
  function MilestoneManager({
13488
13522
  isOpen,
13489
13523
  onClose,
@@ -13491,7 +13525,7 @@ function MilestoneManager({
13491
13525
  onUpdateMilestones = () => {
13492
13526
  }
13493
13527
  }) {
13494
- const [newMilestoneName, setNewMilestoneName] = (0, import_react28.useState)("");
13528
+ const [newMilestoneName, setNewMilestoneName] = (0, import_react31.useState)("");
13495
13529
  const handleAddMilestone = () => {
13496
13530
  if (!newMilestoneName.trim()) return;
13497
13531
  const newMilestone = {
@@ -13516,27 +13550,27 @@ function MilestoneManager({
13516
13550
  };
13517
13551
  if (!isOpen) return null;
13518
13552
  const swallow = (e) => e.stopPropagation();
13519
- return /* @__PURE__ */ import_react28.default.createElement(
13553
+ return /* @__PURE__ */ import_react31.default.createElement(
13520
13554
  "div",
13521
13555
  {
13522
13556
  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",
13523
13557
  onClick: onClose
13524
13558
  },
13525
- /* @__PURE__ */ import_react28.default.createElement(
13559
+ /* @__PURE__ */ import_react31.default.createElement(
13526
13560
  "div",
13527
13561
  {
13528
13562
  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",
13529
13563
  onClick: swallow
13530
13564
  },
13531
- /* @__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(
13565
+ /* @__PURE__ */ import_react31.default.createElement("div", { className: "px-6 py-4 border-b border-white/10 flex items-center justify-between" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "p-2 rounded-lg bg-indigo-500/20 text-indigo-400" }, /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiTarget, { size: 20 })), /* @__PURE__ */ import_react31.default.createElement("div", null, /* @__PURE__ */ import_react31.default.createElement("h2", { className: "text-lg font-semibold text-slate-100" }, "Milestones"), /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-xs text-slate-400" }, "Gerencie os marcos do seu cen\xE1rio"))), /* @__PURE__ */ import_react31.default.createElement(
13532
13566
  "button",
13533
13567
  {
13534
13568
  onClick: onClose,
13535
13569
  className: "p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
13536
13570
  },
13537
- /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiX, { size: 20 })
13571
+ /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiX, { size: 20 })
13538
13572
  )),
13539
- /* @__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(
13573
+ /* @__PURE__ */ import_react31.default.createElement("div", { className: "px-6 py-5 bg-white/5 border-b border-white/5" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ import_react31.default.createElement(
13540
13574
  "input",
13541
13575
  {
13542
13576
  type: "text",
@@ -13546,47 +13580,47 @@ function MilestoneManager({
13546
13580
  placeholder: "Adicionar novo milestone...",
13547
13581
  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"
13548
13582
  }
13549
- ), /* @__PURE__ */ import_react28.default.createElement(
13583
+ ), /* @__PURE__ */ import_react31.default.createElement(
13550
13584
  "button",
13551
13585
  {
13552
13586
  onClick: handleAddMilestone,
13553
13587
  disabled: !newMilestoneName.trim(),
13554
13588
  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"
13555
13589
  },
13556
- /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiPlus, { size: 18 }),
13590
+ /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiPlus, { size: 18 }),
13557
13591
  "Adicionar"
13558
13592
  ))),
13559
- /* @__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(
13593
+ /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex-1 overflow-y-auto px-6 py-4 custom-scrollbar" }, milestones.length > 0 ? /* @__PURE__ */ import_react31.default.createElement("div", { className: "space-y-3" }, milestones.map((ms) => /* @__PURE__ */ import_react31.default.createElement(
13560
13594
  "div",
13561
13595
  {
13562
13596
  key: ms.id,
13563
13597
  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]"}`
13564
13598
  },
13565
- /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ import_react28.default.createElement(
13599
+ /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ import_react31.default.createElement(
13566
13600
  "div",
13567
13601
  {
13568
13602
  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"}`
13569
13603
  }
13570
- ), /* @__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"))),
13571
- /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react28.default.createElement(
13604
+ ), /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ import_react31.default.createElement("span", { className: `text-sm font-medium truncate ${ms.status === "active" ? "text-slate-100" : "text-slate-400 line-through"}` }, ms.name), /* @__PURE__ */ import_react31.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, ms.status === "active" ? "Ativo" : "Inativo"))),
13605
+ /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react31.default.createElement(
13572
13606
  "button",
13573
13607
  {
13574
13608
  onClick: () => handleToggleMilestoneStatus(ms.id),
13575
13609
  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"}`,
13576
13610
  title: ms.status === "active" ? "Inativar" : "Ativar"
13577
13611
  },
13578
- ms.status === "active" ? /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiPauseCircle, { size: 18 }) : /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiPlayCircle, { size: 18 })
13579
- ), /* @__PURE__ */ import_react28.default.createElement(
13612
+ ms.status === "active" ? /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiPauseCircle, { size: 18 }) : /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiPlayCircle, { size: 18 })
13613
+ ), /* @__PURE__ */ import_react31.default.createElement(
13580
13614
  "button",
13581
13615
  {
13582
13616
  onClick: () => handleRemoveMilestone(ms.id),
13583
13617
  className: "p-2 rounded-lg hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-all",
13584
13618
  title: "Remover"
13585
13619
  },
13586
- /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiTrash2, { size: 18 })
13620
+ /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiTrash2, { size: 18 })
13587
13621
  ))
13588
- ))) : /* @__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."))),
13589
- /* @__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))))
13622
+ ))) : /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex flex-col items-center justify-center py-12 text-center" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "p-4 rounded-full bg-slate-800/30 text-slate-600 mb-4" }, /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiTarget, { size: 40 })), /* @__PURE__ */ import_react31.default.createElement("h3", { className: "text-slate-400 font-medium" }, "Nenhum milestone definido"), /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-xs text-slate-600 max-w-[200px] mt-1 italic" }, "Defina marcos importantes para orientar o progresso do projeto."))),
13623
+ /* @__PURE__ */ import_react31.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_react31.default.createElement("div", { className: "flex gap-4" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react31.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Total:"), /* @__PURE__ */ import_react31.default.createElement("span", { className: "text-xs font-bold text-slate-300" }, milestones.length)), /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react31.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Ativos:"), /* @__PURE__ */ import_react31.default.createElement("span", { className: "text-xs font-bold text-indigo-400" }, milestones.filter((m) => m.status === "active").length))))
13590
13624
  )
13591
13625
  );
13592
13626
  }
@@ -13672,13 +13706,13 @@ function XViewScene({
13672
13706
  check_user_permission,
13673
13707
  get_view_members
13674
13708
  }) {
13675
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
13676
- const { data: session, status } = (0, import_react30.useSession)();
13709
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
13710
+ const { data: session, status } = (0, import_react33.useSession)();
13677
13711
  const router = (0, import_navigation.useRouter)();
13678
13712
  const searchParams = (0, import_navigation.useSearchParams)();
13679
13713
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
13680
13714
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
13681
- const viewParams = (0, import_react29.useMemo)(() => {
13715
+ const viewParams = (0, import_react32.useMemo)(() => {
13682
13716
  if (encryptedConfig) {
13683
13717
  const data = decryptData(encryptedConfig);
13684
13718
  if (data) {
@@ -13687,7 +13721,7 @@ function XViewScene({
13687
13721
  }
13688
13722
  return null;
13689
13723
  }, [encryptedConfig, session]);
13690
- (0, import_react29.useEffect)(() => {
13724
+ (0, import_react32.useEffect)(() => {
13691
13725
  async function verifyPermission() {
13692
13726
  if (!viewParams || !session || !check_user_permission) return;
13693
13727
  const { id, type, owner_id } = viewParams;
@@ -13724,65 +13758,65 @@ function XViewScene({
13724
13758
  setIsLoading(false);
13725
13759
  }
13726
13760
  }, [viewParams, session, status, check_user_permission]);
13727
- const sceneConfigId = (0, import_react29.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13728
- const ownerId = (0, import_react29.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13729
- const dbSaveUrl = (0, import_react29.useMemo)(() => {
13761
+ const sceneConfigId = (0, import_react32.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13762
+ const ownerId = (0, import_react32.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13763
+ const dbSaveUrl = (0, import_react32.useMemo)(() => {
13730
13764
  if (ownerId && sceneConfigId) {
13731
13765
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
13732
13766
  }
13733
13767
  return null;
13734
13768
  }, [ownerId, sceneConfigId]);
13735
- const sceneSaveUrl = (0, import_react29.useMemo)(() => {
13769
+ const sceneSaveUrl = (0, import_react32.useMemo)(() => {
13736
13770
  if (ownerId && sceneConfigId) {
13737
13771
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
13738
13772
  }
13739
13773
  return null;
13740
13774
  }, [ownerId, sceneConfigId]);
13741
- const ancestry_save_url = (0, import_react29.useMemo)(() => {
13775
+ const ancestry_save_url = (0, import_react32.useMemo)(() => {
13742
13776
  if (ownerId && sceneConfigId) {
13743
13777
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
13744
13778
  }
13745
13779
  return null;
13746
13780
  }, [ownerId, sceneConfigId]);
13747
- const sceneDataRef = (0, import_react29.useRef)(null);
13748
- const parentDataRef = (0, import_react29.useRef)(null);
13749
- const ancestryDataRef = (0, import_react29.useRef)(null);
13750
- const [isLoading, setIsLoading] = (0, import_react29.useState)(true);
13751
- const [permissionStatus, setPermissionStatus] = (0, import_react29.useState)("loading");
13752
- const [userPermissionRole, setUserPermissionRole] = (0, import_react29.useState)(null);
13753
- const [viewMembers, setViewMembers] = (0, import_react29.useState)([]);
13754
- const [isInitialized, setIsInitialized] = (0, import_react29.useState)(false);
13755
- const [sceneVersion, setSceneVersion] = (0, import_react29.useState)(0);
13756
- const [contextMenu, setContextMenu] = (0, import_react29.useState)({
13781
+ const sceneDataRef = (0, import_react32.useRef)(null);
13782
+ const parentDataRef = (0, import_react32.useRef)(null);
13783
+ const ancestryDataRef = (0, import_react32.useRef)(null);
13784
+ const [isLoading, setIsLoading] = (0, import_react32.useState)(true);
13785
+ const [permissionStatus, setPermissionStatus] = (0, import_react32.useState)("loading");
13786
+ const [userPermissionRole, setUserPermissionRole] = (0, import_react32.useState)(null);
13787
+ const [viewMembers, setViewMembers] = (0, import_react32.useState)([]);
13788
+ const [isInitialized, setIsInitialized] = (0, import_react32.useState)(false);
13789
+ const [sceneVersion, setSceneVersion] = (0, import_react32.useState)(0);
13790
+ const [contextMenu, setContextMenu] = (0, import_react32.useState)({
13757
13791
  visible: false,
13758
13792
  x: 0,
13759
13793
  y: 0,
13760
13794
  nodeData: null
13761
13795
  });
13762
- const [multiContextMenu, setMultiContextMenu] = (0, import_react29.useState)({
13796
+ const [multiContextMenu, setMultiContextMenu] = (0, import_react32.useState)({
13763
13797
  visible: false,
13764
13798
  x: 0,
13765
13799
  y: 0,
13766
13800
  nodeIds: null
13767
13801
  });
13768
- const [relationshipMenu, setRelationshipMenu] = (0, import_react29.useState)({
13802
+ const [relationshipMenu, setRelationshipMenu] = (0, import_react32.useState)({
13769
13803
  visible: false,
13770
13804
  x: 0,
13771
13805
  y: 0,
13772
13806
  linkObject: null
13773
13807
  });
13774
- const [creationMode, setCreationMode] = (0, import_react29.useState)({
13808
+ const [creationMode, setCreationMode] = (0, import_react32.useState)({
13775
13809
  isActive: false,
13776
13810
  sourceNodeData: null
13777
13811
  });
13778
- const [versionMode, setVersionMode] = (0, import_react29.useState)({
13812
+ const [versionMode, setVersionMode] = (0, import_react32.useState)({
13779
13813
  isActive: false,
13780
13814
  sourceNodeData: null
13781
13815
  });
13782
- const [questMode, setQuestMode] = (0, import_react29.useState)({ isActive: false });
13783
- const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react29.useState)(false);
13784
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react29.useState)(false);
13785
- const [ancestryMode, setAncestryMode] = (0, import_react29.useState)({
13816
+ const [questMode, setQuestMode] = (0, import_react32.useState)({ isActive: false });
13817
+ const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react32.useState)(false);
13818
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react32.useState)(false);
13819
+ const [ancestryMode, setAncestryMode] = (0, import_react32.useState)({
13786
13820
  isActive: false,
13787
13821
  tree: null,
13788
13822
  selectedParentId: null,
@@ -13793,42 +13827,42 @@ function XViewScene({
13793
13827
  ancestryDescriptionSections: [],
13794
13828
  isAddingNodes: false
13795
13829
  });
13796
- const [readingMode, setReadingMode] = (0, import_react29.useState)({
13830
+ const [readingMode, setReadingMode] = (0, import_react32.useState)({
13797
13831
  isActive: false,
13798
13832
  ancestry: null,
13799
13833
  branchStack: [],
13800
13834
  autoAbstraction: false
13801
13835
  });
13802
- const [formPosition, setFormPosition] = (0, import_react29.useState)({
13836
+ const [formPosition, setFormPosition] = (0, import_react32.useState)({
13803
13837
  left: 16,
13804
13838
  top: 16,
13805
13839
  opacity: 0
13806
13840
  });
13807
- const [detailsNode, setDetailsNode] = (0, import_react29.useState)(null);
13808
- const [detailsLink, setDetailsLink] = (0, import_react29.useState)(null);
13809
- const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react29.useState)(null);
13810
- const [imageViewer, setImageViewer] = (0, import_react29.useState)({
13841
+ const [detailsNode, setDetailsNode] = (0, import_react32.useState)(null);
13842
+ const [detailsLink, setDetailsLink] = (0, import_react32.useState)(null);
13843
+ const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react32.useState)(null);
13844
+ const [imageViewer, setImageViewer] = (0, import_react32.useState)({
13811
13845
  visible: false,
13812
13846
  images: [],
13813
13847
  startIndex: 0
13814
13848
  });
13815
- const [editingAncestryRel, setEditingAncestryRel] = (0, import_react29.useState)({
13849
+ const [editingAncestryRel, setEditingAncestryRel] = (0, import_react32.useState)({
13816
13850
  visible: false,
13817
13851
  data: null,
13818
13852
  path: null
13819
13853
  });
13820
- const [isImportModalOpen, setIsImportModalOpen] = (0, import_react29.useState)(false);
13821
- const [importSuccessMessage, setImportSuccessMessage] = (0, import_react29.useState)("");
13822
- const [invalidTargetError, setInvalidTargetError] = (0, import_react29.useState)(null);
13823
- const [highlightedNodeId, setHighlightedNodeId] = (0, import_react29.useState)(null);
13824
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react29.useState)(false);
13825
- const [ancestryBoardData, setAncestryBoardData] = (0, import_react29.useState)([]);
13826
- const [isSidebarOpen, setIsSidebarOpen] = (0, import_react29.useState)(false);
13827
- const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = (0, import_react29.useState)(false);
13828
- const mountRef = (0, import_react29.useRef)(null);
13829
- const tooltipRef = (0, import_react29.useRef)(null);
13830
- const formRef = (0, import_react29.useRef)(null);
13831
- const stateRef = (0, import_react29.useRef)({
13854
+ const [isImportModalOpen, setIsImportModalOpen] = (0, import_react32.useState)(false);
13855
+ const [importSuccessMessage, setImportSuccessMessage] = (0, import_react32.useState)("");
13856
+ const [invalidTargetError, setInvalidTargetError] = (0, import_react32.useState)(null);
13857
+ const [highlightedNodeId, setHighlightedNodeId] = (0, import_react32.useState)(null);
13858
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react32.useState)(false);
13859
+ const [ancestryBoardData, setAncestryBoardData] = (0, import_react32.useState)([]);
13860
+ const [isSidebarOpen, setIsSidebarOpen] = (0, import_react32.useState)(false);
13861
+ const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = (0, import_react32.useState)(false);
13862
+ const mountRef = (0, import_react32.useRef)(null);
13863
+ const tooltipRef = (0, import_react32.useRef)(null);
13864
+ const formRef = (0, import_react32.useRef)(null);
13865
+ const stateRef = (0, import_react32.useRef)({
13832
13866
  readMode: {
13833
13867
  currentMaxIndex: 0,
13834
13868
  progressMap: {}
@@ -13892,10 +13926,10 @@ function XViewScene({
13892
13926
  minWidth: 320,
13893
13927
  maxWidth: maxReadPanelW
13894
13928
  });
13895
- (0, import_react29.useEffect)(() => {
13929
+ (0, import_react32.useEffect)(() => {
13896
13930
  stateRef.current.ancestry = ancestryMode;
13897
13931
  }, [ancestryMode]);
13898
- (0, import_react29.useEffect)(() => {
13932
+ (0, import_react32.useEffect)(() => {
13899
13933
  var _a2;
13900
13934
  if (!isInitialized) return;
13901
13935
  const map = /* @__PURE__ */ new Map();
@@ -13918,10 +13952,10 @@ function XViewScene({
13918
13952
  }
13919
13953
  stateRef.current.nodeIdToParentFileMap = map;
13920
13954
  }, [isInitialized, sceneVersion]);
13921
- const handleNavigateBack = (0, import_react29.useCallback)(() => {
13955
+ const handleNavigateBack = (0, import_react32.useCallback)(() => {
13922
13956
  router.push("/dashboard/scenes");
13923
13957
  }, [router]);
13924
- const handleConfirmImport = (0, import_react29.useCallback)(
13958
+ const handleConfirmImport = (0, import_react32.useCallback)(
13925
13959
  async (importPayload) => {
13926
13960
  var _a2, _b2;
13927
13961
  let files = [];
@@ -14049,7 +14083,7 @@ function XViewScene({
14049
14083
  const handleOpenImageViewer = (images, startIndex) => {
14050
14084
  setImageViewer({ visible: true, images, startIndex });
14051
14085
  };
14052
- const tweenToTarget = (0, import_react29.useCallback)(
14086
+ const tweenToTarget = (0, import_react32.useCallback)(
14053
14087
  (target, zoomFactor = 1, forcedDirection = null) => {
14054
14088
  const { camera, controls, tweenGroup } = stateRef.current;
14055
14089
  if (!camera || !controls || !tweenGroup) return;
@@ -14075,7 +14109,7 @@ function XViewScene({
14075
14109
  if (!t || typeof t.closest !== "function") return false;
14076
14110
  return !!t.closest(".ui-overlay");
14077
14111
  };
14078
- const buildFullAncestryTree = (0, import_react29.useCallback)(
14112
+ const buildFullAncestryTree = (0, import_react32.useCallback)(
14079
14113
  (idTree, nodes, ancestries = []) => {
14080
14114
  if (!idTree) return null;
14081
14115
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
@@ -14160,7 +14194,7 @@ function XViewScene({
14160
14194
  },
14161
14195
  []
14162
14196
  );
14163
- const handleActivateTimeline = (0, import_react29.useCallback)(() => {
14197
+ const handleActivateTimeline = (0, import_react32.useCallback)(() => {
14164
14198
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
14165
14199
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
14166
14200
  while (timelineIntervalsGroup.children.length > 0) {
@@ -14320,7 +14354,7 @@ function XViewScene({
14320
14354
  }
14321
14355
  });
14322
14356
  }, []);
14323
- const handleVersionTimeline = (0, import_react29.useCallback)((sourceMesh, versionMeshes) => {
14357
+ const handleVersionTimeline = (0, import_react32.useCallback)((sourceMesh, versionMeshes) => {
14324
14358
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
14325
14359
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
14326
14360
  return;
@@ -14457,7 +14491,7 @@ function XViewScene({
14457
14491
  }
14458
14492
  });
14459
14493
  }, []);
14460
- (0, import_react29.useEffect)(() => {
14494
+ (0, import_react32.useEffect)(() => {
14461
14495
  async function fetchAllData(configPath, ownerId2) {
14462
14496
  var _a2, _b2;
14463
14497
  if (!get_scene_view_data) {
@@ -14562,12 +14596,12 @@ function XViewScene({
14562
14596
  focusNodeId,
14563
14597
  focusAncestryId
14564
14598
  ]);
14565
- const isNodeInView = (0, import_react29.useCallback)((id) => {
14599
+ const isNodeInView = (0, import_react32.useCallback)((id) => {
14566
14600
  const key = String(id);
14567
14601
  const objs = stateRef.current.nodeObjects || {};
14568
14602
  return !!objs[key];
14569
14603
  }, []);
14570
- const addOrUpdateNodeMesh = (0, import_react29.useCallback)(
14604
+ const addOrUpdateNodeMesh = (0, import_react32.useCallback)(
14571
14605
  (nodeData, position, suppressVersionUpdate = false, forceShowQuestDate = false) => {
14572
14606
  const {
14573
14607
  graphGroup,
@@ -14608,7 +14642,7 @@ function XViewScene({
14608
14642
  },
14609
14643
  []
14610
14644
  );
14611
- const handleActivateQuestLens = (0, import_react29.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
14645
+ const handleActivateQuestLens = (0, import_react32.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
14612
14646
  var _a2;
14613
14647
  const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
14614
14648
  if (!nodeObjects || !tweenGroup || !graphGroup) return;
@@ -14822,7 +14856,7 @@ function XViewScene({
14822
14856
  camTween.start();
14823
14857
  }
14824
14858
  }, [addOrUpdateNodeMesh]);
14825
- (0, import_react29.useEffect)(() => {
14859
+ (0, import_react32.useEffect)(() => {
14826
14860
  if (!isInitialized || !sceneDataRef.current) return;
14827
14861
  const currentMount = mountRef.current;
14828
14862
  if (!currentMount) return;
@@ -15578,7 +15612,7 @@ function XViewScene({
15578
15612
  get_scene_view_data,
15579
15613
  save_view_data
15580
15614
  ]);
15581
- const handleGhostNodeImageChange = (0, import_react29.useCallback)((useImage, imageUrl) => {
15615
+ const handleGhostNodeImageChange = (0, import_react32.useCallback)((useImage, imageUrl) => {
15582
15616
  const {
15583
15617
  node: ghostNode,
15584
15618
  line: ghostLine,
@@ -15626,7 +15660,7 @@ function XViewScene({
15626
15660
  aura: newGhostNode.getObjectByName("aura")
15627
15661
  };
15628
15662
  }, []);
15629
- const handleGhostNodeIntensityChange = (0, import_react29.useCallback)((newIntensity) => {
15663
+ const handleGhostNodeIntensityChange = (0, import_react32.useCallback)((newIntensity) => {
15630
15664
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
15631
15665
  if (!ghostNode) return;
15632
15666
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -15647,7 +15681,7 @@ function XViewScene({
15647
15681
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
15648
15682
  }
15649
15683
  }, []);
15650
- const handleDetailNodeIntensityChange = (0, import_react29.useCallback)(
15684
+ const handleDetailNodeIntensityChange = (0, import_react32.useCallback)(
15651
15685
  (nodeId, newIntensity) => {
15652
15686
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
15653
15687
  if (!mesh) return;
@@ -15803,7 +15837,7 @@ function XViewScene({
15803
15837
  mountRef.current.style.cursor = "default";
15804
15838
  }
15805
15839
  };
15806
- const handleAncestryTreeUpdate = (0, import_react29.useCallback)((newTree, extraData = null) => {
15840
+ const handleAncestryTreeUpdate = (0, import_react32.useCallback)((newTree, extraData = null) => {
15807
15841
  setAncestryMode((prev) => {
15808
15842
  const prevTreeStr = JSON.stringify(prev.tree);
15809
15843
  const newTreeStr = JSON.stringify(newTree);
@@ -15826,7 +15860,7 @@ function XViewScene({
15826
15860
  };
15827
15861
  });
15828
15862
  }, []);
15829
- const actionHandlerContext = (0, import_react29.useMemo)(
15863
+ const actionHandlerContext = (0, import_react32.useMemo)(
15830
15864
  () => {
15831
15865
  var _a2;
15832
15866
  return {
@@ -15887,7 +15921,7 @@ function XViewScene({
15887
15921
  const handleStartVersioning = (nodeData) => {
15888
15922
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
15889
15923
  };
15890
- const handleStartQuestQuick = (0, import_react29.useCallback)((questNode) => {
15924
+ const handleStartQuestQuick = (0, import_react32.useCallback)((questNode) => {
15891
15925
  var _a2, _b2, _c2;
15892
15926
  if (!questNode || !actionHandlerContext) return;
15893
15927
  const allParentNodes = Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
@@ -15922,7 +15956,7 @@ function XViewScene({
15922
15956
  }
15923
15957
  setDetailsNode(updatedNode);
15924
15958
  }, [session, actionHandlerContext]);
15925
- const handleFinishQuestQuick = (0, import_react29.useCallback)((questNode) => {
15959
+ const handleFinishQuestQuick = (0, import_react32.useCallback)((questNode) => {
15926
15960
  var _a2, _b2, _c2, _d2;
15927
15961
  if (!questNode || !actionHandlerContext) return;
15928
15962
  const {
@@ -15996,7 +16030,7 @@ function XViewScene({
15996
16030
  setDetailsNode(null);
15997
16031
  }
15998
16032
  }, [session, actionHandlerContext, viewMembers, detailsNode]);
15999
- const handleCancelQuest = (0, import_react29.useCallback)(() => {
16033
+ const handleCancelQuest = (0, import_react32.useCallback)(() => {
16000
16034
  const { graphGroup, ghostElements } = stateRef.current;
16001
16035
  if (ghostElements.node && graphGroup) {
16002
16036
  if (ghostElements.node.userData.labelObject) {
@@ -16055,6 +16089,8 @@ function XViewScene({
16055
16089
  try {
16056
16090
  await actions.save_view_data(sceneSaveUrl2, sceneFileData);
16057
16091
  sceneDataRef2.current.quest_counter = currentCounter + 1;
16092
+ sceneDataRef2.current.quest_nodes = sceneFileData.quest_nodes;
16093
+ sceneDataRef2.current.quest_links = sceneFileData.quest_links;
16058
16094
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
16059
16095
  parentFileId: sceneConfigId2,
16060
16096
  ownerId: ownerId2,
@@ -16149,7 +16185,7 @@ function XViewScene({
16149
16185
  }
16150
16186
  userActionHandlers.handleCancelConnection(context);
16151
16187
  };
16152
- const handleClearAncestryVisuals = (0, import_react29.useCallback)((ancestryId) => {
16188
+ const handleClearAncestryVisuals = (0, import_react32.useCallback)((ancestryId) => {
16153
16189
  const { renderedAncestries, ancestryGroup } = stateRef.current;
16154
16190
  const renderIndex = renderedAncestries.findIndex(
16155
16191
  (a) => String(a.id) === String(ancestryId)
@@ -16167,7 +16203,7 @@ function XViewScene({
16167
16203
  );
16168
16204
  }
16169
16205
  }, []);
16170
- const handleRenderAncestry = (0, import_react29.useCallback)(
16206
+ const handleRenderAncestry = (0, import_react32.useCallback)(
16171
16207
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
16172
16208
  setContextMenu(
16173
16209
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16661,7 +16697,7 @@ function XViewScene({
16661
16697
  ancestryMode.isActive
16662
16698
  ]
16663
16699
  );
16664
- const handleRenderAbstractionTree = (0, import_react29.useCallback)(
16700
+ const handleRenderAbstractionTree = (0, import_react32.useCallback)(
16665
16701
  (ancestryObject, targetNodeId = null) => {
16666
16702
  setContextMenu(
16667
16703
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16749,7 +16785,7 @@ function XViewScene({
16749
16785
  handleClearAncestryVisuals
16750
16786
  ]
16751
16787
  );
16752
- const handleReadModeBranchNav = (0, import_react29.useCallback)(
16788
+ const handleReadModeBranchNav = (0, import_react32.useCallback)(
16753
16789
  (nodeId, action, direction = "right") => {
16754
16790
  const { ancestry, branchStack } = readingMode;
16755
16791
  if (!ancestry || !ancestry.tree) return;
@@ -16927,13 +16963,13 @@ function XViewScene({
16927
16963
  },
16928
16964
  [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
16929
16965
  );
16930
- const handleReadModeHighlight = (0, import_react29.useCallback)((nodeId) => {
16966
+ const handleReadModeHighlight = (0, import_react32.useCallback)((nodeId) => {
16931
16967
  if (stateRef.current.highlightedNodeId !== nodeId) {
16932
16968
  stateRef.current.highlightedNodeId = nodeId;
16933
16969
  }
16934
16970
  setHighlightedNodeId(nodeId);
16935
16971
  }, []);
16936
- const activeNodeBranches = (0, import_react29.useMemo)(() => {
16972
+ const activeNodeBranches = (0, import_react32.useMemo)(() => {
16937
16973
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
16938
16974
  return null;
16939
16975
  const fullTree = buildFullAncestryTree(
@@ -16977,7 +17013,7 @@ function XViewScene({
16977
17013
  readingMode.branchStack,
16978
17014
  ancestryDataRef.current
16979
17015
  ]);
16980
- const backNavigationInfo = (0, import_react29.useMemo)(() => {
17016
+ const backNavigationInfo = (0, import_react32.useMemo)(() => {
16981
17017
  const { branchStack } = readingMode;
16982
17018
  if (!branchStack || branchStack.length === 0) return null;
16983
17019
  const lastStep = branchStack[branchStack.length - 1];
@@ -16988,7 +17024,7 @@ function XViewScene({
16988
17024
  name: "Voltar para anterior"
16989
17025
  };
16990
17026
  }, [readingMode.branchStack]);
16991
- const getReadModeDisplayContext = (0, import_react29.useMemo)(() => {
17027
+ const getReadModeDisplayContext = (0, import_react32.useMemo)(() => {
16992
17028
  const { ancestry, branchStack } = readingMode;
16993
17029
  if (!ancestry) return null;
16994
17030
  if (branchStack.length === 0) {
@@ -17031,7 +17067,7 @@ function XViewScene({
17031
17067
  customProperties: branchProps
17032
17068
  };
17033
17069
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
17034
- const readModeAbstractionTree = (0, import_react29.useMemo)(() => {
17070
+ const readModeAbstractionTree = (0, import_react32.useMemo)(() => {
17035
17071
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
17036
17072
  return null;
17037
17073
  }
@@ -17050,7 +17086,7 @@ function XViewScene({
17050
17086
  buildFullAncestryTree,
17051
17087
  sceneVersion
17052
17088
  ]);
17053
- const handleStartReadingAncestry = (0, import_react29.useCallback)(
17089
+ const handleStartReadingAncestry = (0, import_react32.useCallback)(
17054
17090
  async (ancestryObject, renderMode = "full") => {
17055
17091
  setContextMenu(
17056
17092
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17093,7 +17129,7 @@ function XViewScene({
17093
17129
  },
17094
17130
  [handleRenderAncestry, handleRenderAbstractionTree]
17095
17131
  );
17096
- const handleReadModeSectionChange = (0, import_react29.useCallback)(
17132
+ const handleReadModeSectionChange = (0, import_react32.useCallback)(
17097
17133
  (activeSectionId) => {
17098
17134
  const { ancestry, branchStack } = readingMode;
17099
17135
  if (!ancestry || !readingMode.isActive) return;
@@ -17178,10 +17214,10 @@ function XViewScene({
17178
17214
  ancestryDataRef.current
17179
17215
  ]
17180
17216
  );
17181
- const handleCloseReadMode = (0, import_react29.useCallback)(() => {
17217
+ const handleCloseReadMode = (0, import_react32.useCallback)(() => {
17182
17218
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
17183
17219
  }, []);
17184
- const handleAncestrySectionChange = (0, import_react29.useCallback)(
17220
+ const handleAncestrySectionChange = (0, import_react32.useCallback)(
17185
17221
  (activeSectionId, ancestryOverride = null, rotation = 0) => {
17186
17222
  var _a2, _b2;
17187
17223
  const currentMode = stateRef.current.ancestry;
@@ -17243,7 +17279,7 @@ function XViewScene({
17243
17279
  },
17244
17280
  [handleRenderAncestry]
17245
17281
  );
17246
- const handleEditAncestry = (0, import_react29.useCallback)(
17282
+ const handleEditAncestry = (0, import_react32.useCallback)(
17247
17283
  async (ancestryObject) => {
17248
17284
  setContextMenu(
17249
17285
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17298,7 +17334,7 @@ function XViewScene({
17298
17334
  const handleSelectAncestryParent = (nodeId) => {
17299
17335
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
17300
17336
  };
17301
- const handleRemoveFromAncestry = (0, import_react29.useCallback)((pathToRemove) => {
17337
+ const handleRemoveFromAncestry = (0, import_react32.useCallback)((pathToRemove) => {
17302
17338
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
17303
17339
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
17304
17340
  return;
@@ -17323,7 +17359,7 @@ function XViewScene({
17323
17359
  return { ...prev, tree: newTree };
17324
17360
  });
17325
17361
  }, []);
17326
- const handleSaveAncestry = (0, import_react29.useCallback)(
17362
+ const handleSaveAncestry = (0, import_react32.useCallback)(
17327
17363
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
17328
17364
  const treeToUse = treeOverride || ancestryMode.tree;
17329
17365
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -17559,7 +17595,7 @@ function XViewScene({
17559
17595
  });
17560
17596
  setEditingAncestryRel({ visible: false, data: null, path: null });
17561
17597
  };
17562
- const handleDeleteAncestry = (0, import_react29.useCallback)(
17598
+ const handleDeleteAncestry = (0, import_react32.useCallback)(
17563
17599
  async (ancestryIdToDelete) => {
17564
17600
  if (!ancestryIdToDelete) {
17565
17601
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -17641,18 +17677,28 @@ function XViewScene({
17641
17677
  },
17642
17678
  [save_view_data, delete_file_action]
17643
17679
  );
17644
- const handleOpenAncestryBoard = (0, import_react29.useCallback)(() => {
17680
+ const handleOpenAncestryBoard = (0, import_react32.useCallback)(() => {
17645
17681
  setIsAncestryBoardOpen(true);
17646
17682
  }, []);
17647
- const handleSelectAncestryFromBoard = (0, import_react29.useCallback)(
17648
- (ancestry) => {
17683
+ const handleSelectAncestryFromBoard = (0, import_react32.useCallback)(
17684
+ (item) => {
17649
17685
  setIsAncestryBoardOpen(false);
17650
17686
  setIsSidebarOpen(false);
17651
- handleStartReadingAncestry(ancestry);
17687
+ if (item.type === "ancestry" || !item.type) {
17688
+ handleStartReadingAncestry(item);
17689
+ } else {
17690
+ const nodeId = String(item.id);
17691
+ const sceneMesh = stateRef.current.nodeObjects[nodeId];
17692
+ if (sceneMesh) {
17693
+ tweenToTarget(sceneMesh);
17694
+ } else {
17695
+ console.warn("Objeto n\xE3o encontrado na cena para foco:", nodeId);
17696
+ }
17697
+ }
17652
17698
  },
17653
- [handleStartReadingAncestry]
17699
+ [handleStartReadingAncestry, tweenToTarget]
17654
17700
  );
17655
- const handleSaveAncestryBoard = (0, import_react29.useCallback)(
17701
+ const handleSaveAncestryBoard = (0, import_react32.useCallback)(
17656
17702
  async (groups) => {
17657
17703
  if (!sceneConfigId || !viewParams || !session) return;
17658
17704
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
@@ -17666,7 +17712,7 @@ function XViewScene({
17666
17712
  },
17667
17713
  [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
17668
17714
  );
17669
- const existingNodeTypes = (0, import_react29.useMemo)(() => {
17715
+ const existingNodeTypes = (0, import_react32.useMemo)(() => {
17670
17716
  if (!parentDataRef.current) {
17671
17717
  return [];
17672
17718
  }
@@ -17678,22 +17724,28 @@ function XViewScene({
17678
17724
  ).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
17679
17725
  return [...new Set(allTypes)];
17680
17726
  }, [parentDataRef.current, sceneVersion]);
17681
- const searchableDbNodes = (0, import_react29.useMemo)(() => {
17727
+ const searchableDbNodes = (0, import_react32.useMemo)(() => {
17728
+ var _a2;
17682
17729
  if (!parentDataRef.current) {
17683
17730
  return [];
17684
17731
  }
17685
- return Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17732
+ const datasetsPool = Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17686
17733
  const datasetName = fileData.dataset_name || `Dataset #${dbId.substring(0, 6)}`;
17687
17734
  return (fileData.nodes || []).map((node) => ({
17688
17735
  ...node,
17689
17736
  dataset_name: datasetName
17690
17737
  }));
17691
- }).filter((node) => {
17692
- var _a2;
17693
- return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
17694
17738
  });
17695
- }, [parentDataRef.current, sceneVersion]);
17696
- const handleAddExistingNode = (0, import_react29.useCallback)(
17739
+ const questsPool = (((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || []).map((node) => ({
17740
+ ...node,
17741
+ dataset_name: "Quests Internas (View)"
17742
+ }));
17743
+ return [...datasetsPool, ...questsPool].filter((node) => {
17744
+ var _a3;
17745
+ return !((_a3 = node.version_node) == null ? void 0 : _a3.is_version);
17746
+ });
17747
+ }, [parentDataRef.current, (_b = sceneDataRef.current) == null ? void 0 : _b.quest_nodes, sceneVersion]);
17748
+ const handleAddExistingNode = (0, import_react32.useCallback)(
17697
17749
  (nodeId) => {
17698
17750
  return userActionHandlers.handleAddExistingNodeById(
17699
17751
  actionHandlerContext,
@@ -17702,7 +17754,7 @@ function XViewScene({
17702
17754
  },
17703
17755
  [actionHandlerContext]
17704
17756
  );
17705
- const handleUpdateMilestones = (0, import_react29.useCallback)(
17757
+ const handleUpdateMilestones = (0, import_react32.useCallback)(
17706
17758
  async (newMilestones) => {
17707
17759
  var _a2, _b2, _c2;
17708
17760
  if (!sceneDataRef.current) return;
@@ -17748,7 +17800,7 @@ function XViewScene({
17748
17800
  viewParams == null ? void 0 : viewParams.type
17749
17801
  ]
17750
17802
  );
17751
- const handleSaveCurrentView = (0, import_react29.useCallback)(async () => {
17803
+ const handleSaveCurrentView = (0, import_react32.useCallback)(async () => {
17752
17804
  var _a2, _b2, _c2;
17753
17805
  const { nodeObjects, allLinks } = stateRef.current;
17754
17806
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
@@ -17791,16 +17843,16 @@ function XViewScene({
17791
17843
  console.error("Erro na chamada de save_view_data:", error);
17792
17844
  }
17793
17845
  }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
17794
- const allAvailableNodes = (0, import_react29.useMemo)(() => {
17846
+ const allAvailableNodes = (0, import_react32.useMemo)(() => {
17795
17847
  if (!parentDataRef.current) return [];
17796
17848
  return Object.values(parentDataRef.current).flatMap(
17797
17849
  (fileData) => fileData.nodes || []
17798
17850
  );
17799
17851
  }, [sceneVersion, isInitialized]);
17800
- const allAvailableAncestries = (0, import_react29.useMemo)(() => {
17852
+ const allAvailableAncestries = (0, import_react32.useMemo)(() => {
17801
17853
  return ancestryDataRef.current || [];
17802
17854
  }, [sceneVersion, isInitialized]);
17803
- const handleOpenReference = (0, import_react29.useCallback)(
17855
+ const handleOpenReference = (0, import_react32.useCallback)(
17804
17856
  (referenceData) => {
17805
17857
  const { type, id } = referenceData;
17806
17858
  if (type === "node") {
@@ -17839,13 +17891,13 @@ function XViewScene({
17839
17891
  tweenToTarget
17840
17892
  ]
17841
17893
  );
17842
- const handleToggleAncestryAddMode = (0, import_react29.useCallback)(() => {
17894
+ const handleToggleAncestryAddMode = (0, import_react32.useCallback)(() => {
17843
17895
  setAncestryMode((prev) => ({
17844
17896
  ...prev,
17845
17897
  isAddingNodes: !prev.isAddingNodes
17846
17898
  }));
17847
17899
  }, []);
17848
- const handleFocusNode = (0, import_react29.useCallback)(
17900
+ const handleFocusNode = (0, import_react32.useCallback)(
17849
17901
  (nodeData) => {
17850
17902
  var _a2;
17851
17903
  if (!nodeData) return;
@@ -17861,7 +17913,7 @@ function XViewScene({
17861
17913
  },
17862
17914
  [tweenToTarget]
17863
17915
  );
17864
- const availableDatasets = (0, import_react29.useMemo)(() => {
17916
+ const availableDatasets = (0, import_react32.useMemo)(() => {
17865
17917
  if (!sceneDataRef.current || !parentDataRef.current) return [];
17866
17918
  return sceneDataRef.current.parent_dbs.map((db) => {
17867
17919
  var _a2;
@@ -17871,11 +17923,11 @@ function XViewScene({
17871
17923
  };
17872
17924
  });
17873
17925
  }, [sceneVersion, isInitialized]);
17874
- const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(
17926
+ const sourceNodeDatasetId = creationMode.sourceNodeData ? (_c = stateRef.current.nodeIdToParentFileMap.get(
17875
17927
  String(creationMode.sourceNodeData.id)
17876
- )) == null ? void 0 : _b.parentFileId : null;
17928
+ )) == null ? void 0 : _c.parentFileId : null;
17877
17929
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
17878
- (0, import_react29.useEffect)(() => {
17930
+ (0, import_react32.useEffect)(() => {
17879
17931
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
17880
17932
  const nodeObjects = stateRef.current.nodeObjects || {};
17881
17933
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -17898,7 +17950,7 @@ function XViewScene({
17898
17950
  hasFocusedInitial,
17899
17951
  tweenToTarget
17900
17952
  ]);
17901
- (0, import_react29.useEffect)(() => {
17953
+ (0, import_react32.useEffect)(() => {
17902
17954
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
17903
17955
  const ancestries = ancestryDataRef.current || [];
17904
17956
  const targetAncestry = ancestries.find(
@@ -17923,7 +17975,7 @@ function XViewScene({
17923
17975
  hasOpenedInitialAncestry,
17924
17976
  handleStartReadingAncestry
17925
17977
  ]);
17926
- (0, import_react29.useEffect)(() => {
17978
+ (0, import_react32.useEffect)(() => {
17927
17979
  function handleKeyDown(event) {
17928
17980
  var _a2, _b2, _c2;
17929
17981
  const context = actionHandlerContext;
@@ -18046,10 +18098,10 @@ function XViewScene({
18046
18098
  // <-- handleCancelQuest adicionado aqui
18047
18099
  ]);
18048
18100
  if (isLoading || status === "loading" || permissionStatus === "loading") {
18049
- return /* @__PURE__ */ import_react29.default.createElement(LoadingScreen, null);
18101
+ return /* @__PURE__ */ import_react32.default.createElement(LoadingScreen, null);
18050
18102
  }
18051
18103
  if (permissionStatus === "denied") {
18052
- 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(
18104
+ return /* @__PURE__ */ import_react32.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react32.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_react32.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react32.default.createElement(
18053
18105
  "svg",
18054
18106
  {
18055
18107
  xmlns: "http://www.w3.org/2000/svg",
@@ -18059,7 +18111,7 @@ function XViewScene({
18059
18111
  stroke: "currentColor",
18060
18112
  className: "w-16 h-16 mx-auto"
18061
18113
  },
18062
- /* @__PURE__ */ import_react29.default.createElement(
18114
+ /* @__PURE__ */ import_react32.default.createElement(
18063
18115
  "path",
18064
18116
  {
18065
18117
  strokeLinecap: "round",
@@ -18067,13 +18119,13 @@ function XViewScene({
18067
18119
  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"
18068
18120
  }
18069
18121
  )
18070
- )), /* @__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(
18122
+ )), /* @__PURE__ */ import_react32.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ import_react32.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_react32.default.createElement(
18071
18123
  "button",
18072
18124
  {
18073
18125
  onClick: () => router.push("/dashboard/scenes"),
18074
18126
  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"
18075
18127
  },
18076
- /* @__PURE__ */ import_react29.default.createElement(
18128
+ /* @__PURE__ */ import_react32.default.createElement(
18077
18129
  "svg",
18078
18130
  {
18079
18131
  xmlns: "http://www.w3.org/2000/svg",
@@ -18083,7 +18135,7 @@ function XViewScene({
18083
18135
  stroke: "currentColor",
18084
18136
  className: "w-5 h-5"
18085
18137
  },
18086
- /* @__PURE__ */ import_react29.default.createElement(
18138
+ /* @__PURE__ */ import_react32.default.createElement(
18087
18139
  "path",
18088
18140
  {
18089
18141
  strokeLinecap: "round",
@@ -18095,7 +18147,7 @@ function XViewScene({
18095
18147
  "Voltar para Scenes"
18096
18148
  )));
18097
18149
  }
18098
- return /* @__PURE__ */ import_react29.default.createElement(
18150
+ return /* @__PURE__ */ import_react32.default.createElement(
18099
18151
  "div",
18100
18152
  {
18101
18153
  ref: mountRef,
@@ -18107,7 +18159,7 @@ function XViewScene({
18107
18159
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
18108
18160
  }
18109
18161
  },
18110
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react29.default.createElement(
18162
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react32.default.createElement(
18111
18163
  XViewSidebar,
18112
18164
  {
18113
18165
  dbNodes: searchableDbNodes,
@@ -18127,11 +18179,11 @@ function XViewScene({
18127
18179
  onToggle: setIsSidebarOpen,
18128
18180
  userRole: userPermissionRole,
18129
18181
  viewMembers,
18130
- milestones: ((_c = sceneDataRef.current) == null ? void 0 : _c.milestones) || [],
18182
+ milestones: ((_d = sceneDataRef.current) == null ? void 0 : _d.milestones) || [],
18131
18183
  onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
18132
18184
  }
18133
18185
  ),
18134
- creationMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18186
+ creationMode.isActive && /* @__PURE__ */ import_react32.default.createElement(
18135
18187
  InSceneCreationForm,
18136
18188
  {
18137
18189
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -18152,8 +18204,8 @@ function XViewScene({
18152
18204
  },
18153
18205
  refEl: formRef,
18154
18206
  existingTypes: existingNodeTypes,
18155
- initialColor: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.color,
18156
- sourceTypes: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.type,
18207
+ initialColor: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.color,
18208
+ sourceTypes: (_f = creationMode.sourceNodeData) == null ? void 0 : _f.type,
18157
18209
  onIntensityChange: handleGhostNodeIntensityChange,
18158
18210
  onUploadFile: upload_file_action,
18159
18211
  availableDatasets,
@@ -18163,7 +18215,7 @@ function XViewScene({
18163
18215
  availableAncestries: allAvailableAncestries
18164
18216
  }
18165
18217
  ),
18166
- versionMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18218
+ versionMode.isActive && /* @__PURE__ */ import_react32.default.createElement(
18167
18219
  InSceneVersionForm,
18168
18220
  {
18169
18221
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -18182,14 +18234,14 @@ function XViewScene({
18182
18234
  transition: "opacity 200ms ease-out"
18183
18235
  },
18184
18236
  refEl: formRef,
18185
- fixedType: (_f = versionMode.sourceNodeData) == null ? void 0 : _f.type,
18186
- fixedColor: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.color,
18237
+ fixedType: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.type,
18238
+ fixedColor: (_h = versionMode.sourceNodeData) == null ? void 0 : _h.color,
18187
18239
  onUploadFile: upload_file_action,
18188
18240
  availableNodes: allAvailableNodes,
18189
18241
  availableAncestries: allAvailableAncestries
18190
18242
  }
18191
18243
  ),
18192
- questMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18244
+ questMode.isActive && /* @__PURE__ */ import_react32.default.createElement(
18193
18245
  InSceneQuestForm,
18194
18246
  {
18195
18247
  onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
@@ -18211,13 +18263,13 @@ function XViewScene({
18211
18263
  availableNodes: allAvailableNodes,
18212
18264
  availableAncestries: allAvailableAncestries,
18213
18265
  viewName: viewParams == null ? void 0 : viewParams.name,
18214
- questCounter: ((_h = sceneDataRef.current) == null ? void 0 : _h.quest_counter) || 1,
18266
+ questCounter: ((_i = sceneDataRef.current) == null ? void 0 : _i.quest_counter) || 1,
18215
18267
  viewMembers,
18216
- milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
18268
+ milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18217
18269
  onUpdateMilestones: handleUpdateMilestones
18218
18270
  }
18219
18271
  ),
18220
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react29.default.createElement(
18272
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react32.default.createElement(
18221
18273
  "div",
18222
18274
  {
18223
18275
  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"}`,
@@ -18230,7 +18282,7 @@ function XViewScene({
18230
18282
  maxWidth: "92vw"
18231
18283
  }
18232
18284
  },
18233
- /* @__PURE__ */ import_react29.default.createElement(
18285
+ /* @__PURE__ */ import_react32.default.createElement(
18234
18286
  "div",
18235
18287
  {
18236
18288
  onPointerDown: (e) => {
@@ -18241,7 +18293,7 @@ function XViewScene({
18241
18293
  title: "Arraste para redimensionar"
18242
18294
  }
18243
18295
  ),
18244
- /* @__PURE__ */ import_react29.default.createElement(
18296
+ /* @__PURE__ */ import_react32.default.createElement(
18245
18297
  DescriptionReadModePanel,
18246
18298
  {
18247
18299
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -18276,7 +18328,7 @@ function XViewScene({
18276
18328
  }
18277
18329
  )
18278
18330
  ),
18279
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react29.default.createElement(
18331
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react32.default.createElement(
18280
18332
  CreateAncestryPanel,
18281
18333
  {
18282
18334
  ancestryMode,
@@ -18312,7 +18364,7 @@ function XViewScene({
18312
18364
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
18313
18365
  }
18314
18366
  ),
18315
- editingAncestryRel.visible && /* @__PURE__ */ import_react29.default.createElement(
18367
+ editingAncestryRel.visible && /* @__PURE__ */ import_react32.default.createElement(
18316
18368
  AncestryRelationshipPanel,
18317
18369
  {
18318
18370
  data: editingAncestryRel.data,
@@ -18326,7 +18378,7 @@ function XViewScene({
18326
18378
  onUploadFile: upload_file_action
18327
18379
  }
18328
18380
  ),
18329
- detailsNode && detailsNode.is_quest && /* @__PURE__ */ import_react29.default.createElement(
18381
+ detailsNode && detailsNode.is_quest && /* @__PURE__ */ import_react32.default.createElement(
18330
18382
  QuestDetailsPanel,
18331
18383
  {
18332
18384
  node: detailsNode,
@@ -18348,11 +18400,11 @@ function XViewScene({
18348
18400
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
18349
18401
  viewMembers,
18350
18402
  currentUser: session == null ? void 0 : session.user,
18351
- milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18403
+ milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18352
18404
  onUpdateMilestones: handleUpdateMilestones
18353
18405
  }
18354
18406
  ),
18355
- detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react29.default.createElement(
18407
+ detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react32.default.createElement(
18356
18408
  NodeDetailsPanel,
18357
18409
  {
18358
18410
  node: detailsNode,
@@ -18384,7 +18436,7 @@ function XViewScene({
18384
18436
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
18385
18437
  }
18386
18438
  ),
18387
- detailsLink && /* @__PURE__ */ import_react29.default.createElement(
18439
+ detailsLink && /* @__PURE__ */ import_react32.default.createElement(
18388
18440
  RelationshipDetailsPanel,
18389
18441
  {
18390
18442
  link: detailsLink,
@@ -18398,7 +18450,7 @@ function XViewScene({
18398
18450
  userRole: userPermissionRole
18399
18451
  }
18400
18452
  ),
18401
- ancestryLinkDetails && /* @__PURE__ */ import_react29.default.createElement(
18453
+ ancestryLinkDetails && /* @__PURE__ */ import_react32.default.createElement(
18402
18454
  AncestryLinkDetailsPanel,
18403
18455
  {
18404
18456
  data: ancestryLinkDetails,
@@ -18409,7 +18461,7 @@ function XViewScene({
18409
18461
  onUploadFile: upload_file_action
18410
18462
  }
18411
18463
  ),
18412
- /* @__PURE__ */ import_react29.default.createElement(
18464
+ /* @__PURE__ */ import_react32.default.createElement(
18413
18465
  "div",
18414
18466
  {
18415
18467
  ref: tooltipRef,
@@ -18436,7 +18488,7 @@ function XViewScene({
18436
18488
  }
18437
18489
  }
18438
18490
  ),
18439
- /* @__PURE__ */ import_react29.default.createElement(
18491
+ /* @__PURE__ */ import_react32.default.createElement(
18440
18492
  ContextMenu,
18441
18493
  {
18442
18494
  data: contextMenu,
@@ -18469,7 +18521,7 @@ function XViewScene({
18469
18521
  onFinishQuest: handleFinishQuestQuick
18470
18522
  }
18471
18523
  ),
18472
- /* @__PURE__ */ import_react29.default.createElement(
18524
+ /* @__PURE__ */ import_react32.default.createElement(
18473
18525
  MultiNodeContextMenu,
18474
18526
  {
18475
18527
  data: multiContextMenu,
@@ -18489,7 +18541,7 @@ function XViewScene({
18489
18541
  )
18490
18542
  }
18491
18543
  ),
18492
- /* @__PURE__ */ import_react29.default.createElement(
18544
+ /* @__PURE__ */ import_react32.default.createElement(
18493
18545
  RelationshipContextMenu,
18494
18546
  {
18495
18547
  data: relationshipMenu,
@@ -18507,14 +18559,14 @@ function XViewScene({
18507
18559
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
18508
18560
  }
18509
18561
  ),
18510
- /* @__PURE__ */ import_react29.default.createElement(
18562
+ /* @__PURE__ */ import_react32.default.createElement(
18511
18563
  ImageViewer,
18512
18564
  {
18513
18565
  data: imageViewer,
18514
18566
  onClose: () => setImageViewer({ ...imageViewer, visible: false })
18515
18567
  }
18516
18568
  ),
18517
- /* @__PURE__ */ import_react29.default.createElement(
18569
+ /* @__PURE__ */ import_react32.default.createElement(
18518
18570
  AncestryBoard,
18519
18571
  {
18520
18572
  isOpen: isAncestryBoardOpen,
@@ -18527,29 +18579,29 @@ function XViewScene({
18527
18579
  userRole: userPermissionRole
18528
18580
  }
18529
18581
  ),
18530
- /* @__PURE__ */ import_react29.default.createElement(
18582
+ /* @__PURE__ */ import_react32.default.createElement(
18531
18583
  MilestoneManager,
18532
18584
  {
18533
18585
  isOpen: isMilestoneManagerOpen,
18534
18586
  onClose: () => setIsMilestoneManagerOpen(false),
18535
- milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18587
+ milestones: ((_l = sceneDataRef.current) == null ? void 0 : _l.milestones) || [],
18536
18588
  onUpdateMilestones: handleUpdateMilestones
18537
18589
  }
18538
18590
  ),
18539
- /* @__PURE__ */ import_react29.default.createElement(
18591
+ /* @__PURE__ */ import_react32.default.createElement(
18540
18592
  ImportParentFileModal,
18541
18593
  {
18542
18594
  isOpen: isImportModalOpen,
18543
18595
  onClose: () => setIsImportModalOpen(false),
18544
18596
  onConfirm: handleConfirmImport,
18545
18597
  session,
18546
- parentDbs: ((_l = sceneDataRef.current) == null ? void 0 : _l.parent_dbs) || [],
18598
+ parentDbs: ((_m = sceneDataRef.current) == null ? void 0 : _m.parent_dbs) || [],
18547
18599
  onFetchAvailableFiles: import_parent_file_modal_get,
18548
18600
  currentViewName: viewParams == null ? void 0 : viewParams.name,
18549
18601
  currentAncestries: ancestryDataRef.current || []
18550
18602
  }
18551
18603
  ),
18552
- invalidTargetError && /* @__PURE__ */ import_react29.default.createElement(
18604
+ invalidTargetError && /* @__PURE__ */ import_react32.default.createElement(
18553
18605
  "div",
18554
18606
  {
18555
18607
  className: "ui-overlay",
@@ -18574,13 +18626,13 @@ function XViewScene({
18574
18626
  animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
18575
18627
  }
18576
18628
  },
18577
- /* @__PURE__ */ import_react29.default.createElement("style", null, `
18629
+ /* @__PURE__ */ import_react32.default.createElement("style", null, `
18578
18630
  @keyframes fadeInDown {
18579
18631
  from { opacity: 0; transform: translate(-50%, -20px); }
18580
18632
  to { opacity: 1; transform: translate(-50%, 0); }
18581
18633
  }
18582
18634
  `),
18583
- /* @__PURE__ */ import_react29.default.createElement(
18635
+ /* @__PURE__ */ import_react32.default.createElement(
18584
18636
  "svg",
18585
18637
  {
18586
18638
  width: "20",
@@ -18592,12 +18644,12 @@ function XViewScene({
18592
18644
  strokeLinecap: "round",
18593
18645
  strokeLinejoin: "round"
18594
18646
  },
18595
- /* @__PURE__ */ import_react29.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18596
- /* @__PURE__ */ import_react29.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18597
- /* @__PURE__ */ import_react29.default.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18647
+ /* @__PURE__ */ import_react32.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18648
+ /* @__PURE__ */ import_react32.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18649
+ /* @__PURE__ */ import_react32.default.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18598
18650
  ),
18599
- /* @__PURE__ */ import_react29.default.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18600
- /* @__PURE__ */ import_react29.default.createElement(
18651
+ /* @__PURE__ */ import_react32.default.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18652
+ /* @__PURE__ */ import_react32.default.createElement(
18601
18653
  "button",
18602
18654
  {
18603
18655
  onClick: () => setInvalidTargetError(null),