@lv-x-software-house/x_view 1.2.5-dev.1 → 1.2.5-dev.11
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 +321 -57
- package/dist/index.mjs +321 -57
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -111,6 +111,7 @@ function ContextMenu({
|
|
|
111
111
|
const [menuView, setMenuView] = useState("main");
|
|
112
112
|
const [selectedAncestry, setSelectedAncestry] = useState(null);
|
|
113
113
|
const [versionSubMenu, setVersionSubMenu] = useState(null);
|
|
114
|
+
const [labelSubMenu, setLabelSubMenu] = useState(null);
|
|
114
115
|
const [isLinkCopied, setIsLinkCopied] = useState(false);
|
|
115
116
|
const [selectedQuestStatus, setSelectedQuestStatus] = useState(null);
|
|
116
117
|
const ability = useMemo(() => defineAbilityFor(userRole), [userRole]);
|
|
@@ -119,6 +120,7 @@ function ContextMenu({
|
|
|
119
120
|
setMenuView("main");
|
|
120
121
|
setSelectedAncestry(null);
|
|
121
122
|
setVersionSubMenu(null);
|
|
123
|
+
setLabelSubMenu(null);
|
|
122
124
|
setSelectedQuestStatus(null);
|
|
123
125
|
}
|
|
124
126
|
}, [data.visible, (_a = data.nodeData) == null ? void 0 : _a.id]);
|
|
@@ -134,7 +136,7 @@ function ContextMenu({
|
|
|
134
136
|
if (left + w + 8 > vw) left = Math.max(8, vw - w - 8);
|
|
135
137
|
if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
|
|
136
138
|
setMenuPos({ left, top });
|
|
137
|
-
}, [data, menuView, versionSubMenu, selectedQuestStatus]);
|
|
139
|
+
}, [data, menuView, versionSubMenu, labelSubMenu, selectedQuestStatus]);
|
|
138
140
|
useEffect(() => {
|
|
139
141
|
if (!data.visible) return;
|
|
140
142
|
const handleClickOutside = (e) => {
|
|
@@ -186,7 +188,21 @@ function ContextMenu({
|
|
|
186
188
|
var _a2;
|
|
187
189
|
return (_a2 = c.targetNode) == null ? void 0 : _a2.is_quest;
|
|
188
190
|
});
|
|
189
|
-
const
|
|
191
|
+
const getLabelForConnection = (conn) => {
|
|
192
|
+
if (conn.direction === "outgoing") return conn.link.source_label || null;
|
|
193
|
+
if (conn.direction === "incoming") return conn.link.target_label || null;
|
|
194
|
+
return null;
|
|
195
|
+
};
|
|
196
|
+
const commonWithLabel = commonConnections.filter((c) => getLabelForConnection(c));
|
|
197
|
+
const commonWithoutLabel = commonConnections.filter((c) => !getLabelForConnection(c));
|
|
198
|
+
const labelGroups = commonWithLabel.reduce((acc, conn) => {
|
|
199
|
+
const label = getLabelForConnection(conn);
|
|
200
|
+
if (!acc[label]) acc[label] = [];
|
|
201
|
+
acc[label].push(conn);
|
|
202
|
+
return acc;
|
|
203
|
+
}, {});
|
|
204
|
+
const labelGroupEntries = Object.entries(labelGroups).sort(([a], [b]) => a.localeCompare(b));
|
|
205
|
+
const groupedConnections = commonWithoutLabel.reduce((acc, conn) => {
|
|
190
206
|
var _a2;
|
|
191
207
|
const { targetNode } = conn;
|
|
192
208
|
const groupingKey = ((_a2 = targetNode.version_node) == null ? void 0 : _a2.is_version) ? targetNode.version_node.parent_node : targetNode.id;
|
|
@@ -314,11 +330,32 @@ function ContextMenu({
|
|
|
314
330
|
/* @__PURE__ */ React.createElement("span", { className: "flex-1 truncate" }, conn.targetNode.name)
|
|
315
331
|
))));
|
|
316
332
|
};
|
|
333
|
+
const renderLabelSubMenuView = () => {
|
|
334
|
+
const group = labelSubMenu;
|
|
335
|
+
const isScrollable = group.connections.length > 10;
|
|
336
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ React.createElement("button", { onClick: () => {
|
|
337
|
+
setLabelSubMenu(null);
|
|
338
|
+
setMenuView("connections");
|
|
339
|
+
}, className: "p-1 rounded-full hover:bg-white/10 text-slate-400 hover:text-white flex-shrink-0" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("polyline", { points: "15 18 9 12 15 6" }))), /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-1.5 min-w-0" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-violet-400 flex-shrink-0" }, /* @__PURE__ */ React.createElement("path", { d: "M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z" }), /* @__PURE__ */ React.createElement("line", { x1: "7", y1: "7", x2: "7.01", y2: "7" })), /* @__PURE__ */ React.createElement("p", { className: "text-[11px] uppercase tracking-wider text-violet-300/80 truncate", title: group.label }, group.label))), group.connections.length > 0 && /* @__PURE__ */ React.createElement("button", { onClick: () => handleExpandAndClose(group.connections.map((c) => c.link)), className: "px-2 py-0.5 text-xs bg-indigo-500/50 hover:bg-indigo-500/80 rounded-md transition-colors" }, "Expandir Todas")), /* @__PURE__ */ React.createElement("div", { className: `flex flex-col gap-1 ${isScrollable ? "max-h-[40vh] overflow-y-auto custom-scrollbar" : ""}` }, group.connections.map((conn) => /* @__PURE__ */ React.createElement(
|
|
340
|
+
"button",
|
|
341
|
+
{
|
|
342
|
+
key: conn.targetNode.id,
|
|
343
|
+
onClick: () => handleExpandAndClose([conn.link]),
|
|
344
|
+
className: baseButtonClass,
|
|
345
|
+
title: `Expandir conex\xE3o com ${conn.targetNode.name}`
|
|
346
|
+
},
|
|
347
|
+
/* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" }), /* @__PURE__ */ React.createElement("polyline", { points: "12 5 19 12 12 19" })),
|
|
348
|
+
/* @__PURE__ */ React.createElement("span", { className: "flex-1 truncate" }, conn.targetNode.name)
|
|
349
|
+
))));
|
|
350
|
+
};
|
|
317
351
|
const renderConnectionsView = () => {
|
|
318
352
|
if (versionSubMenu) {
|
|
319
353
|
return renderVersionSubMenuView();
|
|
320
354
|
}
|
|
321
|
-
|
|
355
|
+
if (labelSubMenu) {
|
|
356
|
+
return renderLabelSubMenuView();
|
|
357
|
+
}
|
|
358
|
+
const totalItems = availableAncestries.length + labelGroupEntries.length + finalRenderableConnections.length + (questConnections.length > 0 ? 1 : 0);
|
|
322
359
|
const isScrollable = totalItems > 10;
|
|
323
360
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("main"), className: "p-1 rounded-full hover:bg-white/10 text-slate-400 hover:text-white" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("polyline", { points: "15 18 9 12 15 6" }))), /* @__PURE__ */ React.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Conex\xF5es")), commonConnections.length > 0 && /* @__PURE__ */ React.createElement("button", { onClick: () => handleExpandAndClose(commonConnections.map((c) => c.link)), className: "px-2 py-0.5 text-xs bg-indigo-500/50 hover:bg-indigo-500/80 rounded-md transition-colors" }, "Expandir Todas")), /* @__PURE__ */ React.createElement("div", { className: `flex flex-col ${isScrollable ? "max-h-[40vh] overflow-y-auto custom-scrollbar" : ""}` }, availableAncestries.length > 0 && /* @__PURE__ */ React.createElement("div", { className: `flex flex-col gap-1 ${finalRenderableConnections.length > 0 || questConnections.length > 0 ? "mb-2" : ""}` }, /* @__PURE__ */ React.createElement("div", { className: "px-2 py-1 text-[11px] uppercase tracking-wider text-indigo-400/90" }, "Ancestralidades Salvas"), availableAncestries.map((anc) => /* @__PURE__ */ React.createElement(
|
|
324
361
|
"button",
|
|
@@ -330,7 +367,20 @@ function ContextMenu({
|
|
|
330
367
|
},
|
|
331
368
|
/* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M6 3v4a2 2 0 0 0 2 2h4" }), /* @__PURE__ */ React.createElement("path", { d: "M18 3v4a2 2 0 0 1-2 2h-4" }), /* @__PURE__ */ React.createElement("circle", { cx: "6", cy: "3", r: "2" }), /* @__PURE__ */ React.createElement("circle", { cx: "18", cy: "3", r: "2" }), /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "11", r: "2" }), /* @__PURE__ */ React.createElement("path", { d: "M12 13v6" }), /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "21", r: "2" })),
|
|
332
369
|
/* @__PURE__ */ React.createElement("span", { className: "flex-1 truncate" }, anc.name || `Ancestralidade #${anc.ancestry_id.substring(0, 8)}`)
|
|
333
|
-
))),
|
|
370
|
+
))), labelGroupEntries.length > 0 && /* @__PURE__ */ React.createElement("div", { className: `flex flex-col gap-1 ${availableAncestries.length > 0 ? "mt-2" : ""} ${finalRenderableConnections.length > 0 || questConnections.length > 0 ? "mb-2" : ""}` }, availableAncestries.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), labelGroupEntries.map(([label, conns]) => /* @__PURE__ */ React.createElement(
|
|
371
|
+
"button",
|
|
372
|
+
{
|
|
373
|
+
key: label,
|
|
374
|
+
onClick: () => {
|
|
375
|
+
setLabelSubMenu({ label, connections: conns });
|
|
376
|
+
},
|
|
377
|
+
className: baseButtonClass,
|
|
378
|
+
title: `Ver grupo: ${label}`
|
|
379
|
+
},
|
|
380
|
+
/* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-violet-400" }, /* @__PURE__ */ React.createElement("path", { d: "M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z" }), /* @__PURE__ */ React.createElement("line", { x1: "7", y1: "7", x2: "7.01", y2: "7" })),
|
|
381
|
+
/* @__PURE__ */ React.createElement("span", { className: "flex-1 truncate" }, label),
|
|
382
|
+
/* @__PURE__ */ React.createElement("span", { className: "text-xs px-2 py-0.5 bg-violet-500/20 text-violet-300 rounded-full" }, conns.length)
|
|
383
|
+
))), finalRenderableConnections.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1" }, (availableAncestries.length > 0 || labelGroupEntries.length > 0) && /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), finalRenderableConnections.map((group) => {
|
|
334
384
|
if (group.isVersionGroup) {
|
|
335
385
|
return /* @__PURE__ */ React.createElement(
|
|
336
386
|
"button",
|
|
@@ -408,11 +458,18 @@ function ContextMenu({
|
|
|
408
458
|
))));
|
|
409
459
|
};
|
|
410
460
|
const renderAncestryActionsView = () => {
|
|
461
|
+
var _a2, _b2;
|
|
411
462
|
const ancestryTitle = (selectedAncestry == null ? void 0 : selectedAncestry.name) || `Ancestralidade #${selectedAncestry == null ? void 0 : selectedAncestry.ancestry_id.substring(0, 8)}`;
|
|
412
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("connections"), className: "p-1 rounded-full hover:bg-white/10 text-slate-400 hover:text-white flex-shrink-0" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("polyline", { points: "15 18 9 12 15 6" }))), /* @__PURE__ */ React.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400 truncate", title: ancestryTitle }, ancestryTitle))), /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1" }, ability.can("read", "Ancestry") && /* @__PURE__ */ React.createElement("button", { onClick: () => {
|
|
413
|
-
onRenderAncestry == null ? void 0 : onRenderAncestry(selectedAncestry);
|
|
463
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("connections"), className: "p-1 rounded-full hover:bg-white/10 text-slate-400 hover:text-white flex-shrink-0" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("polyline", { points: "15 18 9 12 15 6" }))), /* @__PURE__ */ React.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400 truncate", title: ancestryTitle }, ancestryTitle))), /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1" }, ability.can("read", "Ancestry") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("button", { onClick: () => {
|
|
464
|
+
onRenderAncestry == null ? void 0 : onRenderAncestry(selectedAncestry, "full");
|
|
465
|
+
onClose();
|
|
466
|
+
}, className: baseButtonClass, title: "Renderizar Ancestralidade Completa" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z" }), /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "3" })), /* @__PURE__ */ React.createElement("span", null, "Renderizar Ancestralidade")), /* @__PURE__ */ React.createElement("button", { onClick: () => {
|
|
467
|
+
onRenderAncestry == null ? void 0 : onRenderAncestry(selectedAncestry, "ancestry_only");
|
|
468
|
+
onClose();
|
|
469
|
+
}, className: baseButtonClass, title: "Renderizar apenas a \xC1rvore de Ancestralidade (Radial)" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ React.createElement("path", { d: "M12 2v3m0 14v3m10-10h-3m-14 0H2m15.66-6.34-2.12 2.12m-9.08 9.08-2.12 2.12m13.32 0-2.12-2.12m-9.08-9.08-2.12-2.12" })), /* @__PURE__ */ React.createElement("span", null, "\xC1rvore de Ancestralidade")), ((_b2 = (_a2 = selectedAncestry == null ? void 0 : selectedAncestry.abstraction_tree) == null ? void 0 : _a2.children) == null ? void 0 : _b2.length) > 0 && /* @__PURE__ */ React.createElement("button", { onClick: () => {
|
|
470
|
+
onRenderAncestry == null ? void 0 : onRenderAncestry(selectedAncestry, "abstraction_only");
|
|
414
471
|
onClose();
|
|
415
|
-
}, className: baseButtonClass, title: "Renderizar
|
|
472
|
+
}, className: baseButtonClass, title: "Renderizar apenas a \xC1rvore de Abstra\xE7\xE3o (Vertical)" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ React.createElement("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ React.createElement("rect", { x: "14", y: "14", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ React.createElement("rect", { x: "3", y: "14", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ React.createElement("path", { d: "M10 6.5h4" }), /* @__PURE__ */ React.createElement("path", { d: "M10 17.5h4" }), /* @__PURE__ */ React.createElement("path", { d: "M6.5 10v4" }), /* @__PURE__ */ React.createElement("path", { d: "M17.5 10v4" })), /* @__PURE__ */ React.createElement("span", null, "\xC1rvore de Abstra\xE7\xE3o"))), ability.can("update", "Ancestry") && /* @__PURE__ */ React.createElement("button", { onClick: () => {
|
|
416
473
|
onEditAncestry == null ? void 0 : onEditAncestry(selectedAncestry);
|
|
417
474
|
onClose();
|
|
418
475
|
}, className: baseButtonClass, title: "Editar Ancestralidade" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M12 20h9" }), /* @__PURE__ */ React.createElement("path", { d: "M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z" })), /* @__PURE__ */ React.createElement("span", null, "Editar Ancestralidade")), (ability.can("update", "Ancestry") || ability.can("delete", "Ancestry")) && /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), ability.can("delete", "Ancestry") && /* @__PURE__ */ React.createElement("button", { onClick: () => {
|
|
@@ -659,7 +716,7 @@ function XViewSidebar({
|
|
|
659
716
|
"div",
|
|
660
717
|
{
|
|
661
718
|
ref: containerRef,
|
|
662
|
-
className: "ui-overlay fixed left-0 top-0 h-
|
|
719
|
+
className: "ui-overlay fixed left-0 top-0 h-[100dvh] w-[min(92vw,320px)] z-40 overflow-hidden",
|
|
663
720
|
onPointerDown: swallow,
|
|
664
721
|
onPointerMove: swallow,
|
|
665
722
|
onPointerUp: swallow,
|
|
@@ -668,7 +725,7 @@ function XViewSidebar({
|
|
|
668
725
|
onContextMenu: swallow,
|
|
669
726
|
onDoubleClick: swallow
|
|
670
727
|
},
|
|
671
|
-
/* @__PURE__ */ React2.createElement("div", { className: "h-full flex flex-col bg-slate-950/80 backdrop-blur-xl border-r border-white/10 shadow-[0_0_40px_rgba(0,0,0,0.45)]" }, /* @__PURE__ */ React2.createElement("div", { className: "relative px-4 py-3 border-b border-white/10 flex items-center gap-2" }, /* @__PURE__ */ React2.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_10px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ React2.createElement("h3", { className: "text-sm font-medium text-slate-100" }, "Ferramentas"), /* @__PURE__ */ React2.createElement(
|
|
728
|
+
/* @__PURE__ */ React2.createElement("div", { className: "h-full flex flex-col overflow-hidden bg-slate-950/80 backdrop-blur-xl border-r border-white/10 shadow-[0_0_40px_rgba(0,0,0,0.45)]" }, /* @__PURE__ */ React2.createElement("div", { className: "relative px-4 py-3 border-b border-white/10 flex items-center gap-2" }, /* @__PURE__ */ React2.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_10px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ React2.createElement("h3", { className: "text-sm font-medium text-slate-100" }, "Ferramentas"), /* @__PURE__ */ React2.createElement(
|
|
672
729
|
"button",
|
|
673
730
|
{
|
|
674
731
|
className: "ml-auto p-2 rounded-md text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
|
|
@@ -725,7 +782,7 @@ function XViewSidebar({
|
|
|
725
782
|
autoComplete: "off"
|
|
726
783
|
}
|
|
727
784
|
)
|
|
728
|
-
), showList && /* @__PURE__ */ React2.createElement("ul", { className: "custom-scrollbar absolute mt-1 z-10 w-full max-h-[
|
|
785
|
+
), showList && /* @__PURE__ */ React2.createElement("ul", { className: "custom-scrollbar absolute mt-1 z-10 w-full max-h-[min(448px,50dvh)] overflow-y-auto rounded-lg bg-slate-900/95 border border-white/10 shadow-xl" }, filteredAndSorted.length > 0 ? filteredAndSorted.map((n) => {
|
|
729
786
|
const inView = isNodeInView(n.id);
|
|
730
787
|
const active = selectedNodeId === n.id;
|
|
731
788
|
const typeLabel = Array.isArray(n.type) ? n.type.join(", ") : n.type;
|
|
@@ -3101,6 +3158,7 @@ function calculateNodePositions(nodes) {
|
|
|
3101
3158
|
return positions;
|
|
3102
3159
|
}
|
|
3103
3160
|
function updateTooltip({ tooltipEl, hoveredNode, hoveredLink, camera, mountEl, isSceneBusy, parentData, ancestryData }) {
|
|
3161
|
+
var _a, _b;
|
|
3104
3162
|
if (!tooltipEl || !camera || !mountEl) return;
|
|
3105
3163
|
let content = "";
|
|
3106
3164
|
let positionTarget = null;
|
|
@@ -3113,17 +3171,21 @@ function updateTooltip({ tooltipEl, hoveredNode, hoveredLink, camera, mountEl, i
|
|
|
3113
3171
|
content = generateTooltipHtml(hoveredNode.userData, parentData, ancestryData);
|
|
3114
3172
|
}
|
|
3115
3173
|
} else if (hoveredLink && !isSceneBusy) {
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3174
|
+
const linkData = hoveredLink.userData.isAncestryLink ? hoveredLink.userData.relationship || {} : hoveredLink.userData;
|
|
3175
|
+
const hasContent = ((_a = linkData.name) == null ? void 0 : _a.trim()) || ((_b = linkData.description) == null ? void 0 : _b.trim());
|
|
3176
|
+
if (hasContent) {
|
|
3177
|
+
currentId = `link_${hoveredLink.userData.id}`;
|
|
3178
|
+
if (hoveredLink.userData.isCurved) {
|
|
3179
|
+
const positions = hoveredLink.geometry.attributes.position.array;
|
|
3180
|
+
const midIndex = Math.floor(positions.length / 2 / 3) * 3;
|
|
3181
|
+
positionTarget = new THREE2.Vector3(positions[midIndex], positions[midIndex + 1], positions[midIndex + 2]);
|
|
3182
|
+
} else {
|
|
3183
|
+
positionTarget = new THREE2.Vector3().addVectors(hoveredLink.userData.sourceNode.position, hoveredLink.userData.targetNode.position).multiplyScalar(0.5);
|
|
3184
|
+
}
|
|
3185
|
+
isLink = true;
|
|
3186
|
+
if (tooltipEl.dataset.currentId !== currentId) {
|
|
3187
|
+
content = generateLinkTooltipHtml(linkData, parentData, ancestryData);
|
|
3188
|
+
}
|
|
3127
3189
|
}
|
|
3128
3190
|
}
|
|
3129
3191
|
if (positionTarget) {
|
|
@@ -3432,9 +3494,9 @@ function CustomPropertyDisplay({
|
|
|
3432
3494
|
};
|
|
3433
3495
|
const handleRemoveListItem = (j) => setTempProp((p) => ({ ...p, value: p.value.filter((_, k) => k !== j) }));
|
|
3434
3496
|
const handleListItemChange = (j, f, v) => setTempProp((p) => {
|
|
3435
|
-
const
|
|
3436
|
-
|
|
3437
|
-
return { ...p, value:
|
|
3497
|
+
const newValue2 = [...p.value];
|
|
3498
|
+
newValue2[j] = { ...newValue2[j], [f]: v };
|
|
3499
|
+
return { ...p, value: newValue2 };
|
|
3438
3500
|
});
|
|
3439
3501
|
const baseInput = "w-full bg-slate-800/70 p-2 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-400/60 transition-all duration-150";
|
|
3440
3502
|
const renderEditView = () => {
|
|
@@ -3488,14 +3550,14 @@ function CustomPropertyDisplay({
|
|
|
3488
3550
|
const inputClass = `${baseInput} ${noSpinnerClass}`;
|
|
3489
3551
|
const handleDateTypeChange = (newDateType) => {
|
|
3490
3552
|
var _a3, _b2, _c2;
|
|
3491
|
-
let
|
|
3553
|
+
let newValue2 = { type: newDateType };
|
|
3492
3554
|
if (newDateType === "Date Interval") {
|
|
3493
|
-
|
|
3494
|
-
|
|
3555
|
+
newValue2.start = ((_a3 = tempProp.value) == null ? void 0 : _a3.start) || "";
|
|
3556
|
+
newValue2.end = ((_b2 = tempProp.value) == null ? void 0 : _b2.end) || "";
|
|
3495
3557
|
} else {
|
|
3496
|
-
|
|
3558
|
+
newValue2.value = ((_c2 = tempProp.value) == null ? void 0 : _c2.type) === newDateType ? tempProp.value.value : "";
|
|
3497
3559
|
}
|
|
3498
|
-
handlePropChange("value",
|
|
3560
|
+
handlePropChange("value", newValue2);
|
|
3499
3561
|
};
|
|
3500
3562
|
const handleDateValueChange = (dateField, dateValue) => {
|
|
3501
3563
|
handlePropChange("value", { ...tempProp.value, [dateField]: dateValue });
|
|
@@ -4343,7 +4405,7 @@ ${space}${bullet} `);
|
|
|
4343
4405
|
}
|
|
4344
4406
|
),
|
|
4345
4407
|
/* @__PURE__ */ React5.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0 shrink-0" }),
|
|
4346
|
-
/* @__PURE__ */ React5.createElement("div", { className: "px-6 pt-5 pb-3 flex items-center justify-between gap-4 shrink-0" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React5.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80" }), /* @__PURE__ */ React5.createElement("p", { className: "text-sm font-medium text-slate-200" }, title || "Editar Descri\xE7\xE3o")), /* @__PURE__ */ React5.createElement("button", { onClick: handleClose, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")),
|
|
4408
|
+
/* @__PURE__ */ React5.createElement("div", { className: "px-6 pt-5 pb-3 flex items-center justify-between gap-4 shrink-0" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ React5.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shrink-0" }), /* @__PURE__ */ React5.createElement("p", { className: "text-sm font-medium text-slate-200 truncate" }, title || "Editar Descri\xE7\xE3o")), /* @__PURE__ */ React5.createElement("button", { onClick: handleClose, className: "w-9 h-9 flex-shrink-0 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")),
|
|
4347
4409
|
/* @__PURE__ */ React5.createElement("div", { className: "px-6 py-3 flex flex-col gap-3 border-b border-white/5 bg-white/5 shrink-0" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 flex-wrap" }, /* @__PURE__ */ React5.createElement(
|
|
4348
4410
|
"button",
|
|
4349
4411
|
{
|
|
@@ -5472,7 +5534,7 @@ function AncestryRelationshipPanel({
|
|
|
5472
5534
|
onImageClick: handleImageClickFromText,
|
|
5473
5535
|
onSaveDescription: handleSaveDescriptionInline
|
|
5474
5536
|
}
|
|
5475
|
-
) : /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement("div", { className: "h-[2px] bg-gradient-to-r from-cyan-400/0 via-cyan-400/70 to-cyan-400/0" }), /* @__PURE__ */ React8.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React8.createElement("div",
|
|
5537
|
+
) : /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement("div", { className: "h-[2px] bg-gradient-to-r from-cyan-400/0 via-cyan-400/70 to-cyan-400/0" }), /* @__PURE__ */ React8.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React8.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React8.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React8.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-cyan-400/80 shadow-[0_0_18px_2px_rgba(45,212,191,0.55)]" }), /* @__PURE__ */ React8.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Rela\xE7\xE3o de Ancestralidade")), /* @__PURE__ */ React8.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, "Editar Rela\xE7\xE3o")), /* @__PURE__ */ React8.createElement("button", { onClick: onClose, className: "w-9 h-9 flex-shrink-0 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")), /* @__PURE__ */ React8.createElement("div", { className: "px-6 pb-4 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ React8.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React8.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o da Rela\xE7\xE3o"), /* @__PURE__ */ React8.createElement("div", { className: "relative group min-h-[60px] bg-slate-800/40 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ React8.createElement(
|
|
5476
5538
|
DescriptionDisplay,
|
|
5477
5539
|
{
|
|
5478
5540
|
description,
|
|
@@ -5794,6 +5856,7 @@ function CreateAncestryPanel({
|
|
|
5794
5856
|
} = ancestryMode;
|
|
5795
5857
|
const [isSaving, setIsSaving] = useState11(false);
|
|
5796
5858
|
const [isLinkCopied, setIsLinkCopied] = useState11(false);
|
|
5859
|
+
const [hasUnsavedChanges, setHasUnsavedChanges] = useState11(false);
|
|
5797
5860
|
const [showDeleteBranchConfirm, setShowDeleteBranchConfirm] = useState11(false);
|
|
5798
5861
|
const handleCopyLink = (e) => {
|
|
5799
5862
|
e.stopPropagation();
|
|
@@ -5861,12 +5924,14 @@ function CreateAncestryPanel({
|
|
|
5861
5924
|
};
|
|
5862
5925
|
const handleSelectAncestryParent = (nodeId, isAbstraction = false) => {
|
|
5863
5926
|
setAncestryMode((prev) => isAbstraction ? { ...prev, selectedAbstractionParentId: nodeId } : { ...prev, selectedParentId: nodeId });
|
|
5927
|
+
setHasUnsavedChanges(true);
|
|
5864
5928
|
};
|
|
5865
5929
|
const handleToggleAddMode = (isAbstraction = false) => {
|
|
5866
5930
|
if (isAbstraction && !ancestryMode.isAddingAbstractionNodes) {
|
|
5867
5931
|
setTargetRenderNodeId(null);
|
|
5868
5932
|
}
|
|
5869
5933
|
setAncestryMode((prev) => isAbstraction ? { ...prev, isAddingAbstractionNodes: !prev.isAddingAbstractionNodes } : { ...prev, isAddingNodes: !prev.isAddingNodes });
|
|
5934
|
+
setHasUnsavedChanges(true);
|
|
5870
5935
|
};
|
|
5871
5936
|
const handleRemoveNode = useCallback2((pathToRemove, isAbstraction = false) => {
|
|
5872
5937
|
if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) return;
|
|
@@ -5884,6 +5949,7 @@ function CreateAncestryPanel({
|
|
|
5884
5949
|
const indexToRemove = pathToRemove[pathToRemove.length - 1];
|
|
5885
5950
|
if (currentParent.children && currentParent.children.length > indexToRemove) {
|
|
5886
5951
|
currentParent.children.splice(indexToRemove, 1);
|
|
5952
|
+
setHasUnsavedChanges(true);
|
|
5887
5953
|
}
|
|
5888
5954
|
return { ...prev, [treeKey]: newTree };
|
|
5889
5955
|
});
|
|
@@ -5942,6 +6008,7 @@ function CreateAncestryPanel({
|
|
|
5942
6008
|
updateGlobalTree(rootTreeClone);
|
|
5943
6009
|
}
|
|
5944
6010
|
setAncestryMode((prev) => ({ ...prev, [treeKey]: rootTreeClone }));
|
|
6011
|
+
setHasUnsavedChanges(true);
|
|
5945
6012
|
} else {
|
|
5946
6013
|
alert("N\xE3o \xE9 poss\xEDvel mover um node para dentro de seus pr\xF3prios descendentes.");
|
|
5947
6014
|
}
|
|
@@ -6014,6 +6081,7 @@ function CreateAncestryPanel({
|
|
|
6014
6081
|
const handleAddProp = () => {
|
|
6015
6082
|
const newProp = createNewCustomProperty(customProps);
|
|
6016
6083
|
setCustomProps((p) => [...p, newProp]);
|
|
6084
|
+
setHasUnsavedChanges(true);
|
|
6017
6085
|
setTimeout(() => {
|
|
6018
6086
|
var _a;
|
|
6019
6087
|
(_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
@@ -6022,11 +6090,13 @@ function CreateAncestryPanel({
|
|
|
6022
6090
|
const handleRemoveProp = (i) => {
|
|
6023
6091
|
const newProps = customProps.filter((_, idx) => idx !== i);
|
|
6024
6092
|
setCustomProps(newProps);
|
|
6093
|
+
setHasUnsavedChanges(true);
|
|
6025
6094
|
};
|
|
6026
6095
|
const handleUpdateProp = (index, updatedProp) => {
|
|
6027
6096
|
const newProps = [...customProps];
|
|
6028
6097
|
newProps[index] = updatedProp;
|
|
6029
6098
|
setCustomProps(newProps);
|
|
6099
|
+
setHasUnsavedChanges(true);
|
|
6030
6100
|
};
|
|
6031
6101
|
const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
|
|
6032
6102
|
useEffect10(() => {
|
|
@@ -6136,6 +6206,7 @@ function CreateAncestryPanel({
|
|
|
6136
6206
|
updateGlobalTree(rootTreeClone);
|
|
6137
6207
|
setBranchStack([...branchStack]);
|
|
6138
6208
|
setIsPickerOpen(false);
|
|
6209
|
+
setHasUnsavedChanges(true);
|
|
6139
6210
|
try {
|
|
6140
6211
|
setIsSaving(true);
|
|
6141
6212
|
const rootProps = extractCustomPropsFromNode(ancestryMode);
|
|
@@ -6149,6 +6220,7 @@ function CreateAncestryPanel({
|
|
|
6149
6220
|
rootExtras
|
|
6150
6221
|
);
|
|
6151
6222
|
setLastSavedSnapshot(takeSnapshot(rootTreeClone, ancestryName, description, processedSections, [], isPrivate, ancestryMode.abstraction_tree));
|
|
6223
|
+
setHasUnsavedChanges(false);
|
|
6152
6224
|
if (onRenderFullAncestry) {
|
|
6153
6225
|
const fullTreePayload = {
|
|
6154
6226
|
ancestry_id: ancestryMode.currentAncestryId || "temp_root",
|
|
@@ -6191,6 +6263,7 @@ function CreateAncestryPanel({
|
|
|
6191
6263
|
if (branchIndex !== -1) {
|
|
6192
6264
|
foundParentPath.node.parallel_branches.splice(branchIndex, 1);
|
|
6193
6265
|
updateGlobalTree(rootTreeClone);
|
|
6266
|
+
setHasUnsavedChanges(true);
|
|
6194
6267
|
try {
|
|
6195
6268
|
setIsSaving(true);
|
|
6196
6269
|
const currentRootProps = extractCustomPropsFromNode(ancestryMode);
|
|
@@ -6212,6 +6285,7 @@ function CreateAncestryPanel({
|
|
|
6212
6285
|
isPrivate,
|
|
6213
6286
|
ancestryMode.abstraction_tree
|
|
6214
6287
|
));
|
|
6288
|
+
setHasUnsavedChanges(false);
|
|
6215
6289
|
if (onClearAncestryVisuals) {
|
|
6216
6290
|
onClearAncestryVisuals(currentStep.branchId);
|
|
6217
6291
|
}
|
|
@@ -6244,6 +6318,7 @@ function CreateAncestryPanel({
|
|
|
6244
6318
|
if (branchIndex !== -1) {
|
|
6245
6319
|
foundParentPath.node.parallel_branches.splice(branchIndex, 1);
|
|
6246
6320
|
updateGlobalTree(rootTreeClone);
|
|
6321
|
+
setHasUnsavedChanges(true);
|
|
6247
6322
|
try {
|
|
6248
6323
|
setIsSaving(true);
|
|
6249
6324
|
const currentRootProps = extractCustomPropsFromNode(ancestryMode);
|
|
@@ -6265,6 +6340,7 @@ function CreateAncestryPanel({
|
|
|
6265
6340
|
isPrivate,
|
|
6266
6341
|
ancestryMode.abstraction_tree
|
|
6267
6342
|
));
|
|
6343
|
+
setHasUnsavedChanges(false);
|
|
6268
6344
|
if (onClearAncestryVisuals) {
|
|
6269
6345
|
onClearAncestryVisuals(currentStep.branchId);
|
|
6270
6346
|
}
|
|
@@ -6526,6 +6602,7 @@ function CreateAncestryPanel({
|
|
|
6526
6602
|
}
|
|
6527
6603
|
setBranchStack(parentStack);
|
|
6528
6604
|
setTargetScrollSectionId(targetFocusId);
|
|
6605
|
+
setHasUnsavedChanges(true);
|
|
6529
6606
|
if (onRenderFullAncestry) {
|
|
6530
6607
|
const parentStack2 = currentStack;
|
|
6531
6608
|
const rotation = parentStack2.reduce((acc, step) => {
|
|
@@ -6587,7 +6664,6 @@ function CreateAncestryPanel({
|
|
|
6587
6664
|
direction,
|
|
6588
6665
|
tree: {
|
|
6589
6666
|
node: nodeData,
|
|
6590
|
-
node_id: nodeId,
|
|
6591
6667
|
children: [],
|
|
6592
6668
|
relationship: {}
|
|
6593
6669
|
}
|
|
@@ -6609,6 +6685,7 @@ function CreateAncestryPanel({
|
|
|
6609
6685
|
savedMaxIndex: parentIndexToSave,
|
|
6610
6686
|
entryDirection: direction
|
|
6611
6687
|
}]);
|
|
6688
|
+
setHasUnsavedChanges(true);
|
|
6612
6689
|
if (branch && branch.tree && onRenderFullAncestry) {
|
|
6613
6690
|
const branchAncestryObj = {
|
|
6614
6691
|
ancestry_id: branch.id,
|
|
@@ -6659,6 +6736,10 @@ function CreateAncestryPanel({
|
|
|
6659
6736
|
const currentInputName = overrides.ancestryName !== void 0 ? overrides.ancestryName : ancestryName;
|
|
6660
6737
|
const currentInputDesc = overrides.description !== void 0 ? overrides.description : description;
|
|
6661
6738
|
const currentInputSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
|
|
6739
|
+
if (!keepOpen && !hasUnsavedChanges) {
|
|
6740
|
+
onClose();
|
|
6741
|
+
return;
|
|
6742
|
+
}
|
|
6662
6743
|
if (!currentInputName.trim()) {
|
|
6663
6744
|
alert("O nome n\xE3o pode estar vazio.");
|
|
6664
6745
|
return;
|
|
@@ -6666,11 +6747,7 @@ function CreateAncestryPanel({
|
|
|
6666
6747
|
setIsSaving(true);
|
|
6667
6748
|
const processedSections = processDescriptionForSave(currentInputDesc, currentInputSections);
|
|
6668
6749
|
setExistingSections(processedSections);
|
|
6669
|
-
const updatedRootTree =
|
|
6670
|
-
ancestryMode.tree,
|
|
6671
|
-
currentInputDesc,
|
|
6672
|
-
processedSections
|
|
6673
|
-
);
|
|
6750
|
+
const updatedRootTree = JSON.parse(JSON.stringify(ancestryMode.tree));
|
|
6674
6751
|
const extrasObj = {
|
|
6675
6752
|
...toObjectFromCustomProps(customProps.filter((p) => !p.isEditing)),
|
|
6676
6753
|
is_private: isPrivate
|
|
@@ -6712,6 +6789,7 @@ function CreateAncestryPanel({
|
|
|
6712
6789
|
isPrivate,
|
|
6713
6790
|
ancestryMode.abstraction_tree
|
|
6714
6791
|
));
|
|
6792
|
+
setHasUnsavedChanges(false);
|
|
6715
6793
|
if (onRenderFullAncestry) {
|
|
6716
6794
|
const rotation = branchStack.reduce((acc, step) => {
|
|
6717
6795
|
return acc + (step.entryDirection === "left" ? -Math.PI / 2 : Math.PI / 2);
|
|
@@ -6763,6 +6841,7 @@ function CreateAncestryPanel({
|
|
|
6763
6841
|
updatedRootTree,
|
|
6764
6842
|
extrasObj
|
|
6765
6843
|
);
|
|
6844
|
+
setHasUnsavedChanges(false);
|
|
6766
6845
|
setLastSavedSnapshot(takeSnapshot(
|
|
6767
6846
|
updatedRootTree,
|
|
6768
6847
|
currentInputName,
|
|
@@ -6785,6 +6864,7 @@ function CreateAncestryPanel({
|
|
|
6785
6864
|
const newTreeString = JSON.stringify(newRootTree);
|
|
6786
6865
|
if (currentTreeString !== newTreeString) {
|
|
6787
6866
|
updateGlobalTree(newRootTree);
|
|
6867
|
+
setHasUnsavedChanges(true);
|
|
6788
6868
|
}
|
|
6789
6869
|
}, [description, existingSections]);
|
|
6790
6870
|
const handleTriggerFullRender = () => {
|
|
@@ -6807,6 +6887,7 @@ function CreateAncestryPanel({
|
|
|
6807
6887
|
};
|
|
6808
6888
|
const handleSaveDescriptionInline = (newDesc) => {
|
|
6809
6889
|
setDescription(newDesc);
|
|
6890
|
+
setHasUnsavedChanges(true);
|
|
6810
6891
|
handleLocalSave(true, { description: newDesc });
|
|
6811
6892
|
};
|
|
6812
6893
|
const swallow = (e) => e.stopPropagation();
|
|
@@ -6936,7 +7017,11 @@ function CreateAncestryPanel({
|
|
|
6936
7017
|
{
|
|
6937
7018
|
type: "text",
|
|
6938
7019
|
value: ancestryName,
|
|
6939
|
-
onChange: (e) =>
|
|
7020
|
+
onChange: (e) => {
|
|
7021
|
+
setAncestryName(e.target.value);
|
|
7022
|
+
setHasUnsavedChanges(true);
|
|
7023
|
+
},
|
|
7024
|
+
readOnly: isContextLinked,
|
|
6940
7025
|
placeholder: "Nome da Ancestralidade",
|
|
6941
7026
|
className: "text-xl sm:text-2xl font-semibold tracking-tight bg-transparent border-none p-0 focus:ring-2 focus:ring-indigo-500 rounded-md -ml-1.5 px-1.5 w-full outline-none transition-all focus:bg-slate-800/70"
|
|
6942
7027
|
}
|
|
@@ -7585,9 +7670,9 @@ function InSceneCreationForm({
|
|
|
7585
7670
|
};
|
|
7586
7671
|
const handleToggleImageMode = () => {
|
|
7587
7672
|
var _a2, _b;
|
|
7588
|
-
const
|
|
7589
|
-
setUseImageAsTexture(
|
|
7590
|
-
if (
|
|
7673
|
+
const newValue2 = !useImageAsTexture;
|
|
7674
|
+
setUseImageAsTexture(newValue2);
|
|
7675
|
+
if (newValue2) {
|
|
7591
7676
|
const firstImageProp = customProps.find((p) => p.type === "images");
|
|
7592
7677
|
if (firstImageProp && ((_b = (_a2 = firstImageProp.value) == null ? void 0 : _a2[0]) == null ? void 0 : _b.value)) {
|
|
7593
7678
|
const url = firstImageProp.value[0].value;
|
|
@@ -7885,9 +7970,9 @@ function InSceneVersionForm({
|
|
|
7885
7970
|
};
|
|
7886
7971
|
const handleToggleImageMode = () => {
|
|
7887
7972
|
var _a, _b;
|
|
7888
|
-
const
|
|
7889
|
-
setUseImageAsTexture(
|
|
7890
|
-
if (
|
|
7973
|
+
const newValue2 = !useImageAsTexture;
|
|
7974
|
+
setUseImageAsTexture(newValue2);
|
|
7975
|
+
if (newValue2) {
|
|
7891
7976
|
const firstImageProp = customProps.find((p) => p.type === "images");
|
|
7892
7977
|
if (firstImageProp && ((_b = (_a = firstImageProp.value) == null ? void 0 : _a[0]) == null ? void 0 : _b.value)) {
|
|
7893
7978
|
const url = firstImageProp.value[0].value;
|
|
@@ -8307,6 +8392,7 @@ function NodeDetailsPanel({
|
|
|
8307
8392
|
return !!(node == null ? void 0 : node.useImageAsTexture);
|
|
8308
8393
|
});
|
|
8309
8394
|
const [selectedImageUrl, setSelectedImageUrl] = useState17((node == null ? void 0 : node.textureImageUrl) ?? null);
|
|
8395
|
+
const [hasUnsavedChanges, setHasUnsavedChanges] = useState17(false);
|
|
8310
8396
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
8311
8397
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
8312
8398
|
initialWidth: isReadMode ? 700 : 440,
|
|
@@ -8344,6 +8430,7 @@ function NodeDetailsPanel({
|
|
|
8344
8430
|
else if ((node == null ? void 0 : node.useImageAsTexture) === "false") setUseImageAsTexture(false);
|
|
8345
8431
|
else setUseImageAsTexture(!!(node == null ? void 0 : node.useImageAsTexture));
|
|
8346
8432
|
setSelectedImageUrl((node == null ? void 0 : node.textureImageUrl) ?? null);
|
|
8433
|
+
setHasUnsavedChanges(false);
|
|
8347
8434
|
}
|
|
8348
8435
|
}, [node]);
|
|
8349
8436
|
const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
|
|
@@ -8370,6 +8457,7 @@ function NodeDetailsPanel({
|
|
|
8370
8457
|
setIntensity(val);
|
|
8371
8458
|
onIntensityChange == null ? void 0 : onIntensityChange(node.id, val);
|
|
8372
8459
|
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, intensity: val });
|
|
8460
|
+
setHasUnsavedChanges(true);
|
|
8373
8461
|
};
|
|
8374
8462
|
const handleCopyLink = () => {
|
|
8375
8463
|
if (!(node == null ? void 0 : node.id)) return;
|
|
@@ -8387,14 +8475,17 @@ function NodeDetailsPanel({
|
|
|
8387
8475
|
const v = e.target.value;
|
|
8388
8476
|
setName(v);
|
|
8389
8477
|
onNameChange == null ? void 0 : onNameChange(node.id, v);
|
|
8478
|
+
setHasUnsavedChanges(true);
|
|
8390
8479
|
};
|
|
8391
8480
|
const handleColorChange = (val) => {
|
|
8392
8481
|
setColor(val);
|
|
8393
8482
|
onColorChange == null ? void 0 : onColorChange(node.id, val);
|
|
8483
|
+
setHasUnsavedChanges(true);
|
|
8394
8484
|
};
|
|
8395
8485
|
const handleSizeChange = (newSize) => {
|
|
8396
8486
|
setSize(newSize);
|
|
8397
8487
|
onSizeChange == null ? void 0 : onSizeChange(node.id, newSize);
|
|
8488
|
+
setHasUnsavedChanges(true);
|
|
8398
8489
|
};
|
|
8399
8490
|
const handleAddType = (newType) => {
|
|
8400
8491
|
const trimmed = newType.trim();
|
|
@@ -8402,10 +8493,12 @@ function NodeDetailsPanel({
|
|
|
8402
8493
|
setTypes([...types, trimmed]);
|
|
8403
8494
|
setTypeInput("");
|
|
8404
8495
|
setShowTypeSuggestions(false);
|
|
8496
|
+
setHasUnsavedChanges(true);
|
|
8405
8497
|
}
|
|
8406
8498
|
};
|
|
8407
8499
|
const handleRemoveType = (indexToRemove) => {
|
|
8408
8500
|
setTypes(types.filter((_, index) => index !== indexToRemove));
|
|
8501
|
+
setHasUnsavedChanges(true);
|
|
8409
8502
|
};
|
|
8410
8503
|
const handleTypeInputKeyDown = (e) => {
|
|
8411
8504
|
if (e.key === "Enter") {
|
|
@@ -8418,6 +8511,7 @@ function NodeDetailsPanel({
|
|
|
8418
8511
|
const handleAddProp = () => {
|
|
8419
8512
|
const newProp = createNewCustomProperty(customProps);
|
|
8420
8513
|
setCustomProps((p) => [...p, newProp]);
|
|
8514
|
+
setHasUnsavedChanges(true);
|
|
8421
8515
|
setTimeout(() => {
|
|
8422
8516
|
var _a;
|
|
8423
8517
|
(_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
@@ -8426,19 +8520,21 @@ function NodeDetailsPanel({
|
|
|
8426
8520
|
const handleRemoveProp = (i) => {
|
|
8427
8521
|
const newProps = customProps.filter((_, idx) => idx !== i);
|
|
8428
8522
|
setCustomProps(newProps);
|
|
8523
|
+
setHasUnsavedChanges(true);
|
|
8429
8524
|
triggerAutoSave({ customProps: newProps });
|
|
8430
8525
|
};
|
|
8431
8526
|
const handleUpdateProp = (index, updatedProp) => {
|
|
8432
8527
|
const newProps = [...customProps];
|
|
8433
8528
|
newProps[index] = updatedProp;
|
|
8434
8529
|
setCustomProps(newProps);
|
|
8530
|
+
setHasUnsavedChanges(true);
|
|
8435
8531
|
if (!updatedProp.isEditing) {
|
|
8436
8532
|
triggerAutoSave({ customProps: newProps });
|
|
8437
8533
|
}
|
|
8438
8534
|
};
|
|
8439
8535
|
const handleToggleImageMode = () => {
|
|
8440
|
-
const newValue = !useImageAsTexture;
|
|
8441
8536
|
setUseImageAsTexture(newValue);
|
|
8537
|
+
setHasUnsavedChanges(true);
|
|
8442
8538
|
let activeUrl = null;
|
|
8443
8539
|
if (newValue) {
|
|
8444
8540
|
const firstImageProp = customProps.find((p) => p.type === "images");
|
|
@@ -8460,6 +8556,7 @@ function NodeDetailsPanel({
|
|
|
8460
8556
|
};
|
|
8461
8557
|
const handleSelectTexture = (url) => {
|
|
8462
8558
|
setSelectedImageUrl(url);
|
|
8559
|
+
setHasUnsavedChanges(true);
|
|
8463
8560
|
onImageChange == null ? void 0 : onImageChange(true, url, color);
|
|
8464
8561
|
onDataUpdate == null ? void 0 : onDataUpdate({
|
|
8465
8562
|
...node,
|
|
@@ -8470,6 +8567,7 @@ function NodeDetailsPanel({
|
|
|
8470
8567
|
};
|
|
8471
8568
|
const handleSaveDescriptionInline = (newDescription) => {
|
|
8472
8569
|
setDescription(newDescription);
|
|
8570
|
+
setHasUnsavedChanges(true);
|
|
8473
8571
|
onDataUpdate({ ...node, description: newDescription });
|
|
8474
8572
|
triggerAutoSave({ description: newDescription });
|
|
8475
8573
|
};
|
|
@@ -8480,6 +8578,10 @@ function NodeDetailsPanel({
|
|
|
8480
8578
|
const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
|
|
8481
8579
|
const currentExistingSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
|
|
8482
8580
|
const currentIntensity = overrides.intensity !== void 0 ? overrides.intensity : intensity;
|
|
8581
|
+
if (!keepOpen && !hasUnsavedChanges) {
|
|
8582
|
+
onClose();
|
|
8583
|
+
return;
|
|
8584
|
+
}
|
|
8483
8585
|
if (!currentName.trim() || currentTypes.length === 0) {
|
|
8484
8586
|
alert("O campo 'Nome' e pelo menos um 'Tipo' s\xE3o obrigat\xF3rios.");
|
|
8485
8587
|
return;
|
|
@@ -8504,6 +8606,7 @@ function NodeDetailsPanel({
|
|
|
8504
8606
|
};
|
|
8505
8607
|
await onSave(dataToSave, keepOpen);
|
|
8506
8608
|
onDataUpdate(dataToSave);
|
|
8609
|
+
setHasUnsavedChanges(false);
|
|
8507
8610
|
if (!keepOpen) {
|
|
8508
8611
|
onClose();
|
|
8509
8612
|
}
|
|
@@ -8570,7 +8673,7 @@ function NodeDetailsPanel({
|
|
|
8570
8673
|
onImageClick: handleImageClickFromText,
|
|
8571
8674
|
onSaveDescription: handleSaveDescriptionInline
|
|
8572
8675
|
}
|
|
8573
|
-
) : /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ React16.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React16.createElement("div",
|
|
8676
|
+
) : /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ React16.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React16.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React16.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ React16.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node"), /* @__PURE__ */ React16.createElement(
|
|
8574
8677
|
"button",
|
|
8575
8678
|
{
|
|
8576
8679
|
onClick: handleCopyLink,
|
|
@@ -8578,7 +8681,7 @@ function NodeDetailsPanel({
|
|
|
8578
8681
|
title: isLinkCopied ? "Link Copiado!" : "Copiar link para este Node"
|
|
8579
8682
|
},
|
|
8580
8683
|
isLinkCopied ? /* @__PURE__ */ React16.createElement(FiCheck10, { size: 12 }) : /* @__PURE__ */ React16.createElement(FiLink5, { size: 12 })
|
|
8581
|
-
)), /* @__PURE__ */ React16.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ React16.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ React16.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React16.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300" }, "Tipos"), /* @__PURE__ */ React16.createElement("div", { className: `relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 ${canEdit ? "focus-within:ring-2 focus-within:ring-indigo-400/60" : ""} transition-all` }, types.map((t, index) => /* @__PURE__ */ React16.createElement("span", { key: index, className: "flex items-center gap-1 bg-indigo-500/30 text-indigo-100 px-1.5 py-0.5 rounded-md text-xs font-medium border border-indigo-500/20" }, t, canEdit && /* @__PURE__ */ React16.createElement(
|
|
8684
|
+
)), /* @__PURE__ */ React16.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ React16.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "w-9 h-9 flex-shrink-0 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ React16.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React16.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300" }, "Tipos"), /* @__PURE__ */ React16.createElement("div", { className: `relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 ${canEdit ? "focus-within:ring-2 focus-within:ring-indigo-400/60" : ""} transition-all` }, types.map((t, index) => /* @__PURE__ */ React16.createElement("span", { key: index, className: "flex items-center gap-1 bg-indigo-500/30 text-indigo-100 px-1.5 py-0.5 rounded-md text-xs font-medium border border-indigo-500/20" }, t, canEdit && /* @__PURE__ */ React16.createElement(
|
|
8582
8685
|
"button",
|
|
8583
8686
|
{
|
|
8584
8687
|
type: "button",
|
|
@@ -8740,6 +8843,7 @@ function NodeDetailsPanel({
|
|
|
8740
8843
|
initialValue: description,
|
|
8741
8844
|
onSave: (newDescription) => {
|
|
8742
8845
|
setDescription(newDescription);
|
|
8846
|
+
setHasUnsavedChanges(true);
|
|
8743
8847
|
onDataUpdate((prev) => ({ ...prev, description: newDescription }));
|
|
8744
8848
|
triggerAutoSave({ description: newDescription });
|
|
8745
8849
|
},
|
|
@@ -8799,6 +8903,7 @@ function QuestDetailsPanel({
|
|
|
8799
8903
|
const [existingSections, setExistingSections] = useState18((node == null ? void 0 : node.description_sections) || []);
|
|
8800
8904
|
const [isSaving, setIsSaving] = useState18(false);
|
|
8801
8905
|
const [isLinkCopied, setIsLinkCopied] = useState18(false);
|
|
8906
|
+
const [hasUnsavedChanges, setHasUnsavedChanges] = useState18(false);
|
|
8802
8907
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
8803
8908
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
8804
8909
|
initialWidth: isReadMode ? 700 : 440,
|
|
@@ -8830,6 +8935,7 @@ function QuestDetailsPanel({
|
|
|
8830
8935
|
setIntensity((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
|
|
8831
8936
|
setExistingSections((node == null ? void 0 : node.description_sections) || []);
|
|
8832
8937
|
setCustomProps(extractCustomPropsFromNode(node || {}));
|
|
8938
|
+
setHasUnsavedChanges(false);
|
|
8833
8939
|
}
|
|
8834
8940
|
}, [node]);
|
|
8835
8941
|
useEffect16(() => {
|
|
@@ -8861,16 +8967,19 @@ function QuestDetailsPanel({
|
|
|
8861
8967
|
setRawTitle(val);
|
|
8862
8968
|
const newStandardName = questPrefix ? `${questPrefix} - \xBB ${val || "Sem t\xEDtulo"}` : val;
|
|
8863
8969
|
onNameChange == null ? void 0 : onNameChange(node.id, newStandardName, val);
|
|
8970
|
+
setHasUnsavedChanges(true);
|
|
8864
8971
|
};
|
|
8865
8972
|
const handleSizeChange = (newSize) => {
|
|
8866
8973
|
setSize(newSize);
|
|
8867
8974
|
onSizeChange == null ? void 0 : onSizeChange(node.id, newSize);
|
|
8975
|
+
setHasUnsavedChanges(true);
|
|
8868
8976
|
};
|
|
8869
8977
|
const handleStatusChange = (newStatus) => {
|
|
8870
8978
|
setStatus(newStatus);
|
|
8871
8979
|
const newColor = QUEST_STATUS_COLORS3[newStatus];
|
|
8872
8980
|
onColorChange == null ? void 0 : onColorChange(node.id, newColor);
|
|
8873
8981
|
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, status: newStatus, color: newColor });
|
|
8982
|
+
setHasUnsavedChanges(true);
|
|
8874
8983
|
};
|
|
8875
8984
|
const handleAddType = (newType) => {
|
|
8876
8985
|
const trimmed = newType.trim();
|
|
@@ -8878,11 +8987,13 @@ function QuestDetailsPanel({
|
|
|
8878
8987
|
setTypes([...types, trimmed]);
|
|
8879
8988
|
setTypeInput("");
|
|
8880
8989
|
setShowTypeSuggestions(false);
|
|
8990
|
+
setHasUnsavedChanges(true);
|
|
8881
8991
|
}
|
|
8882
8992
|
};
|
|
8883
8993
|
const handleRemoveType = (indexToRemove) => {
|
|
8884
8994
|
if (types[indexToRemove] === "quest") return;
|
|
8885
8995
|
setTypes(types.filter((_, index) => index !== indexToRemove));
|
|
8996
|
+
setHasUnsavedChanges(true);
|
|
8886
8997
|
};
|
|
8887
8998
|
const handleTypeInputKeyDown = (e) => {
|
|
8888
8999
|
if (e.key === "Enter") {
|
|
@@ -8895,6 +9006,7 @@ function QuestDetailsPanel({
|
|
|
8895
9006
|
const handleAddProp = () => {
|
|
8896
9007
|
const newProp = createNewCustomProperty(customProps);
|
|
8897
9008
|
setCustomProps((p) => [...p, newProp]);
|
|
9009
|
+
setHasUnsavedChanges(true);
|
|
8898
9010
|
setTimeout(() => {
|
|
8899
9011
|
var _a2;
|
|
8900
9012
|
(_a2 = propsEndRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
@@ -8903,18 +9015,21 @@ function QuestDetailsPanel({
|
|
|
8903
9015
|
const handleRemoveProp = (i) => {
|
|
8904
9016
|
const newProps = customProps.filter((_, idx) => idx !== i);
|
|
8905
9017
|
setCustomProps(newProps);
|
|
9018
|
+
setHasUnsavedChanges(true);
|
|
8906
9019
|
triggerAutoSave({ customProps: newProps });
|
|
8907
9020
|
};
|
|
8908
9021
|
const handleUpdateProp = (index, updatedProp) => {
|
|
8909
9022
|
const newProps = [...customProps];
|
|
8910
9023
|
newProps[index] = updatedProp;
|
|
8911
9024
|
setCustomProps(newProps);
|
|
9025
|
+
setHasUnsavedChanges(true);
|
|
8912
9026
|
if (!updatedProp.isEditing) {
|
|
8913
9027
|
triggerAutoSave({ customProps: newProps });
|
|
8914
9028
|
}
|
|
8915
9029
|
};
|
|
8916
9030
|
const handleSaveDescriptionInline = (newDescription) => {
|
|
8917
9031
|
setDescription(newDescription);
|
|
9032
|
+
setHasUnsavedChanges(true);
|
|
8918
9033
|
onDataUpdate({ ...node, description: newDescription });
|
|
8919
9034
|
triggerAutoSave({ description: newDescription });
|
|
8920
9035
|
};
|
|
@@ -8926,6 +9041,10 @@ function QuestDetailsPanel({
|
|
|
8926
9041
|
const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
|
|
8927
9042
|
const currentExistingSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
|
|
8928
9043
|
const currentStatus = overrides.status !== void 0 ? overrides.status : status;
|
|
9044
|
+
if (!keepOpen && !hasUnsavedChanges) {
|
|
9045
|
+
onClose();
|
|
9046
|
+
return;
|
|
9047
|
+
}
|
|
8929
9048
|
if (!currentRawTitle.trim() || currentTypes.length === 0) {
|
|
8930
9049
|
alert("O campo 'T\xEDtulo' e pelo menos um 'Tipo' s\xE3o obrigat\xF3rios.");
|
|
8931
9050
|
return;
|
|
@@ -8955,6 +9074,7 @@ function QuestDetailsPanel({
|
|
|
8955
9074
|
};
|
|
8956
9075
|
await onSave(dataToSave, keepOpen);
|
|
8957
9076
|
onDataUpdate(dataToSave);
|
|
9077
|
+
setHasUnsavedChanges(false);
|
|
8958
9078
|
if (!keepOpen) {
|
|
8959
9079
|
onClose();
|
|
8960
9080
|
}
|
|
@@ -9012,7 +9132,7 @@ function QuestDetailsPanel({
|
|
|
9012
9132
|
onImageClick: handleImageClickFromText,
|
|
9013
9133
|
onSaveDescription: handleSaveDescriptionInline
|
|
9014
9134
|
}
|
|
9015
|
-
) : /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS3[status]}, transparent)` } }), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React17.createElement("div",
|
|
9135
|
+
) : /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS3[status]}, transparent)` } }), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React17.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React17.createElement(FiTarget2, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React17.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ React17.createElement("button", { onClick: handleCopyLink, className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-sky-400"}`, title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Quest" }, isLinkCopied ? /* @__PURE__ */ React17.createElement(FiCheck11, { size: 12 }) : /* @__PURE__ */ React17.createElement(FiLink6, { size: 12 }))), /* @__PURE__ */ React17.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, standardizedName || (node == null ? void 0 : node.name))), /* @__PURE__ */ React17.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "w-9 h-9 flex-shrink-0 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "T\xEDtulo da Quest"), /* @__PURE__ */ React17.createElement(
|
|
9016
9136
|
"input",
|
|
9017
9137
|
{
|
|
9018
9138
|
type: "text",
|
|
@@ -9186,9 +9306,12 @@ function RelationshipDetailsPanel({
|
|
|
9186
9306
|
const [description, setDescription] = useState20((link == null ? void 0 : link.description) ?? "");
|
|
9187
9307
|
const [customProps, setCustomProps] = useState20(() => extractCustomPropsFromNode(link || {}));
|
|
9188
9308
|
const [existingSections, setExistingSections] = useState20((link == null ? void 0 : link.description_sections) || []);
|
|
9309
|
+
const [sourceLabel, setSourceLabel] = useState20((link == null ? void 0 : link.source_label) ?? "");
|
|
9310
|
+
const [targetLabel, setTargetLabel] = useState20((link == null ? void 0 : link.target_label) ?? "");
|
|
9189
9311
|
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState20(false);
|
|
9190
9312
|
const [isSaving, setIsSaving] = useState20(false);
|
|
9191
9313
|
const [isReadMode, setIsReadMode] = useState20(false);
|
|
9314
|
+
const [hasUnsavedChanges, setHasUnsavedChanges] = useState20(false);
|
|
9192
9315
|
const propsEndRef = useRef16(null);
|
|
9193
9316
|
const canEdit = useMemo9(() => {
|
|
9194
9317
|
const ability = defineAbilityFor(userRole);
|
|
@@ -9199,12 +9322,16 @@ function RelationshipDetailsPanel({
|
|
|
9199
9322
|
setDescription((link == null ? void 0 : link.description) ?? "");
|
|
9200
9323
|
setExistingSections((link == null ? void 0 : link.description_sections) || []);
|
|
9201
9324
|
setCustomProps(extractCustomPropsFromNode(link || {}));
|
|
9325
|
+
setSourceLabel((link == null ? void 0 : link.source_label) ?? "");
|
|
9326
|
+
setTargetLabel((link == null ? void 0 : link.target_label) ?? "");
|
|
9327
|
+
setHasUnsavedChanges(false);
|
|
9202
9328
|
}, [link]);
|
|
9203
9329
|
const swallow = (e) => e.stopPropagation();
|
|
9204
9330
|
const handleAddProp = () => {
|
|
9205
9331
|
if (!canEdit) return;
|
|
9206
9332
|
const newProp = createNewCustomProperty(customProps);
|
|
9207
9333
|
setCustomProps((p) => [...p, newProp]);
|
|
9334
|
+
setHasUnsavedChanges(true);
|
|
9208
9335
|
setTimeout(() => {
|
|
9209
9336
|
var _a;
|
|
9210
9337
|
(_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
@@ -9216,6 +9343,12 @@ function RelationshipDetailsPanel({
|
|
|
9216
9343
|
const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
|
|
9217
9344
|
const currentExistingSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
|
|
9218
9345
|
const currentName = overrides.name !== void 0 ? overrides.name : name;
|
|
9346
|
+
const currentSourceLabel = overrides.sourceLabel !== void 0 ? overrides.sourceLabel : sourceLabel;
|
|
9347
|
+
const currentTargetLabel = overrides.targetLabel !== void 0 ? overrides.targetLabel : targetLabel;
|
|
9348
|
+
if (!keepOpen && !hasUnsavedChanges) {
|
|
9349
|
+
onClose();
|
|
9350
|
+
return;
|
|
9351
|
+
}
|
|
9219
9352
|
setIsSaving(true);
|
|
9220
9353
|
try {
|
|
9221
9354
|
const extrasObj = toObjectFromCustomProps(currentCustomProps.filter((p) => !p.isEditing));
|
|
@@ -9231,8 +9364,11 @@ function RelationshipDetailsPanel({
|
|
|
9231
9364
|
isCurved: link.isCurved,
|
|
9232
9365
|
curveOffset: link.curveOffset
|
|
9233
9366
|
};
|
|
9367
|
+
if (currentSourceLabel.trim()) dataToSave.source_label = currentSourceLabel.trim();
|
|
9368
|
+
if (currentTargetLabel.trim()) dataToSave.target_label = currentTargetLabel.trim();
|
|
9234
9369
|
await onSave(dataToSave, keepOpen);
|
|
9235
9370
|
onDataUpdate(dataToSave);
|
|
9371
|
+
setHasUnsavedChanges(false);
|
|
9236
9372
|
if (!keepOpen) {
|
|
9237
9373
|
onClose();
|
|
9238
9374
|
}
|
|
@@ -9246,18 +9382,21 @@ function RelationshipDetailsPanel({
|
|
|
9246
9382
|
const handleSaveDescriptionInline = (newDescription) => {
|
|
9247
9383
|
if (!canEdit) return;
|
|
9248
9384
|
setDescription(newDescription);
|
|
9385
|
+
setHasUnsavedChanges(true);
|
|
9249
9386
|
onDataUpdate((prev) => ({ ...prev, description: newDescription }));
|
|
9250
9387
|
triggerAutoSave({ description: newDescription });
|
|
9251
9388
|
};
|
|
9252
9389
|
const handleRemoveProp = (i) => {
|
|
9253
9390
|
const newProps = customProps.filter((_, idx) => idx !== i);
|
|
9254
9391
|
setCustomProps(newProps);
|
|
9392
|
+
setHasUnsavedChanges(true);
|
|
9255
9393
|
triggerAutoSave({ customProps: newProps });
|
|
9256
9394
|
};
|
|
9257
9395
|
const handleUpdateProp = (index, updatedProp) => {
|
|
9258
9396
|
const newProps = [...customProps];
|
|
9259
9397
|
newProps[index] = updatedProp;
|
|
9260
9398
|
setCustomProps(newProps);
|
|
9399
|
+
setHasUnsavedChanges(true);
|
|
9261
9400
|
if (!updatedProp.isEditing) {
|
|
9262
9401
|
triggerAutoSave({ customProps: newProps });
|
|
9263
9402
|
}
|
|
@@ -9305,19 +9444,52 @@ function RelationshipDetailsPanel({
|
|
|
9305
9444
|
onImageClick: handleImageClickFromText,
|
|
9306
9445
|
onSaveDescription: handleSaveDescriptionInline
|
|
9307
9446
|
}
|
|
9308
|
-
) : /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }), /* @__PURE__ */ React19.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React19.createElement("div",
|
|
9447
|
+
) : /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }), /* @__PURE__ */ React19.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React19.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React19.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React19.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-teal-400/80 shadow-[0_0_18px_2px_rgba(45,212,191,0.55)]" }), /* @__PURE__ */ React19.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Rela\xE7\xE3o")), /* @__PURE__ */ React19.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || "Rela\xE7\xE3o")), /* @__PURE__ */ React19.createElement("button", { onClick: onClose, disabled: isSaving, className: "w-9 h-9 flex-shrink-0 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Fechar" }, "\xD7")), /* @__PURE__ */ React19.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React19.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React19.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Rela\xE7\xE3o (Opcional)"), /* @__PURE__ */ React19.createElement(
|
|
9309
9448
|
"input",
|
|
9310
9449
|
{
|
|
9311
9450
|
type: "text",
|
|
9312
9451
|
value: name,
|
|
9313
|
-
onChange: (e) =>
|
|
9452
|
+
onChange: (e) => {
|
|
9453
|
+
setName(e.target.value);
|
|
9454
|
+
setHasUnsavedChanges(true);
|
|
9455
|
+
},
|
|
9314
9456
|
placeholder: "Ex: Controla, Pertence a, Fornece...",
|
|
9315
9457
|
disabled: !canEdit,
|
|
9316
9458
|
className: `w-full bg-slate-800/70 p-2 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-400/60
|
|
9317
9459
|
${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
|
|
9318
9460
|
`
|
|
9319
9461
|
}
|
|
9320
|
-
)), /* @__PURE__ */ React19.createElement("div", { className: "space-y-1.
|
|
9462
|
+
)), /* @__PURE__ */ React19.createElement("div", { className: "rounded-xl border border-white/8 bg-slate-800/30 p-3 space-y-3" }, /* @__PURE__ */ React19.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React19.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-violet-400 flex-shrink-0" }, /* @__PURE__ */ React19.createElement("path", { d: "M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z" }), /* @__PURE__ */ React19.createElement("line", { x1: "7", y1: "7", x2: "7.01", y2: "7" })), /* @__PURE__ */ React19.createElement("p", { className: "text-xs font-medium text-violet-300/80 uppercase tracking-wider" }, "Labels de Agrupamento")), /* @__PURE__ */ React19.createElement("p", { className: "text-[11px] text-slate-400 leading-relaxed" }, "Labels agrupam conex\xF5es no menu de Conex\xF5es. Cada lado da conex\xE3o pode ter sua pr\xF3pria label."), /* @__PURE__ */ React19.createElement("div", { className: "grid grid-cols-2 gap-2" }, /* @__PURE__ */ React19.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ React19.createElement("label", { className: "text-[11px] text-slate-400" }, "Label do Source"), /* @__PURE__ */ React19.createElement(
|
|
9463
|
+
"input",
|
|
9464
|
+
{
|
|
9465
|
+
type: "text",
|
|
9466
|
+
value: sourceLabel,
|
|
9467
|
+
onChange: (e) => {
|
|
9468
|
+
setSourceLabel(e.target.value);
|
|
9469
|
+
setHasUnsavedChanges(true);
|
|
9470
|
+
},
|
|
9471
|
+
placeholder: "Ex: Conceitos",
|
|
9472
|
+
disabled: !canEdit,
|
|
9473
|
+
className: `w-full bg-slate-900/60 p-2 text-xs rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-violet-400/60 placeholder:text-slate-600
|
|
9474
|
+
${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
|
|
9475
|
+
`
|
|
9476
|
+
}
|
|
9477
|
+
)), /* @__PURE__ */ React19.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ React19.createElement("label", { className: "text-[11px] text-slate-400" }, "Label do Target"), /* @__PURE__ */ React19.createElement(
|
|
9478
|
+
"input",
|
|
9479
|
+
{
|
|
9480
|
+
type: "text",
|
|
9481
|
+
value: targetLabel,
|
|
9482
|
+
onChange: (e) => {
|
|
9483
|
+
setTargetLabel(e.target.value);
|
|
9484
|
+
setHasUnsavedChanges(true);
|
|
9485
|
+
},
|
|
9486
|
+
placeholder: "Ex: Refer\xEAncias",
|
|
9487
|
+
disabled: !canEdit,
|
|
9488
|
+
className: `w-full bg-slate-900/60 p-2 text-xs rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-violet-400/60 placeholder:text-slate-600
|
|
9489
|
+
${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
|
|
9490
|
+
`
|
|
9491
|
+
}
|
|
9492
|
+
)))), /* @__PURE__ */ React19.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React19.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React19.createElement("div", { className: "relative group min-h-[60px] bg-slate-800/40 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ React19.createElement(
|
|
9321
9493
|
DescriptionDisplay,
|
|
9322
9494
|
{
|
|
9323
9495
|
description,
|
|
@@ -9387,6 +9559,7 @@ function RelationshipDetailsPanel({
|
|
|
9387
9559
|
onSave: (newDescription) => {
|
|
9388
9560
|
if (!canEdit) return;
|
|
9389
9561
|
setDescription(newDescription);
|
|
9562
|
+
setHasUnsavedChanges(true);
|
|
9390
9563
|
onDataUpdate((prev) => ({ ...prev, description: newDescription }));
|
|
9391
9564
|
triggerAutoSave({ description: newDescription });
|
|
9392
9565
|
},
|
|
@@ -9834,7 +10007,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9834
10007
|
onMentionClick,
|
|
9835
10008
|
onImageClick: handleImageClickFromText
|
|
9836
10009
|
}
|
|
9837
|
-
) : /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ React23.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React23.createElement("div",
|
|
10010
|
+
) : /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ React23.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React23.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React23.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React23.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-blue-500/80 shadow-[0_0_18px_2px_rgba(59,130,246,0.55)]" }), /* @__PURE__ */ React23.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Ancestralidade")), /* @__PURE__ */ React23.createElement("h2", { className: "text-lg font-semibold tracking-tight flex items-center gap-2" }, /* @__PURE__ */ React23.createElement("span", { className: "truncate max-w-[150px]" }, sourceName), /* @__PURE__ */ React23.createElement("span", { className: "text-slate-500 text-sm" }, "\u2794"), /* @__PURE__ */ React23.createElement("span", { className: "truncate max-w-[150px]" }, targetName))), /* @__PURE__ */ React23.createElement("button", { onClick: onClose, className: "w-9 h-9 flex-shrink-0 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")), /* @__PURE__ */ React23.createElement("div", { className: "px-6 pb-6 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, description && /* @__PURE__ */ React23.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React23.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React23.createElement("label", { className: "text-xs text-slate-300 font-medium" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React23.createElement(
|
|
9838
10011
|
"button",
|
|
9839
10012
|
{
|
|
9840
10013
|
onClick: () => setIsReadMode(true),
|
|
@@ -10627,6 +10800,7 @@ function XViewScene({
|
|
|
10627
10800
|
});
|
|
10628
10801
|
const [isImportModalOpen, setIsImportModalOpen] = useState25(false);
|
|
10629
10802
|
const [importSuccessMessage, setImportSuccessMessage] = useState25("");
|
|
10803
|
+
const [invalidTargetError, setInvalidTargetError] = useState25(null);
|
|
10630
10804
|
const [highlightedNodeId, setHighlightedNodeId] = useState25(null);
|
|
10631
10805
|
const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState25(false);
|
|
10632
10806
|
const [ancestryBoardData, setAncestryBoardData] = useState25([]);
|
|
@@ -11288,6 +11462,7 @@ function XViewScene({
|
|
|
11288
11462
|
boardPromise
|
|
11289
11463
|
]);
|
|
11290
11464
|
if ((sceneResponse == null ? void 0 : sceneResponse.success) && ((_a2 = sceneResponse.data) == null ? void 0 : _a2.scene) && ((_b2 = sceneResponse.data) == null ? void 0 : _b2.parent)) {
|
|
11465
|
+
console.log("XViewScene - View Members:", sceneResponse.data.scene.members);
|
|
11291
11466
|
if (focusNodeId) {
|
|
11292
11467
|
let targetNode = sceneResponse.data.scene.nodes.find(
|
|
11293
11468
|
(n) => String(n.id) === String(focusNodeId)
|
|
@@ -13528,7 +13703,7 @@ function XViewScene({
|
|
|
13528
13703
|
sceneVersion
|
|
13529
13704
|
]);
|
|
13530
13705
|
const handleStartReadingAncestry = useCallback4(
|
|
13531
|
-
async (ancestryObject) => {
|
|
13706
|
+
async (ancestryObject, renderMode = "full") => {
|
|
13532
13707
|
setContextMenu(
|
|
13533
13708
|
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
13534
13709
|
);
|
|
@@ -13544,14 +13719,20 @@ function XViewScene({
|
|
|
13544
13719
|
const hasDescription = ancestryObject.description && ancestryObject.description.trim() !== "";
|
|
13545
13720
|
const hasMainTreeNodes = ancestryObject.tree.children && ancestryObject.tree.children.length > 0;
|
|
13546
13721
|
const hasAbstractionNodes = ancestryObject.abstraction_tree && ancestryObject.abstraction_tree.children && ancestryObject.abstraction_tree.children.length > 0;
|
|
13547
|
-
const
|
|
13722
|
+
const isFull = renderMode === "full";
|
|
13723
|
+
const isAncestryOnly = renderMode === "ancestry_only";
|
|
13724
|
+
const isAbstractionOnly = renderMode === "abstraction_only";
|
|
13725
|
+
let shouldRenderAbstraction = isAbstractionOnly;
|
|
13726
|
+
if (isFull) {
|
|
13727
|
+
shouldRenderAbstraction = !hasDescription && !hasMainTreeNodes && hasAbstractionNodes;
|
|
13728
|
+
}
|
|
13548
13729
|
setReadingMode({
|
|
13549
|
-
isActive: hasDescription,
|
|
13730
|
+
isActive: isFull ? hasDescription : false,
|
|
13550
13731
|
ancestry: ancestryObject,
|
|
13551
13732
|
branchStack: [],
|
|
13552
|
-
autoAbstraction:
|
|
13733
|
+
autoAbstraction: shouldRenderAbstraction
|
|
13553
13734
|
});
|
|
13554
|
-
if (
|
|
13735
|
+
if (shouldRenderAbstraction) {
|
|
13555
13736
|
handleRenderAbstractionTree(ancestryObject, null);
|
|
13556
13737
|
} else {
|
|
13557
13738
|
const initialSections = /* @__PURE__ */ new Set(["preamble", 0, "0"]);
|
|
@@ -14297,6 +14478,9 @@ function XViewScene({
|
|
|
14297
14478
|
}, 300);
|
|
14298
14479
|
} else {
|
|
14299
14480
|
setHasFocusedInitial(true);
|
|
14481
|
+
setInvalidTargetError(
|
|
14482
|
+
"O link aponta para um item que n\xE3o foi encontrado ou foi exclu\xEDdo."
|
|
14483
|
+
);
|
|
14300
14484
|
}
|
|
14301
14485
|
}
|
|
14302
14486
|
}, [
|
|
@@ -14319,6 +14503,9 @@ function XViewScene({
|
|
|
14319
14503
|
}, 300);
|
|
14320
14504
|
} else {
|
|
14321
14505
|
setHasOpenedInitialAncestry(true);
|
|
14506
|
+
setInvalidTargetError(
|
|
14507
|
+
"O link aponta para uma ancestralidade que n\xE3o foi encontrada ou foi exclu\xEDda."
|
|
14508
|
+
);
|
|
14322
14509
|
}
|
|
14323
14510
|
}
|
|
14324
14511
|
}, [
|
|
@@ -14928,6 +15115,83 @@ function XViewScene({
|
|
|
14928
15115
|
currentViewName: viewParams == null ? void 0 : viewParams.name,
|
|
14929
15116
|
currentAncestries: ancestryDataRef.current || []
|
|
14930
15117
|
}
|
|
15118
|
+
),
|
|
15119
|
+
invalidTargetError && /* @__PURE__ */ React25.createElement(
|
|
15120
|
+
"div",
|
|
15121
|
+
{
|
|
15122
|
+
className: "ui-overlay",
|
|
15123
|
+
style: {
|
|
15124
|
+
position: "fixed",
|
|
15125
|
+
top: "24px",
|
|
15126
|
+
left: "50%",
|
|
15127
|
+
transform: "translateX(-50%)",
|
|
15128
|
+
zIndex: 1e4,
|
|
15129
|
+
padding: "16px 24px",
|
|
15130
|
+
background: "rgba(30, 20, 20, 0.85)",
|
|
15131
|
+
backdropFilter: "blur(12px)",
|
|
15132
|
+
WebkitBackdropFilter: "blur(12px)",
|
|
15133
|
+
border: "1px solid rgba(255, 70, 70, 0.35)",
|
|
15134
|
+
borderRadius: "16px",
|
|
15135
|
+
boxShadow: "0 12px 40px rgba(0,0,0,0.5), 0 0 30px rgba(255, 50, 50, 0.1)",
|
|
15136
|
+
color: "#ffa0a0",
|
|
15137
|
+
display: "flex",
|
|
15138
|
+
alignItems: "center",
|
|
15139
|
+
gap: "16px",
|
|
15140
|
+
fontFamily: "Inter, sans-serif",
|
|
15141
|
+
animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
|
|
15142
|
+
}
|
|
15143
|
+
},
|
|
15144
|
+
/* @__PURE__ */ React25.createElement("style", null, `
|
|
15145
|
+
@keyframes fadeInDown {
|
|
15146
|
+
from { opacity: 0; transform: translate(-50%, -20px); }
|
|
15147
|
+
to { opacity: 1; transform: translate(-50%, 0); }
|
|
15148
|
+
}
|
|
15149
|
+
`),
|
|
15150
|
+
/* @__PURE__ */ React25.createElement(
|
|
15151
|
+
"svg",
|
|
15152
|
+
{
|
|
15153
|
+
width: "20",
|
|
15154
|
+
height: "20",
|
|
15155
|
+
viewBox: "0 0 24 24",
|
|
15156
|
+
fill: "none",
|
|
15157
|
+
stroke: "currentColor",
|
|
15158
|
+
strokeWidth: "2",
|
|
15159
|
+
strokeLinecap: "round",
|
|
15160
|
+
strokeLinejoin: "round"
|
|
15161
|
+
},
|
|
15162
|
+
/* @__PURE__ */ React25.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
15163
|
+
/* @__PURE__ */ React25.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
15164
|
+
/* @__PURE__ */ React25.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
|
|
15165
|
+
),
|
|
15166
|
+
/* @__PURE__ */ React25.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
|
|
15167
|
+
/* @__PURE__ */ React25.createElement(
|
|
15168
|
+
"button",
|
|
15169
|
+
{
|
|
15170
|
+
onClick: () => setInvalidTargetError(null),
|
|
15171
|
+
style: {
|
|
15172
|
+
background: "rgba(255, 255, 255, 0.1)",
|
|
15173
|
+
border: "none",
|
|
15174
|
+
color: "white",
|
|
15175
|
+
padding: "4px 10px",
|
|
15176
|
+
borderRadius: "8px",
|
|
15177
|
+
cursor: "pointer",
|
|
15178
|
+
fontSize: "12px",
|
|
15179
|
+
fontWeight: 600,
|
|
15180
|
+
transition: "all 0.2s",
|
|
15181
|
+
marginLeft: "8px",
|
|
15182
|
+
border: "1px solid rgba(255,255,255,0.1)"
|
|
15183
|
+
},
|
|
15184
|
+
onMouseOver: (e) => {
|
|
15185
|
+
e.currentTarget.style.background = "rgba(255, 255, 255, 0.15)";
|
|
15186
|
+
e.currentTarget.style.transform = "translateY(-1px)";
|
|
15187
|
+
},
|
|
15188
|
+
onMouseOut: (e) => {
|
|
15189
|
+
e.currentTarget.style.background = "rgba(255, 255, 255, 0.1)";
|
|
15190
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
15191
|
+
}
|
|
15192
|
+
},
|
|
15193
|
+
"Fechar"
|
|
15194
|
+
)
|
|
14931
15195
|
)
|
|
14932
15196
|
);
|
|
14933
15197
|
}
|