@lv-x-software-house/x_view 1.2.1-dev.1 → 1.2.1-dev.10
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 +142 -15
- package/dist/index.mjs +208 -78
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -131,6 +131,7 @@ function ContextMenu({
|
|
|
131
131
|
const [menuView, setMenuView] = (0, import_react.useState)("main");
|
|
132
132
|
const [selectedAncestry, setSelectedAncestry] = (0, import_react.useState)(null);
|
|
133
133
|
const [versionSubMenu, setVersionSubMenu] = (0, import_react.useState)(null);
|
|
134
|
+
const [isLinkCopied, setIsLinkCopied] = (0, import_react.useState)(false);
|
|
134
135
|
const ability = (0, import_react.useMemo)(() => defineAbilityFor(userRole), [userRole]);
|
|
135
136
|
(0, import_react.useEffect)(() => {
|
|
136
137
|
if (data.visible) {
|
|
@@ -267,6 +268,20 @@ function ContextMenu({
|
|
|
267
268
|
return ((_a2 = node.version_node) == null ? void 0 : _a2.is_version) && String(node.version_node.parent_node) === String(data.nodeData.id);
|
|
268
269
|
}
|
|
269
270
|
).sort((a, b) => getYearFromDate(b.Date) - getYearFromDate(a.Date));
|
|
271
|
+
const handleCopyLink = (e, nodeData) => {
|
|
272
|
+
e.stopPropagation();
|
|
273
|
+
const baseUrl = window.location.origin + window.location.pathname;
|
|
274
|
+
const fullUrl = `${baseUrl}?focus=${nodeData.id}`;
|
|
275
|
+
navigator.clipboard.writeText(fullUrl).then(() => {
|
|
276
|
+
setIsLinkCopied(true);
|
|
277
|
+
setTimeout(() => {
|
|
278
|
+
setIsLinkCopied(false);
|
|
279
|
+
onClose();
|
|
280
|
+
}, 1500);
|
|
281
|
+
}).catch((err) => {
|
|
282
|
+
console.error("Erro ao copiar link:", err);
|
|
283
|
+
});
|
|
284
|
+
};
|
|
270
285
|
const renderMainView = () => {
|
|
271
286
|
const hasVersions = computedVersions.length > 0;
|
|
272
287
|
const canCreateVersion = ability.can("create", "Versioning");
|
|
@@ -275,7 +290,7 @@ function ContextMenu({
|
|
|
275
290
|
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" }, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => {
|
|
276
291
|
onFocusNode == null ? void 0 : onFocusNode(data.nodeData);
|
|
277
292
|
onClose();
|
|
278
|
-
}, 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")), 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") && /* @__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" }), 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: () => onDeleteNode == null ? void 0 : onDeleteNode(data.nodeData), 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"))));
|
|
293
|
+
}, 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")), 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") && /* @__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: (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: () => onDeleteNode == null ? void 0 : onDeleteNode(data.nodeData), 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"))));
|
|
279
294
|
};
|
|
280
295
|
const renderVersionSubMenuView = () => {
|
|
281
296
|
const group = versionSubMenu;
|
|
@@ -4533,6 +4548,8 @@ var ReadOnlyNodeItem = ({ nodeData, onViewSelect, highlightedPathIds = [], targe
|
|
|
4533
4548
|
function DescriptionReadModePanel({
|
|
4534
4549
|
title,
|
|
4535
4550
|
description,
|
|
4551
|
+
ancestryId,
|
|
4552
|
+
// <-- NOVO: Prop recebida do XViewScene
|
|
4536
4553
|
savedSections,
|
|
4537
4554
|
onBack,
|
|
4538
4555
|
onEdit,
|
|
@@ -4555,12 +4572,24 @@ function DescriptionReadModePanel({
|
|
|
4555
4572
|
abstractionTree = null,
|
|
4556
4573
|
onRenderAbstractionTree = null,
|
|
4557
4574
|
initialShowAbstraction = false
|
|
4558
|
-
// <--- NOVA PROP RECEBIDA
|
|
4559
4575
|
}) {
|
|
4560
4576
|
const [showProperties, setShowProperties] = (0, import_react7.useState)(false);
|
|
4561
4577
|
const [showAbstraction, setShowAbstraction] = (0, import_react7.useState)(false);
|
|
4562
4578
|
const [targetRenderNodeId, setTargetRenderNodeId] = (0, import_react7.useState)(null);
|
|
4563
|
-
import_react7.
|
|
4579
|
+
const [isLinkCopied, setIsLinkCopied] = (0, import_react7.useState)(false);
|
|
4580
|
+
const handleCopyLink = (e) => {
|
|
4581
|
+
e.stopPropagation();
|
|
4582
|
+
if (!ancestryId) return;
|
|
4583
|
+
const baseUrl = window.location.origin + window.location.pathname;
|
|
4584
|
+
const fullUrl = `${baseUrl}?ancestry=${ancestryId}`;
|
|
4585
|
+
navigator.clipboard.writeText(fullUrl).then(() => {
|
|
4586
|
+
setIsLinkCopied(true);
|
|
4587
|
+
setTimeout(() => setIsLinkCopied(false), 2e3);
|
|
4588
|
+
}).catch((err) => {
|
|
4589
|
+
console.error("Erro ao copiar link:", err);
|
|
4590
|
+
});
|
|
4591
|
+
};
|
|
4592
|
+
(0, import_react7.useEffect)(() => {
|
|
4564
4593
|
setShowAbstraction(initialShowAbstraction);
|
|
4565
4594
|
if (initialShowAbstraction) {
|
|
4566
4595
|
setShowProperties(false);
|
|
@@ -4649,7 +4678,15 @@ function DescriptionReadModePanel({
|
|
|
4649
4678
|
title: "Voltar"
|
|
4650
4679
|
},
|
|
4651
4680
|
/* @__PURE__ */ import_react7.default.createElement(import_fi6.FiArrowLeft, { size: 16 })
|
|
4652
|
-
), /* @__PURE__ */ import_react7.default.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ import_react7.default.createElement("
|
|
4681
|
+
), /* @__PURE__ */ import_react7.default.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react7.default.createElement("p", { className: "text-xs/relaxed text-slate-400 uppercase tracking-wider font-semibold" }, showAbstraction ? "Tree de Abstra\xE7\xE3o" : showProperties ? "Propriedades Adicionais" : "Modo de Leitura"), ancestryId && /* @__PURE__ */ import_react7.default.createElement(
|
|
4682
|
+
"button",
|
|
4683
|
+
{
|
|
4684
|
+
onClick: handleCopyLink,
|
|
4685
|
+
className: `p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-indigo-400"}`,
|
|
4686
|
+
title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Ancestralidade"
|
|
4687
|
+
},
|
|
4688
|
+
isLinkCopied ? /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react7.default.createElement(import_fi6.FiLink, { size: 12 })
|
|
4689
|
+
)), /* @__PURE__ */ import_react7.default.createElement("h2", { className: "text-lg sm:text-xl font-semibold tracking-tight text-white truncate", title }, title || "Sem T\xEDtulo"))), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-2 flex-shrink-0" }, hasCustomProps && /* @__PURE__ */ import_react7.default.createElement(
|
|
4653
4690
|
"button",
|
|
4654
4691
|
{
|
|
4655
4692
|
onClick: handleToggleProperties,
|
|
@@ -5176,6 +5213,20 @@ function CreateAncestryPanel({
|
|
|
5176
5213
|
currentAncestryId
|
|
5177
5214
|
} = ancestryMode;
|
|
5178
5215
|
const [isSaving, setIsSaving] = (0, import_react10.useState)(false);
|
|
5216
|
+
const [isLinkCopied, setIsLinkCopied] = (0, import_react10.useState)(false);
|
|
5217
|
+
const handleCopyLink = (e) => {
|
|
5218
|
+
e.stopPropagation();
|
|
5219
|
+
if (!currentAncestryId || currentAncestryId === "temp_root" || currentAncestryId === "temp_creating") {
|
|
5220
|
+
alert("Salve a ancestralidade primeiro para gerar um link.");
|
|
5221
|
+
return;
|
|
5222
|
+
}
|
|
5223
|
+
const baseUrl = window.location.origin + window.location.pathname;
|
|
5224
|
+
const fullUrl = `${baseUrl}?ancestry=${currentAncestryId}`;
|
|
5225
|
+
navigator.clipboard.writeText(fullUrl).then(() => {
|
|
5226
|
+
setIsLinkCopied(true);
|
|
5227
|
+
setTimeout(() => setIsLinkCopied(false), 2e3);
|
|
5228
|
+
}).catch((err) => console.error("Erro ao copiar link:", err));
|
|
5229
|
+
};
|
|
5179
5230
|
const [isPickerOpen, setIsPickerOpen] = (0, import_react10.useState)(false);
|
|
5180
5231
|
const [customProps, setCustomProps] = (0, import_react10.useState)([]);
|
|
5181
5232
|
const propsEndRef = (0, import_react10.useRef)(null);
|
|
@@ -6205,7 +6256,15 @@ function CreateAncestryPanel({
|
|
|
6205
6256
|
onHighlightNode,
|
|
6206
6257
|
onImageClick: handleImageClickFromText
|
|
6207
6258
|
}
|
|
6208
|
-
) : /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0 flex-shrink-0" }), /* @__PURE__ */ import_react10.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4 flex-shrink-0" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "w-full" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react10.default.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ import_react10.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, branchStack.length > 0 ? `Ramifica\xE7\xE3o (N\xEDvel ${branchStack.length})` : isEditMode ? "Editar Ancestralidade" : "Criar Ancestralidade")
|
|
6259
|
+
) : /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0 flex-shrink-0" }), /* @__PURE__ */ import_react10.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4 flex-shrink-0" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "w-full" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react10.default.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ import_react10.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, branchStack.length > 0 ? `Ramifica\xE7\xE3o (N\xEDvel ${branchStack.length})` : isEditMode ? "Editar Ancestralidade" : "Criar Ancestralidade"), currentAncestryId && currentAncestryId !== "temp_creating" && currentAncestryId !== "temp_root" && /* @__PURE__ */ import_react10.default.createElement(
|
|
6260
|
+
"button",
|
|
6261
|
+
{
|
|
6262
|
+
onClick: handleCopyLink,
|
|
6263
|
+
className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-indigo-400"}`,
|
|
6264
|
+
title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Ancestralidade"
|
|
6265
|
+
},
|
|
6266
|
+
isLinkCopied ? /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react10.default.createElement(import_fi9.FiLink, { size: 12 })
|
|
6267
|
+
)), /* @__PURE__ */ import_react10.default.createElement(
|
|
6209
6268
|
"input",
|
|
6210
6269
|
{
|
|
6211
6270
|
type: "text",
|
|
@@ -7259,7 +7318,6 @@ function NodeDetailsPanel({
|
|
|
7259
7318
|
onIntensityChange,
|
|
7260
7319
|
onUploadFile,
|
|
7261
7320
|
userRole
|
|
7262
|
-
// <--- ADIÇÃO: Recebendo a prop userRole
|
|
7263
7321
|
}) {
|
|
7264
7322
|
const [name, setName] = (0, import_react15.useState)((node == null ? void 0 : node.name) ?? "");
|
|
7265
7323
|
const [types, setTypes] = (0, import_react15.useState)([]);
|
|
@@ -7275,6 +7333,7 @@ function NodeDetailsPanel({
|
|
|
7275
7333
|
const [isReadMode, setIsReadMode] = (0, import_react15.useState)(false);
|
|
7276
7334
|
const [existingSections, setExistingSections] = (0, import_react15.useState)((node == null ? void 0 : node.description_sections) || []);
|
|
7277
7335
|
const [isSaving, setIsSaving] = (0, import_react15.useState)(false);
|
|
7336
|
+
const [isLinkCopied, setIsLinkCopied] = (0, import_react15.useState)(false);
|
|
7278
7337
|
const [useImageAsTexture, setUseImageAsTexture] = (0, import_react15.useState)(() => {
|
|
7279
7338
|
if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
|
|
7280
7339
|
if ((node == null ? void 0 : node.useImageAsTexture) === "false") return false;
|
|
@@ -7336,6 +7395,17 @@ function NodeDetailsPanel({
|
|
|
7336
7395
|
onIntensityChange == null ? void 0 : onIntensityChange(node.id, val);
|
|
7337
7396
|
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, intensity: val });
|
|
7338
7397
|
};
|
|
7398
|
+
const handleCopyLink = () => {
|
|
7399
|
+
if (!(node == null ? void 0 : node.id)) return;
|
|
7400
|
+
const baseUrl = window.location.origin + window.location.pathname;
|
|
7401
|
+
const fullUrl = `${baseUrl}?focus=${node.id}`;
|
|
7402
|
+
navigator.clipboard.writeText(fullUrl).then(() => {
|
|
7403
|
+
setIsLinkCopied(true);
|
|
7404
|
+
setTimeout(() => setIsLinkCopied(false), 2e3);
|
|
7405
|
+
}).catch((err) => {
|
|
7406
|
+
console.error("Erro ao copiar link:", err);
|
|
7407
|
+
});
|
|
7408
|
+
};
|
|
7339
7409
|
const swallow = (e) => e.stopPropagation();
|
|
7340
7410
|
const handleNameChange = (e) => {
|
|
7341
7411
|
const v = e.target.value;
|
|
@@ -7509,7 +7579,15 @@ function NodeDetailsPanel({
|
|
|
7509
7579
|
onMentionClick,
|
|
7510
7580
|
onImageClick: handleImageClickFromText
|
|
7511
7581
|
}
|
|
7512
|
-
) : /* @__PURE__ */ import_react15.default.createElement(import_react15.default.Fragment, null, /* @__PURE__ */ import_react15.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ import_react15.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react15.default.createElement("div", null, /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react15.default.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ import_react15.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node")
|
|
7582
|
+
) : /* @__PURE__ */ import_react15.default.createElement(import_react15.default.Fragment, null, /* @__PURE__ */ import_react15.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ import_react15.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react15.default.createElement("div", null, /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react15.default.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ import_react15.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node"), /* @__PURE__ */ import_react15.default.createElement(
|
|
7583
|
+
"button",
|
|
7584
|
+
{
|
|
7585
|
+
onClick: handleCopyLink,
|
|
7586
|
+
className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-indigo-400"}`,
|
|
7587
|
+
title: isLinkCopied ? "Link Copiado!" : "Copiar link para este Node"
|
|
7588
|
+
},
|
|
7589
|
+
isLinkCopied ? /* @__PURE__ */ import_react15.default.createElement(import_fi14.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react15.default.createElement(import_fi14.FiLink, { size: 12 })
|
|
7590
|
+
)), /* @__PURE__ */ import_react15.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ import_react15.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_react15.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react15.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos"), /* @__PURE__ */ import_react15.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_react15.default.createElement("span", { key: index, className: "flex items-center gap-1 bg-indigo-500/30 text-indigo-100 px-1.5 py-0.5 rounded-md text-xs font-medium border border-indigo-500/20" }, t, canEdit && /* @__PURE__ */ import_react15.default.createElement(
|
|
7513
7591
|
"button",
|
|
7514
7592
|
{
|
|
7515
7593
|
type: "button",
|
|
@@ -7662,8 +7740,7 @@ function NodeDetailsPanel({
|
|
|
7662
7740
|
isSaving && /* @__PURE__ */ import_react15.default.createElement(import_fi14.FiLoader, { className: "animate-spin" }),
|
|
7663
7741
|
isSaving ? "Salvando..." : "Salvar"
|
|
7664
7742
|
)))
|
|
7665
|
-
), isDescriptionModalOpen && canEdit &&
|
|
7666
|
-
/* @__PURE__ */ import_react15.default.createElement(
|
|
7743
|
+
), isDescriptionModalOpen && canEdit && /* @__PURE__ */ import_react15.default.createElement(
|
|
7667
7744
|
DescriptionEditModal,
|
|
7668
7745
|
{
|
|
7669
7746
|
isOpen: isDescriptionModalOpen,
|
|
@@ -8975,6 +9052,9 @@ function XViewScene({
|
|
|
8975
9052
|
var _a, _b, _c, _d, _e, _f;
|
|
8976
9053
|
const { data: session, status } = (0, import_react24.useSession)();
|
|
8977
9054
|
const router = (0, import_navigation.useRouter)();
|
|
9055
|
+
const searchParams = (0, import_navigation.useSearchParams)();
|
|
9056
|
+
const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
|
|
9057
|
+
const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
|
|
8978
9058
|
const viewParams = (0, import_react23.useMemo)(() => {
|
|
8979
9059
|
if (encryptedConfig) {
|
|
8980
9060
|
const data = decryptData(encryptedConfig);
|
|
@@ -9006,6 +9086,9 @@ function XViewScene({
|
|
|
9006
9086
|
}
|
|
9007
9087
|
if (viewParams && session && status === "authenticated") {
|
|
9008
9088
|
verifyPermission();
|
|
9089
|
+
} else if (status === "unauthenticated") {
|
|
9090
|
+
setPermissionStatus("denied");
|
|
9091
|
+
setIsLoading(false);
|
|
9009
9092
|
}
|
|
9010
9093
|
}, [viewParams, session, status, check_user_permission]);
|
|
9011
9094
|
const sceneConfigId = (0, import_react23.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
|
|
@@ -9041,6 +9124,8 @@ function XViewScene({
|
|
|
9041
9124
|
const [relationshipMenu, setRelationshipMenu] = (0, import_react23.useState)({ visible: false, x: 0, y: 0, linkObject: null });
|
|
9042
9125
|
const [creationMode, setCreationMode] = (0, import_react23.useState)({ isActive: false, sourceNodeData: null });
|
|
9043
9126
|
const [versionMode, setVersionMode] = (0, import_react23.useState)({ isActive: false, sourceNodeData: null });
|
|
9127
|
+
const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react23.useState)(false);
|
|
9128
|
+
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react23.useState)(false);
|
|
9044
9129
|
const [ancestryMode, setAncestryMode] = (0, import_react23.useState)({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
|
|
9045
9130
|
const [readingMode, setReadingMode] = (0, import_react23.useState)({
|
|
9046
9131
|
isActive: false,
|
|
@@ -9621,12 +9706,23 @@ function XViewScene({
|
|
|
9621
9706
|
const boardPromise = get_ancestry_board_action && session ? get_ancestry_board_action(configPath, sceneType, session, ownerId2) : Promise.resolve({ success: false, data: [] });
|
|
9622
9707
|
const [sceneResponse, boardResponse] = await Promise.all([scenePromise, boardPromise]);
|
|
9623
9708
|
if ((sceneResponse == null ? void 0 : sceneResponse.success) && ((_a2 = sceneResponse.data) == null ? void 0 : _a2.scene) && ((_b2 = sceneResponse.data) == null ? void 0 : _b2.parent)) {
|
|
9709
|
+
if (focusNodeId) {
|
|
9710
|
+
let targetNode = sceneResponse.data.scene.nodes.find((n) => String(n.id) === String(focusNodeId));
|
|
9711
|
+
if (!targetNode) {
|
|
9712
|
+
const allParentNodes = Object.values(sceneResponse.data.parent).flatMap((f) => f.nodes || []);
|
|
9713
|
+
targetNode = allParentNodes.find((n) => String(n.id) === String(focusNodeId));
|
|
9714
|
+
}
|
|
9715
|
+
if (targetNode) {
|
|
9716
|
+
sceneResponse.data.scene.nodes = [targetNode];
|
|
9717
|
+
sceneResponse.data.scene.links = [];
|
|
9718
|
+
}
|
|
9719
|
+
} else if (focusAncestryId) {
|
|
9720
|
+
sceneResponse.data.scene.nodes = [];
|
|
9721
|
+
sceneResponse.data.scene.links = [];
|
|
9722
|
+
}
|
|
9624
9723
|
sceneDataRef.current = sceneResponse.data.scene;
|
|
9625
9724
|
parentDataRef.current = sceneResponse.data.parent;
|
|
9626
9725
|
ancestryDataRef.current = sceneResponse.data.ancestry;
|
|
9627
|
-
console.log("Console de sceneDataRef.current no useEffect inicial:", sceneDataRef.current);
|
|
9628
|
-
console.log("Console de parentDataRef.current no useEffect inicial:", parentDataRef.current);
|
|
9629
|
-
console.log("Console de ancestryDataRef.current no useEffect inicial:", ancestryDataRef.current);
|
|
9630
9726
|
setIsInitialized(true);
|
|
9631
9727
|
} else {
|
|
9632
9728
|
console.error("Falha ao buscar dados da cena:", (sceneResponse == null ? void 0 : sceneResponse.error) || "Resposta inv\xE1lida.");
|
|
@@ -9634,7 +9730,6 @@ function XViewScene({
|
|
|
9634
9730
|
if (boardResponse == null ? void 0 : boardResponse.success) {
|
|
9635
9731
|
setAncestryBoardData(boardResponse.data);
|
|
9636
9732
|
} else {
|
|
9637
|
-
console.warn("Ancestry Board n\xE3o carregado ou vazio:", boardResponse == null ? void 0 : boardResponse.error);
|
|
9638
9733
|
setAncestryBoardData([]);
|
|
9639
9734
|
}
|
|
9640
9735
|
} catch (error) {
|
|
@@ -9658,11 +9753,14 @@ function XViewScene({
|
|
|
9658
9753
|
status,
|
|
9659
9754
|
ownerId,
|
|
9660
9755
|
viewParams,
|
|
9661
|
-
// Importante incluir viewParams nas dependências
|
|
9662
9756
|
get_scene_view_data,
|
|
9663
9757
|
get_ancestry_board_action,
|
|
9664
9758
|
isInitialized,
|
|
9665
|
-
permissionStatus
|
|
9759
|
+
permissionStatus,
|
|
9760
|
+
focusNodeId,
|
|
9761
|
+
// <-- MANTIDO
|
|
9762
|
+
focusAncestryId
|
|
9763
|
+
// <-- ADICIONADO O focusAncestryId NAS DEPENDÊNCIAS
|
|
9666
9764
|
]);
|
|
9667
9765
|
const isNodeInView = (0, import_react23.useCallback)((id) => {
|
|
9668
9766
|
const key = String(id);
|
|
@@ -11946,6 +12044,34 @@ function XViewScene({
|
|
|
11946
12044
|
tweenToTarget(nodeMesh, 1.2);
|
|
11947
12045
|
}
|
|
11948
12046
|
}, [tweenToTarget]);
|
|
12047
|
+
(0, import_react23.useEffect)(() => {
|
|
12048
|
+
if (isInitialized && focusNodeId && !hasFocusedInitial) {
|
|
12049
|
+
const nodeObjects = stateRef.current.nodeObjects || {};
|
|
12050
|
+
const targetMesh = nodeObjects[String(focusNodeId)];
|
|
12051
|
+
if (targetMesh) {
|
|
12052
|
+
setTimeout(() => {
|
|
12053
|
+
tweenToTarget(targetMesh, 1.2);
|
|
12054
|
+
setHasFocusedInitial(true);
|
|
12055
|
+
}, 300);
|
|
12056
|
+
} else {
|
|
12057
|
+
setHasFocusedInitial(true);
|
|
12058
|
+
}
|
|
12059
|
+
}
|
|
12060
|
+
}, [isInitialized, sceneVersion, focusNodeId, hasFocusedInitial, tweenToTarget]);
|
|
12061
|
+
(0, import_react23.useEffect)(() => {
|
|
12062
|
+
if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
|
|
12063
|
+
const ancestries = ancestryDataRef.current || [];
|
|
12064
|
+
const targetAncestry = ancestries.find((a) => String(a.ancestry_id) === String(focusAncestryId));
|
|
12065
|
+
if (targetAncestry) {
|
|
12066
|
+
setTimeout(() => {
|
|
12067
|
+
handleStartReadingAncestry(targetAncestry);
|
|
12068
|
+
setHasOpenedInitialAncestry(true);
|
|
12069
|
+
}, 300);
|
|
12070
|
+
} else {
|
|
12071
|
+
setHasOpenedInitialAncestry(true);
|
|
12072
|
+
}
|
|
12073
|
+
}
|
|
12074
|
+
}, [isInitialized, sceneVersion, focusAncestryId, hasOpenedInitialAncestry, handleStartReadingAncestry]);
|
|
11949
12075
|
if (isLoading || status === "loading" || permissionStatus === "loading") {
|
|
11950
12076
|
return /* @__PURE__ */ import_react23.default.createElement(LoadingScreen, null);
|
|
11951
12077
|
}
|
|
@@ -12040,6 +12166,7 @@ function XViewScene({
|
|
|
12040
12166
|
DescriptionReadModePanel,
|
|
12041
12167
|
{
|
|
12042
12168
|
key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
|
|
12169
|
+
ancestryId: readingMode.ancestry.ancestry_id,
|
|
12043
12170
|
title: (getReadModeDisplayContext == null ? void 0 : getReadModeDisplayContext.name) || readingMode.ancestry.name || "Ancestralidade",
|
|
12044
12171
|
initialSectionId: readingMode.initialSectionId,
|
|
12045
12172
|
description: getReadModeDisplayContext == null ? void 0 : getReadModeDisplayContext.description,
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/XViewScene.jsx
|
|
2
|
-
import React23, { useCallback as useCallback3, useEffect as
|
|
3
|
-
import { useRouter } from "next/navigation";
|
|
2
|
+
import React23, { useCallback as useCallback3, useEffect as useEffect21, useRef as useRef17, useState as useState22, useMemo as useMemo12 } from "react";
|
|
3
|
+
import { useRouter, useSearchParams } from "next/navigation";
|
|
4
4
|
import { useSession } from "next-auth/react";
|
|
5
5
|
import CryptoJS from "crypto-js";
|
|
6
6
|
import * as THREE3 from "three";
|
|
@@ -87,6 +87,7 @@ function ContextMenu({
|
|
|
87
87
|
const [menuView, setMenuView] = useState("main");
|
|
88
88
|
const [selectedAncestry, setSelectedAncestry] = useState(null);
|
|
89
89
|
const [versionSubMenu, setVersionSubMenu] = useState(null);
|
|
90
|
+
const [isLinkCopied, setIsLinkCopied] = useState(false);
|
|
90
91
|
const ability = useMemo(() => defineAbilityFor(userRole), [userRole]);
|
|
91
92
|
useEffect(() => {
|
|
92
93
|
if (data.visible) {
|
|
@@ -223,6 +224,20 @@ function ContextMenu({
|
|
|
223
224
|
return ((_a2 = node.version_node) == null ? void 0 : _a2.is_version) && String(node.version_node.parent_node) === String(data.nodeData.id);
|
|
224
225
|
}
|
|
225
226
|
).sort((a, b) => getYearFromDate(b.Date) - getYearFromDate(a.Date));
|
|
227
|
+
const handleCopyLink = (e, nodeData) => {
|
|
228
|
+
e.stopPropagation();
|
|
229
|
+
const baseUrl = window.location.origin + window.location.pathname;
|
|
230
|
+
const fullUrl = `${baseUrl}?focus=${nodeData.id}`;
|
|
231
|
+
navigator.clipboard.writeText(fullUrl).then(() => {
|
|
232
|
+
setIsLinkCopied(true);
|
|
233
|
+
setTimeout(() => {
|
|
234
|
+
setIsLinkCopied(false);
|
|
235
|
+
onClose();
|
|
236
|
+
}, 1500);
|
|
237
|
+
}).catch((err) => {
|
|
238
|
+
console.error("Erro ao copiar link:", err);
|
|
239
|
+
});
|
|
240
|
+
};
|
|
226
241
|
const renderMainView = () => {
|
|
227
242
|
const hasVersions = computedVersions.length > 0;
|
|
228
243
|
const canCreateVersion = ability.can("create", "Versioning");
|
|
@@ -231,7 +246,7 @@ function ContextMenu({
|
|
|
231
246
|
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" }, /* @__PURE__ */ React.createElement("button", { onClick: () => {
|
|
232
247
|
onFocusNode == null ? void 0 : onFocusNode(data.nodeData);
|
|
233
248
|
onClose();
|
|
234
|
-
}, 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")), 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") && /* @__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
|
|
249
|
+
}, 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")), 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") && /* @__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: (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: () => onDeleteNode == null ? void 0 : onDeleteNode(data.nodeData), 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"))));
|
|
235
250
|
};
|
|
236
251
|
const renderVersionSubMenuView = () => {
|
|
237
252
|
const group = versionSubMenu;
|
|
@@ -720,7 +735,7 @@ function XViewSidebar({
|
|
|
720
735
|
}
|
|
721
736
|
|
|
722
737
|
// src/components/AncestryRelationshipPanel.jsx
|
|
723
|
-
import React8, { useState as useState8, useEffect as
|
|
738
|
+
import React8, { useState as useState8, useEffect as useEffect8, useRef as useRef7 } from "react";
|
|
724
739
|
|
|
725
740
|
// node_modules/uuid/dist/esm-node/rng.js
|
|
726
741
|
import crypto from "crypto";
|
|
@@ -4425,7 +4440,7 @@ function DescriptionDisplay({
|
|
|
4425
4440
|
}
|
|
4426
4441
|
|
|
4427
4442
|
// src/components/DescriptionReadModePanel.jsx
|
|
4428
|
-
import React7, { useState as useState7, useMemo as useMemo6 } from "react";
|
|
4443
|
+
import React7, { useState as useState7, useMemo as useMemo6, useEffect as useEffect7 } from "react";
|
|
4429
4444
|
import {
|
|
4430
4445
|
FiArrowLeft,
|
|
4431
4446
|
FiEdit2,
|
|
@@ -4437,7 +4452,9 @@ import {
|
|
|
4437
4452
|
FiList as FiList2,
|
|
4438
4453
|
FiAlignLeft,
|
|
4439
4454
|
FiGitBranch,
|
|
4440
|
-
FiFolder
|
|
4455
|
+
FiFolder,
|
|
4456
|
+
FiLink as FiLink3,
|
|
4457
|
+
FiCheck as FiCheck4
|
|
4441
4458
|
} from "react-icons/fi";
|
|
4442
4459
|
var findNodePath = (tree, targetNodeId, currentPath = []) => {
|
|
4443
4460
|
var _a;
|
|
@@ -4501,6 +4518,8 @@ var ReadOnlyNodeItem = ({ nodeData, onViewSelect, highlightedPathIds = [], targe
|
|
|
4501
4518
|
function DescriptionReadModePanel({
|
|
4502
4519
|
title,
|
|
4503
4520
|
description,
|
|
4521
|
+
ancestryId,
|
|
4522
|
+
// <-- NOVO: Prop recebida do XViewScene
|
|
4504
4523
|
savedSections,
|
|
4505
4524
|
onBack,
|
|
4506
4525
|
onEdit,
|
|
@@ -4523,12 +4542,24 @@ function DescriptionReadModePanel({
|
|
|
4523
4542
|
abstractionTree = null,
|
|
4524
4543
|
onRenderAbstractionTree = null,
|
|
4525
4544
|
initialShowAbstraction = false
|
|
4526
|
-
// <--- NOVA PROP RECEBIDA
|
|
4527
4545
|
}) {
|
|
4528
4546
|
const [showProperties, setShowProperties] = useState7(false);
|
|
4529
4547
|
const [showAbstraction, setShowAbstraction] = useState7(false);
|
|
4530
4548
|
const [targetRenderNodeId, setTargetRenderNodeId] = useState7(null);
|
|
4531
|
-
|
|
4549
|
+
const [isLinkCopied, setIsLinkCopied] = useState7(false);
|
|
4550
|
+
const handleCopyLink = (e) => {
|
|
4551
|
+
e.stopPropagation();
|
|
4552
|
+
if (!ancestryId) return;
|
|
4553
|
+
const baseUrl = window.location.origin + window.location.pathname;
|
|
4554
|
+
const fullUrl = `${baseUrl}?ancestry=${ancestryId}`;
|
|
4555
|
+
navigator.clipboard.writeText(fullUrl).then(() => {
|
|
4556
|
+
setIsLinkCopied(true);
|
|
4557
|
+
setTimeout(() => setIsLinkCopied(false), 2e3);
|
|
4558
|
+
}).catch((err) => {
|
|
4559
|
+
console.error("Erro ao copiar link:", err);
|
|
4560
|
+
});
|
|
4561
|
+
};
|
|
4562
|
+
useEffect7(() => {
|
|
4532
4563
|
setShowAbstraction(initialShowAbstraction);
|
|
4533
4564
|
if (initialShowAbstraction) {
|
|
4534
4565
|
setShowProperties(false);
|
|
@@ -4617,7 +4648,15 @@ function DescriptionReadModePanel({
|
|
|
4617
4648
|
title: "Voltar"
|
|
4618
4649
|
},
|
|
4619
4650
|
/* @__PURE__ */ React7.createElement(FiArrowLeft, { size: 16 })
|
|
4620
|
-
), /* @__PURE__ */ React7.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React7.createElement("p", { className: "text-xs/relaxed text-slate-400 uppercase tracking-wider font-semibold" }, showAbstraction ? "Tree de Abstra\xE7\xE3o" : showProperties ? "Propriedades Adicionais" : "Modo de Leitura"),
|
|
4651
|
+
), /* @__PURE__ */ React7.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React7.createElement("p", { className: "text-xs/relaxed text-slate-400 uppercase tracking-wider font-semibold" }, showAbstraction ? "Tree de Abstra\xE7\xE3o" : showProperties ? "Propriedades Adicionais" : "Modo de Leitura"), ancestryId && /* @__PURE__ */ React7.createElement(
|
|
4652
|
+
"button",
|
|
4653
|
+
{
|
|
4654
|
+
onClick: handleCopyLink,
|
|
4655
|
+
className: `p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-indigo-400"}`,
|
|
4656
|
+
title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Ancestralidade"
|
|
4657
|
+
},
|
|
4658
|
+
isLinkCopied ? /* @__PURE__ */ React7.createElement(FiCheck4, { size: 12 }) : /* @__PURE__ */ React7.createElement(FiLink3, { size: 12 })
|
|
4659
|
+
)), /* @__PURE__ */ React7.createElement("h2", { className: "text-lg sm:text-xl font-semibold tracking-tight text-white truncate", title }, title || "Sem T\xEDtulo"))), /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2 flex-shrink-0" }, hasCustomProps && /* @__PURE__ */ React7.createElement(
|
|
4621
4660
|
"button",
|
|
4622
4661
|
{
|
|
4623
4662
|
onClick: handleToggleProperties,
|
|
@@ -4768,7 +4807,7 @@ function AncestryRelationshipPanel({
|
|
|
4768
4807
|
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState8(false);
|
|
4769
4808
|
const [isReadMode, setIsReadMode] = useState8(false);
|
|
4770
4809
|
const propsEndRef = useRef7(null);
|
|
4771
|
-
|
|
4810
|
+
useEffect8(() => {
|
|
4772
4811
|
setDescription((data == null ? void 0 : data.description) ?? "");
|
|
4773
4812
|
setExistingSections((data == null ? void 0 : data.description_sections) || []);
|
|
4774
4813
|
setCustomProps(extractCustomPropsFromNode(data || {}));
|
|
@@ -4908,13 +4947,13 @@ function AncestryRelationshipPanel({
|
|
|
4908
4947
|
}
|
|
4909
4948
|
|
|
4910
4949
|
// src/components/CreateAncestryPanel.jsx
|
|
4911
|
-
import React10, { useState as useState10, useEffect as
|
|
4950
|
+
import React10, { useState as useState10, useEffect as useEffect10, useMemo as useMemo8, useRef as useRef8, useCallback } from "react";
|
|
4912
4951
|
import {
|
|
4913
4952
|
FiEdit2 as FiEdit23,
|
|
4914
4953
|
FiBookOpen as FiBookOpen2,
|
|
4915
4954
|
FiFolder as FiFolder2,
|
|
4916
4955
|
FiMousePointer,
|
|
4917
|
-
FiCheck as
|
|
4956
|
+
FiCheck as FiCheck5,
|
|
4918
4957
|
FiLayers as FiLayers5,
|
|
4919
4958
|
FiArrowLeft as FiArrowLeft2,
|
|
4920
4959
|
FiChevronLeft as FiChevronLeft2,
|
|
@@ -4923,11 +4962,12 @@ import {
|
|
|
4923
4962
|
FiCornerUpRight as FiCornerUpRight3,
|
|
4924
4963
|
FiGitBranch as FiGitBranch2,
|
|
4925
4964
|
FiPlus as FiPlus2,
|
|
4926
|
-
FiLock
|
|
4965
|
+
FiLock,
|
|
4966
|
+
FiLink as FiLink4
|
|
4927
4967
|
} from "react-icons/fi";
|
|
4928
4968
|
|
|
4929
4969
|
// src/components/AncestryPickerModal.jsx
|
|
4930
|
-
import React9, { useState as useState9, useMemo as useMemo7, useEffect as
|
|
4970
|
+
import React9, { useState as useState9, useMemo as useMemo7, useEffect as useEffect9 } from "react";
|
|
4931
4971
|
import { FiSearch as FiSearch3, FiLayers as FiLayers4, FiCornerUpRight as FiCornerUpRight2 } from "react-icons/fi";
|
|
4932
4972
|
function AncestryPickerModal({
|
|
4933
4973
|
isOpen,
|
|
@@ -4938,7 +4978,7 @@ function AncestryPickerModal({
|
|
|
4938
4978
|
currentAncestryId
|
|
4939
4979
|
}) {
|
|
4940
4980
|
const [searchTerm, setSearchTerm] = useState9("");
|
|
4941
|
-
|
|
4981
|
+
useEffect9(() => {
|
|
4942
4982
|
if (!isOpen) return;
|
|
4943
4983
|
const handleKeyDown = (e) => {
|
|
4944
4984
|
if (e.key === "Escape") {
|
|
@@ -5159,6 +5199,20 @@ function CreateAncestryPanel({
|
|
|
5159
5199
|
currentAncestryId
|
|
5160
5200
|
} = ancestryMode;
|
|
5161
5201
|
const [isSaving, setIsSaving] = useState10(false);
|
|
5202
|
+
const [isLinkCopied, setIsLinkCopied] = useState10(false);
|
|
5203
|
+
const handleCopyLink = (e) => {
|
|
5204
|
+
e.stopPropagation();
|
|
5205
|
+
if (!currentAncestryId || currentAncestryId === "temp_root" || currentAncestryId === "temp_creating") {
|
|
5206
|
+
alert("Salve a ancestralidade primeiro para gerar um link.");
|
|
5207
|
+
return;
|
|
5208
|
+
}
|
|
5209
|
+
const baseUrl = window.location.origin + window.location.pathname;
|
|
5210
|
+
const fullUrl = `${baseUrl}?ancestry=${currentAncestryId}`;
|
|
5211
|
+
navigator.clipboard.writeText(fullUrl).then(() => {
|
|
5212
|
+
setIsLinkCopied(true);
|
|
5213
|
+
setTimeout(() => setIsLinkCopied(false), 2e3);
|
|
5214
|
+
}).catch((err) => console.error("Erro ao copiar link:", err));
|
|
5215
|
+
};
|
|
5162
5216
|
const [isPickerOpen, setIsPickerOpen] = useState10(false);
|
|
5163
5217
|
const [customProps, setCustomProps] = useState10([]);
|
|
5164
5218
|
const propsEndRef = useRef8(null);
|
|
@@ -5366,7 +5420,7 @@ function CreateAncestryPanel({
|
|
|
5366
5420
|
setCustomProps(newProps);
|
|
5367
5421
|
};
|
|
5368
5422
|
const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
|
|
5369
|
-
|
|
5423
|
+
useEffect10(() => {
|
|
5370
5424
|
if (!isContextLinked) return;
|
|
5371
5425
|
const handleKeyDown = (e) => {
|
|
5372
5426
|
if (branchStack.length === 0) return;
|
|
@@ -5384,7 +5438,7 @@ function CreateAncestryPanel({
|
|
|
5384
5438
|
window.addEventListener("keydown", handleKeyDown);
|
|
5385
5439
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
5386
5440
|
}, [isContextLinked, branchStack]);
|
|
5387
|
-
|
|
5441
|
+
useEffect10(() => {
|
|
5388
5442
|
const ctx = getCurrentContext();
|
|
5389
5443
|
let sourceObject = {};
|
|
5390
5444
|
if (ctx) {
|
|
@@ -6057,7 +6111,7 @@ function CreateAncestryPanel({
|
|
|
6057
6111
|
}
|
|
6058
6112
|
}
|
|
6059
6113
|
};
|
|
6060
|
-
|
|
6114
|
+
useEffect10(() => {
|
|
6061
6115
|
if (!description && existingSections.length === 0) return;
|
|
6062
6116
|
const newRootTree = applyDescriptionToTree(ancestryMode.tree, description, existingSections);
|
|
6063
6117
|
const currentTreeString = JSON.stringify(ancestryMode.tree);
|
|
@@ -6188,7 +6242,15 @@ function CreateAncestryPanel({
|
|
|
6188
6242
|
onHighlightNode,
|
|
6189
6243
|
onImageClick: handleImageClickFromText
|
|
6190
6244
|
}
|
|
6191
|
-
) : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0 flex-shrink-0" }), /* @__PURE__ */ React10.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4 flex-shrink-0" }, /* @__PURE__ */ React10.createElement("div", { className: "w-full" }, /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React10.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ React10.createElement("p", { className: "text-xs/relaxed text-slate-300" }, branchStack.length > 0 ? `Ramifica\xE7\xE3o (N\xEDvel ${branchStack.length})` : isEditMode ? "Editar Ancestralidade" : "Criar Ancestralidade")
|
|
6245
|
+
) : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0 flex-shrink-0" }), /* @__PURE__ */ React10.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4 flex-shrink-0" }, /* @__PURE__ */ React10.createElement("div", { className: "w-full" }, /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React10.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ React10.createElement("p", { className: "text-xs/relaxed text-slate-300" }, branchStack.length > 0 ? `Ramifica\xE7\xE3o (N\xEDvel ${branchStack.length})` : isEditMode ? "Editar Ancestralidade" : "Criar Ancestralidade"), currentAncestryId && currentAncestryId !== "temp_creating" && currentAncestryId !== "temp_root" && /* @__PURE__ */ React10.createElement(
|
|
6246
|
+
"button",
|
|
6247
|
+
{
|
|
6248
|
+
onClick: handleCopyLink,
|
|
6249
|
+
className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-indigo-400"}`,
|
|
6250
|
+
title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Ancestralidade"
|
|
6251
|
+
},
|
|
6252
|
+
isLinkCopied ? /* @__PURE__ */ React10.createElement(FiCheck5, { size: 12 }) : /* @__PURE__ */ React10.createElement(FiLink4, { size: 12 })
|
|
6253
|
+
)), /* @__PURE__ */ React10.createElement(
|
|
6192
6254
|
"input",
|
|
6193
6255
|
{
|
|
6194
6256
|
type: "text",
|
|
@@ -6323,7 +6385,7 @@ function CreateAncestryPanel({
|
|
|
6323
6385
|
className: `p-1.5 rounded-md transition-colors ${isAddingNodes ? "bg-cyan-500 text-white shadow-lg shadow-cyan-500/30" : "bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600"}`,
|
|
6324
6386
|
title: isAddingNodes ? "Concluir edi\xE7\xE3o da estrutura" : "Editar estrutura e adicionar nodes"
|
|
6325
6387
|
},
|
|
6326
|
-
isAddingNodes ? /* @__PURE__ */ React10.createElement(
|
|
6388
|
+
isAddingNodes ? /* @__PURE__ */ React10.createElement(FiCheck5, { size: 14 }) : /* @__PURE__ */ React10.createElement(FiEdit23, { size: 14 })
|
|
6327
6389
|
))), /* @__PURE__ */ React10.createElement("div", { className: "p-4 space-y-2" }, isAddingNodes && /* @__PURE__ */ React10.createElement("div", { className: "mb-3 p-2 rounded bg-cyan-900/20 border border-cyan-500/20 text-xs text-cyan-200 flex items-start gap-2" }, /* @__PURE__ */ React10.createElement(FiMousePointer, { className: "mt-0.5 flex-shrink-0" }), /* @__PURE__ */ React10.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React10.createElement("span", null, "Clique nos nodes do cen\xE1rio para adicion\xE1-los como filhos de: ", /* @__PURE__ */ React10.createElement("strong", { className: "text-white underline decoration-dashed" }, getSelectedParentName())), /* @__PURE__ */ React10.createElement("span", { className: "opacity-75" }, "Arraste e solte itens na lista para reorganizar a hierarquia."))), activeTree && /* @__PURE__ */ React10.createElement(
|
|
6328
6390
|
NodeItem,
|
|
6329
6391
|
{
|
|
@@ -6388,7 +6450,7 @@ function CreateAncestryPanel({
|
|
|
6388
6450
|
className: `p-1.5 rounded-md transition-colors ${ancestryMode.isAddingAbstractionNodes ? "bg-purple-500 text-white shadow-lg shadow-purple-500/30" : "bg-slate-700 text-slate-400 hover:text-white hover:bg-slate-600"}`,
|
|
6389
6451
|
title: "Editar estrutura da abstra\xE7\xE3o"
|
|
6390
6452
|
},
|
|
6391
|
-
ancestryMode.isAddingAbstractionNodes ? /* @__PURE__ */ React10.createElement(
|
|
6453
|
+
ancestryMode.isAddingAbstractionNodes ? /* @__PURE__ */ React10.createElement(FiCheck5, { size: 14 }) : /* @__PURE__ */ React10.createElement(FiEdit23, { size: 14 })
|
|
6392
6454
|
))),
|
|
6393
6455
|
/* @__PURE__ */ React10.createElement("div", { className: "p-4 space-y-2" }, ancestryMode.isAddingAbstractionNodes && /* @__PURE__ */ React10.createElement("div", { className: "mb-3 p-2 rounded bg-purple-900/20 border border-purple-500/20 text-xs text-purple-200 flex items-start gap-2" }, /* @__PURE__ */ React10.createElement(FiMousePointer, { className: "mt-0.5 flex-shrink-0" }), /* @__PURE__ */ React10.createElement("span", null, "Clique nos nodes do cen\xE1rio para adicion\xE1-los. Arraste e solte para organizar a hierarquia.")), /* @__PURE__ */ React10.createElement(
|
|
6394
6456
|
NodeItem,
|
|
@@ -6408,7 +6470,7 @@ function CreateAncestryPanel({
|
|
|
6408
6470
|
isEditable: ancestryMode.isAddingAbstractionNodes
|
|
6409
6471
|
}
|
|
6410
6472
|
))
|
|
6411
|
-
), branchStack.length === 0 && /* @__PURE__ */ React10.createElement("div", { className: "mt-3 flex items-center justify-end px-1" }, /* @__PURE__ */ React10.createElement("label", { className: "flex items-center gap-2 cursor-pointer group select-none" }, /* @__PURE__ */ React10.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${isPrivate ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, isPrivate && /* @__PURE__ */ React10.createElement(
|
|
6473
|
+
), branchStack.length === 0 && /* @__PURE__ */ React10.createElement("div", { className: "mt-3 flex items-center justify-end px-1" }, /* @__PURE__ */ React10.createElement("label", { className: "flex items-center gap-2 cursor-pointer group select-none" }, /* @__PURE__ */ React10.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${isPrivate ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, isPrivate && /* @__PURE__ */ React10.createElement(FiCheck5, { size: 12, className: "text-white" })), /* @__PURE__ */ React10.createElement(
|
|
6412
6474
|
"input",
|
|
6413
6475
|
{
|
|
6414
6476
|
type: "checkbox",
|
|
@@ -6456,7 +6518,7 @@ function CreateAncestryPanel({
|
|
|
6456
6518
|
}
|
|
6457
6519
|
|
|
6458
6520
|
// src/components/ImageViewer.jsx
|
|
6459
|
-
import React11, { useState as useState11, useEffect as
|
|
6521
|
+
import React11, { useState as useState11, useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useCallback as useCallback2 } from "react";
|
|
6460
6522
|
import { FiX as FiX2, FiChevronLeft as FiChevronLeft3, FiChevronRight as FiChevronRight5 } from "react-icons/fi";
|
|
6461
6523
|
function ImageViewer({ data, onClose }) {
|
|
6462
6524
|
var _a;
|
|
@@ -6479,7 +6541,7 @@ function ImageViewer({ data, onClose }) {
|
|
|
6479
6541
|
setCurrentIndex((prev) => (prev - 1 + images.length) % images.length);
|
|
6480
6542
|
}
|
|
6481
6543
|
}, [images.length]);
|
|
6482
|
-
|
|
6544
|
+
useEffect11(() => {
|
|
6483
6545
|
if (!visible) return;
|
|
6484
6546
|
const handleKeyDown = (e) => {
|
|
6485
6547
|
if (e.key === "Escape") {
|
|
@@ -6492,7 +6554,7 @@ function ImageViewer({ data, onClose }) {
|
|
|
6492
6554
|
window.addEventListener("keydown", handleKeyDown, { capture: true });
|
|
6493
6555
|
return () => window.removeEventListener("keydown", handleKeyDown, { capture: true });
|
|
6494
6556
|
}, [visible, onClose, handleNext, handlePrev]);
|
|
6495
|
-
|
|
6557
|
+
useEffect11(() => {
|
|
6496
6558
|
if (!visible || images.length === 0) return;
|
|
6497
6559
|
const curr = images[currentIndex];
|
|
6498
6560
|
const src = curr == null ? void 0 : curr.value;
|
|
@@ -6579,12 +6641,12 @@ function ImageViewer({ data, onClose }) {
|
|
|
6579
6641
|
}
|
|
6580
6642
|
|
|
6581
6643
|
// src/components/InSceneCreationForm.jsx
|
|
6582
|
-
import React13, { useState as useState13, useEffect as
|
|
6644
|
+
import React13, { useState as useState13, useEffect as useEffect13, useRef as useRef10 } from "react";
|
|
6583
6645
|
|
|
6584
6646
|
// src/components/ColorPicker.jsx
|
|
6585
|
-
import React12, { useState as useState12, useEffect as
|
|
6647
|
+
import React12, { useState as useState12, useEffect as useEffect12, useRef as useRef9 } from "react";
|
|
6586
6648
|
import { HexColorPicker } from "react-colorful";
|
|
6587
|
-
import { FiHash, FiCheck as
|
|
6649
|
+
import { FiHash, FiCheck as FiCheck6 } from "react-icons/fi";
|
|
6588
6650
|
var PRESET_COLORS = [
|
|
6589
6651
|
"#ef4444",
|
|
6590
6652
|
"#f97316",
|
|
@@ -6605,7 +6667,7 @@ var PRESET_COLORS = [
|
|
|
6605
6667
|
function ColorPicker({ color, onChange, disabled }) {
|
|
6606
6668
|
const [isOpen, setIsOpen] = useState12(false);
|
|
6607
6669
|
const popoverRef = useRef9(null);
|
|
6608
|
-
|
|
6670
|
+
useEffect12(() => {
|
|
6609
6671
|
const handleClickOutside = (event) => {
|
|
6610
6672
|
if (popoverRef.current && !popoverRef.current.contains(event.target)) {
|
|
6611
6673
|
setIsOpen(false);
|
|
@@ -6653,7 +6715,7 @@ function ColorPicker({ color, onChange, disabled }) {
|
|
|
6653
6715
|
style: { backgroundColor: preset },
|
|
6654
6716
|
title: preset
|
|
6655
6717
|
},
|
|
6656
|
-
color.toLowerCase() === preset.toLowerCase() && /* @__PURE__ */ React12.createElement(
|
|
6718
|
+
color.toLowerCase() === preset.toLowerCase() && /* @__PURE__ */ React12.createElement(FiCheck6, { className: `drop-shadow-md ${["#ffffff", "#4df5cb", "#84cc16", "#f59e0b"].includes(preset) ? "text-black" : "text-white"}`, size: 12 })
|
|
6657
6719
|
)))), /* @__PURE__ */ React12.createElement("style", null, `
|
|
6658
6720
|
.custom-react-colorful .react-colorful {
|
|
6659
6721
|
width: 100%;
|
|
@@ -6678,7 +6740,7 @@ function ColorPicker({ color, onChange, disabled }) {
|
|
|
6678
6740
|
}
|
|
6679
6741
|
|
|
6680
6742
|
// src/components/InSceneCreationForm.jsx
|
|
6681
|
-
import { FiPlus as FiPlus3, FiMaximize2, FiX as FiX3, FiCheck as
|
|
6743
|
+
import { FiPlus as FiPlus3, FiMaximize2, FiX as FiX3, FiCheck as FiCheck7, FiEdit2 as FiEdit24, FiSun } from "react-icons/fi";
|
|
6682
6744
|
function InSceneCreationForm({
|
|
6683
6745
|
onSave,
|
|
6684
6746
|
onCancel,
|
|
@@ -6713,14 +6775,14 @@ function InSceneCreationForm({
|
|
|
6713
6775
|
const [selectedImageUrl, setSelectedImageUrl] = useState13(null);
|
|
6714
6776
|
const propsEndRef = useRef10(null);
|
|
6715
6777
|
const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
|
|
6716
|
-
|
|
6778
|
+
useEffect13(() => {
|
|
6717
6779
|
if (!hasImages && useImageAsTexture) {
|
|
6718
6780
|
setUseImageAsTexture(false);
|
|
6719
6781
|
setSelectedImageUrl(null);
|
|
6720
6782
|
onImageChange == null ? void 0 : onImageChange(false, null);
|
|
6721
6783
|
}
|
|
6722
6784
|
}, [hasImages, useImageAsTexture, onImageChange]);
|
|
6723
|
-
|
|
6785
|
+
useEffect13(() => {
|
|
6724
6786
|
let result = [];
|
|
6725
6787
|
if (typeInput.trim() === "") {
|
|
6726
6788
|
result = existingTypes.filter((t) => !types.includes(t));
|
|
@@ -6742,7 +6804,7 @@ function InSceneCreationForm({
|
|
|
6742
6804
|
}
|
|
6743
6805
|
setFilteredTypes(result);
|
|
6744
6806
|
}, [typeInput, existingTypes, types, sourceTypes]);
|
|
6745
|
-
|
|
6807
|
+
useEffect13(() => {
|
|
6746
6808
|
if (initialColor) {
|
|
6747
6809
|
onColorChange == null ? void 0 : onColorChange(initialColor);
|
|
6748
6810
|
}
|
|
@@ -6941,10 +7003,10 @@ function InSceneCreationForm({
|
|
|
6941
7003
|
onClick: () => handleSizeChange(s),
|
|
6942
7004
|
className: "flex items-center gap-2 group cursor-pointer focus:outline-none"
|
|
6943
7005
|
},
|
|
6944
|
-
/* @__PURE__ */ React13.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${isSelected ? "bg-indigo-500 border-indigo-500 shadow-[0_0_10px_rgba(99,102,241,0.4)]" : "border-slate-600 bg-transparent group-hover:border-slate-500"}` }, isSelected && /* @__PURE__ */ React13.createElement(
|
|
7006
|
+
/* @__PURE__ */ React13.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${isSelected ? "bg-indigo-500 border-indigo-500 shadow-[0_0_10px_rgba(99,102,241,0.4)]" : "border-slate-600 bg-transparent group-hover:border-slate-500"}` }, isSelected && /* @__PURE__ */ React13.createElement(FiCheck7, { size: 12, className: "text-white" })),
|
|
6945
7007
|
/* @__PURE__ */ React13.createElement("span", { className: `text-sm capitalize transition-colors ${isSelected ? "text-white font-medium" : "text-slate-400 group-hover:text-slate-300"}` }, s)
|
|
6946
7008
|
);
|
|
6947
|
-
}))), /* @__PURE__ */ React13.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React13.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React13.createElement("label", { className: "text-xs text-slate-300" }, "Cor e Brilho"), hasImages && /* @__PURE__ */ React13.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ React13.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${useImageAsTexture ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, useImageAsTexture && /* @__PURE__ */ React13.createElement(
|
|
7009
|
+
}))), /* @__PURE__ */ React13.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React13.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React13.createElement("label", { className: "text-xs text-slate-300" }, "Cor e Brilho"), hasImages && /* @__PURE__ */ React13.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ React13.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${useImageAsTexture ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, useImageAsTexture && /* @__PURE__ */ React13.createElement(FiCheck7, { size: 12, className: "text-white" })), /* @__PURE__ */ React13.createElement(
|
|
6948
7010
|
"input",
|
|
6949
7011
|
{
|
|
6950
7012
|
type: "checkbox",
|
|
@@ -7004,8 +7066,8 @@ function InSceneCreationForm({
|
|
|
7004
7066
|
}
|
|
7005
7067
|
|
|
7006
7068
|
// src/components/InSceneVersionForm.jsx
|
|
7007
|
-
import React14, { useState as useState14, useEffect as
|
|
7008
|
-
import { FiPlus as FiPlus4, FiMaximize2 as FiMaximize22, FiCheck as
|
|
7069
|
+
import React14, { useState as useState14, useEffect as useEffect14, useRef as useRef11 } from "react";
|
|
7070
|
+
import { FiPlus as FiPlus4, FiMaximize2 as FiMaximize22, FiCheck as FiCheck8, FiEdit2 as FiEdit25 } from "react-icons/fi";
|
|
7009
7071
|
function InSceneVersionForm({
|
|
7010
7072
|
onSave,
|
|
7011
7073
|
onCancel,
|
|
@@ -7031,14 +7093,14 @@ function InSceneVersionForm({
|
|
|
7031
7093
|
const [useImageAsTexture, setUseImageAsTexture] = useState14(false);
|
|
7032
7094
|
const [selectedImageUrl, setSelectedImageUrl] = useState14(null);
|
|
7033
7095
|
const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
|
|
7034
|
-
|
|
7096
|
+
useEffect14(() => {
|
|
7035
7097
|
if (!hasImages && useImageAsTexture) {
|
|
7036
7098
|
setUseImageAsTexture(false);
|
|
7037
7099
|
setSelectedImageUrl(null);
|
|
7038
7100
|
onImageChange == null ? void 0 : onImageChange(false, null);
|
|
7039
7101
|
}
|
|
7040
7102
|
}, [hasImages, useImageAsTexture, onImageChange]);
|
|
7041
|
-
|
|
7103
|
+
useEffect14(() => {
|
|
7042
7104
|
if (fixedColor) {
|
|
7043
7105
|
}
|
|
7044
7106
|
}, [fixedColor]);
|
|
@@ -7178,10 +7240,10 @@ function InSceneVersionForm({
|
|
|
7178
7240
|
onClick: () => handleSizeChange(s),
|
|
7179
7241
|
className: "flex items-center gap-2 group cursor-pointer focus:outline-none"
|
|
7180
7242
|
},
|
|
7181
|
-
/* @__PURE__ */ React14.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${isSelected ? "bg-indigo-500 border-indigo-500 shadow-[0_0_10px_rgba(99,102,241,0.4)]" : "border-slate-600 bg-transparent group-hover:border-slate-500"}` }, isSelected && /* @__PURE__ */ React14.createElement(
|
|
7243
|
+
/* @__PURE__ */ React14.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${isSelected ? "bg-indigo-500 border-indigo-500 shadow-[0_0_10px_rgba(99,102,241,0.4)]" : "border-slate-600 bg-transparent group-hover:border-slate-500"}` }, isSelected && /* @__PURE__ */ React14.createElement(FiCheck8, { size: 12, className: "text-white" })),
|
|
7182
7244
|
/* @__PURE__ */ React14.createElement("span", { className: `text-sm capitalize transition-colors ${isSelected ? "text-white font-medium" : "text-slate-400 group-hover:text-slate-300"}` }, s)
|
|
7183
7245
|
);
|
|
7184
|
-
}))), /* @__PURE__ */ React14.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React14.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React14.createElement("label", { className: "text-xs text-slate-300" }, "Cor do Node (Fixa)"), hasImages && /* @__PURE__ */ React14.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ React14.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${useImageAsTexture ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, useImageAsTexture && /* @__PURE__ */ React14.createElement(
|
|
7246
|
+
}))), /* @__PURE__ */ React14.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React14.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React14.createElement("label", { className: "text-xs text-slate-300" }, "Cor do Node (Fixa)"), hasImages && /* @__PURE__ */ React14.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ React14.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${useImageAsTexture ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, useImageAsTexture && /* @__PURE__ */ React14.createElement(FiCheck8, { size: 12, className: "text-white" })), /* @__PURE__ */ React14.createElement(
|
|
7185
7247
|
"input",
|
|
7186
7248
|
{
|
|
7187
7249
|
type: "checkbox",
|
|
@@ -7222,8 +7284,8 @@ function InSceneVersionForm({
|
|
|
7222
7284
|
}
|
|
7223
7285
|
|
|
7224
7286
|
// src/components/NodeDetailsPanel.jsx
|
|
7225
|
-
import React15, { useState as useState15, useEffect as
|
|
7226
|
-
import { FiPlus as FiPlus5, FiMaximize2 as FiMaximize23, FiX as FiX4, FiCheck as
|
|
7287
|
+
import React15, { useState as useState15, useEffect as useEffect15, useRef as useRef12 } from "react";
|
|
7288
|
+
import { FiPlus as FiPlus5, FiMaximize2 as FiMaximize23, FiX as FiX4, FiCheck as FiCheck9, FiImage as FiImage3, FiEdit2 as FiEdit26, FiLoader as FiLoader2, FiBookOpen as FiBookOpen3, FiSun as FiSun2, FiLink as FiLink5 } from "react-icons/fi";
|
|
7227
7289
|
function NodeDetailsPanel({
|
|
7228
7290
|
node,
|
|
7229
7291
|
onClose,
|
|
@@ -7242,7 +7304,6 @@ function NodeDetailsPanel({
|
|
|
7242
7304
|
onIntensityChange,
|
|
7243
7305
|
onUploadFile,
|
|
7244
7306
|
userRole
|
|
7245
|
-
// <--- ADIÇÃO: Recebendo a prop userRole
|
|
7246
7307
|
}) {
|
|
7247
7308
|
const [name, setName] = useState15((node == null ? void 0 : node.name) ?? "");
|
|
7248
7309
|
const [types, setTypes] = useState15([]);
|
|
@@ -7258,6 +7319,7 @@ function NodeDetailsPanel({
|
|
|
7258
7319
|
const [isReadMode, setIsReadMode] = useState15(false);
|
|
7259
7320
|
const [existingSections, setExistingSections] = useState15((node == null ? void 0 : node.description_sections) || []);
|
|
7260
7321
|
const [isSaving, setIsSaving] = useState15(false);
|
|
7322
|
+
const [isLinkCopied, setIsLinkCopied] = useState15(false);
|
|
7261
7323
|
const [useImageAsTexture, setUseImageAsTexture] = useState15(() => {
|
|
7262
7324
|
if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
|
|
7263
7325
|
if ((node == null ? void 0 : node.useImageAsTexture) === "false") return false;
|
|
@@ -7273,7 +7335,7 @@ function NodeDetailsPanel({
|
|
|
7273
7335
|
onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
|
|
7274
7336
|
}
|
|
7275
7337
|
};
|
|
7276
|
-
|
|
7338
|
+
useEffect15(() => {
|
|
7277
7339
|
if ((node == null ? void 0 : node.id) !== prevNodeIdRef.current) {
|
|
7278
7340
|
prevNodeIdRef.current = node == null ? void 0 : node.id;
|
|
7279
7341
|
setName((node == null ? void 0 : node.name) ?? "");
|
|
@@ -7295,13 +7357,13 @@ function NodeDetailsPanel({
|
|
|
7295
7357
|
}
|
|
7296
7358
|
}, [node]);
|
|
7297
7359
|
const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
|
|
7298
|
-
|
|
7360
|
+
useEffect15(() => {
|
|
7299
7361
|
if (!hasImages && useImageAsTexture) {
|
|
7300
7362
|
setUseImageAsTexture(false);
|
|
7301
7363
|
setSelectedImageUrl(null);
|
|
7302
7364
|
}
|
|
7303
7365
|
}, [hasImages, useImageAsTexture]);
|
|
7304
|
-
|
|
7366
|
+
useEffect15(() => {
|
|
7305
7367
|
if (typeInput.trim() === "") {
|
|
7306
7368
|
setFilteredTypes(existingTypes.filter((t) => !types.includes(t)));
|
|
7307
7369
|
} else {
|
|
@@ -7319,6 +7381,17 @@ function NodeDetailsPanel({
|
|
|
7319
7381
|
onIntensityChange == null ? void 0 : onIntensityChange(node.id, val);
|
|
7320
7382
|
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, intensity: val });
|
|
7321
7383
|
};
|
|
7384
|
+
const handleCopyLink = () => {
|
|
7385
|
+
if (!(node == null ? void 0 : node.id)) return;
|
|
7386
|
+
const baseUrl = window.location.origin + window.location.pathname;
|
|
7387
|
+
const fullUrl = `${baseUrl}?focus=${node.id}`;
|
|
7388
|
+
navigator.clipboard.writeText(fullUrl).then(() => {
|
|
7389
|
+
setIsLinkCopied(true);
|
|
7390
|
+
setTimeout(() => setIsLinkCopied(false), 2e3);
|
|
7391
|
+
}).catch((err) => {
|
|
7392
|
+
console.error("Erro ao copiar link:", err);
|
|
7393
|
+
});
|
|
7394
|
+
};
|
|
7322
7395
|
const swallow = (e) => e.stopPropagation();
|
|
7323
7396
|
const handleNameChange = (e) => {
|
|
7324
7397
|
const v = e.target.value;
|
|
@@ -7492,7 +7565,15 @@ function NodeDetailsPanel({
|
|
|
7492
7565
|
onMentionClick,
|
|
7493
7566
|
onImageClick: handleImageClickFromText
|
|
7494
7567
|
}
|
|
7495
|
-
) : /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__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("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ React15.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node")
|
|
7568
|
+
) : /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__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("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ React15.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node"), /* @__PURE__ */ React15.createElement(
|
|
7569
|
+
"button",
|
|
7570
|
+
{
|
|
7571
|
+
onClick: handleCopyLink,
|
|
7572
|
+
className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-indigo-400"}`,
|
|
7573
|
+
title: isLinkCopied ? "Link Copiado!" : "Copiar link para este Node"
|
|
7574
|
+
},
|
|
7575
|
+
isLinkCopied ? /* @__PURE__ */ React15.createElement(FiCheck9, { size: 12 }) : /* @__PURE__ */ React15.createElement(FiLink5, { size: 12 })
|
|
7576
|
+
)), /* @__PURE__ */ React15.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ React15.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__ */ React15.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tipos"), /* @__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 ${canEdit ? "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 bg-indigo-500/30 text-indigo-100 px-1.5 py-0.5 rounded-md text-xs font-medium border border-indigo-500/20" }, t, canEdit && /* @__PURE__ */ React15.createElement(
|
|
7496
7577
|
"button",
|
|
7497
7578
|
{
|
|
7498
7579
|
type: "button",
|
|
@@ -7587,10 +7668,10 @@ function NodeDetailsPanel({
|
|
|
7587
7668
|
onClick: () => canEdit && handleSizeChange(s),
|
|
7588
7669
|
className: `flex items-center gap-2 group focus:outline-none ${canEdit ? "cursor-pointer" : "cursor-default opacity-80"}`
|
|
7589
7670
|
},
|
|
7590
|
-
/* @__PURE__ */ React15.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${isSelected ? "bg-indigo-500 border-indigo-500 shadow-[0_0_10px_rgba(99,102,241,0.4)]" : "border-slate-600 bg-transparent " + (canEdit ? "group-hover:border-slate-500" : "")}` }, isSelected && /* @__PURE__ */ React15.createElement(
|
|
7671
|
+
/* @__PURE__ */ React15.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${isSelected ? "bg-indigo-500 border-indigo-500 shadow-[0_0_10px_rgba(99,102,241,0.4)]" : "border-slate-600 bg-transparent " + (canEdit ? "group-hover:border-slate-500" : "")}` }, isSelected && /* @__PURE__ */ React15.createElement(FiCheck9, { size: 12, className: "text-white" })),
|
|
7591
7672
|
/* @__PURE__ */ React15.createElement("span", { className: `text-sm capitalize transition-colors ${isSelected ? "text-white font-medium" : "text-slate-400 " + (canEdit ? "group-hover:text-slate-300" : "")}` }, s)
|
|
7592
7673
|
);
|
|
7593
|
-
}))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Cor e Brilho"), canEdit && hasImages && /* @__PURE__ */ React15.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ React15.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${useImageAsTexture ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, useImageAsTexture && /* @__PURE__ */ React15.createElement(
|
|
7674
|
+
}))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Cor e Brilho"), canEdit && hasImages && /* @__PURE__ */ React15.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ React15.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${useImageAsTexture ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, useImageAsTexture && /* @__PURE__ */ React15.createElement(FiCheck9, { size: 12, className: "text-white" })), /* @__PURE__ */ React15.createElement(
|
|
7594
7675
|
"input",
|
|
7595
7676
|
{
|
|
7596
7677
|
type: "checkbox",
|
|
@@ -7645,8 +7726,7 @@ function NodeDetailsPanel({
|
|
|
7645
7726
|
isSaving && /* @__PURE__ */ React15.createElement(FiLoader2, { className: "animate-spin" }),
|
|
7646
7727
|
isSaving ? "Salvando..." : "Salvar"
|
|
7647
7728
|
)))
|
|
7648
|
-
), isDescriptionModalOpen && canEdit &&
|
|
7649
|
-
/* @__PURE__ */ React15.createElement(
|
|
7729
|
+
), isDescriptionModalOpen && canEdit && /* @__PURE__ */ React15.createElement(
|
|
7650
7730
|
DescriptionEditModal,
|
|
7651
7731
|
{
|
|
7652
7732
|
isOpen: isDescriptionModalOpen,
|
|
@@ -7666,7 +7746,7 @@ function NodeDetailsPanel({
|
|
|
7666
7746
|
}
|
|
7667
7747
|
|
|
7668
7748
|
// src/components/MultiNodeContextMenu.jsx
|
|
7669
|
-
import React16, { useLayoutEffect as useLayoutEffect3, useRef as useRef13, useState as useState16, useEffect as
|
|
7749
|
+
import React16, { useLayoutEffect as useLayoutEffect3, useRef as useRef13, useState as useState16, useEffect as useEffect16 } from "react";
|
|
7670
7750
|
function MultiNodeContextMenu({
|
|
7671
7751
|
data,
|
|
7672
7752
|
userRole,
|
|
@@ -7693,7 +7773,7 @@ function MultiNodeContextMenu({
|
|
|
7693
7773
|
if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
|
|
7694
7774
|
setMenuPos({ left, top });
|
|
7695
7775
|
}, [data]);
|
|
7696
|
-
|
|
7776
|
+
useEffect16(() => {
|
|
7697
7777
|
if (!data.visible) return;
|
|
7698
7778
|
const handleClickOutside = (e) => {
|
|
7699
7779
|
if (menuRef.current && !menuRef.current.contains(e.target)) onClose();
|
|
@@ -7726,7 +7806,7 @@ function MultiNodeContextMenu({
|
|
|
7726
7806
|
}
|
|
7727
7807
|
|
|
7728
7808
|
// src/components/RelationshipDetailsPanel.jsx
|
|
7729
|
-
import React17, { useState as useState17, useEffect as
|
|
7809
|
+
import React17, { useState as useState17, useEffect as useEffect17, useRef as useRef14, useMemo as useMemo9 } from "react";
|
|
7730
7810
|
import { FiPlus as FiPlus6, FiEdit2 as FiEdit27, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4 } from "react-icons/fi";
|
|
7731
7811
|
function RelationshipDetailsPanel({
|
|
7732
7812
|
link,
|
|
@@ -7754,7 +7834,7 @@ function RelationshipDetailsPanel({
|
|
|
7754
7834
|
const ability = defineAbilityFor(userRole);
|
|
7755
7835
|
return ability.can("update", "Connection");
|
|
7756
7836
|
}, [userRole]);
|
|
7757
|
-
|
|
7837
|
+
useEffect17(() => {
|
|
7758
7838
|
setName((link == null ? void 0 : link.name) ?? "");
|
|
7759
7839
|
setDescription((link == null ? void 0 : link.description) ?? "");
|
|
7760
7840
|
setExistingSections((link == null ? void 0 : link.description_sections) || []);
|
|
@@ -7951,7 +8031,7 @@ function RelationshipDetailsPanel({
|
|
|
7951
8031
|
}
|
|
7952
8032
|
|
|
7953
8033
|
// src/components/RelationshipContextMenu.jsx
|
|
7954
|
-
import React18, { useLayoutEffect as useLayoutEffect4, useRef as useRef15, useState as useState18, useEffect as
|
|
8034
|
+
import React18, { useLayoutEffect as useLayoutEffect4, useRef as useRef15, useState as useState18, useEffect as useEffect18, useMemo as useMemo10 } from "react";
|
|
7955
8035
|
function RelationshipContextMenu({
|
|
7956
8036
|
data,
|
|
7957
8037
|
userRole,
|
|
@@ -7992,7 +8072,7 @@ function RelationshipContextMenu({
|
|
|
7992
8072
|
if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
|
|
7993
8073
|
setMenuPos({ left, top });
|
|
7994
8074
|
}, [data]);
|
|
7995
|
-
|
|
8075
|
+
useEffect18(() => {
|
|
7996
8076
|
if (!data.visible) return;
|
|
7997
8077
|
const handleClickOutside = (e) => {
|
|
7998
8078
|
if (menuRef.current && !menuRef.current.contains(e.target)) onClose();
|
|
@@ -8165,7 +8245,7 @@ function LoadingScreen() {
|
|
|
8165
8245
|
}
|
|
8166
8246
|
|
|
8167
8247
|
// src/components/ImportParentFileModal.jsx
|
|
8168
|
-
import React20, { useEffect as
|
|
8248
|
+
import React20, { useEffect as useEffect19, useState as useState19 } from "react";
|
|
8169
8249
|
function ImportParentFileModal({
|
|
8170
8250
|
isOpen,
|
|
8171
8251
|
onClose,
|
|
@@ -8181,7 +8261,7 @@ function ImportParentFileModal({
|
|
|
8181
8261
|
const [availableViews, setAvailableViews] = useState19([]);
|
|
8182
8262
|
const [selectedItem, setSelectedItem] = useState19(null);
|
|
8183
8263
|
const [isLoading, setIsLoading] = useState19(false);
|
|
8184
|
-
|
|
8264
|
+
useEffect19(() => {
|
|
8185
8265
|
if (isOpen && session && onFetchAvailableFiles) {
|
|
8186
8266
|
const fetchData = async () => {
|
|
8187
8267
|
setIsLoading(true);
|
|
@@ -8217,7 +8297,7 @@ function ImportParentFileModal({
|
|
|
8217
8297
|
fetchData();
|
|
8218
8298
|
}
|
|
8219
8299
|
}, [isOpen, session, parentDbs, onFetchAvailableFiles, currentViewName]);
|
|
8220
|
-
|
|
8300
|
+
useEffect19(() => {
|
|
8221
8301
|
setSelectedItem(null);
|
|
8222
8302
|
}, [activeTab]);
|
|
8223
8303
|
if (!isOpen) {
|
|
@@ -8402,7 +8482,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
8402
8482
|
}
|
|
8403
8483
|
|
|
8404
8484
|
// src/components/AncestryBoard.jsx
|
|
8405
|
-
import React22, { useState as useState21, useMemo as useMemo11, useEffect as
|
|
8485
|
+
import React22, { useState as useState21, useMemo as useMemo11, useEffect as useEffect20, useRef as useRef16 } from "react";
|
|
8406
8486
|
import {
|
|
8407
8487
|
FiSearch as FiSearch4,
|
|
8408
8488
|
FiLayers as FiLayers6,
|
|
@@ -8444,7 +8524,7 @@ var GroupItem = ({
|
|
|
8444
8524
|
textarea.style.height = `${textarea.scrollHeight}px`;
|
|
8445
8525
|
}
|
|
8446
8526
|
};
|
|
8447
|
-
|
|
8527
|
+
useEffect20(() => {
|
|
8448
8528
|
adjustHeight();
|
|
8449
8529
|
}, [group.text]);
|
|
8450
8530
|
return /* @__PURE__ */ React22.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React22.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ React22.createElement("div", { className: `
|
|
@@ -8587,7 +8667,7 @@ function AncestryBoard({
|
|
|
8587
8667
|
const canEdit = useMemo11(() => {
|
|
8588
8668
|
return userRole !== "viewer";
|
|
8589
8669
|
}, [userRole]);
|
|
8590
|
-
|
|
8670
|
+
useEffect20(() => {
|
|
8591
8671
|
if (initialGroups && !isLoaded) {
|
|
8592
8672
|
setGroups(initialGroups);
|
|
8593
8673
|
setIsLoaded(true);
|
|
@@ -8618,7 +8698,7 @@ function AncestryBoard({
|
|
|
8618
8698
|
children: sanitizeGroups(g.children || [])
|
|
8619
8699
|
}));
|
|
8620
8700
|
};
|
|
8621
|
-
|
|
8701
|
+
useEffect20(() => {
|
|
8622
8702
|
if (!isLoaded || !onSave) return;
|
|
8623
8703
|
const timeoutId = setTimeout(async () => {
|
|
8624
8704
|
setSaveStatus("saving");
|
|
@@ -8636,7 +8716,7 @@ function AncestryBoard({
|
|
|
8636
8716
|
}, 3e3);
|
|
8637
8717
|
return () => clearTimeout(timeoutId);
|
|
8638
8718
|
}, [groups, isLoaded, onSave]);
|
|
8639
|
-
|
|
8719
|
+
useEffect20(() => {
|
|
8640
8720
|
if (!isOpen) return;
|
|
8641
8721
|
const handleKeyDown = (e) => {
|
|
8642
8722
|
if (e.key === "Escape") {
|
|
@@ -8971,6 +9051,9 @@ function XViewScene({
|
|
|
8971
9051
|
var _a, _b, _c, _d, _e, _f;
|
|
8972
9052
|
const { data: session, status } = useSession();
|
|
8973
9053
|
const router = useRouter();
|
|
9054
|
+
const searchParams = useSearchParams();
|
|
9055
|
+
const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
|
|
9056
|
+
const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
|
|
8974
9057
|
const viewParams = useMemo12(() => {
|
|
8975
9058
|
if (encryptedConfig) {
|
|
8976
9059
|
const data = decryptData(encryptedConfig);
|
|
@@ -8980,7 +9063,7 @@ function XViewScene({
|
|
|
8980
9063
|
}
|
|
8981
9064
|
return null;
|
|
8982
9065
|
}, [encryptedConfig, session]);
|
|
8983
|
-
|
|
9066
|
+
useEffect21(() => {
|
|
8984
9067
|
async function verifyPermission() {
|
|
8985
9068
|
if (!viewParams || !session || !check_user_permission) return;
|
|
8986
9069
|
const { id, type, owner_id } = viewParams;
|
|
@@ -9002,6 +9085,9 @@ function XViewScene({
|
|
|
9002
9085
|
}
|
|
9003
9086
|
if (viewParams && session && status === "authenticated") {
|
|
9004
9087
|
verifyPermission();
|
|
9088
|
+
} else if (status === "unauthenticated") {
|
|
9089
|
+
setPermissionStatus("denied");
|
|
9090
|
+
setIsLoading(false);
|
|
9005
9091
|
}
|
|
9006
9092
|
}, [viewParams, session, status, check_user_permission]);
|
|
9007
9093
|
const sceneConfigId = useMemo12(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
|
|
@@ -9037,6 +9123,8 @@ function XViewScene({
|
|
|
9037
9123
|
const [relationshipMenu, setRelationshipMenu] = useState22({ visible: false, x: 0, y: 0, linkObject: null });
|
|
9038
9124
|
const [creationMode, setCreationMode] = useState22({ isActive: false, sourceNodeData: null });
|
|
9039
9125
|
const [versionMode, setVersionMode] = useState22({ isActive: false, sourceNodeData: null });
|
|
9126
|
+
const [hasFocusedInitial, setHasFocusedInitial] = useState22(false);
|
|
9127
|
+
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState22(false);
|
|
9040
9128
|
const [ancestryMode, setAncestryMode] = useState22({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
|
|
9041
9129
|
const [readingMode, setReadingMode] = useState22({
|
|
9042
9130
|
isActive: false,
|
|
@@ -9098,10 +9186,10 @@ function XViewScene({
|
|
|
9098
9186
|
lastDescriptionLength: 0,
|
|
9099
9187
|
highlightedNodeId: null
|
|
9100
9188
|
});
|
|
9101
|
-
|
|
9189
|
+
useEffect21(() => {
|
|
9102
9190
|
stateRef.current.ancestry = ancestryMode;
|
|
9103
9191
|
}, [ancestryMode]);
|
|
9104
|
-
|
|
9192
|
+
useEffect21(() => {
|
|
9105
9193
|
var _a2;
|
|
9106
9194
|
if (!isInitialized) return;
|
|
9107
9195
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -9602,7 +9690,7 @@ function XViewScene({
|
|
|
9602
9690
|
}
|
|
9603
9691
|
});
|
|
9604
9692
|
}, []);
|
|
9605
|
-
|
|
9693
|
+
useEffect21(() => {
|
|
9606
9694
|
async function fetchAllData(configPath, ownerId2) {
|
|
9607
9695
|
var _a2, _b2;
|
|
9608
9696
|
if (!get_scene_view_data) {
|
|
@@ -9617,12 +9705,23 @@ function XViewScene({
|
|
|
9617
9705
|
const boardPromise = get_ancestry_board_action && session ? get_ancestry_board_action(configPath, sceneType, session, ownerId2) : Promise.resolve({ success: false, data: [] });
|
|
9618
9706
|
const [sceneResponse, boardResponse] = await Promise.all([scenePromise, boardPromise]);
|
|
9619
9707
|
if ((sceneResponse == null ? void 0 : sceneResponse.success) && ((_a2 = sceneResponse.data) == null ? void 0 : _a2.scene) && ((_b2 = sceneResponse.data) == null ? void 0 : _b2.parent)) {
|
|
9708
|
+
if (focusNodeId) {
|
|
9709
|
+
let targetNode = sceneResponse.data.scene.nodes.find((n) => String(n.id) === String(focusNodeId));
|
|
9710
|
+
if (!targetNode) {
|
|
9711
|
+
const allParentNodes = Object.values(sceneResponse.data.parent).flatMap((f) => f.nodes || []);
|
|
9712
|
+
targetNode = allParentNodes.find((n) => String(n.id) === String(focusNodeId));
|
|
9713
|
+
}
|
|
9714
|
+
if (targetNode) {
|
|
9715
|
+
sceneResponse.data.scene.nodes = [targetNode];
|
|
9716
|
+
sceneResponse.data.scene.links = [];
|
|
9717
|
+
}
|
|
9718
|
+
} else if (focusAncestryId) {
|
|
9719
|
+
sceneResponse.data.scene.nodes = [];
|
|
9720
|
+
sceneResponse.data.scene.links = [];
|
|
9721
|
+
}
|
|
9620
9722
|
sceneDataRef.current = sceneResponse.data.scene;
|
|
9621
9723
|
parentDataRef.current = sceneResponse.data.parent;
|
|
9622
9724
|
ancestryDataRef.current = sceneResponse.data.ancestry;
|
|
9623
|
-
console.log("Console de sceneDataRef.current no useEffect inicial:", sceneDataRef.current);
|
|
9624
|
-
console.log("Console de parentDataRef.current no useEffect inicial:", parentDataRef.current);
|
|
9625
|
-
console.log("Console de ancestryDataRef.current no useEffect inicial:", ancestryDataRef.current);
|
|
9626
9725
|
setIsInitialized(true);
|
|
9627
9726
|
} else {
|
|
9628
9727
|
console.error("Falha ao buscar dados da cena:", (sceneResponse == null ? void 0 : sceneResponse.error) || "Resposta inv\xE1lida.");
|
|
@@ -9630,7 +9729,6 @@ function XViewScene({
|
|
|
9630
9729
|
if (boardResponse == null ? void 0 : boardResponse.success) {
|
|
9631
9730
|
setAncestryBoardData(boardResponse.data);
|
|
9632
9731
|
} else {
|
|
9633
|
-
console.warn("Ancestry Board n\xE3o carregado ou vazio:", boardResponse == null ? void 0 : boardResponse.error);
|
|
9634
9732
|
setAncestryBoardData([]);
|
|
9635
9733
|
}
|
|
9636
9734
|
} catch (error) {
|
|
@@ -9654,11 +9752,14 @@ function XViewScene({
|
|
|
9654
9752
|
status,
|
|
9655
9753
|
ownerId,
|
|
9656
9754
|
viewParams,
|
|
9657
|
-
// Importante incluir viewParams nas dependências
|
|
9658
9755
|
get_scene_view_data,
|
|
9659
9756
|
get_ancestry_board_action,
|
|
9660
9757
|
isInitialized,
|
|
9661
|
-
permissionStatus
|
|
9758
|
+
permissionStatus,
|
|
9759
|
+
focusNodeId,
|
|
9760
|
+
// <-- MANTIDO
|
|
9761
|
+
focusAncestryId
|
|
9762
|
+
// <-- ADICIONADO O focusAncestryId NAS DEPENDÊNCIAS
|
|
9662
9763
|
]);
|
|
9663
9764
|
const isNodeInView = useCallback3((id) => {
|
|
9664
9765
|
const key = String(id);
|
|
@@ -9692,7 +9793,7 @@ function XViewScene({
|
|
|
9692
9793
|
}
|
|
9693
9794
|
return mesh;
|
|
9694
9795
|
}, []);
|
|
9695
|
-
|
|
9796
|
+
useEffect21(() => {
|
|
9696
9797
|
if (!isInitialized || !sceneDataRef.current) return;
|
|
9697
9798
|
const currentMount = mountRef.current;
|
|
9698
9799
|
if (!currentMount) return;
|
|
@@ -11942,6 +12043,34 @@ function XViewScene({
|
|
|
11942
12043
|
tweenToTarget(nodeMesh, 1.2);
|
|
11943
12044
|
}
|
|
11944
12045
|
}, [tweenToTarget]);
|
|
12046
|
+
useEffect21(() => {
|
|
12047
|
+
if (isInitialized && focusNodeId && !hasFocusedInitial) {
|
|
12048
|
+
const nodeObjects = stateRef.current.nodeObjects || {};
|
|
12049
|
+
const targetMesh = nodeObjects[String(focusNodeId)];
|
|
12050
|
+
if (targetMesh) {
|
|
12051
|
+
setTimeout(() => {
|
|
12052
|
+
tweenToTarget(targetMesh, 1.2);
|
|
12053
|
+
setHasFocusedInitial(true);
|
|
12054
|
+
}, 300);
|
|
12055
|
+
} else {
|
|
12056
|
+
setHasFocusedInitial(true);
|
|
12057
|
+
}
|
|
12058
|
+
}
|
|
12059
|
+
}, [isInitialized, sceneVersion, focusNodeId, hasFocusedInitial, tweenToTarget]);
|
|
12060
|
+
useEffect21(() => {
|
|
12061
|
+
if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
|
|
12062
|
+
const ancestries = ancestryDataRef.current || [];
|
|
12063
|
+
const targetAncestry = ancestries.find((a) => String(a.ancestry_id) === String(focusAncestryId));
|
|
12064
|
+
if (targetAncestry) {
|
|
12065
|
+
setTimeout(() => {
|
|
12066
|
+
handleStartReadingAncestry(targetAncestry);
|
|
12067
|
+
setHasOpenedInitialAncestry(true);
|
|
12068
|
+
}, 300);
|
|
12069
|
+
} else {
|
|
12070
|
+
setHasOpenedInitialAncestry(true);
|
|
12071
|
+
}
|
|
12072
|
+
}
|
|
12073
|
+
}, [isInitialized, sceneVersion, focusAncestryId, hasOpenedInitialAncestry, handleStartReadingAncestry]);
|
|
11945
12074
|
if (isLoading || status === "loading" || permissionStatus === "loading") {
|
|
11946
12075
|
return /* @__PURE__ */ React23.createElement(LoadingScreen, null);
|
|
11947
12076
|
}
|
|
@@ -12036,6 +12165,7 @@ function XViewScene({
|
|
|
12036
12165
|
DescriptionReadModePanel,
|
|
12037
12166
|
{
|
|
12038
12167
|
key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
|
|
12168
|
+
ancestryId: readingMode.ancestry.ancestry_id,
|
|
12039
12169
|
title: (getReadModeDisplayContext == null ? void 0 : getReadModeDisplayContext.name) || readingMode.ancestry.name || "Ancestralidade",
|
|
12040
12170
|
initialSectionId: readingMode.initialSectionId,
|
|
12041
12171
|
description: getReadModeDisplayContext == null ? void 0 : getReadModeDisplayContext.description,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lv-x-software-house/x_view",
|
|
3
|
-
"version": "1.2.1-dev.
|
|
3
|
+
"version": "1.2.1-dev.10",
|
|
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",
|