@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.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  // src/XViewScene.jsx
2
- import React28, {
3
- useCallback as useCallback4,
4
- useEffect as useEffect22,
5
- useRef as useRef19,
6
- useState as useState27,
7
- useMemo as useMemo12
2
+ import React30, {
3
+ useCallback as useCallback5,
4
+ useEffect as useEffect24,
5
+ useRef as useRef20,
6
+ useState as useState29,
7
+ useMemo as useMemo13
8
8
  } from "react";
9
9
  import { useRouter, useSearchParams } from "next/navigation";
10
10
  import { useSession } from "next-auth/react";
@@ -12950,10 +12950,10 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
12950
12950
  }
12951
12951
 
12952
12952
  // src/components/AncestryBoard.jsx
12953
- import React26, { useState as useState25, useMemo as useMemo11, useEffect as useEffect21, useRef as useRef18 } from "react";
12953
+ import React28, { useState as useState27, useMemo as useMemo12, useEffect as useEffect23 } from "react";
12954
12954
  import {
12955
12955
  FiSearch as FiSearch8,
12956
- FiLayers as FiLayers6,
12956
+ FiLayers as FiLayers7,
12957
12957
  FiCornerUpRight as FiCornerUpRight4,
12958
12958
  FiPlay,
12959
12959
  FiPlus as FiPlus10,
@@ -12963,175 +12963,416 @@ import {
12963
12963
  FiCheckCircle,
12964
12964
  FiLoader as FiLoader5,
12965
12965
  FiX as FiX8,
12966
- FiAlertTriangle,
12967
- FiBox,
12968
- FiCheckSquare as FiCheckSquare3,
12969
- FiGitBranch as FiGitBranch3
12966
+ FiBox as FiBox2,
12967
+ FiCheckSquare as FiCheckSquare4,
12968
+ FiGitBranch as FiGitBranch4
12970
12969
  } from "react-icons/fi";
12971
12970
  import { v4 as uuidv411 } from "uuid";
12971
+
12972
+ // src/components/RichGroupEditor.jsx
12973
+ import React27, { useEffect as useEffect22, useRef as useRef19, useState as useState26, useCallback as useCallback4 } from "react";
12974
+
12975
+ // src/components/MentionPopover.jsx
12976
+ import React26, { useEffect as useEffect21, useRef as useRef18, useState as useState25, useMemo as useMemo11 } from "react";
12977
+ import { FiLayers as FiLayers6, FiCheckSquare as FiCheckSquare3, FiGitBranch as FiGitBranch3, FiBox } from "react-icons/fi";
12978
+ var TYPE_CONFIG = {
12979
+ ancestry: { Icon: FiLayers6, color: "text-indigo-400", label: "Ancestralidade" },
12980
+ quest: { Icon: FiCheckSquare3, color: "text-emerald-400", label: "Quest" },
12981
+ version: { Icon: FiGitBranch3, color: "text-amber-400", label: "Vers\xE3o" },
12982
+ node: { Icon: FiBox, color: "text-slate-400", label: "Node" }
12983
+ };
12984
+ function MentionPopover({ query, items, position, onSelect, onClose }) {
12985
+ const [activeIndex, setActiveIndex] = useState25(0);
12986
+ const listRef = useRef18(null);
12987
+ const filtered = useMemo11(() => {
12988
+ const term = (query || "").toLowerCase().trim();
12989
+ if (!term) return items.slice(0, 8);
12990
+ return items.filter(
12991
+ (item) => (item.searchLabel || "").toLowerCase().includes(term) || (item.searchDesc || "").toLowerCase().includes(term)
12992
+ ).slice(0, 8);
12993
+ }, [items, query]);
12994
+ useEffect21(() => {
12995
+ setActiveIndex(0);
12996
+ }, [query]);
12997
+ useEffect21(() => {
12998
+ const handleKeyDown = (e) => {
12999
+ if (e.key === "ArrowDown") {
13000
+ e.preventDefault();
13001
+ setActiveIndex((i) => Math.min(i + 1, filtered.length - 1));
13002
+ } else if (e.key === "ArrowUp") {
13003
+ e.preventDefault();
13004
+ setActiveIndex((i) => Math.max(i - 1, 0));
13005
+ } else if (e.key === "Enter" || e.key === "Tab") {
13006
+ e.preventDefault();
13007
+ if (filtered[activeIndex]) onSelect(filtered[activeIndex]);
13008
+ } else if (e.key === "Escape") {
13009
+ e.preventDefault();
13010
+ onClose();
13011
+ }
13012
+ };
13013
+ window.addEventListener("keydown", handleKeyDown, true);
13014
+ return () => window.removeEventListener("keydown", handleKeyDown, true);
13015
+ }, [filtered, activeIndex, onSelect, onClose]);
13016
+ useEffect21(() => {
13017
+ if (listRef.current) {
13018
+ const el = listRef.current.children[activeIndex];
13019
+ if (el) el.scrollIntoView({ block: "nearest" });
13020
+ }
13021
+ }, [activeIndex]);
13022
+ return /* @__PURE__ */ React26.createElement(
13023
+ "div",
13024
+ {
13025
+ style: { top: position.top, left: position.left, position: "fixed", zIndex: 9999 },
13026
+ 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",
13027
+ ref: listRef,
13028
+ onMouseDown: (e) => e.preventDefault()
13029
+ },
13030
+ filtered.length === 0 ? /* @__PURE__ */ React26.createElement("div", { className: "px-4 py-3 text-xs text-slate-500" }, "Nenhum resultado para", " ", /* @__PURE__ */ React26.createElement("span", { className: "text-slate-300 font-medium" }, '"', query, '"')) : filtered.map((item, idx) => {
13031
+ const config = TYPE_CONFIG[item.type] || TYPE_CONFIG.node;
13032
+ const { Icon } = config;
13033
+ return /* @__PURE__ */ React26.createElement(
13034
+ "div",
13035
+ {
13036
+ key: item.id,
13037
+ onMouseDown: (e) => {
13038
+ e.preventDefault();
13039
+ onSelect(item);
13040
+ },
13041
+ onMouseEnter: () => setActiveIndex(idx),
13042
+ 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"}`
13043
+ },
13044
+ /* @__PURE__ */ React26.createElement(Icon, { size: 13, className: config.color }),
13045
+ /* @__PURE__ */ React26.createElement("span", { className: "flex-1 truncate font-medium" }, item.searchLabel || "Sem Nome"),
13046
+ /* @__PURE__ */ React26.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)
13047
+ );
13048
+ })
13049
+ );
13050
+ }
13051
+
13052
+ // src/components/RichGroupEditor.jsx
13053
+ 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;";
13054
+ var MENTION_TYPE_STYLE = {
13055
+ ancestry: "background:rgba(99,102,241,0.18);color:#a5b4fc;border:1px solid rgba(99,102,241,0.35);",
13056
+ quest: "background:rgba(16,185,129,0.18);color:#6ee7b7;border:1px solid rgba(16,185,129,0.35);",
13057
+ version: "background:rgba(245,158,11,0.18);color:#fcd34d;border:1px solid rgba(245,158,11,0.35);",
13058
+ node: "background:rgba(100,116,139,0.18);color:#94a3b8;border:1px solid rgba(100,116,139,0.35);"
13059
+ };
13060
+ function mentionStyle(type) {
13061
+ return MENTION_BASE_STYLE + (MENTION_TYPE_STYLE[type] || MENTION_TYPE_STYLE.node);
13062
+ }
13063
+ function escapeHtml(str) {
13064
+ return String(str || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
13065
+ }
13066
+ function contentToHTML(content) {
13067
+ if (!content || content.length === 0) return "";
13068
+ return content.map((seg) => {
13069
+ if (seg.type === "text") {
13070
+ return escapeHtml(seg.value).replace(/\n/g, "<br>");
13071
+ }
13072
+ if (seg.type === "mention") {
13073
+ const style = mentionStyle(seg.mentionType);
13074
+ 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>`;
13075
+ }
13076
+ return "";
13077
+ }).join("");
13078
+ }
13079
+ function domToContent(el) {
13080
+ const segments = [];
13081
+ function pushText(text) {
13082
+ const clean = text.replace(/\u200B/g, "");
13083
+ if (!clean) return;
13084
+ const last = segments[segments.length - 1];
13085
+ if (last && last.type === "text") {
13086
+ last.value += clean;
13087
+ } else {
13088
+ segments.push({ type: "text", value: clean });
13089
+ }
13090
+ }
13091
+ function walk(node) {
13092
+ var _a;
13093
+ if (node.nodeType === Node.TEXT_NODE) {
13094
+ pushText(node.textContent);
13095
+ } else if (node.nodeType === Node.ELEMENT_NODE) {
13096
+ if (((_a = node.dataset) == null ? void 0 : _a.mention) === "true") {
13097
+ segments.push({
13098
+ type: "mention",
13099
+ id: node.dataset.id,
13100
+ name: node.dataset.name,
13101
+ mentionType: node.dataset.mentionType
13102
+ });
13103
+ } else if (node.tagName === "BR") {
13104
+ pushText("\n");
13105
+ } else {
13106
+ if (["DIV", "P"].includes(node.tagName) && segments.length > 0) {
13107
+ pushText("\n");
13108
+ }
13109
+ node.childNodes.forEach(walk);
13110
+ }
13111
+ }
13112
+ }
13113
+ el.childNodes.forEach(walk);
13114
+ return segments;
13115
+ }
13116
+ function RichGroupEditor({
13117
+ content,
13118
+ onChange,
13119
+ onMentionClick,
13120
+ searchItems,
13121
+ readOnly,
13122
+ placeholder
13123
+ }) {
13124
+ const editorRef = useRef19(null);
13125
+ const isMountedRef = useRef19(false);
13126
+ const [mentionState, setMentionState] = useState26(null);
13127
+ const [isEmpty, setIsEmpty] = useState26(true);
13128
+ useEffect22(() => {
13129
+ if (!isMountedRef.current && editorRef.current) {
13130
+ editorRef.current.innerHTML = contentToHTML(content);
13131
+ const hasContent = !!editorRef.current.innerText.replace(/\u200B/g, "").trim();
13132
+ const hasMentions = !!editorRef.current.querySelector("[data-mention]");
13133
+ setIsEmpty(!hasContent && !hasMentions);
13134
+ isMountedRef.current = true;
13135
+ }
13136
+ }, []);
13137
+ const getMentionContext = useCallback4(() => {
13138
+ const selection = window.getSelection();
13139
+ if (!selection || selection.rangeCount === 0) return null;
13140
+ const range = selection.getRangeAt(0);
13141
+ if (range.startContainer.nodeType !== Node.TEXT_NODE) return null;
13142
+ const textBefore = range.startContainer.textContent.substring(0, range.startOffset);
13143
+ const atIndex = textBefore.lastIndexOf("@");
13144
+ if (atIndex === -1) return null;
13145
+ const query = textBefore.substring(atIndex + 1);
13146
+ if (query.includes(" ") || query.length > 40) return null;
13147
+ const rect = range.getBoundingClientRect();
13148
+ return {
13149
+ query,
13150
+ position: { top: rect.bottom + 6, left: rect.left }
13151
+ };
13152
+ }, []);
13153
+ const handleInput = useCallback4(() => {
13154
+ if (!editorRef.current) return;
13155
+ const serialized = domToContent(editorRef.current);
13156
+ onChange(serialized);
13157
+ const text = editorRef.current.innerText.replace(/\u200B/g, "").trim();
13158
+ const hasMentions = !!editorRef.current.querySelector("[data-mention]");
13159
+ setIsEmpty(!text && !hasMentions);
13160
+ const ctx = getMentionContext();
13161
+ setMentionState(ctx);
13162
+ }, [onChange, getMentionContext]);
13163
+ const handleKeyDown = useCallback4(
13164
+ (e) => {
13165
+ if (mentionState && ["ArrowDown", "ArrowUp", "Enter", "Tab", "Escape"].includes(e.key)) {
13166
+ return;
13167
+ }
13168
+ if (e.key === "Enter") {
13169
+ e.preventDefault();
13170
+ const sel = window.getSelection();
13171
+ const range = sel.getRangeAt(0);
13172
+ const br = document.createElement("br");
13173
+ range.deleteContents();
13174
+ range.insertNode(br);
13175
+ const afterBr = br.nextSibling || (() => {
13176
+ const zws = document.createTextNode("\u200B");
13177
+ br.parentNode.insertBefore(zws, br.nextSibling);
13178
+ return zws;
13179
+ })();
13180
+ const newRange = document.createRange();
13181
+ newRange.setStartBefore(afterBr);
13182
+ newRange.collapse(true);
13183
+ sel.removeAllRanges();
13184
+ sel.addRange(newRange);
13185
+ handleInput();
13186
+ }
13187
+ },
13188
+ [mentionState, handleInput]
13189
+ );
13190
+ const insertMention = useCallback4(
13191
+ (item) => {
13192
+ if (!editorRef.current) return;
13193
+ const sel = window.getSelection();
13194
+ if (!sel || sel.rangeCount === 0) return;
13195
+ const range = sel.getRangeAt(0);
13196
+ const textNode = range.startContainer;
13197
+ if (textNode.nodeType !== Node.TEXT_NODE) {
13198
+ setMentionState(null);
13199
+ return;
13200
+ }
13201
+ const cursorPos = range.startOffset;
13202
+ const textContent = textNode.textContent;
13203
+ const atIndex = textContent.lastIndexOf("@", cursorPos - 1);
13204
+ if (atIndex === -1) {
13205
+ setMentionState(null);
13206
+ return;
13207
+ }
13208
+ const before = textContent.substring(0, atIndex);
13209
+ const after = textContent.substring(cursorPos);
13210
+ textNode.textContent = before;
13211
+ const parent = textNode.parentNode;
13212
+ const nextSib = textNode.nextSibling;
13213
+ const span = document.createElement("span");
13214
+ span.contentEditable = "false";
13215
+ span.dataset.mention = "true";
13216
+ span.dataset.id = item.id;
13217
+ span.dataset.name = item.searchLabel || item.name || "";
13218
+ span.dataset.mentionType = item.type;
13219
+ span.style.cssText = mentionStyle(item.type);
13220
+ span.title = "Clique para focar na cena";
13221
+ span.textContent = `@${item.searchLabel || item.name || ""}`;
13222
+ parent.insertBefore(span, nextSib);
13223
+ const trailing = document.createTextNode(after || "\u200B");
13224
+ parent.insertBefore(trailing, span.nextSibling);
13225
+ const newRange = document.createRange();
13226
+ newRange.setStart(trailing, after ? 0 : 1);
13227
+ newRange.collapse(true);
13228
+ sel.removeAllRanges();
13229
+ sel.addRange(newRange);
13230
+ const serialized = domToContent(editorRef.current);
13231
+ onChange(serialized);
13232
+ setMentionState(null);
13233
+ setIsEmpty(false);
13234
+ },
13235
+ [onChange]
13236
+ );
13237
+ const handlePaste = useCallback4(
13238
+ (e) => {
13239
+ e.preventDefault();
13240
+ const text = e.clipboardData.getData("text/plain");
13241
+ if (text) {
13242
+ document.execCommand("insertText", false, text);
13243
+ handleInput();
13244
+ }
13245
+ },
13246
+ [handleInput]
13247
+ );
13248
+ const handleClick = useCallback4(
13249
+ (e) => {
13250
+ const chip = e.target.closest("[data-mention='true']");
13251
+ if (chip && onMentionClick) {
13252
+ e.stopPropagation();
13253
+ const id = chip.dataset.id;
13254
+ const full = searchItems == null ? void 0 : searchItems.find((i) => String(i.id) === String(id));
13255
+ if (full) {
13256
+ onMentionClick(full);
13257
+ } else {
13258
+ onMentionClick({
13259
+ id,
13260
+ name: chip.dataset.name,
13261
+ type: chip.dataset.mentionType,
13262
+ searchLabel: chip.dataset.name
13263
+ });
13264
+ }
13265
+ return;
13266
+ }
13267
+ setTimeout(() => {
13268
+ const ctx = getMentionContext();
13269
+ setMentionState(ctx);
13270
+ }, 0);
13271
+ },
13272
+ [onMentionClick, getMentionContext, searchItems]
13273
+ );
13274
+ const handleBlur = useCallback4(() => {
13275
+ setTimeout(() => setMentionState(null), 200);
13276
+ }, []);
13277
+ return /* @__PURE__ */ React27.createElement("div", { className: "relative" }, isEmpty && !readOnly && /* @__PURE__ */ React27.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__ */ React27.createElement(
13278
+ "div",
13279
+ {
13280
+ ref: editorRef,
13281
+ contentEditable: readOnly ? "false" : "true",
13282
+ suppressContentEditableWarning: true,
13283
+ onInput: handleInput,
13284
+ onKeyDown: handleKeyDown,
13285
+ onPaste: handlePaste,
13286
+ onClick: handleClick,
13287
+ onBlur: handleBlur,
13288
+ 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"}`,
13289
+ style: { overflowWrap: "break-word", wordBreak: "break-word" }
13290
+ }
13291
+ ), mentionState && !readOnly && /* @__PURE__ */ React27.createElement(
13292
+ MentionPopover,
13293
+ {
13294
+ query: mentionState.query,
13295
+ items: searchItems || [],
13296
+ position: mentionState.position,
13297
+ onSelect: insertMention,
13298
+ onClose: () => setMentionState(null)
13299
+ }
13300
+ ));
13301
+ }
13302
+
13303
+ // src/components/AncestryBoard.jsx
12972
13304
  var GroupItem = ({
12973
13305
  group,
12974
13306
  index,
12975
- siblings,
12976
13307
  onUpdate,
12977
13308
  onDelete,
12978
13309
  onAddSubgroup,
12979
13310
  onIndent,
12980
13311
  onOutdent,
12981
- onRemoveAncestry,
12982
- onRequestPickAncestry,
12983
- pickingGroupId,
12984
- onPlayAncestry,
12985
- availableIds,
13312
+ searchItems,
13313
+ onMentionClick,
12986
13314
  canEdit
12987
13315
  }) => {
12988
13316
  const canIndent = index > 0;
12989
- const isPickingForThisGroup = pickingGroupId === group.id;
12990
- const textareaRef = useRef18(null);
12991
- const adjustHeight = () => {
12992
- const textarea = textareaRef.current;
12993
- if (textarea) {
12994
- textarea.style.height = "auto";
12995
- textarea.style.height = `${textarea.scrollHeight}px`;
12996
- }
13317
+ const handleContentChange = (content) => {
13318
+ onUpdate(group.id, { ...group, content });
12997
13319
  };
12998
- useEffect21(() => {
12999
- adjustHeight();
13000
- }, [group.text]);
13001
- return /* @__PURE__ */ React26.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__ */ React26.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ React26.createElement(
13002
- "div",
13320
+ return /* @__PURE__ */ React28.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__ */ React28.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ React28.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__ */ React28.createElement(
13321
+ RichGroupEditor,
13003
13322
  {
13004
- className: `
13005
- flex flex-col gap-2 py-2 px-3 transition-all duration-200
13006
- ${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
13007
- `
13323
+ content: group.content,
13324
+ onChange: handleContentChange,
13325
+ onMentionClick,
13326
+ searchItems,
13327
+ readOnly: !canEdit,
13328
+ placeholder: "Escreva sobre este grupo\u2026 ou @ para mencionar"
13329
+ }
13330
+ ), canEdit && /* @__PURE__ */ React28.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__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(
13331
+ "button",
13332
+ {
13333
+ onClick: () => onAddSubgroup(group.id),
13334
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13335
+ title: "Criar Subgrupo"
13008
13336
  },
13009
- /* @__PURE__ */ React26.createElement(
13010
- "textarea",
13011
- {
13012
- ref: textareaRef,
13013
- 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" : ""}`,
13014
- rows: 1,
13015
- style: {
13016
- minHeight: "1.5rem",
13017
- maxHeight: "250px"
13018
- },
13019
- placeholder: canEdit ? "Escreva sobre este grupo..." : "",
13020
- value: group.text,
13021
- readOnly: !canEdit,
13022
- onChange: (e) => {
13023
- if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
13024
- }
13025
- }
13026
- ),
13027
- group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ React26.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
13028
- const isValid = availableIds.has(String(anc.ancestry_id));
13029
- return /* @__PURE__ */ React26.createElement(
13030
- "div",
13031
- {
13032
- key: anc.ancestry_id,
13033
- className: `
13034
- flex items-center gap-2 rounded-md px-3 py-1.5 text-xs transition-all group/card border
13035
- ${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"}
13036
- `,
13037
- title: isValid ? "" : "Esta ancestralidade foi removida ou n\xE3o existe mais."
13038
- },
13039
- isValid ? /* @__PURE__ */ React26.createElement(
13040
- "button",
13041
- {
13042
- onClick: () => onPlayAncestry(anc),
13043
- className: "text-indigo-400 hover:text-white hover:bg-indigo-500 p-1 rounded-full transition-colors",
13044
- title: "Focar no cen\xE1rio"
13045
- },
13046
- /* @__PURE__ */ React26.createElement(FiPlay, { size: 10, className: "ml-0.5 fill-current" })
13047
- ) : /* @__PURE__ */ React26.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ React26.createElement(FiAlertTriangle, { size: 10 })),
13048
- /* @__PURE__ */ React26.createElement(
13049
- "div",
13050
- {
13051
- className: `flex items-center gap-1.5 font-medium truncate max-w-[180px] ${!isValid && "line-through decoration-red-500/50"}`
13052
- },
13053
- !isValid ? null : anc.type === "node" ? /* @__PURE__ */ React26.createElement(FiBox, { size: 10, className: "text-slate-400" }) : anc.type === "quest" ? /* @__PURE__ */ React26.createElement(FiCheckSquare3, { size: 10, className: "text-emerald-400" }) : anc.type === "version" ? /* @__PURE__ */ React26.createElement(FiGitBranch3, { size: 10, className: "text-amber-400" }) : /* @__PURE__ */ React26.createElement(FiLayers6, { size: 10, className: "text-indigo-400" }),
13054
- anc.name
13055
- ),
13056
- canEdit && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(
13057
- "div",
13058
- {
13059
- className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}`
13060
- }
13061
- ), /* @__PURE__ */ React26.createElement(
13062
- "button",
13063
- {
13064
- onClick: () => onRemoveAncestry(group.id, anc.ancestry_id),
13065
- className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
13066
- title: "Remover men\xE7\xE3o"
13067
- },
13068
- /* @__PURE__ */ React26.createElement(FiX8, { size: 12 })
13069
- ))
13070
- );
13071
- })),
13072
- canEdit && /* @__PURE__ */ React26.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__ */ React26.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React26.createElement(
13073
- "button",
13074
- {
13075
- onClick: () => onRequestPickAncestry(group.id),
13076
- className: `
13077
- flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium transition-colors
13078
- ${isPickingForThisGroup ? "text-indigo-300 animate-pulse" : "text-slate-500 hover:text-indigo-300 hover:bg-indigo-500/10"}
13079
- `,
13080
- title: "Adicionar Ancestralidade a este grupo"
13081
- },
13082
- isPickingForThisGroup ? /* @__PURE__ */ React26.createElement(FiCheckCircle, { size: 12 }) : /* @__PURE__ */ React26.createElement(FiSearch8, { size: 12 }),
13083
- isPickingForThisGroup ? "Selecionando..." : "Adicionar"
13084
- ), /* @__PURE__ */ React26.createElement(
13085
- "button",
13086
- {
13087
- onClick: () => onAddSubgroup(group.id),
13088
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13089
- title: "Criar Subgrupo"
13090
- },
13091
- /* @__PURE__ */ React26.createElement(FiPlus10, { size: 14 })
13092
- )), /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React26.createElement(
13093
- "button",
13094
- {
13095
- onClick: () => onIndent(group.id),
13096
- disabled: !canIndent,
13097
- className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13098
- title: "Aninhar no grupo acima"
13099
- },
13100
- /* @__PURE__ */ React26.createElement(FiArrowRight2, { size: 14 })
13101
- ), /* @__PURE__ */ React26.createElement(
13102
- "button",
13103
- {
13104
- onClick: () => onOutdent(group.id),
13105
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13106
- title: "Desaninhar"
13107
- },
13108
- /* @__PURE__ */ React26.createElement(FiArrowLeft3, { size: 14 })
13109
- ), /* @__PURE__ */ React26.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React26.createElement(
13110
- "button",
13111
- {
13112
- onClick: () => onDelete(group.id),
13113
- className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13114
- title: "Remover Grupo"
13115
- },
13116
- /* @__PURE__ */ React26.createElement(FiTrash23, { size: 14 })
13117
- )))
13118
- ), group.children && group.children.length > 0 && /* @__PURE__ */ React26.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ React26.createElement(
13337
+ /* @__PURE__ */ React28.createElement(FiPlus10, { size: 14 })
13338
+ )), /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(
13339
+ "button",
13340
+ {
13341
+ onClick: () => onIndent(group.id),
13342
+ disabled: !canIndent,
13343
+ className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13344
+ title: "Aninhar no grupo acima"
13345
+ },
13346
+ /* @__PURE__ */ React28.createElement(FiArrowRight2, { size: 14 })
13347
+ ), /* @__PURE__ */ React28.createElement(
13348
+ "button",
13349
+ {
13350
+ onClick: () => onOutdent(group.id),
13351
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13352
+ title: "Desaninhar"
13353
+ },
13354
+ /* @__PURE__ */ React28.createElement(FiArrowLeft3, { size: 14 })
13355
+ ), /* @__PURE__ */ React28.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React28.createElement(
13356
+ "button",
13357
+ {
13358
+ onClick: () => onDelete(group.id),
13359
+ className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13360
+ title: "Remover Grupo"
13361
+ },
13362
+ /* @__PURE__ */ React28.createElement(FiTrash23, { size: 14 })
13363
+ )))), group.children && group.children.length > 0 && /* @__PURE__ */ React28.createElement("div", { className: "ml-2" }, group.children.map((child, idx) => /* @__PURE__ */ React28.createElement(
13119
13364
  GroupItem,
13120
13365
  {
13121
- key: childGroup.id,
13366
+ key: child.id,
13122
13367
  index: idx,
13123
- group: childGroup,
13124
- siblings: group.children,
13368
+ group: child,
13125
13369
  onUpdate,
13126
13370
  onDelete,
13127
13371
  onAddSubgroup,
13128
13372
  onIndent,
13129
13373
  onOutdent,
13130
- onRemoveAncestry,
13131
- onRequestPickAncestry,
13132
- pickingGroupId,
13133
- onPlayAncestry,
13134
- availableIds,
13374
+ searchItems,
13375
+ onMentionClick,
13135
13376
  canEdit
13136
13377
  }
13137
13378
  ))));
@@ -13145,40 +13386,32 @@ function AncestryBoard({
13145
13386
  initialGroups = [],
13146
13387
  onSave,
13147
13388
  userRole
13148
- // [NOVO] Recebe a role do usuário
13149
13389
  }) {
13150
- const [searchTerm, setSearchTerm] = useState25("");
13151
- const [groups, setGroups] = useState25([]);
13152
- const [isLoaded, setIsLoaded] = useState25(false);
13153
- const [pickingGroupId, setPickingGroupId] = useState25(null);
13154
- const [saveStatus, setSaveStatus] = useState25("idle");
13155
- const canEdit = useMemo11(() => {
13156
- return userRole !== "viewer";
13157
- }, [userRole]);
13158
- useEffect21(() => {
13390
+ const [searchTerm, setSearchTerm] = useState27("");
13391
+ const [groups, setGroups] = useState27([]);
13392
+ const [isLoaded, setIsLoaded] = useState27(false);
13393
+ const [saveStatus, setSaveStatus] = useState27("idle");
13394
+ const canEdit = useMemo12(() => userRole !== "viewer", [userRole]);
13395
+ useEffect23(() => {
13159
13396
  if (initialGroups && !isLoaded) {
13160
- setGroups(initialGroups);
13397
+ const migrate = (list) => list.map((g) => ({
13398
+ id: g.id || uuidv411(),
13399
+ content: Array.isArray(g.content) ? g.content : [],
13400
+ // descarta dados legados
13401
+ children: migrate(g.children || [])
13402
+ }));
13403
+ setGroups(migrate(initialGroups));
13161
13404
  setIsLoaded(true);
13162
13405
  }
13163
13406
  }, [initialGroups, isLoaded]);
13164
- const nodeNamesMap = useMemo11(() => {
13407
+ const nodeNamesMap = useMemo12(() => {
13165
13408
  const map = /* @__PURE__ */ new Map();
13166
- if (availableNodes && Array.isArray(availableNodes)) {
13167
- availableNodes.forEach((node) => {
13168
- if (node && node.id) {
13169
- map.set(String(node.id), node.name);
13170
- }
13171
- });
13172
- }
13409
+ availableNodes.forEach((n) => {
13410
+ if (n == null ? void 0 : n.id) map.set(String(n.id), n.name);
13411
+ });
13173
13412
  return map;
13174
13413
  }, [availableNodes]);
13175
- const availableIds = useMemo11(() => {
13176
- const ids = /* @__PURE__ */ new Set();
13177
- availableAncestries.forEach((a) => ids.add(String(a.ancestry_id)));
13178
- availableNodes.forEach((n) => ids.add(String(n.id)));
13179
- return ids;
13180
- }, [availableAncestries, availableNodes]);
13181
- const allSearchableItems = useMemo11(() => {
13414
+ const allSearchableItems = useMemo12(() => {
13182
13415
  const items = [];
13183
13416
  availableAncestries.forEach((anc) => {
13184
13417
  items.push({
@@ -13204,117 +13437,76 @@ function AncestryBoard({
13204
13437
  });
13205
13438
  return items;
13206
13439
  }, [availableAncestries, availableNodes]);
13207
- const sanitizeGroups = (groupList) => {
13208
- return groupList.map((g) => ({
13209
- id: g.id,
13210
- text: g.text || "",
13211
- ancestries: (g.ancestries || []).map((a) => ({
13212
- id: a.id || a.ancestry_id,
13213
- ancestry_id: a.ancestry_id || a.id,
13214
- name: a.name,
13215
- type: a.type || "ancestry"
13216
- })),
13217
- children: sanitizeGroups(g.children || [])
13218
- }));
13219
- };
13220
- useEffect21(() => {
13440
+ const filtered = useMemo12(() => {
13441
+ const term = searchTerm.toLowerCase().trim();
13442
+ return allSearchableItems.filter((item) => {
13443
+ if (!term) return true;
13444
+ const labelMatch = (item.searchLabel || "").toLowerCase().includes(term);
13445
+ const descMatch = (item.searchDesc || "").toLowerCase().includes(term);
13446
+ let parentMatch = false;
13447
+ if (item.type === "ancestry") {
13448
+ const parentName = nodeNamesMap.get(String(item.ancestral_node)) || "";
13449
+ parentMatch = parentName.toLowerCase().includes(term);
13450
+ }
13451
+ return labelMatch || descMatch || parentMatch;
13452
+ });
13453
+ }, [allSearchableItems, searchTerm, nodeNamesMap]);
13454
+ const sanitizeGroups = (list) => list.map((g) => ({
13455
+ id: g.id,
13456
+ content: g.content || [],
13457
+ children: sanitizeGroups(g.children || [])
13458
+ }));
13459
+ useEffect23(() => {
13221
13460
  if (!isLoaded || !onSave) return;
13222
- const timeoutId = setTimeout(async () => {
13461
+ const id = setTimeout(async () => {
13223
13462
  setSaveStatus("saving");
13224
- const cleanData = sanitizeGroups(groups);
13225
13463
  try {
13226
- await onSave(cleanData);
13464
+ await onSave(sanitizeGroups(groups));
13227
13465
  setSaveStatus("saved");
13228
- setTimeout(() => {
13229
- setSaveStatus("idle");
13230
- }, 3e3);
13231
- } catch (error) {
13232
- console.error("Erro ao salvar board:", error);
13466
+ setTimeout(() => setSaveStatus("idle"), 3e3);
13467
+ } catch (err) {
13468
+ console.error("Erro ao salvar board:", err);
13233
13469
  setSaveStatus("error");
13234
13470
  }
13235
13471
  }, 3e3);
13236
- return () => clearTimeout(timeoutId);
13472
+ return () => clearTimeout(id);
13237
13473
  }, [groups, isLoaded, onSave]);
13238
- useEffect21(() => {
13474
+ useEffect23(() => {
13239
13475
  if (!isOpen) return;
13240
- const handleKeyDown = (e) => {
13476
+ const handler = (e) => {
13241
13477
  if (e.key === "Escape") {
13242
- if (pickingGroupId) {
13243
- setPickingGroupId(null);
13244
- } else {
13245
- onClose();
13246
- }
13478
+ onClose();
13247
13479
  e.preventDefault();
13248
13480
  e.stopPropagation();
13249
13481
  }
13250
13482
  };
13251
- window.addEventListener("keydown", handleKeyDown);
13252
- return () => window.removeEventListener("keydown", handleKeyDown);
13253
- }, [isOpen, onClose, pickingGroupId]);
13254
- const filtered = useMemo11(() => {
13255
- const term = searchTerm.toLowerCase().trim();
13256
- return allSearchableItems.filter((item) => {
13257
- var _a, _b;
13258
- if (!term) return true;
13259
- const labelMatch = (_a = item.searchLabel) == null ? void 0 : _a.toLowerCase().includes(term);
13260
- const descMatch = (_b = item.searchDesc) == null ? void 0 : _b.toLowerCase().includes(term);
13261
- let parentMatch = false;
13262
- if (item.type === "ancestry") {
13263
- const parentName = nodeNamesMap.get(String(item.ancestral_node)) || "";
13264
- parentMatch = parentName.toLowerCase().includes(term);
13265
- }
13266
- return labelMatch || descMatch || parentMatch;
13267
- });
13268
- }, [allSearchableItems, searchTerm, nodeNamesMap]);
13483
+ window.addEventListener("keydown", handler);
13484
+ return () => window.removeEventListener("keydown", handler);
13485
+ }, [isOpen, onClose]);
13269
13486
  const handleAddRootGroup = () => {
13270
- const newGroup = {
13271
- id: uuidv411(),
13272
- text: "",
13273
- ancestries: [],
13274
- children: []
13275
- };
13276
- setGroups((prev) => [newGroup, ...prev]);
13487
+ setGroups((prev) => [{ id: uuidv411(), content: [], children: [] }, ...prev]);
13277
13488
  };
13278
13489
  const handleAddSubgroup = (parentId) => {
13279
- const newGroup = {
13280
- id: uuidv411(),
13281
- text: "",
13282
- ancestries: [],
13283
- children: []
13284
- };
13285
- const addRecursive = (list) => {
13286
- return list.map((g) => {
13287
- if (g.id === parentId) {
13288
- return { ...g, children: [newGroup, ...g.children] };
13289
- }
13290
- return { ...g, children: addRecursive(g.children) };
13291
- });
13292
- };
13293
- setGroups((prev) => addRecursive(prev));
13490
+ const newGroup = { id: uuidv411(), content: [], children: [] };
13491
+ const add = (list) => list.map(
13492
+ (g) => g.id === parentId ? { ...g, children: [newGroup, ...g.children] } : { ...g, children: add(g.children) }
13493
+ );
13494
+ setGroups((prev) => add(prev));
13294
13495
  };
13295
13496
  const handleUpdateGroup = (id, newData) => {
13296
- const updateRecursive = (list) => {
13297
- return list.map((g) => {
13298
- if (g.id === id) return newData;
13299
- return { ...g, children: updateRecursive(g.children) };
13300
- });
13301
- };
13302
- setGroups((prev) => updateRecursive(prev));
13497
+ const update = (list) => list.map(
13498
+ (g) => g.id === id ? newData : { ...g, children: update(g.children) }
13499
+ );
13500
+ setGroups((prev) => update(prev));
13303
13501
  };
13304
13502
  const handleDeleteGroup = (id) => {
13305
- const deleteRecursive = (list) => {
13306
- return list.filter((g) => g.id !== id).map((g) => ({
13307
- ...g,
13308
- children: deleteRecursive(g.children)
13309
- }));
13310
- };
13311
- setGroups((prev) => deleteRecursive(prev));
13503
+ const del = (list) => list.filter((g) => g.id !== id).map((g) => ({ ...g, children: del(g.children) }));
13504
+ setGroups((prev) => del(prev));
13312
13505
  };
13313
13506
  const findGroupAndParent = (list, targetId, parent = null) => {
13314
13507
  for (let i = 0; i < list.length; i++) {
13315
- if (list[i].id === targetId) {
13508
+ if (list[i].id === targetId)
13316
13509
  return { group: list[i], parent, index: i, siblings: list };
13317
- }
13318
13510
  if (list[i].children.length > 0) {
13319
13511
  const found = findGroupAndParent(list[i].children, targetId, list[i]);
13320
13512
  if (found) return found;
@@ -13324,220 +13516,119 @@ function AncestryBoard({
13324
13516
  };
13325
13517
  const handleIndent = (id) => {
13326
13518
  setGroups((prev) => {
13327
- const newList = JSON.parse(JSON.stringify(prev));
13328
- const found = findGroupAndParent(newList, id);
13519
+ const next = JSON.parse(JSON.stringify(prev));
13520
+ const found = findGroupAndParent(next, id);
13329
13521
  if (!found || found.index === 0) return prev;
13330
13522
  const { group, siblings, index } = found;
13331
- const prevSibling = siblings[index - 1];
13332
13523
  siblings.splice(index, 1);
13333
- prevSibling.children.push(group);
13334
- return newList;
13524
+ siblings[index - 1].children.push(group);
13525
+ return next;
13335
13526
  });
13336
13527
  };
13337
13528
  const handleOutdent = (id) => {
13338
13529
  setGroups((prev) => {
13339
- const newList = JSON.parse(JSON.stringify(prev));
13340
- const found = findGroupAndParent(newList, id);
13530
+ const next = JSON.parse(JSON.stringify(prev));
13531
+ const found = findGroupAndParent(next, id);
13341
13532
  if (!found || !found.parent) return prev;
13342
13533
  const { group, siblings, index, parent } = found;
13343
13534
  siblings.splice(index, 1);
13344
- const parentFound = findGroupAndParent(newList, parent.id);
13535
+ const parentFound = findGroupAndParent(next, parent.id);
13345
13536
  if (parentFound) {
13346
13537
  parentFound.siblings.splice(parentFound.index + 1, 0, group);
13347
13538
  } else {
13348
- newList.push(group);
13539
+ next.push(group);
13349
13540
  }
13350
- return newList;
13541
+ return next;
13351
13542
  });
13352
13543
  };
13353
- const handleRequestPick = (groupId) => {
13354
- setPickingGroupId((prev) => prev === groupId ? null : groupId);
13355
- };
13356
- const handleSelectAncestry = (ancestry) => {
13357
- if (pickingGroupId) {
13358
- setGroups((prev) => {
13359
- const addRecursive = (list) => {
13360
- return list.map((g) => {
13361
- if (g.id === pickingGroupId) {
13362
- const exists = g.ancestries.some(
13363
- (a) => String(a.id || a.ancestry_id) === String(ancestry.id)
13364
- );
13365
- if (exists) return g;
13366
- return {
13367
- ...g,
13368
- ancestries: [
13369
- ...g.ancestries,
13370
- {
13371
- id: ancestry.id,
13372
- ancestry_id: ancestry.id,
13373
- name: ancestry.searchLabel,
13374
- type: ancestry.type
13375
- }
13376
- ]
13377
- };
13378
- }
13379
- return { ...g, children: addRecursive(g.children) };
13380
- });
13381
- };
13382
- return addRecursive(prev);
13383
- });
13384
- onSelect(ancestry);
13385
- }
13386
- };
13387
- const handlePlayFromGroup = (ancestry) => {
13388
- if (ancestry && onSelect) {
13389
- onSelect(ancestry);
13390
- }
13391
- };
13392
- const handleRemoveAncestryFromGroup = (groupId, ancestryId) => {
13393
- setGroups((prev) => {
13394
- const removeRecursive = (list) => {
13395
- return list.map((g) => {
13396
- if (g.id === groupId) {
13397
- return {
13398
- ...g,
13399
- ancestries: g.ancestries.filter(
13400
- (a) => String(a.id || a.ancestry_id) !== String(ancestryId)
13401
- )
13402
- };
13403
- }
13404
- return { ...g, children: removeRecursive(g.children) };
13405
- });
13406
- };
13407
- return removeRecursive(prev);
13408
- });
13544
+ const handleMentionClick = (item) => {
13545
+ if (onSelect) onSelect(item);
13409
13546
  };
13410
13547
  if (!isOpen) return null;
13411
- return /* @__PURE__ */ React26.createElement(
13548
+ return /* @__PURE__ */ React28.createElement(
13412
13549
  "div",
13413
13550
  {
13414
13551
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
13415
13552
  onClick: onClose
13416
13553
  },
13417
- /* @__PURE__ */ React26.createElement(
13554
+ /* @__PURE__ */ React28.createElement(
13418
13555
  "div",
13419
13556
  {
13420
13557
  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",
13421
13558
  onClick: (e) => e.stopPropagation()
13422
13559
  },
13423
- /* @__PURE__ */ React26.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React26.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ React26.createElement(FiLayers6, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React26.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ React26.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__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(
13424
- FiLoader5,
13425
- {
13426
- className: "animate-spin text-indigo-400",
13427
- size: 12
13428
- }
13429
- ), /* @__PURE__ */ React26.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ React26.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ React26.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ React26.createElement("span", { className: "text-xs text-indigo-300 font-medium animate-pulse hidden sm:inline-block mr-2" }, "Selecione na lateral..."), canEdit && /* @__PURE__ */ React26.createElement(
13560
+ /* @__PURE__ */ React28.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React28.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ React28.createElement(FiLayers7, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React28.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ React28.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__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(FiLoader5, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ React28.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ React28.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ React28.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-3" }, canEdit && /* @__PURE__ */ React28.createElement(
13430
13561
  "button",
13431
13562
  {
13432
13563
  onClick: handleAddRootGroup,
13433
- 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 "
13564
+ 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"
13434
13565
  },
13435
- /* @__PURE__ */ React26.createElement(FiPlus10, { size: 14, className: "text-indigo-400" }),
13436
- /* @__PURE__ */ React26.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13437
- ), /* @__PURE__ */ React26.createElement(
13566
+ /* @__PURE__ */ React28.createElement(FiPlus10, { size: 14, className: "text-indigo-400" }),
13567
+ /* @__PURE__ */ React28.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13568
+ ), /* @__PURE__ */ React28.createElement(
13438
13569
  "button",
13439
13570
  {
13440
13571
  onClick: onClose,
13441
13572
  className: "w-8 h-8 rounded-lg flex items-center justify-center text-slate-400 hover:text-white hover:bg-white/10 transition-colors"
13442
13573
  },
13443
- "\xD7"
13574
+ /* @__PURE__ */ React28.createElement(FiX8, { size: 16 })
13444
13575
  ))),
13445
- /* @__PURE__ */ React26.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React26.createElement(
13446
- "div",
13576
+ /* @__PURE__ */ React28.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React28.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__ */ React28.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ React28.createElement("div", { className: "relative group" }, /* @__PURE__ */ React28.createElement(FiSearch8, { className: "absolute left-3 top-1/2 -translate-y-1/2 text-slate-500 group-focus-within:text-indigo-400 transition-colors" }), /* @__PURE__ */ React28.createElement(
13577
+ "input",
13447
13578
  {
13448
- className: `
13449
- flex flex-col border-r border-white/10 transition-all duration-300 flex-none
13450
- ${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
13451
- min-w-[280px] max-w-[500px] bg-slate-900
13452
- `
13453
- },
13454
- /* @__PURE__ */ React26.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ React26.createElement("div", { className: "relative group" }, /* @__PURE__ */ React26.createElement(
13455
- FiSearch8,
13456
- {
13457
- 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"}`
13458
- }
13459
- ), /* @__PURE__ */ React26.createElement(
13460
- "input",
13579
+ type: "text",
13580
+ placeholder: "Navegar nas ancestralidades e nodes\u2026",
13581
+ 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",
13582
+ value: searchTerm,
13583
+ onChange: (e) => setSearchTerm(e.target.value),
13584
+ autoFocus: true
13585
+ }
13586
+ ))), /* @__PURE__ */ React28.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
13587
+ const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
13588
+ return /* @__PURE__ */ React28.createElement(
13589
+ "div",
13461
13590
  {
13462
- type: "text",
13463
- placeholder: pickingGroupId ? "Pesquise nodes ou ancestralidades..." : "Pesquisar no board...",
13464
- className: `
13465
- 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
13466
- ${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"}
13467
- `,
13468
- value: searchTerm,
13469
- onChange: (e) => setSearchTerm(e.target.value),
13470
- autoFocus: !pickingGroupId
13471
- }
13472
- ))),
13473
- /* @__PURE__ */ React26.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
13474
- const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
13475
- const isPicking = !!pickingGroupId;
13476
- return /* @__PURE__ */ React26.createElement(
13477
- "div",
13591
+ key: anc.id,
13592
+ 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"
13593
+ },
13594
+ /* @__PURE__ */ React28.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__ */ React28.createElement(FiCheckSquare4, { size: 14, className: "text-emerald-400 group-hover:text-white" }) : anc.type === "version" ? /* @__PURE__ */ React28.createElement(FiGitBranch4, { size: 14, className: "text-amber-400 group-hover:text-white" }) : anc.type === "node" ? /* @__PURE__ */ React28.createElement(FiBox2, { size: 14, className: "text-slate-400 group-hover:text-white" }) : /* @__PURE__ */ React28.createElement(FiLayers7, { size: 14, className: "text-indigo-400 group-hover:text-white" })),
13595
+ /* @__PURE__ */ React28.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ React28.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ React28.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, anc.searchLabel || "Sem Nome"), /* @__PURE__ */ React28.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__ */ React28.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__ */ React28.createElement(FiCornerUpRight4, { size: 10 }), /* @__PURE__ */ React28.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.searchDesc && /* @__PURE__ */ React28.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.searchDesc)),
13596
+ /* @__PURE__ */ React28.createElement(
13597
+ "button",
13478
13598
  {
13479
- key: anc.id,
13480
- onClick: () => {
13481
- if (isPicking) handleSelectAncestry(anc);
13599
+ onClick: (e) => {
13600
+ e.stopPropagation();
13601
+ if (onSelect) onSelect(anc);
13482
13602
  },
13483
- className: `
13484
- group relative flex items-start gap-3 p-3 text-left rounded-lg border transition-all duration-200
13485
- ${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"}
13486
- `
13603
+ 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",
13604
+ title: "Focar no cen\xE1rio"
13487
13605
  },
13488
- /* @__PURE__ */ React26.createElement(
13489
- "div",
13490
- {
13491
- className: `
13492
- mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
13493
- ${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"}
13494
- ${anc.type === "quest" ? "text-emerald-400" : anc.type === "version" ? "text-amber-400" : anc.type === "node" ? "text-slate-400" : "text-indigo-400"}
13495
- `
13496
- },
13497
- isPicking ? /* @__PURE__ */ React26.createElement(FiPlus10, { size: 16 }) : anc.type === "quest" ? /* @__PURE__ */ React26.createElement(FiCheckSquare3, { size: 14 }) : anc.type === "version" ? /* @__PURE__ */ React26.createElement(FiGitBranch3, { size: 14 }) : anc.type === "node" ? /* @__PURE__ */ React26.createElement(FiBox, { size: 14 }) : /* @__PURE__ */ React26.createElement(FiLayers6, { size: 14 })
13498
- ),
13499
- /* @__PURE__ */ React26.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ React26.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, anc.searchLabel || "Sem Nome"), /* @__PURE__ */ React26.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__ */ React26.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__ */ React26.createElement(FiCornerUpRight4, { size: 10 }), /* @__PURE__ */ React26.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.searchDesc && /* @__PURE__ */ React26.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.searchDesc)),
13500
- !isPicking && /* @__PURE__ */ React26.createElement(
13501
- "button",
13502
- {
13503
- onClick: (e) => {
13504
- e.stopPropagation();
13505
- handleSelectAncestry(anc);
13506
- },
13507
- 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",
13508
- title: "Focar no cen\xE1rio"
13509
- },
13510
- /* @__PURE__ */ React26.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ React26.createElement(FiPlay, { size: 14, className: "ml-0.5" }))
13511
- )
13512
- );
13513
- }))
13514
- ), /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ React26.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ React26.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__ */ React26.createElement(FiLayers6, { size: 24, className: "opacity-20" }), /* @__PURE__ */ React26.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ React26.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ React26.createElement(React26.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ React26.createElement(
13606
+ /* @__PURE__ */ React28.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ React28.createElement(FiPlay, { size: 14, className: "ml-0.5" }))
13607
+ )
13608
+ );
13609
+ }))), /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ React28.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ React28.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__ */ React28.createElement(FiLayers7, { size: 24, className: "opacity-20" }), /* @__PURE__ */ React28.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ React28.createElement(React28.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ React28.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ React28.createElement(React28.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ React28.createElement(
13515
13610
  GroupItem,
13516
13611
  {
13517
13612
  key: group.id,
13518
13613
  index,
13519
13614
  group,
13520
- siblings: groups,
13521
13615
  onUpdate: handleUpdateGroup,
13522
13616
  onDelete: handleDeleteGroup,
13523
13617
  onAddSubgroup: handleAddSubgroup,
13524
13618
  onIndent: handleIndent,
13525
13619
  onOutdent: handleOutdent,
13526
- onRemoveAncestry: handleRemoveAncestryFromGroup,
13527
- onRequestPickAncestry: handleRequestPick,
13528
- pickingGroupId,
13529
- onPlayAncestry: handlePlayFromGroup,
13530
- availableIds,
13620
+ searchItems: allSearchableItems,
13621
+ onMentionClick: handleMentionClick,
13531
13622
  canEdit
13532
13623
  }
13533
13624
  ))))),
13534
- /* @__PURE__ */ React26.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__ */ React26.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ React26.createElement("span", null, groups.length, " grupos raiz"))
13625
+ /* @__PURE__ */ React28.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__ */ React28.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ React28.createElement("span", null, groups.length, " grupos raiz"))
13535
13626
  )
13536
13627
  );
13537
13628
  }
13538
13629
 
13539
13630
  // src/components/MilestoneManager.jsx
13540
- import React27, { useState as useState26 } from "react";
13631
+ import React29, { useState as useState28 } from "react";
13541
13632
  import { FiTarget as FiTarget4, FiPlus as FiPlus11, FiTrash2 as FiTrash24, FiX as FiX9, FiCheck as FiCheck12, FiPauseCircle, FiPlayCircle } from "react-icons/fi";
13542
13633
  function MilestoneManager({
13543
13634
  isOpen,
@@ -13546,7 +13637,7 @@ function MilestoneManager({
13546
13637
  onUpdateMilestones = () => {
13547
13638
  }
13548
13639
  }) {
13549
- const [newMilestoneName, setNewMilestoneName] = useState26("");
13640
+ const [newMilestoneName, setNewMilestoneName] = useState28("");
13550
13641
  const handleAddMilestone = () => {
13551
13642
  if (!newMilestoneName.trim()) return;
13552
13643
  const newMilestone = {
@@ -13571,27 +13662,27 @@ function MilestoneManager({
13571
13662
  };
13572
13663
  if (!isOpen) return null;
13573
13664
  const swallow = (e) => e.stopPropagation();
13574
- return /* @__PURE__ */ React27.createElement(
13665
+ return /* @__PURE__ */ React29.createElement(
13575
13666
  "div",
13576
13667
  {
13577
13668
  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",
13578
13669
  onClick: onClose
13579
13670
  },
13580
- /* @__PURE__ */ React27.createElement(
13671
+ /* @__PURE__ */ React29.createElement(
13581
13672
  "div",
13582
13673
  {
13583
13674
  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",
13584
13675
  onClick: swallow
13585
13676
  },
13586
- /* @__PURE__ */ React27.createElement("div", { className: "px-6 py-4 border-b border-white/10 flex items-center justify-between" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React27.createElement("div", { className: "p-2 rounded-lg bg-indigo-500/20 text-indigo-400" }, /* @__PURE__ */ React27.createElement(FiTarget4, { size: 20 })), /* @__PURE__ */ React27.createElement("div", null, /* @__PURE__ */ React27.createElement("h2", { className: "text-lg font-semibold text-slate-100" }, "Milestones"), /* @__PURE__ */ React27.createElement("p", { className: "text-xs text-slate-400" }, "Gerencie os marcos do seu cen\xE1rio"))), /* @__PURE__ */ React27.createElement(
13677
+ /* @__PURE__ */ React29.createElement("div", { className: "px-6 py-4 border-b border-white/10 flex items-center justify-between" }, /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React29.createElement("div", { className: "p-2 rounded-lg bg-indigo-500/20 text-indigo-400" }, /* @__PURE__ */ React29.createElement(FiTarget4, { size: 20 })), /* @__PURE__ */ React29.createElement("div", null, /* @__PURE__ */ React29.createElement("h2", { className: "text-lg font-semibold text-slate-100" }, "Milestones"), /* @__PURE__ */ React29.createElement("p", { className: "text-xs text-slate-400" }, "Gerencie os marcos do seu cen\xE1rio"))), /* @__PURE__ */ React29.createElement(
13587
13678
  "button",
13588
13679
  {
13589
13680
  onClick: onClose,
13590
13681
  className: "p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
13591
13682
  },
13592
- /* @__PURE__ */ React27.createElement(FiX9, { size: 20 })
13683
+ /* @__PURE__ */ React29.createElement(FiX9, { size: 20 })
13593
13684
  )),
13594
- /* @__PURE__ */ React27.createElement("div", { className: "px-6 py-5 bg-white/5 border-b border-white/5" }, /* @__PURE__ */ React27.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React27.createElement(
13685
+ /* @__PURE__ */ React29.createElement("div", { className: "px-6 py-5 bg-white/5 border-b border-white/5" }, /* @__PURE__ */ React29.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React29.createElement(
13595
13686
  "input",
13596
13687
  {
13597
13688
  type: "text",
@@ -13601,47 +13692,47 @@ function MilestoneManager({
13601
13692
  placeholder: "Adicionar novo milestone...",
13602
13693
  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"
13603
13694
  }
13604
- ), /* @__PURE__ */ React27.createElement(
13695
+ ), /* @__PURE__ */ React29.createElement(
13605
13696
  "button",
13606
13697
  {
13607
13698
  onClick: handleAddMilestone,
13608
13699
  disabled: !newMilestoneName.trim(),
13609
13700
  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"
13610
13701
  },
13611
- /* @__PURE__ */ React27.createElement(FiPlus11, { size: 18 }),
13702
+ /* @__PURE__ */ React29.createElement(FiPlus11, { size: 18 }),
13612
13703
  "Adicionar"
13613
13704
  ))),
13614
- /* @__PURE__ */ React27.createElement("div", { className: "flex-1 overflow-y-auto px-6 py-4 custom-scrollbar" }, milestones.length > 0 ? /* @__PURE__ */ React27.createElement("div", { className: "space-y-3" }, milestones.map((ms) => /* @__PURE__ */ React27.createElement(
13705
+ /* @__PURE__ */ React29.createElement("div", { className: "flex-1 overflow-y-auto px-6 py-4 custom-scrollbar" }, milestones.length > 0 ? /* @__PURE__ */ React29.createElement("div", { className: "space-y-3" }, milestones.map((ms) => /* @__PURE__ */ React29.createElement(
13615
13706
  "div",
13616
13707
  {
13617
13708
  key: ms.id,
13618
13709
  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]"}`
13619
13710
  },
13620
- /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ React27.createElement(
13711
+ /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ React29.createElement(
13621
13712
  "div",
13622
13713
  {
13623
13714
  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"}`
13624
13715
  }
13625
- ), /* @__PURE__ */ React27.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React27.createElement("span", { className: `text-sm font-medium truncate ${ms.status === "active" ? "text-slate-100" : "text-slate-400 line-through"}` }, ms.name), /* @__PURE__ */ React27.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, ms.status === "active" ? "Ativo" : "Inativo"))),
13626
- /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React27.createElement(
13716
+ ), /* @__PURE__ */ React29.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React29.createElement("span", { className: `text-sm font-medium truncate ${ms.status === "active" ? "text-slate-100" : "text-slate-400 line-through"}` }, ms.name), /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, ms.status === "active" ? "Ativo" : "Inativo"))),
13717
+ /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React29.createElement(
13627
13718
  "button",
13628
13719
  {
13629
13720
  onClick: () => handleToggleMilestoneStatus(ms.id),
13630
13721
  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"}`,
13631
13722
  title: ms.status === "active" ? "Inativar" : "Ativar"
13632
13723
  },
13633
- ms.status === "active" ? /* @__PURE__ */ React27.createElement(FiPauseCircle, { size: 18 }) : /* @__PURE__ */ React27.createElement(FiPlayCircle, { size: 18 })
13634
- ), /* @__PURE__ */ React27.createElement(
13724
+ ms.status === "active" ? /* @__PURE__ */ React29.createElement(FiPauseCircle, { size: 18 }) : /* @__PURE__ */ React29.createElement(FiPlayCircle, { size: 18 })
13725
+ ), /* @__PURE__ */ React29.createElement(
13635
13726
  "button",
13636
13727
  {
13637
13728
  onClick: () => handleRemoveMilestone(ms.id),
13638
13729
  className: "p-2 rounded-lg hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-all",
13639
13730
  title: "Remover"
13640
13731
  },
13641
- /* @__PURE__ */ React27.createElement(FiTrash24, { size: 18 })
13732
+ /* @__PURE__ */ React29.createElement(FiTrash24, { size: 18 })
13642
13733
  ))
13643
- ))) : /* @__PURE__ */ React27.createElement("div", { className: "flex flex-col items-center justify-center py-12 text-center" }, /* @__PURE__ */ React27.createElement("div", { className: "p-4 rounded-full bg-slate-800/30 text-slate-600 mb-4" }, /* @__PURE__ */ React27.createElement(FiTarget4, { size: 40 })), /* @__PURE__ */ React27.createElement("h3", { className: "text-slate-400 font-medium" }, "Nenhum milestone definido"), /* @__PURE__ */ React27.createElement("p", { className: "text-xs text-slate-600 max-w-[200px] mt-1 italic" }, "Defina marcos importantes para orientar o progresso do projeto."))),
13644
- /* @__PURE__ */ React27.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__ */ React27.createElement("div", { className: "flex gap-4" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React27.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Total:"), /* @__PURE__ */ React27.createElement("span", { className: "text-xs font-bold text-slate-300" }, milestones.length)), /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React27.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Ativos:"), /* @__PURE__ */ React27.createElement("span", { className: "text-xs font-bold text-indigo-400" }, milestones.filter((m) => m.status === "active").length))))
13734
+ ))) : /* @__PURE__ */ React29.createElement("div", { className: "flex flex-col items-center justify-center py-12 text-center" }, /* @__PURE__ */ React29.createElement("div", { className: "p-4 rounded-full bg-slate-800/30 text-slate-600 mb-4" }, /* @__PURE__ */ React29.createElement(FiTarget4, { size: 40 })), /* @__PURE__ */ React29.createElement("h3", { className: "text-slate-400 font-medium" }, "Nenhum milestone definido"), /* @__PURE__ */ React29.createElement("p", { className: "text-xs text-slate-600 max-w-[200px] mt-1 italic" }, "Defina marcos importantes para orientar o progresso do projeto."))),
13735
+ /* @__PURE__ */ React29.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__ */ React29.createElement("div", { className: "flex gap-4" }, /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Total:"), /* @__PURE__ */ React29.createElement("span", { className: "text-xs font-bold text-slate-300" }, milestones.length)), /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Ativos:"), /* @__PURE__ */ React29.createElement("span", { className: "text-xs font-bold text-indigo-400" }, milestones.filter((m) => m.status === "active").length))))
13645
13736
  )
13646
13737
  );
13647
13738
  }
@@ -13733,7 +13824,7 @@ function XViewScene({
13733
13824
  const searchParams = useSearchParams();
13734
13825
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
13735
13826
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
13736
- const viewParams = useMemo12(() => {
13827
+ const viewParams = useMemo13(() => {
13737
13828
  if (encryptedConfig) {
13738
13829
  const data = decryptData(encryptedConfig);
13739
13830
  if (data) {
@@ -13742,7 +13833,7 @@ function XViewScene({
13742
13833
  }
13743
13834
  return null;
13744
13835
  }, [encryptedConfig, session]);
13745
- useEffect22(() => {
13836
+ useEffect24(() => {
13746
13837
  async function verifyPermission() {
13747
13838
  if (!viewParams || !session || !check_user_permission) return;
13748
13839
  const { id, type, owner_id } = viewParams;
@@ -13779,65 +13870,65 @@ function XViewScene({
13779
13870
  setIsLoading(false);
13780
13871
  }
13781
13872
  }, [viewParams, session, status, check_user_permission]);
13782
- const sceneConfigId = useMemo12(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13783
- const ownerId = useMemo12(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13784
- const dbSaveUrl = useMemo12(() => {
13873
+ const sceneConfigId = useMemo13(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13874
+ const ownerId = useMemo13(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13875
+ const dbSaveUrl = useMemo13(() => {
13785
13876
  if (ownerId && sceneConfigId) {
13786
13877
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
13787
13878
  }
13788
13879
  return null;
13789
13880
  }, [ownerId, sceneConfigId]);
13790
- const sceneSaveUrl = useMemo12(() => {
13881
+ const sceneSaveUrl = useMemo13(() => {
13791
13882
  if (ownerId && sceneConfigId) {
13792
13883
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
13793
13884
  }
13794
13885
  return null;
13795
13886
  }, [ownerId, sceneConfigId]);
13796
- const ancestry_save_url = useMemo12(() => {
13887
+ const ancestry_save_url = useMemo13(() => {
13797
13888
  if (ownerId && sceneConfigId) {
13798
13889
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
13799
13890
  }
13800
13891
  return null;
13801
13892
  }, [ownerId, sceneConfigId]);
13802
- const sceneDataRef = useRef19(null);
13803
- const parentDataRef = useRef19(null);
13804
- const ancestryDataRef = useRef19(null);
13805
- const [isLoading, setIsLoading] = useState27(true);
13806
- const [permissionStatus, setPermissionStatus] = useState27("loading");
13807
- const [userPermissionRole, setUserPermissionRole] = useState27(null);
13808
- const [viewMembers, setViewMembers] = useState27([]);
13809
- const [isInitialized, setIsInitialized] = useState27(false);
13810
- const [sceneVersion, setSceneVersion] = useState27(0);
13811
- const [contextMenu, setContextMenu] = useState27({
13893
+ const sceneDataRef = useRef20(null);
13894
+ const parentDataRef = useRef20(null);
13895
+ const ancestryDataRef = useRef20(null);
13896
+ const [isLoading, setIsLoading] = useState29(true);
13897
+ const [permissionStatus, setPermissionStatus] = useState29("loading");
13898
+ const [userPermissionRole, setUserPermissionRole] = useState29(null);
13899
+ const [viewMembers, setViewMembers] = useState29([]);
13900
+ const [isInitialized, setIsInitialized] = useState29(false);
13901
+ const [sceneVersion, setSceneVersion] = useState29(0);
13902
+ const [contextMenu, setContextMenu] = useState29({
13812
13903
  visible: false,
13813
13904
  x: 0,
13814
13905
  y: 0,
13815
13906
  nodeData: null
13816
13907
  });
13817
- const [multiContextMenu, setMultiContextMenu] = useState27({
13908
+ const [multiContextMenu, setMultiContextMenu] = useState29({
13818
13909
  visible: false,
13819
13910
  x: 0,
13820
13911
  y: 0,
13821
13912
  nodeIds: null
13822
13913
  });
13823
- const [relationshipMenu, setRelationshipMenu] = useState27({
13914
+ const [relationshipMenu, setRelationshipMenu] = useState29({
13824
13915
  visible: false,
13825
13916
  x: 0,
13826
13917
  y: 0,
13827
13918
  linkObject: null
13828
13919
  });
13829
- const [creationMode, setCreationMode] = useState27({
13920
+ const [creationMode, setCreationMode] = useState29({
13830
13921
  isActive: false,
13831
13922
  sourceNodeData: null
13832
13923
  });
13833
- const [versionMode, setVersionMode] = useState27({
13924
+ const [versionMode, setVersionMode] = useState29({
13834
13925
  isActive: false,
13835
13926
  sourceNodeData: null
13836
13927
  });
13837
- const [questMode, setQuestMode] = useState27({ isActive: false });
13838
- const [hasFocusedInitial, setHasFocusedInitial] = useState27(false);
13839
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState27(false);
13840
- const [ancestryMode, setAncestryMode] = useState27({
13928
+ const [questMode, setQuestMode] = useState29({ isActive: false });
13929
+ const [hasFocusedInitial, setHasFocusedInitial] = useState29(false);
13930
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState29(false);
13931
+ const [ancestryMode, setAncestryMode] = useState29({
13841
13932
  isActive: false,
13842
13933
  tree: null,
13843
13934
  selectedParentId: null,
@@ -13848,42 +13939,42 @@ function XViewScene({
13848
13939
  ancestryDescriptionSections: [],
13849
13940
  isAddingNodes: false
13850
13941
  });
13851
- const [readingMode, setReadingMode] = useState27({
13942
+ const [readingMode, setReadingMode] = useState29({
13852
13943
  isActive: false,
13853
13944
  ancestry: null,
13854
13945
  branchStack: [],
13855
13946
  autoAbstraction: false
13856
13947
  });
13857
- const [formPosition, setFormPosition] = useState27({
13948
+ const [formPosition, setFormPosition] = useState29({
13858
13949
  left: 16,
13859
13950
  top: 16,
13860
13951
  opacity: 0
13861
13952
  });
13862
- const [detailsNode, setDetailsNode] = useState27(null);
13863
- const [detailsLink, setDetailsLink] = useState27(null);
13864
- const [ancestryLinkDetails, setAncestryLinkDetails] = useState27(null);
13865
- const [imageViewer, setImageViewer] = useState27({
13953
+ const [detailsNode, setDetailsNode] = useState29(null);
13954
+ const [detailsLink, setDetailsLink] = useState29(null);
13955
+ const [ancestryLinkDetails, setAncestryLinkDetails] = useState29(null);
13956
+ const [imageViewer, setImageViewer] = useState29({
13866
13957
  visible: false,
13867
13958
  images: [],
13868
13959
  startIndex: 0
13869
13960
  });
13870
- const [editingAncestryRel, setEditingAncestryRel] = useState27({
13961
+ const [editingAncestryRel, setEditingAncestryRel] = useState29({
13871
13962
  visible: false,
13872
13963
  data: null,
13873
13964
  path: null
13874
13965
  });
13875
- const [isImportModalOpen, setIsImportModalOpen] = useState27(false);
13876
- const [importSuccessMessage, setImportSuccessMessage] = useState27("");
13877
- const [invalidTargetError, setInvalidTargetError] = useState27(null);
13878
- const [highlightedNodeId, setHighlightedNodeId] = useState27(null);
13879
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState27(false);
13880
- const [ancestryBoardData, setAncestryBoardData] = useState27([]);
13881
- const [isSidebarOpen, setIsSidebarOpen] = useState27(false);
13882
- const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState27(false);
13883
- const mountRef = useRef19(null);
13884
- const tooltipRef = useRef19(null);
13885
- const formRef = useRef19(null);
13886
- const stateRef = useRef19({
13966
+ const [isImportModalOpen, setIsImportModalOpen] = useState29(false);
13967
+ const [importSuccessMessage, setImportSuccessMessage] = useState29("");
13968
+ const [invalidTargetError, setInvalidTargetError] = useState29(null);
13969
+ const [highlightedNodeId, setHighlightedNodeId] = useState29(null);
13970
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState29(false);
13971
+ const [ancestryBoardData, setAncestryBoardData] = useState29([]);
13972
+ const [isSidebarOpen, setIsSidebarOpen] = useState29(false);
13973
+ const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState29(false);
13974
+ const mountRef = useRef20(null);
13975
+ const tooltipRef = useRef20(null);
13976
+ const formRef = useRef20(null);
13977
+ const stateRef = useRef20({
13887
13978
  readMode: {
13888
13979
  currentMaxIndex: 0,
13889
13980
  progressMap: {}
@@ -13947,10 +14038,10 @@ function XViewScene({
13947
14038
  minWidth: 320,
13948
14039
  maxWidth: maxReadPanelW
13949
14040
  });
13950
- useEffect22(() => {
14041
+ useEffect24(() => {
13951
14042
  stateRef.current.ancestry = ancestryMode;
13952
14043
  }, [ancestryMode]);
13953
- useEffect22(() => {
14044
+ useEffect24(() => {
13954
14045
  var _a2;
13955
14046
  if (!isInitialized) return;
13956
14047
  const map = /* @__PURE__ */ new Map();
@@ -13973,10 +14064,10 @@ function XViewScene({
13973
14064
  }
13974
14065
  stateRef.current.nodeIdToParentFileMap = map;
13975
14066
  }, [isInitialized, sceneVersion]);
13976
- const handleNavigateBack = useCallback4(() => {
14067
+ const handleNavigateBack = useCallback5(() => {
13977
14068
  router.push("/dashboard/scenes");
13978
14069
  }, [router]);
13979
- const handleConfirmImport = useCallback4(
14070
+ const handleConfirmImport = useCallback5(
13980
14071
  async (importPayload) => {
13981
14072
  var _a2, _b2;
13982
14073
  let files = [];
@@ -14104,7 +14195,7 @@ function XViewScene({
14104
14195
  const handleOpenImageViewer = (images, startIndex) => {
14105
14196
  setImageViewer({ visible: true, images, startIndex });
14106
14197
  };
14107
- const tweenToTarget = useCallback4(
14198
+ const tweenToTarget = useCallback5(
14108
14199
  (target, zoomFactor = 1, forcedDirection = null) => {
14109
14200
  const { camera, controls, tweenGroup } = stateRef.current;
14110
14201
  if (!camera || !controls || !tweenGroup) return;
@@ -14130,7 +14221,7 @@ function XViewScene({
14130
14221
  if (!t || typeof t.closest !== "function") return false;
14131
14222
  return !!t.closest(".ui-overlay");
14132
14223
  };
14133
- const buildFullAncestryTree = useCallback4(
14224
+ const buildFullAncestryTree = useCallback5(
14134
14225
  (idTree, nodes, ancestries = []) => {
14135
14226
  if (!idTree) return null;
14136
14227
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
@@ -14215,7 +14306,7 @@ function XViewScene({
14215
14306
  },
14216
14307
  []
14217
14308
  );
14218
- const handleActivateTimeline = useCallback4(() => {
14309
+ const handleActivateTimeline = useCallback5(() => {
14219
14310
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
14220
14311
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
14221
14312
  while (timelineIntervalsGroup.children.length > 0) {
@@ -14375,7 +14466,7 @@ function XViewScene({
14375
14466
  }
14376
14467
  });
14377
14468
  }, []);
14378
- const handleVersionTimeline = useCallback4((sourceMesh, versionMeshes) => {
14469
+ const handleVersionTimeline = useCallback5((sourceMesh, versionMeshes) => {
14379
14470
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
14380
14471
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
14381
14472
  return;
@@ -14512,7 +14603,7 @@ function XViewScene({
14512
14603
  }
14513
14604
  });
14514
14605
  }, []);
14515
- useEffect22(() => {
14606
+ useEffect24(() => {
14516
14607
  async function fetchAllData(configPath, ownerId2) {
14517
14608
  var _a2, _b2;
14518
14609
  if (!get_scene_view_data) {
@@ -14617,12 +14708,12 @@ function XViewScene({
14617
14708
  focusNodeId,
14618
14709
  focusAncestryId
14619
14710
  ]);
14620
- const isNodeInView = useCallback4((id) => {
14711
+ const isNodeInView = useCallback5((id) => {
14621
14712
  const key = String(id);
14622
14713
  const objs = stateRef.current.nodeObjects || {};
14623
14714
  return !!objs[key];
14624
14715
  }, []);
14625
- const addOrUpdateNodeMesh = useCallback4(
14716
+ const addOrUpdateNodeMesh = useCallback5(
14626
14717
  (nodeData, position, suppressVersionUpdate = false, forceShowQuestDate = false) => {
14627
14718
  const {
14628
14719
  graphGroup,
@@ -14663,7 +14754,7 @@ function XViewScene({
14663
14754
  },
14664
14755
  []
14665
14756
  );
14666
- const handleActivateQuestLens = useCallback4(({ assigneeId, status: status2, milestoneId }) => {
14757
+ const handleActivateQuestLens = useCallback5(({ assigneeId, status: status2, milestoneId }) => {
14667
14758
  var _a2;
14668
14759
  const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
14669
14760
  if (!nodeObjects || !tweenGroup || !graphGroup) return;
@@ -14877,7 +14968,7 @@ function XViewScene({
14877
14968
  camTween.start();
14878
14969
  }
14879
14970
  }, [addOrUpdateNodeMesh]);
14880
- useEffect22(() => {
14971
+ useEffect24(() => {
14881
14972
  if (!isInitialized || !sceneDataRef.current) return;
14882
14973
  const currentMount = mountRef.current;
14883
14974
  if (!currentMount) return;
@@ -15633,7 +15724,7 @@ function XViewScene({
15633
15724
  get_scene_view_data,
15634
15725
  save_view_data
15635
15726
  ]);
15636
- const handleGhostNodeImageChange = useCallback4((useImage, imageUrl) => {
15727
+ const handleGhostNodeImageChange = useCallback5((useImage, imageUrl) => {
15637
15728
  const {
15638
15729
  node: ghostNode,
15639
15730
  line: ghostLine,
@@ -15681,7 +15772,7 @@ function XViewScene({
15681
15772
  aura: newGhostNode.getObjectByName("aura")
15682
15773
  };
15683
15774
  }, []);
15684
- const handleGhostNodeIntensityChange = useCallback4((newIntensity) => {
15775
+ const handleGhostNodeIntensityChange = useCallback5((newIntensity) => {
15685
15776
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
15686
15777
  if (!ghostNode) return;
15687
15778
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -15702,7 +15793,7 @@ function XViewScene({
15702
15793
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
15703
15794
  }
15704
15795
  }, []);
15705
- const handleDetailNodeIntensityChange = useCallback4(
15796
+ const handleDetailNodeIntensityChange = useCallback5(
15706
15797
  (nodeId, newIntensity) => {
15707
15798
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
15708
15799
  if (!mesh) return;
@@ -15858,7 +15949,7 @@ function XViewScene({
15858
15949
  mountRef.current.style.cursor = "default";
15859
15950
  }
15860
15951
  };
15861
- const handleAncestryTreeUpdate = useCallback4((newTree, extraData = null) => {
15952
+ const handleAncestryTreeUpdate = useCallback5((newTree, extraData = null) => {
15862
15953
  setAncestryMode((prev) => {
15863
15954
  const prevTreeStr = JSON.stringify(prev.tree);
15864
15955
  const newTreeStr = JSON.stringify(newTree);
@@ -15881,7 +15972,7 @@ function XViewScene({
15881
15972
  };
15882
15973
  });
15883
15974
  }, []);
15884
- const actionHandlerContext = useMemo12(
15975
+ const actionHandlerContext = useMemo13(
15885
15976
  () => {
15886
15977
  var _a2;
15887
15978
  return {
@@ -15942,7 +16033,7 @@ function XViewScene({
15942
16033
  const handleStartVersioning = (nodeData) => {
15943
16034
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
15944
16035
  };
15945
- const handleStartQuestQuick = useCallback4((questNode) => {
16036
+ const handleStartQuestQuick = useCallback5((questNode) => {
15946
16037
  var _a2, _b2, _c2;
15947
16038
  if (!questNode || !actionHandlerContext) return;
15948
16039
  const allParentNodes = Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
@@ -15977,7 +16068,7 @@ function XViewScene({
15977
16068
  }
15978
16069
  setDetailsNode(updatedNode);
15979
16070
  }, [session, actionHandlerContext]);
15980
- const handleFinishQuestQuick = useCallback4((questNode) => {
16071
+ const handleFinishQuestQuick = useCallback5((questNode) => {
15981
16072
  var _a2, _b2, _c2, _d2;
15982
16073
  if (!questNode || !actionHandlerContext) return;
15983
16074
  const {
@@ -16051,7 +16142,7 @@ function XViewScene({
16051
16142
  setDetailsNode(null);
16052
16143
  }
16053
16144
  }, [session, actionHandlerContext, viewMembers, detailsNode]);
16054
- const handleCancelQuest = useCallback4(() => {
16145
+ const handleCancelQuest = useCallback5(() => {
16055
16146
  const { graphGroup, ghostElements } = stateRef.current;
16056
16147
  if (ghostElements.node && graphGroup) {
16057
16148
  if (ghostElements.node.userData.labelObject) {
@@ -16208,7 +16299,7 @@ function XViewScene({
16208
16299
  }
16209
16300
  userActionHandlers.handleCancelConnection(context);
16210
16301
  };
16211
- const handleClearAncestryVisuals = useCallback4((ancestryId) => {
16302
+ const handleClearAncestryVisuals = useCallback5((ancestryId) => {
16212
16303
  const { renderedAncestries, ancestryGroup } = stateRef.current;
16213
16304
  const renderIndex = renderedAncestries.findIndex(
16214
16305
  (a) => String(a.id) === String(ancestryId)
@@ -16226,7 +16317,7 @@ function XViewScene({
16226
16317
  );
16227
16318
  }
16228
16319
  }, []);
16229
- const handleRenderAncestry = useCallback4(
16320
+ const handleRenderAncestry = useCallback5(
16230
16321
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
16231
16322
  setContextMenu(
16232
16323
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16720,7 +16811,7 @@ function XViewScene({
16720
16811
  ancestryMode.isActive
16721
16812
  ]
16722
16813
  );
16723
- const handleRenderAbstractionTree = useCallback4(
16814
+ const handleRenderAbstractionTree = useCallback5(
16724
16815
  (ancestryObject, targetNodeId = null) => {
16725
16816
  setContextMenu(
16726
16817
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16808,7 +16899,7 @@ function XViewScene({
16808
16899
  handleClearAncestryVisuals
16809
16900
  ]
16810
16901
  );
16811
- const handleReadModeBranchNav = useCallback4(
16902
+ const handleReadModeBranchNav = useCallback5(
16812
16903
  (nodeId, action, direction = "right") => {
16813
16904
  const { ancestry, branchStack } = readingMode;
16814
16905
  if (!ancestry || !ancestry.tree) return;
@@ -16986,13 +17077,13 @@ function XViewScene({
16986
17077
  },
16987
17078
  [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
16988
17079
  );
16989
- const handleReadModeHighlight = useCallback4((nodeId) => {
17080
+ const handleReadModeHighlight = useCallback5((nodeId) => {
16990
17081
  if (stateRef.current.highlightedNodeId !== nodeId) {
16991
17082
  stateRef.current.highlightedNodeId = nodeId;
16992
17083
  }
16993
17084
  setHighlightedNodeId(nodeId);
16994
17085
  }, []);
16995
- const activeNodeBranches = useMemo12(() => {
17086
+ const activeNodeBranches = useMemo13(() => {
16996
17087
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
16997
17088
  return null;
16998
17089
  const fullTree = buildFullAncestryTree(
@@ -17036,7 +17127,7 @@ function XViewScene({
17036
17127
  readingMode.branchStack,
17037
17128
  ancestryDataRef.current
17038
17129
  ]);
17039
- const backNavigationInfo = useMemo12(() => {
17130
+ const backNavigationInfo = useMemo13(() => {
17040
17131
  const { branchStack } = readingMode;
17041
17132
  if (!branchStack || branchStack.length === 0) return null;
17042
17133
  const lastStep = branchStack[branchStack.length - 1];
@@ -17047,7 +17138,7 @@ function XViewScene({
17047
17138
  name: "Voltar para anterior"
17048
17139
  };
17049
17140
  }, [readingMode.branchStack]);
17050
- const getReadModeDisplayContext = useMemo12(() => {
17141
+ const getReadModeDisplayContext = useMemo13(() => {
17051
17142
  const { ancestry, branchStack } = readingMode;
17052
17143
  if (!ancestry) return null;
17053
17144
  if (branchStack.length === 0) {
@@ -17090,7 +17181,7 @@ function XViewScene({
17090
17181
  customProperties: branchProps
17091
17182
  };
17092
17183
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
17093
- const readModeAbstractionTree = useMemo12(() => {
17184
+ const readModeAbstractionTree = useMemo13(() => {
17094
17185
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
17095
17186
  return null;
17096
17187
  }
@@ -17109,7 +17200,7 @@ function XViewScene({
17109
17200
  buildFullAncestryTree,
17110
17201
  sceneVersion
17111
17202
  ]);
17112
- const handleStartReadingAncestry = useCallback4(
17203
+ const handleStartReadingAncestry = useCallback5(
17113
17204
  async (ancestryObject, renderMode = "full") => {
17114
17205
  setContextMenu(
17115
17206
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17152,7 +17243,7 @@ function XViewScene({
17152
17243
  },
17153
17244
  [handleRenderAncestry, handleRenderAbstractionTree]
17154
17245
  );
17155
- const handleReadModeSectionChange = useCallback4(
17246
+ const handleReadModeSectionChange = useCallback5(
17156
17247
  (activeSectionId) => {
17157
17248
  const { ancestry, branchStack } = readingMode;
17158
17249
  if (!ancestry || !readingMode.isActive) return;
@@ -17237,10 +17328,10 @@ function XViewScene({
17237
17328
  ancestryDataRef.current
17238
17329
  ]
17239
17330
  );
17240
- const handleCloseReadMode = useCallback4(() => {
17331
+ const handleCloseReadMode = useCallback5(() => {
17241
17332
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
17242
17333
  }, []);
17243
- const handleAncestrySectionChange = useCallback4(
17334
+ const handleAncestrySectionChange = useCallback5(
17244
17335
  (activeSectionId, ancestryOverride = null, rotation = 0) => {
17245
17336
  var _a2, _b2;
17246
17337
  const currentMode = stateRef.current.ancestry;
@@ -17302,7 +17393,7 @@ function XViewScene({
17302
17393
  },
17303
17394
  [handleRenderAncestry]
17304
17395
  );
17305
- const handleEditAncestry = useCallback4(
17396
+ const handleEditAncestry = useCallback5(
17306
17397
  async (ancestryObject) => {
17307
17398
  setContextMenu(
17308
17399
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17357,7 +17448,7 @@ function XViewScene({
17357
17448
  const handleSelectAncestryParent = (nodeId) => {
17358
17449
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
17359
17450
  };
17360
- const handleRemoveFromAncestry = useCallback4((pathToRemove) => {
17451
+ const handleRemoveFromAncestry = useCallback5((pathToRemove) => {
17361
17452
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
17362
17453
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
17363
17454
  return;
@@ -17382,7 +17473,7 @@ function XViewScene({
17382
17473
  return { ...prev, tree: newTree };
17383
17474
  });
17384
17475
  }, []);
17385
- const handleSaveAncestry = useCallback4(
17476
+ const handleSaveAncestry = useCallback5(
17386
17477
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
17387
17478
  const treeToUse = treeOverride || ancestryMode.tree;
17388
17479
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -17618,7 +17709,7 @@ function XViewScene({
17618
17709
  });
17619
17710
  setEditingAncestryRel({ visible: false, data: null, path: null });
17620
17711
  };
17621
- const handleDeleteAncestry = useCallback4(
17712
+ const handleDeleteAncestry = useCallback5(
17622
17713
  async (ancestryIdToDelete) => {
17623
17714
  if (!ancestryIdToDelete) {
17624
17715
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -17700,10 +17791,58 @@ function XViewScene({
17700
17791
  },
17701
17792
  [save_view_data, delete_file_action]
17702
17793
  );
17703
- const handleOpenAncestryBoard = useCallback4(() => {
17794
+ const handleOpenAncestryBoard = useCallback5(() => {
17704
17795
  setIsAncestryBoardOpen(true);
17705
17796
  }, []);
17706
- const handleSelectAncestryFromBoard = useCallback4(
17797
+ const allAvailableNodes = useMemo13(() => {
17798
+ if (!parentDataRef.current) return [];
17799
+ return Object.values(parentDataRef.current).flatMap(
17800
+ (fileData) => fileData.nodes || []
17801
+ );
17802
+ }, [sceneVersion, isInitialized]);
17803
+ const allAvailableAncestries = useMemo13(() => {
17804
+ return ancestryDataRef.current || [];
17805
+ }, [sceneVersion, isInitialized]);
17806
+ const handleOpenReference = useCallback5(
17807
+ (referenceData) => {
17808
+ const { type, id } = referenceData;
17809
+ if (type === "node") {
17810
+ const targetNode = allAvailableNodes.find(
17811
+ (n) => String(n.id) === String(id)
17812
+ );
17813
+ if (targetNode) {
17814
+ setAncestryLinkDetails(null);
17815
+ setDetailsLink(null);
17816
+ setDetailsNode(targetNode);
17817
+ const sceneMesh = stateRef.current.nodeObjects[String(id)];
17818
+ if (sceneMesh) {
17819
+ tweenToTarget(sceneMesh);
17820
+ }
17821
+ } else {
17822
+ alert("Node original n\xE3o encontrado neste contexto.");
17823
+ }
17824
+ } else if (type === "ancestry") {
17825
+ const targetAncestry = allAvailableAncestries.find(
17826
+ (a) => String(a.ancestry_id) === String(id)
17827
+ );
17828
+ if (targetAncestry) {
17829
+ setDetailsNode(null);
17830
+ setDetailsLink(null);
17831
+ setAncestryLinkDetails(null);
17832
+ handleEditAncestry(targetAncestry);
17833
+ } else {
17834
+ alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17835
+ }
17836
+ }
17837
+ },
17838
+ [
17839
+ allAvailableNodes,
17840
+ allAvailableAncestries,
17841
+ handleEditAncestry,
17842
+ tweenToTarget
17843
+ ]
17844
+ );
17845
+ const handleSelectAncestryFromBoard = useCallback5(
17707
17846
  (item) => {
17708
17847
  setIsAncestryBoardOpen(false);
17709
17848
  setIsSidebarOpen(false);
@@ -17715,7 +17854,7 @@ function XViewScene({
17715
17854
  },
17716
17855
  [handleStartReadingAncestry, handleOpenReference]
17717
17856
  );
17718
- const handleSaveAncestryBoard = useCallback4(
17857
+ const handleSaveAncestryBoard = useCallback5(
17719
17858
  async (groups) => {
17720
17859
  if (!sceneConfigId || !viewParams || !session) return;
17721
17860
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
@@ -17729,7 +17868,7 @@ function XViewScene({
17729
17868
  },
17730
17869
  [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
17731
17870
  );
17732
- const existingNodeTypes = useMemo12(() => {
17871
+ const existingNodeTypes = useMemo13(() => {
17733
17872
  if (!parentDataRef.current) {
17734
17873
  return [];
17735
17874
  }
@@ -17741,7 +17880,7 @@ function XViewScene({
17741
17880
  ).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
17742
17881
  return [...new Set(allTypes)];
17743
17882
  }, [parentDataRef.current, sceneVersion]);
17744
- const searchableDbNodes = useMemo12(() => {
17883
+ const searchableDbNodes = useMemo13(() => {
17745
17884
  if (!parentDataRef.current) {
17746
17885
  return [];
17747
17886
  }
@@ -17756,7 +17895,7 @@ function XViewScene({
17756
17895
  return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
17757
17896
  });
17758
17897
  }, [parentDataRef.current, sceneVersion]);
17759
- const handleAddExistingNode = useCallback4(
17898
+ const handleAddExistingNode = useCallback5(
17760
17899
  (nodeId) => {
17761
17900
  return userActionHandlers.handleAddExistingNodeById(
17762
17901
  actionHandlerContext,
@@ -17765,7 +17904,7 @@ function XViewScene({
17765
17904
  },
17766
17905
  [actionHandlerContext]
17767
17906
  );
17768
- const handleUpdateMilestones = useCallback4(
17907
+ const handleUpdateMilestones = useCallback5(
17769
17908
  async (newMilestones) => {
17770
17909
  var _a2, _b2, _c2;
17771
17910
  if (!sceneDataRef.current) return;
@@ -17811,7 +17950,7 @@ function XViewScene({
17811
17950
  viewParams == null ? void 0 : viewParams.type
17812
17951
  ]
17813
17952
  );
17814
- const handleSaveCurrentView = useCallback4(async () => {
17953
+ const handleSaveCurrentView = useCallback5(async () => {
17815
17954
  var _a2, _b2, _c2;
17816
17955
  const { nodeObjects, allLinks } = stateRef.current;
17817
17956
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
@@ -17854,61 +17993,13 @@ function XViewScene({
17854
17993
  console.error("Erro na chamada de save_view_data:", error);
17855
17994
  }
17856
17995
  }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
17857
- const allAvailableNodes = useMemo12(() => {
17858
- if (!parentDataRef.current) return [];
17859
- return Object.values(parentDataRef.current).flatMap(
17860
- (fileData) => fileData.nodes || []
17861
- );
17862
- }, [sceneVersion, isInitialized]);
17863
- const allAvailableAncestries = useMemo12(() => {
17864
- return ancestryDataRef.current || [];
17865
- }, [sceneVersion, isInitialized]);
17866
- const handleOpenReference = useCallback4(
17867
- (referenceData) => {
17868
- const { type, id } = referenceData;
17869
- if (type === "node") {
17870
- const targetNode = allAvailableNodes.find(
17871
- (n) => String(n.id) === String(id)
17872
- );
17873
- if (targetNode) {
17874
- setAncestryLinkDetails(null);
17875
- setDetailsLink(null);
17876
- setDetailsNode(targetNode);
17877
- const sceneMesh = stateRef.current.nodeObjects[String(id)];
17878
- if (sceneMesh) {
17879
- tweenToTarget(sceneMesh);
17880
- }
17881
- } else {
17882
- alert("Node original n\xE3o encontrado neste contexto.");
17883
- }
17884
- } else if (type === "ancestry") {
17885
- const targetAncestry = allAvailableAncestries.find(
17886
- (a) => String(a.ancestry_id) === String(id)
17887
- );
17888
- if (targetAncestry) {
17889
- setDetailsNode(null);
17890
- setDetailsLink(null);
17891
- setAncestryLinkDetails(null);
17892
- handleEditAncestry(targetAncestry);
17893
- } else {
17894
- alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17895
- }
17896
- }
17897
- },
17898
- [
17899
- allAvailableNodes,
17900
- allAvailableAncestries,
17901
- handleEditAncestry,
17902
- tweenToTarget
17903
- ]
17904
- );
17905
- const handleToggleAncestryAddMode = useCallback4(() => {
17996
+ const handleToggleAncestryAddMode = useCallback5(() => {
17906
17997
  setAncestryMode((prev) => ({
17907
17998
  ...prev,
17908
17999
  isAddingNodes: !prev.isAddingNodes
17909
18000
  }));
17910
18001
  }, []);
17911
- const handleFocusNode = useCallback4(
18002
+ const handleFocusNode = useCallback5(
17912
18003
  (nodeData) => {
17913
18004
  var _a2;
17914
18005
  if (!nodeData) return;
@@ -17924,7 +18015,7 @@ function XViewScene({
17924
18015
  },
17925
18016
  [tweenToTarget]
17926
18017
  );
17927
- const availableDatasets = useMemo12(() => {
18018
+ const availableDatasets = useMemo13(() => {
17928
18019
  if (!sceneDataRef.current || !parentDataRef.current) return [];
17929
18020
  return sceneDataRef.current.parent_dbs.map((db) => {
17930
18021
  var _a2;
@@ -17938,7 +18029,7 @@ function XViewScene({
17938
18029
  String(creationMode.sourceNodeData.id)
17939
18030
  )) == null ? void 0 : _b.parentFileId : null;
17940
18031
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
17941
- useEffect22(() => {
18032
+ useEffect24(() => {
17942
18033
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
17943
18034
  const nodeObjects = stateRef.current.nodeObjects || {};
17944
18035
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -17961,7 +18052,7 @@ function XViewScene({
17961
18052
  hasFocusedInitial,
17962
18053
  tweenToTarget
17963
18054
  ]);
17964
- useEffect22(() => {
18055
+ useEffect24(() => {
17965
18056
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
17966
18057
  const ancestries = ancestryDataRef.current || [];
17967
18058
  const targetAncestry = ancestries.find(
@@ -17986,7 +18077,7 @@ function XViewScene({
17986
18077
  hasOpenedInitialAncestry,
17987
18078
  handleStartReadingAncestry
17988
18079
  ]);
17989
- useEffect22(() => {
18080
+ useEffect24(() => {
17990
18081
  function handleKeyDown(event) {
17991
18082
  var _a2, _b2, _c2;
17992
18083
  const context = actionHandlerContext;
@@ -18109,10 +18200,10 @@ function XViewScene({
18109
18200
  // <-- handleCancelQuest adicionado aqui
18110
18201
  ]);
18111
18202
  if (isLoading || status === "loading" || permissionStatus === "loading") {
18112
- return /* @__PURE__ */ React28.createElement(LoadingScreen, null);
18203
+ return /* @__PURE__ */ React30.createElement(LoadingScreen, null);
18113
18204
  }
18114
18205
  if (permissionStatus === "denied") {
18115
- return /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ React28.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ React28.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ React28.createElement(
18206
+ return /* @__PURE__ */ React30.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ React30.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ React30.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ React30.createElement(
18116
18207
  "svg",
18117
18208
  {
18118
18209
  xmlns: "http://www.w3.org/2000/svg",
@@ -18122,7 +18213,7 @@ function XViewScene({
18122
18213
  stroke: "currentColor",
18123
18214
  className: "w-16 h-16 mx-auto"
18124
18215
  },
18125
- /* @__PURE__ */ React28.createElement(
18216
+ /* @__PURE__ */ React30.createElement(
18126
18217
  "path",
18127
18218
  {
18128
18219
  strokeLinecap: "round",
@@ -18130,13 +18221,13 @@ function XViewScene({
18130
18221
  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"
18131
18222
  }
18132
18223
  )
18133
- )), /* @__PURE__ */ React28.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ React28.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__ */ React28.createElement(
18224
+ )), /* @__PURE__ */ React30.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ React30.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__ */ React30.createElement(
18134
18225
  "button",
18135
18226
  {
18136
18227
  onClick: () => router.push("/dashboard/scenes"),
18137
18228
  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"
18138
18229
  },
18139
- /* @__PURE__ */ React28.createElement(
18230
+ /* @__PURE__ */ React30.createElement(
18140
18231
  "svg",
18141
18232
  {
18142
18233
  xmlns: "http://www.w3.org/2000/svg",
@@ -18146,7 +18237,7 @@ function XViewScene({
18146
18237
  stroke: "currentColor",
18147
18238
  className: "w-5 h-5"
18148
18239
  },
18149
- /* @__PURE__ */ React28.createElement(
18240
+ /* @__PURE__ */ React30.createElement(
18150
18241
  "path",
18151
18242
  {
18152
18243
  strokeLinecap: "round",
@@ -18158,7 +18249,7 @@ function XViewScene({
18158
18249
  "Voltar para Scenes"
18159
18250
  )));
18160
18251
  }
18161
- return /* @__PURE__ */ React28.createElement(
18252
+ return /* @__PURE__ */ React30.createElement(
18162
18253
  "div",
18163
18254
  {
18164
18255
  ref: mountRef,
@@ -18170,7 +18261,7 @@ function XViewScene({
18170
18261
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
18171
18262
  }
18172
18263
  },
18173
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ React28.createElement(
18264
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ React30.createElement(
18174
18265
  XViewSidebar,
18175
18266
  {
18176
18267
  dbNodes: searchableDbNodes,
@@ -18194,7 +18285,7 @@ function XViewScene({
18194
18285
  onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
18195
18286
  }
18196
18287
  ),
18197
- creationMode.isActive && /* @__PURE__ */ React28.createElement(
18288
+ creationMode.isActive && /* @__PURE__ */ React30.createElement(
18198
18289
  InSceneCreationForm,
18199
18290
  {
18200
18291
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -18226,7 +18317,7 @@ function XViewScene({
18226
18317
  availableAncestries: allAvailableAncestries
18227
18318
  }
18228
18319
  ),
18229
- versionMode.isActive && /* @__PURE__ */ React28.createElement(
18320
+ versionMode.isActive && /* @__PURE__ */ React30.createElement(
18230
18321
  InSceneVersionForm,
18231
18322
  {
18232
18323
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -18252,7 +18343,7 @@ function XViewScene({
18252
18343
  availableAncestries: allAvailableAncestries
18253
18344
  }
18254
18345
  ),
18255
- questMode.isActive && /* @__PURE__ */ React28.createElement(
18346
+ questMode.isActive && /* @__PURE__ */ React30.createElement(
18256
18347
  InSceneQuestForm,
18257
18348
  {
18258
18349
  onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
@@ -18280,7 +18371,7 @@ function XViewScene({
18280
18371
  onUpdateMilestones: handleUpdateMilestones
18281
18372
  }
18282
18373
  ),
18283
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React28.createElement(
18374
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React30.createElement(
18284
18375
  "div",
18285
18376
  {
18286
18377
  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"}`,
@@ -18293,7 +18384,7 @@ function XViewScene({
18293
18384
  maxWidth: "92vw"
18294
18385
  }
18295
18386
  },
18296
- /* @__PURE__ */ React28.createElement(
18387
+ /* @__PURE__ */ React30.createElement(
18297
18388
  "div",
18298
18389
  {
18299
18390
  onPointerDown: (e) => {
@@ -18304,7 +18395,7 @@ function XViewScene({
18304
18395
  title: "Arraste para redimensionar"
18305
18396
  }
18306
18397
  ),
18307
- /* @__PURE__ */ React28.createElement(
18398
+ /* @__PURE__ */ React30.createElement(
18308
18399
  DescriptionReadModePanel,
18309
18400
  {
18310
18401
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -18339,7 +18430,7 @@ function XViewScene({
18339
18430
  }
18340
18431
  )
18341
18432
  ),
18342
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React28.createElement(
18433
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React30.createElement(
18343
18434
  CreateAncestryPanel,
18344
18435
  {
18345
18436
  ancestryMode,
@@ -18375,7 +18466,7 @@ function XViewScene({
18375
18466
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
18376
18467
  }
18377
18468
  ),
18378
- editingAncestryRel.visible && /* @__PURE__ */ React28.createElement(
18469
+ editingAncestryRel.visible && /* @__PURE__ */ React30.createElement(
18379
18470
  AncestryRelationshipPanel,
18380
18471
  {
18381
18472
  data: editingAncestryRel.data,
@@ -18389,7 +18480,7 @@ function XViewScene({
18389
18480
  onUploadFile: upload_file_action
18390
18481
  }
18391
18482
  ),
18392
- detailsNode && detailsNode.is_quest && /* @__PURE__ */ React28.createElement(
18483
+ detailsNode && detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
18393
18484
  QuestDetailsPanel,
18394
18485
  {
18395
18486
  node: detailsNode,
@@ -18415,7 +18506,7 @@ function XViewScene({
18415
18506
  onUpdateMilestones: handleUpdateMilestones
18416
18507
  }
18417
18508
  ),
18418
- detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React28.createElement(
18509
+ detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
18419
18510
  NodeDetailsPanel,
18420
18511
  {
18421
18512
  node: detailsNode,
@@ -18447,7 +18538,7 @@ function XViewScene({
18447
18538
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
18448
18539
  }
18449
18540
  ),
18450
- detailsLink && /* @__PURE__ */ React28.createElement(
18541
+ detailsLink && /* @__PURE__ */ React30.createElement(
18451
18542
  RelationshipDetailsPanel,
18452
18543
  {
18453
18544
  link: detailsLink,
@@ -18461,7 +18552,7 @@ function XViewScene({
18461
18552
  userRole: userPermissionRole
18462
18553
  }
18463
18554
  ),
18464
- ancestryLinkDetails && /* @__PURE__ */ React28.createElement(
18555
+ ancestryLinkDetails && /* @__PURE__ */ React30.createElement(
18465
18556
  AncestryLinkDetailsPanel,
18466
18557
  {
18467
18558
  data: ancestryLinkDetails,
@@ -18472,7 +18563,7 @@ function XViewScene({
18472
18563
  onUploadFile: upload_file_action
18473
18564
  }
18474
18565
  ),
18475
- /* @__PURE__ */ React28.createElement(
18566
+ /* @__PURE__ */ React30.createElement(
18476
18567
  "div",
18477
18568
  {
18478
18569
  ref: tooltipRef,
@@ -18499,7 +18590,7 @@ function XViewScene({
18499
18590
  }
18500
18591
  }
18501
18592
  ),
18502
- /* @__PURE__ */ React28.createElement(
18593
+ /* @__PURE__ */ React30.createElement(
18503
18594
  ContextMenu,
18504
18595
  {
18505
18596
  data: contextMenu,
@@ -18532,7 +18623,7 @@ function XViewScene({
18532
18623
  onFinishQuest: handleFinishQuestQuick
18533
18624
  }
18534
18625
  ),
18535
- /* @__PURE__ */ React28.createElement(
18626
+ /* @__PURE__ */ React30.createElement(
18536
18627
  MultiNodeContextMenu,
18537
18628
  {
18538
18629
  data: multiContextMenu,
@@ -18552,7 +18643,7 @@ function XViewScene({
18552
18643
  )
18553
18644
  }
18554
18645
  ),
18555
- /* @__PURE__ */ React28.createElement(
18646
+ /* @__PURE__ */ React30.createElement(
18556
18647
  RelationshipContextMenu,
18557
18648
  {
18558
18649
  data: relationshipMenu,
@@ -18570,14 +18661,14 @@ function XViewScene({
18570
18661
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
18571
18662
  }
18572
18663
  ),
18573
- /* @__PURE__ */ React28.createElement(
18664
+ /* @__PURE__ */ React30.createElement(
18574
18665
  ImageViewer,
18575
18666
  {
18576
18667
  data: imageViewer,
18577
18668
  onClose: () => setImageViewer({ ...imageViewer, visible: false })
18578
18669
  }
18579
18670
  ),
18580
- /* @__PURE__ */ React28.createElement(
18671
+ /* @__PURE__ */ React30.createElement(
18581
18672
  AncestryBoard,
18582
18673
  {
18583
18674
  isOpen: isAncestryBoardOpen,
@@ -18590,7 +18681,7 @@ function XViewScene({
18590
18681
  userRole: userPermissionRole
18591
18682
  }
18592
18683
  ),
18593
- /* @__PURE__ */ React28.createElement(
18684
+ /* @__PURE__ */ React30.createElement(
18594
18685
  MilestoneManager,
18595
18686
  {
18596
18687
  isOpen: isMilestoneManagerOpen,
@@ -18599,7 +18690,7 @@ function XViewScene({
18599
18690
  onUpdateMilestones: handleUpdateMilestones
18600
18691
  }
18601
18692
  ),
18602
- /* @__PURE__ */ React28.createElement(
18693
+ /* @__PURE__ */ React30.createElement(
18603
18694
  ImportParentFileModal,
18604
18695
  {
18605
18696
  isOpen: isImportModalOpen,
@@ -18612,7 +18703,7 @@ function XViewScene({
18612
18703
  currentAncestries: ancestryDataRef.current || []
18613
18704
  }
18614
18705
  ),
18615
- invalidTargetError && /* @__PURE__ */ React28.createElement(
18706
+ invalidTargetError && /* @__PURE__ */ React30.createElement(
18616
18707
  "div",
18617
18708
  {
18618
18709
  className: "ui-overlay",
@@ -18637,13 +18728,13 @@ function XViewScene({
18637
18728
  animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
18638
18729
  }
18639
18730
  },
18640
- /* @__PURE__ */ React28.createElement("style", null, `
18731
+ /* @__PURE__ */ React30.createElement("style", null, `
18641
18732
  @keyframes fadeInDown {
18642
18733
  from { opacity: 0; transform: translate(-50%, -20px); }
18643
18734
  to { opacity: 1; transform: translate(-50%, 0); }
18644
18735
  }
18645
18736
  `),
18646
- /* @__PURE__ */ React28.createElement(
18737
+ /* @__PURE__ */ React30.createElement(
18647
18738
  "svg",
18648
18739
  {
18649
18740
  width: "20",
@@ -18655,12 +18746,12 @@ function XViewScene({
18655
18746
  strokeLinecap: "round",
18656
18747
  strokeLinejoin: "round"
18657
18748
  },
18658
- /* @__PURE__ */ React28.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18659
- /* @__PURE__ */ React28.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18660
- /* @__PURE__ */ React28.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18749
+ /* @__PURE__ */ React30.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18750
+ /* @__PURE__ */ React30.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18751
+ /* @__PURE__ */ React30.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18661
18752
  ),
18662
- /* @__PURE__ */ React28.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18663
- /* @__PURE__ */ React28.createElement(
18753
+ /* @__PURE__ */ React30.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18754
+ /* @__PURE__ */ React30.createElement(
18664
18755
  "button",
18665
18756
  {
18666
18757
  onClick: () => setInvalidTargetError(null),