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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -44,9 +44,9 @@ __export(index_exports, {
44
44
  module.exports = __toCommonJS(index_exports);
45
45
 
46
46
  // src/XViewScene.jsx
47
- var import_react32 = __toESM(require("react"));
47
+ var import_react31 = __toESM(require("react"));
48
48
  var import_navigation = require("next/navigation");
49
- var import_react33 = require("next-auth/react");
49
+ var import_react32 = require("next-auth/react");
50
50
  var import_crypto_js = __toESM(require("crypto-js"));
51
51
  var THREE3 = __toESM(require("three"));
52
52
  var import_OrbitControls = require("three/examples/jsm/controls/OrbitControls.js");
@@ -1092,6 +1092,8 @@ var userActionHandlers = {
1092
1092
  if (isCrossDataset) {
1093
1093
  graphDataRef.current[finalTargetDatasetId] = targetDataToUpdate;
1094
1094
  }
1095
+ if (sceneDataRef.current.parent_dbs.some((db) => String(db.db_id) === String(sourceParentInfo.parentFileId))) {
1096
+ }
1095
1097
  const finalPosition = stateRef.current.ghostElements.node.position.clone();
1096
1098
  addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
1097
1099
  stateRef.current.nodeIdToParentFileMap.set(String(newNode.id), {
@@ -1290,6 +1292,9 @@ var userActionHandlers = {
1290
1292
  );
1291
1293
  }
1292
1294
  graphDataRef.current[parentFileId] = specificParentData;
1295
+ if (isView && parentFileId === context.sceneConfigId) {
1296
+ sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
1297
+ }
1293
1298
  const finalPosition = stateRef.current.ghostElements.node.position.clone();
1294
1299
  addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
1295
1300
  setters.setSceneVersion((v) => v + 1);
@@ -2309,8 +2314,6 @@ var userActionHandlers = {
2309
2314
  milestones: sceneDataRef.current.milestones || [],
2310
2315
  quest_counter: sceneDataRef.current.quest_counter || 1
2311
2316
  };
2312
- sceneDataRef.current.quest_nodes = specificParentData.nodes;
2313
- sceneDataRef.current.quest_links = specificParentData.links;
2314
2317
  await context.actions.save_view_data(
2315
2318
  context.sceneSaveUrl,
2316
2319
  viewFilePayload
@@ -2323,6 +2326,10 @@ var userActionHandlers = {
2323
2326
  );
2324
2327
  }
2325
2328
  graphDataRef.current[parentFileId] = specificParentData;
2329
+ if (isView && parentFileId === context.sceneConfigId) {
2330
+ sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
2331
+ sceneDataRef.current.quest_counter = specificParentData.quest_counter || sceneDataRef.current.quest_counter;
2332
+ }
2326
2333
  updateExistingNodeVisuals(stateRef.current, nodeToSave);
2327
2334
  setters.setSceneVersion((v) => v + 1);
2328
2335
  if (!keepOpen) {
@@ -12912,348 +12919,581 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
12912
12919
  }
12913
12920
 
12914
12921
  // src/components/AncestryBoard.jsx
12915
- var import_react30 = __toESM(require("react"));
12922
+ var import_react29 = __toESM(require("react"));
12916
12923
  var import_fi23 = require("react-icons/fi");
12917
12924
  var import_uuid11 = require("uuid");
12918
12925
 
12919
- // src/components/MentionEditor.jsx
12926
+ // src/components/RichGroupEditor.jsx
12920
12927
  var import_react28 = __toESM(require("react"));
12921
- var import_react29 = require("@tiptap/react");
12922
- var import_starter_kit = __toESM(require("@tiptap/starter-kit"));
12923
- var import_extension_mention = __toESM(require("@tiptap/extension-mention"));
12924
- var import_tippy = __toESM(require("tippy.js"));
12925
12928
 
12926
- // src/components/MentionList.jsx
12929
+ // src/components/MentionPopover.jsx
12927
12930
  var import_react27 = __toESM(require("react"));
12928
12931
  var import_fi22 = require("react-icons/fi");
12929
- var MentionList = (0, import_react27.forwardRef)((props, ref) => {
12930
- const [selectedIndex, setSelectedIndex] = (0, import_react27.useState)(0);
12931
- const selectItem = (index) => {
12932
- const item = props.items[index];
12933
- if (item) {
12934
- props.command({ id: item.id, label: item.name, type: item.type });
12935
- }
12936
- };
12937
- const upHandler = () => {
12938
- setSelectedIndex(
12939
- (selectedIndex + props.items.length - 1) % props.items.length
12940
- );
12941
- };
12942
- const downHandler = () => {
12943
- setSelectedIndex((selectedIndex + 1) % props.items.length);
12944
- };
12945
- const enterHandler = () => {
12946
- selectItem(selectedIndex);
12947
- };
12948
- (0, import_react27.useEffect)(() => setSelectedIndex(0), [props.items]);
12949
- (0, import_react27.useImperativeHandle)(ref, () => ({
12950
- onKeyDown: ({ event }) => {
12951
- if (event.key === "ArrowUp") {
12952
- upHandler();
12953
- return true;
12954
- }
12955
- if (event.key === "ArrowDown") {
12956
- downHandler();
12957
- return true;
12958
- }
12959
- if (event.key === "Enter") {
12960
- enterHandler();
12961
- return true;
12932
+ var TYPE_CONFIG = {
12933
+ ancestry: { Icon: import_fi22.FiLayers, color: "text-indigo-400", label: "Ancestralidade" },
12934
+ quest: { Icon: import_fi22.FiCheckSquare, color: "text-emerald-400", label: "Quest" },
12935
+ version: { Icon: import_fi22.FiGitBranch, color: "text-amber-400", label: "Vers\xE3o" },
12936
+ node: { Icon: import_fi22.FiBox, color: "text-slate-400", label: "Node" }
12937
+ };
12938
+ function MentionPopover({ query, items, position, onSelect, onClose }) {
12939
+ const [activeIndex, setActiveIndex] = (0, import_react27.useState)(0);
12940
+ const listRef = (0, import_react27.useRef)(null);
12941
+ const filtered = (0, import_react27.useMemo)(() => {
12942
+ const term = (query || "").toLowerCase().trim();
12943
+ if (!term) return items.slice(0, 8);
12944
+ return items.filter(
12945
+ (item) => (item.searchLabel || "").toLowerCase().includes(term) || (item.searchDesc || "").toLowerCase().includes(term)
12946
+ ).slice(0, 8);
12947
+ }, [items, query]);
12948
+ (0, import_react27.useEffect)(() => {
12949
+ setActiveIndex(0);
12950
+ }, [query]);
12951
+ (0, import_react27.useEffect)(() => {
12952
+ const handleKeyDown = (e) => {
12953
+ if (e.key === "ArrowDown") {
12954
+ e.preventDefault();
12955
+ setActiveIndex((i) => Math.min(i + 1, filtered.length - 1));
12956
+ } else if (e.key === "ArrowUp") {
12957
+ e.preventDefault();
12958
+ setActiveIndex((i) => Math.max(i - 1, 0));
12959
+ } else if (e.key === "Enter" || e.key === "Tab") {
12960
+ e.preventDefault();
12961
+ if (filtered[activeIndex]) onSelect(filtered[activeIndex]);
12962
+ } else if (e.key === "Escape") {
12963
+ e.preventDefault();
12964
+ e.stopPropagation();
12965
+ e.stopImmediatePropagation();
12966
+ onClose();
12962
12967
  }
12963
- return false;
12964
- }
12965
- }));
12966
- return /* @__PURE__ */ import_react27.default.createElement("div", { className: "z-[3000] bg-slate-900 border border-white/10 rounded-lg shadow-2xl overflow-hidden min-w-[280px] max-w-[400px] animate-in fade-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react27.default.createElement("div", { className: "p-2 border-b border-white/5 bg-slate-950/50 flex items-center gap-2" }, /* @__PURE__ */ import_react27.default.createElement(import_fi22.FiSearch, { className: "text-indigo-400", size: 14 }), /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-[10px] uppercase tracking-wider font-bold text-slate-500" }, "Mencionar Recurso")), /* @__PURE__ */ import_react27.default.createElement("div", { className: "p-1 max-h-[300px] overflow-y-auto custom-scrollbar" }, props.items.length ? props.items.map((item, index) => {
12967
- const isQuest = item.type === "quest";
12968
- const isVersion = item.type === "version";
12969
- const isNode = item.type === "node";
12970
- let Icon = import_fi22.FiLayers;
12971
- let colorClass = "text-indigo-400";
12972
- let badgeText = "Ancestralidade";
12973
- if (isQuest) {
12974
- Icon = import_fi22.FiCheckSquare;
12975
- colorClass = "text-amber-400";
12976
- badgeText = "Quest";
12977
- } else if (isVersion) {
12978
- Icon = import_fi22.FiGitBranch;
12979
- colorClass = "text-purple-400";
12980
- badgeText = "Vers\xE3o";
12981
- } else if (isNode) {
12982
- Icon = import_fi22.FiBox;
12983
- colorClass = "text-emerald-400";
12984
- badgeText = "Node";
12985
- }
12986
- return /* @__PURE__ */ import_react27.default.createElement(
12987
- "button",
12988
- {
12989
- className: `
12990
- w-full flex items-center gap-3 px-3 py-2 text-left rounded-md transition-all
12991
- ${index === selectedIndex ? "bg-indigo-500/20 border border-indigo-500/30 text-white" : "text-slate-400 hover:bg-white/5 border border-transparent"}
12992
- `,
12993
- key: item.id,
12994
- onClick: () => selectItem(index)
12995
- },
12996
- /* @__PURE__ */ import_react27.default.createElement("div", { className: `shrink-0 w-8 h-8 rounded border border-white/5 flex items-center justify-center bg-slate-800/50 ${colorClass}` }, /* @__PURE__ */ import_react27.default.createElement(Icon, { size: 14 })),
12997
- /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-sm font-medium truncate" }, item.name), /* @__PURE__ */ import_react27.default.createElement("span", { className: `text-[9px] px-1 py-0.5 rounded border border-current opacity-60 ${colorClass}` }, badgeText)))
12998
- );
12999
- }) : /* @__PURE__ */ import_react27.default.createElement("div", { className: "p-4 text-center text-slate-500 text-sm italic" }, "Nenhum resultado encontrado...")));
13000
- });
13001
- MentionList.displayName = "MentionList";
13002
- var MentionList_default = MentionList;
12968
+ };
12969
+ window.addEventListener("keydown", handleKeyDown, true);
12970
+ return () => window.removeEventListener("keydown", handleKeyDown, true);
12971
+ }, [filtered, activeIndex, onSelect, onClose]);
12972
+ (0, import_react27.useEffect)(() => {
12973
+ if (listRef.current) {
12974
+ const el = listRef.current.children[activeIndex];
12975
+ if (el) el.scrollIntoView({ block: "nearest" });
12976
+ }
12977
+ }, [activeIndex]);
12978
+ return /* @__PURE__ */ import_react27.default.createElement(
12979
+ "div",
12980
+ {
12981
+ style: { top: position.top, left: position.left, position: "fixed", zIndex: 9999 },
12982
+ 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",
12983
+ ref: listRef,
12984
+ onMouseDown: (e) => e.preventDefault()
12985
+ },
12986
+ filtered.length === 0 ? /* @__PURE__ */ import_react27.default.createElement("div", { className: "px-4 py-3 text-xs text-slate-500" }, "Nenhum resultado para", " ", /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-slate-300 font-medium" }, '"', query, '"')) : filtered.map((item, idx) => {
12987
+ const config = TYPE_CONFIG[item.type] || TYPE_CONFIG.node;
12988
+ const { Icon } = config;
12989
+ return /* @__PURE__ */ import_react27.default.createElement(
12990
+ "div",
12991
+ {
12992
+ key: item.id,
12993
+ onMouseDown: (e) => {
12994
+ e.preventDefault();
12995
+ onSelect(item);
12996
+ },
12997
+ onMouseEnter: () => setActiveIndex(idx),
12998
+ 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"}`
12999
+ },
13000
+ /* @__PURE__ */ import_react27.default.createElement(Icon, { size: 13, className: config.color }),
13001
+ /* @__PURE__ */ import_react27.default.createElement("span", { className: "flex-1 truncate font-medium" }, item.searchLabel || "Sem Nome"),
13002
+ /* @__PURE__ */ import_react27.default.createElement("span", { className: "text-[9px] px-1.5 py-0.5 rounded-full bg-white/5 text-slate-500 border border-white/5 uppercase tracking-wide shrink-0" }, config.label)
13003
+ );
13004
+ })
13005
+ );
13006
+ }
13003
13007
 
13004
- // src/components/MentionEditor.jsx
13005
- var CustomMention = import_extension_mention.default.extend({
13006
- addAttributes() {
13008
+ // src/components/RichGroupEditor.jsx
13009
+ 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;";
13010
+ var MENTION_TYPE_STYLE = {
13011
+ ancestry: "background:rgba(99,102,241,0.18);color:#a5b4fc;border:1px solid rgba(99,102,241,0.35);",
13012
+ quest: "background:rgba(16,185,129,0.18);color:#6ee7b7;border:1px solid rgba(16,185,129,0.35);",
13013
+ version: "background:rgba(245,158,11,0.18);color:#fcd34d;border:1px solid rgba(245,158,11,0.35);",
13014
+ node: "background:rgba(100,116,139,0.18);color:#94a3b8;border:1px solid rgba(100,116,139,0.35);"
13015
+ };
13016
+ function mentionStyle(type) {
13017
+ return MENTION_BASE_STYLE + (MENTION_TYPE_STYLE[type] || MENTION_TYPE_STYLE.node);
13018
+ }
13019
+ function escapeHtml(str) {
13020
+ return String(str || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
13021
+ }
13022
+ function contentToHTML(content) {
13023
+ if (!content || content.length === 0) return "";
13024
+ return content.map((seg) => {
13025
+ if (seg.type === "text") {
13026
+ return escapeHtml(seg.value).replace(/\n/g, "<br>");
13027
+ }
13028
+ if (seg.type === "mention") {
13029
+ const style = mentionStyle(seg.mentionType);
13030
+ 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>`;
13031
+ }
13032
+ return "";
13033
+ }).join("");
13034
+ }
13035
+ function domToContent(el) {
13036
+ const segments = [];
13037
+ function pushText(text) {
13038
+ const clean = text.replace(/\u200B/g, "");
13039
+ if (!clean) return;
13040
+ const last = segments[segments.length - 1];
13041
+ if (last && last.type === "text") {
13042
+ last.value += clean;
13043
+ } else {
13044
+ segments.push({ type: "text", value: clean });
13045
+ }
13046
+ }
13047
+ function walk(node) {
13007
13048
  var _a;
13008
- return {
13009
- ...(_a = this.parent) == null ? void 0 : _a.call(this),
13010
- type: {
13011
- default: null,
13012
- parseHTML: (element) => element.getAttribute("data-mention-type"),
13013
- renderHTML: (attributes) => {
13014
- if (!attributes.type) {
13015
- return {};
13016
- }
13017
- return {
13018
- "data-mention-type": attributes.type
13019
- };
13049
+ if (node.nodeType === Node.TEXT_NODE) {
13050
+ pushText(node.textContent);
13051
+ } else if (node.nodeType === Node.ELEMENT_NODE) {
13052
+ if (((_a = node.dataset) == null ? void 0 : _a.mention) === "true") {
13053
+ segments.push({
13054
+ type: "mention",
13055
+ id: node.dataset.id,
13056
+ name: node.dataset.name,
13057
+ mentionType: node.dataset.mentionType
13058
+ });
13059
+ } else if (node.tagName === "BR") {
13060
+ pushText("\n");
13061
+ } else {
13062
+ if (["DIV", "P"].includes(node.tagName) && segments.length > 0) {
13063
+ pushText("\n");
13020
13064
  }
13065
+ node.childNodes.forEach(walk);
13021
13066
  }
13022
- };
13067
+ }
13023
13068
  }
13024
- });
13025
- var MentionEditor = ({
13026
- initialValue = "",
13069
+ el.childNodes.forEach(walk);
13070
+ return segments;
13071
+ }
13072
+ function RichGroupEditor({
13073
+ content,
13027
13074
  onChange,
13028
- onPlay,
13029
- // Mantido para futura expansão se quisermos badges clicáveis reais no editor
13030
- availableItems = [],
13031
- canEdit = true,
13032
- placeholder = "Escreva algo... use @ para mencionar"
13033
- }) => {
13034
- const parseInitialContent = (text) => {
13035
- if (!text) return "<p></p>";
13036
- const parts = text.split(/(\[\[MENTION:[^\]]+\]\])/g);
13037
- return parts.map((part) => {
13038
- const match = part.match(/\[\[MENTION:([^:]+):([^:]+):([^\]]+)\]\]/);
13039
- if (match) {
13040
- const [, type, id, label] = match;
13041
- return `<span data-type="mention" data-id="${id}" data-mention-type="${type}" data-label="${label}">@${label}</span>`;
13042
- }
13043
- return part;
13044
- }).join("");
13045
- };
13046
- const content = (0, import_react28.useMemo)(() => parseInitialContent(initialValue), [initialValue]);
13047
- const editor = (0, import_react29.useEditor)({
13048
- extensions: [
13049
- import_starter_kit.default.configure({
13050
- heading: false,
13051
- bulletList: false,
13052
- orderedList: false,
13053
- codeBlock: false,
13054
- blockquote: false
13055
- }),
13056
- CustomMention.configure({
13057
- HTMLAttributes: {
13058
- class: "mention"
13059
- },
13060
- suggestion: {
13061
- items: ({ query }) => {
13062
- return availableItems.filter(
13063
- (item) => item.name.toLowerCase().includes(query.toLowerCase())
13064
- ).slice(0, 10);
13065
- },
13066
- render: () => {
13067
- let component;
13068
- let popup;
13069
- return {
13070
- onStart: (props) => {
13071
- component = new import_react29.ReactRenderer(MentionList_default, {
13072
- props,
13073
- editor: props.editor
13074
- });
13075
- if (!props.clientRect) {
13076
- return;
13077
- }
13078
- popup = (0, import_tippy.default)("body", {
13079
- getReferenceClientRect: props.clientRect,
13080
- appendTo: () => document.body,
13081
- content: component.element,
13082
- showOnCreate: true,
13083
- interactive: true,
13084
- trigger: "manual",
13085
- placement: "bottom-start"
13086
- });
13087
- },
13088
- onUpdate(props) {
13089
- component.updateProps(props);
13090
- if (!props.clientRect) {
13091
- return;
13092
- }
13093
- popup[0].setProps({
13094
- getReferenceClientRect: props.clientRect
13095
- });
13096
- },
13097
- onKeyDown(props) {
13098
- var _a;
13099
- if (props.event.key === "Escape") {
13100
- popup[0].hide();
13101
- return true;
13102
- }
13103
- return (_a = component == null ? void 0 : component.ref) == null ? void 0 : _a.onKeyDown(props);
13104
- },
13105
- onExit() {
13106
- if (popup && popup[0]) popup[0].destroy();
13107
- if (component) component.destroy();
13108
- }
13109
- };
13110
- }
13111
- }
13112
- })
13113
- ],
13114
- content,
13115
- editable: canEdit,
13116
- onUpdate: ({ editor: editor2 }) => {
13117
- const serialize = (json) => {
13118
- if (!json.content) return "";
13119
- return json.content.map((block) => {
13120
- if (block.type === "paragraph") {
13121
- const inner = block.content ? block.content.map((node) => {
13122
- if (node.type === "text") return node.text;
13123
- if (node.type === "mention") {
13124
- return `[[MENTION:${node.attrs.type}:${node.attrs.id}:${node.attrs.label}]]`;
13125
- }
13126
- return "";
13127
- }).join("") : "";
13128
- return inner;
13129
- }
13130
- return "";
13131
- }).join("\n").trim();
13132
- };
13133
- const serialized = serialize(editor2.getJSON());
13134
- onChange(serialized);
13075
+ onMentionClick,
13076
+ searchItems,
13077
+ readOnly,
13078
+ placeholder
13079
+ }) {
13080
+ const editorRef = (0, import_react28.useRef)(null);
13081
+ const isMountedRef = (0, import_react28.useRef)(false);
13082
+ const dismissedTriggerRef = (0, import_react28.useRef)(null);
13083
+ const [mentionState, setMentionState] = (0, import_react28.useState)(null);
13084
+ const [isEmpty, setIsEmpty] = (0, import_react28.useState)(true);
13085
+ (0, import_react28.useEffect)(() => {
13086
+ if (!isMountedRef.current && editorRef.current) {
13087
+ editorRef.current.innerHTML = contentToHTML(content);
13088
+ const hasContent = !!editorRef.current.innerText.replace(/\u200B/g, "").trim();
13089
+ const hasMentions = !!editorRef.current.querySelector("[data-mention]");
13090
+ setIsEmpty(!hasContent && !hasMentions);
13091
+ isMountedRef.current = true;
13135
13092
  }
13136
- });
13137
- if (!editor) {
13138
- return null;
13139
- }
13140
- return /* @__PURE__ */ import_react28.default.createElement("div", { className: "relative group/editor min-h-[1.5rem] w-full" }, /* @__PURE__ */ import_react28.default.createElement(
13141
- import_react29.EditorContent,
13142
- {
13143
- editor,
13144
- className: "text-sm text-slate-200 placeholder-slate-600 focus:outline-none"
13093
+ }, []);
13094
+ const getMentionContext = (0, import_react28.useCallback)(() => {
13095
+ const selection = window.getSelection();
13096
+ if (!selection || selection.rangeCount === 0) return null;
13097
+ const range = selection.getRangeAt(0);
13098
+ const node = range.startContainer;
13099
+ if (node.nodeType !== Node.TEXT_NODE) return null;
13100
+ const textBefore = node.textContent.substring(0, range.startOffset);
13101
+ const atIndex = textBefore.lastIndexOf("@");
13102
+ if (atIndex === -1) {
13103
+ dismissedTriggerRef.current = null;
13104
+ return null;
13145
13105
  }
13146
- ), /* @__PURE__ */ import_react28.default.createElement("style", null, `
13147
- .tiptap p {
13148
- margin: 0;
13149
- min-height: 1.2em;
13150
- }
13151
- .tiptap .mention {
13152
- display: inline-flex;
13153
- align-items: center;
13154
- background-color: rgba(99, 102, 241, 0.15);
13155
- border: 1px solid rgba(99, 102, 241, 0.3);
13156
- border-radius: 4px;
13157
- padding: 0 4px;
13158
- color: #a5b4fc;
13159
- font-weight: 500;
13160
- cursor: pointer;
13161
- margin: 0 2px;
13162
- transition: all 0.2s;
13163
- }
13164
- .tiptap .mention:hover {
13165
- background-color: rgba(99, 102, 241, 0.25);
13166
- border-color: rgba(99, 102, 241, 0.5);
13167
- color: white;
13106
+ if (dismissedTriggerRef.current && dismissedTriggerRef.current.node === node && dismissedTriggerRef.current.atIndex === atIndex) {
13107
+ return null;
13108
+ }
13109
+ const query = textBefore.substring(atIndex + 1);
13110
+ if (query.includes(" ") || query.includes(".") || query.includes(",") || query.length > 40) {
13111
+ return null;
13112
+ }
13113
+ const rect = range.getBoundingClientRect();
13114
+ return {
13115
+ query,
13116
+ position: { top: rect.bottom + 6, left: rect.left }
13117
+ };
13118
+ }, []);
13119
+ const handleInput = (0, import_react28.useCallback)(() => {
13120
+ if (!editorRef.current) return;
13121
+ const serialized = domToContent(editorRef.current);
13122
+ onChange(serialized);
13123
+ const text = editorRef.current.innerText.replace(/\u200B/g, "").trim();
13124
+ const hasMentions = !!editorRef.current.querySelector("[data-mention]");
13125
+ setIsEmpty(!text && !hasMentions);
13126
+ const ctx = getMentionContext();
13127
+ setMentionState(ctx);
13128
+ }, [onChange, getMentionContext]);
13129
+ const handleKeyDown = (0, import_react28.useCallback)(
13130
+ (e) => {
13131
+ if (mentionState && ["ArrowDown", "ArrowUp", "Enter", "Tab", "Escape"].includes(e.key)) {
13132
+ return;
13133
+ }
13134
+ if (e.key === "Enter") {
13135
+ e.preventDefault();
13136
+ const sel = window.getSelection();
13137
+ const range = sel.getRangeAt(0);
13138
+ const br = document.createElement("br");
13139
+ range.deleteContents();
13140
+ range.insertNode(br);
13141
+ const afterBr = br.nextSibling || (() => {
13142
+ const zws = document.createTextNode("\u200B");
13143
+ br.parentNode.insertBefore(zws, br.nextSibling);
13144
+ return zws;
13145
+ })();
13146
+ const newRange = document.createRange();
13147
+ newRange.setStartBefore(afterBr);
13148
+ newRange.collapse(true);
13149
+ sel.removeAllRanges();
13150
+ sel.addRange(newRange);
13151
+ handleInput();
13152
+ }
13153
+ },
13154
+ [mentionState, handleInput]
13155
+ );
13156
+ const insertMention = (0, import_react28.useCallback)(
13157
+ (item) => {
13158
+ if (!editorRef.current) return;
13159
+ const sel = window.getSelection();
13160
+ if (!sel || sel.rangeCount === 0) return;
13161
+ const range = sel.getRangeAt(0);
13162
+ const textNode = range.startContainer;
13163
+ if (textNode.nodeType !== Node.TEXT_NODE) {
13164
+ setMentionState(null);
13165
+ return;
13166
+ }
13167
+ const cursorPos = range.startOffset;
13168
+ const textContent = textNode.textContent;
13169
+ const atIndex = textContent.lastIndexOf("@", cursorPos - 1);
13170
+ if (atIndex === -1) {
13171
+ setMentionState(null);
13172
+ return;
13173
+ }
13174
+ const before = textContent.substring(0, atIndex);
13175
+ const after = textContent.substring(cursorPos);
13176
+ textNode.textContent = before;
13177
+ const parent = textNode.parentNode;
13178
+ const nextSib = textNode.nextSibling;
13179
+ const span = document.createElement("span");
13180
+ span.contentEditable = "false";
13181
+ span.dataset.mention = "true";
13182
+ span.dataset.id = item.id;
13183
+ span.dataset.name = item.searchLabel || item.name || "";
13184
+ span.dataset.mentionType = item.type;
13185
+ span.style.cssText = mentionStyle(item.type);
13186
+ span.title = "Clique para focar na cena";
13187
+ span.textContent = `@${item.searchLabel || item.name || ""}`;
13188
+ parent.insertBefore(span, nextSib);
13189
+ const trailing = document.createTextNode(after || "\u200B");
13190
+ parent.insertBefore(trailing, span.nextSibling);
13191
+ const newRange = document.createRange();
13192
+ newRange.setStart(trailing, after ? 0 : 1);
13193
+ newRange.collapse(true);
13194
+ sel.removeAllRanges();
13195
+ sel.addRange(newRange);
13196
+ const serialized = domToContent(editorRef.current);
13197
+ onChange(serialized);
13198
+ setMentionState(null);
13199
+ setIsEmpty(false);
13200
+ },
13201
+ [onChange]
13202
+ );
13203
+ const handlePaste = (0, import_react28.useCallback)(
13204
+ (e) => {
13205
+ e.preventDefault();
13206
+ const text = e.clipboardData.getData("text/plain");
13207
+ if (text) {
13208
+ document.execCommand("insertText", false, text);
13209
+ handleInput();
13210
+ }
13211
+ },
13212
+ [handleInput]
13213
+ );
13214
+ const handleClick = (0, import_react28.useCallback)(
13215
+ (e) => {
13216
+ const chip = e.target.closest("[data-mention='true']");
13217
+ if (chip && onMentionClick) {
13218
+ e.stopPropagation();
13219
+ const id = chip.dataset.id;
13220
+ const full = searchItems == null ? void 0 : searchItems.find((i) => String(i.id) === String(id));
13221
+ if (full) {
13222
+ onMentionClick(full);
13223
+ } else {
13224
+ onMentionClick({
13225
+ id,
13226
+ name: chip.dataset.name,
13227
+ type: chip.dataset.mentionType,
13228
+ searchLabel: chip.dataset.name
13229
+ });
13168
13230
  }
13169
- .tiptap:focus {
13170
- outline: none;
13231
+ return;
13232
+ }
13233
+ setTimeout(() => {
13234
+ const ctx = getMentionContext();
13235
+ setMentionState(ctx);
13236
+ }, 0);
13237
+ },
13238
+ [onMentionClick, getMentionContext, searchItems]
13239
+ );
13240
+ const handleBlur = (0, import_react28.useCallback)(() => {
13241
+ setTimeout(() => setMentionState(null), 200);
13242
+ }, []);
13243
+ const handleMentionDismiss = (0, import_react28.useCallback)(() => {
13244
+ const selection = window.getSelection();
13245
+ if (selection && selection.rangeCount > 0) {
13246
+ const range = selection.getRangeAt(0);
13247
+ const node = range.startContainer;
13248
+ if (node.nodeType === Node.TEXT_NODE) {
13249
+ const textBefore = node.textContent.substring(0, range.startOffset);
13250
+ const atIndex = textBefore.lastIndexOf("@");
13251
+ if (atIndex !== -1) {
13252
+ dismissedTriggerRef.current = { node, atIndex };
13171
13253
  }
13172
- `));
13173
- };
13174
- var MentionEditor_default = MentionEditor;
13254
+ }
13255
+ }
13256
+ setMentionState(null);
13257
+ }, []);
13258
+ return /* @__PURE__ */ import_react28.default.createElement("div", { className: "relative" }, isEmpty && !readOnly && /* @__PURE__ */ import_react28.default.createElement("div", { className: "absolute top-0 left-0 text-sm text-slate-600 pointer-events-none select-none" }, placeholder || "Escreva sobre este grupo\u2026 ou digite @ para mencionar"), /* @__PURE__ */ import_react28.default.createElement(
13259
+ "div",
13260
+ {
13261
+ ref: editorRef,
13262
+ contentEditable: readOnly ? "false" : "true",
13263
+ suppressContentEditableWarning: true,
13264
+ onInput: handleInput,
13265
+ onKeyDown: handleKeyDown,
13266
+ onPaste: handlePaste,
13267
+ onClick: handleClick,
13268
+ onBlur: handleBlur,
13269
+ 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"}`,
13270
+ style: { overflowWrap: "break-word", wordBreak: "break-word" }
13271
+ }
13272
+ ), mentionState && !readOnly && /* @__PURE__ */ import_react28.default.createElement(
13273
+ MentionPopover,
13274
+ {
13275
+ query: mentionState.query,
13276
+ items: searchItems || [],
13277
+ position: mentionState.position,
13278
+ onSelect: insertMention,
13279
+ onClose: handleMentionDismiss
13280
+ }
13281
+ ));
13282
+ }
13175
13283
 
13176
13284
  // src/components/AncestryBoard.jsx
13177
- var GroupItem = ({
13178
- group,
13285
+ var Tooltip = ({ text, children }) => {
13286
+ if (!text) return children;
13287
+ return /* @__PURE__ */ import_react29.default.createElement("div", { className: "relative group/tooltip" }, children, /* @__PURE__ */ import_react29.default.createElement("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-2 py-1 bg-slate-900 border border-white/10 text-white text-[10px] rounded opacity-0 group-hover/tooltip:opacity-100 transition-opacity pointer-events-none whitespace-nowrap z-[3000] shadow-2xl" }, text));
13288
+ };
13289
+ var BoardItem = ({
13290
+ item,
13179
13291
  index,
13292
+ prevItem,
13293
+ nextItem,
13180
13294
  onUpdate,
13181
13295
  onDelete,
13182
- onAddSubgroup,
13183
13296
  onIndent,
13297
+ onIndentDown,
13184
13298
  onOutdent,
13185
- onPlayAncestry,
13186
- availableMentionItems,
13299
+ onMoveUp,
13300
+ onMoveDown,
13301
+ searchItems,
13302
+ onMentionClick,
13303
+ onEnterFolder,
13187
13304
  canEdit
13188
13305
  }) => {
13189
- const canIndent = index > 0;
13190
- return /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react30.default.createElement(
13191
- "div",
13192
- {
13193
- className: "flex flex-col gap-2 py-2 px-3 transition-all duration-200 hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"
13194
- },
13195
- /* @__PURE__ */ import_react30.default.createElement(
13196
- MentionEditor_default,
13197
- {
13198
- initialValue: group.text,
13199
- onChange: (newText) => {
13200
- if (canEdit) onUpdate(group.id, { ...group, text: newText });
13201
- },
13202
- onPlay: onPlayAncestry,
13203
- availableItems: availableMentionItems,
13204
- canEdit,
13205
- placeholder: "Escreva sobre este grupo... use @ para mencionar"
13206
- }
13207
- ),
13208
- canEdit && /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-0 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react30.default.createElement(
13209
- "button",
13210
- {
13211
- onClick: () => onAddSubgroup(group.id),
13212
- className: "flex items-center gap-1.5 px-3 py-1.5 text-xs text-slate-500 hover:text-white hover:bg-white/10 rounded-md transition-colors",
13213
- title: "Criar Subgrupo"
13214
- },
13215
- /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiPlus, { size: 14 }),
13216
- /* @__PURE__ */ import_react30.default.createElement("span", null, "Adicionar Subgrupo")
13217
- )), /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react30.default.createElement(
13218
- "button",
13219
- {
13220
- onClick: () => onIndent(group.id),
13221
- disabled: !canIndent,
13222
- className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
13223
- title: "Aninhar no grupo acima"
13224
- },
13225
- /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiArrowRight, { size: 14 })
13226
- ), /* @__PURE__ */ import_react30.default.createElement(
13227
- "button",
13228
- {
13229
- onClick: () => onOutdent(group.id),
13230
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13231
- title: "Desaninhar"
13232
- },
13233
- /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiArrowLeft, { size: 14 })
13234
- ), /* @__PURE__ */ import_react30.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react30.default.createElement(
13235
- "button",
13306
+ var _a;
13307
+ const isFolder = item.type === "folder";
13308
+ const canMoveUp = index > 0;
13309
+ const canMoveDown = nextItem !== void 0;
13310
+ const isNested = onOutdent !== void 0;
13311
+ const getIndentUpTooltip = () => {
13312
+ if (!prevItem) return null;
13313
+ const typeLabel = prevItem.type === "folder" ? "folder" : "text_group";
13314
+ return isFolder ? prevItem.type === "folder" ? "Aninhar na pasta acima" : null : `Mover para dentro do ${typeLabel} acima`;
13315
+ };
13316
+ const getIndentDownTooltip = () => {
13317
+ if (!nextItem) return null;
13318
+ const typeLabel = nextItem.type === "folder" ? "folder" : "text_group";
13319
+ return isFolder ? nextItem.type === "folder" ? "Aninhar na pasta abaixo" : null : `Mover para dentro do ${typeLabel} abaixo`;
13320
+ };
13321
+ const showIndentUp = !!getIndentUpTooltip();
13322
+ const showIndentDown = !!getIndentDownTooltip();
13323
+ const handleContentChange = (content) => {
13324
+ onUpdate(item.id, { ...item, content });
13325
+ };
13326
+ const handleNameChange = (e) => {
13327
+ onUpdate(item.id, { ...item, name: e.target.value });
13328
+ };
13329
+ if (isFolder) {
13330
+ return /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col gap-2 mb-3 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react29.default.createElement(
13331
+ "div",
13236
13332
  {
13237
- onClick: () => onDelete(group.id),
13238
- className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13239
- title: "Remover Grupo"
13333
+ onClick: () => onEnterFolder(item.id),
13334
+ className: "flex items-center gap-3 py-3 px-4 bg-white/5 hover:bg-white/10 border border-white/10 hover:border-white/20 rounded-xl cursor-pointer transition-all duration-200 group/folder"
13240
13335
  },
13241
- /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiTrash2, { size: 14 })
13242
- )))
13243
- ), group.children && group.children.length > 0 && /* @__PURE__ */ import_react30.default.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ import_react30.default.createElement(
13244
- GroupItem,
13336
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "w-10 h-10 rounded-lg bg-indigo-500/10 flex items-center justify-center text-indigo-400 group-hover/folder:scale-110 transition-transform" }, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiFolder, { size: 20 })),
13337
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex-1 min-w-0" }, canEdit ? /* @__PURE__ */ import_react29.default.createElement(
13338
+ "input",
13339
+ {
13340
+ type: "text",
13341
+ value: item.name,
13342
+ onChange: handleNameChange,
13343
+ onClick: (e) => e.stopPropagation(),
13344
+ className: "bg-transparent border-none outline-none text-sm font-medium text-slate-200 w-full focus:text-white",
13345
+ placeholder: "Nome da pasta..."
13346
+ }
13347
+ ) : /* @__PURE__ */ import_react29.default.createElement("span", { className: "text-sm font-medium text-slate-200" }, item.name), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-2 mt-0.5" }, /* @__PURE__ */ import_react29.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider font-semibold" }, ((_a = item.children) == null ? void 0 : _a.length) || 0, " itens"))),
13348
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-1.5 opacity-0 group-item/item:opacity-100 group-hover/folder:opacity-100 transition-opacity" }, canEdit && /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-0.5 bg-slate-900/80 backdrop-blur-sm p-1 rounded-lg border border-white/5 shadow-xl" }, /* @__PURE__ */ import_react29.default.createElement(Tooltip, { text: "Subir" }, /* @__PURE__ */ import_react29.default.createElement(
13349
+ "button",
13350
+ {
13351
+ onClick: (e) => {
13352
+ e.stopPropagation();
13353
+ onMoveUp(item.id);
13354
+ },
13355
+ disabled: !canMoveUp,
13356
+ className: `p-1.5 rounded transition-colors ${!canMoveUp ? "text-slate-800 cursor-not-allowed" : "text-slate-400 hover:text-white hover:bg-white/10"}`
13357
+ },
13358
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowUp, { size: 14 })
13359
+ )), /* @__PURE__ */ import_react29.default.createElement(Tooltip, { text: "Descer" }, /* @__PURE__ */ import_react29.default.createElement(
13360
+ "button",
13361
+ {
13362
+ onClick: (e) => {
13363
+ e.stopPropagation();
13364
+ onMoveDown(item.id);
13365
+ },
13366
+ disabled: !canMoveDown,
13367
+ className: `p-1.5 rounded transition-colors ${!canMoveDown ? "text-slate-800 cursor-not-allowed" : "text-slate-400 hover:text-white hover:bg-white/10"}`
13368
+ },
13369
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowDown, { size: 14 })
13370
+ )), /* @__PURE__ */ import_react29.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-0.5" }), showIndentUp && /* @__PURE__ */ import_react29.default.createElement(Tooltip, { text: getIndentUpTooltip() }, /* @__PURE__ */ import_react29.default.createElement(
13371
+ "button",
13372
+ {
13373
+ onClick: (e) => {
13374
+ e.stopPropagation();
13375
+ onIndent(item.id);
13376
+ },
13377
+ className: "p-1.5 text-slate-400 hover:text-white hover:bg-white/10 rounded transition-colors"
13378
+ },
13379
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowLeft, { size: 14 })
13380
+ )), showIndentDown && /* @__PURE__ */ import_react29.default.createElement(Tooltip, { text: getIndentDownTooltip() }, /* @__PURE__ */ import_react29.default.createElement(
13381
+ "button",
13382
+ {
13383
+ onClick: (e) => {
13384
+ e.stopPropagation();
13385
+ onIndentDown(item.id);
13386
+ },
13387
+ className: "p-1.5 text-slate-400 hover:text-white hover:bg-white/10 rounded transition-colors"
13388
+ },
13389
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowRight, { size: 14 })
13390
+ )), (isNested || !showIndentUp && !showIndentDown) && /* @__PURE__ */ import_react29.default.createElement(Tooltip, { text: "Desaninhar / Recuar n\xEDvel" }, /* @__PURE__ */ import_react29.default.createElement(
13391
+ "button",
13392
+ {
13393
+ onClick: (e) => {
13394
+ e.stopPropagation();
13395
+ onOutdent(item.id);
13396
+ },
13397
+ disabled: !onOutdent,
13398
+ className: `p-1.5 rounded transition-colors ${!onOutdent ? "text-slate-800 cursor-not-allowed" : "text-slate-400 hover:text-white hover:bg-white/10"}`
13399
+ },
13400
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiCornerUpRight, { size: 14 })
13401
+ )), /* @__PURE__ */ import_react29.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-0.5" }), /* @__PURE__ */ import_react29.default.createElement(Tooltip, { text: "Remover Pasta" }, /* @__PURE__ */ import_react29.default.createElement(
13402
+ "button",
13403
+ {
13404
+ onClick: (e) => {
13405
+ e.stopPropagation();
13406
+ onDelete(item.id);
13407
+ },
13408
+ className: "p-1.5 text-slate-500 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors"
13409
+ },
13410
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiTrash2, { size: 14 })
13411
+ ))), /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiChevronRight, { className: "text-slate-500 group-hover/folder:translate-x-1 transition-transform" }))
13412
+ ));
13413
+ }
13414
+ return /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col gap-2 py-2 px-3 transition-all duration-200 hover:bg-white/5 border-l-2 border-transparent hover:border-white/20" }, /* @__PURE__ */ import_react29.default.createElement(
13415
+ RichGroupEditor,
13245
13416
  {
13246
- key: childGroup.id,
13417
+ content: item.content,
13418
+ onChange: handleContentChange,
13419
+ onMentionClick,
13420
+ searchItems,
13421
+ readOnly: !canEdit,
13422
+ placeholder: "Escreva sobre este grupo\u2026 ou @ para mencionar"
13423
+ }
13424
+ ), canEdit && /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react29.default.createElement(
13425
+ "button",
13426
+ {
13427
+ onClick: () => onAddSubgroup(item.id, "group"),
13428
+ className: "flex items-center gap-1 px-1.5 py-1 text-[10px] uppercase font-bold tracking-wider text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
13429
+ title: "Criar Subgrupo"
13430
+ },
13431
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiPlus, { size: 12 }),
13432
+ /* @__PURE__ */ import_react29.default.createElement("span", null, "Subgrupo")
13433
+ )), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react29.default.createElement(Tooltip, { text: "Subir" }, /* @__PURE__ */ import_react29.default.createElement(
13434
+ "button",
13435
+ {
13436
+ onClick: () => onMoveUp(item.id),
13437
+ disabled: !canMoveUp,
13438
+ className: `p-1.5 rounded transition-colors ${!canMoveUp ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`
13439
+ },
13440
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowUp, { size: 14 })
13441
+ )), /* @__PURE__ */ import_react29.default.createElement(Tooltip, { text: "Descer" }, /* @__PURE__ */ import_react29.default.createElement(
13442
+ "button",
13443
+ {
13444
+ onClick: () => onMoveDown(item.id),
13445
+ disabled: !canMoveDown,
13446
+ className: `p-1.5 rounded transition-colors ${!canMoveDown ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`
13447
+ },
13448
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowDown, { size: 14 })
13449
+ )), /* @__PURE__ */ import_react29.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), showIndentUp && /* @__PURE__ */ import_react29.default.createElement(Tooltip, { text: getIndentUpTooltip() }, /* @__PURE__ */ import_react29.default.createElement(
13450
+ "button",
13451
+ {
13452
+ onClick: () => onIndent(item.id),
13453
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors"
13454
+ },
13455
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowLeft, { size: 14 })
13456
+ )), showIndentDown && /* @__PURE__ */ import_react29.default.createElement(Tooltip, { text: getIndentDownTooltip() }, /* @__PURE__ */ import_react29.default.createElement(
13457
+ "button",
13458
+ {
13459
+ onClick: () => onIndentDown(item.id),
13460
+ className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors"
13461
+ },
13462
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowRight, { size: 14 })
13463
+ )), (isNested || !showIndentUp && !showIndentDown) && /* @__PURE__ */ import_react29.default.createElement(Tooltip, { text: "Desaninhar / Recuar n\xEDvel" }, /* @__PURE__ */ import_react29.default.createElement(
13464
+ "button",
13465
+ {
13466
+ onClick: () => onOutdent(item.id),
13467
+ disabled: !onOutdent,
13468
+ className: `p-1.5 rounded transition-colors ${!onOutdent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`
13469
+ },
13470
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiCornerUpRight, { size: 14 })
13471
+ )), /* @__PURE__ */ import_react29.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react29.default.createElement(Tooltip, { text: "Remover Grupo" }, /* @__PURE__ */ import_react29.default.createElement(
13472
+ "button",
13473
+ {
13474
+ onClick: () => onDelete(item.id),
13475
+ className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors"
13476
+ },
13477
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiTrash2, { size: 14 })
13478
+ ))))), item.children && item.children.length > 0 && /* @__PURE__ */ import_react29.default.createElement("div", { className: "ml-2" }, item.children.map((child, idx) => /* @__PURE__ */ import_react29.default.createElement(
13479
+ BoardItem,
13480
+ {
13481
+ key: child.id,
13247
13482
  index: idx,
13248
- group: childGroup,
13249
- siblings: group.children,
13483
+ prevItem: item.children[idx - 1],
13484
+ nextItem: item.children[idx + 1],
13485
+ item: child,
13250
13486
  onUpdate,
13251
13487
  onDelete,
13252
13488
  onAddSubgroup,
13253
13489
  onIndent,
13490
+ onIndentDown,
13254
13491
  onOutdent,
13255
- onPlayAncestry,
13256
- availableMentionItems,
13492
+ onMoveUp,
13493
+ onMoveDown,
13494
+ searchItems,
13495
+ onMentionClick,
13496
+ onEnterFolder,
13257
13497
  canEdit
13258
13498
  }
13259
13499
  ))));
@@ -13268,140 +13508,181 @@ function AncestryBoard({
13268
13508
  onSave,
13269
13509
  userRole
13270
13510
  }) {
13271
- const [groups, setGroups] = (0, import_react30.useState)([]);
13272
- const [isLoaded, setIsLoaded] = (0, import_react30.useState)(false);
13273
- const [saveStatus, setSaveStatus] = (0, import_react30.useState)("idle");
13274
- const canEdit = (0, import_react30.useMemo)(() => {
13275
- return userRole !== "viewer";
13276
- }, [userRole]);
13277
- (0, import_react30.useEffect)(() => {
13511
+ const [groups, setGroups] = (0, import_react29.useState)([]);
13512
+ const [isLoaded, setIsLoaded] = (0, import_react29.useState)(false);
13513
+ const [saveStatus, setSaveStatus] = (0, import_react29.useState)("idle");
13514
+ const [navigationStack, setNavigationStack] = (0, import_react29.useState)([]);
13515
+ const lastSavedGroupsRef = (0, import_react29.useRef)(null);
13516
+ const canEdit = (0, import_react29.useMemo)(() => userRole !== "viewer", [userRole]);
13517
+ (0, import_react29.useEffect)(() => {
13278
13518
  if (initialGroups && !isLoaded) {
13279
- setGroups(initialGroups);
13519
+ const migrate = (list) => list.map((g) => ({
13520
+ id: g.id || (0, import_uuid11.v4)(),
13521
+ type: g.type || "group",
13522
+ name: g.name || "",
13523
+ content: Array.isArray(g.content) ? g.content : [],
13524
+ children: migrate(g.children || [])
13525
+ }));
13526
+ setGroups(migrate(initialGroups));
13280
13527
  setIsLoaded(true);
13281
13528
  }
13282
13529
  }, [initialGroups, isLoaded]);
13283
- const nodeNamesMap = (0, import_react30.useMemo)(() => {
13284
- const map = /* @__PURE__ */ new Map();
13285
- if (availableNodes && Array.isArray(availableNodes)) {
13286
- availableNodes.forEach((node) => {
13287
- if (node && node.id) {
13288
- map.set(String(node.id), node.name);
13289
- }
13530
+ const allSearchableItems = (0, import_react29.useMemo)(() => {
13531
+ const items = [];
13532
+ availableAncestries.forEach((anc) => {
13533
+ items.push({
13534
+ ...anc,
13535
+ id: String(anc.ancestry_id),
13536
+ type: "ancestry",
13537
+ searchLabel: anc.name || "",
13538
+ searchDesc: anc.description || ""
13290
13539
  });
13291
- }
13292
- return map;
13293
- }, [availableNodes]);
13294
- const availableIds = (0, import_react30.useMemo)(() => {
13295
- return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
13296
- }, [availableAncestries]);
13297
- const availableMentionItems = (0, import_react30.useMemo)(() => {
13298
- const ancestries = availableAncestries.map((a) => ({
13299
- id: String(a.ancestry_id),
13300
- ancestry_id: a.ancestry_id,
13301
- name: a.name,
13302
- description: a.description,
13303
- type: "ancestry",
13304
- ancestral_node: a.ancestral_node,
13305
- is_private: a.is_private
13306
- }));
13307
- const nodes = availableNodes.map((n) => {
13540
+ });
13541
+ availableNodes.forEach((node) => {
13542
+ var _a;
13308
13543
  let type = "node";
13309
- if (n.is_quest) type = "quest";
13310
- else if (n.is_version) type = "version";
13311
- return {
13312
- id: String(n.id),
13313
- name: n.name,
13314
- description: n.description,
13544
+ if (node.is_quest) type = "quest";
13545
+ else if ((_a = node.version_node) == null ? void 0 : _a.is_version) type = "version";
13546
+ items.push({
13547
+ ...node,
13548
+ id: String(node.id),
13315
13549
  type,
13316
- raw_node: n
13317
- };
13550
+ searchLabel: node.name || node.raw_title || "",
13551
+ searchDesc: node.description || ""
13552
+ });
13318
13553
  });
13319
- return [...ancestries, ...nodes];
13554
+ return items;
13320
13555
  }, [availableAncestries, availableNodes]);
13321
- const sanitizeGroups = (groupList) => {
13322
- return groupList.map((g) => ({
13323
- id: g.id,
13324
- text: g.text || "",
13325
- children: sanitizeGroups(g.children || [])
13326
- }));
13327
- };
13328
- (0, import_react30.useEffect)(() => {
13556
+ const sanitizeGroups = (list) => list.map((g) => ({
13557
+ id: g.id,
13558
+ type: g.type || "group",
13559
+ name: g.name || "",
13560
+ content: g.content || [],
13561
+ children: sanitizeGroups(g.children || [])
13562
+ }));
13563
+ (0, import_react29.useEffect)(() => {
13329
13564
  if (!isLoaded || !onSave) return;
13330
- const timeoutId = setTimeout(async () => {
13565
+ const id = setTimeout(async () => {
13566
+ const currentSanitized = sanitizeGroups(groups);
13567
+ const currentJson = JSON.stringify(currentSanitized);
13568
+ if (currentJson === lastSavedGroupsRef.current) return;
13331
13569
  setSaveStatus("saving");
13332
- const cleanData = sanitizeGroups(groups);
13333
13570
  try {
13334
- await onSave(cleanData);
13571
+ await onSave(currentSanitized);
13572
+ lastSavedGroupsRef.current = currentJson;
13335
13573
  setSaveStatus("saved");
13336
- setTimeout(() => {
13337
- setSaveStatus("idle");
13338
- }, 3e3);
13339
- } catch (error) {
13340
- console.error("Erro ao salvar board:", error);
13574
+ setTimeout(() => setSaveStatus("idle"), 3e3);
13575
+ } catch (err) {
13576
+ console.error("Erro ao salvar board:", err);
13341
13577
  setSaveStatus("error");
13342
13578
  }
13343
13579
  }, 3e3);
13344
- return () => clearTimeout(timeoutId);
13580
+ return () => clearTimeout(id);
13345
13581
  }, [groups, isLoaded, onSave]);
13346
- (0, import_react30.useEffect)(() => {
13582
+ const triggerInstantSave = async (updatedGroups) => {
13583
+ if (!onSave) return;
13584
+ const sanitized = sanitizeGroups(updatedGroups);
13585
+ const sanitizedJson = JSON.stringify(sanitized);
13586
+ lastSavedGroupsRef.current = sanitizedJson;
13587
+ setSaveStatus("saving");
13588
+ try {
13589
+ await onSave(sanitized);
13590
+ setSaveStatus("saved");
13591
+ setTimeout(() => setSaveStatus("idle"), 3e3);
13592
+ } catch (err) {
13593
+ console.error("Erro ao salvar board:", err);
13594
+ setSaveStatus("error");
13595
+ }
13596
+ };
13597
+ (0, import_react29.useEffect)(() => {
13347
13598
  if (!isOpen) return;
13348
- const handleKeyDown = (e) => {
13599
+ const handler = (e) => {
13349
13600
  if (e.key === "Escape") {
13350
13601
  onClose();
13351
13602
  e.preventDefault();
13352
13603
  e.stopPropagation();
13353
13604
  }
13354
13605
  };
13355
- window.addEventListener("keydown", handleKeyDown);
13356
- return () => window.removeEventListener("keydown", handleKeyDown);
13606
+ window.addEventListener("keydown", handler);
13607
+ return () => window.removeEventListener("keydown", handler);
13357
13608
  }, [isOpen, onClose]);
13358
- const handleAddRootGroup = () => {
13359
- const newGroup = {
13360
- id: (0, import_uuid11.v4)(),
13361
- text: "",
13362
- children: []
13363
- };
13364
- setGroups((prev) => [newGroup, ...prev]);
13609
+ const currentPath = (0, import_react29.useMemo)(() => {
13610
+ const path = [];
13611
+ let currentLevel = groups;
13612
+ for (const folderId of navigationStack) {
13613
+ const folder = currentLevel.find((f) => f.id === folderId);
13614
+ if (folder) {
13615
+ path.push(folder);
13616
+ currentLevel = folder.children;
13617
+ }
13618
+ }
13619
+ return path;
13620
+ }, [groups, navigationStack]);
13621
+ const currentGroups = (0, import_react29.useMemo)(() => {
13622
+ const lastFolder = currentPath[currentPath.length - 1];
13623
+ return lastFolder ? lastFolder.children : groups;
13624
+ }, [groups, currentPath]);
13625
+ const navigateUp = () => {
13626
+ setNavigationStack((prev) => prev.slice(0, -1));
13365
13627
  };
13366
- const handleAddSubgroup = (parentId) => {
13367
- const newGroup = {
13628
+ const navigateTo = (folderId) => {
13629
+ setNavigationStack((prev) => [...prev, folderId]);
13630
+ };
13631
+ const navigateToBreadcrumb = (index) => {
13632
+ setNavigationStack((prev) => prev.slice(0, index + 1));
13633
+ };
13634
+ const navigateHome = () => {
13635
+ setNavigationStack([]);
13636
+ };
13637
+ const handleAddItem = (type = "group") => {
13638
+ const newItem = {
13368
13639
  id: (0, import_uuid11.v4)(),
13369
- text: "",
13640
+ type,
13641
+ name: type === "folder" ? "Nova Pasta" : "",
13642
+ content: [],
13370
13643
  children: []
13371
13644
  };
13372
- const addRecursive = (list) => {
13373
- return list.map((g) => {
13374
- if (g.id === parentId) {
13375
- return { ...g, children: [newGroup, ...g.children] };
13376
- }
13377
- return { ...g, children: addRecursive(g.children) };
13378
- });
13379
- };
13380
- setGroups((prev) => addRecursive(prev));
13645
+ if (navigationStack.length === 0) {
13646
+ setGroups((prev) => [...prev, newItem]);
13647
+ } else {
13648
+ const parentId = navigationStack[navigationStack.length - 1];
13649
+ const add = (list) => list.map(
13650
+ (g) => g.id === parentId ? { ...g, children: [...g.children, newItem] } : { ...g, children: add(g.children) }
13651
+ );
13652
+ setGroups((prev) => add(prev));
13653
+ }
13381
13654
  };
13382
- const handleUpdateGroup = (id, newData) => {
13383
- const updateRecursive = (list) => {
13384
- return list.map((g) => {
13385
- if (g.id === id) return newData;
13386
- return { ...g, children: updateRecursive(g.children) };
13387
- });
13388
- };
13389
- setGroups((prev) => updateRecursive(prev));
13655
+ const handleAddSubgroup = (parentId, type = "group") => {
13656
+ const add = (list) => list.map((g) => {
13657
+ if (g.id === parentId) {
13658
+ if (g.type === "group" && type === "folder") return g;
13659
+ const newItem = {
13660
+ id: (0, import_uuid11.v4)(),
13661
+ type,
13662
+ name: type === "folder" ? "Nova Pasta" : "",
13663
+ content: [],
13664
+ children: []
13665
+ };
13666
+ return { ...g, children: [...g.children, newItem] };
13667
+ }
13668
+ return { ...g, children: add(g.children) };
13669
+ });
13670
+ setGroups((prev) => add(prev));
13390
13671
  };
13391
- const handleDeleteGroup = (id) => {
13392
- const deleteRecursive = (list) => {
13393
- return list.filter((g) => g.id !== id).map((g) => ({
13394
- ...g,
13395
- children: deleteRecursive(g.children)
13396
- }));
13397
- };
13398
- setGroups((prev) => deleteRecursive(prev));
13672
+ const handleUpdateItem = (id, newData) => {
13673
+ const update = (list) => list.map(
13674
+ (g) => g.id === id ? newData : { ...g, children: update(g.children) }
13675
+ );
13676
+ setGroups((prev) => update(prev));
13677
+ };
13678
+ const handleDeleteItem = (id) => {
13679
+ const del = (list) => list.filter((g) => g.id !== id).map((g) => ({ ...g, children: del(g.children) }));
13680
+ setGroups((prev) => del(prev));
13399
13681
  };
13400
13682
  const findGroupAndParent = (list, targetId, parent = null) => {
13401
13683
  for (let i = 0; i < list.length; i++) {
13402
- if (list[i].id === targetId) {
13684
+ if (list[i].id === targetId)
13403
13685
  return { group: list[i], parent, index: i, siblings: list };
13404
- }
13405
13686
  if (list[i].children.length > 0) {
13406
13687
  const found = findGroupAndParent(list[i].children, targetId, list[i]);
13407
13688
  if (found) return found;
@@ -13410,113 +13691,162 @@ function AncestryBoard({
13410
13691
  return null;
13411
13692
  };
13412
13693
  const handleIndent = (id) => {
13413
- setGroups((prev) => {
13414
- const newList = JSON.parse(JSON.stringify(prev));
13415
- const found = findGroupAndParent(newList, id);
13416
- if (!found || found.index === 0) return prev;
13417
- const { group, siblings, index } = found;
13418
- const prevSibling = siblings[index - 1];
13419
- siblings.splice(index, 1);
13420
- prevSibling.children.push(group);
13421
- return newList;
13422
- });
13694
+ const next = JSON.parse(JSON.stringify(groups));
13695
+ const found = findGroupAndParent(next, id);
13696
+ if (!found || found.index === 0) return;
13697
+ const { group, siblings, index } = found;
13698
+ const targetParent = siblings[index - 1];
13699
+ if (group.type === "folder" && targetParent.type === "group") {
13700
+ return;
13701
+ }
13702
+ siblings.splice(index, 1);
13703
+ targetParent.children.push(group);
13704
+ setGroups(next);
13705
+ triggerInstantSave(next);
13423
13706
  };
13424
- const handleOutdent = (id) => {
13425
- setGroups((prev) => {
13426
- const newList = JSON.parse(JSON.stringify(prev));
13427
- const found = findGroupAndParent(newList, id);
13428
- if (!found || !found.parent) return prev;
13429
- const { group, siblings, index, parent } = found;
13430
- siblings.splice(index, 1);
13431
- const parentFound = findGroupAndParent(newList, parent.id);
13432
- if (parentFound) {
13433
- parentFound.siblings.splice(parentFound.index + 1, 0, group);
13434
- } else {
13435
- newList.push(group);
13436
- }
13437
- return newList;
13438
- });
13707
+ const handleIndentDown = (id) => {
13708
+ const next = JSON.parse(JSON.stringify(groups));
13709
+ const found = findGroupAndParent(next, id);
13710
+ if (!found || found.index === found.siblings.length - 1) return;
13711
+ const { group, siblings, index } = found;
13712
+ const targetParent = siblings[index + 1];
13713
+ if (group.type === "folder" && targetParent.type === "group") {
13714
+ return;
13715
+ }
13716
+ siblings.splice(index, 1);
13717
+ targetParent.children.push(group);
13718
+ setGroups(next);
13719
+ triggerInstantSave(next);
13439
13720
  };
13440
- const handlePlayFromGroup = (item) => {
13441
- let fullItem = item;
13442
- if (item.type === "ancestry" || !item.type) {
13443
- fullItem = availableAncestries.find(
13444
- (a) => String(a.ancestry_id) === String(item.id || item.ancestry_id)
13445
- ) || item;
13721
+ const handleOutdent = (id) => {
13722
+ const next = JSON.parse(JSON.stringify(groups));
13723
+ const found = findGroupAndParent(next, id);
13724
+ if (!found || !found.parent) return;
13725
+ const { group, siblings, index, parent } = found;
13726
+ siblings.splice(index, 1);
13727
+ const parentFound = findGroupAndParent(next, parent.id);
13728
+ if (parentFound) {
13729
+ parentFound.siblings.splice(parentFound.index + 1, 0, group);
13446
13730
  } else {
13447
- fullItem = availableNodes.find(
13448
- (n) => String(n.id) === String(item.id)
13449
- ) || item;
13450
- }
13451
- if (fullItem && onSelect) {
13452
- onSelect(fullItem);
13731
+ next.push(group);
13453
13732
  }
13733
+ setGroups(next);
13734
+ triggerInstantSave(next);
13735
+ };
13736
+ const handleMoveUp = (id) => {
13737
+ const next = JSON.parse(JSON.stringify(groups));
13738
+ const found = findGroupAndParent(next, id);
13739
+ if (!found || found.index === 0) return;
13740
+ const { siblings, index } = found;
13741
+ const item = siblings[index];
13742
+ siblings.splice(index, 1);
13743
+ siblings.splice(index - 1, 0, item);
13744
+ setGroups(next);
13745
+ triggerInstantSave(next);
13746
+ };
13747
+ const handleMoveDown = (id) => {
13748
+ const next = JSON.parse(JSON.stringify(groups));
13749
+ const found = findGroupAndParent(next, id);
13750
+ if (!found || found.index === found.siblings.length - 1) return;
13751
+ const { siblings, index } = found;
13752
+ const item = siblings[index];
13753
+ siblings.splice(index, 1);
13754
+ siblings.splice(index + 1, 0, item);
13755
+ setGroups(next);
13756
+ triggerInstantSave(next);
13757
+ };
13758
+ const handleMentionClick = (item) => {
13759
+ if (onSelect) onSelect(item);
13454
13760
  };
13455
13761
  if (!isOpen) return null;
13456
- return /* @__PURE__ */ import_react30.default.createElement(
13762
+ return /* @__PURE__ */ import_react29.default.createElement(
13457
13763
  "div",
13458
13764
  {
13459
13765
  className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
13460
13766
  onClick: onClose
13461
13767
  },
13462
- /* @__PURE__ */ import_react30.default.createElement(
13768
+ /* @__PURE__ */ import_react29.default.createElement(
13463
13769
  "div",
13464
13770
  {
13465
- className: "bg-slate-950 border border-white/10 rounded-xl w-[90vw] max-w-[1200px] h-[90vh] flex flex-col shadow-2xl overflow-hidden animate-in fade-in zoom-in-95 duration-200",
13771
+ 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",
13466
13772
  onClick: (e) => e.stopPropagation()
13467
13773
  },
13468
- /* @__PURE__ */ import_react30.default.createElement("div", { className: "h-14 px-6 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react30.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ import_react30.default.createElement(import_react30.default.Fragment, null, /* @__PURE__ */ import_react30.default.createElement(
13469
- import_fi23.FiLoader,
13774
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react29.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react29.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiLoader, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ import_react29.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ import_react29.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, /* @__PURE__ */ import_react29.default.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ import_react29.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex items-center gap-3" }, canEdit && /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, /* @__PURE__ */ import_react29.default.createElement(
13775
+ "button",
13470
13776
  {
13471
- className: "animate-spin text-indigo-400",
13472
- size: 12
13473
- }
13474
- ), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ import_react30.default.createElement(import_react30.default.Fragment, null, /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ import_react30.default.createElement(import_react30.default.Fragment, null, /* @__PURE__ */ import_react30.default.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-3" }, canEdit && /* @__PURE__ */ import_react30.default.createElement(
13777
+ onClick: () => handleAddItem("folder"),
13778
+ 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"
13779
+ },
13780
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiPlus, { size: 14, className: "text-amber-400" }),
13781
+ /* @__PURE__ */ import_react29.default.createElement("span", { className: "hidden sm:inline" }, "Nova Pasta")
13782
+ ), /* @__PURE__ */ import_react29.default.createElement(
13475
13783
  "button",
13476
13784
  {
13477
- onClick: handleAddRootGroup,
13478
- className: "\n flex items-center gap-2 px-3 py-1.5 \n bg-white/5 hover:bg-white/10 \n border border-white/10 hover:border-white/20\n backdrop-blur-sm\n text-slate-200 hover:text-white\n rounded-md transition-all duration-200\n text-xs font-medium shadow-sm\n "
13785
+ onClick: () => handleAddItem("group"),
13786
+ 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"
13479
13787
  },
13480
- /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiPlus, { size: 14, className: "text-indigo-400" }),
13481
- /* @__PURE__ */ import_react30.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13482
- ), /* @__PURE__ */ import_react30.default.createElement(
13788
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiPlus, { size: 14, className: "text-indigo-400" }),
13789
+ /* @__PURE__ */ import_react29.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
13790
+ )), /* @__PURE__ */ import_react29.default.createElement(
13483
13791
  "button",
13484
13792
  {
13485
13793
  onClick: onClose,
13486
13794
  className: "w-8 h-8 rounded-lg flex items-center justify-center text-slate-400 hover:text-white hover:bg-white/10 transition-colors"
13487
13795
  },
13488
- "\xD7"
13796
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiX, { size: 16 })
13489
13797
  ))),
13490
- /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-1 overflow-hidden bg-slate-900/20" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-8 max-w-[900px] mx-auto w-full space-y-6" }, groups.length === 0 ? /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-4 border-2 border-dashed border-white/5 rounded-2xl bg-slate-900/40 p-12" }, /* @__PURE__ */ import_react30.default.createElement(import_fi23.FiLayers, { size: 40, className: "opacity-10 text-indigo-400" }), /* @__PURE__ */ import_react30.default.createElement("div", { className: "text-center space-y-1" }, /* @__PURE__ */ import_react30.default.createElement("p", { className: "text-sm font-medium text-slate-300" }, "Nenhum grupo criado"), /* @__PURE__ */ import_react30.default.createElement("p", { className: "text-xs text-slate-500 max-w-[200px]" }, canEdit ? "Comece organizando sua narrativa criando o primeiro grupo." : "Este board ainda n\xE3o possui conte\xFAdo.")), canEdit && /* @__PURE__ */ import_react30.default.createElement(
13798
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "h-10 px-6 bg-slate-900/40 border-b border-white/5 flex items-center gap-2 text-[10px] uppercase font-bold tracking-widest text-slate-500 overflow-x-auto no-scrollbar whitespace-nowrap" }, /* @__PURE__ */ import_react29.default.createElement(
13799
+ "button",
13800
+ {
13801
+ onClick: navigateHome,
13802
+ className: `hover:text-white transition-colors flex items-center gap-1 ${navigationStack.length === 0 ? "text-indigo-400" : ""}`
13803
+ },
13804
+ "Home"
13805
+ ), currentPath.map((folder, idx) => /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, { key: folder.id }, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiChevronRight, { size: 10, className: "shrink-0" }), /* @__PURE__ */ import_react29.default.createElement(
13491
13806
  "button",
13492
13807
  {
13493
- onClick: handleAddRootGroup,
13494
- className: "mt-2 px-4 py-2 bg-indigo-500/10 hover:bg-indigo-500/20 text-indigo-400 rounded-lg border border-indigo-500/20 transition-all text-xs font-bold uppercase tracking-wider"
13808
+ onClick: () => navigateToBreadcrumb(idx),
13809
+ className: `hover:text-white transition-colors ${idx === currentPath.length - 1 ? "text-indigo-400" : ""}`
13495
13810
  },
13496
- "Criar Primeiro Grupo"
13497
- )) : groups.map((group, index) => /* @__PURE__ */ import_react30.default.createElement(
13498
- GroupItem,
13811
+ folder.name || "Sem Nome"
13812
+ ))), navigationStack.length > 0 && /* @__PURE__ */ import_react29.default.createElement("div", { className: "ml-auto" }, /* @__PURE__ */ import_react29.default.createElement(
13813
+ "button",
13499
13814
  {
13500
- key: group.id,
13815
+ onClick: navigateUp,
13816
+ className: "flex items-center gap-1 px-2 py-1 rounded bg-white/5 hover:bg-white/10 text-slate-400 hover:text-white transition-all"
13817
+ },
13818
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiArrowLeft, { size: 10 }),
13819
+ /* @__PURE__ */ import_react29.default.createElement("span", null, "Voltar")
13820
+ ))),
13821
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar bg-slate-950/30 p-6 space-y-4" }, currentGroups.length === 0 ? /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-3 border-2 border-dashed border-white/5 rounded-xl bg-slate-900/20" }, /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiLayers, { size: 24, className: "opacity-20" }), /* @__PURE__ */ import_react29.default.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, "Esta pasta est\xE1 vazia.", /* @__PURE__ */ import_react29.default.createElement("br", null), "Use os bot\xF5es acima para criar conte\xFAdo.") : /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null, "Nenhum conte\xFAdo dispon\xEDvel nesta pasta."))) : currentGroups.map((item, index) => /* @__PURE__ */ import_react29.default.createElement(
13822
+ BoardItem,
13823
+ {
13824
+ key: item.id,
13501
13825
  index,
13502
- group,
13503
- onUpdate: handleUpdateGroup,
13504
- onDelete: handleDeleteGroup,
13826
+ prevItem: currentGroups[index - 1],
13827
+ nextItem: currentGroups[index + 1],
13828
+ item,
13829
+ onUpdate: handleUpdateItem,
13830
+ onDelete: handleDeleteItem,
13505
13831
  onAddSubgroup: handleAddSubgroup,
13506
13832
  onIndent: handleIndent,
13833
+ onIndentDown: handleIndentDown,
13507
13834
  onOutdent: handleOutdent,
13508
- onPlayAncestry: handlePlayFromGroup,
13509
- availableMentionItems,
13835
+ onMoveUp: handleMoveUp,
13836
+ onMoveDown: handleMoveDown,
13837
+ searchItems: allSearchableItems,
13838
+ onMentionClick: handleMentionClick,
13839
+ onEnterFolder: navigateTo,
13510
13840
  canEdit
13511
13841
  }
13512
- ))))),
13513
- /* @__PURE__ */ import_react30.default.createElement("div", { className: "px-6 py-3 border-t border-white/10 bg-slate-950/50 text-[10px] uppercase tracking-widest font-bold text-slate-600 flex justify-between items-center flex-shrink-0" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react30.default.createElement("span", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "w-1.5 h-1.5 rounded-full bg-indigo-500" }), " ", availableMentionItems.length, " RECURSOS DISPON\xCDVEIS"), /* @__PURE__ */ import_react30.default.createElement("span", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500" }), " ", groups.length, " GRUPOS PRINCIPAIS")), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-slate-700" }, "X.VIEW :: ANCESTRY BOARD ENGINE"))
13842
+ ))),
13843
+ /* @__PURE__ */ import_react29.default.createElement("div", { className: "px-5 py-2 border-t border-white/10 bg-slate-950/50 text-xs text-slate-500 flex justify-end flex-shrink-0" }, /* @__PURE__ */ import_react29.default.createElement("span", null, currentGroups.length, " itens nesta visualiza\xE7\xE3o"))
13514
13844
  )
13515
13845
  );
13516
13846
  }
13517
13847
 
13518
13848
  // src/components/MilestoneManager.jsx
13519
- var import_react31 = __toESM(require("react"));
13849
+ var import_react30 = __toESM(require("react"));
13520
13850
  var import_fi24 = require("react-icons/fi");
13521
13851
  function MilestoneManager({
13522
13852
  isOpen,
@@ -13525,7 +13855,7 @@ function MilestoneManager({
13525
13855
  onUpdateMilestones = () => {
13526
13856
  }
13527
13857
  }) {
13528
- const [newMilestoneName, setNewMilestoneName] = (0, import_react31.useState)("");
13858
+ const [newMilestoneName, setNewMilestoneName] = (0, import_react30.useState)("");
13529
13859
  const handleAddMilestone = () => {
13530
13860
  if (!newMilestoneName.trim()) return;
13531
13861
  const newMilestone = {
@@ -13550,27 +13880,27 @@ function MilestoneManager({
13550
13880
  };
13551
13881
  if (!isOpen) return null;
13552
13882
  const swallow = (e) => e.stopPropagation();
13553
- return /* @__PURE__ */ import_react31.default.createElement(
13883
+ return /* @__PURE__ */ import_react30.default.createElement(
13554
13884
  "div",
13555
13885
  {
13556
13886
  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",
13557
13887
  onClick: onClose
13558
13888
  },
13559
- /* @__PURE__ */ import_react31.default.createElement(
13889
+ /* @__PURE__ */ import_react30.default.createElement(
13560
13890
  "div",
13561
13891
  {
13562
13892
  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",
13563
13893
  onClick: swallow
13564
13894
  },
13565
- /* @__PURE__ */ import_react31.default.createElement("div", { className: "px-6 py-4 border-b border-white/10 flex items-center justify-between" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "p-2 rounded-lg bg-indigo-500/20 text-indigo-400" }, /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiTarget, { size: 20 })), /* @__PURE__ */ import_react31.default.createElement("div", null, /* @__PURE__ */ import_react31.default.createElement("h2", { className: "text-lg font-semibold text-slate-100" }, "Milestones"), /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-xs text-slate-400" }, "Gerencie os marcos do seu cen\xE1rio"))), /* @__PURE__ */ import_react31.default.createElement(
13895
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "px-6 py-4 border-b border-white/10 flex items-center justify-between" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "p-2 rounded-lg bg-indigo-500/20 text-indigo-400" }, /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiTarget, { size: 20 })), /* @__PURE__ */ import_react30.default.createElement("div", null, /* @__PURE__ */ import_react30.default.createElement("h2", { className: "text-lg font-semibold text-slate-100" }, "Milestones"), /* @__PURE__ */ import_react30.default.createElement("p", { className: "text-xs text-slate-400" }, "Gerencie os marcos do seu cen\xE1rio"))), /* @__PURE__ */ import_react30.default.createElement(
13566
13896
  "button",
13567
13897
  {
13568
13898
  onClick: onClose,
13569
13899
  className: "p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
13570
13900
  },
13571
- /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiX, { size: 20 })
13901
+ /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiX, { size: 20 })
13572
13902
  )),
13573
- /* @__PURE__ */ import_react31.default.createElement("div", { className: "px-6 py-5 bg-white/5 border-b border-white/5" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ import_react31.default.createElement(
13903
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "px-6 py-5 bg-white/5 border-b border-white/5" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ import_react30.default.createElement(
13574
13904
  "input",
13575
13905
  {
13576
13906
  type: "text",
@@ -13580,47 +13910,47 @@ function MilestoneManager({
13580
13910
  placeholder: "Adicionar novo milestone...",
13581
13911
  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"
13582
13912
  }
13583
- ), /* @__PURE__ */ import_react31.default.createElement(
13913
+ ), /* @__PURE__ */ import_react30.default.createElement(
13584
13914
  "button",
13585
13915
  {
13586
13916
  onClick: handleAddMilestone,
13587
13917
  disabled: !newMilestoneName.trim(),
13588
13918
  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"
13589
13919
  },
13590
- /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiPlus, { size: 18 }),
13920
+ /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiPlus, { size: 18 }),
13591
13921
  "Adicionar"
13592
13922
  ))),
13593
- /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex-1 overflow-y-auto px-6 py-4 custom-scrollbar" }, milestones.length > 0 ? /* @__PURE__ */ import_react31.default.createElement("div", { className: "space-y-3" }, milestones.map((ms) => /* @__PURE__ */ import_react31.default.createElement(
13923
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex-1 overflow-y-auto px-6 py-4 custom-scrollbar" }, milestones.length > 0 ? /* @__PURE__ */ import_react30.default.createElement("div", { className: "space-y-3" }, milestones.map((ms) => /* @__PURE__ */ import_react30.default.createElement(
13594
13924
  "div",
13595
13925
  {
13596
13926
  key: ms.id,
13597
13927
  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]"}`
13598
13928
  },
13599
- /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ import_react31.default.createElement(
13929
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ import_react30.default.createElement(
13600
13930
  "div",
13601
13931
  {
13602
13932
  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"}`
13603
13933
  }
13604
- ), /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ import_react31.default.createElement("span", { className: `text-sm font-medium truncate ${ms.status === "active" ? "text-slate-100" : "text-slate-400 line-through"}` }, ms.name), /* @__PURE__ */ import_react31.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, ms.status === "active" ? "Ativo" : "Inativo"))),
13605
- /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react31.default.createElement(
13934
+ ), /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ import_react30.default.createElement("span", { className: `text-sm font-medium truncate ${ms.status === "active" ? "text-slate-100" : "text-slate-400 line-through"}` }, ms.name), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, ms.status === "active" ? "Ativo" : "Inativo"))),
13935
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react30.default.createElement(
13606
13936
  "button",
13607
13937
  {
13608
13938
  onClick: () => handleToggleMilestoneStatus(ms.id),
13609
13939
  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"}`,
13610
13940
  title: ms.status === "active" ? "Inativar" : "Ativar"
13611
13941
  },
13612
- ms.status === "active" ? /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiPauseCircle, { size: 18 }) : /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiPlayCircle, { size: 18 })
13613
- ), /* @__PURE__ */ import_react31.default.createElement(
13942
+ ms.status === "active" ? /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiPauseCircle, { size: 18 }) : /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiPlayCircle, { size: 18 })
13943
+ ), /* @__PURE__ */ import_react30.default.createElement(
13614
13944
  "button",
13615
13945
  {
13616
13946
  onClick: () => handleRemoveMilestone(ms.id),
13617
13947
  className: "p-2 rounded-lg hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-all",
13618
13948
  title: "Remover"
13619
13949
  },
13620
- /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiTrash2, { size: 18 })
13950
+ /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiTrash2, { size: 18 })
13621
13951
  ))
13622
- ))) : /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex flex-col items-center justify-center py-12 text-center" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "p-4 rounded-full bg-slate-800/30 text-slate-600 mb-4" }, /* @__PURE__ */ import_react31.default.createElement(import_fi24.FiTarget, { size: 40 })), /* @__PURE__ */ import_react31.default.createElement("h3", { className: "text-slate-400 font-medium" }, "Nenhum milestone definido"), /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-xs text-slate-600 max-w-[200px] mt-1 italic" }, "Defina marcos importantes para orientar o progresso do projeto."))),
13623
- /* @__PURE__ */ import_react31.default.createElement("div", { className: "px-6 py-4 border-t border-white/5 bg-slate-900/50 flex items-center justify-between rounded-b-2xl" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex gap-4" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react31.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Total:"), /* @__PURE__ */ import_react31.default.createElement("span", { className: "text-xs font-bold text-slate-300" }, milestones.length)), /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react31.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Ativos:"), /* @__PURE__ */ import_react31.default.createElement("span", { className: "text-xs font-bold text-indigo-400" }, milestones.filter((m) => m.status === "active").length))))
13952
+ ))) : /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex flex-col items-center justify-center py-12 text-center" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "p-4 rounded-full bg-slate-800/30 text-slate-600 mb-4" }, /* @__PURE__ */ import_react30.default.createElement(import_fi24.FiTarget, { size: 40 })), /* @__PURE__ */ import_react30.default.createElement("h3", { className: "text-slate-400 font-medium" }, "Nenhum milestone definido"), /* @__PURE__ */ import_react30.default.createElement("p", { className: "text-xs text-slate-600 max-w-[200px] mt-1 italic" }, "Defina marcos importantes para orientar o progresso do projeto."))),
13953
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "px-6 py-4 border-t border-white/5 bg-slate-900/50 flex items-center justify-between rounded-b-2xl" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex gap-4" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Total:"), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-xs font-bold text-slate-300" }, milestones.length)), /* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Ativos:"), /* @__PURE__ */ import_react30.default.createElement("span", { className: "text-xs font-bold text-indigo-400" }, milestones.filter((m) => m.status === "active").length))))
13624
13954
  )
13625
13955
  );
13626
13956
  }
@@ -13706,13 +14036,13 @@ function XViewScene({
13706
14036
  check_user_permission,
13707
14037
  get_view_members
13708
14038
  }) {
13709
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
13710
- const { data: session, status } = (0, import_react33.useSession)();
14039
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
14040
+ const { data: session, status } = (0, import_react32.useSession)();
13711
14041
  const router = (0, import_navigation.useRouter)();
13712
14042
  const searchParams = (0, import_navigation.useSearchParams)();
13713
14043
  const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
13714
14044
  const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
13715
- const viewParams = (0, import_react32.useMemo)(() => {
14045
+ const viewParams = (0, import_react31.useMemo)(() => {
13716
14046
  if (encryptedConfig) {
13717
14047
  const data = decryptData(encryptedConfig);
13718
14048
  if (data) {
@@ -13721,7 +14051,7 @@ function XViewScene({
13721
14051
  }
13722
14052
  return null;
13723
14053
  }, [encryptedConfig, session]);
13724
- (0, import_react32.useEffect)(() => {
14054
+ (0, import_react31.useEffect)(() => {
13725
14055
  async function verifyPermission() {
13726
14056
  if (!viewParams || !session || !check_user_permission) return;
13727
14057
  const { id, type, owner_id } = viewParams;
@@ -13758,65 +14088,65 @@ function XViewScene({
13758
14088
  setIsLoading(false);
13759
14089
  }
13760
14090
  }, [viewParams, session, status, check_user_permission]);
13761
- const sceneConfigId = (0, import_react32.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
13762
- const ownerId = (0, import_react32.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
13763
- const dbSaveUrl = (0, import_react32.useMemo)(() => {
14091
+ const sceneConfigId = (0, import_react31.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
14092
+ const ownerId = (0, import_react31.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
14093
+ const dbSaveUrl = (0, import_react31.useMemo)(() => {
13764
14094
  if (ownerId && sceneConfigId) {
13765
14095
  return `x_view_dbs/${ownerId}/${sceneConfigId}`;
13766
14096
  }
13767
14097
  return null;
13768
14098
  }, [ownerId, sceneConfigId]);
13769
- const sceneSaveUrl = (0, import_react32.useMemo)(() => {
14099
+ const sceneSaveUrl = (0, import_react31.useMemo)(() => {
13770
14100
  if (ownerId && sceneConfigId) {
13771
14101
  return `x_view_scenes/${ownerId}/${sceneConfigId}`;
13772
14102
  }
13773
14103
  return null;
13774
14104
  }, [ownerId, sceneConfigId]);
13775
- const ancestry_save_url = (0, import_react32.useMemo)(() => {
14105
+ const ancestry_save_url = (0, import_react31.useMemo)(() => {
13776
14106
  if (ownerId && sceneConfigId) {
13777
14107
  return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
13778
14108
  }
13779
14109
  return null;
13780
14110
  }, [ownerId, sceneConfigId]);
13781
- const sceneDataRef = (0, import_react32.useRef)(null);
13782
- const parentDataRef = (0, import_react32.useRef)(null);
13783
- const ancestryDataRef = (0, import_react32.useRef)(null);
13784
- const [isLoading, setIsLoading] = (0, import_react32.useState)(true);
13785
- const [permissionStatus, setPermissionStatus] = (0, import_react32.useState)("loading");
13786
- const [userPermissionRole, setUserPermissionRole] = (0, import_react32.useState)(null);
13787
- const [viewMembers, setViewMembers] = (0, import_react32.useState)([]);
13788
- const [isInitialized, setIsInitialized] = (0, import_react32.useState)(false);
13789
- const [sceneVersion, setSceneVersion] = (0, import_react32.useState)(0);
13790
- const [contextMenu, setContextMenu] = (0, import_react32.useState)({
14111
+ const sceneDataRef = (0, import_react31.useRef)(null);
14112
+ const parentDataRef = (0, import_react31.useRef)(null);
14113
+ const ancestryDataRef = (0, import_react31.useRef)(null);
14114
+ const [isLoading, setIsLoading] = (0, import_react31.useState)(true);
14115
+ const [permissionStatus, setPermissionStatus] = (0, import_react31.useState)("loading");
14116
+ const [userPermissionRole, setUserPermissionRole] = (0, import_react31.useState)(null);
14117
+ const [viewMembers, setViewMembers] = (0, import_react31.useState)([]);
14118
+ const [isInitialized, setIsInitialized] = (0, import_react31.useState)(false);
14119
+ const [sceneVersion, setSceneVersion] = (0, import_react31.useState)(0);
14120
+ const [contextMenu, setContextMenu] = (0, import_react31.useState)({
13791
14121
  visible: false,
13792
14122
  x: 0,
13793
14123
  y: 0,
13794
14124
  nodeData: null
13795
14125
  });
13796
- const [multiContextMenu, setMultiContextMenu] = (0, import_react32.useState)({
14126
+ const [multiContextMenu, setMultiContextMenu] = (0, import_react31.useState)({
13797
14127
  visible: false,
13798
14128
  x: 0,
13799
14129
  y: 0,
13800
14130
  nodeIds: null
13801
14131
  });
13802
- const [relationshipMenu, setRelationshipMenu] = (0, import_react32.useState)({
14132
+ const [relationshipMenu, setRelationshipMenu] = (0, import_react31.useState)({
13803
14133
  visible: false,
13804
14134
  x: 0,
13805
14135
  y: 0,
13806
14136
  linkObject: null
13807
14137
  });
13808
- const [creationMode, setCreationMode] = (0, import_react32.useState)({
14138
+ const [creationMode, setCreationMode] = (0, import_react31.useState)({
13809
14139
  isActive: false,
13810
14140
  sourceNodeData: null
13811
14141
  });
13812
- const [versionMode, setVersionMode] = (0, import_react32.useState)({
14142
+ const [versionMode, setVersionMode] = (0, import_react31.useState)({
13813
14143
  isActive: false,
13814
14144
  sourceNodeData: null
13815
14145
  });
13816
- const [questMode, setQuestMode] = (0, import_react32.useState)({ isActive: false });
13817
- const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react32.useState)(false);
13818
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react32.useState)(false);
13819
- const [ancestryMode, setAncestryMode] = (0, import_react32.useState)({
14146
+ const [questMode, setQuestMode] = (0, import_react31.useState)({ isActive: false });
14147
+ const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react31.useState)(false);
14148
+ const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react31.useState)(false);
14149
+ const [ancestryMode, setAncestryMode] = (0, import_react31.useState)({
13820
14150
  isActive: false,
13821
14151
  tree: null,
13822
14152
  selectedParentId: null,
@@ -13827,42 +14157,42 @@ function XViewScene({
13827
14157
  ancestryDescriptionSections: [],
13828
14158
  isAddingNodes: false
13829
14159
  });
13830
- const [readingMode, setReadingMode] = (0, import_react32.useState)({
14160
+ const [readingMode, setReadingMode] = (0, import_react31.useState)({
13831
14161
  isActive: false,
13832
14162
  ancestry: null,
13833
14163
  branchStack: [],
13834
14164
  autoAbstraction: false
13835
14165
  });
13836
- const [formPosition, setFormPosition] = (0, import_react32.useState)({
14166
+ const [formPosition, setFormPosition] = (0, import_react31.useState)({
13837
14167
  left: 16,
13838
14168
  top: 16,
13839
14169
  opacity: 0
13840
14170
  });
13841
- const [detailsNode, setDetailsNode] = (0, import_react32.useState)(null);
13842
- const [detailsLink, setDetailsLink] = (0, import_react32.useState)(null);
13843
- const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react32.useState)(null);
13844
- const [imageViewer, setImageViewer] = (0, import_react32.useState)({
14171
+ const [detailsNode, setDetailsNode] = (0, import_react31.useState)(null);
14172
+ const [detailsLink, setDetailsLink] = (0, import_react31.useState)(null);
14173
+ const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react31.useState)(null);
14174
+ const [imageViewer, setImageViewer] = (0, import_react31.useState)({
13845
14175
  visible: false,
13846
14176
  images: [],
13847
14177
  startIndex: 0
13848
14178
  });
13849
- const [editingAncestryRel, setEditingAncestryRel] = (0, import_react32.useState)({
14179
+ const [editingAncestryRel, setEditingAncestryRel] = (0, import_react31.useState)({
13850
14180
  visible: false,
13851
14181
  data: null,
13852
14182
  path: null
13853
14183
  });
13854
- const [isImportModalOpen, setIsImportModalOpen] = (0, import_react32.useState)(false);
13855
- const [importSuccessMessage, setImportSuccessMessage] = (0, import_react32.useState)("");
13856
- const [invalidTargetError, setInvalidTargetError] = (0, import_react32.useState)(null);
13857
- const [highlightedNodeId, setHighlightedNodeId] = (0, import_react32.useState)(null);
13858
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react32.useState)(false);
13859
- const [ancestryBoardData, setAncestryBoardData] = (0, import_react32.useState)([]);
13860
- const [isSidebarOpen, setIsSidebarOpen] = (0, import_react32.useState)(false);
13861
- const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = (0, import_react32.useState)(false);
13862
- const mountRef = (0, import_react32.useRef)(null);
13863
- const tooltipRef = (0, import_react32.useRef)(null);
13864
- const formRef = (0, import_react32.useRef)(null);
13865
- const stateRef = (0, import_react32.useRef)({
14184
+ const [isImportModalOpen, setIsImportModalOpen] = (0, import_react31.useState)(false);
14185
+ const [importSuccessMessage, setImportSuccessMessage] = (0, import_react31.useState)("");
14186
+ const [invalidTargetError, setInvalidTargetError] = (0, import_react31.useState)(null);
14187
+ const [highlightedNodeId, setHighlightedNodeId] = (0, import_react31.useState)(null);
14188
+ const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react31.useState)(false);
14189
+ const [ancestryBoardData, setAncestryBoardData] = (0, import_react31.useState)([]);
14190
+ const [isSidebarOpen, setIsSidebarOpen] = (0, import_react31.useState)(false);
14191
+ const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = (0, import_react31.useState)(false);
14192
+ const mountRef = (0, import_react31.useRef)(null);
14193
+ const tooltipRef = (0, import_react31.useRef)(null);
14194
+ const formRef = (0, import_react31.useRef)(null);
14195
+ const stateRef = (0, import_react31.useRef)({
13866
14196
  readMode: {
13867
14197
  currentMaxIndex: 0,
13868
14198
  progressMap: {}
@@ -13926,10 +14256,10 @@ function XViewScene({
13926
14256
  minWidth: 320,
13927
14257
  maxWidth: maxReadPanelW
13928
14258
  });
13929
- (0, import_react32.useEffect)(() => {
14259
+ (0, import_react31.useEffect)(() => {
13930
14260
  stateRef.current.ancestry = ancestryMode;
13931
14261
  }, [ancestryMode]);
13932
- (0, import_react32.useEffect)(() => {
14262
+ (0, import_react31.useEffect)(() => {
13933
14263
  var _a2;
13934
14264
  if (!isInitialized) return;
13935
14265
  const map = /* @__PURE__ */ new Map();
@@ -13952,10 +14282,10 @@ function XViewScene({
13952
14282
  }
13953
14283
  stateRef.current.nodeIdToParentFileMap = map;
13954
14284
  }, [isInitialized, sceneVersion]);
13955
- const handleNavigateBack = (0, import_react32.useCallback)(() => {
14285
+ const handleNavigateBack = (0, import_react31.useCallback)(() => {
13956
14286
  router.push("/dashboard/scenes");
13957
14287
  }, [router]);
13958
- const handleConfirmImport = (0, import_react32.useCallback)(
14288
+ const handleConfirmImport = (0, import_react31.useCallback)(
13959
14289
  async (importPayload) => {
13960
14290
  var _a2, _b2;
13961
14291
  let files = [];
@@ -14083,7 +14413,7 @@ function XViewScene({
14083
14413
  const handleOpenImageViewer = (images, startIndex) => {
14084
14414
  setImageViewer({ visible: true, images, startIndex });
14085
14415
  };
14086
- const tweenToTarget = (0, import_react32.useCallback)(
14416
+ const tweenToTarget = (0, import_react31.useCallback)(
14087
14417
  (target, zoomFactor = 1, forcedDirection = null) => {
14088
14418
  const { camera, controls, tweenGroup } = stateRef.current;
14089
14419
  if (!camera || !controls || !tweenGroup) return;
@@ -14109,7 +14439,7 @@ function XViewScene({
14109
14439
  if (!t || typeof t.closest !== "function") return false;
14110
14440
  return !!t.closest(".ui-overlay");
14111
14441
  };
14112
- const buildFullAncestryTree = (0, import_react32.useCallback)(
14442
+ const buildFullAncestryTree = (0, import_react31.useCallback)(
14113
14443
  (idTree, nodes, ancestries = []) => {
14114
14444
  if (!idTree) return null;
14115
14445
  const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
@@ -14194,7 +14524,7 @@ function XViewScene({
14194
14524
  },
14195
14525
  []
14196
14526
  );
14197
- const handleActivateTimeline = (0, import_react32.useCallback)(() => {
14527
+ const handleActivateTimeline = (0, import_react31.useCallback)(() => {
14198
14528
  const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
14199
14529
  if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
14200
14530
  while (timelineIntervalsGroup.children.length > 0) {
@@ -14354,7 +14684,7 @@ function XViewScene({
14354
14684
  }
14355
14685
  });
14356
14686
  }, []);
14357
- const handleVersionTimeline = (0, import_react32.useCallback)((sourceMesh, versionMeshes) => {
14687
+ const handleVersionTimeline = (0, import_react31.useCallback)((sourceMesh, versionMeshes) => {
14358
14688
  const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
14359
14689
  if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
14360
14690
  return;
@@ -14491,7 +14821,7 @@ function XViewScene({
14491
14821
  }
14492
14822
  });
14493
14823
  }, []);
14494
- (0, import_react32.useEffect)(() => {
14824
+ (0, import_react31.useEffect)(() => {
14495
14825
  async function fetchAllData(configPath, ownerId2) {
14496
14826
  var _a2, _b2;
14497
14827
  if (!get_scene_view_data) {
@@ -14596,12 +14926,12 @@ function XViewScene({
14596
14926
  focusNodeId,
14597
14927
  focusAncestryId
14598
14928
  ]);
14599
- const isNodeInView = (0, import_react32.useCallback)((id) => {
14929
+ const isNodeInView = (0, import_react31.useCallback)((id) => {
14600
14930
  const key = String(id);
14601
14931
  const objs = stateRef.current.nodeObjects || {};
14602
14932
  return !!objs[key];
14603
14933
  }, []);
14604
- const addOrUpdateNodeMesh = (0, import_react32.useCallback)(
14934
+ const addOrUpdateNodeMesh = (0, import_react31.useCallback)(
14605
14935
  (nodeData, position, suppressVersionUpdate = false, forceShowQuestDate = false) => {
14606
14936
  const {
14607
14937
  graphGroup,
@@ -14642,7 +14972,7 @@ function XViewScene({
14642
14972
  },
14643
14973
  []
14644
14974
  );
14645
- const handleActivateQuestLens = (0, import_react32.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
14975
+ const handleActivateQuestLens = (0, import_react31.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
14646
14976
  var _a2;
14647
14977
  const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
14648
14978
  if (!nodeObjects || !tweenGroup || !graphGroup) return;
@@ -14856,7 +15186,7 @@ function XViewScene({
14856
15186
  camTween.start();
14857
15187
  }
14858
15188
  }, [addOrUpdateNodeMesh]);
14859
- (0, import_react32.useEffect)(() => {
15189
+ (0, import_react31.useEffect)(() => {
14860
15190
  if (!isInitialized || !sceneDataRef.current) return;
14861
15191
  const currentMount = mountRef.current;
14862
15192
  if (!currentMount) return;
@@ -15612,7 +15942,7 @@ function XViewScene({
15612
15942
  get_scene_view_data,
15613
15943
  save_view_data
15614
15944
  ]);
15615
- const handleGhostNodeImageChange = (0, import_react32.useCallback)((useImage, imageUrl) => {
15945
+ const handleGhostNodeImageChange = (0, import_react31.useCallback)((useImage, imageUrl) => {
15616
15946
  const {
15617
15947
  node: ghostNode,
15618
15948
  line: ghostLine,
@@ -15660,7 +15990,7 @@ function XViewScene({
15660
15990
  aura: newGhostNode.getObjectByName("aura")
15661
15991
  };
15662
15992
  }, []);
15663
- const handleGhostNodeIntensityChange = (0, import_react32.useCallback)((newIntensity) => {
15993
+ const handleGhostNodeIntensityChange = (0, import_react31.useCallback)((newIntensity) => {
15664
15994
  const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
15665
15995
  if (!ghostNode) return;
15666
15996
  const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
@@ -15681,7 +16011,7 @@ function XViewScene({
15681
16011
  ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
15682
16012
  }
15683
16013
  }, []);
15684
- const handleDetailNodeIntensityChange = (0, import_react32.useCallback)(
16014
+ const handleDetailNodeIntensityChange = (0, import_react31.useCallback)(
15685
16015
  (nodeId, newIntensity) => {
15686
16016
  const mesh = stateRef.current.nodeObjects[String(nodeId)];
15687
16017
  if (!mesh) return;
@@ -15837,7 +16167,7 @@ function XViewScene({
15837
16167
  mountRef.current.style.cursor = "default";
15838
16168
  }
15839
16169
  };
15840
- const handleAncestryTreeUpdate = (0, import_react32.useCallback)((newTree, extraData = null) => {
16170
+ const handleAncestryTreeUpdate = (0, import_react31.useCallback)((newTree, extraData = null) => {
15841
16171
  setAncestryMode((prev) => {
15842
16172
  const prevTreeStr = JSON.stringify(prev.tree);
15843
16173
  const newTreeStr = JSON.stringify(newTree);
@@ -15860,7 +16190,7 @@ function XViewScene({
15860
16190
  };
15861
16191
  });
15862
16192
  }, []);
15863
- const actionHandlerContext = (0, import_react32.useMemo)(
16193
+ const actionHandlerContext = (0, import_react31.useMemo)(
15864
16194
  () => {
15865
16195
  var _a2;
15866
16196
  return {
@@ -15921,7 +16251,7 @@ function XViewScene({
15921
16251
  const handleStartVersioning = (nodeData) => {
15922
16252
  userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
15923
16253
  };
15924
- const handleStartQuestQuick = (0, import_react32.useCallback)((questNode) => {
16254
+ const handleStartQuestQuick = (0, import_react31.useCallback)((questNode) => {
15925
16255
  var _a2, _b2, _c2;
15926
16256
  if (!questNode || !actionHandlerContext) return;
15927
16257
  const allParentNodes = Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
@@ -15956,7 +16286,7 @@ function XViewScene({
15956
16286
  }
15957
16287
  setDetailsNode(updatedNode);
15958
16288
  }, [session, actionHandlerContext]);
15959
- const handleFinishQuestQuick = (0, import_react32.useCallback)((questNode) => {
16289
+ const handleFinishQuestQuick = (0, import_react31.useCallback)((questNode) => {
15960
16290
  var _a2, _b2, _c2, _d2;
15961
16291
  if (!questNode || !actionHandlerContext) return;
15962
16292
  const {
@@ -16030,7 +16360,7 @@ function XViewScene({
16030
16360
  setDetailsNode(null);
16031
16361
  }
16032
16362
  }, [session, actionHandlerContext, viewMembers, detailsNode]);
16033
- const handleCancelQuest = (0, import_react32.useCallback)(() => {
16363
+ const handleCancelQuest = (0, import_react31.useCallback)(() => {
16034
16364
  const { graphGroup, ghostElements } = stateRef.current;
16035
16365
  if (ghostElements.node && graphGroup) {
16036
16366
  if (ghostElements.node.userData.labelObject) {
@@ -16089,13 +16419,15 @@ function XViewScene({
16089
16419
  try {
16090
16420
  await actions.save_view_data(sceneSaveUrl2, sceneFileData);
16091
16421
  sceneDataRef2.current.quest_counter = currentCounter + 1;
16092
- sceneDataRef2.current.quest_nodes = sceneFileData.quest_nodes;
16093
- sceneDataRef2.current.quest_links = sceneFileData.quest_links;
16094
16422
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
16095
16423
  parentFileId: sceneConfigId2,
16096
16424
  ownerId: ownerId2,
16097
16425
  datasetName: "Quests Internas (View)"
16098
16426
  });
16427
+ sceneDataRef2.current.quest_nodes = [...graphDataRef.current[sceneConfigId2].nodes];
16428
+ if (parentDataRef.current[sceneConfigId2]) {
16429
+ parentDataRef.current[sceneConfigId2].nodes = [...graphDataRef.current[sceneConfigId2].nodes];
16430
+ }
16099
16431
  const finalPosition = stateRef2.current.ghostElements.node ? stateRef2.current.ghostElements.node.position.clone() : stateRef2.current.controls.target.clone();
16100
16432
  const { graphGroup, ghostElements } = stateRef2.current;
16101
16433
  if (ghostElements.node && graphGroup) {
@@ -16185,7 +16517,7 @@ function XViewScene({
16185
16517
  }
16186
16518
  userActionHandlers.handleCancelConnection(context);
16187
16519
  };
16188
- const handleClearAncestryVisuals = (0, import_react32.useCallback)((ancestryId) => {
16520
+ const handleClearAncestryVisuals = (0, import_react31.useCallback)((ancestryId) => {
16189
16521
  const { renderedAncestries, ancestryGroup } = stateRef.current;
16190
16522
  const renderIndex = renderedAncestries.findIndex(
16191
16523
  (a) => String(a.id) === String(ancestryId)
@@ -16203,7 +16535,7 @@ function XViewScene({
16203
16535
  );
16204
16536
  }
16205
16537
  }, []);
16206
- const handleRenderAncestry = (0, import_react32.useCallback)(
16538
+ const handleRenderAncestry = (0, import_react31.useCallback)(
16207
16539
  async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
16208
16540
  setContextMenu(
16209
16541
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16697,7 +17029,7 @@ function XViewScene({
16697
17029
  ancestryMode.isActive
16698
17030
  ]
16699
17031
  );
16700
- const handleRenderAbstractionTree = (0, import_react32.useCallback)(
17032
+ const handleRenderAbstractionTree = (0, import_react31.useCallback)(
16701
17033
  (ancestryObject, targetNodeId = null) => {
16702
17034
  setContextMenu(
16703
17035
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -16785,7 +17117,7 @@ function XViewScene({
16785
17117
  handleClearAncestryVisuals
16786
17118
  ]
16787
17119
  );
16788
- const handleReadModeBranchNav = (0, import_react32.useCallback)(
17120
+ const handleReadModeBranchNav = (0, import_react31.useCallback)(
16789
17121
  (nodeId, action, direction = "right") => {
16790
17122
  const { ancestry, branchStack } = readingMode;
16791
17123
  if (!ancestry || !ancestry.tree) return;
@@ -16963,13 +17295,13 @@ function XViewScene({
16963
17295
  },
16964
17296
  [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
16965
17297
  );
16966
- const handleReadModeHighlight = (0, import_react32.useCallback)((nodeId) => {
17298
+ const handleReadModeHighlight = (0, import_react31.useCallback)((nodeId) => {
16967
17299
  if (stateRef.current.highlightedNodeId !== nodeId) {
16968
17300
  stateRef.current.highlightedNodeId = nodeId;
16969
17301
  }
16970
17302
  setHighlightedNodeId(nodeId);
16971
17303
  }, []);
16972
- const activeNodeBranches = (0, import_react32.useMemo)(() => {
17304
+ const activeNodeBranches = (0, import_react31.useMemo)(() => {
16973
17305
  if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
16974
17306
  return null;
16975
17307
  const fullTree = buildFullAncestryTree(
@@ -17013,7 +17345,7 @@ function XViewScene({
17013
17345
  readingMode.branchStack,
17014
17346
  ancestryDataRef.current
17015
17347
  ]);
17016
- const backNavigationInfo = (0, import_react32.useMemo)(() => {
17348
+ const backNavigationInfo = (0, import_react31.useMemo)(() => {
17017
17349
  const { branchStack } = readingMode;
17018
17350
  if (!branchStack || branchStack.length === 0) return null;
17019
17351
  const lastStep = branchStack[branchStack.length - 1];
@@ -17024,7 +17356,7 @@ function XViewScene({
17024
17356
  name: "Voltar para anterior"
17025
17357
  };
17026
17358
  }, [readingMode.branchStack]);
17027
- const getReadModeDisplayContext = (0, import_react32.useMemo)(() => {
17359
+ const getReadModeDisplayContext = (0, import_react31.useMemo)(() => {
17028
17360
  const { ancestry, branchStack } = readingMode;
17029
17361
  if (!ancestry) return null;
17030
17362
  if (branchStack.length === 0) {
@@ -17067,7 +17399,7 @@ function XViewScene({
17067
17399
  customProperties: branchProps
17068
17400
  };
17069
17401
  }, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
17070
- const readModeAbstractionTree = (0, import_react32.useMemo)(() => {
17402
+ const readModeAbstractionTree = (0, import_react31.useMemo)(() => {
17071
17403
  if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
17072
17404
  return null;
17073
17405
  }
@@ -17086,7 +17418,7 @@ function XViewScene({
17086
17418
  buildFullAncestryTree,
17087
17419
  sceneVersion
17088
17420
  ]);
17089
- const handleStartReadingAncestry = (0, import_react32.useCallback)(
17421
+ const handleStartReadingAncestry = (0, import_react31.useCallback)(
17090
17422
  async (ancestryObject, renderMode = "full") => {
17091
17423
  setContextMenu(
17092
17424
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17129,7 +17461,7 @@ function XViewScene({
17129
17461
  },
17130
17462
  [handleRenderAncestry, handleRenderAbstractionTree]
17131
17463
  );
17132
- const handleReadModeSectionChange = (0, import_react32.useCallback)(
17464
+ const handleReadModeSectionChange = (0, import_react31.useCallback)(
17133
17465
  (activeSectionId) => {
17134
17466
  const { ancestry, branchStack } = readingMode;
17135
17467
  if (!ancestry || !readingMode.isActive) return;
@@ -17214,10 +17546,10 @@ function XViewScene({
17214
17546
  ancestryDataRef.current
17215
17547
  ]
17216
17548
  );
17217
- const handleCloseReadMode = (0, import_react32.useCallback)(() => {
17549
+ const handleCloseReadMode = (0, import_react31.useCallback)(() => {
17218
17550
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
17219
17551
  }, []);
17220
- const handleAncestrySectionChange = (0, import_react32.useCallback)(
17552
+ const handleAncestrySectionChange = (0, import_react31.useCallback)(
17221
17553
  (activeSectionId, ancestryOverride = null, rotation = 0) => {
17222
17554
  var _a2, _b2;
17223
17555
  const currentMode = stateRef.current.ancestry;
@@ -17279,7 +17611,7 @@ function XViewScene({
17279
17611
  },
17280
17612
  [handleRenderAncestry]
17281
17613
  );
17282
- const handleEditAncestry = (0, import_react32.useCallback)(
17614
+ const handleEditAncestry = (0, import_react31.useCallback)(
17283
17615
  async (ancestryObject) => {
17284
17616
  setContextMenu(
17285
17617
  (prev) => prev.visible ? { ...prev, visible: false } : prev
@@ -17334,7 +17666,7 @@ function XViewScene({
17334
17666
  const handleSelectAncestryParent = (nodeId) => {
17335
17667
  setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
17336
17668
  };
17337
- const handleRemoveFromAncestry = (0, import_react32.useCallback)((pathToRemove) => {
17669
+ const handleRemoveFromAncestry = (0, import_react31.useCallback)((pathToRemove) => {
17338
17670
  if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
17339
17671
  console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
17340
17672
  return;
@@ -17359,7 +17691,7 @@ function XViewScene({
17359
17691
  return { ...prev, tree: newTree };
17360
17692
  });
17361
17693
  }, []);
17362
- const handleSaveAncestry = (0, import_react32.useCallback)(
17694
+ const handleSaveAncestry = (0, import_react31.useCallback)(
17363
17695
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
17364
17696
  const treeToUse = treeOverride || ancestryMode.tree;
17365
17697
  const { isEditMode, currentAncestryId } = ancestryMode;
@@ -17595,7 +17927,7 @@ function XViewScene({
17595
17927
  });
17596
17928
  setEditingAncestryRel({ visible: false, data: null, path: null });
17597
17929
  };
17598
- const handleDeleteAncestry = (0, import_react32.useCallback)(
17930
+ const handleDeleteAncestry = (0, import_react31.useCallback)(
17599
17931
  async (ancestryIdToDelete) => {
17600
17932
  if (!ancestryIdToDelete) {
17601
17933
  alert("ID da ancestralidade n\xE3o encontrado.");
@@ -17677,28 +18009,70 @@ function XViewScene({
17677
18009
  },
17678
18010
  [save_view_data, delete_file_action]
17679
18011
  );
17680
- const handleOpenAncestryBoard = (0, import_react32.useCallback)(() => {
18012
+ const handleOpenAncestryBoard = (0, import_react31.useCallback)(() => {
17681
18013
  setIsAncestryBoardOpen(true);
17682
18014
  }, []);
17683
- const handleSelectAncestryFromBoard = (0, import_react32.useCallback)(
18015
+ const allAvailableNodes = (0, import_react31.useMemo)(() => {
18016
+ if (!parentDataRef.current) return [];
18017
+ return Object.values(parentDataRef.current).flatMap(
18018
+ (fileData) => fileData.nodes || []
18019
+ );
18020
+ }, [sceneVersion, isInitialized]);
18021
+ const allAvailableAncestries = (0, import_react31.useMemo)(() => {
18022
+ return ancestryDataRef.current || [];
18023
+ }, [sceneVersion, isInitialized]);
18024
+ const handleOpenReference = (0, import_react31.useCallback)(
18025
+ (referenceData) => {
18026
+ const { type, id } = referenceData;
18027
+ if (type === "node") {
18028
+ const targetNode = allAvailableNodes.find(
18029
+ (n) => String(n.id) === String(id)
18030
+ );
18031
+ if (targetNode) {
18032
+ setAncestryLinkDetails(null);
18033
+ setDetailsLink(null);
18034
+ setDetailsNode(targetNode);
18035
+ const sceneMesh = stateRef.current.nodeObjects[String(id)];
18036
+ if (sceneMesh) {
18037
+ tweenToTarget(sceneMesh);
18038
+ }
18039
+ } else {
18040
+ alert("Node original n\xE3o encontrado neste contexto.");
18041
+ }
18042
+ } else if (type === "ancestry") {
18043
+ const targetAncestry = allAvailableAncestries.find(
18044
+ (a) => String(a.ancestry_id) === String(id)
18045
+ );
18046
+ if (targetAncestry) {
18047
+ setDetailsNode(null);
18048
+ setDetailsLink(null);
18049
+ setAncestryLinkDetails(null);
18050
+ handleEditAncestry(targetAncestry);
18051
+ } else {
18052
+ alert("Ancestralidade original n\xE3o encontrada neste contexto.");
18053
+ }
18054
+ }
18055
+ },
18056
+ [
18057
+ allAvailableNodes,
18058
+ allAvailableAncestries,
18059
+ handleEditAncestry,
18060
+ tweenToTarget
18061
+ ]
18062
+ );
18063
+ const handleSelectAncestryFromBoard = (0, import_react31.useCallback)(
17684
18064
  (item) => {
17685
18065
  setIsAncestryBoardOpen(false);
17686
18066
  setIsSidebarOpen(false);
17687
- if (item.type === "ancestry" || !item.type) {
18067
+ if (item.type === "ancestry") {
17688
18068
  handleStartReadingAncestry(item);
17689
18069
  } else {
17690
- const nodeId = String(item.id);
17691
- const sceneMesh = stateRef.current.nodeObjects[nodeId];
17692
- if (sceneMesh) {
17693
- tweenToTarget(sceneMesh);
17694
- } else {
17695
- console.warn("Objeto n\xE3o encontrado na cena para foco:", nodeId);
17696
- }
18070
+ handleOpenReference({ type: "node", id: item.id });
17697
18071
  }
17698
18072
  },
17699
- [handleStartReadingAncestry, tweenToTarget]
18073
+ [handleStartReadingAncestry, handleOpenReference]
17700
18074
  );
17701
- const handleSaveAncestryBoard = (0, import_react32.useCallback)(
18075
+ const handleSaveAncestryBoard = (0, import_react31.useCallback)(
17702
18076
  async (groups) => {
17703
18077
  if (!sceneConfigId || !viewParams || !session) return;
17704
18078
  const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
@@ -17712,7 +18086,7 @@ function XViewScene({
17712
18086
  },
17713
18087
  [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
17714
18088
  );
17715
- const existingNodeTypes = (0, import_react32.useMemo)(() => {
18089
+ const existingNodeTypes = (0, import_react31.useMemo)(() => {
17716
18090
  if (!parentDataRef.current) {
17717
18091
  return [];
17718
18092
  }
@@ -17724,28 +18098,22 @@ function XViewScene({
17724
18098
  ).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
17725
18099
  return [...new Set(allTypes)];
17726
18100
  }, [parentDataRef.current, sceneVersion]);
17727
- const searchableDbNodes = (0, import_react32.useMemo)(() => {
17728
- var _a2;
18101
+ const searchableDbNodes = (0, import_react31.useMemo)(() => {
17729
18102
  if (!parentDataRef.current) {
17730
18103
  return [];
17731
18104
  }
17732
- const datasetsPool = Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
18105
+ return Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
17733
18106
  const datasetName = fileData.dataset_name || `Dataset #${dbId.substring(0, 6)}`;
17734
18107
  return (fileData.nodes || []).map((node) => ({
17735
18108
  ...node,
17736
18109
  dataset_name: datasetName
17737
18110
  }));
18111
+ }).filter((node) => {
18112
+ var _a2;
18113
+ return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
17738
18114
  });
17739
- const questsPool = (((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || []).map((node) => ({
17740
- ...node,
17741
- dataset_name: "Quests Internas (View)"
17742
- }));
17743
- return [...datasetsPool, ...questsPool].filter((node) => {
17744
- var _a3;
17745
- return !((_a3 = node.version_node) == null ? void 0 : _a3.is_version);
17746
- });
17747
- }, [parentDataRef.current, (_b = sceneDataRef.current) == null ? void 0 : _b.quest_nodes, sceneVersion]);
17748
- const handleAddExistingNode = (0, import_react32.useCallback)(
18115
+ }, [parentDataRef.current, sceneVersion]);
18116
+ const handleAddExistingNode = (0, import_react31.useCallback)(
17749
18117
  (nodeId) => {
17750
18118
  return userActionHandlers.handleAddExistingNodeById(
17751
18119
  actionHandlerContext,
@@ -17754,7 +18122,7 @@ function XViewScene({
17754
18122
  },
17755
18123
  [actionHandlerContext]
17756
18124
  );
17757
- const handleUpdateMilestones = (0, import_react32.useCallback)(
18125
+ const handleUpdateMilestones = (0, import_react31.useCallback)(
17758
18126
  async (newMilestones) => {
17759
18127
  var _a2, _b2, _c2;
17760
18128
  if (!sceneDataRef.current) return;
@@ -17800,7 +18168,7 @@ function XViewScene({
17800
18168
  viewParams == null ? void 0 : viewParams.type
17801
18169
  ]
17802
18170
  );
17803
- const handleSaveCurrentView = (0, import_react32.useCallback)(async () => {
18171
+ const handleSaveCurrentView = (0, import_react31.useCallback)(async () => {
17804
18172
  var _a2, _b2, _c2;
17805
18173
  const { nodeObjects, allLinks } = stateRef.current;
17806
18174
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
@@ -17843,61 +18211,13 @@ function XViewScene({
17843
18211
  console.error("Erro na chamada de save_view_data:", error);
17844
18212
  }
17845
18213
  }, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
17846
- const allAvailableNodes = (0, import_react32.useMemo)(() => {
17847
- if (!parentDataRef.current) return [];
17848
- return Object.values(parentDataRef.current).flatMap(
17849
- (fileData) => fileData.nodes || []
17850
- );
17851
- }, [sceneVersion, isInitialized]);
17852
- const allAvailableAncestries = (0, import_react32.useMemo)(() => {
17853
- return ancestryDataRef.current || [];
17854
- }, [sceneVersion, isInitialized]);
17855
- const handleOpenReference = (0, import_react32.useCallback)(
17856
- (referenceData) => {
17857
- const { type, id } = referenceData;
17858
- if (type === "node") {
17859
- const targetNode = allAvailableNodes.find(
17860
- (n) => String(n.id) === String(id)
17861
- );
17862
- if (targetNode) {
17863
- setAncestryLinkDetails(null);
17864
- setDetailsLink(null);
17865
- setDetailsNode(targetNode);
17866
- const sceneMesh = stateRef.current.nodeObjects[String(id)];
17867
- if (sceneMesh) {
17868
- tweenToTarget(sceneMesh);
17869
- }
17870
- } else {
17871
- alert("Node original n\xE3o encontrado neste contexto.");
17872
- }
17873
- } else if (type === "ancestry") {
17874
- const targetAncestry = allAvailableAncestries.find(
17875
- (a) => String(a.ancestry_id) === String(id)
17876
- );
17877
- if (targetAncestry) {
17878
- setDetailsNode(null);
17879
- setDetailsLink(null);
17880
- setAncestryLinkDetails(null);
17881
- handleEditAncestry(targetAncestry);
17882
- } else {
17883
- alert("Ancestralidade original n\xE3o encontrada neste contexto.");
17884
- }
17885
- }
17886
- },
17887
- [
17888
- allAvailableNodes,
17889
- allAvailableAncestries,
17890
- handleEditAncestry,
17891
- tweenToTarget
17892
- ]
17893
- );
17894
- const handleToggleAncestryAddMode = (0, import_react32.useCallback)(() => {
18214
+ const handleToggleAncestryAddMode = (0, import_react31.useCallback)(() => {
17895
18215
  setAncestryMode((prev) => ({
17896
18216
  ...prev,
17897
18217
  isAddingNodes: !prev.isAddingNodes
17898
18218
  }));
17899
18219
  }, []);
17900
- const handleFocusNode = (0, import_react32.useCallback)(
18220
+ const handleFocusNode = (0, import_react31.useCallback)(
17901
18221
  (nodeData) => {
17902
18222
  var _a2;
17903
18223
  if (!nodeData) return;
@@ -17913,7 +18233,7 @@ function XViewScene({
17913
18233
  },
17914
18234
  [tweenToTarget]
17915
18235
  );
17916
- const availableDatasets = (0, import_react32.useMemo)(() => {
18236
+ const availableDatasets = (0, import_react31.useMemo)(() => {
17917
18237
  if (!sceneDataRef.current || !parentDataRef.current) return [];
17918
18238
  return sceneDataRef.current.parent_dbs.map((db) => {
17919
18239
  var _a2;
@@ -17923,11 +18243,11 @@ function XViewScene({
17923
18243
  };
17924
18244
  });
17925
18245
  }, [sceneVersion, isInitialized]);
17926
- const sourceNodeDatasetId = creationMode.sourceNodeData ? (_c = stateRef.current.nodeIdToParentFileMap.get(
18246
+ const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(
17927
18247
  String(creationMode.sourceNodeData.id)
17928
- )) == null ? void 0 : _c.parentFileId : null;
18248
+ )) == null ? void 0 : _b.parentFileId : null;
17929
18249
  const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
17930
- (0, import_react32.useEffect)(() => {
18250
+ (0, import_react31.useEffect)(() => {
17931
18251
  if (isInitialized && focusNodeId && !hasFocusedInitial) {
17932
18252
  const nodeObjects = stateRef.current.nodeObjects || {};
17933
18253
  const targetMesh = nodeObjects[String(focusNodeId)];
@@ -17950,7 +18270,7 @@ function XViewScene({
17950
18270
  hasFocusedInitial,
17951
18271
  tweenToTarget
17952
18272
  ]);
17953
- (0, import_react32.useEffect)(() => {
18273
+ (0, import_react31.useEffect)(() => {
17954
18274
  if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
17955
18275
  const ancestries = ancestryDataRef.current || [];
17956
18276
  const targetAncestry = ancestries.find(
@@ -17975,7 +18295,7 @@ function XViewScene({
17975
18295
  hasOpenedInitialAncestry,
17976
18296
  handleStartReadingAncestry
17977
18297
  ]);
17978
- (0, import_react32.useEffect)(() => {
18298
+ (0, import_react31.useEffect)(() => {
17979
18299
  function handleKeyDown(event) {
17980
18300
  var _a2, _b2, _c2;
17981
18301
  const context = actionHandlerContext;
@@ -18098,10 +18418,10 @@ function XViewScene({
18098
18418
  // <-- handleCancelQuest adicionado aqui
18099
18419
  ]);
18100
18420
  if (isLoading || status === "loading" || permissionStatus === "loading") {
18101
- return /* @__PURE__ */ import_react32.default.createElement(LoadingScreen, null);
18421
+ return /* @__PURE__ */ import_react31.default.createElement(LoadingScreen, null);
18102
18422
  }
18103
18423
  if (permissionStatus === "denied") {
18104
- return /* @__PURE__ */ import_react32.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react32.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react32.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react32.default.createElement(
18424
+ return /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react31.default.createElement(
18105
18425
  "svg",
18106
18426
  {
18107
18427
  xmlns: "http://www.w3.org/2000/svg",
@@ -18111,7 +18431,7 @@ function XViewScene({
18111
18431
  stroke: "currentColor",
18112
18432
  className: "w-16 h-16 mx-auto"
18113
18433
  },
18114
- /* @__PURE__ */ import_react32.default.createElement(
18434
+ /* @__PURE__ */ import_react31.default.createElement(
18115
18435
  "path",
18116
18436
  {
18117
18437
  strokeLinecap: "round",
@@ -18119,13 +18439,13 @@ function XViewScene({
18119
18439
  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"
18120
18440
  }
18121
18441
  )
18122
- )), /* @__PURE__ */ import_react32.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ import_react32.default.createElement("p", { className: "text-slate-400 mb-6" }, "Voc\xEA n\xE3o tem permiss\xE3o para acessar este conte\xFAdo. Solicite acesso ao propriet\xE1rio ou verifique se est\xE1 na conta correta."), /* @__PURE__ */ import_react32.default.createElement(
18442
+ )), /* @__PURE__ */ import_react31.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-slate-400 mb-6" }, "Voc\xEA n\xE3o tem permiss\xE3o para acessar este conte\xFAdo. Solicite acesso ao propriet\xE1rio ou verifique se est\xE1 na conta correta."), /* @__PURE__ */ import_react31.default.createElement(
18123
18443
  "button",
18124
18444
  {
18125
18445
  onClick: () => router.push("/dashboard/scenes"),
18126
18446
  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"
18127
18447
  },
18128
- /* @__PURE__ */ import_react32.default.createElement(
18448
+ /* @__PURE__ */ import_react31.default.createElement(
18129
18449
  "svg",
18130
18450
  {
18131
18451
  xmlns: "http://www.w3.org/2000/svg",
@@ -18135,7 +18455,7 @@ function XViewScene({
18135
18455
  stroke: "currentColor",
18136
18456
  className: "w-5 h-5"
18137
18457
  },
18138
- /* @__PURE__ */ import_react32.default.createElement(
18458
+ /* @__PURE__ */ import_react31.default.createElement(
18139
18459
  "path",
18140
18460
  {
18141
18461
  strokeLinecap: "round",
@@ -18147,7 +18467,7 @@ function XViewScene({
18147
18467
  "Voltar para Scenes"
18148
18468
  )));
18149
18469
  }
18150
- return /* @__PURE__ */ import_react32.default.createElement(
18470
+ return /* @__PURE__ */ import_react31.default.createElement(
18151
18471
  "div",
18152
18472
  {
18153
18473
  ref: mountRef,
@@ -18159,7 +18479,7 @@ function XViewScene({
18159
18479
  cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
18160
18480
  }
18161
18481
  },
18162
- userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react32.default.createElement(
18482
+ userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react31.default.createElement(
18163
18483
  XViewSidebar,
18164
18484
  {
18165
18485
  dbNodes: searchableDbNodes,
@@ -18179,11 +18499,11 @@ function XViewScene({
18179
18499
  onToggle: setIsSidebarOpen,
18180
18500
  userRole: userPermissionRole,
18181
18501
  viewMembers,
18182
- milestones: ((_d = sceneDataRef.current) == null ? void 0 : _d.milestones) || [],
18502
+ milestones: ((_c = sceneDataRef.current) == null ? void 0 : _c.milestones) || [],
18183
18503
  onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
18184
18504
  }
18185
18505
  ),
18186
- creationMode.isActive && /* @__PURE__ */ import_react32.default.createElement(
18506
+ creationMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
18187
18507
  InSceneCreationForm,
18188
18508
  {
18189
18509
  onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
@@ -18204,8 +18524,8 @@ function XViewScene({
18204
18524
  },
18205
18525
  refEl: formRef,
18206
18526
  existingTypes: existingNodeTypes,
18207
- initialColor: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.color,
18208
- sourceTypes: (_f = creationMode.sourceNodeData) == null ? void 0 : _f.type,
18527
+ initialColor: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.color,
18528
+ sourceTypes: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.type,
18209
18529
  onIntensityChange: handleGhostNodeIntensityChange,
18210
18530
  onUploadFile: upload_file_action,
18211
18531
  availableDatasets,
@@ -18215,7 +18535,7 @@ function XViewScene({
18215
18535
  availableAncestries: allAvailableAncestries
18216
18536
  }
18217
18537
  ),
18218
- versionMode.isActive && /* @__PURE__ */ import_react32.default.createElement(
18538
+ versionMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
18219
18539
  InSceneVersionForm,
18220
18540
  {
18221
18541
  onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
@@ -18234,14 +18554,14 @@ function XViewScene({
18234
18554
  transition: "opacity 200ms ease-out"
18235
18555
  },
18236
18556
  refEl: formRef,
18237
- fixedType: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.type,
18238
- fixedColor: (_h = versionMode.sourceNodeData) == null ? void 0 : _h.color,
18557
+ fixedType: (_f = versionMode.sourceNodeData) == null ? void 0 : _f.type,
18558
+ fixedColor: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.color,
18239
18559
  onUploadFile: upload_file_action,
18240
18560
  availableNodes: allAvailableNodes,
18241
18561
  availableAncestries: allAvailableAncestries
18242
18562
  }
18243
18563
  ),
18244
- questMode.isActive && /* @__PURE__ */ import_react32.default.createElement(
18564
+ questMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
18245
18565
  InSceneQuestForm,
18246
18566
  {
18247
18567
  onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
@@ -18263,13 +18583,13 @@ function XViewScene({
18263
18583
  availableNodes: allAvailableNodes,
18264
18584
  availableAncestries: allAvailableAncestries,
18265
18585
  viewName: viewParams == null ? void 0 : viewParams.name,
18266
- questCounter: ((_i = sceneDataRef.current) == null ? void 0 : _i.quest_counter) || 1,
18586
+ questCounter: ((_h = sceneDataRef.current) == null ? void 0 : _h.quest_counter) || 1,
18267
18587
  viewMembers,
18268
- milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18588
+ milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
18269
18589
  onUpdateMilestones: handleUpdateMilestones
18270
18590
  }
18271
18591
  ),
18272
- readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react32.default.createElement(
18592
+ readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react31.default.createElement(
18273
18593
  "div",
18274
18594
  {
18275
18595
  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"}`,
@@ -18282,7 +18602,7 @@ function XViewScene({
18282
18602
  maxWidth: "92vw"
18283
18603
  }
18284
18604
  },
18285
- /* @__PURE__ */ import_react32.default.createElement(
18605
+ /* @__PURE__ */ import_react31.default.createElement(
18286
18606
  "div",
18287
18607
  {
18288
18608
  onPointerDown: (e) => {
@@ -18293,7 +18613,7 @@ function XViewScene({
18293
18613
  title: "Arraste para redimensionar"
18294
18614
  }
18295
18615
  ),
18296
- /* @__PURE__ */ import_react32.default.createElement(
18616
+ /* @__PURE__ */ import_react31.default.createElement(
18297
18617
  DescriptionReadModePanel,
18298
18618
  {
18299
18619
  key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
@@ -18328,7 +18648,7 @@ function XViewScene({
18328
18648
  }
18329
18649
  )
18330
18650
  ),
18331
- ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react32.default.createElement(
18651
+ ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react31.default.createElement(
18332
18652
  CreateAncestryPanel,
18333
18653
  {
18334
18654
  ancestryMode,
@@ -18364,7 +18684,7 @@ function XViewScene({
18364
18684
  onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
18365
18685
  }
18366
18686
  ),
18367
- editingAncestryRel.visible && /* @__PURE__ */ import_react32.default.createElement(
18687
+ editingAncestryRel.visible && /* @__PURE__ */ import_react31.default.createElement(
18368
18688
  AncestryRelationshipPanel,
18369
18689
  {
18370
18690
  data: editingAncestryRel.data,
@@ -18378,7 +18698,7 @@ function XViewScene({
18378
18698
  onUploadFile: upload_file_action
18379
18699
  }
18380
18700
  ),
18381
- detailsNode && detailsNode.is_quest && /* @__PURE__ */ import_react32.default.createElement(
18701
+ detailsNode && detailsNode.is_quest && /* @__PURE__ */ import_react31.default.createElement(
18382
18702
  QuestDetailsPanel,
18383
18703
  {
18384
18704
  node: detailsNode,
@@ -18400,11 +18720,11 @@ function XViewScene({
18400
18720
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
18401
18721
  viewMembers,
18402
18722
  currentUser: session == null ? void 0 : session.user,
18403
- milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18723
+ milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
18404
18724
  onUpdateMilestones: handleUpdateMilestones
18405
18725
  }
18406
18726
  ),
18407
- detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react32.default.createElement(
18727
+ detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react31.default.createElement(
18408
18728
  NodeDetailsPanel,
18409
18729
  {
18410
18730
  node: detailsNode,
@@ -18436,7 +18756,7 @@ function XViewScene({
18436
18756
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
18437
18757
  }
18438
18758
  ),
18439
- detailsLink && /* @__PURE__ */ import_react32.default.createElement(
18759
+ detailsLink && /* @__PURE__ */ import_react31.default.createElement(
18440
18760
  RelationshipDetailsPanel,
18441
18761
  {
18442
18762
  link: detailsLink,
@@ -18450,7 +18770,7 @@ function XViewScene({
18450
18770
  userRole: userPermissionRole
18451
18771
  }
18452
18772
  ),
18453
- ancestryLinkDetails && /* @__PURE__ */ import_react32.default.createElement(
18773
+ ancestryLinkDetails && /* @__PURE__ */ import_react31.default.createElement(
18454
18774
  AncestryLinkDetailsPanel,
18455
18775
  {
18456
18776
  data: ancestryLinkDetails,
@@ -18461,7 +18781,7 @@ function XViewScene({
18461
18781
  onUploadFile: upload_file_action
18462
18782
  }
18463
18783
  ),
18464
- /* @__PURE__ */ import_react32.default.createElement(
18784
+ /* @__PURE__ */ import_react31.default.createElement(
18465
18785
  "div",
18466
18786
  {
18467
18787
  ref: tooltipRef,
@@ -18488,7 +18808,7 @@ function XViewScene({
18488
18808
  }
18489
18809
  }
18490
18810
  ),
18491
- /* @__PURE__ */ import_react32.default.createElement(
18811
+ /* @__PURE__ */ import_react31.default.createElement(
18492
18812
  ContextMenu,
18493
18813
  {
18494
18814
  data: contextMenu,
@@ -18521,7 +18841,7 @@ function XViewScene({
18521
18841
  onFinishQuest: handleFinishQuestQuick
18522
18842
  }
18523
18843
  ),
18524
- /* @__PURE__ */ import_react32.default.createElement(
18844
+ /* @__PURE__ */ import_react31.default.createElement(
18525
18845
  MultiNodeContextMenu,
18526
18846
  {
18527
18847
  data: multiContextMenu,
@@ -18541,7 +18861,7 @@ function XViewScene({
18541
18861
  )
18542
18862
  }
18543
18863
  ),
18544
- /* @__PURE__ */ import_react32.default.createElement(
18864
+ /* @__PURE__ */ import_react31.default.createElement(
18545
18865
  RelationshipContextMenu,
18546
18866
  {
18547
18867
  data: relationshipMenu,
@@ -18559,14 +18879,14 @@ function XViewScene({
18559
18879
  onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
18560
18880
  }
18561
18881
  ),
18562
- /* @__PURE__ */ import_react32.default.createElement(
18882
+ /* @__PURE__ */ import_react31.default.createElement(
18563
18883
  ImageViewer,
18564
18884
  {
18565
18885
  data: imageViewer,
18566
18886
  onClose: () => setImageViewer({ ...imageViewer, visible: false })
18567
18887
  }
18568
18888
  ),
18569
- /* @__PURE__ */ import_react32.default.createElement(
18889
+ /* @__PURE__ */ import_react31.default.createElement(
18570
18890
  AncestryBoard,
18571
18891
  {
18572
18892
  isOpen: isAncestryBoardOpen,
@@ -18579,29 +18899,29 @@ function XViewScene({
18579
18899
  userRole: userPermissionRole
18580
18900
  }
18581
18901
  ),
18582
- /* @__PURE__ */ import_react32.default.createElement(
18902
+ /* @__PURE__ */ import_react31.default.createElement(
18583
18903
  MilestoneManager,
18584
18904
  {
18585
18905
  isOpen: isMilestoneManagerOpen,
18586
18906
  onClose: () => setIsMilestoneManagerOpen(false),
18587
- milestones: ((_l = sceneDataRef.current) == null ? void 0 : _l.milestones) || [],
18907
+ milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
18588
18908
  onUpdateMilestones: handleUpdateMilestones
18589
18909
  }
18590
18910
  ),
18591
- /* @__PURE__ */ import_react32.default.createElement(
18911
+ /* @__PURE__ */ import_react31.default.createElement(
18592
18912
  ImportParentFileModal,
18593
18913
  {
18594
18914
  isOpen: isImportModalOpen,
18595
18915
  onClose: () => setIsImportModalOpen(false),
18596
18916
  onConfirm: handleConfirmImport,
18597
18917
  session,
18598
- parentDbs: ((_m = sceneDataRef.current) == null ? void 0 : _m.parent_dbs) || [],
18918
+ parentDbs: ((_l = sceneDataRef.current) == null ? void 0 : _l.parent_dbs) || [],
18599
18919
  onFetchAvailableFiles: import_parent_file_modal_get,
18600
18920
  currentViewName: viewParams == null ? void 0 : viewParams.name,
18601
18921
  currentAncestries: ancestryDataRef.current || []
18602
18922
  }
18603
18923
  ),
18604
- invalidTargetError && /* @__PURE__ */ import_react32.default.createElement(
18924
+ invalidTargetError && /* @__PURE__ */ import_react31.default.createElement(
18605
18925
  "div",
18606
18926
  {
18607
18927
  className: "ui-overlay",
@@ -18626,13 +18946,13 @@ function XViewScene({
18626
18946
  animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
18627
18947
  }
18628
18948
  },
18629
- /* @__PURE__ */ import_react32.default.createElement("style", null, `
18949
+ /* @__PURE__ */ import_react31.default.createElement("style", null, `
18630
18950
  @keyframes fadeInDown {
18631
18951
  from { opacity: 0; transform: translate(-50%, -20px); }
18632
18952
  to { opacity: 1; transform: translate(-50%, 0); }
18633
18953
  }
18634
18954
  `),
18635
- /* @__PURE__ */ import_react32.default.createElement(
18955
+ /* @__PURE__ */ import_react31.default.createElement(
18636
18956
  "svg",
18637
18957
  {
18638
18958
  width: "20",
@@ -18644,12 +18964,12 @@ function XViewScene({
18644
18964
  strokeLinecap: "round",
18645
18965
  strokeLinejoin: "round"
18646
18966
  },
18647
- /* @__PURE__ */ import_react32.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18648
- /* @__PURE__ */ import_react32.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18649
- /* @__PURE__ */ import_react32.default.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18967
+ /* @__PURE__ */ import_react31.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
18968
+ /* @__PURE__ */ import_react31.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
18969
+ /* @__PURE__ */ import_react31.default.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
18650
18970
  ),
18651
- /* @__PURE__ */ import_react32.default.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18652
- /* @__PURE__ */ import_react32.default.createElement(
18971
+ /* @__PURE__ */ import_react31.default.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
18972
+ /* @__PURE__ */ import_react31.default.createElement(
18653
18973
  "button",
18654
18974
  {
18655
18975
  onClick: () => setInvalidTargetError(null),