@lv-x-software-house/x_view 1.2.4 → 1.2.5-dev.1
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 +1665 -809
- package/dist/index.mjs +1672 -810
- package/package.json +52 -43
package/dist/index.js
CHANGED
|
@@ -9890,7 +9890,6 @@ var GroupItem = ({
|
|
|
9890
9890
|
onPlayAncestry,
|
|
9891
9891
|
availableIds,
|
|
9892
9892
|
canEdit
|
|
9893
|
-
// [NOVO] Recebe permissão de edição
|
|
9894
9893
|
}) => {
|
|
9895
9894
|
const canIndent = index > 0;
|
|
9896
9895
|
const isPickingForThisGroup = pickingGroupId === group.id;
|
|
@@ -9905,107 +9904,126 @@ var GroupItem = ({
|
|
|
9905
9904
|
(0, import_react25.useEffect)(() => {
|
|
9906
9905
|
adjustHeight();
|
|
9907
9906
|
}, [group.text]);
|
|
9908
|
-
return /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react25.default.createElement(
|
|
9907
|
+
return /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react25.default.createElement(
|
|
9908
|
+
"div",
|
|
9909
|
+
{
|
|
9910
|
+
className: `
|
|
9909
9911
|
flex flex-col gap-2 py-2 px-3 transition-all duration-200
|
|
9910
9912
|
${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
|
|
9911
|
-
`
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
className: `w-full bg-transparent text-sm text-slate-200 placeholder-slate-600 resize-none focus:outline-none focus:placeholder-slate-500 overflow-y-auto ${!canEdit ? "cursor-default" : ""}`,
|
|
9916
|
-
rows: 1,
|
|
9917
|
-
style: {
|
|
9918
|
-
minHeight: "1.5rem",
|
|
9919
|
-
maxHeight: "250px"
|
|
9920
|
-
},
|
|
9921
|
-
placeholder: canEdit ? "Escreva sobre este grupo..." : "",
|
|
9922
|
-
value: group.text,
|
|
9923
|
-
readOnly: !canEdit,
|
|
9924
|
-
onChange: (e) => {
|
|
9925
|
-
if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
|
|
9926
|
-
}
|
|
9927
|
-
}
|
|
9928
|
-
), group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
|
|
9929
|
-
const isValid = availableIds.has(String(anc.ancestry_id));
|
|
9930
|
-
return /* @__PURE__ */ import_react25.default.createElement(
|
|
9931
|
-
"div",
|
|
9913
|
+
`
|
|
9914
|
+
},
|
|
9915
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
9916
|
+
"textarea",
|
|
9932
9917
|
{
|
|
9933
|
-
|
|
9934
|
-
className: `
|
|
9918
|
+
ref: textareaRef,
|
|
9919
|
+
className: `w-full bg-transparent text-sm text-slate-200 placeholder-slate-600 resize-none focus:outline-none focus:placeholder-slate-500 overflow-y-auto ${!canEdit ? "cursor-default" : ""}`,
|
|
9920
|
+
rows: 1,
|
|
9921
|
+
style: {
|
|
9922
|
+
minHeight: "1.5rem",
|
|
9923
|
+
maxHeight: "250px"
|
|
9924
|
+
},
|
|
9925
|
+
placeholder: canEdit ? "Escreva sobre este grupo..." : "",
|
|
9926
|
+
value: group.text,
|
|
9927
|
+
readOnly: !canEdit,
|
|
9928
|
+
onChange: (e) => {
|
|
9929
|
+
if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
|
|
9930
|
+
}
|
|
9931
|
+
}
|
|
9932
|
+
),
|
|
9933
|
+
group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
|
|
9934
|
+
const isValid = availableIds.has(String(anc.ancestry_id));
|
|
9935
|
+
return /* @__PURE__ */ import_react25.default.createElement(
|
|
9936
|
+
"div",
|
|
9937
|
+
{
|
|
9938
|
+
key: anc.ancestry_id,
|
|
9939
|
+
className: `
|
|
9935
9940
|
flex items-center gap-2 rounded-md px-3 py-1.5 text-xs transition-all group/card border
|
|
9936
9941
|
${isValid ? "bg-slate-800/60 border-white/10 hover:border-indigo-500/30 text-slate-200" : "bg-red-900/10 border-red-500/30 text-red-300/70 hover:bg-red-900/20"}
|
|
9937
9942
|
`,
|
|
9938
|
-
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9943
|
+
title: isValid ? "" : "Esta ancestralidade foi removida ou n\xE3o existe mais."
|
|
9944
|
+
},
|
|
9945
|
+
isValid ? (
|
|
9946
|
+
// [MANTIDO] Botão Play visível para todos
|
|
9947
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
9948
|
+
"button",
|
|
9949
|
+
{
|
|
9950
|
+
onClick: () => onPlayAncestry(anc.ancestry_id),
|
|
9951
|
+
className: "text-indigo-400 hover:text-white hover:bg-indigo-500 p-1 rounded-full transition-colors",
|
|
9952
|
+
title: "Renderizar no cen\xE1rio"
|
|
9953
|
+
},
|
|
9954
|
+
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiPlay, { size: 10, className: "ml-0.5 fill-current" })
|
|
9955
|
+
)
|
|
9956
|
+
) : /* @__PURE__ */ import_react25.default.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiAlertTriangle, { size: 10 })),
|
|
9942
9957
|
/* @__PURE__ */ import_react25.default.createElement(
|
|
9958
|
+
"span",
|
|
9959
|
+
{
|
|
9960
|
+
className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}`
|
|
9961
|
+
},
|
|
9962
|
+
anc.name
|
|
9963
|
+
),
|
|
9964
|
+
canEdit && /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement(
|
|
9965
|
+
"div",
|
|
9966
|
+
{
|
|
9967
|
+
className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}`
|
|
9968
|
+
}
|
|
9969
|
+
), /* @__PURE__ */ import_react25.default.createElement(
|
|
9943
9970
|
"button",
|
|
9944
9971
|
{
|
|
9945
|
-
onClick: () =>
|
|
9946
|
-
className: "text-
|
|
9947
|
-
title: "
|
|
9972
|
+
onClick: () => onRemoveAncestry(group.id, anc.ancestry_id),
|
|
9973
|
+
className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
|
|
9974
|
+
title: "Remover men\xE7\xE3o"
|
|
9948
9975
|
},
|
|
9949
|
-
/* @__PURE__ */ import_react25.default.createElement(import_fi19.
|
|
9950
|
-
)
|
|
9951
|
-
)
|
|
9952
|
-
|
|
9953
|
-
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
title: "Remover men\xE7\xE3o"
|
|
9959
|
-
},
|
|
9960
|
-
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiX, { size: 12 })
|
|
9961
|
-
))
|
|
9962
|
-
);
|
|
9963
|
-
})), canEdit && /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
9964
|
-
"button",
|
|
9965
|
-
{
|
|
9966
|
-
onClick: () => onRequestPickAncestry(group.id),
|
|
9967
|
-
className: `
|
|
9976
|
+
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiX, { size: 12 })
|
|
9977
|
+
))
|
|
9978
|
+
);
|
|
9979
|
+
})),
|
|
9980
|
+
canEdit && /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
9981
|
+
"button",
|
|
9982
|
+
{
|
|
9983
|
+
onClick: () => onRequestPickAncestry(group.id),
|
|
9984
|
+
className: `
|
|
9968
9985
|
flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium transition-colors
|
|
9969
9986
|
${isPickingForThisGroup ? "text-indigo-300 animate-pulse" : "text-slate-500 hover:text-indigo-300 hover:bg-indigo-500/10"}
|
|
9970
9987
|
`,
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
9974
|
-
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
9981
|
-
|
|
9982
|
-
|
|
9983
|
-
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
9988
|
+
title: "Adicionar Ancestralidade a este grupo"
|
|
9989
|
+
},
|
|
9990
|
+
isPickingForThisGroup ? /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiCheckCircle, { size: 12 }) : /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiSearch, { size: 12 }),
|
|
9991
|
+
isPickingForThisGroup ? "Selecionando..." : "Adicionar"
|
|
9992
|
+
), /* @__PURE__ */ import_react25.default.createElement(
|
|
9993
|
+
"button",
|
|
9994
|
+
{
|
|
9995
|
+
onClick: () => onAddSubgroup(group.id),
|
|
9996
|
+
className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
|
|
9997
|
+
title: "Criar Subgrupo"
|
|
9998
|
+
},
|
|
9999
|
+
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiPlus, { size: 14 })
|
|
10000
|
+
)), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
10001
|
+
"button",
|
|
10002
|
+
{
|
|
10003
|
+
onClick: () => onIndent(group.id),
|
|
10004
|
+
disabled: !canIndent,
|
|
10005
|
+
className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
|
|
10006
|
+
title: "Aninhar no grupo acima"
|
|
10007
|
+
},
|
|
10008
|
+
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiArrowRight, { size: 14 })
|
|
10009
|
+
), /* @__PURE__ */ import_react25.default.createElement(
|
|
10010
|
+
"button",
|
|
10011
|
+
{
|
|
10012
|
+
onClick: () => onOutdent(group.id),
|
|
10013
|
+
className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
|
|
10014
|
+
title: "Desaninhar"
|
|
10015
|
+
},
|
|
10016
|
+
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiArrowLeft, { size: 14 })
|
|
10017
|
+
), /* @__PURE__ */ import_react25.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react25.default.createElement(
|
|
10018
|
+
"button",
|
|
10019
|
+
{
|
|
10020
|
+
onClick: () => onDelete(group.id),
|
|
10021
|
+
className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
|
|
10022
|
+
title: "Remover Grupo"
|
|
10023
|
+
},
|
|
10024
|
+
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiTrash2, { size: 14 })
|
|
10025
|
+
)))
|
|
10026
|
+
), group.children && group.children.length > 0 && /* @__PURE__ */ import_react25.default.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ import_react25.default.createElement(
|
|
10009
10027
|
GroupItem,
|
|
10010
10028
|
{
|
|
10011
10029
|
key: childGroup.id,
|
|
@@ -10214,7 +10232,9 @@ function AncestryBoard({
|
|
|
10214
10232
|
const addRecursive = (list) => {
|
|
10215
10233
|
return list.map((g) => {
|
|
10216
10234
|
if (g.id === pickingGroupId) {
|
|
10217
|
-
const exists = g.ancestries.some(
|
|
10235
|
+
const exists = g.ancestries.some(
|
|
10236
|
+
(a) => a.ancestry_id === ancestry.ancestry_id
|
|
10237
|
+
);
|
|
10218
10238
|
if (exists) return g;
|
|
10219
10239
|
return { ...g, ancestries: [...g.ancestries, ancestry] };
|
|
10220
10240
|
}
|
|
@@ -10225,12 +10245,16 @@ function AncestryBoard({
|
|
|
10225
10245
|
});
|
|
10226
10246
|
setPickingGroupId(null);
|
|
10227
10247
|
} else {
|
|
10228
|
-
const fullAncestry = availableAncestries.find(
|
|
10248
|
+
const fullAncestry = availableAncestries.find(
|
|
10249
|
+
(a) => a.ancestry_id === ancestry.ancestry_id
|
|
10250
|
+
) || ancestry;
|
|
10229
10251
|
onSelect(fullAncestry);
|
|
10230
10252
|
}
|
|
10231
10253
|
};
|
|
10232
10254
|
const handlePlayFromGroup = (ancestryId) => {
|
|
10233
|
-
const fullAncestry = availableAncestries.find(
|
|
10255
|
+
const fullAncestry = availableAncestries.find(
|
|
10256
|
+
(a) => a.ancestry_id === ancestryId
|
|
10257
|
+
);
|
|
10234
10258
|
if (fullAncestry && onSelect) {
|
|
10235
10259
|
onSelect(fullAncestry);
|
|
10236
10260
|
}
|
|
@@ -10240,7 +10264,12 @@ function AncestryBoard({
|
|
|
10240
10264
|
const removeRecursive = (list) => {
|
|
10241
10265
|
return list.map((g) => {
|
|
10242
10266
|
if (g.id === groupId) {
|
|
10243
|
-
return {
|
|
10267
|
+
return {
|
|
10268
|
+
...g,
|
|
10269
|
+
ancestries: g.ancestries.filter(
|
|
10270
|
+
(a) => a.ancestry_id !== ancestryId
|
|
10271
|
+
)
|
|
10272
|
+
};
|
|
10244
10273
|
}
|
|
10245
10274
|
return { ...g, children: removeRecursive(g.children) };
|
|
10246
10275
|
});
|
|
@@ -10261,7 +10290,13 @@ function AncestryBoard({
|
|
|
10261
10290
|
className: "bg-slate-950 border border-white/10 rounded-xl w-[98vw] h-[97vh] flex flex-col shadow-2xl overflow-hidden animate-in fade-in zoom-in-95 duration-200",
|
|
10262
10291
|
onClick: (e) => e.stopPropagation()
|
|
10263
10292
|
},
|
|
10264
|
-
/* @__PURE__ */ import_react25.default.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react25.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement(
|
|
10293
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react25.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement(
|
|
10294
|
+
import_fi19.FiLoader,
|
|
10295
|
+
{
|
|
10296
|
+
className: "animate-spin text-indigo-400",
|
|
10297
|
+
size: 12
|
|
10298
|
+
}
|
|
10299
|
+
), /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-xs text-indigo-300 font-medium animate-pulse hidden sm:inline-block mr-2" }, "Selecione na lateral..."), canEdit && /* @__PURE__ */ import_react25.default.createElement(
|
|
10265
10300
|
"button",
|
|
10266
10301
|
{
|
|
10267
10302
|
onClick: handleAddRootGroup,
|
|
@@ -10277,57 +10312,75 @@ function AncestryBoard({
|
|
|
10277
10312
|
},
|
|
10278
10313
|
"\xD7"
|
|
10279
10314
|
))),
|
|
10280
|
-
/* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
10315
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
10316
|
+
"div",
|
|
10317
|
+
{
|
|
10318
|
+
className: `
|
|
10281
10319
|
flex flex-col border-r border-white/10 transition-all duration-300 flex-none
|
|
10282
10320
|
${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
|
|
10283
10321
|
min-w-[280px] max-w-[500px] bg-slate-900
|
|
10284
|
-
`
|
|
10285
|
-
|
|
10286
|
-
{
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10322
|
+
`
|
|
10323
|
+
},
|
|
10324
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "relative group" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
10325
|
+
import_fi19.FiSearch,
|
|
10326
|
+
{
|
|
10327
|
+
className: `absolute left-3 top-1/2 -translate-y-1/2 transition-colors ${pickingGroupId ? "text-indigo-400" : "text-slate-500 group-focus-within:text-indigo-400"}`
|
|
10328
|
+
}
|
|
10329
|
+
), /* @__PURE__ */ import_react25.default.createElement(
|
|
10330
|
+
"input",
|
|
10331
|
+
{
|
|
10332
|
+
type: "text",
|
|
10333
|
+
placeholder: pickingGroupId ? "Pesquise para adicionar..." : "Pesquisar ancestralidade...",
|
|
10334
|
+
className: `
|
|
10290
10335
|
w-full rounded-md pl-9 pr-4 py-2 text-sm transition-all focus:outline-none focus:ring-1 focus:ring-indigo-500 border
|
|
10291
10336
|
${pickingGroupId ? "bg-indigo-950/30 border-indigo-500/30 text-white placeholder-indigo-300/50" : "bg-slate-950 border-white/10 text-slate-200 placeholder-slate-600"}
|
|
10292
10337
|
`,
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
10296
|
-
|
|
10297
|
-
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
|
|
10303
|
-
|
|
10304
|
-
|
|
10305
|
-
|
|
10306
|
-
|
|
10307
|
-
|
|
10338
|
+
value: searchTerm,
|
|
10339
|
+
onChange: (e) => setSearchTerm(e.target.value),
|
|
10340
|
+
autoFocus: !pickingGroupId
|
|
10341
|
+
}
|
|
10342
|
+
))),
|
|
10343
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
|
|
10344
|
+
const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
|
|
10345
|
+
const isPicking = !!pickingGroupId;
|
|
10346
|
+
return /* @__PURE__ */ import_react25.default.createElement(
|
|
10347
|
+
"div",
|
|
10348
|
+
{
|
|
10349
|
+
key: anc.ancestry_id,
|
|
10350
|
+
onClick: () => {
|
|
10351
|
+
if (isPicking) handleSelectAncestry(anc);
|
|
10352
|
+
},
|
|
10353
|
+
className: `
|
|
10308
10354
|
group relative flex items-start gap-3 p-3 text-left rounded-lg border transition-all duration-200
|
|
10309
10355
|
${isPicking ? "border-indigo-500/30 bg-indigo-500/5 hover:bg-indigo-500/20 hover:border-indigo-400 cursor-pointer" : "border-white/5 bg-slate-800/40 hover:bg-indigo-600/10 hover:border-indigo-500/30 cursor-default"}
|
|
10310
10356
|
`
|
|
10311
|
-
|
|
10312
|
-
|
|
10357
|
+
},
|
|
10358
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
10359
|
+
"div",
|
|
10360
|
+
{
|
|
10361
|
+
className: `
|
|
10313
10362
|
mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
|
|
10314
10363
|
${isPicking ? "bg-indigo-500 text-white border-indigo-400" : "bg-slate-800 text-indigo-400 border-white/5 group-hover:bg-indigo-500 group-hover:text-white"}
|
|
10315
|
-
`
|
|
10316
|
-
/* @__PURE__ */ import_react25.default.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react25.default.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, anc.name || "Sem Nome"), anc.is_private && /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-300 border border-amber-500/20" }, "Priv")), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiCornerUpRight, { size: 10 }), /* @__PURE__ */ import_react25.default.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.description && /* @__PURE__ */ import_react25.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
|
|
10317
|
-
!isPicking && /* @__PURE__ */ import_react25.default.createElement(
|
|
10318
|
-
"button",
|
|
10319
|
-
{
|
|
10320
|
-
onClick: (e) => {
|
|
10321
|
-
e.stopPropagation();
|
|
10322
|
-
handleSelectAncestry(anc);
|
|
10364
|
+
`
|
|
10323
10365
|
},
|
|
10324
|
-
|
|
10325
|
-
|
|
10326
|
-
},
|
|
10327
|
-
|
|
10328
|
-
|
|
10329
|
-
|
|
10330
|
-
|
|
10366
|
+
isPicking ? /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiPlus, { size: 16 }) : /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiLayers, { size: 14 })
|
|
10367
|
+
),
|
|
10368
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react25.default.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, anc.name || "Sem Nome"), anc.is_private && /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-300 border border-amber-500/20" }, "Priv")), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiCornerUpRight, { size: 10 }), /* @__PURE__ */ import_react25.default.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.description && /* @__PURE__ */ import_react25.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
|
|
10369
|
+
!isPicking && /* @__PURE__ */ import_react25.default.createElement(
|
|
10370
|
+
"button",
|
|
10371
|
+
{
|
|
10372
|
+
onClick: (e) => {
|
|
10373
|
+
e.stopPropagation();
|
|
10374
|
+
handleSelectAncestry(anc);
|
|
10375
|
+
},
|
|
10376
|
+
className: "absolute right-2 bottom-2 opacity-0 group-hover:opacity-100 transition-all duration-300 transform translate-y-2 group-hover:translate-y-0 z-10",
|
|
10377
|
+
title: "Renderizar Ancestralidade"
|
|
10378
|
+
},
|
|
10379
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiPlay, { size: 14, className: "ml-0.5" }))
|
|
10380
|
+
)
|
|
10381
|
+
);
|
|
10382
|
+
}))
|
|
10383
|
+
), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-3 border-2 border-dashed border-white/5 rounded-xl m-4 bg-slate-900/20" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiLayers, { size: 24, className: "opacity-20" }), /* @__PURE__ */ import_react25.default.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ import_react25.default.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ import_react25.default.createElement(
|
|
10331
10384
|
GroupItem,
|
|
10332
10385
|
{
|
|
10333
10386
|
key: group.id,
|
|
@@ -10406,7 +10459,10 @@ var findNodePath3 = (tree, targetNodeId, currentPath = []) => {
|
|
|
10406
10459
|
}
|
|
10407
10460
|
if (tree.children) {
|
|
10408
10461
|
for (let i = 0; i < tree.children.length; i++) {
|
|
10409
|
-
const res = findNodePath3(tree.children[i], targetNodeId, [
|
|
10462
|
+
const res = findNodePath3(tree.children[i], targetNodeId, [
|
|
10463
|
+
...currentPath,
|
|
10464
|
+
i
|
|
10465
|
+
]);
|
|
10410
10466
|
if (res) return res;
|
|
10411
10467
|
}
|
|
10412
10468
|
}
|
|
@@ -10499,27 +10555,70 @@ function XViewScene({
|
|
|
10499
10555
|
const [userPermissionRole, setUserPermissionRole] = (0, import_react26.useState)(null);
|
|
10500
10556
|
const [isInitialized, setIsInitialized] = (0, import_react26.useState)(false);
|
|
10501
10557
|
const [sceneVersion, setSceneVersion] = (0, import_react26.useState)(0);
|
|
10502
|
-
const [contextMenu, setContextMenu] = (0, import_react26.useState)({
|
|
10503
|
-
|
|
10504
|
-
|
|
10505
|
-
|
|
10506
|
-
|
|
10558
|
+
const [contextMenu, setContextMenu] = (0, import_react26.useState)({
|
|
10559
|
+
visible: false,
|
|
10560
|
+
x: 0,
|
|
10561
|
+
y: 0,
|
|
10562
|
+
nodeData: null
|
|
10563
|
+
});
|
|
10564
|
+
const [multiContextMenu, setMultiContextMenu] = (0, import_react26.useState)({
|
|
10565
|
+
visible: false,
|
|
10566
|
+
x: 0,
|
|
10567
|
+
y: 0,
|
|
10568
|
+
nodeIds: null
|
|
10569
|
+
});
|
|
10570
|
+
const [relationshipMenu, setRelationshipMenu] = (0, import_react26.useState)({
|
|
10571
|
+
visible: false,
|
|
10572
|
+
x: 0,
|
|
10573
|
+
y: 0,
|
|
10574
|
+
linkObject: null
|
|
10575
|
+
});
|
|
10576
|
+
const [creationMode, setCreationMode] = (0, import_react26.useState)({
|
|
10577
|
+
isActive: false,
|
|
10578
|
+
sourceNodeData: null
|
|
10579
|
+
});
|
|
10580
|
+
const [versionMode, setVersionMode] = (0, import_react26.useState)({
|
|
10581
|
+
isActive: false,
|
|
10582
|
+
sourceNodeData: null
|
|
10583
|
+
});
|
|
10507
10584
|
const [questMode, setQuestMode] = (0, import_react26.useState)({ isActive: false });
|
|
10508
10585
|
const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react26.useState)(false);
|
|
10509
10586
|
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react26.useState)(false);
|
|
10510
|
-
const [ancestryMode, setAncestryMode] = (0, import_react26.useState)({
|
|
10587
|
+
const [ancestryMode, setAncestryMode] = (0, import_react26.useState)({
|
|
10588
|
+
isActive: false,
|
|
10589
|
+
tree: null,
|
|
10590
|
+
selectedParentId: null,
|
|
10591
|
+
isEditMode: false,
|
|
10592
|
+
currentAncestryId: null,
|
|
10593
|
+
ancestryName: "",
|
|
10594
|
+
ancestryDescription: "",
|
|
10595
|
+
ancestryDescriptionSections: [],
|
|
10596
|
+
isAddingNodes: false
|
|
10597
|
+
});
|
|
10511
10598
|
const [readingMode, setReadingMode] = (0, import_react26.useState)({
|
|
10512
10599
|
isActive: false,
|
|
10513
10600
|
ancestry: null,
|
|
10514
10601
|
branchStack: [],
|
|
10515
10602
|
autoAbstraction: false
|
|
10516
10603
|
});
|
|
10517
|
-
const [formPosition, setFormPosition] = (0, import_react26.useState)({
|
|
10604
|
+
const [formPosition, setFormPosition] = (0, import_react26.useState)({
|
|
10605
|
+
left: 16,
|
|
10606
|
+
top: 16,
|
|
10607
|
+
opacity: 0
|
|
10608
|
+
});
|
|
10518
10609
|
const [detailsNode, setDetailsNode] = (0, import_react26.useState)(null);
|
|
10519
10610
|
const [detailsLink, setDetailsLink] = (0, import_react26.useState)(null);
|
|
10520
10611
|
const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react26.useState)(null);
|
|
10521
|
-
const [imageViewer, setImageViewer] = (0, import_react26.useState)({
|
|
10522
|
-
|
|
10612
|
+
const [imageViewer, setImageViewer] = (0, import_react26.useState)({
|
|
10613
|
+
visible: false,
|
|
10614
|
+
images: [],
|
|
10615
|
+
startIndex: 0
|
|
10616
|
+
});
|
|
10617
|
+
const [editingAncestryRel, setEditingAncestryRel] = (0, import_react26.useState)({
|
|
10618
|
+
visible: false,
|
|
10619
|
+
data: null,
|
|
10620
|
+
path: null
|
|
10621
|
+
});
|
|
10523
10622
|
const [isImportModalOpen, setIsImportModalOpen] = (0, import_react26.useState)(false);
|
|
10524
10623
|
const [importSuccessMessage, setImportSuccessMessage] = (0, import_react26.useState)("");
|
|
10525
10624
|
const [highlightedNodeId, setHighlightedNodeId] = (0, import_react26.useState)(null);
|
|
@@ -10559,8 +10658,23 @@ function XViewScene({
|
|
|
10559
10658
|
ghostElements: { node: null, line: null, aura: null },
|
|
10560
10659
|
creation: { isActive: false, sourceNodeData: null },
|
|
10561
10660
|
connection: { isActive: false, sourceNodeData: null, line: null },
|
|
10562
|
-
relink: {
|
|
10563
|
-
|
|
10661
|
+
relink: {
|
|
10662
|
+
isActive: false,
|
|
10663
|
+
end: null,
|
|
10664
|
+
fixedNodeId: null,
|
|
10665
|
+
originalLine: null,
|
|
10666
|
+
line: null
|
|
10667
|
+
},
|
|
10668
|
+
ancestry: {
|
|
10669
|
+
isActive: false,
|
|
10670
|
+
tree: null,
|
|
10671
|
+
selectedParentId: null,
|
|
10672
|
+
isEditMode: false,
|
|
10673
|
+
currentAncestryId: null,
|
|
10674
|
+
ancestryName: "",
|
|
10675
|
+
ancestryDescription: "",
|
|
10676
|
+
isAddingNodes: false
|
|
10677
|
+
},
|
|
10564
10678
|
glowTexture: null,
|
|
10565
10679
|
nodeIdToParentFileMap: null,
|
|
10566
10680
|
maxAncestryRenderIndex: 0,
|
|
@@ -10569,7 +10683,11 @@ function XViewScene({
|
|
|
10569
10683
|
highlightedNodeId: null
|
|
10570
10684
|
});
|
|
10571
10685
|
const maxReadPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
10572
|
-
const {
|
|
10686
|
+
const {
|
|
10687
|
+
width: readModeWidth,
|
|
10688
|
+
isResizing: isReadModeResizing,
|
|
10689
|
+
handlePointerDown: handleReadModeResize
|
|
10690
|
+
} = useResizablePanel({
|
|
10573
10691
|
initialWidth: 700,
|
|
10574
10692
|
minWidth: 320,
|
|
10575
10693
|
maxWidth: maxReadPanelW
|
|
@@ -10586,7 +10704,9 @@ function XViewScene({
|
|
|
10586
10704
|
for (const parentFileId in allParentData) {
|
|
10587
10705
|
if (allParentData.hasOwnProperty(parentFileId)) {
|
|
10588
10706
|
const parentFile = allParentData[parentFileId];
|
|
10589
|
-
const parentDbInfo = parentDbsArray.find(
|
|
10707
|
+
const parentDbInfo = parentDbsArray.find(
|
|
10708
|
+
(db) => String(db.db_id) === String(parentFileId)
|
|
10709
|
+
);
|
|
10590
10710
|
const ownerId2 = (parentDbInfo == null ? void 0 : parentDbInfo.owner_id) || null;
|
|
10591
10711
|
const datasetName = parentFile.dataset_name || `Dataset #${parentFileId.substring(0, 6)}`;
|
|
10592
10712
|
if (parentFile.nodes && ownerId2) {
|
|
@@ -10622,7 +10742,10 @@ function XViewScene({
|
|
|
10622
10742
|
if (files.length > 0 && get_single_parent_file && save_view_data) {
|
|
10623
10743
|
for (const file of files) {
|
|
10624
10744
|
try {
|
|
10625
|
-
const parentFileData = await get_single_parent_file(
|
|
10745
|
+
const parentFileData = await get_single_parent_file(
|
|
10746
|
+
file.id,
|
|
10747
|
+
session
|
|
10748
|
+
);
|
|
10626
10749
|
if (parentFileData.success && parentFileData.data) {
|
|
10627
10750
|
parentDataRef.current = {
|
|
10628
10751
|
...parentDataRef.current,
|
|
@@ -10633,7 +10756,11 @@ function XViewScene({
|
|
|
10633
10756
|
owner_id: session.user.id
|
|
10634
10757
|
};
|
|
10635
10758
|
updatedParentDbs.push(newParentDbObject);
|
|
10636
|
-
await add_new_parent_file_to_scene_at_firebase_action(
|
|
10759
|
+
await add_new_parent_file_to_scene_at_firebase_action(
|
|
10760
|
+
sceneConfigId,
|
|
10761
|
+
session,
|
|
10762
|
+
file.id
|
|
10763
|
+
);
|
|
10637
10764
|
importedIds.push(file.id);
|
|
10638
10765
|
successCount++;
|
|
10639
10766
|
}
|
|
@@ -10645,7 +10772,10 @@ function XViewScene({
|
|
|
10645
10772
|
if (viewToImport && get_ancestry_file) {
|
|
10646
10773
|
try {
|
|
10647
10774
|
const targetViewOwnerId = ((_b2 = (_a2 = viewToImport.members) == null ? void 0 : _a2.find((m) => m.permission === "owner")) == null ? void 0 : _b2.id) || session.user.id;
|
|
10648
|
-
const ancestryResponse = await get_ancestry_file(
|
|
10775
|
+
const ancestryResponse = await get_ancestry_file(
|
|
10776
|
+
viewToImport.id,
|
|
10777
|
+
targetViewOwnerId
|
|
10778
|
+
);
|
|
10649
10779
|
if (ancestryResponse.success && Array.isArray(ancestryResponse.data)) {
|
|
10650
10780
|
const viewSpecificAncestries = ancestryResponse.data.filter(
|
|
10651
10781
|
(anc) => anc._source_file_id === viewToImport.id && !anc.is_private
|
|
@@ -10656,14 +10786,21 @@ function XViewScene({
|
|
|
10656
10786
|
_imported_from_view_owner_id: targetViewOwnerId,
|
|
10657
10787
|
_source_file_id: viewToImport.id,
|
|
10658
10788
|
_source_owner_id: targetViewOwnerId,
|
|
10659
|
-
_origin_db_ids: (viewToImport.selected_databases || []).map(
|
|
10789
|
+
_origin_db_ids: (viewToImport.selected_databases || []).map(
|
|
10790
|
+
(db) => db.db_id
|
|
10791
|
+
)
|
|
10660
10792
|
}));
|
|
10661
10793
|
const currentAncestries = ancestryDataRef.current || [];
|
|
10662
10794
|
const newAncestries = processedAncestries.filter(
|
|
10663
|
-
(newAnc) => !currentAncestries.some(
|
|
10795
|
+
(newAnc) => !currentAncestries.some(
|
|
10796
|
+
(curr) => String(curr.ancestry_id) === String(newAnc.ancestry_id)
|
|
10797
|
+
)
|
|
10664
10798
|
);
|
|
10665
10799
|
if (newAncestries.length > 0) {
|
|
10666
|
-
ancestryDataRef.current = [
|
|
10800
|
+
ancestryDataRef.current = [
|
|
10801
|
+
...currentAncestries,
|
|
10802
|
+
...newAncestries
|
|
10803
|
+
];
|
|
10667
10804
|
ancestriesWereImported = true;
|
|
10668
10805
|
}
|
|
10669
10806
|
}
|
|
@@ -10683,7 +10820,9 @@ function XViewScene({
|
|
|
10683
10820
|
if (ancestry_save_url) {
|
|
10684
10821
|
await save_view_data(ancestry_save_url, ancestryDataRef.current);
|
|
10685
10822
|
} else {
|
|
10686
|
-
console.error(
|
|
10823
|
+
console.error(
|
|
10824
|
+
"Erro: URL de salvamento de ancestralidade n\xE3o definida."
|
|
10825
|
+
);
|
|
10687
10826
|
}
|
|
10688
10827
|
}
|
|
10689
10828
|
setSceneVersion((v) => v + 1);
|
|
@@ -10691,113 +10830,136 @@ function XViewScene({
|
|
|
10691
10830
|
setImportSuccessMessage("Importa\xE7\xE3o conclu\xEDda com sucesso.");
|
|
10692
10831
|
setTimeout(() => setImportSuccessMessage(""), 5e3);
|
|
10693
10832
|
} else if (viewToImport && !ancestriesWereImported) {
|
|
10694
|
-
console.warn(
|
|
10833
|
+
console.warn(
|
|
10834
|
+
"Importa\xE7\xE3o finalizada, mas nenhum dado novo foi adicionado."
|
|
10835
|
+
);
|
|
10695
10836
|
}
|
|
10696
10837
|
},
|
|
10697
|
-
[
|
|
10838
|
+
[
|
|
10839
|
+
get_single_parent_file,
|
|
10840
|
+
get_ancestry_file,
|
|
10841
|
+
save_view_data,
|
|
10842
|
+
session,
|
|
10843
|
+
sceneSaveUrl,
|
|
10844
|
+
ancestry_save_url,
|
|
10845
|
+
sceneConfigId,
|
|
10846
|
+
add_new_parent_file_to_scene_at_firebase_action
|
|
10847
|
+
]
|
|
10698
10848
|
);
|
|
10699
10849
|
const handleOpenImageViewer = (images, startIndex) => {
|
|
10700
10850
|
setImageViewer({ visible: true, images, startIndex });
|
|
10701
10851
|
};
|
|
10702
|
-
const tweenToTarget = (0, import_react26.useCallback)(
|
|
10703
|
-
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
|
|
10713
|
-
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10852
|
+
const tweenToTarget = (0, import_react26.useCallback)(
|
|
10853
|
+
(target, zoomFactor = 1, forcedDirection = null) => {
|
|
10854
|
+
const { camera, controls, tweenGroup } = stateRef.current;
|
|
10855
|
+
if (!camera || !controls || !tweenGroup) return;
|
|
10856
|
+
const targetPos = target instanceof THREE3.Mesh ? target.getWorldPosition(new THREE3.Vector3()) : target;
|
|
10857
|
+
const controlsTween = new import_tween2.Tween(controls.target).to(targetPos, 1500).easing(import_tween2.Easing.Cubic.Out);
|
|
10858
|
+
tweenGroup.add(controlsTween);
|
|
10859
|
+
controlsTween.start();
|
|
10860
|
+
let offset;
|
|
10861
|
+
if (forcedDirection) {
|
|
10862
|
+
offset = forcedDirection.clone().normalize().multiplyScalar(x_view_config.CAMERA_ZOOM_DISTANCE / zoomFactor);
|
|
10863
|
+
} else {
|
|
10864
|
+
offset = camera.position.clone().sub(controls.target).normalize().multiplyScalar(x_view_config.CAMERA_ZOOM_DISTANCE / zoomFactor);
|
|
10865
|
+
}
|
|
10866
|
+
const targetCameraPos = targetPos.clone().add(offset);
|
|
10867
|
+
const cameraTween = new import_tween2.Tween(camera.position).to(targetCameraPos, 1500).easing(import_tween2.Easing.Cubic.Out);
|
|
10868
|
+
tweenGroup.add(cameraTween);
|
|
10869
|
+
cameraTween.start();
|
|
10870
|
+
},
|
|
10871
|
+
[]
|
|
10872
|
+
);
|
|
10720
10873
|
const isFromUiOverlay = (event) => {
|
|
10721
10874
|
const t = event == null ? void 0 : event.target;
|
|
10722
10875
|
if (!t || typeof t.closest !== "function") return false;
|
|
10723
10876
|
return !!t.closest(".ui-overlay");
|
|
10724
10877
|
};
|
|
10725
|
-
const buildFullAncestryTree = (0, import_react26.useCallback)(
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
|
|
10730
|
-
|
|
10731
|
-
|
|
10732
|
-
|
|
10733
|
-
|
|
10734
|
-
|
|
10735
|
-
};
|
|
10736
|
-
}
|
|
10737
|
-
let nodeId = treeItem.node_id;
|
|
10738
|
-
if (!nodeId && treeItem.node) nodeId = treeItem.node.id;
|
|
10739
|
-
const fullNode = nodeMap.get(String(nodeId));
|
|
10740
|
-
const effectiveNode = fullNode || treeItem.node;
|
|
10741
|
-
let processedBranches = [];
|
|
10742
|
-
if (treeItem.parallel_branches && Array.isArray(treeItem.parallel_branches)) {
|
|
10743
|
-
processedBranches = treeItem.parallel_branches.map((branch) => {
|
|
10744
|
-
if (branch.linked_ancestry_id) {
|
|
10745
|
-
const linkedAncestry = ancestryMap.get(String(branch.linked_ancestry_id));
|
|
10746
|
-
if (linkedAncestry && linkedAncestry.tree) {
|
|
10747
|
-
const graftedTree = recursiveBuild(linkedAncestry.tree);
|
|
10748
|
-
return {
|
|
10749
|
-
...branch,
|
|
10750
|
-
name: linkedAncestry.name,
|
|
10751
|
-
description: linkedAncestry.description,
|
|
10752
|
-
description_sections: linkedAncestry.description_sections,
|
|
10753
|
-
tree: graftedTree,
|
|
10754
|
-
isLinked: true
|
|
10755
|
-
};
|
|
10756
|
-
}
|
|
10757
|
-
}
|
|
10878
|
+
const buildFullAncestryTree = (0, import_react26.useCallback)(
|
|
10879
|
+
(idTree, nodes, ancestries = []) => {
|
|
10880
|
+
if (!idTree) return null;
|
|
10881
|
+
const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
|
|
10882
|
+
const ancestryMap = new Map(
|
|
10883
|
+
ancestries.map((a) => [String(a.ancestry_id), a])
|
|
10884
|
+
);
|
|
10885
|
+
const recursiveBuild = (treeItem) => {
|
|
10886
|
+
if (!treeItem) return null;
|
|
10887
|
+
if (treeItem.is_section) {
|
|
10758
10888
|
return {
|
|
10759
|
-
...
|
|
10760
|
-
|
|
10889
|
+
...treeItem,
|
|
10890
|
+
children: (treeItem.children || []).map(recursiveBuild).filter(Boolean)
|
|
10761
10891
|
};
|
|
10762
|
-
}
|
|
10763
|
-
|
|
10764
|
-
|
|
10765
|
-
|
|
10766
|
-
|
|
10767
|
-
|
|
10768
|
-
parallel_branches
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
|
|
10773
|
-
|
|
10774
|
-
|
|
10775
|
-
|
|
10776
|
-
|
|
10777
|
-
|
|
10778
|
-
|
|
10779
|
-
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
|
|
10783
|
-
|
|
10784
|
-
|
|
10785
|
-
return {
|
|
10786
|
-
...branch,
|
|
10787
|
-
name: linkedAncestry.name,
|
|
10788
|
-
description: linkedAncestry.description,
|
|
10789
|
-
description_sections: linkedAncestry.description_sections,
|
|
10790
|
-
tree: recursiveBuild(linkedAncestry.tree),
|
|
10791
|
-
isLinked: true
|
|
10792
|
-
};
|
|
10892
|
+
}
|
|
10893
|
+
let nodeId = treeItem.node_id;
|
|
10894
|
+
if (!nodeId && treeItem.node) nodeId = treeItem.node.id;
|
|
10895
|
+
const fullNode = nodeMap.get(String(nodeId));
|
|
10896
|
+
const effectiveNode = fullNode || treeItem.node;
|
|
10897
|
+
let processedBranches = [];
|
|
10898
|
+
if (treeItem.parallel_branches && Array.isArray(treeItem.parallel_branches)) {
|
|
10899
|
+
processedBranches = treeItem.parallel_branches.map((branch) => {
|
|
10900
|
+
if (branch.linked_ancestry_id) {
|
|
10901
|
+
const linkedAncestry = ancestryMap.get(
|
|
10902
|
+
String(branch.linked_ancestry_id)
|
|
10903
|
+
);
|
|
10904
|
+
if (linkedAncestry && linkedAncestry.tree) {
|
|
10905
|
+
const graftedTree = recursiveBuild(linkedAncestry.tree);
|
|
10906
|
+
return {
|
|
10907
|
+
...branch,
|
|
10908
|
+
name: linkedAncestry.name,
|
|
10909
|
+
description: linkedAncestry.description,
|
|
10910
|
+
description_sections: linkedAncestry.description_sections,
|
|
10911
|
+
tree: graftedTree,
|
|
10912
|
+
isLinked: true
|
|
10913
|
+
};
|
|
10914
|
+
}
|
|
10793
10915
|
}
|
|
10794
|
-
|
|
10795
|
-
|
|
10796
|
-
|
|
10916
|
+
return {
|
|
10917
|
+
...branch,
|
|
10918
|
+
tree: recursiveBuild(branch.tree)
|
|
10919
|
+
};
|
|
10920
|
+
});
|
|
10921
|
+
}
|
|
10922
|
+
return {
|
|
10923
|
+
...effectiveNode ? { node: effectiveNode } : { node: { id: nodeId, name: "Unknown" } },
|
|
10924
|
+
relationship: treeItem.relationship || {},
|
|
10925
|
+
children: (treeItem.children || []).map(recursiveBuild).filter(Boolean),
|
|
10926
|
+
parallel_branches: processedBranches
|
|
10927
|
+
};
|
|
10797
10928
|
};
|
|
10798
|
-
|
|
10799
|
-
|
|
10800
|
-
|
|
10929
|
+
let rootId = idTree.node_id;
|
|
10930
|
+
if (!rootId && idTree.node) rootId = idTree.node.id;
|
|
10931
|
+
if (rootId) {
|
|
10932
|
+
const rootNode = nodeMap.get(String(rootId));
|
|
10933
|
+
const effectiveRoot = rootNode || idTree.node;
|
|
10934
|
+
if (!effectiveRoot) return null;
|
|
10935
|
+
return {
|
|
10936
|
+
node: effectiveRoot,
|
|
10937
|
+
relationship: idTree.relationship || {},
|
|
10938
|
+
children: (idTree.children || []).map(recursiveBuild).filter(Boolean),
|
|
10939
|
+
parallel_branches: (idTree.parallel_branches || []).map((branch) => {
|
|
10940
|
+
if (branch.linked_ancestry_id) {
|
|
10941
|
+
const linkedAncestry = ancestryMap.get(
|
|
10942
|
+
String(branch.linked_ancestry_id)
|
|
10943
|
+
);
|
|
10944
|
+
if (linkedAncestry && linkedAncestry.tree) {
|
|
10945
|
+
return {
|
|
10946
|
+
...branch,
|
|
10947
|
+
name: linkedAncestry.name,
|
|
10948
|
+
description: linkedAncestry.description,
|
|
10949
|
+
description_sections: linkedAncestry.description_sections,
|
|
10950
|
+
tree: recursiveBuild(linkedAncestry.tree),
|
|
10951
|
+
isLinked: true
|
|
10952
|
+
};
|
|
10953
|
+
}
|
|
10954
|
+
}
|
|
10955
|
+
return { ...branch, tree: recursiveBuild(branch.tree) };
|
|
10956
|
+
})
|
|
10957
|
+
};
|
|
10958
|
+
}
|
|
10959
|
+
return recursiveBuild(idTree);
|
|
10960
|
+
},
|
|
10961
|
+
[]
|
|
10962
|
+
);
|
|
10801
10963
|
const handleActivateTimeline = (0, import_react26.useCallback)(() => {
|
|
10802
10964
|
const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
10803
10965
|
if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
|
|
@@ -10878,10 +11040,12 @@ function XViewScene({
|
|
|
10878
11040
|
if (timelineNodes.length === 0) return;
|
|
10879
11041
|
const sortedTimePoints = Array.from(allTimePoints).sort((a, b) => a - b);
|
|
10880
11042
|
const maxTimeIndex = sortedTimePoints.length - 1;
|
|
10881
|
-
const timeToYMap = new Map(
|
|
10882
|
-
time,
|
|
10883
|
-
|
|
10884
|
-
|
|
11043
|
+
const timeToYMap = new Map(
|
|
11044
|
+
sortedTimePoints.map((time, index) => [
|
|
11045
|
+
time,
|
|
11046
|
+
(index - maxTimeIndex) * TIMELINE_LAYER_SPACING_Y
|
|
11047
|
+
])
|
|
11048
|
+
);
|
|
10885
11049
|
timelineNodes.sort((a, b) => {
|
|
10886
11050
|
if (a.isUndated && b.isUndated) return 0;
|
|
10887
11051
|
if (a.isUndated) return 1;
|
|
@@ -10924,7 +11088,12 @@ function XViewScene({
|
|
|
10924
11088
|
if (type === "interval") {
|
|
10925
11089
|
const endY = timeToYMap.get(endDate.getTime());
|
|
10926
11090
|
if (endY > y) {
|
|
10927
|
-
const barGeometry = new THREE3.CylinderGeometry(
|
|
11091
|
+
const barGeometry = new THREE3.CylinderGeometry(
|
|
11092
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
11093
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
11094
|
+
1,
|
|
11095
|
+
16
|
|
11096
|
+
);
|
|
10928
11097
|
const barMaterial = new THREE3.MeshStandardMaterial({
|
|
10929
11098
|
color: TIMELINE_GOLD_COLOR,
|
|
10930
11099
|
emissive: 12092939,
|
|
@@ -10953,7 +11122,8 @@ function XViewScene({
|
|
|
10953
11122
|
}, []);
|
|
10954
11123
|
const handleVersionTimeline = (0, import_react26.useCallback)((sourceMesh, versionMeshes) => {
|
|
10955
11124
|
const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
10956
|
-
if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
|
|
11125
|
+
if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
|
|
11126
|
+
return;
|
|
10957
11127
|
versionMeshes.forEach((mesh) => {
|
|
10958
11128
|
const oldLabel = mesh.getObjectByName("timelineLabel");
|
|
10959
11129
|
if (oldLabel) {
|
|
@@ -10969,7 +11139,8 @@ function XViewScene({
|
|
|
10969
11139
|
}
|
|
10970
11140
|
if (mesh.userData.timelineEndLabel) {
|
|
10971
11141
|
timelineIntervalsGroup.remove(mesh.userData.timelineEndLabel);
|
|
10972
|
-
if (mesh.userData.timelineEndLabel.material.map)
|
|
11142
|
+
if (mesh.userData.timelineEndLabel.material.map)
|
|
11143
|
+
mesh.userData.timelineEndLabel.material.map.dispose();
|
|
10973
11144
|
mesh.userData.timelineEndLabel.material.dispose();
|
|
10974
11145
|
delete mesh.userData.timelineEndLabel;
|
|
10975
11146
|
}
|
|
@@ -11029,8 +11200,15 @@ function XViewScene({
|
|
|
11029
11200
|
});
|
|
11030
11201
|
if (timelineNodes.length === 0) return;
|
|
11031
11202
|
const sortedTimePoints = Array.from(allTimePoints).sort((a, b) => a - b);
|
|
11032
|
-
const timeToYMap = new Map(
|
|
11033
|
-
|
|
11203
|
+
const timeToYMap = new Map(
|
|
11204
|
+
sortedTimePoints.map((time, index) => [
|
|
11205
|
+
time,
|
|
11206
|
+
index * TIMELINE_LAYER_SPACING_Y
|
|
11207
|
+
])
|
|
11208
|
+
);
|
|
11209
|
+
timelineNodes.sort(
|
|
11210
|
+
(a, b) => a.startDate - b.startDate || a.endDate - b.endDate
|
|
11211
|
+
);
|
|
11034
11212
|
const baseX = sourceMesh.position.x + TIMELINE_NODE_SPACING_X;
|
|
11035
11213
|
const baseY = sourceMesh.position.y;
|
|
11036
11214
|
const maxNodeIndex = timelineNodes.length - 1;
|
|
@@ -11048,7 +11226,12 @@ function XViewScene({
|
|
|
11048
11226
|
if (type === "interval") {
|
|
11049
11227
|
const relativeEndY = timeToYMap.get(endDate.getTime()) - timeToYMap.get(startDate.getTime());
|
|
11050
11228
|
if (relativeEndY > 0) {
|
|
11051
|
-
const barGeometry = new THREE3.CylinderGeometry(
|
|
11229
|
+
const barGeometry = new THREE3.CylinderGeometry(
|
|
11230
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
11231
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
11232
|
+
1,
|
|
11233
|
+
16
|
|
11234
|
+
);
|
|
11052
11235
|
const barMaterial = new THREE3.MeshStandardMaterial({
|
|
11053
11236
|
color: TIMELINE_GOLD_COLOR,
|
|
11054
11237
|
emissive: 12092939,
|
|
@@ -11085,15 +11268,31 @@ function XViewScene({
|
|
|
11085
11268
|
try {
|
|
11086
11269
|
const typeStr = (viewParams == null ? void 0 : viewParams.type) || "";
|
|
11087
11270
|
const sceneType = typeStr.toLowerCase().includes("database") ? "database" : "view";
|
|
11088
|
-
const scenePromise = get_scene_view_data(
|
|
11271
|
+
const scenePromise = get_scene_view_data(
|
|
11272
|
+
configPath,
|
|
11273
|
+
ownerId2,
|
|
11274
|
+
typeStr,
|
|
11275
|
+
session,
|
|
11276
|
+
focusNodeId,
|
|
11277
|
+
focusAncestryId
|
|
11278
|
+
);
|
|
11089
11279
|
const boardPromise = get_ancestry_board_action && session ? get_ancestry_board_action(configPath, sceneType, session, ownerId2) : Promise.resolve({ success: false, data: [] });
|
|
11090
|
-
const [sceneResponse, boardResponse] = await Promise.all([
|
|
11280
|
+
const [sceneResponse, boardResponse] = await Promise.all([
|
|
11281
|
+
scenePromise,
|
|
11282
|
+
boardPromise
|
|
11283
|
+
]);
|
|
11091
11284
|
if ((sceneResponse == null ? void 0 : sceneResponse.success) && ((_a2 = sceneResponse.data) == null ? void 0 : _a2.scene) && ((_b2 = sceneResponse.data) == null ? void 0 : _b2.parent)) {
|
|
11092
11285
|
if (focusNodeId) {
|
|
11093
|
-
let targetNode = sceneResponse.data.scene.nodes.find(
|
|
11286
|
+
let targetNode = sceneResponse.data.scene.nodes.find(
|
|
11287
|
+
(n) => String(n.id) === String(focusNodeId)
|
|
11288
|
+
);
|
|
11094
11289
|
if (!targetNode) {
|
|
11095
|
-
const allParentNodes = Object.values(
|
|
11096
|
-
|
|
11290
|
+
const allParentNodes = Object.values(
|
|
11291
|
+
sceneResponse.data.parent
|
|
11292
|
+
).flatMap((f) => f.nodes || []);
|
|
11293
|
+
targetNode = allParentNodes.find(
|
|
11294
|
+
(n) => String(n.id) === String(focusNodeId)
|
|
11295
|
+
);
|
|
11097
11296
|
}
|
|
11098
11297
|
if (targetNode) {
|
|
11099
11298
|
sceneResponse.data.scene.nodes = [targetNode];
|
|
@@ -11106,12 +11305,24 @@ function XViewScene({
|
|
|
11106
11305
|
sceneDataRef.current = sceneResponse.data.scene;
|
|
11107
11306
|
parentDataRef.current = sceneResponse.data.parent;
|
|
11108
11307
|
ancestryDataRef.current = sceneResponse.data.ancestry;
|
|
11109
|
-
console.log(
|
|
11110
|
-
|
|
11111
|
-
|
|
11308
|
+
console.log(
|
|
11309
|
+
"Console de sceneResponse.data.scene:",
|
|
11310
|
+
sceneResponse.data.scene
|
|
11311
|
+
);
|
|
11312
|
+
console.log(
|
|
11313
|
+
"Console de sceneResponse.data.parent:",
|
|
11314
|
+
sceneResponse.data.parent
|
|
11315
|
+
);
|
|
11316
|
+
console.log(
|
|
11317
|
+
"Console de sceneResponse.data.ancestry:",
|
|
11318
|
+
sceneResponse.data.ancestry
|
|
11319
|
+
);
|
|
11112
11320
|
setIsInitialized(true);
|
|
11113
11321
|
} else {
|
|
11114
|
-
console.error(
|
|
11322
|
+
console.error(
|
|
11323
|
+
"Falha ao buscar dados da cena:",
|
|
11324
|
+
(sceneResponse == null ? void 0 : sceneResponse.error) || "Resposta inv\xE1lida."
|
|
11325
|
+
);
|
|
11115
11326
|
}
|
|
11116
11327
|
if (boardResponse == null ? void 0 : boardResponse.success) {
|
|
11117
11328
|
setAncestryBoardData(boardResponse.data);
|
|
@@ -11130,7 +11341,9 @@ function XViewScene({
|
|
|
11130
11341
|
console.error("Usu\xE1rio n\xE3o autenticado. Acesso negado.");
|
|
11131
11342
|
setIsLoading(false);
|
|
11132
11343
|
} else if (!sceneConfigId && status !== "loading") {
|
|
11133
|
-
console.warn(
|
|
11344
|
+
console.warn(
|
|
11345
|
+
"Nenhum par\xE2metro de cena encontrado na URL ou falha na decripta\xE7\xE3o."
|
|
11346
|
+
);
|
|
11134
11347
|
setIsLoading(false);
|
|
11135
11348
|
}
|
|
11136
11349
|
}, [
|
|
@@ -11151,33 +11364,46 @@ function XViewScene({
|
|
|
11151
11364
|
const objs = stateRef.current.nodeObjects || {};
|
|
11152
11365
|
return !!objs[key];
|
|
11153
11366
|
}, []);
|
|
11154
|
-
const addOrUpdateNodeMesh = (0, import_react26.useCallback)(
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
tweenGroup
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
|
|
11168
|
-
|
|
11169
|
-
|
|
11170
|
-
|
|
11367
|
+
const addOrUpdateNodeMesh = (0, import_react26.useCallback)(
|
|
11368
|
+
(nodeData, position, suppressVersionUpdate = false) => {
|
|
11369
|
+
const {
|
|
11370
|
+
graphGroup,
|
|
11371
|
+
nodeObjects,
|
|
11372
|
+
clickableNodes,
|
|
11373
|
+
glowTexture,
|
|
11374
|
+
tweenGroup
|
|
11375
|
+
} = stateRef.current;
|
|
11376
|
+
const nodeId = String(nodeData.id);
|
|
11377
|
+
if (nodeObjects[nodeId]) {
|
|
11378
|
+
const existingMesh = nodeObjects[nodeId];
|
|
11379
|
+
if (position) {
|
|
11380
|
+
const updateTween = new import_tween2.Tween(existingMesh.position).to(position, 800).easing(import_tween2.Easing.Cubic.Out);
|
|
11381
|
+
tweenGroup.add(updateTween);
|
|
11382
|
+
updateTween.start();
|
|
11383
|
+
}
|
|
11384
|
+
return existingMesh;
|
|
11385
|
+
}
|
|
11386
|
+
const mesh = createNodeMesh(
|
|
11387
|
+
nodeData,
|
|
11388
|
+
position || new THREE3.Vector3(),
|
|
11389
|
+
glowTexture
|
|
11390
|
+
);
|
|
11391
|
+
graphGroup.add(mesh);
|
|
11392
|
+
if (mesh.userData.labelObject) {
|
|
11393
|
+
if (mesh.userData.labelOffset) {
|
|
11394
|
+
mesh.userData.labelObject.position.copy(mesh.position).add(mesh.userData.labelOffset);
|
|
11395
|
+
}
|
|
11396
|
+
graphGroup.add(mesh.userData.labelObject);
|
|
11171
11397
|
}
|
|
11172
|
-
|
|
11173
|
-
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
}
|
|
11179
|
-
|
|
11180
|
-
|
|
11398
|
+
nodeObjects[nodeId] = mesh;
|
|
11399
|
+
clickableNodes.push(mesh);
|
|
11400
|
+
if (!suppressVersionUpdate) {
|
|
11401
|
+
setSceneVersion((v) => v + 1);
|
|
11402
|
+
}
|
|
11403
|
+
return mesh;
|
|
11404
|
+
},
|
|
11405
|
+
[]
|
|
11406
|
+
);
|
|
11181
11407
|
(0, import_react26.useEffect)(() => {
|
|
11182
11408
|
if (!isInitialized || !sceneDataRef.current) return;
|
|
11183
11409
|
const currentMount = mountRef.current;
|
|
@@ -11192,7 +11418,12 @@ function XViewScene({
|
|
|
11192
11418
|
const scene = new THREE3.Scene();
|
|
11193
11419
|
scene.background = new THREE3.Color(0);
|
|
11194
11420
|
stateRef.current.scene = scene;
|
|
11195
|
-
const camera = new THREE3.PerspectiveCamera(
|
|
11421
|
+
const camera = new THREE3.PerspectiveCamera(
|
|
11422
|
+
75,
|
|
11423
|
+
currentMount.clientWidth / currentMount.clientHeight,
|
|
11424
|
+
0.1,
|
|
11425
|
+
2e3
|
|
11426
|
+
);
|
|
11196
11427
|
camera.position.set(0, 60, 120);
|
|
11197
11428
|
stateRef.current.camera = camera;
|
|
11198
11429
|
const renderer = new THREE3.WebGLRenderer({ antialias: true });
|
|
@@ -11213,7 +11444,12 @@ function XViewScene({
|
|
|
11213
11444
|
directionalLight.position.set(50, 50, 50);
|
|
11214
11445
|
scene.add(directionalLight);
|
|
11215
11446
|
const renderScene = new import_RenderPass.RenderPass(scene, camera);
|
|
11216
|
-
const bloomPass = new import_UnrealBloomPass.UnrealBloomPass(
|
|
11447
|
+
const bloomPass = new import_UnrealBloomPass.UnrealBloomPass(
|
|
11448
|
+
new THREE3.Vector2(currentMount.clientWidth, currentMount.clientHeight),
|
|
11449
|
+
x_view_config.BLOOM_EFFECT.strength,
|
|
11450
|
+
x_view_config.BLOOM_EFFECT.radius,
|
|
11451
|
+
x_view_config.BLOOM_EFFECT.threshold
|
|
11452
|
+
);
|
|
11217
11453
|
const composer = new import_EffectComposer.EffectComposer(renderer);
|
|
11218
11454
|
composer.addPass(renderScene);
|
|
11219
11455
|
composer.addPass(bloomPass);
|
|
@@ -11256,8 +11492,16 @@ function XViewScene({
|
|
|
11256
11492
|
const sourceNode = nodeObjects[String(linksArray[0].source)];
|
|
11257
11493
|
const targetNode = nodeObjects[String(linksArray[0].target)];
|
|
11258
11494
|
if (sourceNode && targetNode) {
|
|
11259
|
-
const resolution = new THREE3.Vector2(
|
|
11260
|
-
|
|
11495
|
+
const resolution = new THREE3.Vector2(
|
|
11496
|
+
currentMount.clientWidth,
|
|
11497
|
+
currentMount.clientHeight
|
|
11498
|
+
);
|
|
11499
|
+
const newLinks = createMultipleLinkLines(
|
|
11500
|
+
linksArray,
|
|
11501
|
+
sourceNode,
|
|
11502
|
+
targetNode,
|
|
11503
|
+
resolution
|
|
11504
|
+
);
|
|
11261
11505
|
newLinks.forEach((line, idx) => {
|
|
11262
11506
|
const meta = linksArray[idx];
|
|
11263
11507
|
if (meta) {
|
|
@@ -11298,7 +11542,10 @@ function XViewScene({
|
|
|
11298
11542
|
function tryPickNode() {
|
|
11299
11543
|
raycaster.setFromCamera(mouse, camera);
|
|
11300
11544
|
raycaster.layers.enable(GHOST_BLOOM_LAYER);
|
|
11301
|
-
const intersects = raycaster.intersectObjects(
|
|
11545
|
+
const intersects = raycaster.intersectObjects(
|
|
11546
|
+
stateRef.current.clickableNodes,
|
|
11547
|
+
false
|
|
11548
|
+
);
|
|
11302
11549
|
return intersects.length > 0 ? intersects[0].object : null;
|
|
11303
11550
|
}
|
|
11304
11551
|
function findClosestLinkToRay() {
|
|
@@ -11310,7 +11557,10 @@ function XViewScene({
|
|
|
11310
11557
|
x: (mouse.x * 0.5 + 0.5) * clientWidth,
|
|
11311
11558
|
y: (-mouse.y * 0.5 + 0.5) * clientHeight
|
|
11312
11559
|
};
|
|
11313
|
-
const allVisibleLinks = [
|
|
11560
|
+
const allVisibleLinks = [
|
|
11561
|
+
...stateRef.current.allLinks,
|
|
11562
|
+
...stateRef.current.ancestryLinks
|
|
11563
|
+
];
|
|
11314
11564
|
const THRESH = x_view_config.LINE_HOVER_THRESHOLD_PX + 4;
|
|
11315
11565
|
const tmpP1 = new THREE3.Vector3();
|
|
11316
11566
|
const tmpP2 = new THREE3.Vector3();
|
|
@@ -11325,19 +11575,35 @@ function XViewScene({
|
|
|
11325
11575
|
const up = new THREE3.Vector3(0, 1, 0);
|
|
11326
11576
|
const normal = new THREE3.Vector3().crossVectors(dir, up).normalize();
|
|
11327
11577
|
const controlPoint = mid.add(normal.multiplyScalar(curveOffset || 0));
|
|
11328
|
-
const curve = new THREE3.QuadraticBezierCurve3(
|
|
11578
|
+
const curve = new THREE3.QuadraticBezierCurve3(
|
|
11579
|
+
start,
|
|
11580
|
+
controlPoint,
|
|
11581
|
+
end
|
|
11582
|
+
);
|
|
11329
11583
|
const points = curve.getPoints(x_view_config.CURVE_SEGMENTS || 32);
|
|
11330
11584
|
for (let i = 0; i < points.length - 1; i++) {
|
|
11331
11585
|
tmpP1.copy(points[i]).project(camera);
|
|
11332
11586
|
tmpP2.copy(points[i + 1]).project(camera);
|
|
11333
|
-
const p1_px = {
|
|
11334
|
-
|
|
11587
|
+
const p1_px = {
|
|
11588
|
+
x: (tmpP1.x * 0.5 + 0.5) * clientWidth,
|
|
11589
|
+
y: (-tmpP1.y * 0.5 + 0.5) * clientHeight
|
|
11590
|
+
};
|
|
11591
|
+
const p2_px = {
|
|
11592
|
+
x: (tmpP2.x * 0.5 + 0.5) * clientWidth,
|
|
11593
|
+
y: (-tmpP2.y * 0.5 + 0.5) * clientHeight
|
|
11594
|
+
};
|
|
11335
11595
|
const L2 = (p2_px.x - p1_px.x) ** 2 + (p2_px.y - p1_px.y) ** 2;
|
|
11336
11596
|
if (L2 === 0) continue;
|
|
11337
11597
|
let t = ((mousePixels.x - p1_px.x) * (p2_px.x - p1_px.x) + (mousePixels.y - p1_px.y) * (p2_px.y - p1_px.y)) / L2;
|
|
11338
11598
|
t = Math.max(0, Math.min(1, t));
|
|
11339
|
-
const closestPoint = {
|
|
11340
|
-
|
|
11599
|
+
const closestPoint = {
|
|
11600
|
+
x: p1_px.x + t * (p2_px.x - p1_px.x),
|
|
11601
|
+
y: p1_px.y + t * (p2_px.y - p1_px.y)
|
|
11602
|
+
};
|
|
11603
|
+
const dist = Math.hypot(
|
|
11604
|
+
mousePixels.x - closestPoint.x,
|
|
11605
|
+
mousePixels.y - closestPoint.y
|
|
11606
|
+
);
|
|
11341
11607
|
if (dist < THRESH && dist < minDistance) {
|
|
11342
11608
|
minDistance = dist;
|
|
11343
11609
|
closestLink = link;
|
|
@@ -11346,14 +11612,26 @@ function XViewScene({
|
|
|
11346
11612
|
} else {
|
|
11347
11613
|
const p1 = new THREE3.Vector3().copy(sourceNode.position).project(camera);
|
|
11348
11614
|
const p2 = new THREE3.Vector3().copy(targetNode.position).project(camera);
|
|
11349
|
-
const p1_px = {
|
|
11350
|
-
|
|
11615
|
+
const p1_px = {
|
|
11616
|
+
x: (p1.x * 0.5 + 0.5) * clientWidth,
|
|
11617
|
+
y: (-p1.y * 0.5 + 0.5) * clientHeight
|
|
11618
|
+
};
|
|
11619
|
+
const p2_px = {
|
|
11620
|
+
x: (p2.x * 0.5 + 0.5) * clientWidth,
|
|
11621
|
+
y: (-p2.y * 0.5 + 0.5) * clientHeight
|
|
11622
|
+
};
|
|
11351
11623
|
const L2 = (p2_px.x - p1_px.x) ** 2 + (p2_px.y - p1_px.y) ** 2;
|
|
11352
11624
|
if (L2 === 0) return;
|
|
11353
11625
|
let t = ((mousePixels.x - p1_px.x) * (p2_px.x - p1_px.x) + (mousePixels.y - p1_px.y) * (p2_px.y - p1_px.y)) / L2;
|
|
11354
11626
|
t = Math.max(0, Math.min(1, t));
|
|
11355
|
-
const closestPoint = {
|
|
11356
|
-
|
|
11627
|
+
const closestPoint = {
|
|
11628
|
+
x: p1_px.x + t * (p2_px.x - p1_px.x),
|
|
11629
|
+
y: p1_px.y + t * (p2_px.y - p1_px.y)
|
|
11630
|
+
};
|
|
11631
|
+
const dist = Math.hypot(
|
|
11632
|
+
mousePixels.x - closestPoint.x,
|
|
11633
|
+
mousePixels.y - closestPoint.y
|
|
11634
|
+
);
|
|
11357
11635
|
if (dist < THRESH && dist < minDistance) {
|
|
11358
11636
|
minDistance = dist;
|
|
11359
11637
|
closestLink = link;
|
|
@@ -11388,7 +11666,11 @@ function XViewScene({
|
|
|
11388
11666
|
if (picked && !stateRef.current.ancestry.isActive) {
|
|
11389
11667
|
stateRef.current.controls.enabled = false;
|
|
11390
11668
|
}
|
|
11391
|
-
stateRef.current.pointerDown = {
|
|
11669
|
+
stateRef.current.pointerDown = {
|
|
11670
|
+
isDown: true,
|
|
11671
|
+
x: event.clientX,
|
|
11672
|
+
y: event.clientY
|
|
11673
|
+
};
|
|
11392
11674
|
stateRef.current.dragCandidate = picked;
|
|
11393
11675
|
}
|
|
11394
11676
|
function onPointerMove(event) {
|
|
@@ -11399,7 +11681,10 @@ function XViewScene({
|
|
|
11399
11681
|
const raycaster2 = new THREE3.Raycaster();
|
|
11400
11682
|
raycaster2.setFromCamera(mouse, camera);
|
|
11401
11683
|
camera.getWorldDirection(plane.normal);
|
|
11402
|
-
plane.setFromNormalAndCoplanarPoint(
|
|
11684
|
+
plane.setFromNormalAndCoplanarPoint(
|
|
11685
|
+
plane.normal,
|
|
11686
|
+
stateRef.current.draggedNode.position
|
|
11687
|
+
);
|
|
11403
11688
|
if (raycaster2.ray.intersectPlane(plane, intersectionPoint)) {
|
|
11404
11689
|
const draggedNode = stateRef.current.draggedNode;
|
|
11405
11690
|
draggedNode.position.copy(intersectionPoint);
|
|
@@ -11408,7 +11693,8 @@ function XViewScene({
|
|
|
11408
11693
|
}
|
|
11409
11694
|
if (stateRef.current.connection.isActive || stateRef.current.relink.isActive || stateRef.current.ancestry.isActive) {
|
|
11410
11695
|
const newHoveredNode2 = tryPickNode();
|
|
11411
|
-
if (stateRef.current.hoveredNode !== newHoveredNode2)
|
|
11696
|
+
if (stateRef.current.hoveredNode !== newHoveredNode2)
|
|
11697
|
+
stateRef.current.hoveredNode = newHoveredNode2;
|
|
11412
11698
|
if (currentMount) {
|
|
11413
11699
|
let fixedId = null;
|
|
11414
11700
|
if (stateRef.current.connection.isActive) {
|
|
@@ -11439,14 +11725,20 @@ function XViewScene({
|
|
|
11439
11725
|
stateRef.current.controls.enabled = false;
|
|
11440
11726
|
if (currentMount) currentMount.style.cursor = "grabbing";
|
|
11441
11727
|
camera.getWorldDirection(plane.normal);
|
|
11442
|
-
plane.setFromNormalAndCoplanarPoint(
|
|
11728
|
+
plane.setFromNormalAndCoplanarPoint(
|
|
11729
|
+
plane.normal,
|
|
11730
|
+
stateRef.current.draggedNode.position
|
|
11731
|
+
);
|
|
11443
11732
|
}
|
|
11444
11733
|
}
|
|
11445
11734
|
const newHoveredNode = tryPickNode();
|
|
11446
11735
|
const newHoveredLink = !newHoveredNode ? findClosestLinkToRay() : null;
|
|
11447
|
-
if (stateRef.current.hoveredNode !== newHoveredNode)
|
|
11448
|
-
|
|
11449
|
-
if (
|
|
11736
|
+
if (stateRef.current.hoveredNode !== newHoveredNode)
|
|
11737
|
+
stateRef.current.hoveredNode = newHoveredNode;
|
|
11738
|
+
if (stateRef.current.hoveredLink !== newHoveredLink)
|
|
11739
|
+
stateRef.current.hoveredLink = newHoveredLink;
|
|
11740
|
+
if (currentMount)
|
|
11741
|
+
currentMount.style.cursor = newHoveredNode || newHoveredLink ? "pointer" : "grab";
|
|
11450
11742
|
}
|
|
11451
11743
|
const isNodeInTree = (tree, nodeId) => {
|
|
11452
11744
|
if (!tree) return false;
|
|
@@ -11461,7 +11753,10 @@ function XViewScene({
|
|
|
11461
11753
|
const context = actionHandlerContext;
|
|
11462
11754
|
if (connection.isActive) {
|
|
11463
11755
|
if (hoveredNode && String(hoveredNode.userData.id) !== String(connection.sourceNodeData.id)) {
|
|
11464
|
-
await userActionHandlers.handleCompleteConnection(
|
|
11756
|
+
await userActionHandlers.handleCompleteConnection(
|
|
11757
|
+
context,
|
|
11758
|
+
hoveredNode.userData
|
|
11759
|
+
);
|
|
11465
11760
|
} else {
|
|
11466
11761
|
userActionHandlers.handleCancelConnection(context);
|
|
11467
11762
|
}
|
|
@@ -11469,7 +11764,10 @@ function XViewScene({
|
|
|
11469
11764
|
}
|
|
11470
11765
|
if (relink.isActive) {
|
|
11471
11766
|
if (hoveredNode && String(hoveredNode.userData.id) !== String(relink.fixedNodeId)) {
|
|
11472
|
-
await userActionHandlers.handleCompleteRelink(
|
|
11767
|
+
await userActionHandlers.handleCompleteRelink(
|
|
11768
|
+
context,
|
|
11769
|
+
hoveredNode.userData
|
|
11770
|
+
);
|
|
11473
11771
|
} else {
|
|
11474
11772
|
userActionHandlers.handleCancelRelink(context);
|
|
11475
11773
|
}
|
|
@@ -11487,7 +11785,9 @@ function XViewScene({
|
|
|
11487
11785
|
const clickedNodeId = String(clickedNode.userData.id);
|
|
11488
11786
|
const parentId = String(currentSelectedParent);
|
|
11489
11787
|
if (clickedNodeId === parentId) {
|
|
11490
|
-
alert(
|
|
11788
|
+
alert(
|
|
11789
|
+
"Erro: N\xE3o \xE9 poss\xEDvel adicionar um Node como filho dele mesmo."
|
|
11790
|
+
);
|
|
11491
11791
|
return;
|
|
11492
11792
|
}
|
|
11493
11793
|
const parentInfo = stateRef.current.nodeIdToParentFileMap.get(clickedNodeId);
|
|
@@ -11497,16 +11797,33 @@ function XViewScene({
|
|
|
11497
11797
|
const addChildToNode = (current, targetParentId, childNode) => {
|
|
11498
11798
|
const currentId = current.is_section ? current.id || current.section_id : String(current.node.id);
|
|
11499
11799
|
if (String(currentId) === String(targetParentId)) {
|
|
11500
|
-
const alreadyExists = current.children.some(
|
|
11800
|
+
const alreadyExists = current.children.some(
|
|
11801
|
+
(child) => !child.is_section && String(child.node.id) === String(childNode.id)
|
|
11802
|
+
);
|
|
11501
11803
|
if (alreadyExists) return current;
|
|
11502
|
-
return {
|
|
11804
|
+
return {
|
|
11805
|
+
...current,
|
|
11806
|
+
children: [
|
|
11807
|
+
...current.children,
|
|
11808
|
+
{ node: childNode, children: [], relationship: {} }
|
|
11809
|
+
]
|
|
11810
|
+
};
|
|
11503
11811
|
}
|
|
11504
|
-
return {
|
|
11812
|
+
return {
|
|
11813
|
+
...current,
|
|
11814
|
+
children: current.children.map(
|
|
11815
|
+
(c) => addChildToNode(c, targetParentId, childNode)
|
|
11816
|
+
)
|
|
11817
|
+
};
|
|
11505
11818
|
};
|
|
11506
11819
|
setAncestryMode((prev) => {
|
|
11507
11820
|
const treeKey = isAbstraction ? "abstraction_tree" : "tree";
|
|
11508
11821
|
if (!prev[treeKey]) return prev;
|
|
11509
|
-
const newTree = addChildToNode(
|
|
11822
|
+
const newTree = addChildToNode(
|
|
11823
|
+
prev[treeKey],
|
|
11824
|
+
parentId,
|
|
11825
|
+
fullNodeData
|
|
11826
|
+
);
|
|
11510
11827
|
return { ...prev, [treeKey]: newTree };
|
|
11511
11828
|
});
|
|
11512
11829
|
}
|
|
@@ -11520,7 +11837,8 @@ function XViewScene({
|
|
|
11520
11837
|
stateRef.current.dragCandidate = null;
|
|
11521
11838
|
stateRef.current.pointerDown.isDown = false;
|
|
11522
11839
|
stateRef.current.controls.enabled = true;
|
|
11523
|
-
if (currentMount)
|
|
11840
|
+
if (currentMount)
|
|
11841
|
+
currentMount.style.cursor = stateRef.current.hoveredNode || stateRef.current.hoveredLink ? "pointer" : "grab";
|
|
11524
11842
|
return;
|
|
11525
11843
|
}
|
|
11526
11844
|
const dragDistance = Math.hypot(
|
|
@@ -11568,16 +11886,21 @@ function XViewScene({
|
|
|
11568
11886
|
}
|
|
11569
11887
|
function handleDoubleClick(event) {
|
|
11570
11888
|
if (stateRef.current.camera) stateRef.current.camera.layers.enableAll();
|
|
11571
|
-
if (isFromUiOverlay(event) || stateRef.current.isDragging || stateRef.current.creation.isActive || stateRef.current.connection.isActive || stateRef.current.relink.isActive)
|
|
11572
|
-
|
|
11889
|
+
if (isFromUiOverlay(event) || stateRef.current.isDragging || stateRef.current.creation.isActive || stateRef.current.connection.isActive || stateRef.current.relink.isActive)
|
|
11890
|
+
return;
|
|
11891
|
+
if (stateRef.current.hoveredNode)
|
|
11892
|
+
tweenToTarget(stateRef.current.hoveredNode);
|
|
11573
11893
|
}
|
|
11574
11894
|
function handleContextMenu(event) {
|
|
11575
11895
|
if (stateRef.current.camera) stateRef.current.camera.layers.enableAll();
|
|
11576
11896
|
if (isFromUiOverlay(event)) return;
|
|
11577
11897
|
event.preventDefault();
|
|
11578
|
-
if (stateRef.current.creation.isActive || stateRef.current.connection.isActive || stateRef.current.relink.isActive)
|
|
11898
|
+
if (stateRef.current.creation.isActive || stateRef.current.connection.isActive || stateRef.current.relink.isActive)
|
|
11899
|
+
return;
|
|
11579
11900
|
setMouseFromEvent(event);
|
|
11580
|
-
setContextMenu(
|
|
11901
|
+
setContextMenu(
|
|
11902
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
11903
|
+
);
|
|
11581
11904
|
setMultiContextMenu((prev) => ({ ...prev, visible: false }));
|
|
11582
11905
|
setRelationshipMenu((prev) => ({ ...prev, visible: false }));
|
|
11583
11906
|
const pickedNode = tryPickNode();
|
|
@@ -11608,7 +11931,12 @@ function XViewScene({
|
|
|
11608
11931
|
return;
|
|
11609
11932
|
}
|
|
11610
11933
|
stateRef.current.selectedNodes.clear();
|
|
11611
|
-
setRelationshipMenu({
|
|
11934
|
+
setRelationshipMenu({
|
|
11935
|
+
visible: true,
|
|
11936
|
+
x: event.clientX,
|
|
11937
|
+
y: event.clientY,
|
|
11938
|
+
linkObject: pickedLink
|
|
11939
|
+
});
|
|
11612
11940
|
return;
|
|
11613
11941
|
}
|
|
11614
11942
|
stateRef.current.selectedNodes.clear();
|
|
@@ -11640,7 +11968,10 @@ function XViewScene({
|
|
|
11640
11968
|
}
|
|
11641
11969
|
});
|
|
11642
11970
|
}
|
|
11643
|
-
const allRenderedLinks = [
|
|
11971
|
+
const allRenderedLinks = [
|
|
11972
|
+
...stateRef.current.allLinks,
|
|
11973
|
+
...stateRef.current.ancestryLinks
|
|
11974
|
+
];
|
|
11644
11975
|
allRenderedLinks.forEach((line) => {
|
|
11645
11976
|
const { sourceNode, targetNode, isCurved, curveOffset } = line.userData;
|
|
11646
11977
|
if (sourceNode && targetNode) {
|
|
@@ -11652,13 +11983,20 @@ function XViewScene({
|
|
|
11652
11983
|
const up = new THREE3.Vector3(0, 1, 0);
|
|
11653
11984
|
const normal = new THREE3.Vector3().crossVectors(dir, up).normalize();
|
|
11654
11985
|
const controlPoint = mid.add(normal.multiplyScalar(curveOffset));
|
|
11655
|
-
const curve = new THREE3.QuadraticBezierCurve3(
|
|
11986
|
+
const curve = new THREE3.QuadraticBezierCurve3(
|
|
11987
|
+
start,
|
|
11988
|
+
controlPoint,
|
|
11989
|
+
end
|
|
11990
|
+
);
|
|
11656
11991
|
const points = curve.getPoints(x_view_config.CURVE_SEGMENTS);
|
|
11657
11992
|
const positions = [];
|
|
11658
11993
|
points.forEach((p) => positions.push(p.x, p.y, p.z));
|
|
11659
11994
|
line.geometry.setPositions(positions);
|
|
11660
11995
|
} else {
|
|
11661
|
-
line.geometry.setPositions([
|
|
11996
|
+
line.geometry.setPositions([
|
|
11997
|
+
...sourceNode.position.toArray(),
|
|
11998
|
+
...targetNode.position.toArray()
|
|
11999
|
+
]);
|
|
11662
12000
|
}
|
|
11663
12001
|
}
|
|
11664
12002
|
});
|
|
@@ -11671,7 +12009,11 @@ function XViewScene({
|
|
|
11671
12009
|
const startPos = node.position;
|
|
11672
12010
|
const distance = startPos.distanceTo(endPos);
|
|
11673
12011
|
bar.scale.y = distance;
|
|
11674
|
-
const midpoint = new THREE3.Vector3().lerpVectors(
|
|
12012
|
+
const midpoint = new THREE3.Vector3().lerpVectors(
|
|
12013
|
+
startPos,
|
|
12014
|
+
endPos,
|
|
12015
|
+
0.5
|
|
12016
|
+
);
|
|
11675
12017
|
bar.position.copy(midpoint);
|
|
11676
12018
|
const direction = new THREE3.Vector3().subVectors(endPos, startPos).normalize();
|
|
11677
12019
|
const upVector = new THREE3.Vector3(0, 1, 0);
|
|
@@ -11682,7 +12024,11 @@ function XViewScene({
|
|
|
11682
12024
|
const { ghostElements, creation, connection, relink } = stateRef.current;
|
|
11683
12025
|
if (creation.isActive && ghostElements.node && ghostElements.line) {
|
|
11684
12026
|
const srcMesh = stateRef.current.nodeObjects[String(creation.sourceNodeData.id)];
|
|
11685
|
-
if (srcMesh)
|
|
12027
|
+
if (srcMesh)
|
|
12028
|
+
ghostElements.line.geometry.setPositions([
|
|
12029
|
+
...srcMesh.position.toArray(),
|
|
12030
|
+
...ghostElements.node.position.toArray()
|
|
12031
|
+
]);
|
|
11686
12032
|
}
|
|
11687
12033
|
if (connection.isActive && connection.line) {
|
|
11688
12034
|
const srcMesh = stateRef.current.nodeObjects[String(connection.sourceNodeData.id)];
|
|
@@ -11691,7 +12037,11 @@ function XViewScene({
|
|
|
11691
12037
|
raycaster2.setFromCamera(mouse, camera);
|
|
11692
12038
|
camera.getWorldDirection(plane.normal);
|
|
11693
12039
|
plane.setFromNormalAndCoplanarPoint(plane.normal, srcMesh.position);
|
|
11694
|
-
if (raycaster2.ray.intersectPlane(plane, intersectionPoint))
|
|
12040
|
+
if (raycaster2.ray.intersectPlane(plane, intersectionPoint))
|
|
12041
|
+
connection.line.geometry.setPositions([
|
|
12042
|
+
...srcMesh.position.toArray(),
|
|
12043
|
+
...intersectionPoint.toArray()
|
|
12044
|
+
]);
|
|
11695
12045
|
}
|
|
11696
12046
|
}
|
|
11697
12047
|
if (relink.isActive && relink.line) {
|
|
@@ -11701,7 +12051,11 @@ function XViewScene({
|
|
|
11701
12051
|
raycaster2.setFromCamera(mouse, camera);
|
|
11702
12052
|
camera.getWorldDirection(plane.normal);
|
|
11703
12053
|
plane.setFromNormalAndCoplanarPoint(plane.normal, fixedMesh.position);
|
|
11704
|
-
if (raycaster2.ray.intersectPlane(plane, intersectionPoint))
|
|
12054
|
+
if (raycaster2.ray.intersectPlane(plane, intersectionPoint))
|
|
12055
|
+
relink.line.geometry.setPositions([
|
|
12056
|
+
...fixedMesh.position.toArray(),
|
|
12057
|
+
...intersectionPoint.toArray()
|
|
12058
|
+
]);
|
|
11705
12059
|
}
|
|
11706
12060
|
}
|
|
11707
12061
|
Object.values(stateRef.current.nodeObjects).forEach((node) => {
|
|
@@ -11745,11 +12099,18 @@ function XViewScene({
|
|
|
11745
12099
|
renderer.setSize(clientWidth, clientHeight);
|
|
11746
12100
|
composer.setSize(clientWidth, clientHeight);
|
|
11747
12101
|
const resVec = new THREE3.Vector2(clientWidth, clientHeight);
|
|
11748
|
-
stateRef.current.allLinks.forEach(
|
|
11749
|
-
|
|
11750
|
-
|
|
11751
|
-
|
|
11752
|
-
|
|
12102
|
+
stateRef.current.allLinks.forEach(
|
|
12103
|
+
(line) => line.material.resolution.copy(resVec)
|
|
12104
|
+
);
|
|
12105
|
+
stateRef.current.ancestryLinks.forEach(
|
|
12106
|
+
(line) => line.material.resolution.copy(resVec)
|
|
12107
|
+
);
|
|
12108
|
+
if (stateRef.current.ghostElements.line)
|
|
12109
|
+
stateRef.current.ghostElements.line.material.resolution.copy(resVec);
|
|
12110
|
+
if (stateRef.current.connection.line)
|
|
12111
|
+
stateRef.current.connection.line.material.resolution.copy(resVec);
|
|
12112
|
+
if (stateRef.current.relink.line)
|
|
12113
|
+
stateRef.current.relink.line.material.resolution.copy(resVec);
|
|
11753
12114
|
}
|
|
11754
12115
|
window.addEventListener("resize", handleResize);
|
|
11755
12116
|
return () => {
|
|
@@ -11769,14 +12130,16 @@ function XViewScene({
|
|
|
11769
12130
|
ancestryGroup.traverse((obj) => {
|
|
11770
12131
|
if (obj.geometry) obj.geometry.dispose();
|
|
11771
12132
|
if (obj.material) {
|
|
11772
|
-
if (Array.isArray(obj.material))
|
|
12133
|
+
if (Array.isArray(obj.material))
|
|
12134
|
+
obj.material.forEach((m) => m.dispose());
|
|
11773
12135
|
else obj.material.dispose();
|
|
11774
12136
|
}
|
|
11775
12137
|
});
|
|
11776
12138
|
graphGroup.traverse((obj) => {
|
|
11777
12139
|
if (obj.geometry) obj.geometry.dispose();
|
|
11778
12140
|
if (obj.material) {
|
|
11779
|
-
if (Array.isArray(obj.material))
|
|
12141
|
+
if (Array.isArray(obj.material))
|
|
12142
|
+
obj.material.forEach((m) => m.dispose());
|
|
11780
12143
|
else obj.material.dispose();
|
|
11781
12144
|
}
|
|
11782
12145
|
});
|
|
@@ -11787,9 +12150,22 @@ function XViewScene({
|
|
|
11787
12150
|
currentMount.removeChild(renderer.domElement);
|
|
11788
12151
|
}
|
|
11789
12152
|
};
|
|
11790
|
-
}, [
|
|
11791
|
-
|
|
11792
|
-
|
|
12153
|
+
}, [
|
|
12154
|
+
isInitialized,
|
|
12155
|
+
tweenToTarget,
|
|
12156
|
+
dbSaveUrl,
|
|
12157
|
+
isNodeInView,
|
|
12158
|
+
addOrUpdateNodeMesh,
|
|
12159
|
+
handleActivateTimeline,
|
|
12160
|
+
get_scene_view_data,
|
|
12161
|
+
save_view_data
|
|
12162
|
+
]);
|
|
12163
|
+
const handleGhostNodeImageChange = (0, import_react26.useCallback)((useImage, imageUrl) => {
|
|
12164
|
+
const {
|
|
12165
|
+
node: ghostNode,
|
|
12166
|
+
line: ghostLine,
|
|
12167
|
+
aura: ghostAura
|
|
12168
|
+
} = stateRef.current.ghostElements;
|
|
11793
12169
|
const { graphGroup, glowTexture } = stateRef.current;
|
|
11794
12170
|
if (!ghostNode || !graphGroup) return;
|
|
11795
12171
|
const currentData = {
|
|
@@ -11800,13 +12176,15 @@ function XViewScene({
|
|
|
11800
12176
|
const position = ghostNode.position.clone();
|
|
11801
12177
|
if (ghostNode.userData.labelObject) {
|
|
11802
12178
|
graphGroup.remove(ghostNode.userData.labelObject);
|
|
11803
|
-
if (ghostNode.userData.labelObject.material.map)
|
|
12179
|
+
if (ghostNode.userData.labelObject.material.map)
|
|
12180
|
+
ghostNode.userData.labelObject.material.map.dispose();
|
|
11804
12181
|
ghostNode.userData.labelObject.material.dispose();
|
|
11805
12182
|
}
|
|
11806
12183
|
graphGroup.remove(ghostNode);
|
|
11807
12184
|
if (ghostNode.geometry) ghostNode.geometry.dispose();
|
|
11808
12185
|
if (ghostNode.material) {
|
|
11809
|
-
if (Array.isArray(ghostNode.material))
|
|
12186
|
+
if (Array.isArray(ghostNode.material))
|
|
12187
|
+
ghostNode.material.forEach((m) => m.dispose());
|
|
11810
12188
|
else ghostNode.material.dispose();
|
|
11811
12189
|
}
|
|
11812
12190
|
const newGhostNode = createNodeMesh(currentData, position, glowTexture);
|
|
@@ -11851,28 +12229,31 @@ function XViewScene({
|
|
|
11851
12229
|
ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
|
|
11852
12230
|
}
|
|
11853
12231
|
}, []);
|
|
11854
|
-
const handleDetailNodeIntensityChange = (0, import_react26.useCallback)(
|
|
11855
|
-
|
|
11856
|
-
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
|
|
11860
|
-
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
|
|
11864
|
-
borderMesh.material
|
|
12232
|
+
const handleDetailNodeIntensityChange = (0, import_react26.useCallback)(
|
|
12233
|
+
(nodeId, newIntensity) => {
|
|
12234
|
+
const mesh = stateRef.current.nodeObjects[String(nodeId)];
|
|
12235
|
+
if (!mesh) return;
|
|
12236
|
+
const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
|
|
12237
|
+
mesh.userData.intensity = newIntensity;
|
|
12238
|
+
mesh.userData._baseEmissiveIntensity = adjustedIntensity;
|
|
12239
|
+
const isImageNode = mesh.userData.useImageAsTexture === true;
|
|
12240
|
+
if (isImageNode) {
|
|
12241
|
+
const borderMesh = mesh.getObjectByName("borderRing");
|
|
12242
|
+
if (borderMesh && borderMesh.material) {
|
|
12243
|
+
borderMesh.material.emissiveIntensity = adjustedIntensity;
|
|
12244
|
+
}
|
|
12245
|
+
} else {
|
|
12246
|
+
if (mesh.material) {
|
|
12247
|
+
mesh.material.emissiveIntensity = adjustedIntensity;
|
|
12248
|
+
}
|
|
11865
12249
|
}
|
|
11866
|
-
|
|
11867
|
-
if (
|
|
11868
|
-
|
|
12250
|
+
const aura = mesh.getObjectByName("aura");
|
|
12251
|
+
if (aura && aura.material) {
|
|
12252
|
+
aura.material.opacity = Math.min(0.8, newIntensity * 0.15);
|
|
11869
12253
|
}
|
|
11870
|
-
}
|
|
11871
|
-
|
|
11872
|
-
|
|
11873
|
-
aura.material.opacity = Math.min(0.8, newIntensity * 0.15);
|
|
11874
|
-
}
|
|
11875
|
-
}, []);
|
|
12254
|
+
},
|
|
12255
|
+
[]
|
|
12256
|
+
);
|
|
11876
12257
|
const handleGhostNodeColorChange = (newColor) => {
|
|
11877
12258
|
const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
|
|
11878
12259
|
if (!ghostNode) return;
|
|
@@ -11983,7 +12364,9 @@ function XViewScene({
|
|
|
11983
12364
|
mesh.userData.size = newSize;
|
|
11984
12365
|
};
|
|
11985
12366
|
const handleStartAncestryCreation = (nodeData) => {
|
|
11986
|
-
setContextMenu(
|
|
12367
|
+
setContextMenu(
|
|
12368
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
12369
|
+
);
|
|
11987
12370
|
stateRef.current.maxAncestryRenderIndex = 0;
|
|
11988
12371
|
setAncestryMode({
|
|
11989
12372
|
isActive: true,
|
|
@@ -12008,9 +12391,12 @@ function XViewScene({
|
|
|
12008
12391
|
const newTreeStr = JSON.stringify(newTree);
|
|
12009
12392
|
let metaChanged = false;
|
|
12010
12393
|
if (extraData) {
|
|
12011
|
-
if (extraData.ancestryName !== void 0 && extraData.ancestryName !== prev.ancestryName)
|
|
12012
|
-
|
|
12013
|
-
if (extraData.
|
|
12394
|
+
if (extraData.ancestryName !== void 0 && extraData.ancestryName !== prev.ancestryName)
|
|
12395
|
+
metaChanged = true;
|
|
12396
|
+
if (extraData.ancestryDescription !== void 0 && extraData.ancestryDescription !== prev.ancestryDescription)
|
|
12397
|
+
metaChanged = true;
|
|
12398
|
+
if (extraData.ancestryDescriptionSections !== void 0 && JSON.stringify(extraData.ancestryDescriptionSections) !== JSON.stringify(prev.ancestryDescriptionSections))
|
|
12399
|
+
metaChanged = true;
|
|
12014
12400
|
}
|
|
12015
12401
|
if (prevTreeStr === newTreeStr && !metaChanged) {
|
|
12016
12402
|
return prev;
|
|
@@ -12088,13 +12474,15 @@ function XViewScene({
|
|
|
12088
12474
|
if (ghostElements.node && graphGroup) {
|
|
12089
12475
|
if (ghostElements.node.userData.labelObject) {
|
|
12090
12476
|
graphGroup.remove(ghostElements.node.userData.labelObject);
|
|
12091
|
-
if (ghostElements.node.userData.labelObject.material.map)
|
|
12477
|
+
if (ghostElements.node.userData.labelObject.material.map)
|
|
12478
|
+
ghostElements.node.userData.labelObject.material.map.dispose();
|
|
12092
12479
|
ghostElements.node.userData.labelObject.material.dispose();
|
|
12093
12480
|
}
|
|
12094
12481
|
graphGroup.remove(ghostElements.node);
|
|
12095
12482
|
ghostElements.node.traverse((child) => {
|
|
12096
12483
|
if (child.material) {
|
|
12097
|
-
if (Array.isArray(child.material))
|
|
12484
|
+
if (Array.isArray(child.material))
|
|
12485
|
+
child.material.forEach((m) => m.dispose());
|
|
12098
12486
|
else child.material.dispose();
|
|
12099
12487
|
}
|
|
12100
12488
|
if (child.geometry) child.geometry.dispose();
|
|
@@ -12104,7 +12492,17 @@ function XViewScene({
|
|
|
12104
12492
|
setQuestMode({ isActive: false });
|
|
12105
12493
|
}, []);
|
|
12106
12494
|
const handleSaveQuestNode = async (context, newQuestData) => {
|
|
12107
|
-
const {
|
|
12495
|
+
const {
|
|
12496
|
+
graphDataRef,
|
|
12497
|
+
sceneDataRef: sceneDataRef2,
|
|
12498
|
+
stateRef: stateRef2,
|
|
12499
|
+
setters,
|
|
12500
|
+
actions,
|
|
12501
|
+
sceneSaveUrl: sceneSaveUrl2,
|
|
12502
|
+
viewType,
|
|
12503
|
+
sceneConfigId: sceneConfigId2,
|
|
12504
|
+
ownerId: ownerId2
|
|
12505
|
+
} = context;
|
|
12108
12506
|
if (!graphDataRef.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
|
|
12109
12507
|
const currentCounter = sceneDataRef2.current.quest_counter || 1;
|
|
12110
12508
|
const newNode = {
|
|
@@ -12137,7 +12535,8 @@ function XViewScene({
|
|
|
12137
12535
|
const finalPosition = stateRef2.current.ghostElements.node ? stateRef2.current.ghostElements.node.position.clone() : stateRef2.current.controls.target.clone();
|
|
12138
12536
|
const { graphGroup, ghostElements } = stateRef2.current;
|
|
12139
12537
|
if (ghostElements.node && graphGroup) {
|
|
12140
|
-
if (ghostElements.node.userData.labelObject)
|
|
12538
|
+
if (ghostElements.node.userData.labelObject)
|
|
12539
|
+
graphGroup.remove(ghostElements.node.userData.labelObject);
|
|
12141
12540
|
graphGroup.remove(ghostElements.node);
|
|
12142
12541
|
}
|
|
12143
12542
|
stateRef2.current.ghostElements = { node: null, line: null, aura: null };
|
|
@@ -12151,14 +12550,33 @@ function XViewScene({
|
|
|
12151
12550
|
}
|
|
12152
12551
|
};
|
|
12153
12552
|
userActionHandlers.handleCompleteConnection = async (context, targetNodeData) => {
|
|
12154
|
-
const {
|
|
12553
|
+
const {
|
|
12554
|
+
stateRef: stateRef2,
|
|
12555
|
+
graphDataRef,
|
|
12556
|
+
sceneDataRef: sceneDataRef2,
|
|
12557
|
+
sceneConfigId: sceneConfigId2,
|
|
12558
|
+
sceneSaveUrl: sceneSaveUrl2,
|
|
12559
|
+
ownerId: ownerId2
|
|
12560
|
+
} = context;
|
|
12155
12561
|
const { sourceNodeData } = stateRef2.current.connection;
|
|
12156
12562
|
if (!graphDataRef.current || !sceneDataRef2.current || !sourceNodeData || !targetNodeData) {
|
|
12157
12563
|
userActionHandlers.handleCancelConnection(context);
|
|
12158
12564
|
return;
|
|
12159
12565
|
}
|
|
12160
|
-
const sourceParentInfo = getParentFileInfoForNode(
|
|
12161
|
-
|
|
12566
|
+
const sourceParentInfo = getParentFileInfoForNode(
|
|
12567
|
+
graphDataRef.current,
|
|
12568
|
+
sceneDataRef2.current,
|
|
12569
|
+
sourceNodeData.id,
|
|
12570
|
+
sceneConfigId2,
|
|
12571
|
+
ownerId2
|
|
12572
|
+
);
|
|
12573
|
+
const targetParentInfo = getParentFileInfoForNode(
|
|
12574
|
+
graphDataRef.current,
|
|
12575
|
+
sceneDataRef2.current,
|
|
12576
|
+
targetNodeData.id,
|
|
12577
|
+
sceneConfigId2,
|
|
12578
|
+
ownerId2
|
|
12579
|
+
);
|
|
12162
12580
|
let parentInfoToSave = sourceParentInfo;
|
|
12163
12581
|
const isSourceQuest = sourceParentInfo.parentFileId === sceneConfigId2;
|
|
12164
12582
|
const isTargetQuest = targetParentInfo.parentFileId === sceneConfigId2;
|
|
@@ -12184,10 +12602,15 @@ function XViewScene({
|
|
|
12184
12602
|
};
|
|
12185
12603
|
await context.actions.save_view_data(sceneSaveUrl2, viewFilePayload);
|
|
12186
12604
|
} else {
|
|
12187
|
-
const specificParentData = JSON.parse(
|
|
12605
|
+
const specificParentData = JSON.parse(
|
|
12606
|
+
JSON.stringify(graphDataRef.current[parentFileIdToSave])
|
|
12607
|
+
);
|
|
12188
12608
|
specificParentData.links.push(newLink);
|
|
12189
12609
|
const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
|
|
12190
|
-
await context.actions.save_view_data(
|
|
12610
|
+
await context.actions.save_view_data(
|
|
12611
|
+
filenameForSpecificParent,
|
|
12612
|
+
specificParentData
|
|
12613
|
+
);
|
|
12191
12614
|
graphDataRef.current[parentFileIdToSave] = specificParentData;
|
|
12192
12615
|
}
|
|
12193
12616
|
addNewLinkToScene(stateRef2.current, newLink);
|
|
@@ -12199,7 +12622,9 @@ function XViewScene({
|
|
|
12199
12622
|
};
|
|
12200
12623
|
const handleClearAncestryVisuals = (0, import_react26.useCallback)((ancestryId) => {
|
|
12201
12624
|
const { renderedAncestries, ancestryGroup } = stateRef.current;
|
|
12202
|
-
const renderIndex = renderedAncestries.findIndex(
|
|
12625
|
+
const renderIndex = renderedAncestries.findIndex(
|
|
12626
|
+
(a) => String(a.id) === String(ancestryId)
|
|
12627
|
+
);
|
|
12203
12628
|
if (renderIndex !== -1) {
|
|
12204
12629
|
const toRemove = renderedAncestries[renderIndex];
|
|
12205
12630
|
toRemove.lines.forEach((line) => {
|
|
@@ -12208,12 +12633,16 @@ function XViewScene({
|
|
|
12208
12633
|
if (line.material) line.material.dispose();
|
|
12209
12634
|
});
|
|
12210
12635
|
renderedAncestries.splice(renderIndex, 1);
|
|
12211
|
-
stateRef.current.ancestryLinks = renderedAncestries.flatMap(
|
|
12636
|
+
stateRef.current.ancestryLinks = renderedAncestries.flatMap(
|
|
12637
|
+
(a) => a.lines
|
|
12638
|
+
);
|
|
12212
12639
|
}
|
|
12213
12640
|
}, []);
|
|
12214
12641
|
const handleRenderAncestry = (0, import_react26.useCallback)(
|
|
12215
12642
|
async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
|
|
12216
|
-
setContextMenu(
|
|
12643
|
+
setContextMenu(
|
|
12644
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
12645
|
+
);
|
|
12217
12646
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
12218
12647
|
return;
|
|
12219
12648
|
}
|
|
@@ -12240,14 +12669,16 @@ function XViewScene({
|
|
|
12240
12669
|
if (numId !== void 0 && normalizedAllowedIds.has(numId)) return true;
|
|
12241
12670
|
if (strId && normalizedAllowedIds.has(strId)) return true;
|
|
12242
12671
|
if (strSecId && normalizedAllowedIds.has(strSecId)) return true;
|
|
12243
|
-
if (numId !== void 0 && normalizedAllowedIds.has(String(numId)))
|
|
12672
|
+
if (numId !== void 0 && normalizedAllowedIds.has(String(numId)))
|
|
12673
|
+
return true;
|
|
12244
12674
|
return false;
|
|
12245
12675
|
};
|
|
12246
12676
|
const checkIsActive = (section, targetId) => {
|
|
12247
12677
|
if (targetId === null || targetId === void 0) return false;
|
|
12248
12678
|
const sTarget = String(targetId);
|
|
12249
12679
|
if (section.id && String(section.id) === sTarget) return true;
|
|
12250
|
-
if (section.section_id && String(section.section_id) === sTarget)
|
|
12680
|
+
if (section.section_id && String(section.section_id) === sTarget)
|
|
12681
|
+
return true;
|
|
12251
12682
|
if (section.section_numeric_id !== void 0) {
|
|
12252
12683
|
if (String(section.section_numeric_id) === sTarget) return true;
|
|
12253
12684
|
}
|
|
@@ -12263,7 +12694,9 @@ function XViewScene({
|
|
|
12263
12694
|
traverse(sectionTree);
|
|
12264
12695
|
return ids;
|
|
12265
12696
|
};
|
|
12266
|
-
const existingIndex = renderedAncestries.findIndex(
|
|
12697
|
+
const existingIndex = renderedAncestries.findIndex(
|
|
12698
|
+
(a) => String(a.id) === String(ancestryObject.ancestry_id)
|
|
12699
|
+
);
|
|
12267
12700
|
let skipGeneration = false;
|
|
12268
12701
|
let ancestryEntry = null;
|
|
12269
12702
|
if (existingIndex !== -1) {
|
|
@@ -12318,9 +12751,15 @@ function XViewScene({
|
|
|
12318
12751
|
if (line.material) line.material.dispose();
|
|
12319
12752
|
});
|
|
12320
12753
|
}
|
|
12321
|
-
const allParentNodes = Object.values(parentDataRef.current).flatMap(
|
|
12754
|
+
const allParentNodes = Object.values(parentDataRef.current).flatMap(
|
|
12755
|
+
(fileData) => fileData.nodes
|
|
12756
|
+
);
|
|
12322
12757
|
const allAncestries = ancestryDataRef.current || [];
|
|
12323
|
-
const fullTree = buildFullAncestryTree(
|
|
12758
|
+
const fullTree = buildFullAncestryTree(
|
|
12759
|
+
ancestryObject.tree,
|
|
12760
|
+
allParentNodes,
|
|
12761
|
+
allAncestries
|
|
12762
|
+
);
|
|
12324
12763
|
if (!fullTree) return;
|
|
12325
12764
|
const rootNodeId = String(ancestryObject.ancestral_node);
|
|
12326
12765
|
let rootNodeMesh = nodeObjects[rootNodeId];
|
|
@@ -12363,7 +12802,10 @@ function XViewScene({
|
|
|
12363
12802
|
const colorIndex = stateRef.current.ancestryRenderCounter % 3;
|
|
12364
12803
|
colorHex = ANCESTRY_COLORS[colorIndex];
|
|
12365
12804
|
}
|
|
12366
|
-
const resolution = new THREE3.Vector2(
|
|
12805
|
+
const resolution = new THREE3.Vector2(
|
|
12806
|
+
renderer.domElement.clientWidth,
|
|
12807
|
+
renderer.domElement.clientHeight
|
|
12808
|
+
);
|
|
12367
12809
|
const cleanupLinesForNode = (nodeId) => {
|
|
12368
12810
|
if (!ancestryEntry || !ancestryEntry.lines) return;
|
|
12369
12811
|
const linesKeep = [];
|
|
@@ -12403,7 +12845,13 @@ function XViewScene({
|
|
|
12403
12845
|
}
|
|
12404
12846
|
if (originMesh && rootNodeMesh) {
|
|
12405
12847
|
cleanupLinesForNode(rootNodeId);
|
|
12406
|
-
const branchLine = createAncestryLinkLine(
|
|
12848
|
+
const branchLine = createAncestryLinkLine(
|
|
12849
|
+
originMesh,
|
|
12850
|
+
rootNodeMesh,
|
|
12851
|
+
resolution,
|
|
12852
|
+
{},
|
|
12853
|
+
colorHex
|
|
12854
|
+
);
|
|
12407
12855
|
ancestryGroup.add(branchLine);
|
|
12408
12856
|
ancestryEntry.lines.push(branchLine);
|
|
12409
12857
|
}
|
|
@@ -12414,8 +12862,14 @@ function XViewScene({
|
|
|
12414
12862
|
if (!children || children.length === 0) return null;
|
|
12415
12863
|
let lastRenderedMesh = null;
|
|
12416
12864
|
const numChildren = children.length;
|
|
12417
|
-
const forwardVec = new THREE3.Vector3(0, 0, 1).applyAxisAngle(
|
|
12418
|
-
|
|
12865
|
+
const forwardVec = new THREE3.Vector3(0, 0, 1).applyAxisAngle(
|
|
12866
|
+
new THREE3.Vector3(0, 1, 0),
|
|
12867
|
+
currentAngle
|
|
12868
|
+
);
|
|
12869
|
+
const rightVec = new THREE3.Vector3(1, 0, 0).applyAxisAngle(
|
|
12870
|
+
new THREE3.Vector3(0, 1, 0),
|
|
12871
|
+
currentAngle
|
|
12872
|
+
);
|
|
12419
12873
|
const angleRange = numChildren > 3 ? Math.PI : Math.PI / 1.5;
|
|
12420
12874
|
children.forEach((childItem, index) => {
|
|
12421
12875
|
if (childItem.is_section) return;
|
|
@@ -12436,14 +12890,30 @@ function XViewScene({
|
|
|
12436
12890
|
targetPositionsCache.set(sNodeId, childPosition.clone());
|
|
12437
12891
|
cleanupLinesForNode(sNodeId);
|
|
12438
12892
|
}
|
|
12439
|
-
const childMesh = addOrUpdateNodeMesh(
|
|
12893
|
+
const childMesh = addOrUpdateNodeMesh(
|
|
12894
|
+
childItem.node,
|
|
12895
|
+
childPosition,
|
|
12896
|
+
true
|
|
12897
|
+
);
|
|
12440
12898
|
allRenderedNodePositions.push(childPosition);
|
|
12441
|
-
const line = createAncestryLinkLine(
|
|
12899
|
+
const line = createAncestryLinkLine(
|
|
12900
|
+
parentMesh,
|
|
12901
|
+
childMesh,
|
|
12902
|
+
resolution,
|
|
12903
|
+
childItem.relationship,
|
|
12904
|
+
colorHex
|
|
12905
|
+
);
|
|
12442
12906
|
ancestryGroup.add(line);
|
|
12443
12907
|
ancestryEntry.lines.push(line);
|
|
12444
12908
|
lastRenderedMesh = childMesh;
|
|
12445
12909
|
if (childItem.children && childItem.children.length > 0) {
|
|
12446
|
-
const lastDescendant = renderCluster(
|
|
12910
|
+
const lastDescendant = renderCluster(
|
|
12911
|
+
childItem.children,
|
|
12912
|
+
childMesh,
|
|
12913
|
+
childPosition,
|
|
12914
|
+
level + 1,
|
|
12915
|
+
currentAngle
|
|
12916
|
+
);
|
|
12447
12917
|
if (lastDescendant) lastRenderedMesh = lastDescendant;
|
|
12448
12918
|
}
|
|
12449
12919
|
});
|
|
@@ -12457,9 +12927,13 @@ function XViewScene({
|
|
|
12457
12927
|
else looseNodes.push(child);
|
|
12458
12928
|
});
|
|
12459
12929
|
}
|
|
12460
|
-
sections.sort(
|
|
12930
|
+
sections.sort(
|
|
12931
|
+
(a, b) => (a.section_numeric_id || 0) - (b.section_numeric_id || 0)
|
|
12932
|
+
);
|
|
12461
12933
|
let combinedStartNodes = [...looseNodes];
|
|
12462
|
-
let session0Index = sections.findIndex(
|
|
12934
|
+
let session0Index = sections.findIndex(
|
|
12935
|
+
(s) => s.section_numeric_id === 0 || s.name === "Sess\xE3o 0"
|
|
12936
|
+
);
|
|
12463
12937
|
if (session0Index !== -1) {
|
|
12464
12938
|
const session0 = sections[session0Index];
|
|
12465
12939
|
if (checkShouldRender(session0) && session0.children) {
|
|
@@ -12468,7 +12942,13 @@ function XViewScene({
|
|
|
12468
12942
|
sections.splice(session0Index, 1);
|
|
12469
12943
|
}
|
|
12470
12944
|
const rootTargetPos2 = targetPositionsCache.get(rootNodeId) || rootNodeMesh.position;
|
|
12471
|
-
const lastStartMesh = renderCluster(
|
|
12945
|
+
const lastStartMesh = renderCluster(
|
|
12946
|
+
combinedStartNodes,
|
|
12947
|
+
rootNodeMesh,
|
|
12948
|
+
rootTargetPos2,
|
|
12949
|
+
1,
|
|
12950
|
+
baseRotation
|
|
12951
|
+
);
|
|
12472
12952
|
if (lastStartMesh) {
|
|
12473
12953
|
currentAnchorMesh = lastStartMesh;
|
|
12474
12954
|
}
|
|
@@ -12479,10 +12959,18 @@ function XViewScene({
|
|
|
12479
12959
|
const sectionNodes = section.children || [];
|
|
12480
12960
|
if (sectionNodes.length > 0) {
|
|
12481
12961
|
const parentAngle = nodeRotationMap.get(String(currentAnchorMesh.userData.id)) ?? baseRotation;
|
|
12482
|
-
const lastMeshOfThisSection = renderCluster(
|
|
12962
|
+
const lastMeshOfThisSection = renderCluster(
|
|
12963
|
+
sectionNodes,
|
|
12964
|
+
currentAnchorMesh,
|
|
12965
|
+
currentAnchorPosition,
|
|
12966
|
+
1,
|
|
12967
|
+
parentAngle
|
|
12968
|
+
);
|
|
12483
12969
|
if (lastMeshOfThisSection) {
|
|
12484
12970
|
currentAnchorMesh = lastMeshOfThisSection;
|
|
12485
|
-
currentAnchorPosition = targetPositionsCache.get(
|
|
12971
|
+
currentAnchorPosition = targetPositionsCache.get(
|
|
12972
|
+
String(lastMeshOfThisSection.userData.id)
|
|
12973
|
+
) || lastMeshOfThisSection.position;
|
|
12486
12974
|
}
|
|
12487
12975
|
}
|
|
12488
12976
|
}
|
|
@@ -12511,7 +12999,10 @@ function XViewScene({
|
|
|
12511
12999
|
} else {
|
|
12512
13000
|
const directChildren = fullTree.children ? fullTree.children.filter((c) => !c.is_section) : [];
|
|
12513
13001
|
if (directChildren.length > 0) {
|
|
12514
|
-
targetSectionForZone = {
|
|
13002
|
+
targetSectionForZone = {
|
|
13003
|
+
name: "In\xEDcio",
|
|
13004
|
+
children: directChildren
|
|
13005
|
+
};
|
|
12515
13006
|
}
|
|
12516
13007
|
}
|
|
12517
13008
|
} else {
|
|
@@ -12585,7 +13076,10 @@ function XViewScene({
|
|
|
12585
13076
|
stateRef.current.ancestryLinks = stateRef.current.renderedAncestries.flatMap((a) => a.lines);
|
|
12586
13077
|
focusTargetPosition = center;
|
|
12587
13078
|
focusTargetRotation = baseRotation;
|
|
12588
|
-
const desiredDistance = Math.max(
|
|
13079
|
+
const desiredDistance = Math.max(
|
|
13080
|
+
x_view_config.CAMERA_ZOOM_DISTANCE,
|
|
13081
|
+
radius * 2.8
|
|
13082
|
+
);
|
|
12589
13083
|
focusZoomFactor = x_view_config.CAMERA_ZOOM_DISTANCE / desiredDistance;
|
|
12590
13084
|
} else {
|
|
12591
13085
|
const anchorId = String(currentAnchorMesh.userData.id);
|
|
@@ -12600,13 +13094,18 @@ function XViewScene({
|
|
|
12600
13094
|
}
|
|
12601
13095
|
if (!focusTargetPosition && !allowedSectionIds) {
|
|
12602
13096
|
if (allRenderedNodePositions.length > 0) {
|
|
12603
|
-
const boundingBox = new THREE3.Box3().setFromPoints(
|
|
13097
|
+
const boundingBox = new THREE3.Box3().setFromPoints(
|
|
13098
|
+
allRenderedNodePositions
|
|
13099
|
+
);
|
|
12604
13100
|
const center = new THREE3.Vector3();
|
|
12605
13101
|
boundingBox.getCenter(center);
|
|
12606
13102
|
const size = new THREE3.Vector3();
|
|
12607
13103
|
boundingBox.getSize(size);
|
|
12608
13104
|
const maxDim = Math.max(size.x, size.y, size.z);
|
|
12609
|
-
const fitZoom = Math.min(
|
|
13105
|
+
const fitZoom = Math.min(
|
|
13106
|
+
1,
|
|
13107
|
+
x_view_config.CAMERA_ZOOM_DISTANCE / (maxDim * 1.5)
|
|
13108
|
+
);
|
|
12610
13109
|
const defaultBase = new THREE3.Vector3(-50, 40, 20);
|
|
12611
13110
|
const rotatedCinematicAngle = defaultBase.clone().applyAxisAngle(new THREE3.Vector3(0, 1, 0), baseRotation);
|
|
12612
13111
|
tweenToTarget(center, fitZoom, rotatedCinematicAngle);
|
|
@@ -12625,210 +13124,280 @@ function XViewScene({
|
|
|
12625
13124
|
tweenToTarget(targetPos, focusZoomFactor, rotatedCinematicAngle);
|
|
12626
13125
|
}
|
|
12627
13126
|
},
|
|
12628
|
-
[
|
|
13127
|
+
[
|
|
13128
|
+
addOrUpdateNodeMesh,
|
|
13129
|
+
tweenToTarget,
|
|
13130
|
+
buildFullAncestryTree,
|
|
13131
|
+
readingMode.isActive,
|
|
13132
|
+
ancestryMode.isActive
|
|
13133
|
+
]
|
|
12629
13134
|
);
|
|
12630
|
-
const handleRenderAbstractionTree = (0, import_react26.useCallback)(
|
|
12631
|
-
|
|
12632
|
-
|
|
12633
|
-
|
|
12634
|
-
|
|
12635
|
-
|
|
12636
|
-
|
|
12637
|
-
|
|
12638
|
-
|
|
12639
|
-
|
|
12640
|
-
|
|
12641
|
-
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
13135
|
+
const handleRenderAbstractionTree = (0, import_react26.useCallback)(
|
|
13136
|
+
(ancestryObject, targetNodeId = null) => {
|
|
13137
|
+
setContextMenu(
|
|
13138
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
13139
|
+
);
|
|
13140
|
+
if (!ancestryObject || !ancestryObject.abstraction_tree) return;
|
|
13141
|
+
const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
|
|
13142
|
+
const allParentNodes = Object.values(parentDataRef.current).flatMap(
|
|
13143
|
+
(f) => f.nodes
|
|
13144
|
+
);
|
|
13145
|
+
let fullTree = buildFullAncestryTree(
|
|
13146
|
+
ancestryObject.abstraction_tree,
|
|
13147
|
+
allParentNodes,
|
|
13148
|
+
ancestryDataRef.current
|
|
13149
|
+
);
|
|
13150
|
+
if (!fullTree || !fullTree.node) return;
|
|
13151
|
+
if (targetNodeId) {
|
|
13152
|
+
const pruneTreeToPath = (treeNode, targetId) => {
|
|
13153
|
+
var _a2;
|
|
13154
|
+
if (!treeNode) return null;
|
|
13155
|
+
const currentId = treeNode.is_section ? treeNode.section_id : String((_a2 = treeNode.node) == null ? void 0 : _a2.id);
|
|
13156
|
+
if (String(currentId) === String(targetId)) {
|
|
13157
|
+
return { ...treeNode, children: [] };
|
|
12651
13158
|
}
|
|
12652
|
-
|
|
12653
|
-
|
|
12654
|
-
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
}
|
|
12658
|
-
const absId = ancestryObject.ancestry_id + "_abs";
|
|
12659
|
-
handleClearAncestryVisuals(absId);
|
|
12660
|
-
const colorHex = 9133302;
|
|
12661
|
-
const resolution = new THREE3.Vector2(renderer.domElement.clientWidth, renderer.domElement.clientHeight);
|
|
12662
|
-
const ancestryEntry = { id: absId, lines: [], isFullRender: true };
|
|
12663
|
-
renderedAncestries.push(ancestryEntry);
|
|
12664
|
-
const rootNodeId = String(fullTree.node.id);
|
|
12665
|
-
let rootNodeMesh = nodeObjects[rootNodeId];
|
|
12666
|
-
let rootTargetPos = rootNodeMesh ? rootNodeMesh.position.clone() : new THREE3.Vector3(0, 0, 0);
|
|
12667
|
-
if (!rootNodeMesh) {
|
|
12668
|
-
rootNodeMesh = addOrUpdateNodeMesh(fullTree.node, rootTargetPos, true);
|
|
12669
|
-
}
|
|
12670
|
-
const SPACING_Y = -40;
|
|
12671
|
-
const SPACING_X = 55;
|
|
12672
|
-
const renderVertical = (treeNode, parentMesh, parentPos, level) => {
|
|
12673
|
-
if (!treeNode.children || treeNode.children.length === 0) return;
|
|
12674
|
-
const totalSiblings = treeNode.children.length;
|
|
12675
|
-
treeNode.children.forEach((childItem, i) => {
|
|
12676
|
-
if (!childItem.node) return;
|
|
12677
|
-
const childX = parentPos.x + (i - (totalSiblings - 1) / 2) * (SPACING_X / Math.max(1, level * 0.4));
|
|
12678
|
-
const childY = parentPos.y + SPACING_Y;
|
|
12679
|
-
const childPos = new THREE3.Vector3(childX, childY, parentPos.z);
|
|
12680
|
-
const childMesh = addOrUpdateNodeMesh(childItem.node, childPos, true);
|
|
12681
|
-
const line = createAncestryLinkLine(parentMesh, childMesh, resolution, {}, colorHex);
|
|
12682
|
-
ancestryGroup.add(line);
|
|
12683
|
-
ancestryEntry.lines.push(line);
|
|
12684
|
-
renderVertical(childItem, childMesh, childPos, level + 1);
|
|
12685
|
-
});
|
|
12686
|
-
};
|
|
12687
|
-
renderVertical(fullTree, rootNodeMesh, rootTargetPos, 1);
|
|
12688
|
-
stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
|
|
12689
|
-
tweenToTarget(rootTargetPos, 0.7);
|
|
12690
|
-
}, [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, handleClearAncestryVisuals]);
|
|
12691
|
-
const handleReadModeBranchNav = (0, import_react26.useCallback)((nodeId, action, direction = "right") => {
|
|
12692
|
-
const { ancestry, branchStack } = readingMode;
|
|
12693
|
-
if (!ancestry || !ancestry.tree) return;
|
|
12694
|
-
const allAncestries = ancestryDataRef.current || [];
|
|
12695
|
-
const fullTree = buildFullAncestryTree(ancestry.tree, Object.values(parentDataRef.current).flatMap((f) => f.nodes), allAncestries);
|
|
12696
|
-
if (action === "open") {
|
|
12697
|
-
let currentPtr = fullTree;
|
|
12698
|
-
for (const step of branchStack) {
|
|
12699
|
-
const found = findNodePath3(currentPtr, step.nodeId);
|
|
12700
|
-
if (found && found.node.parallel_branches) {
|
|
12701
|
-
const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
|
|
12702
|
-
if (branch) currentPtr = branch.tree;
|
|
12703
|
-
}
|
|
12704
|
-
}
|
|
12705
|
-
const foundTarget = findNodePath3(currentPtr, nodeId);
|
|
12706
|
-
if (foundTarget && foundTarget.node && foundTarget.node.parallel_branches && foundTarget.node.parallel_branches.length > 0) {
|
|
12707
|
-
const branchToOpen = foundTarget.node.parallel_branches.find((b) => (b.direction || "right") === direction);
|
|
12708
|
-
if (!branchToOpen) return;
|
|
12709
|
-
if (branchToOpen && branchToOpen.tree) {
|
|
12710
|
-
const parentIndexToSave = stateRef.current.readMode.currentMaxIndex;
|
|
12711
|
-
const savedBranchProgress = 0;
|
|
12712
|
-
stateRef.current.readMode.currentMaxIndex = savedBranchProgress;
|
|
12713
|
-
stateRef.current.maxAncestryRenderIndex = savedBranchProgress;
|
|
12714
|
-
const newStack = [...branchStack, {
|
|
12715
|
-
nodeId,
|
|
12716
|
-
branchId: branchToOpen.id,
|
|
12717
|
-
savedMaxIndex: parentIndexToSave,
|
|
12718
|
-
entryDirection: direction
|
|
12719
|
-
}];
|
|
12720
|
-
setReadingMode((prev) => ({ ...prev, branchStack: newStack, initialSectionId: null }));
|
|
12721
|
-
const branchAncestryObj = {
|
|
12722
|
-
ancestry_id: branchToOpen.id,
|
|
12723
|
-
ancestral_node: branchToOpen.tree.node.id,
|
|
12724
|
-
name: branchToOpen.name,
|
|
12725
|
-
description: branchToOpen.description,
|
|
12726
|
-
description_sections: branchToOpen.description_sections,
|
|
12727
|
-
tree: branchToOpen.tree,
|
|
12728
|
-
_originNodeId: nodeId,
|
|
12729
|
-
_branchDirection: direction
|
|
12730
|
-
};
|
|
12731
|
-
const allowedIds = /* @__PURE__ */ new Set(["preamble", 0, "0"]);
|
|
12732
|
-
const branchSections = parseDescriptionSections(branchToOpen.description || "", branchToOpen.description_sections || []);
|
|
12733
|
-
for (let i = 0; i <= savedBranchProgress; i++) {
|
|
12734
|
-
if (branchSections[i]) {
|
|
12735
|
-
if (branchSections[i].id) allowedIds.add(String(branchSections[i].id));
|
|
12736
|
-
if (branchSections[i].numericId !== void 0 && branchSections[i].numericId !== null) {
|
|
12737
|
-
allowedIds.add(branchSections[i].numericId);
|
|
12738
|
-
allowedIds.add(String(branchSections[i].numericId));
|
|
13159
|
+
if (treeNode.children && treeNode.children.length > 0) {
|
|
13160
|
+
for (let child of treeNode.children) {
|
|
13161
|
+
const prunedChild = pruneTreeToPath(child, targetId);
|
|
13162
|
+
if (prunedChild) {
|
|
13163
|
+
return { ...treeNode, children: [prunedChild] };
|
|
12739
13164
|
}
|
|
12740
13165
|
}
|
|
12741
13166
|
}
|
|
12742
|
-
|
|
12743
|
-
|
|
12744
|
-
|
|
12745
|
-
|
|
12746
|
-
|
|
12747
|
-
|
|
12748
|
-
|
|
12749
|
-
|
|
12750
|
-
|
|
12751
|
-
|
|
12752
|
-
|
|
12753
|
-
|
|
13167
|
+
return null;
|
|
13168
|
+
};
|
|
13169
|
+
const pruned = pruneTreeToPath(fullTree, targetNodeId);
|
|
13170
|
+
if (pruned) fullTree = pruned;
|
|
13171
|
+
}
|
|
13172
|
+
const absId = ancestryObject.ancestry_id + "_abs";
|
|
13173
|
+
handleClearAncestryVisuals(absId);
|
|
13174
|
+
const colorHex = 9133302;
|
|
13175
|
+
const resolution = new THREE3.Vector2(
|
|
13176
|
+
renderer.domElement.clientWidth,
|
|
13177
|
+
renderer.domElement.clientHeight
|
|
13178
|
+
);
|
|
13179
|
+
const ancestryEntry = { id: absId, lines: [], isFullRender: true };
|
|
13180
|
+
renderedAncestries.push(ancestryEntry);
|
|
13181
|
+
const rootNodeId = String(fullTree.node.id);
|
|
13182
|
+
let rootNodeMesh = nodeObjects[rootNodeId];
|
|
13183
|
+
let rootTargetPos = rootNodeMesh ? rootNodeMesh.position.clone() : new THREE3.Vector3(0, 0, 0);
|
|
13184
|
+
if (!rootNodeMesh) {
|
|
13185
|
+
rootNodeMesh = addOrUpdateNodeMesh(fullTree.node, rootTargetPos, true);
|
|
12754
13186
|
}
|
|
12755
|
-
|
|
12756
|
-
|
|
12757
|
-
const
|
|
12758
|
-
|
|
12759
|
-
|
|
12760
|
-
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
|
|
12764
|
-
|
|
12765
|
-
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
|
|
12770
|
-
|
|
13187
|
+
const SPACING_Y = -40;
|
|
13188
|
+
const SPACING_X = 55;
|
|
13189
|
+
const renderVertical = (treeNode, parentMesh, parentPos, level) => {
|
|
13190
|
+
if (!treeNode.children || treeNode.children.length === 0) return;
|
|
13191
|
+
const totalSiblings = treeNode.children.length;
|
|
13192
|
+
treeNode.children.forEach((childItem, i) => {
|
|
13193
|
+
if (!childItem.node) return;
|
|
13194
|
+
const childX = parentPos.x + (i - (totalSiblings - 1) / 2) * (SPACING_X / Math.max(1, level * 0.4));
|
|
13195
|
+
const childY = parentPos.y + SPACING_Y;
|
|
13196
|
+
const childPos = new THREE3.Vector3(childX, childY, parentPos.z);
|
|
13197
|
+
const childMesh = addOrUpdateNodeMesh(childItem.node, childPos, true);
|
|
13198
|
+
const line = createAncestryLinkLine(
|
|
13199
|
+
parentMesh,
|
|
13200
|
+
childMesh,
|
|
13201
|
+
resolution,
|
|
13202
|
+
{},
|
|
13203
|
+
colorHex
|
|
13204
|
+
);
|
|
13205
|
+
ancestryGroup.add(line);
|
|
13206
|
+
ancestryEntry.lines.push(line);
|
|
13207
|
+
renderVertical(childItem, childMesh, childPos, level + 1);
|
|
13208
|
+
});
|
|
13209
|
+
};
|
|
13210
|
+
renderVertical(fullTree, rootNodeMesh, rootTargetPos, 1);
|
|
13211
|
+
stateRef.current.ancestryLinks = renderedAncestries.flatMap(
|
|
13212
|
+
(a) => a.lines
|
|
13213
|
+
);
|
|
13214
|
+
tweenToTarget(rootTargetPos, 0.7);
|
|
13215
|
+
},
|
|
13216
|
+
[
|
|
13217
|
+
addOrUpdateNodeMesh,
|
|
13218
|
+
tweenToTarget,
|
|
13219
|
+
buildFullAncestryTree,
|
|
13220
|
+
handleClearAncestryVisuals
|
|
13221
|
+
]
|
|
13222
|
+
);
|
|
13223
|
+
const handleReadModeBranchNav = (0, import_react26.useCallback)(
|
|
13224
|
+
(nodeId, action, direction = "right") => {
|
|
13225
|
+
const { ancestry, branchStack } = readingMode;
|
|
13226
|
+
if (!ancestry || !ancestry.tree) return;
|
|
13227
|
+
const allAncestries = ancestryDataRef.current || [];
|
|
13228
|
+
const fullTree = buildFullAncestryTree(
|
|
13229
|
+
ancestry.tree,
|
|
13230
|
+
Object.values(parentDataRef.current).flatMap((f) => f.nodes),
|
|
13231
|
+
allAncestries
|
|
13232
|
+
);
|
|
13233
|
+
if (action === "open") {
|
|
13234
|
+
let currentPtr = fullTree;
|
|
13235
|
+
for (const step of branchStack) {
|
|
13236
|
+
const found = findNodePath3(currentPtr, step.nodeId);
|
|
12771
13237
|
if (found && found.node.parallel_branches) {
|
|
12772
|
-
const branch = found.node.parallel_branches.find(
|
|
12773
|
-
|
|
12774
|
-
|
|
12775
|
-
|
|
13238
|
+
const branch = found.node.parallel_branches.find(
|
|
13239
|
+
(b) => b.id === step.branchId
|
|
13240
|
+
);
|
|
13241
|
+
if (branch) currentPtr = branch.tree;
|
|
13242
|
+
}
|
|
13243
|
+
}
|
|
13244
|
+
const foundTarget = findNodePath3(currentPtr, nodeId);
|
|
13245
|
+
if (foundTarget && foundTarget.node && foundTarget.node.parallel_branches && foundTarget.node.parallel_branches.length > 0) {
|
|
13246
|
+
const branchToOpen = foundTarget.node.parallel_branches.find(
|
|
13247
|
+
(b) => (b.direction || "right") === direction
|
|
13248
|
+
);
|
|
13249
|
+
if (!branchToOpen) return;
|
|
13250
|
+
if (branchToOpen && branchToOpen.tree) {
|
|
13251
|
+
const parentIndexToSave = stateRef.current.readMode.currentMaxIndex;
|
|
13252
|
+
const savedBranchProgress = 0;
|
|
13253
|
+
stateRef.current.readMode.currentMaxIndex = savedBranchProgress;
|
|
13254
|
+
stateRef.current.maxAncestryRenderIndex = savedBranchProgress;
|
|
13255
|
+
const newStack = [
|
|
13256
|
+
...branchStack,
|
|
13257
|
+
{
|
|
13258
|
+
nodeId,
|
|
13259
|
+
branchId: branchToOpen.id,
|
|
13260
|
+
savedMaxIndex: parentIndexToSave,
|
|
13261
|
+
entryDirection: direction
|
|
13262
|
+
}
|
|
13263
|
+
];
|
|
13264
|
+
setReadingMode((prev) => ({
|
|
13265
|
+
...prev,
|
|
13266
|
+
branchStack: newStack,
|
|
13267
|
+
initialSectionId: null
|
|
13268
|
+
}));
|
|
13269
|
+
const branchAncestryObj = {
|
|
13270
|
+
ancestry_id: branchToOpen.id,
|
|
13271
|
+
ancestral_node: branchToOpen.tree.node.id,
|
|
13272
|
+
name: branchToOpen.name,
|
|
13273
|
+
description: branchToOpen.description,
|
|
13274
|
+
description_sections: branchToOpen.description_sections,
|
|
13275
|
+
tree: branchToOpen.tree,
|
|
13276
|
+
_originNodeId: nodeId,
|
|
13277
|
+
_branchDirection: direction
|
|
13278
|
+
};
|
|
13279
|
+
const allowedIds = /* @__PURE__ */ new Set(["preamble", 0, "0"]);
|
|
13280
|
+
const branchSections = parseDescriptionSections(
|
|
13281
|
+
branchToOpen.description || "",
|
|
13282
|
+
branchToOpen.description_sections || []
|
|
13283
|
+
);
|
|
13284
|
+
for (let i = 0; i <= savedBranchProgress; i++) {
|
|
13285
|
+
if (branchSections[i]) {
|
|
13286
|
+
if (branchSections[i].id)
|
|
13287
|
+
allowedIds.add(String(branchSections[i].id));
|
|
13288
|
+
if (branchSections[i].numericId !== void 0 && branchSections[i].numericId !== null) {
|
|
13289
|
+
allowedIds.add(branchSections[i].numericId);
|
|
13290
|
+
allowedIds.add(String(branchSections[i].numericId));
|
|
13291
|
+
}
|
|
13292
|
+
}
|
|
12776
13293
|
}
|
|
13294
|
+
const rotation = newStack.reduce((acc, step) => {
|
|
13295
|
+
return acc + (step.entryDirection === "left" ? -Math.PI / 2 : Math.PI / 2);
|
|
13296
|
+
}, 0);
|
|
13297
|
+
const initialFocusId = "preamble";
|
|
13298
|
+
handleRenderAncestry(
|
|
13299
|
+
branchAncestryObj,
|
|
13300
|
+
allowedIds,
|
|
13301
|
+
initialFocusId,
|
|
13302
|
+
rotation,
|
|
13303
|
+
false
|
|
13304
|
+
);
|
|
12777
13305
|
}
|
|
12778
13306
|
}
|
|
12779
|
-
|
|
12780
|
-
|
|
12781
|
-
|
|
12782
|
-
|
|
12783
|
-
|
|
12784
|
-
|
|
12785
|
-
|
|
12786
|
-
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12792
|
-
|
|
12793
|
-
|
|
12794
|
-
|
|
12795
|
-
|
|
12796
|
-
|
|
12797
|
-
|
|
12798
|
-
|
|
13307
|
+
} else if (action === "back") {
|
|
13308
|
+
if (branchStack.length === 0) return;
|
|
13309
|
+
const newStack = [...branchStack];
|
|
13310
|
+
const popped = newStack.pop();
|
|
13311
|
+
if (popped && popped.branchId) {
|
|
13312
|
+
stateRef.current.readMode.progressMap[popped.branchId] = stateRef.current.readMode.currentMaxIndex;
|
|
13313
|
+
}
|
|
13314
|
+
const parentSavedIndex = popped.savedMaxIndex !== void 0 ? popped.savedMaxIndex : 0;
|
|
13315
|
+
stateRef.current.readMode.currentMaxIndex = parentSavedIndex;
|
|
13316
|
+
stateRef.current.maxAncestryRenderIndex = parentSavedIndex;
|
|
13317
|
+
let targetTreeToRender = fullTree;
|
|
13318
|
+
let targetAncestryInfo = ancestry;
|
|
13319
|
+
if (newStack.length > 0) {
|
|
13320
|
+
let ptr = fullTree;
|
|
13321
|
+
for (const step of newStack) {
|
|
13322
|
+
const found = findNodePath3(ptr, step.nodeId);
|
|
13323
|
+
if (found && found.node.parallel_branches) {
|
|
13324
|
+
const branch = found.node.parallel_branches.find(
|
|
13325
|
+
(b) => b.id === step.branchId
|
|
13326
|
+
);
|
|
13327
|
+
if (branch) {
|
|
13328
|
+
ptr = branch.tree;
|
|
13329
|
+
targetAncestryInfo = {
|
|
13330
|
+
...branch,
|
|
13331
|
+
ancestry_id: branch.id,
|
|
13332
|
+
ancestral_node: branch.tree.node.id
|
|
13333
|
+
};
|
|
13334
|
+
}
|
|
13335
|
+
}
|
|
13336
|
+
}
|
|
13337
|
+
targetTreeToRender = ptr;
|
|
13338
|
+
}
|
|
13339
|
+
const activeParentStackItem = newStack.length > 0 ? newStack[newStack.length - 1] : null;
|
|
13340
|
+
const parentAncestryObj = {
|
|
13341
|
+
...targetAncestryInfo,
|
|
13342
|
+
tree: targetTreeToRender,
|
|
13343
|
+
_originNodeId: activeParentStackItem ? activeParentStackItem.nodeId : null,
|
|
13344
|
+
_branchDirection: activeParentStackItem ? activeParentStackItem.entryDirection : null
|
|
13345
|
+
};
|
|
13346
|
+
const descriptionText = targetAncestryInfo.description || "";
|
|
13347
|
+
const savedSections = targetAncestryInfo.description_sections || [];
|
|
13348
|
+
const sections = parseDescriptionSections(
|
|
13349
|
+
descriptionText,
|
|
13350
|
+
savedSections
|
|
13351
|
+
);
|
|
13352
|
+
let focusTargetId = null;
|
|
13353
|
+
if (popped && popped.nodeId) {
|
|
13354
|
+
const mentionTag = `[[MENTION:node:${popped.nodeId}]]`;
|
|
13355
|
+
for (let i = 0; i < sections.length; i++) {
|
|
13356
|
+
if (sections[i].content && sections[i].content.includes(mentionTag)) {
|
|
13357
|
+
const section = sections[i];
|
|
13358
|
+
focusTargetId = section.numericId !== void 0 ? section.numericId : section.id;
|
|
13359
|
+
break;
|
|
13360
|
+
}
|
|
12799
13361
|
}
|
|
12800
13362
|
}
|
|
12801
|
-
|
|
12802
|
-
|
|
12803
|
-
|
|
12804
|
-
|
|
12805
|
-
|
|
12806
|
-
|
|
12807
|
-
|
|
12808
|
-
|
|
12809
|
-
|
|
12810
|
-
|
|
12811
|
-
|
|
13363
|
+
const allowedIds = /* @__PURE__ */ new Set();
|
|
13364
|
+
allowedIds.add("preamble");
|
|
13365
|
+
allowedIds.add(0);
|
|
13366
|
+
allowedIds.add("0");
|
|
13367
|
+
for (let i = 0; i <= parentSavedIndex; i++) {
|
|
13368
|
+
if (sections[i]) {
|
|
13369
|
+
if (sections[i].id) allowedIds.add(String(sections[i].id));
|
|
13370
|
+
if (sections[i].numericId !== void 0 && sections[i].numericId !== null) {
|
|
13371
|
+
allowedIds.add(sections[i].numericId);
|
|
13372
|
+
allowedIds.add(String(sections[i].numericId));
|
|
13373
|
+
}
|
|
12812
13374
|
}
|
|
12813
13375
|
}
|
|
12814
|
-
|
|
12815
|
-
|
|
12816
|
-
|
|
12817
|
-
|
|
12818
|
-
|
|
12819
|
-
|
|
12820
|
-
|
|
12821
|
-
|
|
12822
|
-
|
|
13376
|
+
const rotation = newStack.reduce((acc, step) => {
|
|
13377
|
+
return acc + (step.entryDirection === "left" ? -Math.PI / 2 : Math.PI / 2);
|
|
13378
|
+
}, 0);
|
|
13379
|
+
handleRenderAncestry(
|
|
13380
|
+
parentAncestryObj,
|
|
13381
|
+
allowedIds,
|
|
13382
|
+
focusTargetId,
|
|
13383
|
+
rotation,
|
|
13384
|
+
false
|
|
13385
|
+
);
|
|
13386
|
+
if (popped && popped.nodeId) {
|
|
13387
|
+
const nodeMesh = stateRef.current.nodeObjects[String(popped.nodeId)];
|
|
13388
|
+
if (nodeMesh) {
|
|
13389
|
+
tweenToTarget(nodeMesh);
|
|
13390
|
+
}
|
|
12823
13391
|
}
|
|
13392
|
+
setReadingMode((prev) => ({
|
|
13393
|
+
...prev,
|
|
13394
|
+
branchStack: newStack,
|
|
13395
|
+
initialSectionId: focusTargetId
|
|
13396
|
+
}));
|
|
12824
13397
|
}
|
|
12825
|
-
|
|
12826
|
-
|
|
12827
|
-
|
|
12828
|
-
initialSectionId: focusTargetId
|
|
12829
|
-
}));
|
|
12830
|
-
}
|
|
12831
|
-
}, [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]);
|
|
13398
|
+
},
|
|
13399
|
+
[readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
|
|
13400
|
+
);
|
|
12832
13401
|
const handleReadModeHighlight = (0, import_react26.useCallback)((nodeId) => {
|
|
12833
13402
|
if (stateRef.current.highlightedNodeId !== nodeId) {
|
|
12834
13403
|
stateRef.current.highlightedNodeId = nodeId;
|
|
@@ -12836,7 +13405,8 @@ function XViewScene({
|
|
|
12836
13405
|
setHighlightedNodeId(nodeId);
|
|
12837
13406
|
}, []);
|
|
12838
13407
|
const activeNodeBranches = (0, import_react26.useMemo)(() => {
|
|
12839
|
-
if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
|
|
13408
|
+
if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
|
|
13409
|
+
return null;
|
|
12840
13410
|
const fullTree = buildFullAncestryTree(
|
|
12841
13411
|
readingMode.ancestry.tree,
|
|
12842
13412
|
Object.values(parentDataRef.current).flatMap((f) => f.nodes),
|
|
@@ -12871,7 +13441,13 @@ function XViewScene({
|
|
|
12871
13441
|
};
|
|
12872
13442
|
}
|
|
12873
13443
|
return null;
|
|
12874
|
-
}, [
|
|
13444
|
+
}, [
|
|
13445
|
+
highlightedNodeId,
|
|
13446
|
+
readingMode.ancestry,
|
|
13447
|
+
buildFullAncestryTree,
|
|
13448
|
+
readingMode.branchStack,
|
|
13449
|
+
ancestryDataRef.current
|
|
13450
|
+
]);
|
|
12875
13451
|
const backNavigationInfo = (0, import_react26.useMemo)(() => {
|
|
12876
13452
|
const { branchStack } = readingMode;
|
|
12877
13453
|
if (!branchStack || branchStack.length === 0) return null;
|
|
@@ -12907,7 +13483,9 @@ function XViewScene({
|
|
|
12907
13483
|
for (const step of branchStack) {
|
|
12908
13484
|
const found = findNodePath3(currentPtr, step.nodeId);
|
|
12909
13485
|
if (found && found.node.parallel_branches) {
|
|
12910
|
-
const branch = found.node.parallel_branches.find(
|
|
13486
|
+
const branch = found.node.parallel_branches.find(
|
|
13487
|
+
(b) => b.id === step.branchId
|
|
13488
|
+
);
|
|
12911
13489
|
if (branch) {
|
|
12912
13490
|
currentPtr = branch.tree;
|
|
12913
13491
|
currentMeta = branch;
|
|
@@ -12928,17 +13506,26 @@ function XViewScene({
|
|
|
12928
13506
|
if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
|
|
12929
13507
|
return null;
|
|
12930
13508
|
}
|
|
12931
|
-
const allNodes = Object.values(parentDataRef.current || {}).flatMap(
|
|
13509
|
+
const allNodes = Object.values(parentDataRef.current || {}).flatMap(
|
|
13510
|
+
(f) => f.nodes || []
|
|
13511
|
+
);
|
|
12932
13512
|
const allAncestries = ancestryDataRef.current || [];
|
|
12933
13513
|
return buildFullAncestryTree(
|
|
12934
13514
|
readingMode.ancestry.abstraction_tree,
|
|
12935
13515
|
allNodes,
|
|
12936
13516
|
allAncestries
|
|
12937
13517
|
);
|
|
12938
|
-
}, [
|
|
13518
|
+
}, [
|
|
13519
|
+
readingMode.isActive,
|
|
13520
|
+
readingMode.ancestry,
|
|
13521
|
+
buildFullAncestryTree,
|
|
13522
|
+
sceneVersion
|
|
13523
|
+
]);
|
|
12939
13524
|
const handleStartReadingAncestry = (0, import_react26.useCallback)(
|
|
12940
13525
|
async (ancestryObject) => {
|
|
12941
|
-
setContextMenu(
|
|
13526
|
+
setContextMenu(
|
|
13527
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
13528
|
+
);
|
|
12942
13529
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
12943
13530
|
console.warn("Ancestralidade inv\xE1lida para leitura.");
|
|
12944
13531
|
return;
|
|
@@ -12953,7 +13540,7 @@ function XViewScene({
|
|
|
12953
13540
|
const hasAbstractionNodes = ancestryObject.abstraction_tree && ancestryObject.abstraction_tree.children && ancestryObject.abstraction_tree.children.length > 0;
|
|
12954
13541
|
const shouldAutoRenderAbstraction = !hasDescription && !hasMainTreeNodes && hasAbstractionNodes;
|
|
12955
13542
|
setReadingMode({
|
|
12956
|
-
isActive:
|
|
13543
|
+
isActive: hasDescription,
|
|
12957
13544
|
ancestry: ancestryObject,
|
|
12958
13545
|
branchStack: [],
|
|
12959
13546
|
autoAbstraction: shouldAutoRenderAbstraction
|
|
@@ -12971,148 +13558,190 @@ function XViewScene({
|
|
|
12971
13558
|
},
|
|
12972
13559
|
[handleRenderAncestry, handleRenderAbstractionTree]
|
|
12973
13560
|
);
|
|
12974
|
-
const handleReadModeSectionChange = (0, import_react26.useCallback)(
|
|
12975
|
-
|
|
12976
|
-
|
|
12977
|
-
|
|
12978
|
-
|
|
12979
|
-
|
|
12980
|
-
|
|
12981
|
-
|
|
12982
|
-
|
|
12983
|
-
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
|
|
12993
|
-
|
|
12994
|
-
|
|
13561
|
+
const handleReadModeSectionChange = (0, import_react26.useCallback)(
|
|
13562
|
+
(activeSectionId) => {
|
|
13563
|
+
const { ancestry, branchStack } = readingMode;
|
|
13564
|
+
if (!ancestry || !readingMode.isActive) return;
|
|
13565
|
+
let targetObj = ancestry;
|
|
13566
|
+
let targetTree = ancestry.tree;
|
|
13567
|
+
if (branchStack.length > 0) {
|
|
13568
|
+
const allNodes = Object.values(parentDataRef.current).flatMap(
|
|
13569
|
+
(f) => f.nodes
|
|
13570
|
+
);
|
|
13571
|
+
const fullTree = buildFullAncestryTree(
|
|
13572
|
+
ancestry.tree,
|
|
13573
|
+
allNodes,
|
|
13574
|
+
ancestryDataRef.current
|
|
13575
|
+
);
|
|
13576
|
+
let currentPtr = fullTree;
|
|
13577
|
+
for (const step of branchStack) {
|
|
13578
|
+
const found = findNodePath3(currentPtr, step.nodeId);
|
|
13579
|
+
if (found && found.node && found.node.parallel_branches) {
|
|
13580
|
+
const branch = found.node.parallel_branches.find(
|
|
13581
|
+
(b) => b.id === step.branchId
|
|
13582
|
+
);
|
|
13583
|
+
if (branch) {
|
|
13584
|
+
targetObj = branch;
|
|
13585
|
+
targetTree = branch.tree;
|
|
13586
|
+
currentPtr = branch.tree;
|
|
13587
|
+
}
|
|
12995
13588
|
}
|
|
12996
13589
|
}
|
|
12997
13590
|
}
|
|
12998
|
-
|
|
12999
|
-
|
|
13000
|
-
|
|
13001
|
-
|
|
13002
|
-
|
|
13003
|
-
|
|
13004
|
-
|
|
13005
|
-
|
|
13006
|
-
|
|
13007
|
-
|
|
13008
|
-
|
|
13009
|
-
|
|
13010
|
-
|
|
13011
|
-
|
|
13012
|
-
|
|
13013
|
-
|
|
13014
|
-
|
|
13015
|
-
|
|
13016
|
-
|
|
13017
|
-
|
|
13018
|
-
|
|
13019
|
-
allowedIds.add(String(sections[i].
|
|
13591
|
+
const descriptionText = targetObj.description || "";
|
|
13592
|
+
const savedSections = targetObj.description_sections || [];
|
|
13593
|
+
const sections = parseDescriptionSections(descriptionText, savedSections);
|
|
13594
|
+
let activeIndex = sections.findIndex(
|
|
13595
|
+
(s) => String(s.id) === String(activeSectionId)
|
|
13596
|
+
);
|
|
13597
|
+
if (activeIndex === -1 && !isNaN(parseInt(activeSectionId))) {
|
|
13598
|
+
activeIndex = sections.findIndex(
|
|
13599
|
+
(s) => s.numericId === parseInt(activeSectionId)
|
|
13600
|
+
);
|
|
13601
|
+
}
|
|
13602
|
+
if (activeIndex === -1) activeIndex = 0;
|
|
13603
|
+
stateRef.current.readMode.currentMaxIndex = activeIndex;
|
|
13604
|
+
stateRef.current.maxAncestryRenderIndex = activeIndex;
|
|
13605
|
+
const renderLimitIndex = stateRef.current.maxAncestryRenderIndex;
|
|
13606
|
+
const allowedIds = /* @__PURE__ */ new Set();
|
|
13607
|
+
allowedIds.add("preamble");
|
|
13608
|
+
allowedIds.add(0);
|
|
13609
|
+
allowedIds.add("0");
|
|
13610
|
+
for (let i = 0; i <= renderLimitIndex; i++) {
|
|
13611
|
+
if (sections[i]) {
|
|
13612
|
+
if (sections[i].id) allowedIds.add(String(sections[i].id));
|
|
13613
|
+
if (sections[i].numericId !== void 0 && sections[i].numericId !== null) {
|
|
13614
|
+
allowedIds.add(sections[i].numericId);
|
|
13615
|
+
allowedIds.add(String(sections[i].numericId));
|
|
13616
|
+
}
|
|
13020
13617
|
}
|
|
13021
13618
|
}
|
|
13022
|
-
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
|
|
13026
|
-
|
|
13027
|
-
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13619
|
+
const activeSection = sections[activeIndex];
|
|
13620
|
+
let focusTargetId = activeSectionId;
|
|
13621
|
+
if (activeSection && activeSection.numericId !== void 0 && activeSection.numericId !== null) {
|
|
13622
|
+
focusTargetId = activeSection.numericId;
|
|
13623
|
+
}
|
|
13624
|
+
const currentStackItem = branchStack.length > 0 ? branchStack[branchStack.length - 1] : null;
|
|
13625
|
+
const renderPayload = {
|
|
13626
|
+
...targetObj,
|
|
13627
|
+
ancestry_id: targetObj.ancestry_id || targetObj.id,
|
|
13628
|
+
ancestral_node: targetTree.node ? targetTree.node.id : targetTree.node_id,
|
|
13629
|
+
tree: targetTree,
|
|
13630
|
+
_originNodeId: currentStackItem ? currentStackItem.nodeId : null,
|
|
13631
|
+
_branchDirection: currentStackItem ? currentStackItem.entryDirection : null,
|
|
13632
|
+
_forceUpdate: true
|
|
13633
|
+
};
|
|
13634
|
+
const rotation = branchStack.reduce((acc, step) => {
|
|
13635
|
+
return acc + (step.entryDirection === "left" ? -Math.PI / 2 : Math.PI / 2);
|
|
13636
|
+
}, 0);
|
|
13637
|
+
handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
|
|
13638
|
+
},
|
|
13639
|
+
[
|
|
13640
|
+
readingMode,
|
|
13641
|
+
handleRenderAncestry,
|
|
13642
|
+
buildFullAncestryTree,
|
|
13643
|
+
ancestryDataRef.current
|
|
13644
|
+
]
|
|
13645
|
+
);
|
|
13043
13646
|
const handleCloseReadMode = (0, import_react26.useCallback)(() => {
|
|
13044
13647
|
setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
|
|
13045
13648
|
}, []);
|
|
13046
|
-
const handleAncestrySectionChange = (0, import_react26.useCallback)(
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
|
|
13061
|
-
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13066
|
-
|
|
13067
|
-
|
|
13068
|
-
|
|
13069
|
-
|
|
13070
|
-
|
|
13071
|
-
|
|
13072
|
-
|
|
13073
|
-
|
|
13074
|
-
|
|
13075
|
-
|
|
13076
|
-
|
|
13077
|
-
|
|
13078
|
-
|
|
13079
|
-
|
|
13080
|
-
|
|
13081
|
-
|
|
13082
|
-
|
|
13083
|
-
|
|
13084
|
-
|
|
13085
|
-
|
|
13649
|
+
const handleAncestrySectionChange = (0, import_react26.useCallback)(
|
|
13650
|
+
(activeSectionId, ancestryOverride = null, rotation = 0) => {
|
|
13651
|
+
var _a2, _b2;
|
|
13652
|
+
const currentMode = stateRef.current.ancestry;
|
|
13653
|
+
let targetObj = ancestryOverride;
|
|
13654
|
+
if (!targetObj) {
|
|
13655
|
+
const currentAncestryId = currentMode.currentAncestryId;
|
|
13656
|
+
const ancestryObj = (ancestryDataRef.current || []).find(
|
|
13657
|
+
(a) => String(a.ancestry_id) === String(currentAncestryId)
|
|
13658
|
+
);
|
|
13659
|
+
targetObj = ancestryObj || (currentMode.isActive ? {
|
|
13660
|
+
...currentMode,
|
|
13661
|
+
ancestry_id: "temp_creating",
|
|
13662
|
+
ancestral_node: (_b2 = (_a2 = currentMode.tree) == null ? void 0 : _a2.node) == null ? void 0 : _b2.id
|
|
13663
|
+
} : null);
|
|
13664
|
+
}
|
|
13665
|
+
if (!targetObj) return;
|
|
13666
|
+
const targetId = targetObj.ancestry_id || targetObj.id;
|
|
13667
|
+
if (stateRef.current.lastRenderedAncestryId !== targetId) {
|
|
13668
|
+
stateRef.current.maxAncestryRenderIndex = 0;
|
|
13669
|
+
stateRef.current.lastRenderedAncestryId = targetId;
|
|
13670
|
+
}
|
|
13671
|
+
const descriptionText = (ancestryOverride ? targetObj.description : currentMode.ancestryDescription) || targetObj.description || "";
|
|
13672
|
+
const savedSections = (ancestryOverride ? targetObj.description_sections : currentMode.ancestryDescriptionSections) || targetObj.description_sections || [];
|
|
13673
|
+
const sections = parseDescriptionSections(descriptionText, savedSections);
|
|
13674
|
+
let activeIndex = sections.findIndex(
|
|
13675
|
+
(s) => String(s.id) === String(activeSectionId)
|
|
13676
|
+
);
|
|
13677
|
+
if (activeIndex === -1 && !isNaN(parseInt(activeSectionId))) {
|
|
13678
|
+
activeIndex = sections.findIndex(
|
|
13679
|
+
(s) => s.numericId === parseInt(activeSectionId)
|
|
13680
|
+
);
|
|
13681
|
+
}
|
|
13682
|
+
if (activeIndex === -1) activeIndex = 0;
|
|
13683
|
+
if (stateRef.current.maxAncestryRenderIndex === void 0)
|
|
13684
|
+
stateRef.current.maxAncestryRenderIndex = 0;
|
|
13685
|
+
stateRef.current.maxAncestryRenderIndex = activeIndex;
|
|
13686
|
+
const renderLimitIndex = stateRef.current.maxAncestryRenderIndex;
|
|
13687
|
+
const allowedIds = /* @__PURE__ */ new Set();
|
|
13688
|
+
allowedIds.add("preamble");
|
|
13689
|
+
allowedIds.add(0);
|
|
13690
|
+
allowedIds.add("0");
|
|
13691
|
+
for (let i = 0; i <= renderLimitIndex; i++) {
|
|
13692
|
+
if (sections[i]) {
|
|
13693
|
+
if (sections[i].id) allowedIds.add(String(sections[i].id));
|
|
13694
|
+
if (sections[i].numericId !== void 0 && sections[i].numericId !== null) {
|
|
13695
|
+
allowedIds.add(sections[i].numericId);
|
|
13696
|
+
allowedIds.add(String(sections[i].numericId));
|
|
13697
|
+
}
|
|
13086
13698
|
}
|
|
13087
13699
|
}
|
|
13088
|
-
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
|
|
13700
|
+
const activeSection = sections[activeIndex];
|
|
13701
|
+
let focusTargetId = activeSectionId;
|
|
13702
|
+
if (activeSection && activeSection.numericId !== void 0 && activeSection.numericId !== null) {
|
|
13703
|
+
focusTargetId = activeSection.numericId;
|
|
13704
|
+
}
|
|
13705
|
+
const treeToRender = ancestryOverride ? ancestryOverride.tree : currentMode.isActive && currentMode.tree ? currentMode.tree : targetObj.tree;
|
|
13706
|
+
const renderPayload = { ...targetObj, tree: treeToRender };
|
|
13707
|
+
handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
|
|
13708
|
+
},
|
|
13709
|
+
[handleRenderAncestry]
|
|
13710
|
+
);
|
|
13098
13711
|
const handleEditAncestry = (0, import_react26.useCallback)(
|
|
13099
13712
|
async (ancestryObject) => {
|
|
13100
|
-
setContextMenu(
|
|
13713
|
+
setContextMenu(
|
|
13714
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
13715
|
+
);
|
|
13101
13716
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
13102
|
-
alert(
|
|
13717
|
+
alert(
|
|
13718
|
+
"N\xE3o foi poss\xEDvel carregar os dados desta ancestralidade para edi\xE7\xE3o."
|
|
13719
|
+
);
|
|
13103
13720
|
return;
|
|
13104
13721
|
}
|
|
13105
13722
|
stateRef.current.maxAncestryRenderIndex = 0;
|
|
13106
13723
|
const initialSections = /* @__PURE__ */ new Set(["preamble", 0]);
|
|
13107
13724
|
await handleRenderAncestry(ancestryObject, initialSections);
|
|
13108
|
-
const allParentNodes = Object.values(parentDataRef.current).flatMap(
|
|
13725
|
+
const allParentNodes = Object.values(parentDataRef.current).flatMap(
|
|
13726
|
+
(fileData) => fileData.nodes
|
|
13727
|
+
);
|
|
13109
13728
|
const allAncestries = ancestryDataRef.current || [];
|
|
13110
|
-
const fullTree = buildFullAncestryTree(
|
|
13729
|
+
const fullTree = buildFullAncestryTree(
|
|
13730
|
+
ancestryObject.tree,
|
|
13731
|
+
allParentNodes,
|
|
13732
|
+
allAncestries
|
|
13733
|
+
);
|
|
13111
13734
|
if (!fullTree) {
|
|
13112
|
-
alert(
|
|
13735
|
+
alert(
|
|
13736
|
+
"Falha ao reconstruir a \xE1rvore de ancestralidade. Alguns Nodes podem estar faltando."
|
|
13737
|
+
);
|
|
13113
13738
|
return;
|
|
13114
13739
|
}
|
|
13115
|
-
const fullAbstractionTree = ancestryObject.abstraction_tree ? buildFullAncestryTree(
|
|
13740
|
+
const fullAbstractionTree = ancestryObject.abstraction_tree ? buildFullAncestryTree(
|
|
13741
|
+
ancestryObject.abstraction_tree,
|
|
13742
|
+
allParentNodes,
|
|
13743
|
+
allAncestries
|
|
13744
|
+
) : { node: fullTree.node, children: [] };
|
|
13116
13745
|
setAncestryMode({
|
|
13117
13746
|
isActive: true,
|
|
13118
13747
|
...ancestryObject,
|
|
@@ -13164,7 +13793,9 @@ function XViewScene({
|
|
|
13164
13793
|
const treeToUse = treeOverride || ancestryMode.tree;
|
|
13165
13794
|
const { isEditMode, currentAncestryId } = ancestryMode;
|
|
13166
13795
|
if (!treeToUse || !treeToUse.node) {
|
|
13167
|
-
alert(
|
|
13796
|
+
alert(
|
|
13797
|
+
"Erro: A estrutura da ancestralidade \xE9 inv\xE1lida (Node raiz ausente)."
|
|
13798
|
+
);
|
|
13168
13799
|
return;
|
|
13169
13800
|
}
|
|
13170
13801
|
if (!save_view_data || !stateRef.current.nodeIdToParentFileMap) return;
|
|
@@ -13197,14 +13828,18 @@ function XViewScene({
|
|
|
13197
13828
|
};
|
|
13198
13829
|
};
|
|
13199
13830
|
const treeWithIds = convertTreeToIds(treeToUse);
|
|
13200
|
-
const abstractionTreeWithIds = convertTreeToIds(
|
|
13831
|
+
const abstractionTreeWithIds = convertTreeToIds(
|
|
13832
|
+
ancestryMode.abstraction_tree
|
|
13833
|
+
);
|
|
13201
13834
|
if (!treeWithIds) {
|
|
13202
13835
|
alert("Erro ao processar a \xE1rvore da ancestralidade.");
|
|
13203
13836
|
return;
|
|
13204
13837
|
}
|
|
13205
13838
|
let originalAncestryObj = null;
|
|
13206
13839
|
if (isEditMode && currentAncestryId) {
|
|
13207
|
-
originalAncestryObj = (ancestryDataRef.current || []).find(
|
|
13840
|
+
originalAncestryObj = (ancestryDataRef.current || []).find(
|
|
13841
|
+
(anc) => String(anc.ancestry_id) === String(currentAncestryId)
|
|
13842
|
+
);
|
|
13208
13843
|
}
|
|
13209
13844
|
const ancestryObjectToSave = {
|
|
13210
13845
|
ancestry_id: isEditMode && currentAncestryId ? currentAncestryId : `${import_short_uuid2.default.generate()}`,
|
|
@@ -13287,14 +13922,20 @@ function XViewScene({
|
|
|
13287
13922
|
try {
|
|
13288
13923
|
if (isExternalSave) {
|
|
13289
13924
|
try {
|
|
13290
|
-
const remoteResponse = await get_ancestry_file(
|
|
13925
|
+
const remoteResponse = await get_ancestry_file(
|
|
13926
|
+
targetFileIdForCache,
|
|
13927
|
+
targetOwnerIdForCache
|
|
13928
|
+
);
|
|
13291
13929
|
if (remoteResponse.success && Array.isArray(remoteResponse.data)) {
|
|
13292
13930
|
masterAncestryList = remoteResponse.data;
|
|
13293
13931
|
} else {
|
|
13294
13932
|
masterAncestryList = [];
|
|
13295
13933
|
}
|
|
13296
13934
|
} catch (fetchErr) {
|
|
13297
|
-
console.warn(
|
|
13935
|
+
console.warn(
|
|
13936
|
+
"Arquivo de destino n\xE3o existe ou erro ao buscar, criando novo:",
|
|
13937
|
+
fetchErr
|
|
13938
|
+
);
|
|
13298
13939
|
masterAncestryList = [];
|
|
13299
13940
|
}
|
|
13300
13941
|
} else {
|
|
@@ -13314,7 +13955,9 @@ function XViewScene({
|
|
|
13314
13955
|
const result = await save_view_data(finalSaveUrl, masterAncestryList);
|
|
13315
13956
|
if (result.success) {
|
|
13316
13957
|
const localList = [...ancestryDataRef.current || []];
|
|
13317
|
-
const localIndex = localList.findIndex(
|
|
13958
|
+
const localIndex = localList.findIndex(
|
|
13959
|
+
(a) => String(a.ancestry_id) === String(ancestryObjectToSave.ancestry_id)
|
|
13960
|
+
);
|
|
13318
13961
|
if (localIndex !== -1) {
|
|
13319
13962
|
localList[localIndex] = ancestryObjectToSave;
|
|
13320
13963
|
} else {
|
|
@@ -13342,11 +13985,29 @@ function XViewScene({
|
|
|
13342
13985
|
return;
|
|
13343
13986
|
}
|
|
13344
13987
|
if (!keepOpen) {
|
|
13345
|
-
setAncestryMode({
|
|
13988
|
+
setAncestryMode({
|
|
13989
|
+
isActive: false,
|
|
13990
|
+
tree: null,
|
|
13991
|
+
selectedParentId: null,
|
|
13992
|
+
isEditMode: false,
|
|
13993
|
+
currentAncestryId: null,
|
|
13994
|
+
ancestryName: "",
|
|
13995
|
+
ancestryDescription: "",
|
|
13996
|
+
ancestryDescriptionSections: [],
|
|
13997
|
+
isAddingNodes: false
|
|
13998
|
+
});
|
|
13346
13999
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
13347
14000
|
}
|
|
13348
14001
|
},
|
|
13349
|
-
[
|
|
14002
|
+
[
|
|
14003
|
+
ancestryMode,
|
|
14004
|
+
ancestry_save_url,
|
|
14005
|
+
handleRenderAncestry,
|
|
14006
|
+
save_view_data,
|
|
14007
|
+
sceneConfigId,
|
|
14008
|
+
ownerId,
|
|
14009
|
+
get_ancestry_file
|
|
14010
|
+
]
|
|
13350
14011
|
);
|
|
13351
14012
|
const handleOpenAncestryRelEditor = (path, currentData) => {
|
|
13352
14013
|
setEditingAncestryRel({ visible: true, data: currentData, path });
|
|
@@ -13376,7 +14037,9 @@ function XViewScene({
|
|
|
13376
14037
|
if (ancestryToDelete && delete_file_action) {
|
|
13377
14038
|
const urls = extractFileUrlsFromProperties(ancestryToDelete);
|
|
13378
14039
|
if (urls.length > 0) {
|
|
13379
|
-
Promise.all(urls.map((url) => delete_file_action(url))).catch(
|
|
14040
|
+
Promise.all(urls.map((url) => delete_file_action(url))).catch(
|
|
14041
|
+
(err) => console.error("Erro ao deletar arquivos da ancestralidade:", err)
|
|
14042
|
+
);
|
|
13380
14043
|
}
|
|
13381
14044
|
}
|
|
13382
14045
|
if (!ancestryToDelete) {
|
|
@@ -13386,7 +14049,9 @@ function XViewScene({
|
|
|
13386
14049
|
const sourceFileId = ancestryToDelete._source_file_id;
|
|
13387
14050
|
const sourceOwnerId = ancestryToDelete._source_owner_id;
|
|
13388
14051
|
if (!sourceFileId || !sourceOwnerId) {
|
|
13389
|
-
alert(
|
|
14052
|
+
alert(
|
|
14053
|
+
"N\xE3o foi poss\xEDvel identificar o arquivo de origem desta ancestralidade."
|
|
14054
|
+
);
|
|
13390
14055
|
return;
|
|
13391
14056
|
}
|
|
13392
14057
|
const finalSaveUrl = `x_view_ancestry/${sourceOwnerId}/${sourceFileId}`;
|
|
@@ -13394,13 +14059,18 @@ function XViewScene({
|
|
|
13394
14059
|
(anc) => anc._source_file_id === sourceFileId && String(anc.ancestry_id) !== String(ancestryIdToDelete)
|
|
13395
14060
|
);
|
|
13396
14061
|
try {
|
|
13397
|
-
const result = await save_view_data(
|
|
14062
|
+
const result = await save_view_data(
|
|
14063
|
+
finalSaveUrl,
|
|
14064
|
+
updatedAncestriesForFile
|
|
14065
|
+
);
|
|
13398
14066
|
if (result.success) {
|
|
13399
14067
|
ancestryDataRef.current = (ancestryDataRef.current || []).filter(
|
|
13400
14068
|
(ancestry) => String(ancestry.ancestry_id) !== String(ancestryIdToDelete)
|
|
13401
14069
|
);
|
|
13402
14070
|
const { renderedAncestries, ancestryGroup } = stateRef.current;
|
|
13403
|
-
const renderIndex = renderedAncestries.findIndex(
|
|
14071
|
+
const renderIndex = renderedAncestries.findIndex(
|
|
14072
|
+
(a) => String(a.id) === String(ancestryIdToDelete)
|
|
14073
|
+
);
|
|
13404
14074
|
if (renderIndex !== -1) {
|
|
13405
14075
|
const toRemove = renderedAncestries[renderIndex];
|
|
13406
14076
|
toRemove.lines.forEach((line) => {
|
|
@@ -13409,18 +14079,29 @@ function XViewScene({
|
|
|
13409
14079
|
if (line.material) line.material.dispose();
|
|
13410
14080
|
});
|
|
13411
14081
|
renderedAncestries.splice(renderIndex, 1);
|
|
13412
|
-
stateRef.current.ancestryLinks = renderedAncestries.flatMap(
|
|
14082
|
+
stateRef.current.ancestryLinks = renderedAncestries.flatMap(
|
|
14083
|
+
(a) => a.lines
|
|
14084
|
+
);
|
|
13413
14085
|
}
|
|
13414
14086
|
setSceneVersion((v) => v + 1);
|
|
13415
14087
|
} else {
|
|
13416
|
-
throw new Error(
|
|
14088
|
+
throw new Error(
|
|
14089
|
+
result.error || "Ocorreu um erro desconhecido ao excluir."
|
|
14090
|
+
);
|
|
13417
14091
|
}
|
|
13418
14092
|
} catch (error) {
|
|
13419
14093
|
console.error("Falha ao excluir a ancestralidade:", error);
|
|
13420
14094
|
alert(`Erro ao excluir a ancestralidade: ${error.message}`);
|
|
13421
14095
|
return;
|
|
13422
14096
|
}
|
|
13423
|
-
setAncestryMode({
|
|
14097
|
+
setAncestryMode({
|
|
14098
|
+
isActive: false,
|
|
14099
|
+
tree: null,
|
|
14100
|
+
selectedParentId: null,
|
|
14101
|
+
isEditMode: false,
|
|
14102
|
+
currentAncestryId: null,
|
|
14103
|
+
ancestryName: ""
|
|
14104
|
+
});
|
|
13424
14105
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
13425
14106
|
},
|
|
13426
14107
|
[save_view_data, delete_file_action]
|
|
@@ -13428,24 +14109,38 @@ function XViewScene({
|
|
|
13428
14109
|
const handleOpenAncestryBoard = (0, import_react26.useCallback)(() => {
|
|
13429
14110
|
setIsAncestryBoardOpen(true);
|
|
13430
14111
|
}, []);
|
|
13431
|
-
const handleSelectAncestryFromBoard = (0, import_react26.useCallback)(
|
|
13432
|
-
|
|
13433
|
-
|
|
13434
|
-
|
|
13435
|
-
|
|
13436
|
-
|
|
13437
|
-
|
|
13438
|
-
|
|
13439
|
-
|
|
13440
|
-
|
|
14112
|
+
const handleSelectAncestryFromBoard = (0, import_react26.useCallback)(
|
|
14113
|
+
(ancestry) => {
|
|
14114
|
+
setIsAncestryBoardOpen(false);
|
|
14115
|
+
setIsSidebarOpen(false);
|
|
14116
|
+
handleStartReadingAncestry(ancestry);
|
|
14117
|
+
},
|
|
14118
|
+
[handleStartReadingAncestry]
|
|
14119
|
+
);
|
|
14120
|
+
const handleSaveAncestryBoard = (0, import_react26.useCallback)(
|
|
14121
|
+
async (groups) => {
|
|
14122
|
+
if (!sceneConfigId || !viewParams || !session) return;
|
|
14123
|
+
const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
|
|
14124
|
+
await save_ancestry_board_action(
|
|
14125
|
+
sceneConfigId,
|
|
14126
|
+
sceneType,
|
|
14127
|
+
groups,
|
|
14128
|
+
session,
|
|
14129
|
+
ownerId
|
|
14130
|
+
);
|
|
14131
|
+
},
|
|
14132
|
+
[sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
|
|
14133
|
+
);
|
|
13441
14134
|
const existingNodeTypes = (0, import_react26.useMemo)(() => {
|
|
13442
14135
|
if (!parentDataRef.current) {
|
|
13443
14136
|
return [];
|
|
13444
14137
|
}
|
|
13445
|
-
const allTypes = Object.values(parentDataRef.current).flatMap(
|
|
13446
|
-
|
|
13447
|
-
|
|
13448
|
-
|
|
14138
|
+
const allTypes = Object.values(parentDataRef.current).flatMap(
|
|
14139
|
+
(fileData) => fileData.nodes.flatMap((node) => {
|
|
14140
|
+
if (Array.isArray(node.type)) return node.type;
|
|
14141
|
+
return [node.type];
|
|
14142
|
+
})
|
|
14143
|
+
).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
|
|
13449
14144
|
return [...new Set(allTypes)];
|
|
13450
14145
|
}, [parentDataRef.current, sceneVersion]);
|
|
13451
14146
|
const searchableDbNodes = (0, import_react26.useMemo)(() => {
|
|
@@ -13459,7 +14154,10 @@ function XViewScene({
|
|
|
13459
14154
|
}, [parentDataRef.current, sceneVersion]);
|
|
13460
14155
|
const handleAddExistingNode = (0, import_react26.useCallback)(
|
|
13461
14156
|
(nodeId) => {
|
|
13462
|
-
return userActionHandlers.handleAddExistingNodeById(
|
|
14157
|
+
return userActionHandlers.handleAddExistingNodeById(
|
|
14158
|
+
actionHandlerContext,
|
|
14159
|
+
nodeId
|
|
14160
|
+
);
|
|
13463
14161
|
},
|
|
13464
14162
|
[actionHandlerContext]
|
|
13465
14163
|
);
|
|
@@ -13467,7 +14165,9 @@ function XViewScene({
|
|
|
13467
14165
|
var _a2, _b2, _c2;
|
|
13468
14166
|
const { nodeObjects, allLinks } = stateRef.current;
|
|
13469
14167
|
if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
|
|
13470
|
-
console.warn(
|
|
14168
|
+
console.warn(
|
|
14169
|
+
"N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente."
|
|
14170
|
+
);
|
|
13471
14171
|
return;
|
|
13472
14172
|
}
|
|
13473
14173
|
if (!save_view_data) return;
|
|
@@ -13504,48 +14204,68 @@ function XViewScene({
|
|
|
13504
14204
|
}, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
|
|
13505
14205
|
const allAvailableNodes = (0, import_react26.useMemo)(() => {
|
|
13506
14206
|
if (!parentDataRef.current) return [];
|
|
13507
|
-
return Object.values(parentDataRef.current).flatMap(
|
|
14207
|
+
return Object.values(parentDataRef.current).flatMap(
|
|
14208
|
+
(fileData) => fileData.nodes || []
|
|
14209
|
+
);
|
|
13508
14210
|
}, [sceneVersion, isInitialized]);
|
|
13509
14211
|
const allAvailableAncestries = (0, import_react26.useMemo)(() => {
|
|
13510
14212
|
return ancestryDataRef.current || [];
|
|
13511
14213
|
}, [sceneVersion, isInitialized]);
|
|
13512
|
-
const handleOpenReference = (0, import_react26.useCallback)(
|
|
13513
|
-
|
|
13514
|
-
|
|
13515
|
-
|
|
13516
|
-
|
|
13517
|
-
|
|
13518
|
-
|
|
13519
|
-
|
|
13520
|
-
|
|
13521
|
-
|
|
13522
|
-
|
|
14214
|
+
const handleOpenReference = (0, import_react26.useCallback)(
|
|
14215
|
+
(referenceData) => {
|
|
14216
|
+
const { type, id } = referenceData;
|
|
14217
|
+
if (type === "node") {
|
|
14218
|
+
const targetNode = allAvailableNodes.find(
|
|
14219
|
+
(n) => String(n.id) === String(id)
|
|
14220
|
+
);
|
|
14221
|
+
if (targetNode) {
|
|
14222
|
+
setAncestryLinkDetails(null);
|
|
14223
|
+
setDetailsLink(null);
|
|
14224
|
+
setDetailsNode(targetNode);
|
|
14225
|
+
const sceneMesh = stateRef.current.nodeObjects[String(id)];
|
|
14226
|
+
if (sceneMesh) {
|
|
14227
|
+
tweenToTarget(sceneMesh);
|
|
14228
|
+
}
|
|
14229
|
+
} else {
|
|
14230
|
+
alert("Node original n\xE3o encontrado neste contexto.");
|
|
14231
|
+
}
|
|
14232
|
+
} else if (type === "ancestry") {
|
|
14233
|
+
const targetAncestry = allAvailableAncestries.find(
|
|
14234
|
+
(a) => String(a.ancestry_id) === String(id)
|
|
14235
|
+
);
|
|
14236
|
+
if (targetAncestry) {
|
|
14237
|
+
setDetailsNode(null);
|
|
14238
|
+
setDetailsLink(null);
|
|
14239
|
+
setAncestryLinkDetails(null);
|
|
14240
|
+
handleEditAncestry(targetAncestry);
|
|
14241
|
+
} else {
|
|
14242
|
+
alert("Ancestralidade original n\xE3o encontrada neste contexto.");
|
|
13523
14243
|
}
|
|
13524
|
-
} else {
|
|
13525
|
-
alert("Node original n\xE3o encontrado neste contexto.");
|
|
13526
|
-
}
|
|
13527
|
-
} else if (type === "ancestry") {
|
|
13528
|
-
const targetAncestry = allAvailableAncestries.find((a) => String(a.ancestry_id) === String(id));
|
|
13529
|
-
if (targetAncestry) {
|
|
13530
|
-
setDetailsNode(null);
|
|
13531
|
-
setDetailsLink(null);
|
|
13532
|
-
setAncestryLinkDetails(null);
|
|
13533
|
-
handleEditAncestry(targetAncestry);
|
|
13534
|
-
} else {
|
|
13535
|
-
alert("Ancestralidade original n\xE3o encontrada neste contexto.");
|
|
13536
14244
|
}
|
|
13537
|
-
}
|
|
13538
|
-
|
|
14245
|
+
},
|
|
14246
|
+
[
|
|
14247
|
+
allAvailableNodes,
|
|
14248
|
+
allAvailableAncestries,
|
|
14249
|
+
handleEditAncestry,
|
|
14250
|
+
tweenToTarget
|
|
14251
|
+
]
|
|
14252
|
+
);
|
|
13539
14253
|
const handleToggleAncestryAddMode = (0, import_react26.useCallback)(() => {
|
|
13540
|
-
setAncestryMode((prev) => ({
|
|
14254
|
+
setAncestryMode((prev) => ({
|
|
14255
|
+
...prev,
|
|
14256
|
+
isAddingNodes: !prev.isAddingNodes
|
|
14257
|
+
}));
|
|
13541
14258
|
}, []);
|
|
13542
|
-
const handleFocusNode = (0, import_react26.useCallback)(
|
|
13543
|
-
|
|
13544
|
-
|
|
13545
|
-
|
|
13546
|
-
|
|
13547
|
-
|
|
13548
|
-
|
|
14259
|
+
const handleFocusNode = (0, import_react26.useCallback)(
|
|
14260
|
+
(nodeData) => {
|
|
14261
|
+
if (!nodeData) return;
|
|
14262
|
+
const nodeMesh = stateRef.current.nodeObjects[String(nodeData.id)];
|
|
14263
|
+
if (nodeMesh) {
|
|
14264
|
+
tweenToTarget(nodeMesh, 1.2);
|
|
14265
|
+
}
|
|
14266
|
+
},
|
|
14267
|
+
[tweenToTarget]
|
|
14268
|
+
);
|
|
13549
14269
|
const availableDatasets = (0, import_react26.useMemo)(() => {
|
|
13550
14270
|
if (!sceneDataRef.current || !parentDataRef.current) return [];
|
|
13551
14271
|
return sceneDataRef.current.parent_dbs.map((db) => {
|
|
@@ -13556,7 +14276,9 @@ function XViewScene({
|
|
|
13556
14276
|
};
|
|
13557
14277
|
});
|
|
13558
14278
|
}, [sceneVersion, isInitialized]);
|
|
13559
|
-
const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(
|
|
14279
|
+
const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(
|
|
14280
|
+
String(creationMode.sourceNodeData.id)
|
|
14281
|
+
)) == null ? void 0 : _b.parentFileId : null;
|
|
13560
14282
|
const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
|
|
13561
14283
|
(0, import_react26.useEffect)(() => {
|
|
13562
14284
|
if (isInitialized && focusNodeId && !hasFocusedInitial) {
|
|
@@ -13571,11 +14293,19 @@ function XViewScene({
|
|
|
13571
14293
|
setHasFocusedInitial(true);
|
|
13572
14294
|
}
|
|
13573
14295
|
}
|
|
13574
|
-
}, [
|
|
14296
|
+
}, [
|
|
14297
|
+
isInitialized,
|
|
14298
|
+
sceneVersion,
|
|
14299
|
+
focusNodeId,
|
|
14300
|
+
hasFocusedInitial,
|
|
14301
|
+
tweenToTarget
|
|
14302
|
+
]);
|
|
13575
14303
|
(0, import_react26.useEffect)(() => {
|
|
13576
14304
|
if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
|
|
13577
14305
|
const ancestries = ancestryDataRef.current || [];
|
|
13578
|
-
const targetAncestry = ancestries.find(
|
|
14306
|
+
const targetAncestry = ancestries.find(
|
|
14307
|
+
(a) => String(a.ancestry_id) === String(focusAncestryId)
|
|
14308
|
+
);
|
|
13579
14309
|
if (targetAncestry) {
|
|
13580
14310
|
setTimeout(() => {
|
|
13581
14311
|
handleStartReadingAncestry(targetAncestry);
|
|
@@ -13585,18 +14315,38 @@ function XViewScene({
|
|
|
13585
14315
|
setHasOpenedInitialAncestry(true);
|
|
13586
14316
|
}
|
|
13587
14317
|
}
|
|
13588
|
-
}, [
|
|
14318
|
+
}, [
|
|
14319
|
+
isInitialized,
|
|
14320
|
+
sceneVersion,
|
|
14321
|
+
focusAncestryId,
|
|
14322
|
+
hasOpenedInitialAncestry,
|
|
14323
|
+
handleStartReadingAncestry
|
|
14324
|
+
]);
|
|
13589
14325
|
(0, import_react26.useEffect)(() => {
|
|
13590
14326
|
function handleKeyDown(event) {
|
|
13591
14327
|
var _a2, _b2, _c2;
|
|
13592
14328
|
const context = actionHandlerContext;
|
|
13593
14329
|
if (event.key === "Escape") {
|
|
13594
|
-
if (stateRef.current.connection.isActive)
|
|
13595
|
-
|
|
13596
|
-
if (stateRef.current.
|
|
13597
|
-
|
|
14330
|
+
if (stateRef.current.connection.isActive)
|
|
14331
|
+
userActionHandlers.handleCancelConnection(context);
|
|
14332
|
+
if (stateRef.current.relink.isActive)
|
|
14333
|
+
userActionHandlers.handleCancelRelink(context);
|
|
14334
|
+
if (stateRef.current.creation.isActive)
|
|
14335
|
+
userActionHandlers.handleCancelCreation(context);
|
|
14336
|
+
if ((_a2 = stateRef.current.versionMode) == null ? void 0 : _a2.isActive)
|
|
14337
|
+
userActionHandlers.handleCancelVersioning(context);
|
|
13598
14338
|
if (stateRef.current.ancestry.isActive) {
|
|
13599
|
-
setAncestryMode({
|
|
14339
|
+
setAncestryMode({
|
|
14340
|
+
isActive: false,
|
|
14341
|
+
tree: null,
|
|
14342
|
+
selectedParentId: null,
|
|
14343
|
+
isEditMode: false,
|
|
14344
|
+
currentAncestryId: null,
|
|
14345
|
+
ancestryName: "",
|
|
14346
|
+
ancestryDescription: "",
|
|
14347
|
+
ancestryDescriptionSections: [],
|
|
14348
|
+
isAddingNodes: false
|
|
14349
|
+
});
|
|
13600
14350
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
13601
14351
|
}
|
|
13602
14352
|
if (questMode.isActive) {
|
|
@@ -13605,7 +14355,9 @@ function XViewScene({
|
|
|
13605
14355
|
if (stateRef.current.selectedNodes.size > 0) {
|
|
13606
14356
|
stateRef.current.selectedNodes.clear();
|
|
13607
14357
|
}
|
|
13608
|
-
setContextMenu(
|
|
14358
|
+
setContextMenu(
|
|
14359
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
14360
|
+
);
|
|
13609
14361
|
setMultiContextMenu((prev) => ({ ...prev, visible: false }));
|
|
13610
14362
|
setRelationshipMenu((prev) => ({ ...prev, visible: false }));
|
|
13611
14363
|
}
|
|
@@ -13624,7 +14376,9 @@ function XViewScene({
|
|
|
13624
14376
|
let attempts = 0;
|
|
13625
14377
|
const MIN_CLEARANCE = 15;
|
|
13626
14378
|
while (isOccupied && attempts < 30) {
|
|
13627
|
-
isOccupied = existingNodes.some(
|
|
14379
|
+
isOccupied = existingNodes.some(
|
|
14380
|
+
(mesh) => mesh.position.distanceTo(ghostPosition) < MIN_CLEARANCE
|
|
14381
|
+
);
|
|
13628
14382
|
if (isOccupied) {
|
|
13629
14383
|
ghostPosition.x = controls.target.x + Math.cos(angle) * radius;
|
|
13630
14384
|
ghostPosition.y = controls.target.y + (Math.random() - 0.5) * 8;
|
|
@@ -13643,7 +14397,11 @@ function XViewScene({
|
|
|
13643
14397
|
intensity: 0,
|
|
13644
14398
|
type: ["quest"]
|
|
13645
14399
|
};
|
|
13646
|
-
const ghostNode = createNodeMesh(
|
|
14400
|
+
const ghostNode = createNodeMesh(
|
|
14401
|
+
ghostData,
|
|
14402
|
+
ghostPosition,
|
|
14403
|
+
glowTexture
|
|
14404
|
+
);
|
|
13647
14405
|
ghostNode.traverse((child) => {
|
|
13648
14406
|
if (child.isMesh) {
|
|
13649
14407
|
child.material.transparent = true;
|
|
@@ -13690,13 +14448,49 @@ function XViewScene({
|
|
|
13690
14448
|
return /* @__PURE__ */ import_react26.default.createElement(LoadingScreen, null);
|
|
13691
14449
|
}
|
|
13692
14450
|
if (permissionStatus === "denied") {
|
|
13693
|
-
return /* @__PURE__ */ import_react26.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react26.default.createElement(
|
|
14451
|
+
return /* @__PURE__ */ import_react26.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react26.default.createElement(
|
|
14452
|
+
"svg",
|
|
14453
|
+
{
|
|
14454
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
14455
|
+
fill: "none",
|
|
14456
|
+
viewBox: "0 0 24 24",
|
|
14457
|
+
strokeWidth: 1.5,
|
|
14458
|
+
stroke: "currentColor",
|
|
14459
|
+
className: "w-16 h-16 mx-auto"
|
|
14460
|
+
},
|
|
14461
|
+
/* @__PURE__ */ import_react26.default.createElement(
|
|
14462
|
+
"path",
|
|
14463
|
+
{
|
|
14464
|
+
strokeLinecap: "round",
|
|
14465
|
+
strokeLinejoin: "round",
|
|
14466
|
+
d: "M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
|
|
14467
|
+
}
|
|
14468
|
+
)
|
|
14469
|
+
)), /* @__PURE__ */ import_react26.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ import_react26.default.createElement("p", { className: "text-slate-400 mb-6" }, "Voc\xEA n\xE3o tem permiss\xE3o para acessar este conte\xFAdo. Solicite acesso ao propriet\xE1rio ou verifique se est\xE1 na conta correta."), /* @__PURE__ */ import_react26.default.createElement(
|
|
13694
14470
|
"button",
|
|
13695
14471
|
{
|
|
13696
14472
|
onClick: () => router.push("/dashboard/scenes"),
|
|
13697
14473
|
className: "flex items-center justify-center gap-2 w-full py-3 px-4 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors font-medium"
|
|
13698
14474
|
},
|
|
13699
|
-
/* @__PURE__ */ import_react26.default.createElement(
|
|
14475
|
+
/* @__PURE__ */ import_react26.default.createElement(
|
|
14476
|
+
"svg",
|
|
14477
|
+
{
|
|
14478
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
14479
|
+
fill: "none",
|
|
14480
|
+
viewBox: "0 0 24 24",
|
|
14481
|
+
strokeWidth: 2,
|
|
14482
|
+
stroke: "currentColor",
|
|
14483
|
+
className: "w-5 h-5"
|
|
14484
|
+
},
|
|
14485
|
+
/* @__PURE__ */ import_react26.default.createElement(
|
|
14486
|
+
"path",
|
|
14487
|
+
{
|
|
14488
|
+
strokeLinecap: "round",
|
|
14489
|
+
strokeLinejoin: "round",
|
|
14490
|
+
d: "M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"
|
|
14491
|
+
}
|
|
14492
|
+
)
|
|
14493
|
+
),
|
|
13700
14494
|
"Voltar para Scenes"
|
|
13701
14495
|
)));
|
|
13702
14496
|
}
|
|
@@ -13743,7 +14537,14 @@ function XViewScene({
|
|
|
13743
14537
|
onImageChange: handleGhostNodeImageChange,
|
|
13744
14538
|
onOpenImageViewer: handleOpenImageViewer,
|
|
13745
14539
|
onMentionClick: handleAddExistingNode,
|
|
13746
|
-
style: {
|
|
14540
|
+
style: {
|
|
14541
|
+
position: "absolute",
|
|
14542
|
+
left: `${formPosition.left}px`,
|
|
14543
|
+
top: `${formPosition.top}px`,
|
|
14544
|
+
opacity: formPosition.opacity,
|
|
14545
|
+
zIndex: 20,
|
|
14546
|
+
transition: "opacity 200ms ease-out"
|
|
14547
|
+
},
|
|
13747
14548
|
refEl: formRef,
|
|
13748
14549
|
existingTypes: existingNodeTypes,
|
|
13749
14550
|
initialColor: (_c = creationMode.sourceNodeData) == null ? void 0 : _c.color,
|
|
@@ -13767,7 +14568,14 @@ function XViewScene({
|
|
|
13767
14568
|
onImageChange: handleGhostNodeImageChange,
|
|
13768
14569
|
onOpenImageViewer: handleOpenImageViewer,
|
|
13769
14570
|
onMentionClick: handleAddExistingNode,
|
|
13770
|
-
style: {
|
|
14571
|
+
style: {
|
|
14572
|
+
position: "absolute",
|
|
14573
|
+
left: `${formPosition.left}px`,
|
|
14574
|
+
top: `${formPosition.top}px`,
|
|
14575
|
+
opacity: formPosition.opacity,
|
|
14576
|
+
zIndex: 20,
|
|
14577
|
+
transition: "opacity 200ms ease-out"
|
|
14578
|
+
},
|
|
13771
14579
|
refEl: formRef,
|
|
13772
14580
|
fixedType: (_e = versionMode.sourceNodeData) == null ? void 0 : _e.type,
|
|
13773
14581
|
fixedColor: (_f = versionMode.sourceNodeData) == null ? void 0 : _f.color,
|
|
@@ -13784,7 +14592,13 @@ function XViewScene({
|
|
|
13784
14592
|
onNameChange: handleGhostNodeNameChange,
|
|
13785
14593
|
onColorChange: handleGhostNodeColorChange,
|
|
13786
14594
|
onSizeChange: handleGhostNodeSizeChange,
|
|
13787
|
-
style: {
|
|
14595
|
+
style: {
|
|
14596
|
+
position: "absolute",
|
|
14597
|
+
left: `16px`,
|
|
14598
|
+
top: `16px`,
|
|
14599
|
+
zIndex: 20,
|
|
14600
|
+
transition: "opacity 200ms ease-out"
|
|
14601
|
+
},
|
|
13788
14602
|
refEl: formRef,
|
|
13789
14603
|
onOpenImageViewer: handleOpenImageViewer,
|
|
13790
14604
|
onMentionClick: handleAddExistingNode,
|
|
@@ -13799,7 +14613,14 @@ function XViewScene({
|
|
|
13799
14613
|
"div",
|
|
13800
14614
|
{
|
|
13801
14615
|
className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col ${isReadModeResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
|
|
13802
|
-
style: {
|
|
14616
|
+
style: {
|
|
14617
|
+
top: 16,
|
|
14618
|
+
right: 16,
|
|
14619
|
+
zIndex: 1100,
|
|
14620
|
+
maxHeight: "calc(100vh - 32px)",
|
|
14621
|
+
width: `${readModeWidth}px`,
|
|
14622
|
+
maxWidth: "92vw"
|
|
14623
|
+
}
|
|
13803
14624
|
},
|
|
13804
14625
|
/* @__PURE__ */ import_react26.default.createElement(
|
|
13805
14626
|
"div",
|
|
@@ -13857,7 +14678,16 @@ function XViewScene({
|
|
|
13857
14678
|
onSave: handleSaveAncestry,
|
|
13858
14679
|
onEditRelationship: handleOpenAncestryRelEditor,
|
|
13859
14680
|
onClose: () => {
|
|
13860
|
-
setAncestryMode({
|
|
14681
|
+
setAncestryMode({
|
|
14682
|
+
isActive: false,
|
|
14683
|
+
tree: null,
|
|
14684
|
+
selectedParentId: null,
|
|
14685
|
+
isEditMode: false,
|
|
14686
|
+
currentAncestryId: null,
|
|
14687
|
+
ancestryName: "",
|
|
14688
|
+
ancestryDescription: "",
|
|
14689
|
+
isAddingNodes: false
|
|
14690
|
+
});
|
|
13861
14691
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
13862
14692
|
},
|
|
13863
14693
|
availableNodes: allAvailableNodes,
|
|
@@ -13922,7 +14752,12 @@ function XViewScene({
|
|
|
13922
14752
|
onOpenImageViewer: handleOpenImageViewer,
|
|
13923
14753
|
existingTypes: existingNodeTypes,
|
|
13924
14754
|
onImageChange: (useImage, url, currentColorOverride) => {
|
|
13925
|
-
const updatedNode = {
|
|
14755
|
+
const updatedNode = {
|
|
14756
|
+
...detailsNode,
|
|
14757
|
+
useImageAsTexture: useImage,
|
|
14758
|
+
textureImageUrl: url,
|
|
14759
|
+
color: currentColorOverride || detailsNode.color
|
|
14760
|
+
};
|
|
13926
14761
|
updateExistingNodeVisuals(stateRef.current, updatedNode);
|
|
13927
14762
|
setDetailsNode(updatedNode);
|
|
13928
14763
|
},
|
|
@@ -13996,7 +14831,9 @@ function XViewScene({
|
|
|
13996
14831
|
parentData: parentDataRef.current,
|
|
13997
14832
|
sceneData: sceneDataRef.current,
|
|
13998
14833
|
ancestryData: ancestryDataRef.current,
|
|
13999
|
-
onClose: () => setContextMenu(
|
|
14834
|
+
onClose: () => setContextMenu(
|
|
14835
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
14836
|
+
),
|
|
14000
14837
|
onStartCreation: (data) => userActionHandlers.handleStartCreation(actionHandlerContext, data),
|
|
14001
14838
|
onStartConnection: (data) => userActionHandlers.handleStartConnection(actionHandlerContext, data),
|
|
14002
14839
|
onStartVersioning: handleStartVersioning,
|
|
@@ -14004,7 +14841,11 @@ function XViewScene({
|
|
|
14004
14841
|
onDeleteNode: (data) => userActionHandlers.handleDeleteNode(actionHandlerContext, data),
|
|
14005
14842
|
onDismissNode: (data) => userActionHandlers.handleDismissNode(actionHandlerContext, data),
|
|
14006
14843
|
onDismissOtherNodes: (data) => userActionHandlers.handleDismissOtherNodes(actionHandlerContext, data),
|
|
14007
|
-
onExpandConnections: (sourceNode, links) => userActionHandlers.handleExpandConnections(
|
|
14844
|
+
onExpandConnections: (sourceNode, links) => userActionHandlers.handleExpandConnections(
|
|
14845
|
+
actionHandlerContext,
|
|
14846
|
+
sourceNode,
|
|
14847
|
+
links
|
|
14848
|
+
),
|
|
14008
14849
|
onRenderAncestry: handleStartReadingAncestry,
|
|
14009
14850
|
onEditAncestry: handleEditAncestry,
|
|
14010
14851
|
onDeleteAncestry: (ancestryId) => handleDeleteAncestry(ancestryId),
|
|
@@ -14017,9 +14858,18 @@ function XViewScene({
|
|
|
14017
14858
|
data: multiContextMenu,
|
|
14018
14859
|
userRole: userPermissionRole,
|
|
14019
14860
|
onClose: () => setMultiContextMenu((prev) => ({ ...prev, visible: false })),
|
|
14020
|
-
onDismissNodes: (ids) => userActionHandlers.handleDismissMultipleNodes(
|
|
14021
|
-
|
|
14022
|
-
|
|
14861
|
+
onDismissNodes: (ids) => userActionHandlers.handleDismissMultipleNodes(
|
|
14862
|
+
actionHandlerContext,
|
|
14863
|
+
ids
|
|
14864
|
+
),
|
|
14865
|
+
onDismissOtherNodes: (ids) => userActionHandlers.handleDismissOtherMultipleNodes(
|
|
14866
|
+
actionHandlerContext,
|
|
14867
|
+
ids
|
|
14868
|
+
),
|
|
14869
|
+
onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(
|
|
14870
|
+
actionHandlerContext,
|
|
14871
|
+
ids
|
|
14872
|
+
)
|
|
14023
14873
|
}
|
|
14024
14874
|
),
|
|
14025
14875
|
/* @__PURE__ */ import_react26.default.createElement(
|
|
@@ -14040,7 +14890,13 @@ function XViewScene({
|
|
|
14040
14890
|
onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
|
|
14041
14891
|
}
|
|
14042
14892
|
),
|
|
14043
|
-
/* @__PURE__ */ import_react26.default.createElement(
|
|
14893
|
+
/* @__PURE__ */ import_react26.default.createElement(
|
|
14894
|
+
ImageViewer,
|
|
14895
|
+
{
|
|
14896
|
+
data: imageViewer,
|
|
14897
|
+
onClose: () => setImageViewer({ ...imageViewer, visible: false })
|
|
14898
|
+
}
|
|
14899
|
+
),
|
|
14044
14900
|
/* @__PURE__ */ import_react26.default.createElement(
|
|
14045
14901
|
AncestryBoard,
|
|
14046
14902
|
{
|