@lv-x-software-house/x_view 1.2.6-dev.3 → 1.2.6-dev.7

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 +960 -605
  2. package/dist/index.mjs +908 -575
  3. package/package.json +4 -22
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- "use client";
2
1
  var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -30,14 +29,24 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
29
  // src/index.js
31
30
  var index_exports = {};
32
31
  __export(index_exports, {
33
- XViewScene: () => XViewScene
32
+ XViewScene: () => XViewScene,
33
+ delete_uploaded_file_logic: () => delete_uploaded_file_logic,
34
+ get_ancestry_board_logic: () => get_ancestry_board_logic,
35
+ get_ancestry_file_logic: () => get_ancestry_file_logic,
36
+ get_scene_view_data_logic: () => get_scene_view_data_logic,
37
+ get_single_parent_file_logic: () => get_single_parent_file_logic,
38
+ get_view_members_logic: () => get_view_members_logic,
39
+ import_parent_file_modal_get_logic: () => import_parent_file_modal_get_logic,
40
+ save_ancestry_board_logic: () => save_ancestry_board_logic,
41
+ save_view_data_logic: () => save_view_data_logic,
42
+ x_view_add_new_parent_file_to_scene_at_firebase: () => x_view_add_new_parent_file_to_scene_at_firebase
34
43
  });
35
44
  module.exports = __toCommonJS(index_exports);
36
45
 
37
46
  // src/XViewScene.jsx
38
- var import_react32 = __toESM(require("react"));
47
+ var import_react29 = __toESM(require("react"));
39
48
  var import_navigation = require("next/navigation");
40
- var import_react33 = require("next-auth/react");
49
+ var import_react30 = require("next-auth/react");
41
50
  var import_crypto_js = __toESM(require("crypto-js"));
42
51
  var THREE3 = __toESM(require("three"));
43
52
  var import_OrbitControls = require("three/examples/jsm/controls/OrbitControls.js");
@@ -1083,6 +1092,8 @@ var userActionHandlers = {
1083
1092
  if (isCrossDataset) {
1084
1093
  graphDataRef.current[finalTargetDatasetId] = targetDataToUpdate;
1085
1094
  }
1095
+ if (sceneDataRef.current.parent_dbs.some((db) => String(db.db_id) === String(sourceParentInfo.parentFileId))) {
1096
+ }
1086
1097
  const finalPosition = stateRef.current.ghostElements.node.position.clone();
1087
1098
  addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
1088
1099
  stateRef.current.nodeIdToParentFileMap.set(String(newNode.id), {
@@ -1281,6 +1292,9 @@ var userActionHandlers = {
1281
1292
  );
1282
1293
  }
1283
1294
  graphDataRef.current[parentFileId] = specificParentData;
1295
+ if (isView && parentFileId === context.sceneConfigId) {
1296
+ sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
1297
+ }
1284
1298
  const finalPosition = stateRef.current.ghostElements.node.position.clone();
1285
1299
  addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
1286
1300
  setters.setSceneVersion((v) => v + 1);
@@ -2300,8 +2314,6 @@ var userActionHandlers = {
2300
2314
  milestones: sceneDataRef.current.milestones || [],
2301
2315
  quest_counter: sceneDataRef.current.quest_counter || 1
2302
2316
  };
2303
- sceneDataRef.current.quest_nodes = specificParentData.nodes;
2304
- sceneDataRef.current.quest_links = specificParentData.links;
2305
2317
  await context.actions.save_view_data(
2306
2318
  context.sceneSaveUrl,
2307
2319
  viewFilePayload
@@ -2314,6 +2326,10 @@ var userActionHandlers = {
2314
2326
  );
2315
2327
  }
2316
2328
  graphDataRef.current[parentFileId] = specificParentData;
2329
+ if (isView && parentFileId === context.sceneConfigId) {
2330
+ sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
2331
+ sceneDataRef.current.quest_counter = specificParentData.quest_counter || sceneDataRef.current.quest_counter;
2332
+ }
2317
2333
  updateExistingNodeVisuals(stateRef.current, nodeToSave);
2318
2334
  setters.setSceneVersion((v) => v + 1);
2319
2335
  if (!keepOpen) {
@@ -12903,371 +12919,130 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
12903
12919
  }
12904
12920
 
12905
12921
  // src/components/AncestryBoard.jsx
12906
- var import_react30 = __toESM(require("react"));
12907
- var import_fi23 = require("react-icons/fi");
12908
- var import_uuid11 = require("uuid");
12909
-
12910
- // src/components/MentionEditor.jsx
12911
- var import_react28 = __toESM(require("react"));
12912
- var import_react29 = require("@tiptap/react");
12913
- var import_starter_kit = __toESM(require("@tiptap/starter-kit"));
12914
- var import_extension_mention = __toESM(require("@tiptap/extension-mention"));
12915
- var import_tippy = __toESM(require("tippy.js"));
12916
-
12917
- // src/components/MentionList.jsx
12918
12922
  var import_react27 = __toESM(require("react"));
12919
12923
  var import_fi22 = require("react-icons/fi");
12920
- var MentionList = (0, import_react27.forwardRef)((props, ref) => {
12921
- const [selectedIndex, setSelectedIndex] = (0, import_react27.useState)(0);
12922
- const selectItem = (index) => {
12923
- const item = props.items[index];
12924
- if (item) {
12925
- props.command({ id: item.id, label: item.name, type: item.type });
12926
- }
12927
- };
12928
- const upHandler = () => {
12929
- setSelectedIndex(
12930
- (selectedIndex + props.items.length - 1) % props.items.length
12931
- );
12932
- };
12933
- const downHandler = () => {
12934
- setSelectedIndex((selectedIndex + 1) % props.items.length);
12935
- };
12936
- const enterHandler = () => {
12937
- selectItem(selectedIndex);
12938
- };
12939
- (0, import_react27.useEffect)(() => setSelectedIndex(0), [props.items]);
12940
- (0, import_react27.useImperativeHandle)(ref, () => ({
12941
- onKeyDown: ({ event }) => {
12942
- if (event.key === "ArrowUp") {
12943
- upHandler();
12944
- return true;
12945
- }
12946
- if (event.key === "ArrowDown") {
12947
- downHandler();
12948
- return true;
12949
- }
12950
- if (event.key === "Enter") {
12951
- enterHandler();
12952
- return true;
12953
- }
12954
- return false;
12955
- }
12956
- }));
12957
- 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) => {
12958
- const isQuest = item.type === "quest";
12959
- const isVersion = item.type === "version";
12960
- const isNode = item.type === "node";
12961
- let Icon = import_fi22.FiLayers;
12962
- let colorClass = "text-indigo-400";
12963
- let badgeText = "Ancestralidade";
12964
- if (isQuest) {
12965
- Icon = import_fi22.FiCheckSquare;
12966
- colorClass = "text-amber-400";
12967
- badgeText = "Quest";
12968
- } else if (isVersion) {
12969
- Icon = import_fi22.FiGitBranch;
12970
- colorClass = "text-purple-400";
12971
- badgeText = "Vers\xE3o";
12972
- } else if (isNode) {
12973
- Icon = import_fi22.FiBox;
12974
- colorClass = "text-emerald-400";
12975
- badgeText = "Node";
12976
- }
12977
- return /* @__PURE__ */ import_react27.default.createElement(
12978
- "button",
12979
- {
12980
- className: `
12981
- w-full flex items-center gap-3 px-3 py-2 text-left rounded-md transition-all
12982
- ${index === selectedIndex ? "bg-indigo-500/20 border border-indigo-500/30 text-white" : "text-slate-400 hover:bg-white/5 border border-transparent"}
12983
- `,
12984
- key: item.id,
12985
- onClick: () => selectItem(index)
12986
- },
12987
- /* @__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 })),
12988
- /* @__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)))
12989
- );
12990
- }) : /* @__PURE__ */ import_react27.default.createElement("div", { className: "p-4 text-center text-slate-500 text-sm italic" }, "Nenhum resultado encontrado...")));
12991
- });
12992
- MentionList.displayName = "MentionList";
12993
- var MentionList_default = MentionList;
12994
-
12995
- // src/components/MentionEditor.jsx
12996
- var CustomMention = import_extension_mention.default.extend({
12997
- addAttributes() {
12998
- var _a;
12999
- return {
13000
- ...(_a = this.parent) == null ? void 0 : _a.call(this),
13001
- type: {
13002
- default: null,
13003
- parseHTML: (element) => element.getAttribute("data-mention-type"),
13004
- renderHTML: (attributes) => {
13005
- if (!attributes.type) {
13006
- return {};
13007
- }
13008
- return {
13009
- "data-mention-type": attributes.type
13010
- };
13011
- }
13012
- },
13013
- label: {
13014
- default: null,
13015
- parseHTML: (element) => element.getAttribute("data-label"),
13016
- renderHTML: (attributes) => {
13017
- if (!attributes.label) {
13018
- return {};
13019
- }
13020
- return {
13021
- "data-label": attributes.label
13022
- };
13023
- }
13024
- }
13025
- };
13026
- }
13027
- });
13028
- var MentionEditor = ({
13029
- initialValue = "",
13030
- onChange,
13031
- onPlay,
13032
- availableItems = [],
13033
- canEdit = true,
13034
- placeholder = "Escreva algo... use @ para mencionar"
13035
- }) => {
13036
- const parseInitialContent = (text) => {
13037
- if (!text) return "<p></p>";
13038
- const parts = text.split(/(\[\[MENTION:[^\]]+\]\])/g);
13039
- return parts.map((part) => {
13040
- const match = part.match(/\[\[MENTION:([^:]+):([^:]+):([^\]]+)\]\]/);
13041
- if (match) {
13042
- const [, type, id, label] = match;
13043
- return `<span data-type="mention" data-id="${id}" data-mention-type="${type}" data-label="${label}">@${label}</span>`;
13044
- }
13045
- return part;
13046
- }).join("");
13047
- };
13048
- const content = (0, import_react28.useMemo)(() => parseInitialContent(initialValue), [initialValue]);
13049
- const editor = (0, import_react29.useEditor)({
13050
- extensions: [
13051
- import_starter_kit.default.configure({
13052
- heading: false,
13053
- bulletList: false,
13054
- orderedList: false,
13055
- codeBlock: false,
13056
- blockquote: false
13057
- }),
13058
- CustomMention.configure({
13059
- HTMLAttributes: {
13060
- class: "mention"
13061
- },
13062
- suggestion: {
13063
- items: ({ query }) => {
13064
- return availableItems.filter(
13065
- (item) => item.name.toLowerCase().includes(query.toLowerCase())
13066
- ).slice(0, 10);
13067
- },
13068
- render: () => {
13069
- let component;
13070
- let popup;
13071
- return {
13072
- onStart: (props) => {
13073
- component = new import_react29.ReactRenderer(MentionList_default, {
13074
- props,
13075
- editor: props.editor
13076
- });
13077
- if (!props.clientRect) {
13078
- return;
13079
- }
13080
- popup = (0, import_tippy.default)("body", {
13081
- getReferenceClientRect: props.clientRect,
13082
- appendTo: () => document.body,
13083
- content: component.element,
13084
- showOnCreate: true,
13085
- interactive: true,
13086
- trigger: "manual",
13087
- placement: "bottom-start",
13088
- theme: "x-view-dark"
13089
- });
13090
- },
13091
- onUpdate(props) {
13092
- component.updateProps(props);
13093
- if (!props.clientRect) {
13094
- return;
13095
- }
13096
- popup[0].setProps({
13097
- getReferenceClientRect: props.clientRect
13098
- });
13099
- },
13100
- onKeyDown(props) {
13101
- var _a;
13102
- if (props.event.key === "Escape") {
13103
- popup[0].hide();
13104
- return true;
13105
- }
13106
- return (_a = component == null ? void 0 : component.ref) == null ? void 0 : _a.onKeyDown(props);
13107
- },
13108
- onExit() {
13109
- if (popup && popup[0]) popup[0].destroy();
13110
- if (component) component.destroy();
13111
- }
13112
- };
13113
- }
13114
- }
13115
- })
13116
- ],
13117
- content,
13118
- editable: canEdit,
13119
- onUpdate: ({ editor: editor2 }) => {
13120
- const serialize = (json) => {
13121
- if (!json.content) return "";
13122
- return json.content.map((block) => {
13123
- if (block.type === "paragraph") {
13124
- const inner = block.content ? block.content.map((node) => {
13125
- if (node.type === "text") return node.text;
13126
- if (node.type === "mention") {
13127
- return `[[MENTION:${node.attrs.type}:${node.attrs.id}:${node.attrs.label}]]`;
13128
- }
13129
- return "";
13130
- }).join("") : "";
13131
- return inner;
13132
- }
13133
- return "";
13134
- }).join("\n").trim();
13135
- };
13136
- const serialized = serialize(editor2.getJSON());
13137
- onChange(serialized);
13138
- }
13139
- });
13140
- if (!editor) {
13141
- return null;
13142
- }
13143
- return /* @__PURE__ */ import_react28.default.createElement("div", { className: "relative group/editor min-h-[1.5rem] w-full" }, /* @__PURE__ */ import_react28.default.createElement(
13144
- import_react29.EditorContent,
13145
- {
13146
- editor,
13147
- className: "text-sm text-slate-200 placeholder-slate-600 focus:outline-none"
13148
- }
13149
- ), /* @__PURE__ */ import_react28.default.createElement("style", null, `
13150
- .tiptap p {
13151
- margin: 0;
13152
- min-height: 1.25rem;
13153
- line-height: 1.5;
13154
- }
13155
- .tiptap .mention {
13156
- display: inline-flex;
13157
- align-items: center;
13158
- background: rgba(99, 102, 241, 0.12);
13159
- border: 1px solid rgba(99, 102, 241, 0.25);
13160
- border-radius: 6px;
13161
- padding: 1px 6px;
13162
- color: #a5b4fc;
13163
- font-weight: 600;
13164
- cursor: pointer;
13165
- margin: 0 1px;
13166
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
13167
- transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
13168
- font-size: 0.85rem;
13169
- text-decoration: none;
13170
- vertical-align: baseline;
13171
- }
13172
- .tiptap .mention:hover {
13173
- background: rgba(99, 102, 241, 0.22);
13174
- border-color: rgba(99, 102, 241, 0.5);
13175
- color: #fff;
13176
- transform: translateY(-1px);
13177
- box-shadow: 0 4px 12px rgba(99, 102, 241, 0.2);
13178
- }
13179
- .tiptap .mention::before {
13180
- content: "";
13181
- display: inline-block;
13182
- width: 12px;
13183
- height: 12px;
13184
- margin-right: 4px;
13185
- background-size: contain;
13186
- background-repeat: no-repeat;
13187
- opacity: 0.8;
13188
- filter: brightness(1.2);
13189
- }
13190
-
13191
- /* Type specific styles */
13192
- .tiptap .mention[data-mention-type="ancestry"] {
13193
- background: rgba(139, 92, 246, 0.15);
13194
- border-color: rgba(139, 92, 246, 0.3);
13195
- color: #c4b5fd;
13196
- }
13197
- .tiptap .mention[data-mention-type="quest"] {
13198
- background: rgba(16, 185, 129, 0.15);
13199
- border-color: rgba(16, 185, 129, 0.3);
13200
- color: #6ee7b7;
13201
- }
13202
- .tiptap .mention[data-mention-type="node"] {
13203
- background: rgba(59, 130, 246, 0.15);
13204
- border-color: rgba(59, 130, 246, 0.3);
13205
- color: #93c5fd;
13206
- }
13207
- .tiptap .mention[data-mention-type="version"] {
13208
- background: rgba(245, 158, 11, 0.15);
13209
- border-color: rgba(245, 158, 11, 0.3);
13210
- color: #fcd34d;
13211
- }
13212
-
13213
- .tiptap:focus {
13214
- outline: none;
13215
- }
13216
-
13217
- .ProseMirror-placeholder:first-child::before {
13218
- content: attr(data-placeholder);
13219
- float: left;
13220
- color: #475569;
13221
- pointer-events: none;
13222
- height: 0;
13223
- font-style: italic;
13224
- }
13225
- `));
13226
- };
13227
- var MentionEditor_default = MentionEditor;
13228
-
13229
- // src/components/AncestryBoard.jsx
12924
+ var import_uuid11 = require("uuid");
13230
12925
  var GroupItem = ({
13231
12926
  group,
13232
12927
  index,
12928
+ siblings,
13233
12929
  onUpdate,
13234
12930
  onDelete,
13235
12931
  onAddSubgroup,
13236
12932
  onIndent,
13237
12933
  onOutdent,
12934
+ onRemoveAncestry,
12935
+ onRequestPickAncestry,
12936
+ pickingGroupId,
13238
12937
  onPlayAncestry,
13239
- availableMentionItems,
12938
+ availableIds,
13240
12939
  canEdit
13241
12940
  }) => {
13242
12941
  const canIndent = index > 0;
13243
- 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(
12942
+ const isPickingForThisGroup = pickingGroupId === group.id;
12943
+ const textareaRef = (0, import_react27.useRef)(null);
12944
+ const adjustHeight = () => {
12945
+ const textarea = textareaRef.current;
12946
+ if (textarea) {
12947
+ textarea.style.height = "auto";
12948
+ textarea.style.height = `${textarea.scrollHeight}px`;
12949
+ }
12950
+ };
12951
+ (0, import_react27.useEffect)(() => {
12952
+ adjustHeight();
12953
+ }, [group.text]);
12954
+ 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(
13244
12955
  "div",
13245
12956
  {
13246
- 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"
12957
+ className: `
12958
+ flex flex-col gap-2 py-2 px-3 transition-all duration-200
12959
+ ${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
12960
+ `
13247
12961
  },
13248
- /* @__PURE__ */ import_react30.default.createElement(
13249
- MentionEditor_default,
12962
+ /* @__PURE__ */ import_react27.default.createElement(
12963
+ "textarea",
13250
12964
  {
13251
- initialValue: group.text,
13252
- onChange: (newText) => {
13253
- if (canEdit) onUpdate(group.id, { ...group, text: newText });
12965
+ ref: textareaRef,
12966
+ 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" : ""}`,
12967
+ rows: 1,
12968
+ style: {
12969
+ minHeight: "1.5rem",
12970
+ maxHeight: "250px"
13254
12971
  },
13255
- onPlay: onPlayAncestry,
13256
- availableItems: availableMentionItems,
13257
- canEdit,
13258
- placeholder: "Escreva sobre este grupo... use @ para mencionar"
12972
+ placeholder: canEdit ? "Escreva sobre este grupo..." : "",
12973
+ value: group.text,
12974
+ readOnly: !canEdit,
12975
+ onChange: (e) => {
12976
+ if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
12977
+ }
13259
12978
  }
13260
12979
  ),
13261
- 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(
12980
+ group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
12981
+ const isValid = availableIds.has(String(anc.ancestry_id));
12982
+ return /* @__PURE__ */ import_react27.default.createElement(
12983
+ "div",
12984
+ {
12985
+ key: anc.ancestry_id,
12986
+ className: `
12987
+ flex items-center gap-2 rounded-md px-3 py-1.5 text-xs transition-all group/card border
12988
+ ${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"}
12989
+ `,
12990
+ title: isValid ? "" : "Esta ancestralidade foi removida ou n\xE3o existe mais."
12991
+ },
12992
+ isValid ? /* @__PURE__ */ import_react27.default.createElement(
12993
+ "button",
12994
+ {
12995
+ onClick: () => onPlayAncestry(anc),
12996
+ className: "text-indigo-400 hover:text-white hover:bg-indigo-500 p-1 rounded-full transition-colors",
12997
+ title: "Focar no cen\xE1rio"
12998
+ },
12999
+ /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiPlay, { size: 10, className: "ml-0.5 fill-current" })
13000
+ ) : /* @__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 })),
13001
+ /* @__PURE__ */ import_react27.default.createElement(
13002
+ "div",
13003
+ {
13004
+ className: `flex items-center gap-1.5 font-medium truncate max-w-[180px] ${!isValid && "line-through decoration-red-500/50"}`
13005
+ },
13006
+ !isValid ? null : anc.type === "node" ? /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiBox, { size: 10, className: "text-slate-400" }) : anc.type === "quest" ? /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiCheckSquare, { size: 10, className: "text-emerald-400" }) : anc.type === "version" ? /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiGitBranch, { size: 10, className: "text-amber-400" }) : /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiLayers, { size: 10, className: "text-indigo-400" }),
13007
+ anc.name
13008
+ ),
13009
+ canEdit && /* @__PURE__ */ import_react27.default.createElement(import_react27.default.Fragment, null, /* @__PURE__ */ import_react27.default.createElement(
13010
+ "div",
13011
+ {
13012
+ className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}`
13013
+ }
13014
+ ), /* @__PURE__ */ import_react27.default.createElement(
13015
+ "button",
13016
+ {
13017
+ onClick: () => onRemoveAncestry(group.id, anc.ancestry_id),
13018
+ className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
13019
+ title: "Remover men\xE7\xE3o"
13020
+ },
13021
+ /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiX, { size: 12 })
13022
+ ))
13023
+ );
13024
+ })),
13025
+ 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(
13026
+ "button",
13027
+ {
13028
+ onClick: () => onRequestPickAncestry(group.id),
13029
+ className: `
13030
+ flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium transition-colors
13031
+ ${isPickingForThisGroup ? "text-indigo-300 animate-pulse" : "text-slate-500 hover:text-indigo-300 hover:bg-indigo-500/10"}
13032
+ `,
13033
+ title: "Adicionar Ancestralidade a este grupo"
13034
+ },
13035
+ isPickingForThisGroup ? /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiCheckCircle, { size: 12 }) : /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiSearch, { size: 12 }),
13036
+ isPickingForThisGroup ? "Selecionando..." : "Adicionar"
13037
+ ), /* @__PURE__ */ import_react27.default.createElement(
13262
13038
  "button",
13263
13039
  {
13264
13040
  onClick: () => onAddSubgroup(group.id),
13265
- 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",
13041
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13266
13042
  title: "Criar Subgrupo"
13267
13043
  },
13268
- /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiPlus, { size: 14 }),
13269
- /* @__PURE__ */ import_react30.default.createElement("span", null, "Adicionar Subgrupo")
13270
- )), /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react30.default.createElement(
13044
+ /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiPlus, { size: 14 })
13045
+ )), /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react27.default.createElement(
13271
13046
  "button",
13272
13047
  {
13273
13048
  onClick: () => onIndent(group.id),
@@ -13275,25 +13050,25 @@ var GroupItem = ({
13275
13050
  className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13276
13051
  title: "Aninhar no grupo acima"
13277
13052
  },
13278
- /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiArrowRight, { size: 14 })
13279
- ), /* @__PURE__ */ import_react30.default.createElement(
13053
+ /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiArrowRight, { size: 14 })
13054
+ ), /* @__PURE__ */ import_react27.default.createElement(
13280
13055
  "button",
13281
13056
  {
13282
13057
  onClick: () => onOutdent(group.id),
13283
13058
  className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13284
13059
  title: "Desaninhar"
13285
13060
  },
13286
- /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiArrowLeft, { size: 14 })
13287
- ), /* @__PURE__ */ import_react30.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react30.default.createElement(
13061
+ /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiArrowLeft, { size: 14 })
13062
+ ), /* @__PURE__ */ import_react27.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react27.default.createElement(
13288
13063
  "button",
13289
13064
  {
13290
13065
  onClick: () => onDelete(group.id),
13291
13066
  className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13292
13067
  title: "Remover Grupo"
13293
13068
  },
13294
- /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiTrash2, { size: 14 })
13069
+ /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiTrash2, { size: 14 })
13295
13070
  )))
13296
- ), 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(
13071
+ ), 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(
13297
13072
  GroupItem,
13298
13073
  {
13299
13074
  key: childGroup.id,
@@ -13305,8 +13080,11 @@ var GroupItem = ({
13305
13080
  onAddSubgroup,
13306
13081
  onIndent,
13307
13082
  onOutdent,
13083
+ onRemoveAncestry,
13084
+ onRequestPickAncestry,
13085
+ pickingGroupId,
13308
13086
  onPlayAncestry,
13309
- availableMentionItems,
13087
+ availableIds,
13310
13088
  canEdit
13311
13089
  }
13312
13090
  ))));
@@ -13320,20 +13098,23 @@ function AncestryBoard({
13320
13098
  initialGroups = [],
13321
13099
  onSave,
13322
13100
  userRole
13101
+ // [NOVO] Recebe a role do usuário
13323
13102
  }) {
13324
- const [groups, setGroups] = (0, import_react30.useState)([]);
13325
- const [isLoaded, setIsLoaded] = (0, import_react30.useState)(false);
13326
- const [saveStatus, setSaveStatus] = (0, import_react30.useState)("idle");
13327
- const canEdit = (0, import_react30.useMemo)(() => {
13103
+ const [searchTerm, setSearchTerm] = (0, import_react27.useState)("");
13104
+ const [groups, setGroups] = (0, import_react27.useState)([]);
13105
+ const [isLoaded, setIsLoaded] = (0, import_react27.useState)(false);
13106
+ const [pickingGroupId, setPickingGroupId] = (0, import_react27.useState)(null);
13107
+ const [saveStatus, setSaveStatus] = (0, import_react27.useState)("idle");
13108
+ const canEdit = (0, import_react27.useMemo)(() => {
13328
13109
  return userRole !== "viewer";
13329
13110
  }, [userRole]);
13330
- (0, import_react30.useEffect)(() => {
13111
+ (0, import_react27.useEffect)(() => {
13331
13112
  if (initialGroups && !isLoaded) {
13332
13113
  setGroups(initialGroups);
13333
13114
  setIsLoaded(true);
13334
13115
  }
13335
13116
  }, [initialGroups, isLoaded]);
13336
- const nodeNamesMap = (0, import_react30.useMemo)(() => {
13117
+ const nodeNamesMap = (0, import_react27.useMemo)(() => {
13337
13118
  const map = /* @__PURE__ */ new Map();
13338
13119
  if (availableNodes && Array.isArray(availableNodes)) {
13339
13120
  availableNodes.forEach((node) => {
@@ -13344,41 +13125,52 @@ function AncestryBoard({
13344
13125
  }
13345
13126
  return map;
13346
13127
  }, [availableNodes]);
13347
- const availableIds = (0, import_react30.useMemo)(() => {
13348
- return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
13349
- }, [availableAncestries]);
13350
- const availableMentionItems = (0, import_react30.useMemo)(() => {
13351
- const ancestries = availableAncestries.map((a) => ({
13352
- id: String(a.ancestry_id),
13353
- ancestry_id: a.ancestry_id,
13354
- name: a.name,
13355
- description: a.description,
13356
- type: "ancestry",
13357
- ancestral_node: a.ancestral_node,
13358
- is_private: a.is_private
13359
- }));
13360
- const nodes = availableNodes.map((n) => {
13128
+ const availableIds = (0, import_react27.useMemo)(() => {
13129
+ const ids = /* @__PURE__ */ new Set();
13130
+ availableAncestries.forEach((a) => ids.add(String(a.ancestry_id)));
13131
+ availableNodes.forEach((n) => ids.add(String(n.id)));
13132
+ return ids;
13133
+ }, [availableAncestries, availableNodes]);
13134
+ const allSearchableItems = (0, import_react27.useMemo)(() => {
13135
+ const items = [];
13136
+ availableAncestries.forEach((anc) => {
13137
+ items.push({
13138
+ ...anc,
13139
+ id: String(anc.ancestry_id),
13140
+ type: "ancestry",
13141
+ searchLabel: anc.name || "",
13142
+ searchDesc: anc.description || ""
13143
+ });
13144
+ });
13145
+ availableNodes.forEach((node) => {
13146
+ var _a;
13361
13147
  let type = "node";
13362
- if (n.is_quest) type = "quest";
13363
- else if (n.is_version) type = "version";
13364
- return {
13365
- id: String(n.id),
13366
- name: n.name,
13367
- description: n.description,
13148
+ if (node.is_quest) type = "quest";
13149
+ else if ((_a = node.version_node) == null ? void 0 : _a.is_version) type = "version";
13150
+ items.push({
13151
+ ...node,
13152
+ id: String(node.id),
13368
13153
  type,
13369
- raw_node: n
13370
- };
13154
+ searchLabel: node.name || node.raw_title || "",
13155
+ searchDesc: node.description || ""
13156
+ });
13371
13157
  });
13372
- return [...ancestries, ...nodes];
13158
+ return items;
13373
13159
  }, [availableAncestries, availableNodes]);
13374
13160
  const sanitizeGroups = (groupList) => {
13375
13161
  return groupList.map((g) => ({
13376
13162
  id: g.id,
13377
13163
  text: g.text || "",
13164
+ ancestries: (g.ancestries || []).map((a) => ({
13165
+ id: a.id || a.ancestry_id,
13166
+ ancestry_id: a.ancestry_id || a.id,
13167
+ name: a.name,
13168
+ type: a.type || "ancestry"
13169
+ })),
13378
13170
  children: sanitizeGroups(g.children || [])
13379
13171
  }));
13380
13172
  };
13381
- (0, import_react30.useEffect)(() => {
13173
+ (0, import_react27.useEffect)(() => {
13382
13174
  if (!isLoaded || !onSave) return;
13383
13175
  const timeoutId = setTimeout(async () => {
13384
13176
  setSaveStatus("saving");
@@ -13396,22 +13188,42 @@ function AncestryBoard({
13396
13188
  }, 3e3);
13397
13189
  return () => clearTimeout(timeoutId);
13398
13190
  }, [groups, isLoaded, onSave]);
13399
- (0, import_react30.useEffect)(() => {
13191
+ (0, import_react27.useEffect)(() => {
13400
13192
  if (!isOpen) return;
13401
13193
  const handleKeyDown = (e) => {
13402
13194
  if (e.key === "Escape") {
13403
- onClose();
13195
+ if (pickingGroupId) {
13196
+ setPickingGroupId(null);
13197
+ } else {
13198
+ onClose();
13199
+ }
13404
13200
  e.preventDefault();
13405
13201
  e.stopPropagation();
13406
13202
  }
13407
13203
  };
13408
13204
  window.addEventListener("keydown", handleKeyDown);
13409
13205
  return () => window.removeEventListener("keydown", handleKeyDown);
13410
- }, [isOpen, onClose]);
13206
+ }, [isOpen, onClose, pickingGroupId]);
13207
+ const filtered = (0, import_react27.useMemo)(() => {
13208
+ const term = searchTerm.toLowerCase().trim();
13209
+ return allSearchableItems.filter((item) => {
13210
+ var _a, _b;
13211
+ if (!term) return true;
13212
+ const labelMatch = (_a = item.searchLabel) == null ? void 0 : _a.toLowerCase().includes(term);
13213
+ const descMatch = (_b = item.searchDesc) == null ? void 0 : _b.toLowerCase().includes(term);
13214
+ let parentMatch = false;
13215
+ if (item.type === "ancestry") {
13216
+ const parentName = nodeNamesMap.get(String(item.ancestral_node)) || "";
13217
+ parentMatch = parentName.toLowerCase().includes(term);
13218
+ }
13219
+ return labelMatch || descMatch || parentMatch;
13220
+ });
13221
+ }, [allSearchableItems, searchTerm, nodeNamesMap]);
13411
13222
  const handleAddRootGroup = () => {
13412
13223
  const newGroup = {
13413
13224
  id: (0, import_uuid11.v4)(),
13414
13225
  text: "",
13226
+ ancestries: [],
13415
13227
  children: []
13416
13228
  };
13417
13229
  setGroups((prev) => [newGroup, ...prev]);
@@ -13420,6 +13232,7 @@ function AncestryBoard({
13420
13232
  const newGroup = {
13421
13233
  id: (0, import_uuid11.v4)(),
13422
13234
  text: "",
13235
+ ancestries: [],
13423
13236
  children: []
13424
13237
  };
13425
13238
  const addRecursive = (list) => {
@@ -13490,49 +13303,91 @@ function AncestryBoard({
13490
13303
  return newList;
13491
13304
  });
13492
13305
  };
13493
- const handlePlayFromGroup = (item) => {
13494
- let fullItem = item;
13495
- if (item.type === "ancestry" || !item.type) {
13496
- fullItem = availableAncestries.find(
13497
- (a) => String(a.ancestry_id) === String(item.id || item.ancestry_id)
13498
- ) || item;
13499
- } else {
13500
- fullItem = availableNodes.find(
13501
- (n) => String(n.id) === String(item.id)
13502
- ) || item;
13306
+ const handleRequestPick = (groupId) => {
13307
+ setPickingGroupId((prev) => prev === groupId ? null : groupId);
13308
+ };
13309
+ const handleSelectAncestry = (ancestry) => {
13310
+ if (pickingGroupId) {
13311
+ setGroups((prev) => {
13312
+ const addRecursive = (list) => {
13313
+ return list.map((g) => {
13314
+ if (g.id === pickingGroupId) {
13315
+ const exists = g.ancestries.some(
13316
+ (a) => String(a.id || a.ancestry_id) === String(ancestry.id)
13317
+ );
13318
+ if (exists) return g;
13319
+ return {
13320
+ ...g,
13321
+ ancestries: [
13322
+ ...g.ancestries,
13323
+ {
13324
+ id: ancestry.id,
13325
+ ancestry_id: ancestry.id,
13326
+ name: ancestry.searchLabel,
13327
+ type: ancestry.type
13328
+ }
13329
+ ]
13330
+ };
13331
+ }
13332
+ return { ...g, children: addRecursive(g.children) };
13333
+ });
13334
+ };
13335
+ return addRecursive(prev);
13336
+ });
13337
+ onSelect(ancestry);
13503
13338
  }
13504
- if (fullItem && onSelect) {
13505
- onSelect(fullItem);
13339
+ };
13340
+ const handlePlayFromGroup = (ancestry) => {
13341
+ if (ancestry && onSelect) {
13342
+ onSelect(ancestry);
13506
13343
  }
13507
13344
  };
13345
+ const handleRemoveAncestryFromGroup = (groupId, ancestryId) => {
13346
+ setGroups((prev) => {
13347
+ const removeRecursive = (list) => {
13348
+ return list.map((g) => {
13349
+ if (g.id === groupId) {
13350
+ return {
13351
+ ...g,
13352
+ ancestries: g.ancestries.filter(
13353
+ (a) => String(a.id || a.ancestry_id) !== String(ancestryId)
13354
+ )
13355
+ };
13356
+ }
13357
+ return { ...g, children: removeRecursive(g.children) };
13358
+ });
13359
+ };
13360
+ return removeRecursive(prev);
13361
+ });
13362
+ };
13508
13363
  if (!isOpen) return null;
13509
- return /* @__PURE__ */ import_react30.default.createElement(
13364
+ return /* @__PURE__ */ import_react27.default.createElement(
13510
13365
  "div",
13511
13366
  {
13512
13367
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
13513
13368
  onClick: onClose
13514
13369
  },
13515
- /* @__PURE__ */ import_react30.default.createElement(
13370
+ /* @__PURE__ */ import_react27.default.createElement(
13516
13371
  "div",
13517
13372
  {
13518
- 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",
13373
+ 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",
13519
13374
  onClick: (e) => e.stopPropagation()
13520
13375
  },
13521
- /* @__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(
13522
- import_fi23.FiLoader,
13376
+ /* @__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(
13377
+ import_fi22.FiLoader,
13523
13378
  {
13524
13379
  className: "animate-spin text-indigo-400",
13525
13380
  size: 12
13526
13381
  }
13527
- ), /* @__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(
13382
+ ), /* @__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(
13528
13383
  "button",
13529
13384
  {
13530
13385
  onClick: handleAddRootGroup,
13531
13386
  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 "
13532
13387
  },
13533
- /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiPlus, { size: 14, className: "text-indigo-400" }),
13534
- /* @__PURE__ */ import_react30.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13535
- ), /* @__PURE__ */ import_react30.default.createElement(
13388
+ /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiPlus, { size: 14, className: "text-indigo-400" }),
13389
+ /* @__PURE__ */ import_react27.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13390
+ ), /* @__PURE__ */ import_react27.default.createElement(
13536
13391
  "button",
13537
13392
  {
13538
13393
  onClick: onClose,
@@ -13540,37 +13395,103 @@ function AncestryBoard({
13540
13395
  },
13541
13396
  "\xD7"
13542
13397
  ))),
13543
- /* @__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(
13544
- "button",
13398
+ /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react27.default.createElement(
13399
+ "div",
13545
13400
  {
13546
- onClick: handleAddRootGroup,
13547
- 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"
13401
+ className: `
13402
+ flex flex-col border-r border-white/10 transition-all duration-300 flex-none
13403
+ ${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
13404
+ min-w-[280px] max-w-[500px] bg-slate-900
13405
+ `
13548
13406
  },
13549
- "Criar Primeiro Grupo"
13550
- )) : groups.map((group, index) => /* @__PURE__ */ import_react30.default.createElement(
13407
+ /* @__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(
13408
+ import_fi22.FiSearch,
13409
+ {
13410
+ 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"}`
13411
+ }
13412
+ ), /* @__PURE__ */ import_react27.default.createElement(
13413
+ "input",
13414
+ {
13415
+ type: "text",
13416
+ placeholder: pickingGroupId ? "Pesquise nodes ou ancestralidades..." : "Pesquisar no board...",
13417
+ className: `
13418
+ 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
13419
+ ${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"}
13420
+ `,
13421
+ value: searchTerm,
13422
+ onChange: (e) => setSearchTerm(e.target.value),
13423
+ autoFocus: !pickingGroupId
13424
+ }
13425
+ ))),
13426
+ /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
13427
+ const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
13428
+ const isPicking = !!pickingGroupId;
13429
+ return /* @__PURE__ */ import_react27.default.createElement(
13430
+ "div",
13431
+ {
13432
+ key: anc.id,
13433
+ onClick: () => {
13434
+ if (isPicking) handleSelectAncestry(anc);
13435
+ },
13436
+ className: `
13437
+ group relative flex items-start gap-3 p-3 text-left rounded-lg border transition-all duration-200
13438
+ ${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"}
13439
+ `
13440
+ },
13441
+ /* @__PURE__ */ import_react27.default.createElement(
13442
+ "div",
13443
+ {
13444
+ className: `
13445
+ mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
13446
+ ${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"}
13447
+ ${anc.type === "quest" ? "text-emerald-400" : anc.type === "version" ? "text-amber-400" : anc.type === "node" ? "text-slate-400" : "text-indigo-400"}
13448
+ `
13449
+ },
13450
+ isPicking ? /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiPlus, { size: 16 }) : anc.type === "quest" ? /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiCheckSquare, { size: 14 }) : anc.type === "version" ? /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiGitBranch, { size: 14 }) : anc.type === "node" ? /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiBox, { size: 14 }) : /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiLayers, { size: 14 })
13451
+ ),
13452
+ /* @__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.searchLabel || "Sem Nome"), /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-[9px] px-1.5 py-0.5 rounded-full bg-white/5 text-slate-500 border border-white/5 uppercase tracking-tighter" }, anc.type)), anc.type === "ancestry" && /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiCornerUpRight, { size: 10 }), /* @__PURE__ */ import_react27.default.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.searchDesc && /* @__PURE__ */ import_react27.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.searchDesc)),
13453
+ !isPicking && /* @__PURE__ */ import_react27.default.createElement(
13454
+ "button",
13455
+ {
13456
+ onClick: (e) => {
13457
+ e.stopPropagation();
13458
+ handleSelectAncestry(anc);
13459
+ },
13460
+ 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",
13461
+ title: "Focar no cen\xE1rio"
13462
+ },
13463
+ /* @__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" }))
13464
+ )
13465
+ );
13466
+ }))
13467
+ ), /* @__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(
13551
13468
  GroupItem,
13552
13469
  {
13553
13470
  key: group.id,
13554
13471
  index,
13555
13472
  group,
13473
+ siblings: groups,
13556
13474
  onUpdate: handleUpdateGroup,
13557
13475
  onDelete: handleDeleteGroup,
13558
13476
  onAddSubgroup: handleAddSubgroup,
13559
13477
  onIndent: handleIndent,
13560
13478
  onOutdent: handleOutdent,
13479
+ onRemoveAncestry: handleRemoveAncestryFromGroup,
13480
+ onRequestPickAncestry: handleRequestPick,
13481
+ pickingGroupId,
13561
13482
  onPlayAncestry: handlePlayFromGroup,
13562
- availableMentionItems,
13483
+ availableIds,
13563
13484
  canEdit
13564
13485
  }
13565
13486
  ))))),
13566
- /* @__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"))
13487
+ /* @__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"))
13567
13488
  )
13568
13489
  );
13569
13490
  }
13570
13491
 
13571
13492
  // src/components/MilestoneManager.jsx
13572
- var import_react31 = __toESM(require("react"));
13573
- var import_fi24 = require("react-icons/fi");
13493
+ var import_react28 = __toESM(require("react"));
13494
+ var import_fi23 = require("react-icons/fi");
13574
13495
  function MilestoneManager({
13575
13496
  isOpen,
13576
13497
  onClose,
@@ -13578,7 +13499,7 @@ function MilestoneManager({
13578
13499
  onUpdateMilestones = () => {
13579
13500
  }
13580
13501
  }) {
13581
- const [newMilestoneName, setNewMilestoneName] = (0, import_react31.useState)("");
13502
+ const [newMilestoneName, setNewMilestoneName] = (0, import_react28.useState)("");
13582
13503
  const handleAddMilestone = () => {
13583
13504
  if (!newMilestoneName.trim()) return;
13584
13505
  const newMilestone = {
@@ -13603,27 +13524,27 @@ function MilestoneManager({
13603
13524
  };
13604
13525
  if (!isOpen) return null;
13605
13526
  const swallow = (e) => e.stopPropagation();
13606
- return /* @__PURE__ */ import_react31.default.createElement(
13527
+ return /* @__PURE__ */ import_react28.default.createElement(
13607
13528
  "div",
13608
13529
  {
13609
13530
  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",
13610
13531
  onClick: onClose
13611
13532
  },
13612
- /* @__PURE__ */ import_react31.default.createElement(
13533
+ /* @__PURE__ */ import_react28.default.createElement(
13613
13534
  "div",
13614
13535
  {
13615
13536
  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",
13616
13537
  onClick: swallow
13617
13538
  },
13618
- /* @__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(
13539
+ /* @__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(
13619
13540
  "button",
13620
13541
  {
13621
13542
  onClick: onClose,
13622
13543
  className: "p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
13623
13544
  },
13624
- /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiX, { size: 20 })
13545
+ /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiX, { size: 20 })
13625
13546
  )),
13626
- /* @__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(
13547
+ /* @__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(
13627
13548
  "input",
13628
13549
  {
13629
13550
  type: "text",
@@ -13633,47 +13554,47 @@ function MilestoneManager({
13633
13554
  placeholder: "Adicionar novo milestone...",
13634
13555
  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"
13635
13556
  }
13636
- ), /* @__PURE__ */ import_react31.default.createElement(
13557
+ ), /* @__PURE__ */ import_react28.default.createElement(
13637
13558
  "button",
13638
13559
  {
13639
13560
  onClick: handleAddMilestone,
13640
13561
  disabled: !newMilestoneName.trim(),
13641
13562
  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"
13642
13563
  },
13643
- /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiPlus, { size: 18 }),
13564
+ /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiPlus, { size: 18 }),
13644
13565
  "Adicionar"
13645
13566
  ))),
13646
- /* @__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(
13567
+ /* @__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(
13647
13568
  "div",
13648
13569
  {
13649
13570
  key: ms.id,
13650
13571
  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]"}`
13651
13572
  },
13652
- /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ import_react31.default.createElement(
13573
+ /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ import_react28.default.createElement(
13653
13574
  "div",
13654
13575
  {
13655
13576
  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"}`
13656
13577
  }
13657
- ), /* @__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"))),
13658
- /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react31.default.createElement(
13578
+ ), /* @__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"))),
13579
+ /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react28.default.createElement(
13659
13580
  "button",
13660
13581
  {
13661
13582
  onClick: () => handleToggleMilestoneStatus(ms.id),
13662
13583
  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"}`,
13663
13584
  title: ms.status === "active" ? "Inativar" : "Ativar"
13664
13585
  },
13665
- ms.status === "active" ? /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiPauseCircle, { size: 18 }) : /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiPlayCircle, { size: 18 })
13666
- ), /* @__PURE__ */ import_react31.default.createElement(
13586
+ ms.status === "active" ? /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiPauseCircle, { size: 18 }) : /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiPlayCircle, { size: 18 })
13587
+ ), /* @__PURE__ */ import_react28.default.createElement(
13667
13588
  "button",
13668
13589
  {
13669
13590
  onClick: () => handleRemoveMilestone(ms.id),
13670
13591
  className: "p-2 rounded-lg hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-all",
13671
13592
  title: "Remover"
13672
13593
  },
13673
- /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiTrash2, { size: 18 })
13594
+ /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiTrash2, { size: 18 })
13674
13595
  ))
13675
- ))) : /* @__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."))),
13676
- /* @__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))))
13596
+ ))) : /* @__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."))),
13597
+ /* @__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))))
13677
13598
  )
13678
13599
  );
13679
13600
  }
@@ -13759,13 +13680,13 @@ function XViewScene({
13759
13680
  check_user_permission,
13760
13681
  get_view_members
13761
13682
  }) {
13762
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
13763
- const { data: session, status } = (0, import_react33.useSession)();
13683
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
13684
+ const { data: session, status } = (0, import_react30.useSession)();
13764
13685
  const router = (0, import_navigation.useRouter)();
13765
13686
  const searchParams = (0, import_navigation.useSearchParams)();
13766
13687
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
13767
13688
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
13768
- const viewParams = (0, import_react32.useMemo)(() => {
13689
+ const viewParams = (0, import_react29.useMemo)(() => {
13769
13690
  if (encryptedConfig) {
13770
13691
  const data = decryptData(encryptedConfig);
13771
13692
  if (data) {
@@ -13774,7 +13695,7 @@ function XViewScene({
13774
13695
  }
13775
13696
  return null;
13776
13697
  }, [encryptedConfig, session]);
13777
- (0, import_react32.useEffect)(() => {
13698
+ (0, import_react29.useEffect)(() => {
13778
13699
  async function verifyPermission() {
13779
13700
  if (!viewParams || !session || !check_user_permission) return;
13780
13701
  const { id, type, owner_id } = viewParams;
@@ -13811,65 +13732,65 @@ function XViewScene({
13811
13732
  setIsLoading(false);
13812
13733
  }
13813
13734
  }, [viewParams, session, status, check_user_permission]);
13814
- const sceneConfigId = (0, import_react32.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13815
- const ownerId = (0, import_react32.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13816
- const dbSaveUrl = (0, import_react32.useMemo)(() => {
13735
+ const sceneConfigId = (0, import_react29.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13736
+ const ownerId = (0, import_react29.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13737
+ const dbSaveUrl = (0, import_react29.useMemo)(() => {
13817
13738
  if (ownerId && sceneConfigId) {
13818
13739
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
13819
13740
  }
13820
13741
  return null;
13821
13742
  }, [ownerId, sceneConfigId]);
13822
- const sceneSaveUrl = (0, import_react32.useMemo)(() => {
13743
+ const sceneSaveUrl = (0, import_react29.useMemo)(() => {
13823
13744
  if (ownerId && sceneConfigId) {
13824
13745
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
13825
13746
  }
13826
13747
  return null;
13827
13748
  }, [ownerId, sceneConfigId]);
13828
- const ancestry_save_url = (0, import_react32.useMemo)(() => {
13749
+ const ancestry_save_url = (0, import_react29.useMemo)(() => {
13829
13750
  if (ownerId && sceneConfigId) {
13830
13751
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
13831
13752
  }
13832
13753
  return null;
13833
13754
  }, [ownerId, sceneConfigId]);
13834
- const sceneDataRef = (0, import_react32.useRef)(null);
13835
- const parentDataRef = (0, import_react32.useRef)(null);
13836
- const ancestryDataRef = (0, import_react32.useRef)(null);
13837
- const [isLoading, setIsLoading] = (0, import_react32.useState)(true);
13838
- const [permissionStatus, setPermissionStatus] = (0, import_react32.useState)("loading");
13839
- const [userPermissionRole, setUserPermissionRole] = (0, import_react32.useState)(null);
13840
- const [viewMembers, setViewMembers] = (0, import_react32.useState)([]);
13841
- const [isInitialized, setIsInitialized] = (0, import_react32.useState)(false);
13842
- const [sceneVersion, setSceneVersion] = (0, import_react32.useState)(0);
13843
- const [contextMenu, setContextMenu] = (0, import_react32.useState)({
13755
+ const sceneDataRef = (0, import_react29.useRef)(null);
13756
+ const parentDataRef = (0, import_react29.useRef)(null);
13757
+ const ancestryDataRef = (0, import_react29.useRef)(null);
13758
+ const [isLoading, setIsLoading] = (0, import_react29.useState)(true);
13759
+ const [permissionStatus, setPermissionStatus] = (0, import_react29.useState)("loading");
13760
+ const [userPermissionRole, setUserPermissionRole] = (0, import_react29.useState)(null);
13761
+ const [viewMembers, setViewMembers] = (0, import_react29.useState)([]);
13762
+ const [isInitialized, setIsInitialized] = (0, import_react29.useState)(false);
13763
+ const [sceneVersion, setSceneVersion] = (0, import_react29.useState)(0);
13764
+ const [contextMenu, setContextMenu] = (0, import_react29.useState)({
13844
13765
  visible: false,
13845
13766
  x: 0,
13846
13767
  y: 0,
13847
13768
  nodeData: null
13848
13769
  });
13849
- const [multiContextMenu, setMultiContextMenu] = (0, import_react32.useState)({
13770
+ const [multiContextMenu, setMultiContextMenu] = (0, import_react29.useState)({
13850
13771
  visible: false,
13851
13772
  x: 0,
13852
13773
  y: 0,
13853
13774
  nodeIds: null
13854
13775
  });
13855
- const [relationshipMenu, setRelationshipMenu] = (0, import_react32.useState)({
13776
+ const [relationshipMenu, setRelationshipMenu] = (0, import_react29.useState)({
13856
13777
  visible: false,
13857
13778
  x: 0,
13858
13779
  y: 0,
13859
13780
  linkObject: null
13860
13781
  });
13861
- const [creationMode, setCreationMode] = (0, import_react32.useState)({
13782
+ const [creationMode, setCreationMode] = (0, import_react29.useState)({
13862
13783
  isActive: false,
13863
13784
  sourceNodeData: null
13864
13785
  });
13865
- const [versionMode, setVersionMode] = (0, import_react32.useState)({
13786
+ const [versionMode, setVersionMode] = (0, import_react29.useState)({
13866
13787
  isActive: false,
13867
13788
  sourceNodeData: null
13868
13789
  });
13869
- const [questMode, setQuestMode] = (0, import_react32.useState)({ isActive: false });
13870
- const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react32.useState)(false);
13871
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react32.useState)(false);
13872
- const [ancestryMode, setAncestryMode] = (0, import_react32.useState)({
13790
+ const [questMode, setQuestMode] = (0, import_react29.useState)({ isActive: false });
13791
+ const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react29.useState)(false);
13792
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react29.useState)(false);
13793
+ const [ancestryMode, setAncestryMode] = (0, import_react29.useState)({
13873
13794
  isActive: false,
13874
13795
  tree: null,
13875
13796
  selectedParentId: null,
@@ -13880,42 +13801,42 @@ function XViewScene({
13880
13801
  ancestryDescriptionSections: [],
13881
13802
  isAddingNodes: false
13882
13803
  });
13883
- const [readingMode, setReadingMode] = (0, import_react32.useState)({
13804
+ const [readingMode, setReadingMode] = (0, import_react29.useState)({
13884
13805
  isActive: false,
13885
13806
  ancestry: null,
13886
13807
  branchStack: [],
13887
13808
  autoAbstraction: false
13888
13809
  });
13889
- const [formPosition, setFormPosition] = (0, import_react32.useState)({
13810
+ const [formPosition, setFormPosition] = (0, import_react29.useState)({
13890
13811
  left: 16,
13891
13812
  top: 16,
13892
13813
  opacity: 0
13893
13814
  });
13894
- const [detailsNode, setDetailsNode] = (0, import_react32.useState)(null);
13895
- const [detailsLink, setDetailsLink] = (0, import_react32.useState)(null);
13896
- const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react32.useState)(null);
13897
- const [imageViewer, setImageViewer] = (0, import_react32.useState)({
13815
+ const [detailsNode, setDetailsNode] = (0, import_react29.useState)(null);
13816
+ const [detailsLink, setDetailsLink] = (0, import_react29.useState)(null);
13817
+ const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react29.useState)(null);
13818
+ const [imageViewer, setImageViewer] = (0, import_react29.useState)({
13898
13819
  visible: false,
13899
13820
  images: [],
13900
13821
  startIndex: 0
13901
13822
  });
13902
- const [editingAncestryRel, setEditingAncestryRel] = (0, import_react32.useState)({
13823
+ const [editingAncestryRel, setEditingAncestryRel] = (0, import_react29.useState)({
13903
13824
  visible: false,
13904
13825
  data: null,
13905
13826
  path: null
13906
13827
  });
13907
- const [isImportModalOpen, setIsImportModalOpen] = (0, import_react32.useState)(false);
13908
- const [importSuccessMessage, setImportSuccessMessage] = (0, import_react32.useState)("");
13909
- const [invalidTargetError, setInvalidTargetError] = (0, import_react32.useState)(null);
13910
- const [highlightedNodeId, setHighlightedNodeId] = (0, import_react32.useState)(null);
13911
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react32.useState)(false);
13912
- const [ancestryBoardData, setAncestryBoardData] = (0, import_react32.useState)([]);
13913
- const [isSidebarOpen, setIsSidebarOpen] = (0, import_react32.useState)(false);
13914
- const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = (0, import_react32.useState)(false);
13915
- const mountRef = (0, import_react32.useRef)(null);
13916
- const tooltipRef = (0, import_react32.useRef)(null);
13917
- const formRef = (0, import_react32.useRef)(null);
13918
- const stateRef = (0, import_react32.useRef)({
13828
+ const [isImportModalOpen, setIsImportModalOpen] = (0, import_react29.useState)(false);
13829
+ const [importSuccessMessage, setImportSuccessMessage] = (0, import_react29.useState)("");
13830
+ const [invalidTargetError, setInvalidTargetError] = (0, import_react29.useState)(null);
13831
+ const [highlightedNodeId, setHighlightedNodeId] = (0, import_react29.useState)(null);
13832
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react29.useState)(false);
13833
+ const [ancestryBoardData, setAncestryBoardData] = (0, import_react29.useState)([]);
13834
+ const [isSidebarOpen, setIsSidebarOpen] = (0, import_react29.useState)(false);
13835
+ const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = (0, import_react29.useState)(false);
13836
+ const mountRef = (0, import_react29.useRef)(null);
13837
+ const tooltipRef = (0, import_react29.useRef)(null);
13838
+ const formRef = (0, import_react29.useRef)(null);
13839
+ const stateRef = (0, import_react29.useRef)({
13919
13840
  readMode: {
13920
13841
  currentMaxIndex: 0,
13921
13842
  progressMap: {}
@@ -13979,10 +13900,10 @@ function XViewScene({
13979
13900
  minWidth: 320,
13980
13901
  maxWidth: maxReadPanelW
13981
13902
  });
13982
- (0, import_react32.useEffect)(() => {
13903
+ (0, import_react29.useEffect)(() => {
13983
13904
  stateRef.current.ancestry = ancestryMode;
13984
13905
  }, [ancestryMode]);
13985
- (0, import_react32.useEffect)(() => {
13906
+ (0, import_react29.useEffect)(() => {
13986
13907
  var _a2;
13987
13908
  if (!isInitialized) return;
13988
13909
  const map = /* @__PURE__ */ new Map();
@@ -14005,10 +13926,10 @@ function XViewScene({
14005
13926
  }
14006
13927
  stateRef.current.nodeIdToParentFileMap = map;
14007
13928
  }, [isInitialized, sceneVersion]);
14008
- const handleNavigateBack = (0, import_react32.useCallback)(() => {
13929
+ const handleNavigateBack = (0, import_react29.useCallback)(() => {
14009
13930
  router.push("/dashboard/scenes");
14010
13931
  }, [router]);
14011
- const handleConfirmImport = (0, import_react32.useCallback)(
13932
+ const handleConfirmImport = (0, import_react29.useCallback)(
14012
13933
  async (importPayload) => {
14013
13934
  var _a2, _b2;
14014
13935
  let files = [];
@@ -14136,7 +14057,7 @@ function XViewScene({
14136
14057
  const handleOpenImageViewer = (images, startIndex) => {
14137
14058
  setImageViewer({ visible: true, images, startIndex });
14138
14059
  };
14139
- const tweenToTarget = (0, import_react32.useCallback)(
14060
+ const tweenToTarget = (0, import_react29.useCallback)(
14140
14061
  (target, zoomFactor = 1, forcedDirection = null) => {
14141
14062
  const { camera, controls, tweenGroup } = stateRef.current;
14142
14063
  if (!camera || !controls || !tweenGroup) return;
@@ -14162,7 +14083,7 @@ function XViewScene({
14162
14083
  if (!t || typeof t.closest !== "function") return false;
14163
14084
  return !!t.closest(".ui-overlay");
14164
14085
  };
14165
- const buildFullAncestryTree = (0, import_react32.useCallback)(
14086
+ const buildFullAncestryTree = (0, import_react29.useCallback)(
14166
14087
  (idTree, nodes, ancestries = []) => {
14167
14088
  if (!idTree) return null;
14168
14089
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
@@ -14247,7 +14168,7 @@ function XViewScene({
14247
14168
  },
14248
14169
  []
14249
14170
  );
14250
- const handleActivateTimeline = (0, import_react32.useCallback)(() => {
14171
+ const handleActivateTimeline = (0, import_react29.useCallback)(() => {
14251
14172
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
14252
14173
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
14253
14174
  while (timelineIntervalsGroup.children.length > 0) {
@@ -14407,7 +14328,7 @@ function XViewScene({
14407
14328
  }
14408
14329
  });
14409
14330
  }, []);
14410
- const handleVersionTimeline = (0, import_react32.useCallback)((sourceMesh, versionMeshes) => {
14331
+ const handleVersionTimeline = (0, import_react29.useCallback)((sourceMesh, versionMeshes) => {
14411
14332
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
14412
14333
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
14413
14334
  return;
@@ -14544,7 +14465,7 @@ function XViewScene({
14544
14465
  }
14545
14466
  });
14546
14467
  }, []);
14547
- (0, import_react32.useEffect)(() => {
14468
+ (0, import_react29.useEffect)(() => {
14548
14469
  async function fetchAllData(configPath, ownerId2) {
14549
14470
  var _a2, _b2;
14550
14471
  if (!get_scene_view_data) {
@@ -14649,12 +14570,12 @@ function XViewScene({
14649
14570
  focusNodeId,
14650
14571
  focusAncestryId
14651
14572
  ]);
14652
- const isNodeInView = (0, import_react32.useCallback)((id) => {
14573
+ const isNodeInView = (0, import_react29.useCallback)((id) => {
14653
14574
  const key = String(id);
14654
14575
  const objs = stateRef.current.nodeObjects || {};
14655
14576
  return !!objs[key];
14656
14577
  }, []);
14657
- const addOrUpdateNodeMesh = (0, import_react32.useCallback)(
14578
+ const addOrUpdateNodeMesh = (0, import_react29.useCallback)(
14658
14579
  (nodeData, position, suppressVersionUpdate = false, forceShowQuestDate = false) => {
14659
14580
  const {
14660
14581
  graphGroup,
@@ -14695,7 +14616,7 @@ function XViewScene({
14695
14616
  },
14696
14617
  []
14697
14618
  );
14698
- const handleActivateQuestLens = (0, import_react32.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
14619
+ const handleActivateQuestLens = (0, import_react29.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
14699
14620
  var _a2;
14700
14621
  const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
14701
14622
  if (!nodeObjects || !tweenGroup || !graphGroup) return;
@@ -14909,7 +14830,7 @@ function XViewScene({
14909
14830
  camTween.start();
14910
14831
  }
14911
14832
  }, [addOrUpdateNodeMesh]);
14912
- (0, import_react32.useEffect)(() => {
14833
+ (0, import_react29.useEffect)(() => {
14913
14834
  if (!isInitialized || !sceneDataRef.current) return;
14914
14835
  const currentMount = mountRef.current;
14915
14836
  if (!currentMount) return;
@@ -15665,7 +15586,7 @@ function XViewScene({
15665
15586
  get_scene_view_data,
15666
15587
  save_view_data
15667
15588
  ]);
15668
- const handleGhostNodeImageChange = (0, import_react32.useCallback)((useImage, imageUrl) => {
15589
+ const handleGhostNodeImageChange = (0, import_react29.useCallback)((useImage, imageUrl) => {
15669
15590
  const {
15670
15591
  node: ghostNode,
15671
15592
  line: ghostLine,
@@ -15713,7 +15634,7 @@ function XViewScene({
15713
15634
  aura: newGhostNode.getObjectByName("aura")
15714
15635
  };
15715
15636
  }, []);
15716
- const handleGhostNodeIntensityChange = (0, import_react32.useCallback)((newIntensity) => {
15637
+ const handleGhostNodeIntensityChange = (0, import_react29.useCallback)((newIntensity) => {
15717
15638
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
15718
15639
  if (!ghostNode) return;
15719
15640
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -15734,7 +15655,7 @@ function XViewScene({
15734
15655
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
15735
15656
  }
15736
15657
  }, []);
15737
- const handleDetailNodeIntensityChange = (0, import_react32.useCallback)(
15658
+ const handleDetailNodeIntensityChange = (0, import_react29.useCallback)(
15738
15659
  (nodeId, newIntensity) => {
15739
15660
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
15740
15661
  if (!mesh) return;
@@ -15890,7 +15811,7 @@ function XViewScene({
15890
15811
  mountRef.current.style.cursor = "default";
15891
15812
  }
15892
15813
  };
15893
- const handleAncestryTreeUpdate = (0, import_react32.useCallback)((newTree, extraData = null) => {
15814
+ const handleAncestryTreeUpdate = (0, import_react29.useCallback)((newTree, extraData = null) => {
15894
15815
  setAncestryMode((prev) => {
15895
15816
  const prevTreeStr = JSON.stringify(prev.tree);
15896
15817
  const newTreeStr = JSON.stringify(newTree);
@@ -15913,7 +15834,7 @@ function XViewScene({
15913
15834
  };
15914
15835
  });
15915
15836
  }, []);
15916
- const actionHandlerContext = (0, import_react32.useMemo)(
15837
+ const actionHandlerContext = (0, import_react29.useMemo)(
15917
15838
  () => {
15918
15839
  var _a2;
15919
15840
  return {
@@ -15974,7 +15895,7 @@ function XViewScene({
15974
15895
  const handleStartVersioning = (nodeData) => {
15975
15896
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
15976
15897
  };
15977
- const handleStartQuestQuick = (0, import_react32.useCallback)((questNode) => {
15898
+ const handleStartQuestQuick = (0, import_react29.useCallback)((questNode) => {
15978
15899
  var _a2, _b2, _c2;
15979
15900
  if (!questNode || !actionHandlerContext) return;
15980
15901
  const allParentNodes = Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
@@ -16009,7 +15930,7 @@ function XViewScene({
16009
15930
  }
16010
15931
  setDetailsNode(updatedNode);
16011
15932
  }, [session, actionHandlerContext]);
16012
- const handleFinishQuestQuick = (0, import_react32.useCallback)((questNode) => {
15933
+ const handleFinishQuestQuick = (0, import_react29.useCallback)((questNode) => {
16013
15934
  var _a2, _b2, _c2, _d2;
16014
15935
  if (!questNode || !actionHandlerContext) return;
16015
15936
  const {
@@ -16083,7 +16004,7 @@ function XViewScene({
16083
16004
  setDetailsNode(null);
16084
16005
  }
16085
16006
  }, [session, actionHandlerContext, viewMembers, detailsNode]);
16086
- const handleCancelQuest = (0, import_react32.useCallback)(() => {
16007
+ const handleCancelQuest = (0, import_react29.useCallback)(() => {
16087
16008
  const { graphGroup, ghostElements } = stateRef.current;
16088
16009
  if (ghostElements.node && graphGroup) {
16089
16010
  if (ghostElements.node.userData.labelObject) {
@@ -16142,13 +16063,15 @@ function XViewScene({
16142
16063
  try {
16143
16064
  await actions.save_view_data(sceneSaveUrl2, sceneFileData);
16144
16065
  sceneDataRef2.current.quest_counter = currentCounter + 1;
16145
- sceneDataRef2.current.quest_nodes = sceneFileData.quest_nodes;
16146
- sceneDataRef2.current.quest_links = sceneFileData.quest_links;
16147
16066
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
16148
16067
  parentFileId: sceneConfigId2,
16149
16068
  ownerId: ownerId2,
16150
16069
  datasetName: "Quests Internas (View)"
16151
16070
  });
16071
+ sceneDataRef2.current.quest_nodes = [...graphDataRef.current[sceneConfigId2].nodes];
16072
+ if (parentDataRef.current[sceneConfigId2]) {
16073
+ parentDataRef.current[sceneConfigId2].nodes = [...graphDataRef.current[sceneConfigId2].nodes];
16074
+ }
16152
16075
  const finalPosition = stateRef2.current.ghostElements.node ? stateRef2.current.ghostElements.node.position.clone() : stateRef2.current.controls.target.clone();
16153
16076
  const { graphGroup, ghostElements } = stateRef2.current;
16154
16077
  if (ghostElements.node && graphGroup) {
@@ -16238,7 +16161,7 @@ function XViewScene({
16238
16161
  }
16239
16162
  userActionHandlers.handleCancelConnection(context);
16240
16163
  };
16241
- const handleClearAncestryVisuals = (0, import_react32.useCallback)((ancestryId) => {
16164
+ const handleClearAncestryVisuals = (0, import_react29.useCallback)((ancestryId) => {
16242
16165
  const { renderedAncestries, ancestryGroup } = stateRef.current;
16243
16166
  const renderIndex = renderedAncestries.findIndex(
16244
16167
  (a) => String(a.id) === String(ancestryId)
@@ -16256,7 +16179,7 @@ function XViewScene({
16256
16179
  );
16257
16180
  }
16258
16181
  }, []);
16259
- const handleRenderAncestry = (0, import_react32.useCallback)(
16182
+ const handleRenderAncestry = (0, import_react29.useCallback)(
16260
16183
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
16261
16184
  setContextMenu(
16262
16185
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16750,7 +16673,7 @@ function XViewScene({
16750
16673
  ancestryMode.isActive
16751
16674
  ]
16752
16675
  );
16753
- const handleRenderAbstractionTree = (0, import_react32.useCallback)(
16676
+ const handleRenderAbstractionTree = (0, import_react29.useCallback)(
16754
16677
  (ancestryObject, targetNodeId = null) => {
16755
16678
  setContextMenu(
16756
16679
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16838,7 +16761,7 @@ function XViewScene({
16838
16761
  handleClearAncestryVisuals
16839
16762
  ]
16840
16763
  );
16841
- const handleReadModeBranchNav = (0, import_react32.useCallback)(
16764
+ const handleReadModeBranchNav = (0, import_react29.useCallback)(
16842
16765
  (nodeId, action, direction = "right") => {
16843
16766
  const { ancestry, branchStack } = readingMode;
16844
16767
  if (!ancestry || !ancestry.tree) return;
@@ -17016,13 +16939,13 @@ function XViewScene({
17016
16939
  },
17017
16940
  [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
17018
16941
  );
17019
- const handleReadModeHighlight = (0, import_react32.useCallback)((nodeId) => {
16942
+ const handleReadModeHighlight = (0, import_react29.useCallback)((nodeId) => {
17020
16943
  if (stateRef.current.highlightedNodeId !== nodeId) {
17021
16944
  stateRef.current.highlightedNodeId = nodeId;
17022
16945
  }
17023
16946
  setHighlightedNodeId(nodeId);
17024
16947
  }, []);
17025
- const activeNodeBranches = (0, import_react32.useMemo)(() => {
16948
+ const activeNodeBranches = (0, import_react29.useMemo)(() => {
17026
16949
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
17027
16950
  return null;
17028
16951
  const fullTree = buildFullAncestryTree(
@@ -17066,7 +16989,7 @@ function XViewScene({
17066
16989
  readingMode.branchStack,
17067
16990
  ancestryDataRef.current
17068
16991
  ]);
17069
- const backNavigationInfo = (0, import_react32.useMemo)(() => {
16992
+ const backNavigationInfo = (0, import_react29.useMemo)(() => {
17070
16993
  const { branchStack } = readingMode;
17071
16994
  if (!branchStack || branchStack.length === 0) return null;
17072
16995
  const lastStep = branchStack[branchStack.length - 1];
@@ -17077,7 +17000,7 @@ function XViewScene({
17077
17000
  name: "Voltar para anterior"
17078
17001
  };
17079
17002
  }, [readingMode.branchStack]);
17080
- const getReadModeDisplayContext = (0, import_react32.useMemo)(() => {
17003
+ const getReadModeDisplayContext = (0, import_react29.useMemo)(() => {
17081
17004
  const { ancestry, branchStack } = readingMode;
17082
17005
  if (!ancestry) return null;
17083
17006
  if (branchStack.length === 0) {
@@ -17120,7 +17043,7 @@ function XViewScene({
17120
17043
  customProperties: branchProps
17121
17044
  };
17122
17045
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
17123
- const readModeAbstractionTree = (0, import_react32.useMemo)(() => {
17046
+ const readModeAbstractionTree = (0, import_react29.useMemo)(() => {
17124
17047
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
17125
17048
  return null;
17126
17049
  }
@@ -17139,7 +17062,7 @@ function XViewScene({
17139
17062
  buildFullAncestryTree,
17140
17063
  sceneVersion
17141
17064
  ]);
17142
- const handleStartReadingAncestry = (0, import_react32.useCallback)(
17065
+ const handleStartReadingAncestry = (0, import_react29.useCallback)(
17143
17066
  async (ancestryObject, renderMode = "full") => {
17144
17067
  setContextMenu(
17145
17068
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17182,7 +17105,7 @@ function XViewScene({
17182
17105
  },
17183
17106
  [handleRenderAncestry, handleRenderAbstractionTree]
17184
17107
  );
17185
- const handleReadModeSectionChange = (0, import_react32.useCallback)(
17108
+ const handleReadModeSectionChange = (0, import_react29.useCallback)(
17186
17109
  (activeSectionId) => {
17187
17110
  const { ancestry, branchStack } = readingMode;
17188
17111
  if (!ancestry || !readingMode.isActive) return;
@@ -17267,10 +17190,10 @@ function XViewScene({
17267
17190
  ancestryDataRef.current
17268
17191
  ]
17269
17192
  );
17270
- const handleCloseReadMode = (0, import_react32.useCallback)(() => {
17193
+ const handleCloseReadMode = (0, import_react29.useCallback)(() => {
17271
17194
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
17272
17195
  }, []);
17273
- const handleAncestrySectionChange = (0, import_react32.useCallback)(
17196
+ const handleAncestrySectionChange = (0, import_react29.useCallback)(
17274
17197
  (activeSectionId, ancestryOverride = null, rotation = 0) => {
17275
17198
  var _a2, _b2;
17276
17199
  const currentMode = stateRef.current.ancestry;
@@ -17332,7 +17255,7 @@ function XViewScene({
17332
17255
  },
17333
17256
  [handleRenderAncestry]
17334
17257
  );
17335
- const handleEditAncestry = (0, import_react32.useCallback)(
17258
+ const handleEditAncestry = (0, import_react29.useCallback)(
17336
17259
  async (ancestryObject) => {
17337
17260
  setContextMenu(
17338
17261
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17387,7 +17310,7 @@ function XViewScene({
17387
17310
  const handleSelectAncestryParent = (nodeId) => {
17388
17311
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
17389
17312
  };
17390
- const handleRemoveFromAncestry = (0, import_react32.useCallback)((pathToRemove) => {
17313
+ const handleRemoveFromAncestry = (0, import_react29.useCallback)((pathToRemove) => {
17391
17314
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
17392
17315
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
17393
17316
  return;
@@ -17412,7 +17335,7 @@ function XViewScene({
17412
17335
  return { ...prev, tree: newTree };
17413
17336
  });
17414
17337
  }, []);
17415
- const handleSaveAncestry = (0, import_react32.useCallback)(
17338
+ const handleSaveAncestry = (0, import_react29.useCallback)(
17416
17339
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
17417
17340
  const treeToUse = treeOverride || ancestryMode.tree;
17418
17341
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -17648,7 +17571,7 @@ function XViewScene({
17648
17571
  });
17649
17572
  setEditingAncestryRel({ visible: false, data: null, path: null });
17650
17573
  };
17651
- const handleDeleteAncestry = (0, import_react32.useCallback)(
17574
+ const handleDeleteAncestry = (0, import_react29.useCallback)(
17652
17575
  async (ancestryIdToDelete) => {
17653
17576
  if (!ancestryIdToDelete) {
17654
17577
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -17730,28 +17653,22 @@ function XViewScene({
17730
17653
  },
17731
17654
  [save_view_data, delete_file_action]
17732
17655
  );
17733
- const handleOpenAncestryBoard = (0, import_react32.useCallback)(() => {
17656
+ const handleOpenAncestryBoard = (0, import_react29.useCallback)(() => {
17734
17657
  setIsAncestryBoardOpen(true);
17735
17658
  }, []);
17736
- const handleSelectAncestryFromBoard = (0, import_react32.useCallback)(
17659
+ const handleSelectAncestryFromBoard = (0, import_react29.useCallback)(
17737
17660
  (item) => {
17738
17661
  setIsAncestryBoardOpen(false);
17739
17662
  setIsSidebarOpen(false);
17740
- if (item.type === "ancestry" || !item.type) {
17663
+ if (item.type === "ancestry") {
17741
17664
  handleStartReadingAncestry(item);
17742
17665
  } else {
17743
- const nodeId = String(item.id);
17744
- const sceneMesh = stateRef.current.nodeObjects[nodeId];
17745
- if (sceneMesh) {
17746
- tweenToTarget(sceneMesh);
17747
- } else {
17748
- console.warn("Objeto n\xE3o encontrado na cena para foco:", nodeId);
17749
- }
17666
+ handleOpenReference({ type: "node", id: item.id });
17750
17667
  }
17751
17668
  },
17752
- [handleStartReadingAncestry, tweenToTarget]
17669
+ [handleStartReadingAncestry, handleOpenReference]
17753
17670
  );
17754
- const handleSaveAncestryBoard = (0, import_react32.useCallback)(
17671
+ const handleSaveAncestryBoard = (0, import_react29.useCallback)(
17755
17672
  async (groups) => {
17756
17673
  if (!sceneConfigId || !viewParams || !session) return;
17757
17674
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
@@ -17765,7 +17682,7 @@ function XViewScene({
17765
17682
  },
17766
17683
  [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
17767
17684
  );
17768
- const existingNodeTypes = (0, import_react32.useMemo)(() => {
17685
+ const existingNodeTypes = (0, import_react29.useMemo)(() => {
17769
17686
  if (!parentDataRef.current) {
17770
17687
  return [];
17771
17688
  }
@@ -17777,28 +17694,22 @@ function XViewScene({
17777
17694
  ).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
17778
17695
  return [...new Set(allTypes)];
17779
17696
  }, [parentDataRef.current, sceneVersion]);
17780
- const searchableDbNodes = (0, import_react32.useMemo)(() => {
17781
- var _a2;
17697
+ const searchableDbNodes = (0, import_react29.useMemo)(() => {
17782
17698
  if (!parentDataRef.current) {
17783
17699
  return [];
17784
17700
  }
17785
- const datasetsPool = Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17701
+ return Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17786
17702
  const datasetName = fileData.dataset_name || `Dataset #${dbId.substring(0, 6)}`;
17787
17703
  return (fileData.nodes || []).map((node) => ({
17788
17704
  ...node,
17789
17705
  dataset_name: datasetName
17790
17706
  }));
17707
+ }).filter((node) => {
17708
+ var _a2;
17709
+ return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
17791
17710
  });
17792
- const questsPool = (((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || []).map((node) => ({
17793
- ...node,
17794
- dataset_name: "Quests Internas (View)"
17795
- }));
17796
- return [...datasetsPool, ...questsPool].filter((node) => {
17797
- var _a3;
17798
- return !((_a3 = node.version_node) == null ? void 0 : _a3.is_version);
17799
- });
17800
- }, [parentDataRef.current, (_b = sceneDataRef.current) == null ? void 0 : _b.quest_nodes, sceneVersion]);
17801
- const handleAddExistingNode = (0, import_react32.useCallback)(
17711
+ }, [parentDataRef.current, sceneVersion]);
17712
+ const handleAddExistingNode = (0, import_react29.useCallback)(
17802
17713
  (nodeId) => {
17803
17714
  return userActionHandlers.handleAddExistingNodeById(
17804
17715
  actionHandlerContext,
@@ -17807,7 +17718,7 @@ function XViewScene({
17807
17718
  },
17808
17719
  [actionHandlerContext]
17809
17720
  );
17810
- const handleUpdateMilestones = (0, import_react32.useCallback)(
17721
+ const handleUpdateMilestones = (0, import_react29.useCallback)(
17811
17722
  async (newMilestones) => {
17812
17723
  var _a2, _b2, _c2;
17813
17724
  if (!sceneDataRef.current) return;
@@ -17853,7 +17764,7 @@ function XViewScene({
17853
17764
  viewParams == null ? void 0 : viewParams.type
17854
17765
  ]
17855
17766
  );
17856
- const handleSaveCurrentView = (0, import_react32.useCallback)(async () => {
17767
+ const handleSaveCurrentView = (0, import_react29.useCallback)(async () => {
17857
17768
  var _a2, _b2, _c2;
17858
17769
  const { nodeObjects, allLinks } = stateRef.current;
17859
17770
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
@@ -17896,16 +17807,16 @@ function XViewScene({
17896
17807
  console.error("Erro na chamada de save_view_data:", error);
17897
17808
  }
17898
17809
  }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
17899
- const allAvailableNodes = (0, import_react32.useMemo)(() => {
17810
+ const allAvailableNodes = (0, import_react29.useMemo)(() => {
17900
17811
  if (!parentDataRef.current) return [];
17901
17812
  return Object.values(parentDataRef.current).flatMap(
17902
17813
  (fileData) => fileData.nodes || []
17903
17814
  );
17904
17815
  }, [sceneVersion, isInitialized]);
17905
- const allAvailableAncestries = (0, import_react32.useMemo)(() => {
17816
+ const allAvailableAncestries = (0, import_react29.useMemo)(() => {
17906
17817
  return ancestryDataRef.current || [];
17907
17818
  }, [sceneVersion, isInitialized]);
17908
- const handleOpenReference = (0, import_react32.useCallback)(
17819
+ const handleOpenReference = (0, import_react29.useCallback)(
17909
17820
  (referenceData) => {
17910
17821
  const { type, id } = referenceData;
17911
17822
  if (type === "node") {
@@ -17944,13 +17855,13 @@ function XViewScene({
17944
17855
  tweenToTarget
17945
17856
  ]
17946
17857
  );
17947
- const handleToggleAncestryAddMode = (0, import_react32.useCallback)(() => {
17858
+ const handleToggleAncestryAddMode = (0, import_react29.useCallback)(() => {
17948
17859
  setAncestryMode((prev) => ({
17949
17860
  ...prev,
17950
17861
  isAddingNodes: !prev.isAddingNodes
17951
17862
  }));
17952
17863
  }, []);
17953
- const handleFocusNode = (0, import_react32.useCallback)(
17864
+ const handleFocusNode = (0, import_react29.useCallback)(
17954
17865
  (nodeData) => {
17955
17866
  var _a2;
17956
17867
  if (!nodeData) return;
@@ -17966,7 +17877,7 @@ function XViewScene({
17966
17877
  },
17967
17878
  [tweenToTarget]
17968
17879
  );
17969
- const availableDatasets = (0, import_react32.useMemo)(() => {
17880
+ const availableDatasets = (0, import_react29.useMemo)(() => {
17970
17881
  if (!sceneDataRef.current || !parentDataRef.current) return [];
17971
17882
  return sceneDataRef.current.parent_dbs.map((db) => {
17972
17883
  var _a2;
@@ -17976,11 +17887,11 @@ function XViewScene({
17976
17887
  };
17977
17888
  });
17978
17889
  }, [sceneVersion, isInitialized]);
17979
- const sourceNodeDatasetId = creationMode.sourceNodeData ? (_c = stateRef.current.nodeIdToParentFileMap.get(
17890
+ const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(
17980
17891
  String(creationMode.sourceNodeData.id)
17981
- )) == null ? void 0 : _c.parentFileId : null;
17892
+ )) == null ? void 0 : _b.parentFileId : null;
17982
17893
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
17983
- (0, import_react32.useEffect)(() => {
17894
+ (0, import_react29.useEffect)(() => {
17984
17895
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
17985
17896
  const nodeObjects = stateRef.current.nodeObjects || {};
17986
17897
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -18003,7 +17914,7 @@ function XViewScene({
18003
17914
  hasFocusedInitial,
18004
17915
  tweenToTarget
18005
17916
  ]);
18006
- (0, import_react32.useEffect)(() => {
17917
+ (0, import_react29.useEffect)(() => {
18007
17918
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
18008
17919
  const ancestries = ancestryDataRef.current || [];
18009
17920
  const targetAncestry = ancestries.find(
@@ -18028,7 +17939,7 @@ function XViewScene({
18028
17939
  hasOpenedInitialAncestry,
18029
17940
  handleStartReadingAncestry
18030
17941
  ]);
18031
- (0, import_react32.useEffect)(() => {
17942
+ (0, import_react29.useEffect)(() => {
18032
17943
  function handleKeyDown(event) {
18033
17944
  var _a2, _b2, _c2;
18034
17945
  const context = actionHandlerContext;
@@ -18151,10 +18062,10 @@ function XViewScene({
18151
18062
  // <-- handleCancelQuest adicionado aqui
18152
18063
  ]);
18153
18064
  if (isLoading || status === "loading" || permissionStatus === "loading") {
18154
- return /* @__PURE__ */ import_react32.default.createElement(LoadingScreen, null);
18065
+ return /* @__PURE__ */ import_react29.default.createElement(LoadingScreen, null);
18155
18066
  }
18156
18067
  if (permissionStatus === "denied") {
18157
- 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(
18068
+ 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(
18158
18069
  "svg",
18159
18070
  {
18160
18071
  xmlns: "http://www.w3.org/2000/svg",
@@ -18164,7 +18075,7 @@ function XViewScene({
18164
18075
  stroke: "currentColor",
18165
18076
  className: "w-16 h-16 mx-auto"
18166
18077
  },
18167
- /* @__PURE__ */ import_react32.default.createElement(
18078
+ /* @__PURE__ */ import_react29.default.createElement(
18168
18079
  "path",
18169
18080
  {
18170
18081
  strokeLinecap: "round",
@@ -18172,13 +18083,13 @@ function XViewScene({
18172
18083
  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"
18173
18084
  }
18174
18085
  )
18175
- )), /* @__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(
18086
+ )), /* @__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(
18176
18087
  "button",
18177
18088
  {
18178
18089
  onClick: () => router.push("/dashboard/scenes"),
18179
18090
  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"
18180
18091
  },
18181
- /* @__PURE__ */ import_react32.default.createElement(
18092
+ /* @__PURE__ */ import_react29.default.createElement(
18182
18093
  "svg",
18183
18094
  {
18184
18095
  xmlns: "http://www.w3.org/2000/svg",
@@ -18188,7 +18099,7 @@ function XViewScene({
18188
18099
  stroke: "currentColor",
18189
18100
  className: "w-5 h-5"
18190
18101
  },
18191
- /* @__PURE__ */ import_react32.default.createElement(
18102
+ /* @__PURE__ */ import_react29.default.createElement(
18192
18103
  "path",
18193
18104
  {
18194
18105
  strokeLinecap: "round",
@@ -18200,7 +18111,7 @@ function XViewScene({
18200
18111
  "Voltar para Scenes"
18201
18112
  )));
18202
18113
  }
18203
- return /* @__PURE__ */ import_react32.default.createElement(
18114
+ return /* @__PURE__ */ import_react29.default.createElement(
18204
18115
  "div",
18205
18116
  {
18206
18117
  ref: mountRef,
@@ -18212,7 +18123,7 @@ function XViewScene({
18212
18123
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
18213
18124
  }
18214
18125
  },
18215
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react32.default.createElement(
18126
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react29.default.createElement(
18216
18127
  XViewSidebar,
18217
18128
  {
18218
18129
  dbNodes: searchableDbNodes,
@@ -18232,11 +18143,11 @@ function XViewScene({
18232
18143
  onToggle: setIsSidebarOpen,
18233
18144
  userRole: userPermissionRole,
18234
18145
  viewMembers,
18235
- milestones: ((_d = sceneDataRef.current) == null ? void 0 : _d.milestones) || [],
18146
+ milestones: ((_c = sceneDataRef.current) == null ? void 0 : _c.milestones) || [],
18236
18147
  onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
18237
18148
  }
18238
18149
  ),
18239
- creationMode.isActive && /* @__PURE__ */ import_react32.default.createElement(
18150
+ creationMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18240
18151
  InSceneCreationForm,
18241
18152
  {
18242
18153
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -18257,8 +18168,8 @@ function XViewScene({
18257
18168
  },
18258
18169
  refEl: formRef,
18259
18170
  existingTypes: existingNodeTypes,
18260
- initialColor: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.color,
18261
- sourceTypes: (_f = creationMode.sourceNodeData) == null ? void 0 : _f.type,
18171
+ initialColor: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.color,
18172
+ sourceTypes: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.type,
18262
18173
  onIntensityChange: handleGhostNodeIntensityChange,
18263
18174
  onUploadFile: upload_file_action,
18264
18175
  availableDatasets,
@@ -18268,7 +18179,7 @@ function XViewScene({
18268
18179
  availableAncestries: allAvailableAncestries
18269
18180
  }
18270
18181
  ),
18271
- versionMode.isActive && /* @__PURE__ */ import_react32.default.createElement(
18182
+ versionMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18272
18183
  InSceneVersionForm,
18273
18184
  {
18274
18185
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -18287,14 +18198,14 @@ function XViewScene({
18287
18198
  transition: "opacity 200ms ease-out"
18288
18199
  },
18289
18200
  refEl: formRef,
18290
- fixedType: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.type,
18291
- fixedColor: (_h = versionMode.sourceNodeData) == null ? void 0 : _h.color,
18201
+ fixedType: (_f = versionMode.sourceNodeData) == null ? void 0 : _f.type,
18202
+ fixedColor: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.color,
18292
18203
  onUploadFile: upload_file_action,
18293
18204
  availableNodes: allAvailableNodes,
18294
18205
  availableAncestries: allAvailableAncestries
18295
18206
  }
18296
18207
  ),
18297
- questMode.isActive && /* @__PURE__ */ import_react32.default.createElement(
18208
+ questMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18298
18209
  InSceneQuestForm,
18299
18210
  {
18300
18211
  onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
@@ -18316,13 +18227,13 @@ function XViewScene({
18316
18227
  availableNodes: allAvailableNodes,
18317
18228
  availableAncestries: allAvailableAncestries,
18318
18229
  viewName: viewParams == null ? void 0 : viewParams.name,
18319
- questCounter: ((_i = sceneDataRef.current) == null ? void 0 : _i.quest_counter) || 1,
18230
+ questCounter: ((_h = sceneDataRef.current) == null ? void 0 : _h.quest_counter) || 1,
18320
18231
  viewMembers,
18321
- milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18232
+ milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
18322
18233
  onUpdateMilestones: handleUpdateMilestones
18323
18234
  }
18324
18235
  ),
18325
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react32.default.createElement(
18236
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react29.default.createElement(
18326
18237
  "div",
18327
18238
  {
18328
18239
  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"}`,
@@ -18335,7 +18246,7 @@ function XViewScene({
18335
18246
  maxWidth: "92vw"
18336
18247
  }
18337
18248
  },
18338
- /* @__PURE__ */ import_react32.default.createElement(
18249
+ /* @__PURE__ */ import_react29.default.createElement(
18339
18250
  "div",
18340
18251
  {
18341
18252
  onPointerDown: (e) => {
@@ -18346,7 +18257,7 @@ function XViewScene({
18346
18257
  title: "Arraste para redimensionar"
18347
18258
  }
18348
18259
  ),
18349
- /* @__PURE__ */ import_react32.default.createElement(
18260
+ /* @__PURE__ */ import_react29.default.createElement(
18350
18261
  DescriptionReadModePanel,
18351
18262
  {
18352
18263
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -18381,7 +18292,7 @@ function XViewScene({
18381
18292
  }
18382
18293
  )
18383
18294
  ),
18384
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react32.default.createElement(
18295
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react29.default.createElement(
18385
18296
  CreateAncestryPanel,
18386
18297
  {
18387
18298
  ancestryMode,
@@ -18417,7 +18328,7 @@ function XViewScene({
18417
18328
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
18418
18329
  }
18419
18330
  ),
18420
- editingAncestryRel.visible && /* @__PURE__ */ import_react32.default.createElement(
18331
+ editingAncestryRel.visible && /* @__PURE__ */ import_react29.default.createElement(
18421
18332
  AncestryRelationshipPanel,
18422
18333
  {
18423
18334
  data: editingAncestryRel.data,
@@ -18431,7 +18342,7 @@ function XViewScene({
18431
18342
  onUploadFile: upload_file_action
18432
18343
  }
18433
18344
  ),
18434
- detailsNode && detailsNode.is_quest && /* @__PURE__ */ import_react32.default.createElement(
18345
+ detailsNode && detailsNode.is_quest && /* @__PURE__ */ import_react29.default.createElement(
18435
18346
  QuestDetailsPanel,
18436
18347
  {
18437
18348
  node: detailsNode,
@@ -18453,11 +18364,11 @@ function XViewScene({
18453
18364
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
18454
18365
  viewMembers,
18455
18366
  currentUser: session == null ? void 0 : session.user,
18456
- milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18367
+ milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18457
18368
  onUpdateMilestones: handleUpdateMilestones
18458
18369
  }
18459
18370
  ),
18460
- detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react32.default.createElement(
18371
+ detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react29.default.createElement(
18461
18372
  NodeDetailsPanel,
18462
18373
  {
18463
18374
  node: detailsNode,
@@ -18489,7 +18400,7 @@ function XViewScene({
18489
18400
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
18490
18401
  }
18491
18402
  ),
18492
- detailsLink && /* @__PURE__ */ import_react32.default.createElement(
18403
+ detailsLink && /* @__PURE__ */ import_react29.default.createElement(
18493
18404
  RelationshipDetailsPanel,
18494
18405
  {
18495
18406
  link: detailsLink,
@@ -18503,7 +18414,7 @@ function XViewScene({
18503
18414
  userRole: userPermissionRole
18504
18415
  }
18505
18416
  ),
18506
- ancestryLinkDetails && /* @__PURE__ */ import_react32.default.createElement(
18417
+ ancestryLinkDetails && /* @__PURE__ */ import_react29.default.createElement(
18507
18418
  AncestryLinkDetailsPanel,
18508
18419
  {
18509
18420
  data: ancestryLinkDetails,
@@ -18514,7 +18425,7 @@ function XViewScene({
18514
18425
  onUploadFile: upload_file_action
18515
18426
  }
18516
18427
  ),
18517
- /* @__PURE__ */ import_react32.default.createElement(
18428
+ /* @__PURE__ */ import_react29.default.createElement(
18518
18429
  "div",
18519
18430
  {
18520
18431
  ref: tooltipRef,
@@ -18541,7 +18452,7 @@ function XViewScene({
18541
18452
  }
18542
18453
  }
18543
18454
  ),
18544
- /* @__PURE__ */ import_react32.default.createElement(
18455
+ /* @__PURE__ */ import_react29.default.createElement(
18545
18456
  ContextMenu,
18546
18457
  {
18547
18458
  data: contextMenu,
@@ -18574,7 +18485,7 @@ function XViewScene({
18574
18485
  onFinishQuest: handleFinishQuestQuick
18575
18486
  }
18576
18487
  ),
18577
- /* @__PURE__ */ import_react32.default.createElement(
18488
+ /* @__PURE__ */ import_react29.default.createElement(
18578
18489
  MultiNodeContextMenu,
18579
18490
  {
18580
18491
  data: multiContextMenu,
@@ -18594,7 +18505,7 @@ function XViewScene({
18594
18505
  )
18595
18506
  }
18596
18507
  ),
18597
- /* @__PURE__ */ import_react32.default.createElement(
18508
+ /* @__PURE__ */ import_react29.default.createElement(
18598
18509
  RelationshipContextMenu,
18599
18510
  {
18600
18511
  data: relationshipMenu,
@@ -18612,14 +18523,14 @@ function XViewScene({
18612
18523
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
18613
18524
  }
18614
18525
  ),
18615
- /* @__PURE__ */ import_react32.default.createElement(
18526
+ /* @__PURE__ */ import_react29.default.createElement(
18616
18527
  ImageViewer,
18617
18528
  {
18618
18529
  data: imageViewer,
18619
18530
  onClose: () => setImageViewer({ ...imageViewer, visible: false })
18620
18531
  }
18621
18532
  ),
18622
- /* @__PURE__ */ import_react32.default.createElement(
18533
+ /* @__PURE__ */ import_react29.default.createElement(
18623
18534
  AncestryBoard,
18624
18535
  {
18625
18536
  isOpen: isAncestryBoardOpen,
@@ -18632,29 +18543,29 @@ function XViewScene({
18632
18543
  userRole: userPermissionRole
18633
18544
  }
18634
18545
  ),
18635
- /* @__PURE__ */ import_react32.default.createElement(
18546
+ /* @__PURE__ */ import_react29.default.createElement(
18636
18547
  MilestoneManager,
18637
18548
  {
18638
18549
  isOpen: isMilestoneManagerOpen,
18639
18550
  onClose: () => setIsMilestoneManagerOpen(false),
18640
- milestones: ((_l = sceneDataRef.current) == null ? void 0 : _l.milestones) || [],
18551
+ milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18641
18552
  onUpdateMilestones: handleUpdateMilestones
18642
18553
  }
18643
18554
  ),
18644
- /* @__PURE__ */ import_react32.default.createElement(
18555
+ /* @__PURE__ */ import_react29.default.createElement(
18645
18556
  ImportParentFileModal,
18646
18557
  {
18647
18558
  isOpen: isImportModalOpen,
18648
18559
  onClose: () => setIsImportModalOpen(false),
18649
18560
  onConfirm: handleConfirmImport,
18650
18561
  session,
18651
- parentDbs: ((_m = sceneDataRef.current) == null ? void 0 : _m.parent_dbs) || [],
18562
+ parentDbs: ((_l = sceneDataRef.current) == null ? void 0 : _l.parent_dbs) || [],
18652
18563
  onFetchAvailableFiles: import_parent_file_modal_get,
18653
18564
  currentViewName: viewParams == null ? void 0 : viewParams.name,
18654
18565
  currentAncestries: ancestryDataRef.current || []
18655
18566
  }
18656
18567
  ),
18657
- invalidTargetError && /* @__PURE__ */ import_react32.default.createElement(
18568
+ invalidTargetError && /* @__PURE__ */ import_react29.default.createElement(
18658
18569
  "div",
18659
18570
  {
18660
18571
  className: "ui-overlay",
@@ -18679,13 +18590,13 @@ function XViewScene({
18679
18590
  animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
18680
18591
  }
18681
18592
  },
18682
- /* @__PURE__ */ import_react32.default.createElement("style", null, `
18593
+ /* @__PURE__ */ import_react29.default.createElement("style", null, `
18683
18594
  @keyframes fadeInDown {
18684
18595
  from { opacity: 0; transform: translate(-50%, -20px); }
18685
18596
  to { opacity: 1; transform: translate(-50%, 0); }
18686
18597
  }
18687
18598
  `),
18688
- /* @__PURE__ */ import_react32.default.createElement(
18599
+ /* @__PURE__ */ import_react29.default.createElement(
18689
18600
  "svg",
18690
18601
  {
18691
18602
  width: "20",
@@ -18697,12 +18608,12 @@ function XViewScene({
18697
18608
  strokeLinecap: "round",
18698
18609
  strokeLinejoin: "round"
18699
18610
  },
18700
- /* @__PURE__ */ import_react32.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18701
- /* @__PURE__ */ import_react32.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18702
- /* @__PURE__ */ import_react32.default.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18611
+ /* @__PURE__ */ import_react29.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18612
+ /* @__PURE__ */ import_react29.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18613
+ /* @__PURE__ */ import_react29.default.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18703
18614
  ),
18704
- /* @__PURE__ */ import_react32.default.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18705
- /* @__PURE__ */ import_react32.default.createElement(
18615
+ /* @__PURE__ */ import_react29.default.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18616
+ /* @__PURE__ */ import_react29.default.createElement(
18706
18617
  "button",
18707
18618
  {
18708
18619
  onClick: () => setInvalidTargetError(null),
@@ -18732,7 +18643,451 @@ function XViewScene({
18732
18643
  )
18733
18644
  );
18734
18645
  }
18646
+
18647
+ // src/x_view_server_logic.js
18648
+ async function save_view_data_logic(db_services, filename, data) {
18649
+ try {
18650
+ const saveResult = await db_services.save_file(filename, data);
18651
+ return saveResult;
18652
+ } catch (error) {
18653
+ console.error("catch (error) em save_view_data_logic:", error);
18654
+ return { success: false, error: error.message };
18655
+ }
18656
+ }
18657
+ async function get_scene_view_data_logic(db_services, scene_config, owner_id, type, session, focusNodeId = null, focusAncestryId = null) {
18658
+ var _a, _b;
18659
+ try {
18660
+ if (!session || !session.user) {
18661
+ return { success: false, error: "Usu\xE1rio n\xE3o autenticado." };
18662
+ }
18663
+ const membershipCheck = await db_services.check_membership(owner_id, type, scene_config, session.user.id);
18664
+ const isFullMember = membershipCheck.success && membershipCheck.isValidMember;
18665
+ if (!isFullMember && !focusNodeId && !focusAncestryId) {
18666
+ return { success: false, error: "Acesso Negado: Voc\xEA n\xE3o possui permiss\xE3o para acessar este cen\xE1rio." };
18667
+ }
18668
+ const sceneResponse = await db_services.get_file(`x_view_scenes/${owner_id}/${scene_config}`);
18669
+ if (!sceneResponse || !sceneResponse.success) {
18670
+ console.error("Falha ao buscar dados da cena:", sceneResponse == null ? void 0 : sceneResponse.error);
18671
+ return { success: false, error: `N\xE3o foi poss\xEDvel carregar o arquivo da cena: ${scene_config}` };
18672
+ }
18673
+ const sceneData = sceneResponse.data;
18674
+ const parentDbObjects = sceneData.parent_dbs || [];
18675
+ if (type && type.toLowerCase().includes("database")) {
18676
+ const selfExists = parentDbObjects.some((db) => String(db.db_id) === String(scene_config));
18677
+ if (!selfExists) {
18678
+ parentDbObjects.push({ db_id: scene_config, owner_id });
18679
+ }
18680
+ }
18681
+ const parentResponsesPromises = parentDbObjects.map(
18682
+ (db_info) => db_services.get_file(`x_view_dbs/${db_info.owner_id}/${db_info.db_id}`)
18683
+ );
18684
+ const parentResponsesResults = await Promise.allSettled(parentResponsesPromises);
18685
+ const parentData = {};
18686
+ for (let i = 0; i < parentResponsesResults.length; i++) {
18687
+ const result = parentResponsesResults[i];
18688
+ const db_info = parentDbObjects[i];
18689
+ if (result.status === "fulfilled" && ((_a = result.value) == null ? void 0 : _a.success)) {
18690
+ parentData[db_info.db_id] = result.value.data;
18691
+ } else {
18692
+ console.warn(
18693
+ `Arquivo pai n\xE3o carregado: ${db_info.db_id}. Pode ter sido deletado.`,
18694
+ result.status === "rejected" ? result.reason : (_b = result.value) == null ? void 0 : _b.error
18695
+ );
18696
+ }
18697
+ }
18698
+ if (type && type.toLowerCase() === "view") {
18699
+ parentData[scene_config] = {
18700
+ dataset_name: "Quests Internas (View)",
18701
+ nodes: sceneData.quest_nodes || [],
18702
+ links: sceneData.quest_links || []
18703
+ };
18704
+ }
18705
+ const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
18706
+ const allLinks = Object.values(parentData).flatMap((db) => db.links || []);
18707
+ const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
18708
+ const parentLinkMap = new Map(allLinks.map((link) => [`${link.source}-${link.target}`, link]));
18709
+ const validatedNodes = (sceneData.nodes || []).map((sceneNode) => {
18710
+ var _a2, _b2;
18711
+ const nodeTypes = Array.isArray(sceneNode.type) ? sceneNode.type : [sceneNode.type];
18712
+ if (nodeTypes.includes("quest")) {
18713
+ const dbQuestNode = (_b2 = (_a2 = parentData[scene_config]) == null ? void 0 : _a2.nodes) == null ? void 0 : _b2.find((qn) => String(qn.id) === String(sceneNode.id));
18714
+ if (dbQuestNode) {
18715
+ return { ...sceneNode, ...dbQuestNode };
18716
+ }
18717
+ return sceneNode;
18718
+ }
18719
+ const dbNode = parentNodeMap.get(String(sceneNode.id));
18720
+ if (dbNode) {
18721
+ return { ...sceneNode, ...dbNode };
18722
+ }
18723
+ return null;
18724
+ }).filter(Boolean);
18725
+ const validNodeIdsInScene = new Set(validatedNodes.map((node) => String(node.id)));
18726
+ const validatedLinks = (sceneData.links || []).filter((sceneLink) => {
18727
+ const linkExistsInParent = parentLinkMap.has(`${sceneLink.source}-${sceneLink.target}`);
18728
+ const nodesAreValidForScene = validNodeIdsInScene.has(String(sceneLink.source)) && validNodeIdsInScene.has(String(sceneLink.target));
18729
+ return linkExistsInParent && nodesAreValidForScene;
18730
+ }).map((sceneLink) => parentLinkMap.get(`${sceneLink.source}-${sceneLink.target}`));
18731
+ const validatedSceneData = {
18732
+ ...sceneData,
18733
+ nodes: validatedNodes,
18734
+ links: validatedLinks
18735
+ };
18736
+ const ancestryFilePaths = [];
18737
+ ancestryFilePaths.push({
18738
+ path: `x_view_ancestry/${owner_id}/${scene_config}`,
18739
+ source_id: scene_config,
18740
+ owner_id,
18741
+ isSceneFile: true
18742
+ });
18743
+ parentDbObjects.forEach((db_info) => {
18744
+ ancestryFilePaths.push({
18745
+ path: `x_view_ancestry/${db_info.owner_id}/${db_info.db_id}`,
18746
+ source_id: db_info.db_id,
18747
+ owner_id: db_info.owner_id,
18748
+ isSceneFile: false
18749
+ });
18750
+ });
18751
+ const ancestryPromises = ancestryFilePaths.map((file) => db_services.get_file(file.path));
18752
+ const ancestryResults = await Promise.allSettled(ancestryPromises);
18753
+ const ancestriesFromSceneFile = [];
18754
+ const ancestriesFromDbFiles = [];
18755
+ ancestryResults.forEach((result, index) => {
18756
+ var _a2;
18757
+ const fileInfo = ancestryFilePaths[index];
18758
+ if (result.status === "fulfilled" && ((_a2 = result.value) == null ? void 0 : _a2.success) && Array.isArray(result.value.data)) {
18759
+ const ancestriesFromFile = result.value.data.map((ancestry) => {
18760
+ const existingSource = ancestry._source_file_id;
18761
+ const existingOwner = ancestry._source_owner_id;
18762
+ const isImportedItem = existingSource && existingSource !== fileInfo.source_id;
18763
+ return {
18764
+ ...ancestry,
18765
+ _source_file_id: isImportedItem ? existingSource : fileInfo.source_id,
18766
+ _source_owner_id: isImportedItem ? existingOwner : fileInfo.owner_id
18767
+ };
18768
+ });
18769
+ if (fileInfo.isSceneFile) {
18770
+ ancestriesFromSceneFile.push(...ancestriesFromFile);
18771
+ } else {
18772
+ ancestriesFromDbFiles.push(...ancestriesFromFile);
18773
+ }
18774
+ }
18775
+ });
18776
+ const ancestryMap = /* @__PURE__ */ new Map();
18777
+ ancestriesFromDbFiles.forEach((anc) => ancestryMap.set(anc.ancestry_id, anc));
18778
+ ancestriesFromSceneFile.forEach((anc) => ancestryMap.set(anc.ancestry_id, anc));
18779
+ let ancestryData = Array.from(ancestryMap.values());
18780
+ const externalSourcesToRefresh = /* @__PURE__ */ new Map();
18781
+ ancestryData.forEach((anc) => {
18782
+ const targetSourceId = anc._source_file_id || anc._imported_from_view_id;
18783
+ const targetOwnerId = anc._source_owner_id || anc._imported_from_view_owner_id;
18784
+ if (targetSourceId && targetSourceId !== scene_config && targetOwnerId) {
18785
+ const isAlreadyLoadedAsParent = parentDbObjects.some((db) => String(db.db_id) === String(targetSourceId));
18786
+ if (!isAlreadyLoadedAsParent) {
18787
+ const key = `${targetOwnerId}/${targetSourceId}`;
18788
+ externalSourcesToRefresh.set(key, {
18789
+ owner_id: targetOwnerId,
18790
+ source_id: targetSourceId,
18791
+ key
18792
+ });
18793
+ }
18794
+ }
18795
+ });
18796
+ const successfullyFetchedSources = /* @__PURE__ */ new Set();
18797
+ const failedSources = /* @__PURE__ */ new Set();
18798
+ if (externalSourcesToRefresh.size > 0) {
18799
+ const refreshPromises = Array.from(externalSourcesToRefresh.values()).map(
18800
+ (src) => db_services.get_file(`x_view_ancestry/${src.owner_id}/${src.source_id}`).then((res) => ({ ...res, _meta_key: src.key }))
18801
+ );
18802
+ const refreshResults = await Promise.allSettled(refreshPromises);
18803
+ const freshAncestryMap = /* @__PURE__ */ new Map();
18804
+ refreshResults.forEach((result) => {
18805
+ var _a2, _b2;
18806
+ if (result.status === "fulfilled" && ((_a2 = result.value) == null ? void 0 : _a2.success) && Array.isArray(result.value.data)) {
18807
+ successfullyFetchedSources.add(result.value._meta_key);
18808
+ result.value.data.forEach((freshAnc) => {
18809
+ if (!freshAnc.is_private) {
18810
+ freshAncestryMap.set(String(freshAnc.ancestry_id), freshAnc);
18811
+ }
18812
+ });
18813
+ } else if (result.status === "fulfilled" && !((_b2 = result.value) == null ? void 0 : _b2.success)) {
18814
+ failedSources.add(result.value._meta_key);
18815
+ }
18816
+ });
18817
+ ancestryData = ancestryData.filter((localAnc) => {
18818
+ const targetSourceId = localAnc._source_file_id || localAnc._imported_from_view_id;
18819
+ const targetOwnerId = localAnc._source_owner_id || localAnc._imported_from_view_owner_id;
18820
+ if (!targetSourceId || targetSourceId === scene_config) return true;
18821
+ const key = `${targetOwnerId}/${targetSourceId}`;
18822
+ if (failedSources.has(key)) {
18823
+ return false;
18824
+ }
18825
+ if (externalSourcesToRefresh.has(key) && successfullyFetchedSources.has(key)) {
18826
+ const stillExists = freshAncestryMap.has(String(localAnc.ancestry_id));
18827
+ return stillExists;
18828
+ }
18829
+ return true;
18830
+ }).map((localAnc) => {
18831
+ const freshVersion = freshAncestryMap.get(String(localAnc.ancestry_id));
18832
+ if (freshVersion) {
18833
+ return {
18834
+ ...freshVersion,
18835
+ _imported_from_view_id: localAnc._imported_from_view_id,
18836
+ _imported_from_view_owner_id: localAnc._imported_from_view_owner_id,
18837
+ _origin_db_ids: localAnc._origin_db_ids,
18838
+ _source_file_id: localAnc._source_file_id,
18839
+ _source_owner_id: localAnc._source_owner_id
18840
+ };
18841
+ }
18842
+ return localAnc;
18843
+ });
18844
+ }
18845
+ const ancestryFilePath = `x_view_ancestry/${owner_id}/${scene_config}`;
18846
+ const parentNodeIds = new Set(allNodes.map((node) => String(node.id)));
18847
+ const pruneTree = (node) => {
18848
+ if (!node) return null;
18849
+ if (node.is_section) {
18850
+ const validChildren2 = (node.children || []).map((child) => pruneTree(child)).filter(Boolean);
18851
+ return { ...node, children: validChildren2 };
18852
+ }
18853
+ if (!parentNodeIds.has(String(node.node_id))) {
18854
+ return null;
18855
+ }
18856
+ const validChildren = (node.children || []).map((child) => pruneTree(child)).filter(Boolean);
18857
+ let validBranches = [];
18858
+ if (node.parallel_branches) {
18859
+ validBranches = node.parallel_branches.map((branch) => ({
18860
+ ...branch,
18861
+ tree: pruneTree(branch.tree)
18862
+ })).filter((b) => b.tree !== null);
18863
+ }
18864
+ return {
18865
+ ...node,
18866
+ children: validChildren,
18867
+ parallel_branches: validBranches
18868
+ };
18869
+ };
18870
+ const originalAncestryDataString = JSON.stringify(Array.from(ancestryMap.values()));
18871
+ const cleanedAncestryData = ancestryData.map((ancestry) => {
18872
+ if (!parentNodeIds.has(String(ancestry.ancestral_node))) return null;
18873
+ const cleanedTree = pruneTree(ancestry.tree);
18874
+ if (!cleanedTree) return null;
18875
+ let cleanedAbstraction = null;
18876
+ if (ancestry.abstraction_tree) {
18877
+ cleanedAbstraction = pruneTree(ancestry.abstraction_tree);
18878
+ }
18879
+ return {
18880
+ ...ancestry,
18881
+ tree: cleanedTree,
18882
+ abstraction_tree: cleanedAbstraction
18883
+ };
18884
+ }).filter(Boolean);
18885
+ if (JSON.stringify(cleanedAncestryData) !== originalAncestryDataString) {
18886
+ ancestryData = cleanedAncestryData;
18887
+ try {
18888
+ await db_services.save_file(ancestryFilePath, ancestryData);
18889
+ } catch (saveError) {
18890
+ console.error("Falha ao salvar o arquivo de ancestralidade da cena atualizado:", saveError);
18891
+ }
18892
+ }
18893
+ if (!isFullMember) {
18894
+ const requiredNodeIds = /* @__PURE__ */ new Set();
18895
+ const requiredAncestryIds = /* @__PURE__ */ new Set();
18896
+ if (focusNodeId) requiredNodeIds.add(String(focusNodeId));
18897
+ if (focusAncestryId) requiredAncestryIds.add(String(focusAncestryId));
18898
+ const allNodesFromDb = Object.values(parentData).flatMap((db) => db.nodes || []);
18899
+ const extractDependenciesFromText = (text) => {
18900
+ if (!text) return;
18901
+ const mentionRegex = /\[\[MENTION:node:([a-zA-Z0-9\-_]+)\]\]/g;
18902
+ const refRegex = /\[\[REF:(node|ancestry):([a-zA-Z0-9\-_]+):([a-zA-Z0-9\-_]+)\]\]/g;
18903
+ let match;
18904
+ while ((match = mentionRegex.exec(text)) !== null) {
18905
+ requiredNodeIds.add(match[1]);
18906
+ }
18907
+ while ((match = refRegex.exec(text)) !== null) {
18908
+ if (match[1] === "node") requiredNodeIds.add(match[2]);
18909
+ if (match[1] === "ancestry") requiredAncestryIds.add(match[2]);
18910
+ }
18911
+ };
18912
+ const extractTreeDependencies = (treeItem) => {
18913
+ var _a2;
18914
+ if (!treeItem) return;
18915
+ if (treeItem.node_id) requiredNodeIds.add(String(treeItem.node_id));
18916
+ if ((_a2 = treeItem.node) == null ? void 0 : _a2.id) requiredNodeIds.add(String(treeItem.node.id));
18917
+ if (treeItem.children) {
18918
+ treeItem.children.forEach(extractTreeDependencies);
18919
+ }
18920
+ if (treeItem.parallel_branches) {
18921
+ treeItem.parallel_branches.forEach((branch) => {
18922
+ if (branch.linked_ancestry_id) {
18923
+ requiredAncestryIds.add(String(branch.linked_ancestry_id));
18924
+ }
18925
+ if (branch.description) extractDependenciesFromText(branch.description);
18926
+ if (branch.description_sections) {
18927
+ branch.description_sections.forEach((s) => extractDependenciesFromText(s.content));
18928
+ }
18929
+ extractTreeDependencies(branch.tree);
18930
+ });
18931
+ }
18932
+ };
18933
+ let previousSize;
18934
+ do {
18935
+ previousSize = requiredNodeIds.size + requiredAncestryIds.size;
18936
+ requiredAncestryIds.forEach((ancId) => {
18937
+ const anc = ancestryData.find((a) => String(a.ancestry_id) === ancId);
18938
+ if (anc && !anc.is_private) {
18939
+ if (anc.description) extractDependenciesFromText(anc.description);
18940
+ if (anc.description_sections) {
18941
+ anc.description_sections.forEach((s) => extractDependenciesFromText(s.content));
18942
+ }
18943
+ extractTreeDependencies(anc.tree);
18944
+ extractTreeDependencies(anc.abstraction_tree);
18945
+ }
18946
+ });
18947
+ requiredNodeIds.forEach((nodeId) => {
18948
+ const node = allNodesFromDb.find((n) => String(n.id) === nodeId);
18949
+ if (node) {
18950
+ if (node.description) extractDependenciesFromText(node.description);
18951
+ if (node.description_sections) {
18952
+ node.description_sections.forEach((s) => extractDependenciesFromText(s.content));
18953
+ }
18954
+ }
18955
+ });
18956
+ } while (requiredNodeIds.size + requiredAncestryIds.size > previousSize);
18957
+ const restrictedSceneData = { ...validatedSceneData, nodes: [], links: [] };
18958
+ const restrictedParentData = {};
18959
+ const restrictedAncestryData = ancestryData.filter((a) => requiredAncestryIds.has(String(a.ancestry_id)) && !a.is_private);
18960
+ for (const [dbId, dbContent] of Object.entries(parentData)) {
18961
+ const filteredNodes = (dbContent.nodes || []).filter((n) => requiredNodeIds.has(String(n.id)));
18962
+ if (filteredNodes.length > 0) {
18963
+ restrictedParentData[dbId] = { ...dbContent, nodes: filteredNodes, links: [] };
18964
+ }
18965
+ }
18966
+ if (focusNodeId) {
18967
+ const mainNode = allNodesFromDb.find((n) => String(n.id) === String(focusNodeId));
18968
+ if (mainNode) {
18969
+ restrictedSceneData.nodes = [mainNode];
18970
+ }
18971
+ }
18972
+ return {
18973
+ success: true,
18974
+ data: {
18975
+ scene: restrictedSceneData,
18976
+ parent: restrictedParentData,
18977
+ ancestry: restrictedAncestryData
18978
+ }
18979
+ };
18980
+ }
18981
+ return {
18982
+ success: true,
18983
+ data: { scene: validatedSceneData, parent: parentData, ancestry: ancestryData }
18984
+ };
18985
+ } catch (error) {
18986
+ console.error("Erro em get_scene_view_data_logic:", error);
18987
+ return { success: false, error: error.message };
18988
+ }
18989
+ }
18990
+ async function import_parent_file_modal_get_logic(db_services, session) {
18991
+ try {
18992
+ const call_firestore_get_x_view_data = await db_services.get_firestore_data(session);
18993
+ const x_view_databases = call_firestore_get_x_view_data.data.sub_collections.x_view_databases || [];
18994
+ const x_views = call_firestore_get_x_view_data.data.sub_collections.x_views || [];
18995
+ return {
18996
+ success: true,
18997
+ data: {
18998
+ databases: x_view_databases,
18999
+ views: x_views
19000
+ }
19001
+ };
19002
+ } catch (error) {
19003
+ console.error("catch (error) em import_parent_file_modal_get_logic:", error);
19004
+ return { success: false, error: error.message };
19005
+ }
19006
+ }
19007
+ async function get_single_parent_file_logic(db_services, file_id, session) {
19008
+ try {
19009
+ const call_GCP_cloud_storage_get_file = await db_services.get_file(`x_view_dbs/${session.user.id}/${file_id}`);
19010
+ return call_GCP_cloud_storage_get_file;
19011
+ } catch (error) {
19012
+ console.error("catch (error) em get_single_parent_file_logic:", error);
19013
+ return { success: false, error: error.message };
19014
+ }
19015
+ }
19016
+ async function x_view_add_new_parent_file_to_scene_at_firebase(file_id, session, new_parent, db_services) {
19017
+ try {
19018
+ const update_data = {
19019
+ scene_id: file_id,
19020
+ new_parent,
19021
+ session
19022
+ };
19023
+ const call_firestore_add_new_parent_file_to_scene_at_firebase = await db_services.add_new_parent_file_to_scene_at_firebase(update_data);
19024
+ return call_firestore_add_new_parent_file_to_scene_at_firebase;
19025
+ } catch (error) {
19026
+ console.error("catch (error) em get_single_parent_file_logic:", error);
19027
+ return { success: false, error: error.message };
19028
+ }
19029
+ }
19030
+ async function get_ancestry_file_logic(db_services, file_id, owner_id) {
19031
+ try {
19032
+ const path = `x_view_ancestry/${owner_id}/${file_id}`;
19033
+ const call_GCP_cloud_storage_get_file = await db_services.get_file(path);
19034
+ return call_GCP_cloud_storage_get_file;
19035
+ } catch (error) {
19036
+ console.error("catch (error) em get_ancestry_file_logic:", error);
19037
+ return { success: false, error: error.message };
19038
+ }
19039
+ }
19040
+ async function save_ancestry_board_logic(db_services, scene_id, type, groups, session, owner_id) {
19041
+ try {
19042
+ const targetOwnerId = owner_id || session.user.id;
19043
+ return await db_services.save_ancestry_board(session, scene_id, type, groups, targetOwnerId);
19044
+ } catch (error) {
19045
+ console.error("Erro em save_ancestry_board_logic:", error);
19046
+ return { success: false, error: error.message };
19047
+ }
19048
+ }
19049
+ async function get_ancestry_board_logic(db_services, scene_id, type, session, owner_id) {
19050
+ try {
19051
+ const targetOwnerId = owner_id || session.user.id;
19052
+ return await db_services.get_ancestry_board(session, scene_id, type, targetOwnerId);
19053
+ } catch (error) {
19054
+ console.error("Erro em get_ancestry_board_logic:", error);
19055
+ return { success: false, error: error.message };
19056
+ }
19057
+ }
19058
+ async function delete_uploaded_file_logic(db_services, fileUrl) {
19059
+ try {
19060
+ if (db_services.delete_public_file) {
19061
+ return await db_services.delete_public_file(fileUrl);
19062
+ }
19063
+ return { success: false, error: "Servi\xE7o de dele\xE7\xE3o n\xE3o configurado." };
19064
+ } catch (error) {
19065
+ console.error("Erro em delete_uploaded_file_logic:", error);
19066
+ return { success: false, error: error.message };
19067
+ }
19068
+ }
19069
+ async function get_view_members_logic(db_services, ownerId, type, itemId) {
19070
+ try {
19071
+ if (!db_services.get_view_members) {
19072
+ return { success: false, error: "Servi\xE7o de busca de membros n\xE3o configurado." };
19073
+ }
19074
+ return await db_services.get_view_members(ownerId, type, itemId);
19075
+ } catch (error) {
19076
+ console.error("Erro em get_view_members_logic:", error);
19077
+ return { success: false, error: error.message };
19078
+ }
19079
+ }
18735
19080
  // Annotate the CommonJS export names for ESM import in node:
18736
19081
  0 && (module.exports = {
18737
- XViewScene
19082
+ XViewScene,
19083
+ delete_uploaded_file_logic,
19084
+ get_ancestry_board_logic,
19085
+ get_ancestry_file_logic,
19086
+ get_scene_view_data_logic,
19087
+ get_single_parent_file_logic,
19088
+ get_view_members_logic,
19089
+ import_parent_file_modal_get_logic,
19090
+ save_ancestry_board_logic,
19091
+ save_view_data_logic,
19092
+ x_view_add_new_parent_file_to_scene_at_firebase
18738
19093
  });