@lv-x-software-house/x_view 1.2.4-dev.27 → 1.2.4-dev.29
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 +111 -28
- package/dist/index.mjs +111 -28
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -116,6 +116,13 @@ function defineAbilityFor(role) {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
// src/components/ContextMenu.jsx
|
|
119
|
+
var QUEST_STATUS_COLORS = {
|
|
120
|
+
"Backlog": "#64748b",
|
|
121
|
+
"In Progress": "#eab308",
|
|
122
|
+
"Review": "#a855f7",
|
|
123
|
+
"Done": "#22c55e"
|
|
124
|
+
};
|
|
125
|
+
var QUEST_STATUSES = ["Backlog", "In Progress", "Review", "Done"];
|
|
119
126
|
function ContextMenu({
|
|
120
127
|
data,
|
|
121
128
|
userRole,
|
|
@@ -136,19 +143,21 @@ function ContextMenu({
|
|
|
136
143
|
onFocusNode,
|
|
137
144
|
onClose
|
|
138
145
|
}) {
|
|
139
|
-
var _a, _b;
|
|
146
|
+
var _a, _b, _c;
|
|
140
147
|
const menuRef = (0, import_react.useRef)(null);
|
|
141
148
|
const [menuPos, setMenuPos] = (0, import_react.useState)({ left: 0, top: 0 });
|
|
142
149
|
const [menuView, setMenuView] = (0, import_react.useState)("main");
|
|
143
150
|
const [selectedAncestry, setSelectedAncestry] = (0, import_react.useState)(null);
|
|
144
151
|
const [versionSubMenu, setVersionSubMenu] = (0, import_react.useState)(null);
|
|
145
152
|
const [isLinkCopied, setIsLinkCopied] = (0, import_react.useState)(false);
|
|
153
|
+
const [selectedQuestStatus, setSelectedQuestStatus] = (0, import_react.useState)(null);
|
|
146
154
|
const ability = (0, import_react.useMemo)(() => defineAbilityFor(userRole), [userRole]);
|
|
147
155
|
(0, import_react.useEffect)(() => {
|
|
148
156
|
if (data.visible) {
|
|
149
157
|
setMenuView("main");
|
|
150
158
|
setSelectedAncestry(null);
|
|
151
159
|
setVersionSubMenu(null);
|
|
160
|
+
setSelectedQuestStatus(null);
|
|
152
161
|
}
|
|
153
162
|
}, [data.visible, (_a = data.nodeData) == null ? void 0 : _a.id]);
|
|
154
163
|
(0, import_react.useLayoutEffect)(() => {
|
|
@@ -163,7 +172,7 @@ function ContextMenu({
|
|
|
163
172
|
if (left + w + 8 > vw) left = Math.max(8, vw - w - 8);
|
|
164
173
|
if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
|
|
165
174
|
setMenuPos({ left, top });
|
|
166
|
-
}, [data, menuView, versionSubMenu]);
|
|
175
|
+
}, [data, menuView, versionSubMenu, selectedQuestStatus]);
|
|
167
176
|
(0, import_react.useEffect)(() => {
|
|
168
177
|
if (!data.visible) return;
|
|
169
178
|
const handleClickOutside = (e) => {
|
|
@@ -206,7 +215,16 @@ function ContextMenu({
|
|
|
206
215
|
var _a2;
|
|
207
216
|
return c.targetNode && !(((_a2 = c.targetNode.version_node) == null ? void 0 : _a2.is_version) && String(c.targetNode.version_node.parent_node) === String(data.nodeData.id));
|
|
208
217
|
});
|
|
209
|
-
const
|
|
218
|
+
const isCurrentNodeQuest = ((_c = data.nodeData) == null ? void 0 : _c.is_quest) === true;
|
|
219
|
+
const commonConnections = isCurrentNodeQuest ? connections : connections.filter((c) => {
|
|
220
|
+
var _a2;
|
|
221
|
+
return !((_a2 = c.targetNode) == null ? void 0 : _a2.is_quest);
|
|
222
|
+
});
|
|
223
|
+
const questConnections = isCurrentNodeQuest ? [] : connections.filter((c) => {
|
|
224
|
+
var _a2;
|
|
225
|
+
return (_a2 = c.targetNode) == null ? void 0 : _a2.is_quest;
|
|
226
|
+
});
|
|
227
|
+
const groupedConnections = commonConnections.reduce((acc, conn) => {
|
|
210
228
|
var _a2;
|
|
211
229
|
const { targetNode } = conn;
|
|
212
230
|
const groupingKey = ((_a2 = targetNode.version_node) == null ? void 0 : _a2.is_version) ? targetNode.version_node.parent_node : targetNode.id;
|
|
@@ -242,6 +260,20 @@ function ContextMenu({
|
|
|
242
260
|
};
|
|
243
261
|
}
|
|
244
262
|
}).filter(Boolean);
|
|
263
|
+
const questsByStatus = {
|
|
264
|
+
"Backlog": [],
|
|
265
|
+
"In Progress": [],
|
|
266
|
+
"Review": [],
|
|
267
|
+
"Done": []
|
|
268
|
+
};
|
|
269
|
+
questConnections.forEach((conn) => {
|
|
270
|
+
const status = conn.targetNode.status || "Backlog";
|
|
271
|
+
if (questsByStatus[status]) {
|
|
272
|
+
questsByStatus[status].push(conn);
|
|
273
|
+
} else {
|
|
274
|
+
questsByStatus["Backlog"].push(conn);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
245
277
|
const availableAncestries = (ancestryData || []).filter(
|
|
246
278
|
(ancestry) => String(ancestry.ancestral_node) === String(data.nodeData.id)
|
|
247
279
|
);
|
|
@@ -299,7 +331,7 @@ function ContextMenu({
|
|
|
299
331
|
const canCreateVersion = ability.can("create", "Versioning");
|
|
300
332
|
const canReadVersion = ability.can("read", "Versioning");
|
|
301
333
|
const shouldShowVersioningBtn = canCreateVersion || canReadVersion && hasVersions;
|
|
302
|
-
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ import_react.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex flex-col gap-1" }, ability.can("create", "Connection") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Conectar")), ability.can("create", "Node") && !((_a2 = data.nodeData) == null ? void 0 : _a2.is_quest) && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar Ancestralidade" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("path", { d: "M10 20.5c.5-.5.8-1.2.8-2s-.3-1.5-.8-2c-.5-.5-1.2-.8-2-.8s-1.5.3-2 .8c-.5.5-.8 1.2-.8 2s.3 1.5.8 2c.5.5 1.2-.8 2 .8s1.5-.3 2-.8Z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 3.5c.5.5.8 1.2.8 2s-.3 1.5-.8 2c-.5-.5-1.2-.8-2 .8s1.5.3-2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("line", { x1: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ import_react.default.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => {
|
|
334
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ import_react.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex flex-col gap-1" }, ability.can("create", "Connection") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Conectar")), ability.can("create", "Node") && !((_a2 = data.nodeData) == null ? void 0 : _a2.is_quest) && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar Ancestralidade" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("path", { d: "M10 20.5c.5-.5.8-1.2.8-2s-.3-1.5-.8-2c-.5-.5-1.2-.8-2-.8s-1.5.3-2 .8c-.5.5-.8 1.2-.8 2s.3 1.5.8 2c.5.5 1.2-.8 2 .8s1.5-.3 2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 3.5c.5.5.8 1.2.8 2s-.3 1.5-.8 2c-.5-.5-1.2-.8-2 .8s1.5.3-2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("line", { x1: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ import_react.default.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => {
|
|
303
335
|
onFocusNode == null ? void 0 : onFocusNode(data.nodeData);
|
|
304
336
|
onClose();
|
|
305
337
|
}, className: baseButtonClass, title: "Focar na c\xE2mera" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "3" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Focar neste Node")), /* @__PURE__ */ import_react.default.createElement("button", { onClick: (e) => handleCopyLink(e, data.nodeData), className: baseButtonClass, title: "Copiar Link para Compartilhar" }, isLinkCopied ? /* @__PURE__ */ import_react.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#4ade80", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react.default.createElement("polyline", { points: "20 6 9 17 4 12" })) : /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ import_react.default.createElement("span", { className: isLinkCopied ? "text-green-400" : "" }, isLinkCopied ? "Copiado!" : "Copiar Link")), ability.can("dismiss", "Node") && /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onDismissNode == null ? void 0 : onDismissNode(data.nodeData), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Dismiss")), /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => onDismissOtherNodes == null ? void 0 : onDismissOtherNodes(data.nodeData), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Dismiss other nodes"))), ability.can("delete", "Node") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("deleteConfirmation"), className: deleteButtonClass, title: "Excluir Node" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ import_react.default.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Excluir Node"))));
|
|
@@ -326,7 +358,7 @@ function ContextMenu({
|
|
|
326
358
|
}
|
|
327
359
|
const totalItems = availableAncestries.length + finalRenderableConnections.length;
|
|
328
360
|
const isScrollable = totalItems > 10;
|
|
329
|
-
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center justify-between gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("main"), className: "p-1 rounded-full hover:bg-white/10 text-slate-400 hover:text-white" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("polyline", { points: "15 18 9 12 15 6" }))), /* @__PURE__ */ import_react.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Conex\xF5es")),
|
|
361
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center justify-between gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("main"), className: "p-1 rounded-full hover:bg-white/10 text-slate-400 hover:text-white" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("polyline", { points: "15 18 9 12 15 6" }))), /* @__PURE__ */ import_react.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Conex\xF5es")), commonConnections.length > 0 && /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("div", { className: `flex flex-col ${isScrollable ? "max-h-[40vh] overflow-y-auto custom-scrollbar" : ""}` }, availableAncestries.length > 0 && /* @__PURE__ */ import_react.default.createElement("div", { className: `flex flex-col gap-1 ${finalRenderableConnections.length > 0 || questConnections.length > 0 ? "mb-4" : "mb-2"}` }, /* @__PURE__ */ import_react.default.createElement("div", { className: "px-2 py-1 text-[11px] uppercase tracking-wider text-indigo-400/90" }, "Ancestralidades Salvas"), availableAncestries.map((anc) => /* @__PURE__ */ import_react.default.createElement(
|
|
330
362
|
"button",
|
|
331
363
|
{
|
|
332
364
|
key: anc.ancestry_id,
|
|
@@ -336,7 +368,17 @@ function ContextMenu({
|
|
|
336
368
|
},
|
|
337
369
|
/* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("path", { d: "M6 3v4a2 2 0 0 0 2 2h4" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M18 3v4a2 2 0 0 1-2 2h-4" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "6", cy: "3", r: "2" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "18", cy: "3", r: "2" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "11", r: "2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 13v6" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "21", r: "2" })),
|
|
338
370
|
/* @__PURE__ */ import_react.default.createElement("span", { className: "flex-1 truncate" }, anc.name || `Ancestralidade #${anc.ancestry_id.substring(0, 8)}`)
|
|
339
|
-
)),
|
|
371
|
+
))), questConnections.length > 0 && /* @__PURE__ */ import_react.default.createElement("div", { className: `flex flex-col gap-1 ${finalRenderableConnections.length > 0 ? "mb-4" : "mb-2"}` }, /* @__PURE__ */ import_react.default.createElement("div", { className: "px-2 py-1 text-[11px] uppercase tracking-wider text-sky-400/90" }, "Quests Relacionadas"), /* @__PURE__ */ import_react.default.createElement(
|
|
372
|
+
"button",
|
|
373
|
+
{
|
|
374
|
+
onClick: () => setMenuView("quest_statuses"),
|
|
375
|
+
className: baseButtonClass,
|
|
376
|
+
title: "Ver Quests Conectadas"
|
|
377
|
+
},
|
|
378
|
+
/* @__PURE__ */ import_react.default.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-sky-400" }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "6" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "2" })),
|
|
379
|
+
/* @__PURE__ */ import_react.default.createElement("span", { className: "flex-1 truncate" }, "Status das Quests"),
|
|
380
|
+
/* @__PURE__ */ import_react.default.createElement("span", { className: "text-xs px-2 py-0.5 bg-sky-500/20 text-sky-200 rounded-full" }, questConnections.length)
|
|
381
|
+
)), finalRenderableConnections.length > 0 && /* @__PURE__ */ import_react.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "px-2 py-1 text-[11px] uppercase tracking-wider text-indigo-400/90 border-t border-white/5 pt-2" }, "Outros Nodes"), finalRenderableConnections.map((group) => {
|
|
340
382
|
if (group.isVersionGroup) {
|
|
341
383
|
return /* @__PURE__ */ import_react.default.createElement(
|
|
342
384
|
"button",
|
|
@@ -366,6 +408,43 @@ function ContextMenu({
|
|
|
366
408
|
}
|
|
367
409
|
}))));
|
|
368
410
|
};
|
|
411
|
+
const renderQuestStatusesView = () => {
|
|
412
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center justify-between gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("connections"), className: "p-1 rounded-full hover:bg-white/10 text-slate-400 hover:text-white" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("polyline", { points: "15 18 9 12 15 6" }))), /* @__PURE__ */ import_react.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Status das Quests"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex flex-col gap-1" }, QUEST_STATUSES.map((status) => {
|
|
413
|
+
const count = questsByStatus[status].length;
|
|
414
|
+
const color = QUEST_STATUS_COLORS[status];
|
|
415
|
+
return /* @__PURE__ */ import_react.default.createElement(
|
|
416
|
+
"button",
|
|
417
|
+
{
|
|
418
|
+
key: status,
|
|
419
|
+
onClick: () => {
|
|
420
|
+
if (count > 0) {
|
|
421
|
+
setSelectedQuestStatus(status);
|
|
422
|
+
setMenuView("quest_list");
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
className: `${baseButtonClass} ${count === 0 ? "opacity-50 cursor-default hover:bg-transparent hover:text-slate-200" : ""}`
|
|
426
|
+
},
|
|
427
|
+
/* @__PURE__ */ import_react.default.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor: color } }),
|
|
428
|
+
/* @__PURE__ */ import_react.default.createElement("span", { className: "flex-1 truncate" }, status),
|
|
429
|
+
count > 0 && /* @__PURE__ */ import_react.default.createElement("span", { className: "text-xs px-2 py-0.5 bg-white/10 rounded-full" }, count)
|
|
430
|
+
);
|
|
431
|
+
})));
|
|
432
|
+
};
|
|
433
|
+
const renderQuestListView = () => {
|
|
434
|
+
const quests = questsByStatus[selectedQuestStatus] || [];
|
|
435
|
+
const isScrollable = quests.length > 10;
|
|
436
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center justify-between gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("quest_statuses"), className: "p-1 rounded-full hover:bg-white/10 text-slate-400 hover:text-white flex-shrink-0" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("polyline", { points: "15 18 9 12 15 6" }))), /* @__PURE__ */ import_react.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400 truncate", title: `Quests: ${selectedQuestStatus}` }, "Quests: ", selectedQuestStatus)), quests.length > 0 && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => handleExpandAndClose(quests.map((q) => q.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__ */ import_react.default.createElement("div", { className: `flex flex-col gap-1 ${isScrollable ? "max-h-[40vh] overflow-y-auto custom-scrollbar" : ""}` }, quests.map((conn) => /* @__PURE__ */ import_react.default.createElement(
|
|
437
|
+
"button",
|
|
438
|
+
{
|
|
439
|
+
key: conn.targetNode.id,
|
|
440
|
+
onClick: () => handleConnectionClick({ links: [conn.link] }),
|
|
441
|
+
className: baseButtonClass,
|
|
442
|
+
title: `Expandir Quest ${conn.targetNode.name}`
|
|
443
|
+
},
|
|
444
|
+
/* @__PURE__ */ import_react.default.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: "opacity-70" }, /* @__PURE__ */ import_react.default.createElement("polyline", { points: "13 17 18 12 13 7" }), /* @__PURE__ */ import_react.default.createElement("polyline", { points: "6 17 11 12 6 7" })),
|
|
445
|
+
/* @__PURE__ */ import_react.default.createElement("span", { className: "flex-1 truncate" }, conn.targetNode.name)
|
|
446
|
+
))));
|
|
447
|
+
};
|
|
369
448
|
const renderAncestryActionsView = () => {
|
|
370
449
|
const ancestryTitle = (selectedAncestry == null ? void 0 : selectedAncestry.name) || `Ancestralidade #${selectedAncestry == null ? void 0 : selectedAncestry.ancestry_id.substring(0, 8)}`;
|
|
371
450
|
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center justify-between gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("connections"), className: "p-1 rounded-full hover:bg-white/10 text-slate-400 hover:text-white flex-shrink-0" }, /* @__PURE__ */ import_react.default.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__ */ import_react.default.createElement("polyline", { points: "15 18 9 12 15 6" }))), /* @__PURE__ */ import_react.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400 truncate", title: ancestryTitle }, ancestryTitle))), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex flex-col gap-1" }, ability.can("read", "Ancestry") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => {
|
|
@@ -427,7 +506,7 @@ function ContextMenu({
|
|
|
427
506
|
onDoubleClick: swallow
|
|
428
507
|
},
|
|
429
508
|
/* @__PURE__ */ import_react.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
|
|
430
|
-
/* @__PURE__ */ import_react.default.createElement("div", { className: "p-1.5" }, menuView === "main" && renderMainView(), menuView === "connections" && renderConnectionsView(), menuView === "ancestryActions" && renderAncestryActionsView(), menuView === "versioning" && renderVersioningView(), menuView === "deleteConfirmation" && renderDeleteConfirmationView())
|
|
509
|
+
/* @__PURE__ */ import_react.default.createElement("div", { className: "p-1.5" }, menuView === "main" && renderMainView(), menuView === "connections" && renderConnectionsView(), menuView === "ancestryActions" && renderAncestryActionsView(), menuView === "versioning" && renderVersioningView(), menuView === "quest_statuses" && renderQuestStatusesView(), menuView === "quest_list" && renderQuestListView(), menuView === "deleteConfirmation" && renderDeleteConfirmationView())
|
|
431
510
|
);
|
|
432
511
|
}
|
|
433
512
|
|
|
@@ -1011,7 +1090,8 @@ var createNodeMesh = (nodeData, position, glowTexture) => {
|
|
|
1011
1090
|
const size = nodeData.size || "medium";
|
|
1012
1091
|
const scale = NODE_SCALE_FACTORS[size] || 1;
|
|
1013
1092
|
mesh.scale.set(scale, scale, scale);
|
|
1014
|
-
const
|
|
1093
|
+
const labelText = nodeData.is_quest && nodeData.raw_title ? nodeData.raw_title : nodeData.name;
|
|
1094
|
+
const label = createTextSprite(labelText);
|
|
1015
1095
|
label.name = "label";
|
|
1016
1096
|
mesh.userData.labelObject = label;
|
|
1017
1097
|
mesh.userData.labelOffset = new THREE.Vector3(0, 3.8, 0);
|
|
@@ -1116,13 +1196,15 @@ var updateExistingNodeVisuals = (state, updatedNode) => {
|
|
|
1116
1196
|
const size = updatedNode.size || "medium";
|
|
1117
1197
|
const scale = NODE_SCALE_FACTORS[size] || 1;
|
|
1118
1198
|
existingMesh.scale.set(scale, scale, scale);
|
|
1119
|
-
|
|
1199
|
+
const oldText = existingMesh.userData.is_quest && existingMesh.userData.raw_title ? existingMesh.userData.raw_title : existingMesh.userData.name;
|
|
1200
|
+
const newText = updatedNode.is_quest && updatedNode.raw_title ? updatedNode.raw_title : updatedNode.name;
|
|
1201
|
+
if (oldText !== newText) {
|
|
1120
1202
|
const oldLabelToDispose = existingMesh.userData.labelObject;
|
|
1121
1203
|
if (oldLabelToDispose && state.graphGroup) {
|
|
1122
1204
|
state.graphGroup.remove(oldLabelToDispose);
|
|
1123
1205
|
if (oldLabelToDispose.material) oldLabelToDispose.material.dispose();
|
|
1124
1206
|
}
|
|
1125
|
-
const newLabel = createTextSprite(
|
|
1207
|
+
const newLabel = createTextSprite(newText || "");
|
|
1126
1208
|
newLabel.name = "label";
|
|
1127
1209
|
existingMesh.userData.labelObject = newLabel;
|
|
1128
1210
|
if (state.graphGroup) {
|
|
@@ -7967,7 +8049,7 @@ function InSceneVersionForm({
|
|
|
7967
8049
|
// src/components/InSceneQuestForm.jsx
|
|
7968
8050
|
var import_react16 = __toESM(require("react"));
|
|
7969
8051
|
var import_fi14 = require("react-icons/fi");
|
|
7970
|
-
var
|
|
8052
|
+
var QUEST_STATUS_COLORS2 = {
|
|
7971
8053
|
"Backlog": "#64748b",
|
|
7972
8054
|
"In Progress": "#eab308",
|
|
7973
8055
|
"Review": "#a855f7",
|
|
@@ -8052,7 +8134,7 @@ function InSceneQuestForm({
|
|
|
8052
8134
|
raw_title: name.trim(),
|
|
8053
8135
|
// Salva o título puro como fallback ou metadado útil
|
|
8054
8136
|
type: types,
|
|
8055
|
-
color:
|
|
8137
|
+
color: QUEST_STATUS_COLORS2[status],
|
|
8056
8138
|
status,
|
|
8057
8139
|
size,
|
|
8058
8140
|
intensity,
|
|
@@ -8078,7 +8160,7 @@ function InSceneQuestForm({
|
|
|
8078
8160
|
onContextMenu: swallow,
|
|
8079
8161
|
onDoubleClick: swallow
|
|
8080
8162
|
},
|
|
8081
|
-
/* @__PURE__ */ import_react16.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${
|
|
8163
|
+
/* @__PURE__ */ import_react16.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS2[status]}, transparent)` } }),
|
|
8082
8164
|
/* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react16.default.createElement("div", null, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova quest")), /* @__PURE__ */ import_react16.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, "Criar Quest")), /* @__PURE__ */ import_react16.default.createElement(
|
|
8083
8165
|
"button",
|
|
8084
8166
|
{
|
|
@@ -8099,7 +8181,7 @@ function InSceneQuestForm({
|
|
|
8099
8181
|
onChange: (e) => {
|
|
8100
8182
|
const val = e.target.value;
|
|
8101
8183
|
setName(val);
|
|
8102
|
-
onNameChange == null ? void 0 : onNameChange(
|
|
8184
|
+
onNameChange == null ? void 0 : onNameChange(val || "Nova Quest");
|
|
8103
8185
|
},
|
|
8104
8186
|
className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60"
|
|
8105
8187
|
}
|
|
@@ -8110,20 +8192,20 @@ function InSceneQuestForm({
|
|
|
8110
8192
|
onClick: () => setIsStatusDropdownOpen(!isStatusDropdownOpen),
|
|
8111
8193
|
className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 hover:border-white/20 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 transition-colors flex items-center justify-between"
|
|
8112
8194
|
},
|
|
8113
|
-
/* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor:
|
|
8195
|
+
/* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor: QUEST_STATUS_COLORS2[status] } }), /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-slate-200 font-medium" }, status)),
|
|
8114
8196
|
/* @__PURE__ */ import_react16.default.createElement(import_fi14.FiChevronDown, { className: `text-slate-400 transition-transform duration-200 ${isStatusDropdownOpen ? "rotate-180" : ""}` })
|
|
8115
|
-
), isStatusDropdownOpen && /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ import_react16.default.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(
|
|
8197
|
+
), isStatusDropdownOpen && /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ import_react16.default.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(QUEST_STATUS_COLORS2).map((s) => /* @__PURE__ */ import_react16.default.createElement(
|
|
8116
8198
|
"li",
|
|
8117
8199
|
{
|
|
8118
8200
|
key: s,
|
|
8119
8201
|
onClick: () => {
|
|
8120
8202
|
setStatus(s);
|
|
8121
8203
|
setIsStatusDropdownOpen(false);
|
|
8122
|
-
onColorChange == null ? void 0 : onColorChange(
|
|
8204
|
+
onColorChange == null ? void 0 : onColorChange(QUEST_STATUS_COLORS2[s]);
|
|
8123
8205
|
},
|
|
8124
8206
|
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${status === s ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
8125
8207
|
},
|
|
8126
|
-
/* @__PURE__ */ import_react16.default.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor:
|
|
8208
|
+
/* @__PURE__ */ import_react16.default.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS2[s] } }),
|
|
8127
8209
|
s
|
|
8128
8210
|
)))))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react16.default.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 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ import_react16.default.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiX, { size: 12 })))), /* @__PURE__ */ import_react16.default.createElement(
|
|
8129
8211
|
"input",
|
|
@@ -8679,7 +8761,7 @@ function NodeDetailsPanel({
|
|
|
8679
8761
|
// src/components/QuestDetailsPanel.jsx
|
|
8680
8762
|
var import_react18 = __toESM(require("react"));
|
|
8681
8763
|
var import_fi16 = require("react-icons/fi");
|
|
8682
|
-
var
|
|
8764
|
+
var QUEST_STATUS_COLORS3 = {
|
|
8683
8765
|
"Backlog": "#64748b",
|
|
8684
8766
|
"In Progress": "#eab308",
|
|
8685
8767
|
"Review": "#a855f7",
|
|
@@ -8793,7 +8875,7 @@ function QuestDetailsPanel({
|
|
|
8793
8875
|
};
|
|
8794
8876
|
const handleStatusChange = (newStatus) => {
|
|
8795
8877
|
setStatus(newStatus);
|
|
8796
|
-
const newColor =
|
|
8878
|
+
const newColor = QUEST_STATUS_COLORS3[newStatus];
|
|
8797
8879
|
onColorChange == null ? void 0 : onColorChange(node.id, newColor);
|
|
8798
8880
|
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, status: newStatus, color: newColor });
|
|
8799
8881
|
};
|
|
@@ -8866,7 +8948,7 @@ function QuestDetailsPanel({
|
|
|
8866
8948
|
raw_title: currentRawTitle.trim(),
|
|
8867
8949
|
// Salva o título simples
|
|
8868
8950
|
type: currentTypes,
|
|
8869
|
-
color:
|
|
8951
|
+
color: QUEST_STATUS_COLORS3[currentStatus],
|
|
8870
8952
|
status: currentStatus,
|
|
8871
8953
|
size,
|
|
8872
8954
|
description: currentDescription,
|
|
@@ -8937,7 +9019,7 @@ function QuestDetailsPanel({
|
|
|
8937
9019
|
onImageClick: handleImageClickFromText,
|
|
8938
9020
|
onSaveDescription: handleSaveDescriptionInline
|
|
8939
9021
|
}
|
|
8940
|
-
) : /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${
|
|
9022
|
+
) : /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS3[status]}, transparent)` } }), /* @__PURE__ */ import_react18.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react18.default.createElement("div", null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ import_react18.default.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__ */ import_react18.default.createElement(import_fi16.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiLink, { size: 12 }))), /* @__PURE__ */ import_react18.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, standardizedName || (node == null ? void 0 : node.name))), /* @__PURE__ */ import_react18.default.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__ */ import_react18.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "T\xEDtulo da Quest"), /* @__PURE__ */ import_react18.default.createElement(
|
|
8941
9023
|
"input",
|
|
8942
9024
|
{
|
|
8943
9025
|
type: "text",
|
|
@@ -8954,9 +9036,9 @@ function QuestDetailsPanel({
|
|
|
8954
9036
|
disabled: !canEdit,
|
|
8955
9037
|
className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 transition-colors flex items-center justify-between ${canEdit ? "hover:border-white/20 focus:ring-2 focus:ring-indigo-400/60 cursor-pointer" : "cursor-default opacity-80"}`
|
|
8956
9038
|
},
|
|
8957
|
-
/* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor:
|
|
9039
|
+
/* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor: QUEST_STATUS_COLORS3[status] } }), /* @__PURE__ */ import_react18.default.createElement("span", { className: "text-slate-200 font-medium" }, status)),
|
|
8958
9040
|
canEdit && /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiChevronDown, { className: `text-slate-400 transition-transform duration-200 ${isStatusDropdownOpen ? "rotate-180" : ""}` })
|
|
8959
|
-
), isStatusDropdownOpen && canEdit && /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ import_react18.default.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(
|
|
9041
|
+
), isStatusDropdownOpen && canEdit && /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ import_react18.default.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(QUEST_STATUS_COLORS3).map((s) => /* @__PURE__ */ import_react18.default.createElement(
|
|
8960
9042
|
"li",
|
|
8961
9043
|
{
|
|
8962
9044
|
key: s,
|
|
@@ -8966,7 +9048,7 @@ function QuestDetailsPanel({
|
|
|
8966
9048
|
},
|
|
8967
9049
|
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${status === s ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
8968
9050
|
},
|
|
8969
|
-
/* @__PURE__ */ import_react18.default.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor:
|
|
9051
|
+
/* @__PURE__ */ import_react18.default.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS3[s] } }),
|
|
8970
9052
|
s
|
|
8971
9053
|
)))))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react18.default.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__ */ import_react18.default.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, canEdit && t !== "quest" && /* @__PURE__ */ import_react18.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiX, { size: 12 })))), canEdit && /* @__PURE__ */ import_react18.default.createElement(
|
|
8972
9054
|
"input",
|
|
@@ -11852,7 +11934,9 @@ function XViewScene({
|
|
|
11852
11934
|
if (oldLabel.material.map) oldLabel.material.map.dispose();
|
|
11853
11935
|
oldLabel.material.dispose();
|
|
11854
11936
|
}
|
|
11855
|
-
const
|
|
11937
|
+
const isQuest = mesh.userData.is_quest;
|
|
11938
|
+
const displayText = isQuest && newRawTitle !== void 0 ? newRawTitle : newName;
|
|
11939
|
+
const newLabel = createTextSprite(displayText || "");
|
|
11856
11940
|
graphGroup.add(newLabel);
|
|
11857
11941
|
mesh.userData.labelObject = newLabel;
|
|
11858
11942
|
mesh.userData.name = newName;
|
|
@@ -12033,15 +12117,14 @@ function XViewScene({
|
|
|
12033
12117
|
graphDataRef.current[sceneConfigId2] = { nodes: [], links: [] };
|
|
12034
12118
|
}
|
|
12035
12119
|
graphDataRef.current[sceneConfigId2].nodes.push(newNode);
|
|
12036
|
-
sceneDataRef2.current.nodes.push(newNode);
|
|
12037
12120
|
const sceneFileData = {
|
|
12038
12121
|
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
12039
12122
|
nodes: sceneDataRef2.current.nodes,
|
|
12123
|
+
// Permanece intacto, como estava no último save de cena inicial
|
|
12040
12124
|
links: sceneDataRef2.current.links,
|
|
12041
12125
|
quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
|
|
12042
12126
|
quest_links: graphDataRef.current[sceneConfigId2].links,
|
|
12043
12127
|
quest_counter: currentCounter + 1
|
|
12044
|
-
// NOVO: Incrementa o contador nos metadados
|
|
12045
12128
|
};
|
|
12046
12129
|
try {
|
|
12047
12130
|
await actions.save_view_data(sceneSaveUrl2, sceneFileData);
|
package/dist/index.mjs
CHANGED
|
@@ -72,6 +72,13 @@ function defineAbilityFor(role) {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
// src/components/ContextMenu.jsx
|
|
75
|
+
var QUEST_STATUS_COLORS = {
|
|
76
|
+
"Backlog": "#64748b",
|
|
77
|
+
"In Progress": "#eab308",
|
|
78
|
+
"Review": "#a855f7",
|
|
79
|
+
"Done": "#22c55e"
|
|
80
|
+
};
|
|
81
|
+
var QUEST_STATUSES = ["Backlog", "In Progress", "Review", "Done"];
|
|
75
82
|
function ContextMenu({
|
|
76
83
|
data,
|
|
77
84
|
userRole,
|
|
@@ -92,19 +99,21 @@ function ContextMenu({
|
|
|
92
99
|
onFocusNode,
|
|
93
100
|
onClose
|
|
94
101
|
}) {
|
|
95
|
-
var _a, _b;
|
|
102
|
+
var _a, _b, _c;
|
|
96
103
|
const menuRef = useRef(null);
|
|
97
104
|
const [menuPos, setMenuPos] = useState({ left: 0, top: 0 });
|
|
98
105
|
const [menuView, setMenuView] = useState("main");
|
|
99
106
|
const [selectedAncestry, setSelectedAncestry] = useState(null);
|
|
100
107
|
const [versionSubMenu, setVersionSubMenu] = useState(null);
|
|
101
108
|
const [isLinkCopied, setIsLinkCopied] = useState(false);
|
|
109
|
+
const [selectedQuestStatus, setSelectedQuestStatus] = useState(null);
|
|
102
110
|
const ability = useMemo(() => defineAbilityFor(userRole), [userRole]);
|
|
103
111
|
useEffect(() => {
|
|
104
112
|
if (data.visible) {
|
|
105
113
|
setMenuView("main");
|
|
106
114
|
setSelectedAncestry(null);
|
|
107
115
|
setVersionSubMenu(null);
|
|
116
|
+
setSelectedQuestStatus(null);
|
|
108
117
|
}
|
|
109
118
|
}, [data.visible, (_a = data.nodeData) == null ? void 0 : _a.id]);
|
|
110
119
|
useLayoutEffect(() => {
|
|
@@ -119,7 +128,7 @@ function ContextMenu({
|
|
|
119
128
|
if (left + w + 8 > vw) left = Math.max(8, vw - w - 8);
|
|
120
129
|
if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
|
|
121
130
|
setMenuPos({ left, top });
|
|
122
|
-
}, [data, menuView, versionSubMenu]);
|
|
131
|
+
}, [data, menuView, versionSubMenu, selectedQuestStatus]);
|
|
123
132
|
useEffect(() => {
|
|
124
133
|
if (!data.visible) return;
|
|
125
134
|
const handleClickOutside = (e) => {
|
|
@@ -162,7 +171,16 @@ function ContextMenu({
|
|
|
162
171
|
var _a2;
|
|
163
172
|
return c.targetNode && !(((_a2 = c.targetNode.version_node) == null ? void 0 : _a2.is_version) && String(c.targetNode.version_node.parent_node) === String(data.nodeData.id));
|
|
164
173
|
});
|
|
165
|
-
const
|
|
174
|
+
const isCurrentNodeQuest = ((_c = data.nodeData) == null ? void 0 : _c.is_quest) === true;
|
|
175
|
+
const commonConnections = isCurrentNodeQuest ? connections : connections.filter((c) => {
|
|
176
|
+
var _a2;
|
|
177
|
+
return !((_a2 = c.targetNode) == null ? void 0 : _a2.is_quest);
|
|
178
|
+
});
|
|
179
|
+
const questConnections = isCurrentNodeQuest ? [] : connections.filter((c) => {
|
|
180
|
+
var _a2;
|
|
181
|
+
return (_a2 = c.targetNode) == null ? void 0 : _a2.is_quest;
|
|
182
|
+
});
|
|
183
|
+
const groupedConnections = commonConnections.reduce((acc, conn) => {
|
|
166
184
|
var _a2;
|
|
167
185
|
const { targetNode } = conn;
|
|
168
186
|
const groupingKey = ((_a2 = targetNode.version_node) == null ? void 0 : _a2.is_version) ? targetNode.version_node.parent_node : targetNode.id;
|
|
@@ -198,6 +216,20 @@ function ContextMenu({
|
|
|
198
216
|
};
|
|
199
217
|
}
|
|
200
218
|
}).filter(Boolean);
|
|
219
|
+
const questsByStatus = {
|
|
220
|
+
"Backlog": [],
|
|
221
|
+
"In Progress": [],
|
|
222
|
+
"Review": [],
|
|
223
|
+
"Done": []
|
|
224
|
+
};
|
|
225
|
+
questConnections.forEach((conn) => {
|
|
226
|
+
const status = conn.targetNode.status || "Backlog";
|
|
227
|
+
if (questsByStatus[status]) {
|
|
228
|
+
questsByStatus[status].push(conn);
|
|
229
|
+
} else {
|
|
230
|
+
questsByStatus["Backlog"].push(conn);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
201
233
|
const availableAncestries = (ancestryData || []).filter(
|
|
202
234
|
(ancestry) => String(ancestry.ancestral_node) === String(data.nodeData.id)
|
|
203
235
|
);
|
|
@@ -255,7 +287,7 @@ function ContextMenu({
|
|
|
255
287
|
const canCreateVersion = ability.can("create", "Versioning");
|
|
256
288
|
const canReadVersion = ability.can("read", "Versioning");
|
|
257
289
|
const shouldShowVersioningBtn = canCreateVersion || canReadVersion && hasVersions;
|
|
258
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ React.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1" }, ability.can("create", "Connection") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__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: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ React.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ React.createElement("span", null, "Conectar")), ability.can("create", "Node") && !((_a2 = data.nodeData) == null ? void 0 : _a2.is_quest) && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__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: "10" }), /* @__PURE__ */ React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ React.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ React.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar 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: "M10 20.5c.5-.5.8-1.2.8-2s-.3-1.5-.8-2c-.5-.5-1.2-.8-2-.8s-1.5.3-2 .8c-.5.5-.8 1.2-.8 2s.3 1.5.8 2c.5.5 1.2-.8 2 .8s1.5-.3 2-.8Z" }), /* @__PURE__ */ React.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ React.createElement("path", { d: "M14 3.5c.5.5.8 1.2.8 2s-.3 1.5-.8 2c-.5-.5-1.2-.8-2 .8s1.5.3-2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ React.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ React.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__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: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ React.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ React.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ React.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ React.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__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 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z" }), /* @__PURE__ */ React.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ React.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ React.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => {
|
|
290
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ React.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1" }, ability.can("create", "Connection") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__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: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ React.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ React.createElement("span", null, "Conectar")), ability.can("create", "Node") && !((_a2 = data.nodeData) == null ? void 0 : _a2.is_quest) && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__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: "10" }), /* @__PURE__ */ React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ React.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ React.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar 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: "M10 20.5c.5-.5.8-1.2.8-2s-.3-1.5-.8-2c-.5-.5-1.2-.8-2-.8s-1.5.3-2 .8c-.5.5-.8 1.2-.8 2s.3 1.5.8 2c.5.5 1.2-.8 2 .8s1.5-.3 2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ React.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ React.createElement("path", { d: "M14 3.5c.5.5.8 1.2.8 2s-.3 1.5-.8 2c-.5-.5-1.2-.8-2 .8s1.5.3-2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ React.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ React.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__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: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ React.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ React.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ React.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ React.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__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 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z" }), /* @__PURE__ */ React.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ React.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ React.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => {
|
|
259
291
|
onFocusNode == null ? void 0 : onFocusNode(data.nodeData);
|
|
260
292
|
onClose();
|
|
261
293
|
}, className: baseButtonClass, title: "Focar na c\xE2mera" }, /* @__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: "10" }), /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "3" })), /* @__PURE__ */ React.createElement("span", null, "Focar neste Node")), /* @__PURE__ */ React.createElement("button", { onClick: (e) => handleCopyLink(e, data.nodeData), className: baseButtonClass, title: "Copiar Link para Compartilhar" }, isLinkCopied ? /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#4ade80", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("polyline", { points: "20 6 9 17 4 12" })) : /* @__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: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ React.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ React.createElement("span", { className: isLinkCopied ? "text-green-400" : "" }, isLinkCopied ? "Copiado!" : "Copiar Link")), ability.can("dismiss", "Node") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("button", { onClick: () => onDismissNode == null ? void 0 : onDismissNode(data.nodeData), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__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: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ React.createElement("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }), /* @__PURE__ */ React.createElement("path", { d: "M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }), /* @__PURE__ */ React.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ React.createElement("span", null, "Dismiss")), /* @__PURE__ */ React.createElement("button", { onClick: () => onDismissOtherNodes == null ? void 0 : onDismissOtherNodes(data.nodeData), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__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: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ React.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ React.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ React.createElement("span", null, "Dismiss other nodes"))), ability.can("delete", "Node") && /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("deleteConfirmation"), className: deleteButtonClass, title: "Excluir Node" }, /* @__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("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ React.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ React.createElement("span", null, "Excluir Node"))));
|
|
@@ -282,7 +314,7 @@ function ContextMenu({
|
|
|
282
314
|
}
|
|
283
315
|
const totalItems = availableAncestries.length + finalRenderableConnections.length;
|
|
284
316
|
const isScrollable = totalItems > 10;
|
|
285
|
-
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")),
|
|
317
|
+
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-4" : "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(
|
|
286
318
|
"button",
|
|
287
319
|
{
|
|
288
320
|
key: anc.ancestry_id,
|
|
@@ -292,7 +324,17 @@ function ContextMenu({
|
|
|
292
324
|
},
|
|
293
325
|
/* @__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" })),
|
|
294
326
|
/* @__PURE__ */ React.createElement("span", { className: "flex-1 truncate" }, anc.name || `Ancestralidade #${anc.ancestry_id.substring(0, 8)}`)
|
|
295
|
-
)),
|
|
327
|
+
))), questConnections.length > 0 && /* @__PURE__ */ React.createElement("div", { className: `flex flex-col gap-1 ${finalRenderableConnections.length > 0 ? "mb-4" : "mb-2"}` }, /* @__PURE__ */ React.createElement("div", { className: "px-2 py-1 text-[11px] uppercase tracking-wider text-sky-400/90" }, "Quests Relacionadas"), /* @__PURE__ */ React.createElement(
|
|
328
|
+
"button",
|
|
329
|
+
{
|
|
330
|
+
onClick: () => setMenuView("quest_statuses"),
|
|
331
|
+
className: baseButtonClass,
|
|
332
|
+
title: "Ver Quests Conectadas"
|
|
333
|
+
},
|
|
334
|
+
/* @__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-sky-400" }, /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "6" }), /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "2" })),
|
|
335
|
+
/* @__PURE__ */ React.createElement("span", { className: "flex-1 truncate" }, "Status das Quests"),
|
|
336
|
+
/* @__PURE__ */ React.createElement("span", { className: "text-xs px-2 py-0.5 bg-sky-500/20 text-sky-200 rounded-full" }, questConnections.length)
|
|
337
|
+
)), finalRenderableConnections.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React.createElement("div", { className: "px-2 py-1 text-[11px] uppercase tracking-wider text-indigo-400/90 border-t border-white/5 pt-2" }, "Outros Nodes"), finalRenderableConnections.map((group) => {
|
|
296
338
|
if (group.isVersionGroup) {
|
|
297
339
|
return /* @__PURE__ */ React.createElement(
|
|
298
340
|
"button",
|
|
@@ -322,6 +364,43 @@ function ContextMenu({
|
|
|
322
364
|
}
|
|
323
365
|
}))));
|
|
324
366
|
};
|
|
367
|
+
const renderQuestStatusesView = () => {
|
|
368
|
+
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("connections"), 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" }, "Status das Quests"))), /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1" }, QUEST_STATUSES.map((status) => {
|
|
369
|
+
const count = questsByStatus[status].length;
|
|
370
|
+
const color = QUEST_STATUS_COLORS[status];
|
|
371
|
+
return /* @__PURE__ */ React.createElement(
|
|
372
|
+
"button",
|
|
373
|
+
{
|
|
374
|
+
key: status,
|
|
375
|
+
onClick: () => {
|
|
376
|
+
if (count > 0) {
|
|
377
|
+
setSelectedQuestStatus(status);
|
|
378
|
+
setMenuView("quest_list");
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
className: `${baseButtonClass} ${count === 0 ? "opacity-50 cursor-default hover:bg-transparent hover:text-slate-200" : ""}`
|
|
382
|
+
},
|
|
383
|
+
/* @__PURE__ */ React.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor: color } }),
|
|
384
|
+
/* @__PURE__ */ React.createElement("span", { className: "flex-1 truncate" }, status),
|
|
385
|
+
count > 0 && /* @__PURE__ */ React.createElement("span", { className: "text-xs px-2 py-0.5 bg-white/10 rounded-full" }, count)
|
|
386
|
+
);
|
|
387
|
+
})));
|
|
388
|
+
};
|
|
389
|
+
const renderQuestListView = () => {
|
|
390
|
+
const quests = questsByStatus[selectedQuestStatus] || [];
|
|
391
|
+
const isScrollable = quests.length > 10;
|
|
392
|
+
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("quest_statuses"), 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: `Quests: ${selectedQuestStatus}` }, "Quests: ", selectedQuestStatus)), quests.length > 0 && /* @__PURE__ */ React.createElement("button", { onClick: () => handleExpandAndClose(quests.map((q) => q.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" : ""}` }, quests.map((conn) => /* @__PURE__ */ React.createElement(
|
|
393
|
+
"button",
|
|
394
|
+
{
|
|
395
|
+
key: conn.targetNode.id,
|
|
396
|
+
onClick: () => handleConnectionClick({ links: [conn.link] }),
|
|
397
|
+
className: baseButtonClass,
|
|
398
|
+
title: `Expandir Quest ${conn.targetNode.name}`
|
|
399
|
+
},
|
|
400
|
+
/* @__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: "opacity-70" }, /* @__PURE__ */ React.createElement("polyline", { points: "13 17 18 12 13 7" }), /* @__PURE__ */ React.createElement("polyline", { points: "6 17 11 12 6 7" })),
|
|
401
|
+
/* @__PURE__ */ React.createElement("span", { className: "flex-1 truncate" }, conn.targetNode.name)
|
|
402
|
+
))));
|
|
403
|
+
};
|
|
325
404
|
const renderAncestryActionsView = () => {
|
|
326
405
|
const ancestryTitle = (selectedAncestry == null ? void 0 : selectedAncestry.name) || `Ancestralidade #${selectedAncestry == null ? void 0 : selectedAncestry.ancestry_id.substring(0, 8)}`;
|
|
327
406
|
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: () => {
|
|
@@ -383,7 +462,7 @@ function ContextMenu({
|
|
|
383
462
|
onDoubleClick: swallow
|
|
384
463
|
},
|
|
385
464
|
/* @__PURE__ */ React.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
|
|
386
|
-
/* @__PURE__ */ React.createElement("div", { className: "p-1.5" }, menuView === "main" && renderMainView(), menuView === "connections" && renderConnectionsView(), menuView === "ancestryActions" && renderAncestryActionsView(), menuView === "versioning" && renderVersioningView(), menuView === "deleteConfirmation" && renderDeleteConfirmationView())
|
|
465
|
+
/* @__PURE__ */ React.createElement("div", { className: "p-1.5" }, menuView === "main" && renderMainView(), menuView === "connections" && renderConnectionsView(), menuView === "ancestryActions" && renderAncestryActionsView(), menuView === "versioning" && renderVersioningView(), menuView === "quest_statuses" && renderQuestStatusesView(), menuView === "quest_list" && renderQuestListView(), menuView === "deleteConfirmation" && renderDeleteConfirmationView())
|
|
387
466
|
);
|
|
388
467
|
}
|
|
389
468
|
|
|
@@ -967,7 +1046,8 @@ var createNodeMesh = (nodeData, position, glowTexture) => {
|
|
|
967
1046
|
const size = nodeData.size || "medium";
|
|
968
1047
|
const scale = NODE_SCALE_FACTORS[size] || 1;
|
|
969
1048
|
mesh.scale.set(scale, scale, scale);
|
|
970
|
-
const
|
|
1049
|
+
const labelText = nodeData.is_quest && nodeData.raw_title ? nodeData.raw_title : nodeData.name;
|
|
1050
|
+
const label = createTextSprite(labelText);
|
|
971
1051
|
label.name = "label";
|
|
972
1052
|
mesh.userData.labelObject = label;
|
|
973
1053
|
mesh.userData.labelOffset = new THREE.Vector3(0, 3.8, 0);
|
|
@@ -1072,13 +1152,15 @@ var updateExistingNodeVisuals = (state, updatedNode) => {
|
|
|
1072
1152
|
const size = updatedNode.size || "medium";
|
|
1073
1153
|
const scale = NODE_SCALE_FACTORS[size] || 1;
|
|
1074
1154
|
existingMesh.scale.set(scale, scale, scale);
|
|
1075
|
-
|
|
1155
|
+
const oldText = existingMesh.userData.is_quest && existingMesh.userData.raw_title ? existingMesh.userData.raw_title : existingMesh.userData.name;
|
|
1156
|
+
const newText = updatedNode.is_quest && updatedNode.raw_title ? updatedNode.raw_title : updatedNode.name;
|
|
1157
|
+
if (oldText !== newText) {
|
|
1076
1158
|
const oldLabelToDispose = existingMesh.userData.labelObject;
|
|
1077
1159
|
if (oldLabelToDispose && state.graphGroup) {
|
|
1078
1160
|
state.graphGroup.remove(oldLabelToDispose);
|
|
1079
1161
|
if (oldLabelToDispose.material) oldLabelToDispose.material.dispose();
|
|
1080
1162
|
}
|
|
1081
|
-
const newLabel = createTextSprite(
|
|
1163
|
+
const newLabel = createTextSprite(newText || "");
|
|
1082
1164
|
newLabel.name = "label";
|
|
1083
1165
|
existingMesh.userData.labelObject = newLabel;
|
|
1084
1166
|
if (state.graphGroup) {
|
|
@@ -7954,7 +8036,7 @@ function InSceneVersionForm({
|
|
|
7954
8036
|
// src/components/InSceneQuestForm.jsx
|
|
7955
8037
|
import React15, { useState as useState16, useRef as useRef12 } from "react";
|
|
7956
8038
|
import { FiPlus as FiPlus5, FiCheck as FiCheck9, FiEdit2 as FiEdit26, FiTarget, FiX as FiX4, FiChevronDown as FiChevronDown5 } from "react-icons/fi";
|
|
7957
|
-
var
|
|
8039
|
+
var QUEST_STATUS_COLORS2 = {
|
|
7958
8040
|
"Backlog": "#64748b",
|
|
7959
8041
|
"In Progress": "#eab308",
|
|
7960
8042
|
"Review": "#a855f7",
|
|
@@ -8039,7 +8121,7 @@ function InSceneQuestForm({
|
|
|
8039
8121
|
raw_title: name.trim(),
|
|
8040
8122
|
// Salva o título puro como fallback ou metadado útil
|
|
8041
8123
|
type: types,
|
|
8042
|
-
color:
|
|
8124
|
+
color: QUEST_STATUS_COLORS2[status],
|
|
8043
8125
|
status,
|
|
8044
8126
|
size,
|
|
8045
8127
|
intensity,
|
|
@@ -8065,7 +8147,7 @@ function InSceneQuestForm({
|
|
|
8065
8147
|
onContextMenu: swallow,
|
|
8066
8148
|
onDoubleClick: swallow
|
|
8067
8149
|
},
|
|
8068
|
-
/* @__PURE__ */ React15.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${
|
|
8150
|
+
/* @__PURE__ */ React15.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS2[status]}, transparent)` } }),
|
|
8069
8151
|
/* @__PURE__ */ React15.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React15.createElement(FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React15.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova quest")), /* @__PURE__ */ React15.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, "Criar Quest")), /* @__PURE__ */ React15.createElement(
|
|
8070
8152
|
"button",
|
|
8071
8153
|
{
|
|
@@ -8086,7 +8168,7 @@ function InSceneQuestForm({
|
|
|
8086
8168
|
onChange: (e) => {
|
|
8087
8169
|
const val = e.target.value;
|
|
8088
8170
|
setName(val);
|
|
8089
|
-
onNameChange == null ? void 0 : onNameChange(
|
|
8171
|
+
onNameChange == null ? void 0 : onNameChange(val || "Nova Quest");
|
|
8090
8172
|
},
|
|
8091
8173
|
className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60"
|
|
8092
8174
|
}
|
|
@@ -8097,20 +8179,20 @@ function InSceneQuestForm({
|
|
|
8097
8179
|
onClick: () => setIsStatusDropdownOpen(!isStatusDropdownOpen),
|
|
8098
8180
|
className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 hover:border-white/20 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 transition-colors flex items-center justify-between"
|
|
8099
8181
|
},
|
|
8100
|
-
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor:
|
|
8182
|
+
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor: QUEST_STATUS_COLORS2[status] } }), /* @__PURE__ */ React15.createElement("span", { className: "text-slate-200 font-medium" }, status)),
|
|
8101
8183
|
/* @__PURE__ */ React15.createElement(FiChevronDown5, { className: `text-slate-400 transition-transform duration-200 ${isStatusDropdownOpen ? "rotate-180" : ""}` })
|
|
8102
|
-
), isStatusDropdownOpen && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ React15.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(
|
|
8184
|
+
), isStatusDropdownOpen && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ React15.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(QUEST_STATUS_COLORS2).map((s) => /* @__PURE__ */ React15.createElement(
|
|
8103
8185
|
"li",
|
|
8104
8186
|
{
|
|
8105
8187
|
key: s,
|
|
8106
8188
|
onClick: () => {
|
|
8107
8189
|
setStatus(s);
|
|
8108
8190
|
setIsStatusDropdownOpen(false);
|
|
8109
|
-
onColorChange == null ? void 0 : onColorChange(
|
|
8191
|
+
onColorChange == null ? void 0 : onColorChange(QUEST_STATUS_COLORS2[s]);
|
|
8110
8192
|
},
|
|
8111
8193
|
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${status === s ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
8112
8194
|
},
|
|
8113
|
-
/* @__PURE__ */ React15.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor:
|
|
8195
|
+
/* @__PURE__ */ React15.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS2[s] } }),
|
|
8114
8196
|
s
|
|
8115
8197
|
)))))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ React15.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 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ React15.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ React15.createElement(FiX4, { size: 12 })))), /* @__PURE__ */ React15.createElement(
|
|
8116
8198
|
"input",
|
|
@@ -8666,7 +8748,7 @@ function NodeDetailsPanel({
|
|
|
8666
8748
|
// src/components/QuestDetailsPanel.jsx
|
|
8667
8749
|
import React17, { useState as useState18, useEffect as useEffect16, useRef as useRef14 } from "react";
|
|
8668
8750
|
import { FiPlus as FiPlus7, FiX as FiX6, FiCheck as FiCheck11, FiEdit2 as FiEdit28, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4, FiLink as FiLink6, FiTarget as FiTarget2, FiChevronDown as FiChevronDown6 } from "react-icons/fi";
|
|
8669
|
-
var
|
|
8751
|
+
var QUEST_STATUS_COLORS3 = {
|
|
8670
8752
|
"Backlog": "#64748b",
|
|
8671
8753
|
"In Progress": "#eab308",
|
|
8672
8754
|
"Review": "#a855f7",
|
|
@@ -8780,7 +8862,7 @@ function QuestDetailsPanel({
|
|
|
8780
8862
|
};
|
|
8781
8863
|
const handleStatusChange = (newStatus) => {
|
|
8782
8864
|
setStatus(newStatus);
|
|
8783
|
-
const newColor =
|
|
8865
|
+
const newColor = QUEST_STATUS_COLORS3[newStatus];
|
|
8784
8866
|
onColorChange == null ? void 0 : onColorChange(node.id, newColor);
|
|
8785
8867
|
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, status: newStatus, color: newColor });
|
|
8786
8868
|
};
|
|
@@ -8853,7 +8935,7 @@ function QuestDetailsPanel({
|
|
|
8853
8935
|
raw_title: currentRawTitle.trim(),
|
|
8854
8936
|
// Salva o título simples
|
|
8855
8937
|
type: currentTypes,
|
|
8856
|
-
color:
|
|
8938
|
+
color: QUEST_STATUS_COLORS3[currentStatus],
|
|
8857
8939
|
status: currentStatus,
|
|
8858
8940
|
size,
|
|
8859
8941
|
description: currentDescription,
|
|
@@ -8924,7 +9006,7 @@ function QuestDetailsPanel({
|
|
|
8924
9006
|
onImageClick: handleImageClickFromText,
|
|
8925
9007
|
onSaveDescription: handleSaveDescriptionInline
|
|
8926
9008
|
}
|
|
8927
|
-
) : /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${
|
|
9009
|
+
) : /* @__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", null, /* @__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 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(
|
|
8928
9010
|
"input",
|
|
8929
9011
|
{
|
|
8930
9012
|
type: "text",
|
|
@@ -8941,9 +9023,9 @@ function QuestDetailsPanel({
|
|
|
8941
9023
|
disabled: !canEdit,
|
|
8942
9024
|
className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 transition-colors flex items-center justify-between ${canEdit ? "hover:border-white/20 focus:ring-2 focus:ring-indigo-400/60 cursor-pointer" : "cursor-default opacity-80"}`
|
|
8943
9025
|
},
|
|
8944
|
-
/* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React17.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor:
|
|
9026
|
+
/* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React17.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor: QUEST_STATUS_COLORS3[status] } }), /* @__PURE__ */ React17.createElement("span", { className: "text-slate-200 font-medium" }, status)),
|
|
8945
9027
|
canEdit && /* @__PURE__ */ React17.createElement(FiChevronDown6, { className: `text-slate-400 transition-transform duration-200 ${isStatusDropdownOpen ? "rotate-180" : ""}` })
|
|
8946
|
-
), isStatusDropdownOpen && canEdit && /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ React17.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(
|
|
9028
|
+
), isStatusDropdownOpen && canEdit && /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ React17.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(QUEST_STATUS_COLORS3).map((s) => /* @__PURE__ */ React17.createElement(
|
|
8947
9029
|
"li",
|
|
8948
9030
|
{
|
|
8949
9031
|
key: s,
|
|
@@ -8953,7 +9035,7 @@ function QuestDetailsPanel({
|
|
|
8953
9035
|
},
|
|
8954
9036
|
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${status === s ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
8955
9037
|
},
|
|
8956
|
-
/* @__PURE__ */ React17.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor:
|
|
9038
|
+
/* @__PURE__ */ React17.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS3[s] } }),
|
|
8957
9039
|
s
|
|
8958
9040
|
)))))), /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ React17.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__ */ React17.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, canEdit && t !== "quest" && /* @__PURE__ */ React17.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ React17.createElement(FiX6, { size: 12 })))), canEdit && /* @__PURE__ */ React17.createElement(
|
|
8959
9041
|
"input",
|
|
@@ -11852,7 +11934,9 @@ function XViewScene({
|
|
|
11852
11934
|
if (oldLabel.material.map) oldLabel.material.map.dispose();
|
|
11853
11935
|
oldLabel.material.dispose();
|
|
11854
11936
|
}
|
|
11855
|
-
const
|
|
11937
|
+
const isQuest = mesh.userData.is_quest;
|
|
11938
|
+
const displayText = isQuest && newRawTitle !== void 0 ? newRawTitle : newName;
|
|
11939
|
+
const newLabel = createTextSprite(displayText || "");
|
|
11856
11940
|
graphGroup.add(newLabel);
|
|
11857
11941
|
mesh.userData.labelObject = newLabel;
|
|
11858
11942
|
mesh.userData.name = newName;
|
|
@@ -12033,15 +12117,14 @@ function XViewScene({
|
|
|
12033
12117
|
graphDataRef.current[sceneConfigId2] = { nodes: [], links: [] };
|
|
12034
12118
|
}
|
|
12035
12119
|
graphDataRef.current[sceneConfigId2].nodes.push(newNode);
|
|
12036
|
-
sceneDataRef2.current.nodes.push(newNode);
|
|
12037
12120
|
const sceneFileData = {
|
|
12038
12121
|
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
12039
12122
|
nodes: sceneDataRef2.current.nodes,
|
|
12123
|
+
// Permanece intacto, como estava no último save de cena inicial
|
|
12040
12124
|
links: sceneDataRef2.current.links,
|
|
12041
12125
|
quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
|
|
12042
12126
|
quest_links: graphDataRef.current[sceneConfigId2].links,
|
|
12043
12127
|
quest_counter: currentCounter + 1
|
|
12044
|
-
// NOVO: Incrementa o contador nos metadados
|
|
12045
12128
|
};
|
|
12046
12129
|
try {
|
|
12047
12130
|
await actions.save_view_data(sceneSaveUrl2, sceneFileData);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lv-x-software-house/x_view",
|
|
3
|
-
"version": "1.2.4-dev.
|
|
3
|
+
"version": "1.2.4-dev.29",
|
|
4
4
|
"description": "Pacote privado contendo os componentes e lógica de renderização 3D do X View.",
|
|
5
5
|
"author": "iv.x - Engenharia de Software - ivxsoftwarehouse@gmail.com",
|
|
6
6
|
"license": "UNLICENSED",
|