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

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 +700 -608
  2. package/dist/index.mjs +706 -615
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -44,9 +44,9 @@ __export(index_exports, {
44
44
  module.exports = __toCommonJS(index_exports);
45
45
 
46
46
  // src/XViewScene.jsx
47
- var import_react29 = __toESM(require("react"));
47
+ var import_react31 = __toESM(require("react"));
48
48
  var import_navigation = require("next/navigation");
49
- var import_react30 = require("next-auth/react");
49
+ var import_react32 = require("next-auth/react");
50
50
  var import_crypto_js = __toESM(require("crypto-js"));
51
51
  var THREE3 = __toESM(require("three"));
52
52
  var import_OrbitControls = require("three/examples/jsm/controls/OrbitControls.js");
@@ -12919,172 +12919,414 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
12919
12919
  }
12920
12920
 
12921
12921
  // src/components/AncestryBoard.jsx
12922
+ var import_react29 = __toESM(require("react"));
12923
+ var import_fi23 = require("react-icons/fi");
12924
+ var import_uuid11 = require("uuid");
12925
+
12926
+ // src/components/RichGroupEditor.jsx
12927
+ var import_react28 = __toESM(require("react"));
12928
+
12929
+ // src/components/MentionPopover.jsx
12922
12930
  var import_react27 = __toESM(require("react"));
12923
12931
  var import_fi22 = require("react-icons/fi");
12924
- var import_uuid11 = require("uuid");
12932
+ var TYPE_CONFIG = {
12933
+ ancestry: { Icon: import_fi22.FiLayers, color: "text-indigo-400", label: "Ancestralidade" },
12934
+ quest: { Icon: import_fi22.FiCheckSquare, color: "text-emerald-400", label: "Quest" },
12935
+ version: { Icon: import_fi22.FiGitBranch, color: "text-amber-400", label: "Vers\xE3o" },
12936
+ node: { Icon: import_fi22.FiBox, color: "text-slate-400", label: "Node" }
12937
+ };
12938
+ function MentionPopover({ query, items, position, onSelect, onClose }) {
12939
+ const [activeIndex, setActiveIndex] = (0, import_react27.useState)(0);
12940
+ const listRef = (0, import_react27.useRef)(null);
12941
+ const filtered = (0, import_react27.useMemo)(() => {
12942
+ const term = (query || "").toLowerCase().trim();
12943
+ if (!term) return items.slice(0, 8);
12944
+ return items.filter(
12945
+ (item) => (item.searchLabel || "").toLowerCase().includes(term) || (item.searchDesc || "").toLowerCase().includes(term)
12946
+ ).slice(0, 8);
12947
+ }, [items, query]);
12948
+ (0, import_react27.useEffect)(() => {
12949
+ setActiveIndex(0);
12950
+ }, [query]);
12951
+ (0, import_react27.useEffect)(() => {
12952
+ const handleKeyDown = (e) => {
12953
+ if (e.key === "ArrowDown") {
12954
+ e.preventDefault();
12955
+ setActiveIndex((i) => Math.min(i + 1, filtered.length - 1));
12956
+ } else if (e.key === "ArrowUp") {
12957
+ e.preventDefault();
12958
+ setActiveIndex((i) => Math.max(i - 1, 0));
12959
+ } else if (e.key === "Enter" || e.key === "Tab") {
12960
+ e.preventDefault();
12961
+ if (filtered[activeIndex]) onSelect(filtered[activeIndex]);
12962
+ } else if (e.key === "Escape") {
12963
+ e.preventDefault();
12964
+ onClose();
12965
+ }
12966
+ };
12967
+ window.addEventListener("keydown", handleKeyDown, true);
12968
+ return () => window.removeEventListener("keydown", handleKeyDown, true);
12969
+ }, [filtered, activeIndex, onSelect, onClose]);
12970
+ (0, import_react27.useEffect)(() => {
12971
+ if (listRef.current) {
12972
+ const el = listRef.current.children[activeIndex];
12973
+ if (el) el.scrollIntoView({ block: "nearest" });
12974
+ }
12975
+ }, [activeIndex]);
12976
+ return /* @__PURE__ */ import_react27.default.createElement(
12977
+ "div",
12978
+ {
12979
+ style: { top: position.top, left: position.left, position: "fixed", zIndex: 9999 },
12980
+ className: "bg-slate-900 border border-white/10 rounded-xl shadow-2xl py-1.5 min-w-[260px] max-h-[240px] overflow-y-auto custom-scrollbar animate-in fade-in zoom-in-95 duration-100",
12981
+ ref: listRef,
12982
+ onMouseDown: (e) => e.preventDefault()
12983
+ },
12984
+ filtered.length === 0 ? /* @__PURE__ */ import_react27.default.createElement("div", { className: "px-4 py-3 text-xs text-slate-500" }, "Nenhum resultado para", " ", /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-slate-300 font-medium" }, '"', query, '"')) : filtered.map((item, idx) => {
12985
+ const config = TYPE_CONFIG[item.type] || TYPE_CONFIG.node;
12986
+ const { Icon } = config;
12987
+ return /* @__PURE__ */ import_react27.default.createElement(
12988
+ "div",
12989
+ {
12990
+ key: item.id,
12991
+ onMouseDown: (e) => {
12992
+ e.preventDefault();
12993
+ onSelect(item);
12994
+ },
12995
+ onMouseEnter: () => setActiveIndex(idx),
12996
+ className: `flex items-center gap-2.5 px-3 py-2 cursor-pointer text-sm transition-colors duration-100 ${idx === activeIndex ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5"}`
12997
+ },
12998
+ /* @__PURE__ */ import_react27.default.createElement(Icon, { size: 13, className: config.color }),
12999
+ /* @__PURE__ */ import_react27.default.createElement("span", { className: "flex-1 truncate font-medium" }, item.searchLabel || "Sem Nome"),
13000
+ /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-[9px] px-1.5 py-0.5 rounded-full bg-white/5 text-slate-500 border border-white/5 uppercase tracking-wide shrink-0" }, config.label)
13001
+ );
13002
+ })
13003
+ );
13004
+ }
13005
+
13006
+ // src/components/RichGroupEditor.jsx
13007
+ var MENTION_BASE_STYLE = "display:inline-flex;align-items:center;padding:1px 7px;border-radius:5px;margin:0 2px;font-size:0.78em;font-weight:600;cursor:pointer;white-space:nowrap;vertical-align:middle;user-select:none;line-height:1.6;";
13008
+ var MENTION_TYPE_STYLE = {
13009
+ ancestry: "background:rgba(99,102,241,0.18);color:#a5b4fc;border:1px solid rgba(99,102,241,0.35);",
13010
+ quest: "background:rgba(16,185,129,0.18);color:#6ee7b7;border:1px solid rgba(16,185,129,0.35);",
13011
+ version: "background:rgba(245,158,11,0.18);color:#fcd34d;border:1px solid rgba(245,158,11,0.35);",
13012
+ node: "background:rgba(100,116,139,0.18);color:#94a3b8;border:1px solid rgba(100,116,139,0.35);"
13013
+ };
13014
+ function mentionStyle(type) {
13015
+ return MENTION_BASE_STYLE + (MENTION_TYPE_STYLE[type] || MENTION_TYPE_STYLE.node);
13016
+ }
13017
+ function escapeHtml(str) {
13018
+ return String(str || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
13019
+ }
13020
+ function contentToHTML(content) {
13021
+ if (!content || content.length === 0) return "";
13022
+ return content.map((seg) => {
13023
+ if (seg.type === "text") {
13024
+ return escapeHtml(seg.value).replace(/\n/g, "<br>");
13025
+ }
13026
+ if (seg.type === "mention") {
13027
+ const style = mentionStyle(seg.mentionType);
13028
+ return `<span contenteditable="false" data-mention="true" data-id="${escapeHtml(String(seg.id))}" data-name="${escapeHtml(seg.name || "")}" data-mention-type="${escapeHtml(seg.mentionType || "node")}" style="${style}" title="Clique para focar na cena">@${escapeHtml(seg.name || "")}</span>`;
13029
+ }
13030
+ return "";
13031
+ }).join("");
13032
+ }
13033
+ function domToContent(el) {
13034
+ const segments = [];
13035
+ function pushText(text) {
13036
+ const clean = text.replace(/\u200B/g, "");
13037
+ if (!clean) return;
13038
+ const last = segments[segments.length - 1];
13039
+ if (last && last.type === "text") {
13040
+ last.value += clean;
13041
+ } else {
13042
+ segments.push({ type: "text", value: clean });
13043
+ }
13044
+ }
13045
+ function walk(node) {
13046
+ var _a;
13047
+ if (node.nodeType === Node.TEXT_NODE) {
13048
+ pushText(node.textContent);
13049
+ } else if (node.nodeType === Node.ELEMENT_NODE) {
13050
+ if (((_a = node.dataset) == null ? void 0 : _a.mention) === "true") {
13051
+ segments.push({
13052
+ type: "mention",
13053
+ id: node.dataset.id,
13054
+ name: node.dataset.name,
13055
+ mentionType: node.dataset.mentionType
13056
+ });
13057
+ } else if (node.tagName === "BR") {
13058
+ pushText("\n");
13059
+ } else {
13060
+ if (["DIV", "P"].includes(node.tagName) && segments.length > 0) {
13061
+ pushText("\n");
13062
+ }
13063
+ node.childNodes.forEach(walk);
13064
+ }
13065
+ }
13066
+ }
13067
+ el.childNodes.forEach(walk);
13068
+ return segments;
13069
+ }
13070
+ function RichGroupEditor({
13071
+ content,
13072
+ onChange,
13073
+ onMentionClick,
13074
+ searchItems,
13075
+ readOnly,
13076
+ placeholder
13077
+ }) {
13078
+ const editorRef = (0, import_react28.useRef)(null);
13079
+ const isMountedRef = (0, import_react28.useRef)(false);
13080
+ const [mentionState, setMentionState] = (0, import_react28.useState)(null);
13081
+ const [isEmpty, setIsEmpty] = (0, import_react28.useState)(true);
13082
+ (0, import_react28.useEffect)(() => {
13083
+ if (!isMountedRef.current && editorRef.current) {
13084
+ editorRef.current.innerHTML = contentToHTML(content);
13085
+ const hasContent = !!editorRef.current.innerText.replace(/\u200B/g, "").trim();
13086
+ const hasMentions = !!editorRef.current.querySelector("[data-mention]");
13087
+ setIsEmpty(!hasContent && !hasMentions);
13088
+ isMountedRef.current = true;
13089
+ }
13090
+ }, []);
13091
+ const getMentionContext = (0, import_react28.useCallback)(() => {
13092
+ const selection = window.getSelection();
13093
+ if (!selection || selection.rangeCount === 0) return null;
13094
+ const range = selection.getRangeAt(0);
13095
+ if (range.startContainer.nodeType !== Node.TEXT_NODE) return null;
13096
+ const textBefore = range.startContainer.textContent.substring(0, range.startOffset);
13097
+ const atIndex = textBefore.lastIndexOf("@");
13098
+ if (atIndex === -1) return null;
13099
+ const query = textBefore.substring(atIndex + 1);
13100
+ if (query.includes(" ") || query.length > 40) return null;
13101
+ const rect = range.getBoundingClientRect();
13102
+ return {
13103
+ query,
13104
+ position: { top: rect.bottom + 6, left: rect.left }
13105
+ };
13106
+ }, []);
13107
+ const handleInput = (0, import_react28.useCallback)(() => {
13108
+ if (!editorRef.current) return;
13109
+ const serialized = domToContent(editorRef.current);
13110
+ onChange(serialized);
13111
+ const text = editorRef.current.innerText.replace(/\u200B/g, "").trim();
13112
+ const hasMentions = !!editorRef.current.querySelector("[data-mention]");
13113
+ setIsEmpty(!text && !hasMentions);
13114
+ const ctx = getMentionContext();
13115
+ setMentionState(ctx);
13116
+ }, [onChange, getMentionContext]);
13117
+ const handleKeyDown = (0, import_react28.useCallback)(
13118
+ (e) => {
13119
+ if (mentionState && ["ArrowDown", "ArrowUp", "Enter", "Tab", "Escape"].includes(e.key)) {
13120
+ return;
13121
+ }
13122
+ if (e.key === "Enter") {
13123
+ e.preventDefault();
13124
+ const sel = window.getSelection();
13125
+ const range = sel.getRangeAt(0);
13126
+ const br = document.createElement("br");
13127
+ range.deleteContents();
13128
+ range.insertNode(br);
13129
+ const afterBr = br.nextSibling || (() => {
13130
+ const zws = document.createTextNode("\u200B");
13131
+ br.parentNode.insertBefore(zws, br.nextSibling);
13132
+ return zws;
13133
+ })();
13134
+ const newRange = document.createRange();
13135
+ newRange.setStartBefore(afterBr);
13136
+ newRange.collapse(true);
13137
+ sel.removeAllRanges();
13138
+ sel.addRange(newRange);
13139
+ handleInput();
13140
+ }
13141
+ },
13142
+ [mentionState, handleInput]
13143
+ );
13144
+ const insertMention = (0, import_react28.useCallback)(
13145
+ (item) => {
13146
+ if (!editorRef.current) return;
13147
+ const sel = window.getSelection();
13148
+ if (!sel || sel.rangeCount === 0) return;
13149
+ const range = sel.getRangeAt(0);
13150
+ const textNode = range.startContainer;
13151
+ if (textNode.nodeType !== Node.TEXT_NODE) {
13152
+ setMentionState(null);
13153
+ return;
13154
+ }
13155
+ const cursorPos = range.startOffset;
13156
+ const textContent = textNode.textContent;
13157
+ const atIndex = textContent.lastIndexOf("@", cursorPos - 1);
13158
+ if (atIndex === -1) {
13159
+ setMentionState(null);
13160
+ return;
13161
+ }
13162
+ const before = textContent.substring(0, atIndex);
13163
+ const after = textContent.substring(cursorPos);
13164
+ textNode.textContent = before;
13165
+ const parent = textNode.parentNode;
13166
+ const nextSib = textNode.nextSibling;
13167
+ const span = document.createElement("span");
13168
+ span.contentEditable = "false";
13169
+ span.dataset.mention = "true";
13170
+ span.dataset.id = item.id;
13171
+ span.dataset.name = item.searchLabel || item.name || "";
13172
+ span.dataset.mentionType = item.type;
13173
+ span.style.cssText = mentionStyle(item.type);
13174
+ span.title = "Clique para focar na cena";
13175
+ span.textContent = `@${item.searchLabel || item.name || ""}`;
13176
+ parent.insertBefore(span, nextSib);
13177
+ const trailing = document.createTextNode(after || "\u200B");
13178
+ parent.insertBefore(trailing, span.nextSibling);
13179
+ const newRange = document.createRange();
13180
+ newRange.setStart(trailing, after ? 0 : 1);
13181
+ newRange.collapse(true);
13182
+ sel.removeAllRanges();
13183
+ sel.addRange(newRange);
13184
+ const serialized = domToContent(editorRef.current);
13185
+ onChange(serialized);
13186
+ setMentionState(null);
13187
+ setIsEmpty(false);
13188
+ },
13189
+ [onChange]
13190
+ );
13191
+ const handlePaste = (0, import_react28.useCallback)(
13192
+ (e) => {
13193
+ e.preventDefault();
13194
+ const text = e.clipboardData.getData("text/plain");
13195
+ if (text) {
13196
+ document.execCommand("insertText", false, text);
13197
+ handleInput();
13198
+ }
13199
+ },
13200
+ [handleInput]
13201
+ );
13202
+ const handleClick = (0, import_react28.useCallback)(
13203
+ (e) => {
13204
+ const chip = e.target.closest("[data-mention='true']");
13205
+ if (chip && onMentionClick) {
13206
+ e.stopPropagation();
13207
+ const id = chip.dataset.id;
13208
+ const full = searchItems == null ? void 0 : searchItems.find((i) => String(i.id) === String(id));
13209
+ if (full) {
13210
+ onMentionClick(full);
13211
+ } else {
13212
+ onMentionClick({
13213
+ id,
13214
+ name: chip.dataset.name,
13215
+ type: chip.dataset.mentionType,
13216
+ searchLabel: chip.dataset.name
13217
+ });
13218
+ }
13219
+ return;
13220
+ }
13221
+ setTimeout(() => {
13222
+ const ctx = getMentionContext();
13223
+ setMentionState(ctx);
13224
+ }, 0);
13225
+ },
13226
+ [onMentionClick, getMentionContext, searchItems]
13227
+ );
13228
+ const handleBlur = (0, import_react28.useCallback)(() => {
13229
+ setTimeout(() => setMentionState(null), 200);
13230
+ }, []);
13231
+ return /* @__PURE__ */ import_react28.default.createElement("div", { className: "relative" }, isEmpty && !readOnly && /* @__PURE__ */ import_react28.default.createElement("div", { className: "absolute top-0 left-0 text-sm text-slate-600 pointer-events-none select-none" }, placeholder || "Escreva sobre este grupo\u2026 ou digite @ para mencionar"), /* @__PURE__ */ import_react28.default.createElement(
13232
+ "div",
13233
+ {
13234
+ ref: editorRef,
13235
+ contentEditable: readOnly ? "false" : "true",
13236
+ suppressContentEditableWarning: true,
13237
+ onInput: handleInput,
13238
+ onKeyDown: handleKeyDown,
13239
+ onPaste: handlePaste,
13240
+ onClick: handleClick,
13241
+ onBlur: handleBlur,
13242
+ className: `w-full min-h-[1.5rem] max-h-[250px] overflow-y-auto text-sm text-slate-200 focus:outline-none leading-relaxed ${!readOnly ? "cursor-text" : "cursor-default"}`,
13243
+ style: { overflowWrap: "break-word", wordBreak: "break-word" }
13244
+ }
13245
+ ), mentionState && !readOnly && /* @__PURE__ */ import_react28.default.createElement(
13246
+ MentionPopover,
13247
+ {
13248
+ query: mentionState.query,
13249
+ items: searchItems || [],
13250
+ position: mentionState.position,
13251
+ onSelect: insertMention,
13252
+ onClose: () => setMentionState(null)
13253
+ }
13254
+ ));
13255
+ }
13256
+
13257
+ // src/components/AncestryBoard.jsx
12925
13258
  var GroupItem = ({
12926
13259
  group,
12927
13260
  index,
12928
- siblings,
12929
13261
  onUpdate,
12930
13262
  onDelete,
12931
13263
  onAddSubgroup,
12932
13264
  onIndent,
12933
13265
  onOutdent,
12934
- onRemoveAncestry,
12935
- onRequestPickAncestry,
12936
- pickingGroupId,
12937
- onPlayAncestry,
12938
- availableIds,
13266
+ searchItems,
13267
+ onMentionClick,
12939
13268
  canEdit
12940
13269
  }) => {
12941
13270
  const canIndent = index > 0;
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
- }
13271
+ const handleContentChange = (content) => {
13272
+ onUpdate(group.id, { ...group, content });
12950
13273
  };
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(
12955
- "div",
13274
+ return /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col gap-2 py-2 px-3 transition-all duration-200 hover:bg-white/5 border-l-2 border-transparent hover:border-white/20" }, /* @__PURE__ */ import_react29.default.createElement(
13275
+ RichGroupEditor,
12956
13276
  {
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
- `
13277
+ content: group.content,
13278
+ onChange: handleContentChange,
13279
+ onMentionClick,
13280
+ searchItems,
13281
+ readOnly: !canEdit,
13282
+ placeholder: "Escreva sobre este grupo\u2026 ou @ para mencionar"
13283
+ }
13284
+ ), canEdit && /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react29.default.createElement(
13285
+ "button",
13286
+ {
13287
+ onClick: () => onAddSubgroup(group.id),
13288
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13289
+ title: "Criar Subgrupo"
12961
13290
  },
12962
- /* @__PURE__ */ import_react27.default.createElement(
12963
- "textarea",
12964
- {
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"
12971
- },
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
- }
12978
- }
12979
- ),
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(
13038
- "button",
13039
- {
13040
- onClick: () => onAddSubgroup(group.id),
13041
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13042
- title: "Criar Subgrupo"
13043
- },
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(
13046
- "button",
13047
- {
13048
- onClick: () => onIndent(group.id),
13049
- disabled: !canIndent,
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"}`,
13051
- title: "Aninhar no grupo acima"
13052
- },
13053
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiArrowRight, { size: 14 })
13054
- ), /* @__PURE__ */ import_react27.default.createElement(
13055
- "button",
13056
- {
13057
- onClick: () => onOutdent(group.id),
13058
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13059
- title: "Desaninhar"
13060
- },
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(
13063
- "button",
13064
- {
13065
- onClick: () => onDelete(group.id),
13066
- className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13067
- title: "Remover Grupo"
13068
- },
13069
- /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiTrash2, { size: 14 })
13070
- )))
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(
13291
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiPlus, { size: 14 })
13292
+ )), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react29.default.createElement(
13293
+ "button",
13294
+ {
13295
+ onClick: () => onIndent(group.id),
13296
+ disabled: !canIndent,
13297
+ className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13298
+ title: "Aninhar no grupo acima"
13299
+ },
13300
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowRight, { size: 14 })
13301
+ ), /* @__PURE__ */ import_react29.default.createElement(
13302
+ "button",
13303
+ {
13304
+ onClick: () => onOutdent(group.id),
13305
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13306
+ title: "Desaninhar"
13307
+ },
13308
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowLeft, { size: 14 })
13309
+ ), /* @__PURE__ */ import_react29.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react29.default.createElement(
13310
+ "button",
13311
+ {
13312
+ onClick: () => onDelete(group.id),
13313
+ className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13314
+ title: "Remover Grupo"
13315
+ },
13316
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiTrash2, { size: 14 })
13317
+ )))), group.children && group.children.length > 0 && /* @__PURE__ */ import_react29.default.createElement("div", { className: "ml-2" }, group.children.map((child, idx) => /* @__PURE__ */ import_react29.default.createElement(
13072
13318
  GroupItem,
13073
13319
  {
13074
- key: childGroup.id,
13320
+ key: child.id,
13075
13321
  index: idx,
13076
- group: childGroup,
13077
- siblings: group.children,
13322
+ group: child,
13078
13323
  onUpdate,
13079
13324
  onDelete,
13080
13325
  onAddSubgroup,
13081
13326
  onIndent,
13082
13327
  onOutdent,
13083
- onRemoveAncestry,
13084
- onRequestPickAncestry,
13085
- pickingGroupId,
13086
- onPlayAncestry,
13087
- availableIds,
13328
+ searchItems,
13329
+ onMentionClick,
13088
13330
  canEdit
13089
13331
  }
13090
13332
  ))));
@@ -13098,40 +13340,32 @@ function AncestryBoard({
13098
13340
  initialGroups = [],
13099
13341
  onSave,
13100
13342
  userRole
13101
- // [NOVO] Recebe a role do usuário
13102
13343
  }) {
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)(() => {
13109
- return userRole !== "viewer";
13110
- }, [userRole]);
13111
- (0, import_react27.useEffect)(() => {
13344
+ const [searchTerm, setSearchTerm] = (0, import_react29.useState)("");
13345
+ const [groups, setGroups] = (0, import_react29.useState)([]);
13346
+ const [isLoaded, setIsLoaded] = (0, import_react29.useState)(false);
13347
+ const [saveStatus, setSaveStatus] = (0, import_react29.useState)("idle");
13348
+ const canEdit = (0, import_react29.useMemo)(() => userRole !== "viewer", [userRole]);
13349
+ (0, import_react29.useEffect)(() => {
13112
13350
  if (initialGroups && !isLoaded) {
13113
- setGroups(initialGroups);
13351
+ const migrate = (list) => list.map((g) => ({
13352
+ id: g.id || (0, import_uuid11.v4)(),
13353
+ content: Array.isArray(g.content) ? g.content : [],
13354
+ // descarta dados legados
13355
+ children: migrate(g.children || [])
13356
+ }));
13357
+ setGroups(migrate(initialGroups));
13114
13358
  setIsLoaded(true);
13115
13359
  }
13116
13360
  }, [initialGroups, isLoaded]);
13117
- const nodeNamesMap = (0, import_react27.useMemo)(() => {
13361
+ const nodeNamesMap = (0, import_react29.useMemo)(() => {
13118
13362
  const map = /* @__PURE__ */ new Map();
13119
- if (availableNodes && Array.isArray(availableNodes)) {
13120
- availableNodes.forEach((node) => {
13121
- if (node && node.id) {
13122
- map.set(String(node.id), node.name);
13123
- }
13124
- });
13125
- }
13363
+ availableNodes.forEach((n) => {
13364
+ if (n == null ? void 0 : n.id) map.set(String(n.id), n.name);
13365
+ });
13126
13366
  return map;
13127
13367
  }, [availableNodes]);
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)(() => {
13368
+ const allSearchableItems = (0, import_react29.useMemo)(() => {
13135
13369
  const items = [];
13136
13370
  availableAncestries.forEach((anc) => {
13137
13371
  items.push({
@@ -13157,117 +13391,76 @@ function AncestryBoard({
13157
13391
  });
13158
13392
  return items;
13159
13393
  }, [availableAncestries, availableNodes]);
13160
- const sanitizeGroups = (groupList) => {
13161
- return groupList.map((g) => ({
13162
- id: g.id,
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
- })),
13170
- children: sanitizeGroups(g.children || [])
13171
- }));
13172
- };
13173
- (0, import_react27.useEffect)(() => {
13394
+ const filtered = (0, import_react29.useMemo)(() => {
13395
+ const term = searchTerm.toLowerCase().trim();
13396
+ return allSearchableItems.filter((item) => {
13397
+ if (!term) return true;
13398
+ const labelMatch = (item.searchLabel || "").toLowerCase().includes(term);
13399
+ const descMatch = (item.searchDesc || "").toLowerCase().includes(term);
13400
+ let parentMatch = false;
13401
+ if (item.type === "ancestry") {
13402
+ const parentName = nodeNamesMap.get(String(item.ancestral_node)) || "";
13403
+ parentMatch = parentName.toLowerCase().includes(term);
13404
+ }
13405
+ return labelMatch || descMatch || parentMatch;
13406
+ });
13407
+ }, [allSearchableItems, searchTerm, nodeNamesMap]);
13408
+ const sanitizeGroups = (list) => list.map((g) => ({
13409
+ id: g.id,
13410
+ content: g.content || [],
13411
+ children: sanitizeGroups(g.children || [])
13412
+ }));
13413
+ (0, import_react29.useEffect)(() => {
13174
13414
  if (!isLoaded || !onSave) return;
13175
- const timeoutId = setTimeout(async () => {
13415
+ const id = setTimeout(async () => {
13176
13416
  setSaveStatus("saving");
13177
- const cleanData = sanitizeGroups(groups);
13178
13417
  try {
13179
- await onSave(cleanData);
13418
+ await onSave(sanitizeGroups(groups));
13180
13419
  setSaveStatus("saved");
13181
- setTimeout(() => {
13182
- setSaveStatus("idle");
13183
- }, 3e3);
13184
- } catch (error) {
13185
- console.error("Erro ao salvar board:", error);
13420
+ setTimeout(() => setSaveStatus("idle"), 3e3);
13421
+ } catch (err) {
13422
+ console.error("Erro ao salvar board:", err);
13186
13423
  setSaveStatus("error");
13187
13424
  }
13188
13425
  }, 3e3);
13189
- return () => clearTimeout(timeoutId);
13426
+ return () => clearTimeout(id);
13190
13427
  }, [groups, isLoaded, onSave]);
13191
- (0, import_react27.useEffect)(() => {
13428
+ (0, import_react29.useEffect)(() => {
13192
13429
  if (!isOpen) return;
13193
- const handleKeyDown = (e) => {
13430
+ const handler = (e) => {
13194
13431
  if (e.key === "Escape") {
13195
- if (pickingGroupId) {
13196
- setPickingGroupId(null);
13197
- } else {
13198
- onClose();
13199
- }
13432
+ onClose();
13200
13433
  e.preventDefault();
13201
13434
  e.stopPropagation();
13202
13435
  }
13203
13436
  };
13204
- window.addEventListener("keydown", handleKeyDown);
13205
- return () => window.removeEventListener("keydown", handleKeyDown);
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]);
13437
+ window.addEventListener("keydown", handler);
13438
+ return () => window.removeEventListener("keydown", handler);
13439
+ }, [isOpen, onClose]);
13222
13440
  const handleAddRootGroup = () => {
13223
- const newGroup = {
13224
- id: (0, import_uuid11.v4)(),
13225
- text: "",
13226
- ancestries: [],
13227
- children: []
13228
- };
13229
- setGroups((prev) => [newGroup, ...prev]);
13441
+ setGroups((prev) => [{ id: (0, import_uuid11.v4)(), content: [], children: [] }, ...prev]);
13230
13442
  };
13231
13443
  const handleAddSubgroup = (parentId) => {
13232
- const newGroup = {
13233
- id: (0, import_uuid11.v4)(),
13234
- text: "",
13235
- ancestries: [],
13236
- children: []
13237
- };
13238
- const addRecursive = (list) => {
13239
- return list.map((g) => {
13240
- if (g.id === parentId) {
13241
- return { ...g, children: [newGroup, ...g.children] };
13242
- }
13243
- return { ...g, children: addRecursive(g.children) };
13244
- });
13245
- };
13246
- setGroups((prev) => addRecursive(prev));
13444
+ const newGroup = { id: (0, import_uuid11.v4)(), content: [], children: [] };
13445
+ const add = (list) => list.map(
13446
+ (g) => g.id === parentId ? { ...g, children: [newGroup, ...g.children] } : { ...g, children: add(g.children) }
13447
+ );
13448
+ setGroups((prev) => add(prev));
13247
13449
  };
13248
13450
  const handleUpdateGroup = (id, newData) => {
13249
- const updateRecursive = (list) => {
13250
- return list.map((g) => {
13251
- if (g.id === id) return newData;
13252
- return { ...g, children: updateRecursive(g.children) };
13253
- });
13254
- };
13255
- setGroups((prev) => updateRecursive(prev));
13451
+ const update = (list) => list.map(
13452
+ (g) => g.id === id ? newData : { ...g, children: update(g.children) }
13453
+ );
13454
+ setGroups((prev) => update(prev));
13256
13455
  };
13257
13456
  const handleDeleteGroup = (id) => {
13258
- const deleteRecursive = (list) => {
13259
- return list.filter((g) => g.id !== id).map((g) => ({
13260
- ...g,
13261
- children: deleteRecursive(g.children)
13262
- }));
13263
- };
13264
- setGroups((prev) => deleteRecursive(prev));
13457
+ const del = (list) => list.filter((g) => g.id !== id).map((g) => ({ ...g, children: del(g.children) }));
13458
+ setGroups((prev) => del(prev));
13265
13459
  };
13266
13460
  const findGroupAndParent = (list, targetId, parent = null) => {
13267
13461
  for (let i = 0; i < list.length; i++) {
13268
- if (list[i].id === targetId) {
13462
+ if (list[i].id === targetId)
13269
13463
  return { group: list[i], parent, index: i, siblings: list };
13270
- }
13271
13464
  if (list[i].children.length > 0) {
13272
13465
  const found = findGroupAndParent(list[i].children, targetId, list[i]);
13273
13466
  if (found) return found;
@@ -13277,221 +13470,120 @@ function AncestryBoard({
13277
13470
  };
13278
13471
  const handleIndent = (id) => {
13279
13472
  setGroups((prev) => {
13280
- const newList = JSON.parse(JSON.stringify(prev));
13281
- const found = findGroupAndParent(newList, id);
13473
+ const next = JSON.parse(JSON.stringify(prev));
13474
+ const found = findGroupAndParent(next, id);
13282
13475
  if (!found || found.index === 0) return prev;
13283
13476
  const { group, siblings, index } = found;
13284
- const prevSibling = siblings[index - 1];
13285
13477
  siblings.splice(index, 1);
13286
- prevSibling.children.push(group);
13287
- return newList;
13478
+ siblings[index - 1].children.push(group);
13479
+ return next;
13288
13480
  });
13289
13481
  };
13290
13482
  const handleOutdent = (id) => {
13291
13483
  setGroups((prev) => {
13292
- const newList = JSON.parse(JSON.stringify(prev));
13293
- const found = findGroupAndParent(newList, id);
13484
+ const next = JSON.parse(JSON.stringify(prev));
13485
+ const found = findGroupAndParent(next, id);
13294
13486
  if (!found || !found.parent) return prev;
13295
13487
  const { group, siblings, index, parent } = found;
13296
13488
  siblings.splice(index, 1);
13297
- const parentFound = findGroupAndParent(newList, parent.id);
13489
+ const parentFound = findGroupAndParent(next, parent.id);
13298
13490
  if (parentFound) {
13299
13491
  parentFound.siblings.splice(parentFound.index + 1, 0, group);
13300
13492
  } else {
13301
- newList.push(group);
13493
+ next.push(group);
13302
13494
  }
13303
- return newList;
13495
+ return next;
13304
13496
  });
13305
13497
  };
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);
13338
- }
13339
- };
13340
- const handlePlayFromGroup = (ancestry) => {
13341
- if (ancestry && onSelect) {
13342
- onSelect(ancestry);
13343
- }
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
- });
13498
+ const handleMentionClick = (item) => {
13499
+ if (onSelect) onSelect(item);
13362
13500
  };
13363
13501
  if (!isOpen) return null;
13364
- return /* @__PURE__ */ import_react27.default.createElement(
13502
+ return /* @__PURE__ */ import_react29.default.createElement(
13365
13503
  "div",
13366
13504
  {
13367
13505
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
13368
13506
  onClick: onClose
13369
13507
  },
13370
- /* @__PURE__ */ import_react27.default.createElement(
13508
+ /* @__PURE__ */ import_react29.default.createElement(
13371
13509
  "div",
13372
13510
  {
13373
13511
  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",
13374
13512
  onClick: (e) => e.stopPropagation()
13375
13513
  },
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,
13378
- {
13379
- className: "animate-spin text-indigo-400",
13380
- size: 12
13381
- }
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(
13514
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react29.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiLoader, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ import_react29.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ import_react29.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, /* @__PURE__ */ import_react29.default.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ import_react29.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-3" }, canEdit && /* @__PURE__ */ import_react29.default.createElement(
13383
13515
  "button",
13384
13516
  {
13385
13517
  onClick: handleAddRootGroup,
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 "
13518
+ className: "flex items-center gap-2 px-3 py-1.5 bg-white/5 hover:bg-white/10 border border-white/10 hover:border-white/20 backdrop-blur-sm text-slate-200 hover:text-white rounded-md transition-all duration-200 text-xs font-medium shadow-sm"
13387
13519
  },
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(
13520
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiPlus, { size: 14, className: "text-indigo-400" }),
13521
+ /* @__PURE__ */ import_react29.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13522
+ ), /* @__PURE__ */ import_react29.default.createElement(
13391
13523
  "button",
13392
13524
  {
13393
13525
  onClick: onClose,
13394
13526
  className: "w-8 h-8 rounded-lg flex items-center justify-center text-slate-400 hover:text-white hover:bg-white/10 transition-colors"
13395
13527
  },
13396
- "\xD7"
13528
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiX, { size: 16 })
13397
13529
  ))),
13398
- /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react27.default.createElement(
13399
- "div",
13530
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col border-r border-white/10 w-[20%] min-w-[280px] max-w-[460px] bg-slate-900 flex-none" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "relative group" }, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiSearch, { className: "absolute left-3 top-1/2 -translate-y-1/2 text-slate-500 group-focus-within:text-indigo-400 transition-colors" }), /* @__PURE__ */ import_react29.default.createElement(
13531
+ "input",
13400
13532
  {
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
- `
13406
- },
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",
13533
+ type: "text",
13534
+ placeholder: "Navegar nas ancestralidades e nodes\u2026",
13535
+ className: "w-full rounded-md pl-9 pr-4 py-2 text-sm bg-slate-950 border border-white/10 text-slate-200 placeholder-slate-600 focus:outline-none focus:ring-1 focus:ring-indigo-500 transition-all",
13536
+ value: searchTerm,
13537
+ onChange: (e) => setSearchTerm(e.target.value),
13538
+ autoFocus: true
13539
+ }
13540
+ ))), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
13541
+ const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
13542
+ return /* @__PURE__ */ import_react29.default.createElement(
13543
+ "div",
13414
13544
  {
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",
13545
+ key: anc.id,
13546
+ className: "group relative flex items-start gap-3 p-3 text-left rounded-lg border border-white/5 bg-slate-800/40 hover:bg-indigo-600/10 hover:border-indigo-500/30 cursor-default transition-all duration-200"
13547
+ },
13548
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border bg-slate-800 border-white/5 group-hover:bg-indigo-500 group-hover:text-white transition-all shadow-lg" }, anc.type === "quest" ? /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiCheckSquare, { size: 14, className: "text-emerald-400 group-hover:text-white" }) : anc.type === "version" ? /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiGitBranch, { size: 14, className: "text-amber-400 group-hover:text-white" }) : anc.type === "node" ? /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiBox, { size: 14, className: "text-slate-400 group-hover:text-white" }) : /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiLayers, { size: 14, className: "text-indigo-400 group-hover:text-white" })),
13549
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react29.default.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, anc.searchLabel || "Sem Nome"), /* @__PURE__ */ import_react29.default.createElement("span", { className: "text-[9px] px-1.5 py-0.5 rounded-full bg-white/5 text-slate-500 border border-white/5 uppercase tracking-tighter" }, anc.type)), anc.type === "ancestry" && /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiCornerUpRight, { size: 10 }), /* @__PURE__ */ import_react29.default.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.searchDesc && /* @__PURE__ */ import_react29.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.searchDesc)),
13550
+ /* @__PURE__ */ import_react29.default.createElement(
13551
+ "button",
13431
13552
  {
13432
- key: anc.id,
13433
- onClick: () => {
13434
- if (isPicking) handleSelectAncestry(anc);
13553
+ onClick: (e) => {
13554
+ e.stopPropagation();
13555
+ if (onSelect) onSelect(anc);
13435
13556
  },
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
- `
13557
+ 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",
13558
+ title: "Focar no cen\xE1rio"
13440
13559
  },
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(
13560
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiPlay, { size: 14, className: "ml-0.5" }))
13561
+ )
13562
+ );
13563
+ }))), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-3 border-2 border-dashed border-white/5 rounded-xl m-4 bg-slate-900/20" }, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiLayers, { size: 24, className: "opacity-20" }), /* @__PURE__ */ import_react29.default.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ import_react29.default.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ import_react29.default.createElement(
13468
13564
  GroupItem,
13469
13565
  {
13470
13566
  key: group.id,
13471
13567
  index,
13472
13568
  group,
13473
- siblings: groups,
13474
13569
  onUpdate: handleUpdateGroup,
13475
13570
  onDelete: handleDeleteGroup,
13476
13571
  onAddSubgroup: handleAddSubgroup,
13477
13572
  onIndent: handleIndent,
13478
13573
  onOutdent: handleOutdent,
13479
- onRemoveAncestry: handleRemoveAncestryFromGroup,
13480
- onRequestPickAncestry: handleRequestPick,
13481
- pickingGroupId,
13482
- onPlayAncestry: handlePlayFromGroup,
13483
- availableIds,
13574
+ searchItems: allSearchableItems,
13575
+ onMentionClick: handleMentionClick,
13484
13576
  canEdit
13485
13577
  }
13486
13578
  ))))),
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"))
13579
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "px-5 py-2 border-t border-white/10 bg-slate-950/50 text-xs text-slate-500 flex justify-between flex-shrink-0" }, /* @__PURE__ */ import_react29.default.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ import_react29.default.createElement("span", null, groups.length, " grupos raiz"))
13488
13580
  )
13489
13581
  );
13490
13582
  }
13491
13583
 
13492
13584
  // src/components/MilestoneManager.jsx
13493
- var import_react28 = __toESM(require("react"));
13494
- var import_fi23 = require("react-icons/fi");
13585
+ var import_react30 = __toESM(require("react"));
13586
+ var import_fi24 = require("react-icons/fi");
13495
13587
  function MilestoneManager({
13496
13588
  isOpen,
13497
13589
  onClose,
@@ -13499,7 +13591,7 @@ function MilestoneManager({
13499
13591
  onUpdateMilestones = () => {
13500
13592
  }
13501
13593
  }) {
13502
- const [newMilestoneName, setNewMilestoneName] = (0, import_react28.useState)("");
13594
+ const [newMilestoneName, setNewMilestoneName] = (0, import_react30.useState)("");
13503
13595
  const handleAddMilestone = () => {
13504
13596
  if (!newMilestoneName.trim()) return;
13505
13597
  const newMilestone = {
@@ -13524,27 +13616,27 @@ function MilestoneManager({
13524
13616
  };
13525
13617
  if (!isOpen) return null;
13526
13618
  const swallow = (e) => e.stopPropagation();
13527
- return /* @__PURE__ */ import_react28.default.createElement(
13619
+ return /* @__PURE__ */ import_react30.default.createElement(
13528
13620
  "div",
13529
13621
  {
13530
13622
  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",
13531
13623
  onClick: onClose
13532
13624
  },
13533
- /* @__PURE__ */ import_react28.default.createElement(
13625
+ /* @__PURE__ */ import_react30.default.createElement(
13534
13626
  "div",
13535
13627
  {
13536
13628
  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",
13537
13629
  onClick: swallow
13538
13630
  },
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(
13631
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "px-6 py-4 border-b border-white/10 flex items-center justify-between" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "p-2 rounded-lg bg-indigo-500/20 text-indigo-400" }, /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiTarget, { size: 20 })), /* @__PURE__ */ import_react30.default.createElement("div", null, /* @__PURE__ */ import_react30.default.createElement("h2", { className: "text-lg font-semibold text-slate-100" }, "Milestones"), /* @__PURE__ */ import_react30.default.createElement("p", { className: "text-xs text-slate-400" }, "Gerencie os marcos do seu cen\xE1rio"))), /* @__PURE__ */ import_react30.default.createElement(
13540
13632
  "button",
13541
13633
  {
13542
13634
  onClick: onClose,
13543
13635
  className: "p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
13544
13636
  },
13545
- /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiX, { size: 20 })
13637
+ /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiX, { size: 20 })
13546
13638
  )),
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(
13639
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "px-6 py-5 bg-white/5 border-b border-white/5" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ import_react30.default.createElement(
13548
13640
  "input",
13549
13641
  {
13550
13642
  type: "text",
@@ -13554,47 +13646,47 @@ function MilestoneManager({
13554
13646
  placeholder: "Adicionar novo milestone...",
13555
13647
  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"
13556
13648
  }
13557
- ), /* @__PURE__ */ import_react28.default.createElement(
13649
+ ), /* @__PURE__ */ import_react30.default.createElement(
13558
13650
  "button",
13559
13651
  {
13560
13652
  onClick: handleAddMilestone,
13561
13653
  disabled: !newMilestoneName.trim(),
13562
13654
  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"
13563
13655
  },
13564
- /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiPlus, { size: 18 }),
13656
+ /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiPlus, { size: 18 }),
13565
13657
  "Adicionar"
13566
13658
  ))),
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(
13659
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex-1 overflow-y-auto px-6 py-4 custom-scrollbar" }, milestones.length > 0 ? /* @__PURE__ */ import_react30.default.createElement("div", { className: "space-y-3" }, milestones.map((ms) => /* @__PURE__ */ import_react30.default.createElement(
13568
13660
  "div",
13569
13661
  {
13570
13662
  key: ms.id,
13571
13663
  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]"}`
13572
13664
  },
13573
- /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ import_react28.default.createElement(
13665
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ import_react30.default.createElement(
13574
13666
  "div",
13575
13667
  {
13576
13668
  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"}`
13577
13669
  }
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(
13670
+ ), /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ import_react30.default.createElement("span", { className: `text-sm font-medium truncate ${ms.status === "active" ? "text-slate-100" : "text-slate-400 line-through"}` }, ms.name), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, ms.status === "active" ? "Ativo" : "Inativo"))),
13671
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react30.default.createElement(
13580
13672
  "button",
13581
13673
  {
13582
13674
  onClick: () => handleToggleMilestoneStatus(ms.id),
13583
13675
  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"}`,
13584
13676
  title: ms.status === "active" ? "Inativar" : "Ativar"
13585
13677
  },
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(
13678
+ ms.status === "active" ? /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiPauseCircle, { size: 18 }) : /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiPlayCircle, { size: 18 })
13679
+ ), /* @__PURE__ */ import_react30.default.createElement(
13588
13680
  "button",
13589
13681
  {
13590
13682
  onClick: () => handleRemoveMilestone(ms.id),
13591
13683
  className: "p-2 rounded-lg hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-all",
13592
13684
  title: "Remover"
13593
13685
  },
13594
- /* @__PURE__ */ import_react28.default.createElement(import_fi23.FiTrash2, { size: 18 })
13686
+ /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiTrash2, { size: 18 })
13595
13687
  ))
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))))
13688
+ ))) : /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-col items-center justify-center py-12 text-center" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "p-4 rounded-full bg-slate-800/30 text-slate-600 mb-4" }, /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiTarget, { size: 40 })), /* @__PURE__ */ import_react30.default.createElement("h3", { className: "text-slate-400 font-medium" }, "Nenhum milestone definido"), /* @__PURE__ */ import_react30.default.createElement("p", { className: "text-xs text-slate-600 max-w-[200px] mt-1 italic" }, "Defina marcos importantes para orientar o progresso do projeto."))),
13689
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "px-6 py-4 border-t border-white/5 bg-slate-900/50 flex items-center justify-between rounded-b-2xl" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex gap-4" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Total:"), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-xs font-bold text-slate-300" }, milestones.length)), /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Ativos:"), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-xs font-bold text-indigo-400" }, milestones.filter((m) => m.status === "active").length))))
13598
13690
  )
13599
13691
  );
13600
13692
  }
@@ -13681,12 +13773,12 @@ function XViewScene({
13681
13773
  get_view_members
13682
13774
  }) {
13683
13775
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
13684
- const { data: session, status } = (0, import_react30.useSession)();
13776
+ const { data: session, status } = (0, import_react32.useSession)();
13685
13777
  const router = (0, import_navigation.useRouter)();
13686
13778
  const searchParams = (0, import_navigation.useSearchParams)();
13687
13779
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
13688
13780
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
13689
- const viewParams = (0, import_react29.useMemo)(() => {
13781
+ const viewParams = (0, import_react31.useMemo)(() => {
13690
13782
  if (encryptedConfig) {
13691
13783
  const data = decryptData(encryptedConfig);
13692
13784
  if (data) {
@@ -13695,7 +13787,7 @@ function XViewScene({
13695
13787
  }
13696
13788
  return null;
13697
13789
  }, [encryptedConfig, session]);
13698
- (0, import_react29.useEffect)(() => {
13790
+ (0, import_react31.useEffect)(() => {
13699
13791
  async function verifyPermission() {
13700
13792
  if (!viewParams || !session || !check_user_permission) return;
13701
13793
  const { id, type, owner_id } = viewParams;
@@ -13732,65 +13824,65 @@ function XViewScene({
13732
13824
  setIsLoading(false);
13733
13825
  }
13734
13826
  }, [viewParams, session, status, check_user_permission]);
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)(() => {
13827
+ const sceneConfigId = (0, import_react31.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13828
+ const ownerId = (0, import_react31.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13829
+ const dbSaveUrl = (0, import_react31.useMemo)(() => {
13738
13830
  if (ownerId && sceneConfigId) {
13739
13831
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
13740
13832
  }
13741
13833
  return null;
13742
13834
  }, [ownerId, sceneConfigId]);
13743
- const sceneSaveUrl = (0, import_react29.useMemo)(() => {
13835
+ const sceneSaveUrl = (0, import_react31.useMemo)(() => {
13744
13836
  if (ownerId && sceneConfigId) {
13745
13837
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
13746
13838
  }
13747
13839
  return null;
13748
13840
  }, [ownerId, sceneConfigId]);
13749
- const ancestry_save_url = (0, import_react29.useMemo)(() => {
13841
+ const ancestry_save_url = (0, import_react31.useMemo)(() => {
13750
13842
  if (ownerId && sceneConfigId) {
13751
13843
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
13752
13844
  }
13753
13845
  return null;
13754
13846
  }, [ownerId, sceneConfigId]);
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)({
13847
+ const sceneDataRef = (0, import_react31.useRef)(null);
13848
+ const parentDataRef = (0, import_react31.useRef)(null);
13849
+ const ancestryDataRef = (0, import_react31.useRef)(null);
13850
+ const [isLoading, setIsLoading] = (0, import_react31.useState)(true);
13851
+ const [permissionStatus, setPermissionStatus] = (0, import_react31.useState)("loading");
13852
+ const [userPermissionRole, setUserPermissionRole] = (0, import_react31.useState)(null);
13853
+ const [viewMembers, setViewMembers] = (0, import_react31.useState)([]);
13854
+ const [isInitialized, setIsInitialized] = (0, import_react31.useState)(false);
13855
+ const [sceneVersion, setSceneVersion] = (0, import_react31.useState)(0);
13856
+ const [contextMenu, setContextMenu] = (0, import_react31.useState)({
13765
13857
  visible: false,
13766
13858
  x: 0,
13767
13859
  y: 0,
13768
13860
  nodeData: null
13769
13861
  });
13770
- const [multiContextMenu, setMultiContextMenu] = (0, import_react29.useState)({
13862
+ const [multiContextMenu, setMultiContextMenu] = (0, import_react31.useState)({
13771
13863
  visible: false,
13772
13864
  x: 0,
13773
13865
  y: 0,
13774
13866
  nodeIds: null
13775
13867
  });
13776
- const [relationshipMenu, setRelationshipMenu] = (0, import_react29.useState)({
13868
+ const [relationshipMenu, setRelationshipMenu] = (0, import_react31.useState)({
13777
13869
  visible: false,
13778
13870
  x: 0,
13779
13871
  y: 0,
13780
13872
  linkObject: null
13781
13873
  });
13782
- const [creationMode, setCreationMode] = (0, import_react29.useState)({
13874
+ const [creationMode, setCreationMode] = (0, import_react31.useState)({
13783
13875
  isActive: false,
13784
13876
  sourceNodeData: null
13785
13877
  });
13786
- const [versionMode, setVersionMode] = (0, import_react29.useState)({
13878
+ const [versionMode, setVersionMode] = (0, import_react31.useState)({
13787
13879
  isActive: false,
13788
13880
  sourceNodeData: null
13789
13881
  });
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)({
13882
+ const [questMode, setQuestMode] = (0, import_react31.useState)({ isActive: false });
13883
+ const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react31.useState)(false);
13884
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react31.useState)(false);
13885
+ const [ancestryMode, setAncestryMode] = (0, import_react31.useState)({
13794
13886
  isActive: false,
13795
13887
  tree: null,
13796
13888
  selectedParentId: null,
@@ -13801,42 +13893,42 @@ function XViewScene({
13801
13893
  ancestryDescriptionSections: [],
13802
13894
  isAddingNodes: false
13803
13895
  });
13804
- const [readingMode, setReadingMode] = (0, import_react29.useState)({
13896
+ const [readingMode, setReadingMode] = (0, import_react31.useState)({
13805
13897
  isActive: false,
13806
13898
  ancestry: null,
13807
13899
  branchStack: [],
13808
13900
  autoAbstraction: false
13809
13901
  });
13810
- const [formPosition, setFormPosition] = (0, import_react29.useState)({
13902
+ const [formPosition, setFormPosition] = (0, import_react31.useState)({
13811
13903
  left: 16,
13812
13904
  top: 16,
13813
13905
  opacity: 0
13814
13906
  });
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)({
13907
+ const [detailsNode, setDetailsNode] = (0, import_react31.useState)(null);
13908
+ const [detailsLink, setDetailsLink] = (0, import_react31.useState)(null);
13909
+ const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react31.useState)(null);
13910
+ const [imageViewer, setImageViewer] = (0, import_react31.useState)({
13819
13911
  visible: false,
13820
13912
  images: [],
13821
13913
  startIndex: 0
13822
13914
  });
13823
- const [editingAncestryRel, setEditingAncestryRel] = (0, import_react29.useState)({
13915
+ const [editingAncestryRel, setEditingAncestryRel] = (0, import_react31.useState)({
13824
13916
  visible: false,
13825
13917
  data: null,
13826
13918
  path: null
13827
13919
  });
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)({
13920
+ const [isImportModalOpen, setIsImportModalOpen] = (0, import_react31.useState)(false);
13921
+ const [importSuccessMessage, setImportSuccessMessage] = (0, import_react31.useState)("");
13922
+ const [invalidTargetError, setInvalidTargetError] = (0, import_react31.useState)(null);
13923
+ const [highlightedNodeId, setHighlightedNodeId] = (0, import_react31.useState)(null);
13924
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react31.useState)(false);
13925
+ const [ancestryBoardData, setAncestryBoardData] = (0, import_react31.useState)([]);
13926
+ const [isSidebarOpen, setIsSidebarOpen] = (0, import_react31.useState)(false);
13927
+ const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = (0, import_react31.useState)(false);
13928
+ const mountRef = (0, import_react31.useRef)(null);
13929
+ const tooltipRef = (0, import_react31.useRef)(null);
13930
+ const formRef = (0, import_react31.useRef)(null);
13931
+ const stateRef = (0, import_react31.useRef)({
13840
13932
  readMode: {
13841
13933
  currentMaxIndex: 0,
13842
13934
  progressMap: {}
@@ -13900,10 +13992,10 @@ function XViewScene({
13900
13992
  minWidth: 320,
13901
13993
  maxWidth: maxReadPanelW
13902
13994
  });
13903
- (0, import_react29.useEffect)(() => {
13995
+ (0, import_react31.useEffect)(() => {
13904
13996
  stateRef.current.ancestry = ancestryMode;
13905
13997
  }, [ancestryMode]);
13906
- (0, import_react29.useEffect)(() => {
13998
+ (0, import_react31.useEffect)(() => {
13907
13999
  var _a2;
13908
14000
  if (!isInitialized) return;
13909
14001
  const map = /* @__PURE__ */ new Map();
@@ -13926,10 +14018,10 @@ function XViewScene({
13926
14018
  }
13927
14019
  stateRef.current.nodeIdToParentFileMap = map;
13928
14020
  }, [isInitialized, sceneVersion]);
13929
- const handleNavigateBack = (0, import_react29.useCallback)(() => {
14021
+ const handleNavigateBack = (0, import_react31.useCallback)(() => {
13930
14022
  router.push("/dashboard/scenes");
13931
14023
  }, [router]);
13932
- const handleConfirmImport = (0, import_react29.useCallback)(
14024
+ const handleConfirmImport = (0, import_react31.useCallback)(
13933
14025
  async (importPayload) => {
13934
14026
  var _a2, _b2;
13935
14027
  let files = [];
@@ -14057,7 +14149,7 @@ function XViewScene({
14057
14149
  const handleOpenImageViewer = (images, startIndex) => {
14058
14150
  setImageViewer({ visible: true, images, startIndex });
14059
14151
  };
14060
- const tweenToTarget = (0, import_react29.useCallback)(
14152
+ const tweenToTarget = (0, import_react31.useCallback)(
14061
14153
  (target, zoomFactor = 1, forcedDirection = null) => {
14062
14154
  const { camera, controls, tweenGroup } = stateRef.current;
14063
14155
  if (!camera || !controls || !tweenGroup) return;
@@ -14083,7 +14175,7 @@ function XViewScene({
14083
14175
  if (!t || typeof t.closest !== "function") return false;
14084
14176
  return !!t.closest(".ui-overlay");
14085
14177
  };
14086
- const buildFullAncestryTree = (0, import_react29.useCallback)(
14178
+ const buildFullAncestryTree = (0, import_react31.useCallback)(
14087
14179
  (idTree, nodes, ancestries = []) => {
14088
14180
  if (!idTree) return null;
14089
14181
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
@@ -14168,7 +14260,7 @@ function XViewScene({
14168
14260
  },
14169
14261
  []
14170
14262
  );
14171
- const handleActivateTimeline = (0, import_react29.useCallback)(() => {
14263
+ const handleActivateTimeline = (0, import_react31.useCallback)(() => {
14172
14264
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
14173
14265
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
14174
14266
  while (timelineIntervalsGroup.children.length > 0) {
@@ -14328,7 +14420,7 @@ function XViewScene({
14328
14420
  }
14329
14421
  });
14330
14422
  }, []);
14331
- const handleVersionTimeline = (0, import_react29.useCallback)((sourceMesh, versionMeshes) => {
14423
+ const handleVersionTimeline = (0, import_react31.useCallback)((sourceMesh, versionMeshes) => {
14332
14424
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
14333
14425
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
14334
14426
  return;
@@ -14465,7 +14557,7 @@ function XViewScene({
14465
14557
  }
14466
14558
  });
14467
14559
  }, []);
14468
- (0, import_react29.useEffect)(() => {
14560
+ (0, import_react31.useEffect)(() => {
14469
14561
  async function fetchAllData(configPath, ownerId2) {
14470
14562
  var _a2, _b2;
14471
14563
  if (!get_scene_view_data) {
@@ -14570,12 +14662,12 @@ function XViewScene({
14570
14662
  focusNodeId,
14571
14663
  focusAncestryId
14572
14664
  ]);
14573
- const isNodeInView = (0, import_react29.useCallback)((id) => {
14665
+ const isNodeInView = (0, import_react31.useCallback)((id) => {
14574
14666
  const key = String(id);
14575
14667
  const objs = stateRef.current.nodeObjects || {};
14576
14668
  return !!objs[key];
14577
14669
  }, []);
14578
- const addOrUpdateNodeMesh = (0, import_react29.useCallback)(
14670
+ const addOrUpdateNodeMesh = (0, import_react31.useCallback)(
14579
14671
  (nodeData, position, suppressVersionUpdate = false, forceShowQuestDate = false) => {
14580
14672
  const {
14581
14673
  graphGroup,
@@ -14616,7 +14708,7 @@ function XViewScene({
14616
14708
  },
14617
14709
  []
14618
14710
  );
14619
- const handleActivateQuestLens = (0, import_react29.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
14711
+ const handleActivateQuestLens = (0, import_react31.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
14620
14712
  var _a2;
14621
14713
  const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
14622
14714
  if (!nodeObjects || !tweenGroup || !graphGroup) return;
@@ -14830,7 +14922,7 @@ function XViewScene({
14830
14922
  camTween.start();
14831
14923
  }
14832
14924
  }, [addOrUpdateNodeMesh]);
14833
- (0, import_react29.useEffect)(() => {
14925
+ (0, import_react31.useEffect)(() => {
14834
14926
  if (!isInitialized || !sceneDataRef.current) return;
14835
14927
  const currentMount = mountRef.current;
14836
14928
  if (!currentMount) return;
@@ -15586,7 +15678,7 @@ function XViewScene({
15586
15678
  get_scene_view_data,
15587
15679
  save_view_data
15588
15680
  ]);
15589
- const handleGhostNodeImageChange = (0, import_react29.useCallback)((useImage, imageUrl) => {
15681
+ const handleGhostNodeImageChange = (0, import_react31.useCallback)((useImage, imageUrl) => {
15590
15682
  const {
15591
15683
  node: ghostNode,
15592
15684
  line: ghostLine,
@@ -15634,7 +15726,7 @@ function XViewScene({
15634
15726
  aura: newGhostNode.getObjectByName("aura")
15635
15727
  };
15636
15728
  }, []);
15637
- const handleGhostNodeIntensityChange = (0, import_react29.useCallback)((newIntensity) => {
15729
+ const handleGhostNodeIntensityChange = (0, import_react31.useCallback)((newIntensity) => {
15638
15730
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
15639
15731
  if (!ghostNode) return;
15640
15732
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -15655,7 +15747,7 @@ function XViewScene({
15655
15747
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
15656
15748
  }
15657
15749
  }, []);
15658
- const handleDetailNodeIntensityChange = (0, import_react29.useCallback)(
15750
+ const handleDetailNodeIntensityChange = (0, import_react31.useCallback)(
15659
15751
  (nodeId, newIntensity) => {
15660
15752
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
15661
15753
  if (!mesh) return;
@@ -15811,7 +15903,7 @@ function XViewScene({
15811
15903
  mountRef.current.style.cursor = "default";
15812
15904
  }
15813
15905
  };
15814
- const handleAncestryTreeUpdate = (0, import_react29.useCallback)((newTree, extraData = null) => {
15906
+ const handleAncestryTreeUpdate = (0, import_react31.useCallback)((newTree, extraData = null) => {
15815
15907
  setAncestryMode((prev) => {
15816
15908
  const prevTreeStr = JSON.stringify(prev.tree);
15817
15909
  const newTreeStr = JSON.stringify(newTree);
@@ -15834,7 +15926,7 @@ function XViewScene({
15834
15926
  };
15835
15927
  });
15836
15928
  }, []);
15837
- const actionHandlerContext = (0, import_react29.useMemo)(
15929
+ const actionHandlerContext = (0, import_react31.useMemo)(
15838
15930
  () => {
15839
15931
  var _a2;
15840
15932
  return {
@@ -15895,7 +15987,7 @@ function XViewScene({
15895
15987
  const handleStartVersioning = (nodeData) => {
15896
15988
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
15897
15989
  };
15898
- const handleStartQuestQuick = (0, import_react29.useCallback)((questNode) => {
15990
+ const handleStartQuestQuick = (0, import_react31.useCallback)((questNode) => {
15899
15991
  var _a2, _b2, _c2;
15900
15992
  if (!questNode || !actionHandlerContext) return;
15901
15993
  const allParentNodes = Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
@@ -15930,7 +16022,7 @@ function XViewScene({
15930
16022
  }
15931
16023
  setDetailsNode(updatedNode);
15932
16024
  }, [session, actionHandlerContext]);
15933
- const handleFinishQuestQuick = (0, import_react29.useCallback)((questNode) => {
16025
+ const handleFinishQuestQuick = (0, import_react31.useCallback)((questNode) => {
15934
16026
  var _a2, _b2, _c2, _d2;
15935
16027
  if (!questNode || !actionHandlerContext) return;
15936
16028
  const {
@@ -16004,7 +16096,7 @@ function XViewScene({
16004
16096
  setDetailsNode(null);
16005
16097
  }
16006
16098
  }, [session, actionHandlerContext, viewMembers, detailsNode]);
16007
- const handleCancelQuest = (0, import_react29.useCallback)(() => {
16099
+ const handleCancelQuest = (0, import_react31.useCallback)(() => {
16008
16100
  const { graphGroup, ghostElements } = stateRef.current;
16009
16101
  if (ghostElements.node && graphGroup) {
16010
16102
  if (ghostElements.node.userData.labelObject) {
@@ -16161,7 +16253,7 @@ function XViewScene({
16161
16253
  }
16162
16254
  userActionHandlers.handleCancelConnection(context);
16163
16255
  };
16164
- const handleClearAncestryVisuals = (0, import_react29.useCallback)((ancestryId) => {
16256
+ const handleClearAncestryVisuals = (0, import_react31.useCallback)((ancestryId) => {
16165
16257
  const { renderedAncestries, ancestryGroup } = stateRef.current;
16166
16258
  const renderIndex = renderedAncestries.findIndex(
16167
16259
  (a) => String(a.id) === String(ancestryId)
@@ -16179,7 +16271,7 @@ function XViewScene({
16179
16271
  );
16180
16272
  }
16181
16273
  }, []);
16182
- const handleRenderAncestry = (0, import_react29.useCallback)(
16274
+ const handleRenderAncestry = (0, import_react31.useCallback)(
16183
16275
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
16184
16276
  setContextMenu(
16185
16277
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16673,7 +16765,7 @@ function XViewScene({
16673
16765
  ancestryMode.isActive
16674
16766
  ]
16675
16767
  );
16676
- const handleRenderAbstractionTree = (0, import_react29.useCallback)(
16768
+ const handleRenderAbstractionTree = (0, import_react31.useCallback)(
16677
16769
  (ancestryObject, targetNodeId = null) => {
16678
16770
  setContextMenu(
16679
16771
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16761,7 +16853,7 @@ function XViewScene({
16761
16853
  handleClearAncestryVisuals
16762
16854
  ]
16763
16855
  );
16764
- const handleReadModeBranchNav = (0, import_react29.useCallback)(
16856
+ const handleReadModeBranchNav = (0, import_react31.useCallback)(
16765
16857
  (nodeId, action, direction = "right") => {
16766
16858
  const { ancestry, branchStack } = readingMode;
16767
16859
  if (!ancestry || !ancestry.tree) return;
@@ -16939,13 +17031,13 @@ function XViewScene({
16939
17031
  },
16940
17032
  [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
16941
17033
  );
16942
- const handleReadModeHighlight = (0, import_react29.useCallback)((nodeId) => {
17034
+ const handleReadModeHighlight = (0, import_react31.useCallback)((nodeId) => {
16943
17035
  if (stateRef.current.highlightedNodeId !== nodeId) {
16944
17036
  stateRef.current.highlightedNodeId = nodeId;
16945
17037
  }
16946
17038
  setHighlightedNodeId(nodeId);
16947
17039
  }, []);
16948
- const activeNodeBranches = (0, import_react29.useMemo)(() => {
17040
+ const activeNodeBranches = (0, import_react31.useMemo)(() => {
16949
17041
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
16950
17042
  return null;
16951
17043
  const fullTree = buildFullAncestryTree(
@@ -16989,7 +17081,7 @@ function XViewScene({
16989
17081
  readingMode.branchStack,
16990
17082
  ancestryDataRef.current
16991
17083
  ]);
16992
- const backNavigationInfo = (0, import_react29.useMemo)(() => {
17084
+ const backNavigationInfo = (0, import_react31.useMemo)(() => {
16993
17085
  const { branchStack } = readingMode;
16994
17086
  if (!branchStack || branchStack.length === 0) return null;
16995
17087
  const lastStep = branchStack[branchStack.length - 1];
@@ -17000,7 +17092,7 @@ function XViewScene({
17000
17092
  name: "Voltar para anterior"
17001
17093
  };
17002
17094
  }, [readingMode.branchStack]);
17003
- const getReadModeDisplayContext = (0, import_react29.useMemo)(() => {
17095
+ const getReadModeDisplayContext = (0, import_react31.useMemo)(() => {
17004
17096
  const { ancestry, branchStack } = readingMode;
17005
17097
  if (!ancestry) return null;
17006
17098
  if (branchStack.length === 0) {
@@ -17043,7 +17135,7 @@ function XViewScene({
17043
17135
  customProperties: branchProps
17044
17136
  };
17045
17137
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
17046
- const readModeAbstractionTree = (0, import_react29.useMemo)(() => {
17138
+ const readModeAbstractionTree = (0, import_react31.useMemo)(() => {
17047
17139
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
17048
17140
  return null;
17049
17141
  }
@@ -17062,7 +17154,7 @@ function XViewScene({
17062
17154
  buildFullAncestryTree,
17063
17155
  sceneVersion
17064
17156
  ]);
17065
- const handleStartReadingAncestry = (0, import_react29.useCallback)(
17157
+ const handleStartReadingAncestry = (0, import_react31.useCallback)(
17066
17158
  async (ancestryObject, renderMode = "full") => {
17067
17159
  setContextMenu(
17068
17160
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17105,7 +17197,7 @@ function XViewScene({
17105
17197
  },
17106
17198
  [handleRenderAncestry, handleRenderAbstractionTree]
17107
17199
  );
17108
- const handleReadModeSectionChange = (0, import_react29.useCallback)(
17200
+ const handleReadModeSectionChange = (0, import_react31.useCallback)(
17109
17201
  (activeSectionId) => {
17110
17202
  const { ancestry, branchStack } = readingMode;
17111
17203
  if (!ancestry || !readingMode.isActive) return;
@@ -17190,10 +17282,10 @@ function XViewScene({
17190
17282
  ancestryDataRef.current
17191
17283
  ]
17192
17284
  );
17193
- const handleCloseReadMode = (0, import_react29.useCallback)(() => {
17285
+ const handleCloseReadMode = (0, import_react31.useCallback)(() => {
17194
17286
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
17195
17287
  }, []);
17196
- const handleAncestrySectionChange = (0, import_react29.useCallback)(
17288
+ const handleAncestrySectionChange = (0, import_react31.useCallback)(
17197
17289
  (activeSectionId, ancestryOverride = null, rotation = 0) => {
17198
17290
  var _a2, _b2;
17199
17291
  const currentMode = stateRef.current.ancestry;
@@ -17255,7 +17347,7 @@ function XViewScene({
17255
17347
  },
17256
17348
  [handleRenderAncestry]
17257
17349
  );
17258
- const handleEditAncestry = (0, import_react29.useCallback)(
17350
+ const handleEditAncestry = (0, import_react31.useCallback)(
17259
17351
  async (ancestryObject) => {
17260
17352
  setContextMenu(
17261
17353
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17310,7 +17402,7 @@ function XViewScene({
17310
17402
  const handleSelectAncestryParent = (nodeId) => {
17311
17403
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
17312
17404
  };
17313
- const handleRemoveFromAncestry = (0, import_react29.useCallback)((pathToRemove) => {
17405
+ const handleRemoveFromAncestry = (0, import_react31.useCallback)((pathToRemove) => {
17314
17406
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
17315
17407
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
17316
17408
  return;
@@ -17335,7 +17427,7 @@ function XViewScene({
17335
17427
  return { ...prev, tree: newTree };
17336
17428
  });
17337
17429
  }, []);
17338
- const handleSaveAncestry = (0, import_react29.useCallback)(
17430
+ const handleSaveAncestry = (0, import_react31.useCallback)(
17339
17431
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
17340
17432
  const treeToUse = treeOverride || ancestryMode.tree;
17341
17433
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -17571,7 +17663,7 @@ function XViewScene({
17571
17663
  });
17572
17664
  setEditingAncestryRel({ visible: false, data: null, path: null });
17573
17665
  };
17574
- const handleDeleteAncestry = (0, import_react29.useCallback)(
17666
+ const handleDeleteAncestry = (0, import_react31.useCallback)(
17575
17667
  async (ancestryIdToDelete) => {
17576
17668
  if (!ancestryIdToDelete) {
17577
17669
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -17653,10 +17745,58 @@ function XViewScene({
17653
17745
  },
17654
17746
  [save_view_data, delete_file_action]
17655
17747
  );
17656
- const handleOpenAncestryBoard = (0, import_react29.useCallback)(() => {
17748
+ const handleOpenAncestryBoard = (0, import_react31.useCallback)(() => {
17657
17749
  setIsAncestryBoardOpen(true);
17658
17750
  }, []);
17659
- const handleSelectAncestryFromBoard = (0, import_react29.useCallback)(
17751
+ const allAvailableNodes = (0, import_react31.useMemo)(() => {
17752
+ if (!parentDataRef.current) return [];
17753
+ return Object.values(parentDataRef.current).flatMap(
17754
+ (fileData) => fileData.nodes || []
17755
+ );
17756
+ }, [sceneVersion, isInitialized]);
17757
+ const allAvailableAncestries = (0, import_react31.useMemo)(() => {
17758
+ return ancestryDataRef.current || [];
17759
+ }, [sceneVersion, isInitialized]);
17760
+ const handleOpenReference = (0, import_react31.useCallback)(
17761
+ (referenceData) => {
17762
+ const { type, id } = referenceData;
17763
+ if (type === "node") {
17764
+ const targetNode = allAvailableNodes.find(
17765
+ (n) => String(n.id) === String(id)
17766
+ );
17767
+ if (targetNode) {
17768
+ setAncestryLinkDetails(null);
17769
+ setDetailsLink(null);
17770
+ setDetailsNode(targetNode);
17771
+ const sceneMesh = stateRef.current.nodeObjects[String(id)];
17772
+ if (sceneMesh) {
17773
+ tweenToTarget(sceneMesh);
17774
+ }
17775
+ } else {
17776
+ alert("Node original n\xE3o encontrado neste contexto.");
17777
+ }
17778
+ } else if (type === "ancestry") {
17779
+ const targetAncestry = allAvailableAncestries.find(
17780
+ (a) => String(a.ancestry_id) === String(id)
17781
+ );
17782
+ if (targetAncestry) {
17783
+ setDetailsNode(null);
17784
+ setDetailsLink(null);
17785
+ setAncestryLinkDetails(null);
17786
+ handleEditAncestry(targetAncestry);
17787
+ } else {
17788
+ alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17789
+ }
17790
+ }
17791
+ },
17792
+ [
17793
+ allAvailableNodes,
17794
+ allAvailableAncestries,
17795
+ handleEditAncestry,
17796
+ tweenToTarget
17797
+ ]
17798
+ );
17799
+ const handleSelectAncestryFromBoard = (0, import_react31.useCallback)(
17660
17800
  (item) => {
17661
17801
  setIsAncestryBoardOpen(false);
17662
17802
  setIsSidebarOpen(false);
@@ -17668,7 +17808,7 @@ function XViewScene({
17668
17808
  },
17669
17809
  [handleStartReadingAncestry, handleOpenReference]
17670
17810
  );
17671
- const handleSaveAncestryBoard = (0, import_react29.useCallback)(
17811
+ const handleSaveAncestryBoard = (0, import_react31.useCallback)(
17672
17812
  async (groups) => {
17673
17813
  if (!sceneConfigId || !viewParams || !session) return;
17674
17814
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
@@ -17682,7 +17822,7 @@ function XViewScene({
17682
17822
  },
17683
17823
  [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
17684
17824
  );
17685
- const existingNodeTypes = (0, import_react29.useMemo)(() => {
17825
+ const existingNodeTypes = (0, import_react31.useMemo)(() => {
17686
17826
  if (!parentDataRef.current) {
17687
17827
  return [];
17688
17828
  }
@@ -17694,7 +17834,7 @@ function XViewScene({
17694
17834
  ).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
17695
17835
  return [...new Set(allTypes)];
17696
17836
  }, [parentDataRef.current, sceneVersion]);
17697
- const searchableDbNodes = (0, import_react29.useMemo)(() => {
17837
+ const searchableDbNodes = (0, import_react31.useMemo)(() => {
17698
17838
  if (!parentDataRef.current) {
17699
17839
  return [];
17700
17840
  }
@@ -17709,7 +17849,7 @@ function XViewScene({
17709
17849
  return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
17710
17850
  });
17711
17851
  }, [parentDataRef.current, sceneVersion]);
17712
- const handleAddExistingNode = (0, import_react29.useCallback)(
17852
+ const handleAddExistingNode = (0, import_react31.useCallback)(
17713
17853
  (nodeId) => {
17714
17854
  return userActionHandlers.handleAddExistingNodeById(
17715
17855
  actionHandlerContext,
@@ -17718,7 +17858,7 @@ function XViewScene({
17718
17858
  },
17719
17859
  [actionHandlerContext]
17720
17860
  );
17721
- const handleUpdateMilestones = (0, import_react29.useCallback)(
17861
+ const handleUpdateMilestones = (0, import_react31.useCallback)(
17722
17862
  async (newMilestones) => {
17723
17863
  var _a2, _b2, _c2;
17724
17864
  if (!sceneDataRef.current) return;
@@ -17764,7 +17904,7 @@ function XViewScene({
17764
17904
  viewParams == null ? void 0 : viewParams.type
17765
17905
  ]
17766
17906
  );
17767
- const handleSaveCurrentView = (0, import_react29.useCallback)(async () => {
17907
+ const handleSaveCurrentView = (0, import_react31.useCallback)(async () => {
17768
17908
  var _a2, _b2, _c2;
17769
17909
  const { nodeObjects, allLinks } = stateRef.current;
17770
17910
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
@@ -17807,61 +17947,13 @@ function XViewScene({
17807
17947
  console.error("Erro na chamada de save_view_data:", error);
17808
17948
  }
17809
17949
  }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
17810
- const allAvailableNodes = (0, import_react29.useMemo)(() => {
17811
- if (!parentDataRef.current) return [];
17812
- return Object.values(parentDataRef.current).flatMap(
17813
- (fileData) => fileData.nodes || []
17814
- );
17815
- }, [sceneVersion, isInitialized]);
17816
- const allAvailableAncestries = (0, import_react29.useMemo)(() => {
17817
- return ancestryDataRef.current || [];
17818
- }, [sceneVersion, isInitialized]);
17819
- const handleOpenReference = (0, import_react29.useCallback)(
17820
- (referenceData) => {
17821
- const { type, id } = referenceData;
17822
- if (type === "node") {
17823
- const targetNode = allAvailableNodes.find(
17824
- (n) => String(n.id) === String(id)
17825
- );
17826
- if (targetNode) {
17827
- setAncestryLinkDetails(null);
17828
- setDetailsLink(null);
17829
- setDetailsNode(targetNode);
17830
- const sceneMesh = stateRef.current.nodeObjects[String(id)];
17831
- if (sceneMesh) {
17832
- tweenToTarget(sceneMesh);
17833
- }
17834
- } else {
17835
- alert("Node original n\xE3o encontrado neste contexto.");
17836
- }
17837
- } else if (type === "ancestry") {
17838
- const targetAncestry = allAvailableAncestries.find(
17839
- (a) => String(a.ancestry_id) === String(id)
17840
- );
17841
- if (targetAncestry) {
17842
- setDetailsNode(null);
17843
- setDetailsLink(null);
17844
- setAncestryLinkDetails(null);
17845
- handleEditAncestry(targetAncestry);
17846
- } else {
17847
- alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17848
- }
17849
- }
17850
- },
17851
- [
17852
- allAvailableNodes,
17853
- allAvailableAncestries,
17854
- handleEditAncestry,
17855
- tweenToTarget
17856
- ]
17857
- );
17858
- const handleToggleAncestryAddMode = (0, import_react29.useCallback)(() => {
17950
+ const handleToggleAncestryAddMode = (0, import_react31.useCallback)(() => {
17859
17951
  setAncestryMode((prev) => ({
17860
17952
  ...prev,
17861
17953
  isAddingNodes: !prev.isAddingNodes
17862
17954
  }));
17863
17955
  }, []);
17864
- const handleFocusNode = (0, import_react29.useCallback)(
17956
+ const handleFocusNode = (0, import_react31.useCallback)(
17865
17957
  (nodeData) => {
17866
17958
  var _a2;
17867
17959
  if (!nodeData) return;
@@ -17877,7 +17969,7 @@ function XViewScene({
17877
17969
  },
17878
17970
  [tweenToTarget]
17879
17971
  );
17880
- const availableDatasets = (0, import_react29.useMemo)(() => {
17972
+ const availableDatasets = (0, import_react31.useMemo)(() => {
17881
17973
  if (!sceneDataRef.current || !parentDataRef.current) return [];
17882
17974
  return sceneDataRef.current.parent_dbs.map((db) => {
17883
17975
  var _a2;
@@ -17891,7 +17983,7 @@ function XViewScene({
17891
17983
  String(creationMode.sourceNodeData.id)
17892
17984
  )) == null ? void 0 : _b.parentFileId : null;
17893
17985
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
17894
- (0, import_react29.useEffect)(() => {
17986
+ (0, import_react31.useEffect)(() => {
17895
17987
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
17896
17988
  const nodeObjects = stateRef.current.nodeObjects || {};
17897
17989
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -17914,7 +18006,7 @@ function XViewScene({
17914
18006
  hasFocusedInitial,
17915
18007
  tweenToTarget
17916
18008
  ]);
17917
- (0, import_react29.useEffect)(() => {
18009
+ (0, import_react31.useEffect)(() => {
17918
18010
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
17919
18011
  const ancestries = ancestryDataRef.current || [];
17920
18012
  const targetAncestry = ancestries.find(
@@ -17939,7 +18031,7 @@ function XViewScene({
17939
18031
  hasOpenedInitialAncestry,
17940
18032
  handleStartReadingAncestry
17941
18033
  ]);
17942
- (0, import_react29.useEffect)(() => {
18034
+ (0, import_react31.useEffect)(() => {
17943
18035
  function handleKeyDown(event) {
17944
18036
  var _a2, _b2, _c2;
17945
18037
  const context = actionHandlerContext;
@@ -18062,10 +18154,10 @@ function XViewScene({
18062
18154
  // <-- handleCancelQuest adicionado aqui
18063
18155
  ]);
18064
18156
  if (isLoading || status === "loading" || permissionStatus === "loading") {
18065
- return /* @__PURE__ */ import_react29.default.createElement(LoadingScreen, null);
18157
+ return /* @__PURE__ */ import_react31.default.createElement(LoadingScreen, null);
18066
18158
  }
18067
18159
  if (permissionStatus === "denied") {
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(
18160
+ return /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react31.default.createElement(
18069
18161
  "svg",
18070
18162
  {
18071
18163
  xmlns: "http://www.w3.org/2000/svg",
@@ -18075,7 +18167,7 @@ function XViewScene({
18075
18167
  stroke: "currentColor",
18076
18168
  className: "w-16 h-16 mx-auto"
18077
18169
  },
18078
- /* @__PURE__ */ import_react29.default.createElement(
18170
+ /* @__PURE__ */ import_react31.default.createElement(
18079
18171
  "path",
18080
18172
  {
18081
18173
  strokeLinecap: "round",
@@ -18083,13 +18175,13 @@ function XViewScene({
18083
18175
  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"
18084
18176
  }
18085
18177
  )
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(
18178
+ )), /* @__PURE__ */ import_react31.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-slate-400 mb-6" }, "Voc\xEA n\xE3o tem permiss\xE3o para acessar este conte\xFAdo. Solicite acesso ao propriet\xE1rio ou verifique se est\xE1 na conta correta."), /* @__PURE__ */ import_react31.default.createElement(
18087
18179
  "button",
18088
18180
  {
18089
18181
  onClick: () => router.push("/dashboard/scenes"),
18090
18182
  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"
18091
18183
  },
18092
- /* @__PURE__ */ import_react29.default.createElement(
18184
+ /* @__PURE__ */ import_react31.default.createElement(
18093
18185
  "svg",
18094
18186
  {
18095
18187
  xmlns: "http://www.w3.org/2000/svg",
@@ -18099,7 +18191,7 @@ function XViewScene({
18099
18191
  stroke: "currentColor",
18100
18192
  className: "w-5 h-5"
18101
18193
  },
18102
- /* @__PURE__ */ import_react29.default.createElement(
18194
+ /* @__PURE__ */ import_react31.default.createElement(
18103
18195
  "path",
18104
18196
  {
18105
18197
  strokeLinecap: "round",
@@ -18111,7 +18203,7 @@ function XViewScene({
18111
18203
  "Voltar para Scenes"
18112
18204
  )));
18113
18205
  }
18114
- return /* @__PURE__ */ import_react29.default.createElement(
18206
+ return /* @__PURE__ */ import_react31.default.createElement(
18115
18207
  "div",
18116
18208
  {
18117
18209
  ref: mountRef,
@@ -18123,7 +18215,7 @@ function XViewScene({
18123
18215
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
18124
18216
  }
18125
18217
  },
18126
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react29.default.createElement(
18218
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react31.default.createElement(
18127
18219
  XViewSidebar,
18128
18220
  {
18129
18221
  dbNodes: searchableDbNodes,
@@ -18147,7 +18239,7 @@ function XViewScene({
18147
18239
  onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
18148
18240
  }
18149
18241
  ),
18150
- creationMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18242
+ creationMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
18151
18243
  InSceneCreationForm,
18152
18244
  {
18153
18245
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -18179,7 +18271,7 @@ function XViewScene({
18179
18271
  availableAncestries: allAvailableAncestries
18180
18272
  }
18181
18273
  ),
18182
- versionMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18274
+ versionMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
18183
18275
  InSceneVersionForm,
18184
18276
  {
18185
18277
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -18205,7 +18297,7 @@ function XViewScene({
18205
18297
  availableAncestries: allAvailableAncestries
18206
18298
  }
18207
18299
  ),
18208
- questMode.isActive && /* @__PURE__ */ import_react29.default.createElement(
18300
+ questMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
18209
18301
  InSceneQuestForm,
18210
18302
  {
18211
18303
  onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
@@ -18233,7 +18325,7 @@ function XViewScene({
18233
18325
  onUpdateMilestones: handleUpdateMilestones
18234
18326
  }
18235
18327
  ),
18236
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react29.default.createElement(
18328
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react31.default.createElement(
18237
18329
  "div",
18238
18330
  {
18239
18331
  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"}`,
@@ -18246,7 +18338,7 @@ function XViewScene({
18246
18338
  maxWidth: "92vw"
18247
18339
  }
18248
18340
  },
18249
- /* @__PURE__ */ import_react29.default.createElement(
18341
+ /* @__PURE__ */ import_react31.default.createElement(
18250
18342
  "div",
18251
18343
  {
18252
18344
  onPointerDown: (e) => {
@@ -18257,7 +18349,7 @@ function XViewScene({
18257
18349
  title: "Arraste para redimensionar"
18258
18350
  }
18259
18351
  ),
18260
- /* @__PURE__ */ import_react29.default.createElement(
18352
+ /* @__PURE__ */ import_react31.default.createElement(
18261
18353
  DescriptionReadModePanel,
18262
18354
  {
18263
18355
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -18292,7 +18384,7 @@ function XViewScene({
18292
18384
  }
18293
18385
  )
18294
18386
  ),
18295
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react29.default.createElement(
18387
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react31.default.createElement(
18296
18388
  CreateAncestryPanel,
18297
18389
  {
18298
18390
  ancestryMode,
@@ -18328,7 +18420,7 @@ function XViewScene({
18328
18420
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
18329
18421
  }
18330
18422
  ),
18331
- editingAncestryRel.visible && /* @__PURE__ */ import_react29.default.createElement(
18423
+ editingAncestryRel.visible && /* @__PURE__ */ import_react31.default.createElement(
18332
18424
  AncestryRelationshipPanel,
18333
18425
  {
18334
18426
  data: editingAncestryRel.data,
@@ -18342,7 +18434,7 @@ function XViewScene({
18342
18434
  onUploadFile: upload_file_action
18343
18435
  }
18344
18436
  ),
18345
- detailsNode && detailsNode.is_quest && /* @__PURE__ */ import_react29.default.createElement(
18437
+ detailsNode && detailsNode.is_quest && /* @__PURE__ */ import_react31.default.createElement(
18346
18438
  QuestDetailsPanel,
18347
18439
  {
18348
18440
  node: detailsNode,
@@ -18368,7 +18460,7 @@ function XViewScene({
18368
18460
  onUpdateMilestones: handleUpdateMilestones
18369
18461
  }
18370
18462
  ),
18371
- detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react29.default.createElement(
18463
+ detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react31.default.createElement(
18372
18464
  NodeDetailsPanel,
18373
18465
  {
18374
18466
  node: detailsNode,
@@ -18400,7 +18492,7 @@ function XViewScene({
18400
18492
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
18401
18493
  }
18402
18494
  ),
18403
- detailsLink && /* @__PURE__ */ import_react29.default.createElement(
18495
+ detailsLink && /* @__PURE__ */ import_react31.default.createElement(
18404
18496
  RelationshipDetailsPanel,
18405
18497
  {
18406
18498
  link: detailsLink,
@@ -18414,7 +18506,7 @@ function XViewScene({
18414
18506
  userRole: userPermissionRole
18415
18507
  }
18416
18508
  ),
18417
- ancestryLinkDetails && /* @__PURE__ */ import_react29.default.createElement(
18509
+ ancestryLinkDetails && /* @__PURE__ */ import_react31.default.createElement(
18418
18510
  AncestryLinkDetailsPanel,
18419
18511
  {
18420
18512
  data: ancestryLinkDetails,
@@ -18425,7 +18517,7 @@ function XViewScene({
18425
18517
  onUploadFile: upload_file_action
18426
18518
  }
18427
18519
  ),
18428
- /* @__PURE__ */ import_react29.default.createElement(
18520
+ /* @__PURE__ */ import_react31.default.createElement(
18429
18521
  "div",
18430
18522
  {
18431
18523
  ref: tooltipRef,
@@ -18452,7 +18544,7 @@ function XViewScene({
18452
18544
  }
18453
18545
  }
18454
18546
  ),
18455
- /* @__PURE__ */ import_react29.default.createElement(
18547
+ /* @__PURE__ */ import_react31.default.createElement(
18456
18548
  ContextMenu,
18457
18549
  {
18458
18550
  data: contextMenu,
@@ -18485,7 +18577,7 @@ function XViewScene({
18485
18577
  onFinishQuest: handleFinishQuestQuick
18486
18578
  }
18487
18579
  ),
18488
- /* @__PURE__ */ import_react29.default.createElement(
18580
+ /* @__PURE__ */ import_react31.default.createElement(
18489
18581
  MultiNodeContextMenu,
18490
18582
  {
18491
18583
  data: multiContextMenu,
@@ -18505,7 +18597,7 @@ function XViewScene({
18505
18597
  )
18506
18598
  }
18507
18599
  ),
18508
- /* @__PURE__ */ import_react29.default.createElement(
18600
+ /* @__PURE__ */ import_react31.default.createElement(
18509
18601
  RelationshipContextMenu,
18510
18602
  {
18511
18603
  data: relationshipMenu,
@@ -18523,14 +18615,14 @@ function XViewScene({
18523
18615
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
18524
18616
  }
18525
18617
  ),
18526
- /* @__PURE__ */ import_react29.default.createElement(
18618
+ /* @__PURE__ */ import_react31.default.createElement(
18527
18619
  ImageViewer,
18528
18620
  {
18529
18621
  data: imageViewer,
18530
18622
  onClose: () => setImageViewer({ ...imageViewer, visible: false })
18531
18623
  }
18532
18624
  ),
18533
- /* @__PURE__ */ import_react29.default.createElement(
18625
+ /* @__PURE__ */ import_react31.default.createElement(
18534
18626
  AncestryBoard,
18535
18627
  {
18536
18628
  isOpen: isAncestryBoardOpen,
@@ -18543,7 +18635,7 @@ function XViewScene({
18543
18635
  userRole: userPermissionRole
18544
18636
  }
18545
18637
  ),
18546
- /* @__PURE__ */ import_react29.default.createElement(
18638
+ /* @__PURE__ */ import_react31.default.createElement(
18547
18639
  MilestoneManager,
18548
18640
  {
18549
18641
  isOpen: isMilestoneManagerOpen,
@@ -18552,7 +18644,7 @@ function XViewScene({
18552
18644
  onUpdateMilestones: handleUpdateMilestones
18553
18645
  }
18554
18646
  ),
18555
- /* @__PURE__ */ import_react29.default.createElement(
18647
+ /* @__PURE__ */ import_react31.default.createElement(
18556
18648
  ImportParentFileModal,
18557
18649
  {
18558
18650
  isOpen: isImportModalOpen,
@@ -18565,7 +18657,7 @@ function XViewScene({
18565
18657
  currentAncestries: ancestryDataRef.current || []
18566
18658
  }
18567
18659
  ),
18568
- invalidTargetError && /* @__PURE__ */ import_react29.default.createElement(
18660
+ invalidTargetError && /* @__PURE__ */ import_react31.default.createElement(
18569
18661
  "div",
18570
18662
  {
18571
18663
  className: "ui-overlay",
@@ -18590,13 +18682,13 @@ function XViewScene({
18590
18682
  animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
18591
18683
  }
18592
18684
  },
18593
- /* @__PURE__ */ import_react29.default.createElement("style", null, `
18685
+ /* @__PURE__ */ import_react31.default.createElement("style", null, `
18594
18686
  @keyframes fadeInDown {
18595
18687
  from { opacity: 0; transform: translate(-50%, -20px); }
18596
18688
  to { opacity: 1; transform: translate(-50%, 0); }
18597
18689
  }
18598
18690
  `),
18599
- /* @__PURE__ */ import_react29.default.createElement(
18691
+ /* @__PURE__ */ import_react31.default.createElement(
18600
18692
  "svg",
18601
18693
  {
18602
18694
  width: "20",
@@ -18608,12 +18700,12 @@ function XViewScene({
18608
18700
  strokeLinecap: "round",
18609
18701
  strokeLinejoin: "round"
18610
18702
  },
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
+ /* @__PURE__ */ import_react31.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18704
+ /* @__PURE__ */ import_react31.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18705
+ /* @__PURE__ */ import_react31.default.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18614
18706
  ),
18615
- /* @__PURE__ */ import_react29.default.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18616
- /* @__PURE__ */ import_react29.default.createElement(
18707
+ /* @__PURE__ */ import_react31.default.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18708
+ /* @__PURE__ */ import_react31.default.createElement(
18617
18709
  "button",
18618
18710
  {
18619
18711
  onClick: () => setInvalidTargetError(null),