@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.
Files changed (3) hide show
  1. package/dist/index.js +1665 -809
  2. package/dist/index.mjs +1672 -810
  3. 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("div", { className: `
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
- ` }, /* @__PURE__ */ import_react25.default.createElement(
9912
- "textarea",
9913
- {
9914
- ref: textareaRef,
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
- key: anc.ancestry_id,
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
- title: isValid ? "" : "Esta ancestralidade foi removida ou n\xE3o existe mais."
9939
- },
9940
- isValid ? (
9941
- // [MANTIDO] Botão Play visível para todos
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: () => onPlayAncestry(anc.ancestry_id),
9946
- className: "text-indigo-400 hover:text-white hover:bg-indigo-500 p-1 rounded-full transition-colors",
9947
- title: "Renderizar no cen\xE1rio"
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.FiPlay, { size: 10, className: "ml-0.5 fill-current" })
9950
- )
9951
- ) : /* @__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 })),
9952
- /* @__PURE__ */ import_react25.default.createElement("span", { className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}` }, anc.name),
9953
- canEdit && /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement("div", { className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}` }), /* @__PURE__ */ import_react25.default.createElement(
9954
- "button",
9955
- {
9956
- onClick: () => onRemoveAncestry(group.id, anc.ancestry_id),
9957
- className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
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
- title: "Adicionar Ancestralidade a este grupo"
9972
- },
9973
- isPickingForThisGroup ? /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiCheckCircle, { size: 12 }) : /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiSearch, { size: 12 }),
9974
- isPickingForThisGroup ? "Selecionando..." : "Adicionar"
9975
- ), /* @__PURE__ */ import_react25.default.createElement(
9976
- "button",
9977
- {
9978
- onClick: () => onAddSubgroup(group.id),
9979
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
9980
- title: "Criar Subgrupo"
9981
- },
9982
- /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiPlus, { size: 14 })
9983
- )), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react25.default.createElement(
9984
- "button",
9985
- {
9986
- onClick: () => onIndent(group.id),
9987
- disabled: !canIndent,
9988
- className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
9989
- title: "Aninhar no grupo acima"
9990
- },
9991
- /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiArrowRight, { size: 14 })
9992
- ), /* @__PURE__ */ import_react25.default.createElement(
9993
- "button",
9994
- {
9995
- onClick: () => onOutdent(group.id),
9996
- className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
9997
- title: "Desaninhar"
9998
- },
9999
- /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiArrowLeft, { size: 14 })
10000
- ), /* @__PURE__ */ import_react25.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react25.default.createElement(
10001
- "button",
10002
- {
10003
- onClick: () => onDelete(group.id),
10004
- className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
10005
- title: "Remover Grupo"
10006
- },
10007
- /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiTrash2, { size: 14 })
10008
- )))), 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(
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((a) => a.ancestry_id === ancestry.ancestry_id);
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((a) => a.ancestry_id === ancestry.ancestry_id) || ancestry;
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((a) => a.ancestry_id === ancestryId);
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 { ...g, ancestries: g.ancestries.filter((a) => a.ancestry_id !== ancestryId) };
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(import_fi19.FiLoader, { className: "animate-spin text-indigo-400", size: 12 }), /* @__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(
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("div", { className: `
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
- ` }, /* @__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(import_fi19.FiSearch, { 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"}` }), /* @__PURE__ */ import_react25.default.createElement(
10285
- "input",
10286
- {
10287
- type: "text",
10288
- placeholder: pickingGroupId ? "Pesquise para adicionar..." : "Pesquisar ancestralidade...",
10289
- className: `
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
- value: searchTerm,
10294
- onChange: (e) => setSearchTerm(e.target.value),
10295
- autoFocus: !pickingGroupId
10296
- }
10297
- ))), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
10298
- const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
10299
- const isPicking = !!pickingGroupId;
10300
- return /* @__PURE__ */ import_react25.default.createElement(
10301
- "div",
10302
- {
10303
- key: anc.ancestry_id,
10304
- onClick: () => {
10305
- if (isPicking) handleSelectAncestry(anc);
10306
- },
10307
- className: `
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
- /* @__PURE__ */ import_react25.default.createElement("div", { className: `
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
- ` }, isPicking ? /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiPlus, { size: 16 }) : /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiLayers, { size: 14 })),
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
- 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",
10325
- title: "Renderizar Ancestralidade"
10326
- },
10327
- /* @__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" }))
10328
- )
10329
- );
10330
- }))), /* @__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(
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, [...currentPath, i]);
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)({ visible: false, x: 0, y: 0, nodeData: null });
10503
- const [multiContextMenu, setMultiContextMenu] = (0, import_react26.useState)({ visible: false, x: 0, y: 0, nodeIds: null });
10504
- const [relationshipMenu, setRelationshipMenu] = (0, import_react26.useState)({ visible: false, x: 0, y: 0, linkObject: null });
10505
- const [creationMode, setCreationMode] = (0, import_react26.useState)({ isActive: false, sourceNodeData: null });
10506
- const [versionMode, setVersionMode] = (0, import_react26.useState)({ isActive: false, sourceNodeData: null });
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)({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
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)({ left: 16, top: 16, opacity: 0 });
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)({ visible: false, images: [], startIndex: 0 });
10522
- const [editingAncestryRel, setEditingAncestryRel] = (0, import_react26.useState)({ visible: false, data: null, path: null });
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: { isActive: false, end: null, fixedNodeId: null, originalLine: null, line: null },
10563
- ancestry: { isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", isAddingNodes: false },
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 { width: readModeWidth, isResizing: isReadModeResizing, handlePointerDown: handleReadModeResize } = useResizablePanel({
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((db) => String(db.db_id) === String(parentFileId));
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(file.id, session);
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(sceneConfigId, session, file.id);
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(viewToImport.id, targetViewOwnerId);
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((db) => db.db_id)
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((curr) => String(curr.ancestry_id) === String(newAnc.ancestry_id))
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 = [...currentAncestries, ...newAncestries];
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("Erro: URL de salvamento de ancestralidade n\xE3o definida.");
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("Importa\xE7\xE3o finalizada, mas nenhum dado novo foi adicionado.");
10833
+ console.warn(
10834
+ "Importa\xE7\xE3o finalizada, mas nenhum dado novo foi adicionado."
10835
+ );
10695
10836
  }
10696
10837
  },
10697
- [get_single_parent_file, get_ancestry_file, save_view_data, session, sceneSaveUrl, ancestry_save_url, sceneConfigId, add_new_parent_file_to_scene_at_firebase_action]
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)((target, zoomFactor = 1, forcedDirection = null) => {
10703
- const { camera, controls, tweenGroup } = stateRef.current;
10704
- if (!camera || !controls || !tweenGroup) return;
10705
- const targetPos = target instanceof THREE3.Mesh ? target.getWorldPosition(new THREE3.Vector3()) : target;
10706
- const controlsTween = new import_tween2.Tween(controls.target).to(targetPos, 1500).easing(import_tween2.Easing.Cubic.Out);
10707
- tweenGroup.add(controlsTween);
10708
- controlsTween.start();
10709
- let offset;
10710
- if (forcedDirection) {
10711
- offset = forcedDirection.clone().normalize().multiplyScalar(x_view_config.CAMERA_ZOOM_DISTANCE / zoomFactor);
10712
- } else {
10713
- offset = camera.position.clone().sub(controls.target).normalize().multiplyScalar(x_view_config.CAMERA_ZOOM_DISTANCE / zoomFactor);
10714
- }
10715
- const targetCameraPos = targetPos.clone().add(offset);
10716
- const cameraTween = new import_tween2.Tween(camera.position).to(targetCameraPos, 1500).easing(import_tween2.Easing.Cubic.Out);
10717
- tweenGroup.add(cameraTween);
10718
- cameraTween.start();
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)((idTree, nodes, ancestries = []) => {
10726
- if (!idTree) return null;
10727
- const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
10728
- const ancestryMap = new Map(ancestries.map((a) => [String(a.ancestry_id), a]));
10729
- const recursiveBuild = (treeItem) => {
10730
- if (!treeItem) return null;
10731
- if (treeItem.is_section) {
10732
- return {
10733
- ...treeItem,
10734
- children: (treeItem.children || []).map(recursiveBuild).filter(Boolean)
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
- ...branch,
10760
- tree: recursiveBuild(branch.tree)
10889
+ ...treeItem,
10890
+ children: (treeItem.children || []).map(recursiveBuild).filter(Boolean)
10761
10891
  };
10762
- });
10763
- }
10764
- return {
10765
- ...effectiveNode ? { node: effectiveNode } : { node: { id: nodeId, name: "Unknown" } },
10766
- relationship: treeItem.relationship || {},
10767
- children: (treeItem.children || []).map(recursiveBuild).filter(Boolean),
10768
- parallel_branches: processedBranches
10769
- };
10770
- };
10771
- let rootId = idTree.node_id;
10772
- if (!rootId && idTree.node) rootId = idTree.node.id;
10773
- if (rootId) {
10774
- const rootNode = nodeMap.get(String(rootId));
10775
- const effectiveRoot = rootNode || idTree.node;
10776
- if (!effectiveRoot) return null;
10777
- return {
10778
- node: effectiveRoot,
10779
- relationship: idTree.relationship || {},
10780
- children: (idTree.children || []).map(recursiveBuild).filter(Boolean),
10781
- parallel_branches: (idTree.parallel_branches || []).map((branch) => {
10782
- if (branch.linked_ancestry_id) {
10783
- const linkedAncestry = ancestryMap.get(String(branch.linked_ancestry_id));
10784
- if (linkedAncestry && linkedAncestry.tree) {
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
- return { ...branch, tree: recursiveBuild(branch.tree) };
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
- return recursiveBuild(idTree);
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(sortedTimePoints.map((time, index) => [
10882
- time,
10883
- (index - maxTimeIndex) * TIMELINE_LAYER_SPACING_Y
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(TIMELINE_INTERVAL_BAR_RADIUS, TIMELINE_INTERVAL_BAR_RADIUS, 1, 16);
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) return;
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) mesh.userData.timelineEndLabel.material.map.dispose();
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(sortedTimePoints.map((time, index) => [time, index * TIMELINE_LAYER_SPACING_Y]));
11033
- timelineNodes.sort((a, b) => a.startDate - b.startDate || a.endDate - b.endDate);
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(TIMELINE_INTERVAL_BAR_RADIUS, TIMELINE_INTERVAL_BAR_RADIUS, 1, 16);
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(configPath, ownerId2, typeStr, session, focusNodeId, focusAncestryId);
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([scenePromise, boardPromise]);
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((n) => String(n.id) === String(focusNodeId));
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(sceneResponse.data.parent).flatMap((f) => f.nodes || []);
11096
- targetNode = allParentNodes.find((n) => String(n.id) === String(focusNodeId));
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("Console de sceneResponse.data.scene:", sceneResponse.data.scene);
11110
- console.log("Console de sceneResponse.data.parent:", sceneResponse.data.parent);
11111
- console.log("Console de sceneResponse.data.ancestry:", sceneResponse.data.ancestry);
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("Falha ao buscar dados da cena:", (sceneResponse == null ? void 0 : sceneResponse.error) || "Resposta inv\xE1lida.");
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("Nenhum par\xE2metro de cena encontrado na URL ou falha na decripta\xE7\xE3o.");
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)((nodeData, position, suppressVersionUpdate = false) => {
11155
- const { graphGroup, nodeObjects, clickableNodes, glowTexture, tweenGroup } = stateRef.current;
11156
- const nodeId = String(nodeData.id);
11157
- if (nodeObjects[nodeId]) {
11158
- const existingMesh = nodeObjects[nodeId];
11159
- if (position) {
11160
- const updateTween = new import_tween2.Tween(existingMesh.position).to(position, 800).easing(import_tween2.Easing.Cubic.Out);
11161
- tweenGroup.add(updateTween);
11162
- updateTween.start();
11163
- }
11164
- return existingMesh;
11165
- }
11166
- const mesh = createNodeMesh(nodeData, position || new THREE3.Vector3(), glowTexture);
11167
- graphGroup.add(mesh);
11168
- if (mesh.userData.labelObject) {
11169
- if (mesh.userData.labelOffset) {
11170
- mesh.userData.labelObject.position.copy(mesh.position).add(mesh.userData.labelOffset);
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
- graphGroup.add(mesh.userData.labelObject);
11173
- }
11174
- nodeObjects[nodeId] = mesh;
11175
- clickableNodes.push(mesh);
11176
- if (!suppressVersionUpdate) {
11177
- setSceneVersion((v) => v + 1);
11178
- }
11179
- return mesh;
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(75, currentMount.clientWidth / currentMount.clientHeight, 0.1, 2e3);
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(new THREE3.Vector2(currentMount.clientWidth, currentMount.clientHeight), x_view_config.BLOOM_EFFECT.strength, x_view_config.BLOOM_EFFECT.radius, x_view_config.BLOOM_EFFECT.threshold);
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(currentMount.clientWidth, currentMount.clientHeight);
11260
- const newLinks = createMultipleLinkLines(linksArray, sourceNode, targetNode, resolution);
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(stateRef.current.clickableNodes, false);
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 = [...stateRef.current.allLinks, ...stateRef.current.ancestryLinks];
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(start, controlPoint, end);
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 = { x: (tmpP1.x * 0.5 + 0.5) * clientWidth, y: (-tmpP1.y * 0.5 + 0.5) * clientHeight };
11334
- const p2_px = { x: (tmpP2.x * 0.5 + 0.5) * clientWidth, y: (-tmpP2.y * 0.5 + 0.5) * clientHeight };
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 = { x: p1_px.x + t * (p2_px.x - p1_px.x), y: p1_px.y + t * (p2_px.y - p1_px.y) };
11340
- const dist = Math.hypot(mousePixels.x - closestPoint.x, mousePixels.y - closestPoint.y);
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 = { x: (p1.x * 0.5 + 0.5) * clientWidth, y: (-p1.y * 0.5 + 0.5) * clientHeight };
11350
- const p2_px = { x: (p2.x * 0.5 + 0.5) * clientWidth, y: (-p2.y * 0.5 + 0.5) * clientHeight };
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 = { x: p1_px.x + t * (p2_px.x - p1_px.x), y: p1_px.y + t * (p2_px.y - p1_px.y) };
11356
- const dist = Math.hypot(mousePixels.x - closestPoint.x, mousePixels.y - closestPoint.y);
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 = { isDown: true, x: event.clientX, y: event.clientY };
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(plane.normal, stateRef.current.draggedNode.position);
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) 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(plane.normal, stateRef.current.draggedNode.position);
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) stateRef.current.hoveredNode = newHoveredNode;
11448
- if (stateRef.current.hoveredLink !== newHoveredLink) stateRef.current.hoveredLink = newHoveredLink;
11449
- if (currentMount) currentMount.style.cursor = newHoveredNode || newHoveredLink ? "pointer" : "grab";
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(context, hoveredNode.userData);
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(context, hoveredNode.userData);
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("Erro: N\xE3o \xE9 poss\xEDvel adicionar um Node como filho dele mesmo.");
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((child) => !child.is_section && String(child.node.id) === String(childNode.id));
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 { ...current, children: [...current.children, { node: childNode, children: [], relationship: {} }] };
11804
+ return {
11805
+ ...current,
11806
+ children: [
11807
+ ...current.children,
11808
+ { node: childNode, children: [], relationship: {} }
11809
+ ]
11810
+ };
11503
11811
  }
11504
- return { ...current, children: current.children.map((c) => addChildToNode(c, targetParentId, childNode)) };
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(prev[treeKey], parentId, fullNodeData);
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) currentMount.style.cursor = stateRef.current.hoveredNode || stateRef.current.hoveredLink ? "pointer" : "grab";
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) return;
11572
- if (stateRef.current.hoveredNode) tweenToTarget(stateRef.current.hoveredNode);
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) return;
11898
+ if (stateRef.current.creation.isActive || stateRef.current.connection.isActive || stateRef.current.relink.isActive)
11899
+ return;
11579
11900
  setMouseFromEvent(event);
11580
- setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
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({ visible: true, x: event.clientX, y: event.clientY, linkObject: pickedLink });
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 = [...stateRef.current.allLinks, ...stateRef.current.ancestryLinks];
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(start, controlPoint, end);
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([...sourceNode.position.toArray(), ...targetNode.position.toArray()]);
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(startPos, endPos, 0.5);
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) ghostElements.line.geometry.setPositions([...srcMesh.position.toArray(), ...ghostElements.node.position.toArray()]);
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)) connection.line.geometry.setPositions([...srcMesh.position.toArray(), ...intersectionPoint.toArray()]);
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)) relink.line.geometry.setPositions([...fixedMesh.position.toArray(), ...intersectionPoint.toArray()]);
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((line) => line.material.resolution.copy(resVec));
11749
- stateRef.current.ancestryLinks.forEach((line) => line.material.resolution.copy(resVec));
11750
- if (stateRef.current.ghostElements.line) stateRef.current.ghostElements.line.material.resolution.copy(resVec);
11751
- if (stateRef.current.connection.line) stateRef.current.connection.line.material.resolution.copy(resVec);
11752
- if (stateRef.current.relink.line) stateRef.current.relink.line.material.resolution.copy(resVec);
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)) obj.material.forEach((m) => m.dispose());
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)) obj.material.forEach((m) => m.dispose());
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
- }, [isInitialized, tweenToTarget, dbSaveUrl, isNodeInView, addOrUpdateNodeMesh, handleActivateTimeline, get_scene_view_data, save_view_data]);
11791
- const handleGhostNodeImageChange = (0, import_react26.useCallback)((useImage, imageUrl) => {
11792
- const { node: ghostNode, line: ghostLine, aura: ghostAura } = stateRef.current.ghostElements;
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) ghostNode.userData.labelObject.material.map.dispose();
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)) ghostNode.material.forEach((m) => m.dispose());
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)((nodeId, newIntensity) => {
11855
- const mesh = stateRef.current.nodeObjects[String(nodeId)];
11856
- if (!mesh) return;
11857
- const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
11858
- mesh.userData.intensity = newIntensity;
11859
- mesh.userData._baseEmissiveIntensity = adjustedIntensity;
11860
- const isImageNode = mesh.userData.useImageAsTexture === true;
11861
- if (isImageNode) {
11862
- const borderMesh = mesh.getObjectByName("borderRing");
11863
- if (borderMesh && borderMesh.material) {
11864
- borderMesh.material.emissiveIntensity = adjustedIntensity;
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
- } else {
11867
- if (mesh.material) {
11868
- mesh.material.emissiveIntensity = adjustedIntensity;
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
- const aura = mesh.getObjectByName("aura");
11872
- if (aura && aura.material) {
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((prev) => prev.visible ? { ...prev, visible: false } : prev);
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) metaChanged = true;
12012
- if (extraData.ancestryDescription !== void 0 && extraData.ancestryDescription !== prev.ancestryDescription) metaChanged = true;
12013
- if (extraData.ancestryDescriptionSections !== void 0 && JSON.stringify(extraData.ancestryDescriptionSections) !== JSON.stringify(prev.ancestryDescriptionSections)) metaChanged = true;
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) ghostElements.node.userData.labelObject.material.map.dispose();
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)) child.material.forEach((m) => m.dispose());
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 { graphDataRef, sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType, sceneConfigId: sceneConfigId2, ownerId: ownerId2 } = context;
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) graphGroup.remove(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 { stateRef: stateRef2, graphDataRef, sceneDataRef: sceneDataRef2, sceneConfigId: sceneConfigId2, sceneSaveUrl: sceneSaveUrl2, ownerId: ownerId2 } = context;
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(graphDataRef.current, sceneDataRef2.current, sourceNodeData.id, sceneConfigId2, ownerId2);
12161
- const targetParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, targetNodeData.id, sceneConfigId2, ownerId2);
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(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
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(filenameForSpecificParent, specificParentData);
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((a) => String(a.id) === String(ancestryId));
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((a) => a.lines);
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((prev) => prev.visible ? { ...prev, visible: false } : prev);
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))) return true;
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) return true;
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((a) => String(a.id) === String(ancestryObject.ancestry_id));
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((fileData) => fileData.nodes);
12754
+ const allParentNodes = Object.values(parentDataRef.current).flatMap(
12755
+ (fileData) => fileData.nodes
12756
+ );
12322
12757
  const allAncestries = ancestryDataRef.current || [];
12323
- const fullTree = buildFullAncestryTree(ancestryObject.tree, allParentNodes, allAncestries);
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(renderer.domElement.clientWidth, renderer.domElement.clientHeight);
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(originMesh, rootNodeMesh, resolution, {}, colorHex);
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(new THREE3.Vector3(0, 1, 0), currentAngle);
12418
- const rightVec = new THREE3.Vector3(1, 0, 0).applyAxisAngle(new THREE3.Vector3(0, 1, 0), currentAngle);
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(childItem.node, childPosition, true);
12893
+ const childMesh = addOrUpdateNodeMesh(
12894
+ childItem.node,
12895
+ childPosition,
12896
+ true
12897
+ );
12440
12898
  allRenderedNodePositions.push(childPosition);
12441
- const line = createAncestryLinkLine(parentMesh, childMesh, resolution, childItem.relationship, colorHex);
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(childItem.children, childMesh, childPosition, level + 1, currentAngle);
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((a, b) => (a.section_numeric_id || 0) - (b.section_numeric_id || 0));
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((s) => s.section_numeric_id === 0 || s.name === "Sess\xE3o 0");
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(combinedStartNodes, rootNodeMesh, rootTargetPos2, 1, baseRotation);
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(sectionNodes, currentAnchorMesh, currentAnchorPosition, 1, parentAngle);
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(String(lastMeshOfThisSection.userData.id)) || lastMeshOfThisSection.position;
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 = { name: "In\xEDcio", children: directChildren };
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(x_view_config.CAMERA_ZOOM_DISTANCE, radius * 2.8);
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(allRenderedNodePositions);
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(1, x_view_config.CAMERA_ZOOM_DISTANCE / (maxDim * 1.5));
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
- [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, readingMode.isActive, ancestryMode.isActive]
13127
+ [
13128
+ addOrUpdateNodeMesh,
13129
+ tweenToTarget,
13130
+ buildFullAncestryTree,
13131
+ readingMode.isActive,
13132
+ ancestryMode.isActive
13133
+ ]
12629
13134
  );
12630
- const handleRenderAbstractionTree = (0, import_react26.useCallback)((ancestryObject, targetNodeId = null) => {
12631
- setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
12632
- if (!ancestryObject || !ancestryObject.abstraction_tree) return;
12633
- const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
12634
- const allParentNodes = Object.values(parentDataRef.current).flatMap((f) => f.nodes);
12635
- let fullTree = buildFullAncestryTree(ancestryObject.abstraction_tree, allParentNodes, ancestryDataRef.current);
12636
- if (!fullTree || !fullTree.node) return;
12637
- if (targetNodeId) {
12638
- const pruneTreeToPath = (treeNode, targetId) => {
12639
- var _a2;
12640
- if (!treeNode) return null;
12641
- const currentId = treeNode.is_section ? treeNode.section_id : String((_a2 = treeNode.node) == null ? void 0 : _a2.id);
12642
- if (String(currentId) === String(targetId)) {
12643
- return { ...treeNode, children: [] };
12644
- }
12645
- if (treeNode.children && treeNode.children.length > 0) {
12646
- for (let child of treeNode.children) {
12647
- const prunedChild = pruneTreeToPath(child, targetId);
12648
- if (prunedChild) {
12649
- return { ...treeNode, children: [prunedChild] };
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
- return null;
12654
- };
12655
- const pruned = pruneTreeToPath(fullTree, targetNodeId);
12656
- if (pruned) fullTree = pruned;
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
- const rotation = newStack.reduce((acc, step) => {
12743
- return acc + (step.entryDirection === "left" ? -Math.PI / 2 : Math.PI / 2);
12744
- }, 0);
12745
- const initialFocusId = "preamble";
12746
- handleRenderAncestry(
12747
- branchAncestryObj,
12748
- allowedIds,
12749
- initialFocusId,
12750
- rotation,
12751
- false
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
- } else if (action === "back") {
12756
- if (branchStack.length === 0) return;
12757
- const newStack = [...branchStack];
12758
- const popped = newStack.pop();
12759
- if (popped && popped.branchId) {
12760
- stateRef.current.readMode.progressMap[popped.branchId] = stateRef.current.readMode.currentMaxIndex;
12761
- }
12762
- const parentSavedIndex = popped.savedMaxIndex !== void 0 ? popped.savedMaxIndex : 0;
12763
- stateRef.current.readMode.currentMaxIndex = parentSavedIndex;
12764
- stateRef.current.maxAncestryRenderIndex = parentSavedIndex;
12765
- let targetTreeToRender = fullTree;
12766
- let targetAncestryInfo = ancestry;
12767
- if (newStack.length > 0) {
12768
- let ptr = fullTree;
12769
- for (const step of newStack) {
12770
- const found = findNodePath3(ptr, step.nodeId);
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((b) => b.id === step.branchId);
12773
- if (branch) {
12774
- ptr = branch.tree;
12775
- targetAncestryInfo = { ...branch, ancestry_id: branch.id, ancestral_node: branch.tree.node.id };
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
- targetTreeToRender = ptr;
12780
- }
12781
- const activeParentStackItem = newStack.length > 0 ? newStack[newStack.length - 1] : null;
12782
- const parentAncestryObj = {
12783
- ...targetAncestryInfo,
12784
- tree: targetTreeToRender,
12785
- _originNodeId: activeParentStackItem ? activeParentStackItem.nodeId : null,
12786
- _branchDirection: activeParentStackItem ? activeParentStackItem.entryDirection : null
12787
- };
12788
- const descriptionText = targetAncestryInfo.description || "";
12789
- const savedSections = targetAncestryInfo.description_sections || [];
12790
- const sections = parseDescriptionSections(descriptionText, savedSections);
12791
- let focusTargetId = null;
12792
- if (popped && popped.nodeId) {
12793
- const mentionTag = `[[MENTION:node:${popped.nodeId}]]`;
12794
- for (let i = 0; i < sections.length; i++) {
12795
- if (sections[i].content && sections[i].content.includes(mentionTag)) {
12796
- const section = sections[i];
12797
- focusTargetId = section.numericId !== void 0 ? section.numericId : section.id;
12798
- break;
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
- const allowedIds = /* @__PURE__ */ new Set();
12803
- allowedIds.add("preamble");
12804
- allowedIds.add(0);
12805
- allowedIds.add("0");
12806
- for (let i = 0; i <= parentSavedIndex; i++) {
12807
- if (sections[i]) {
12808
- if (sections[i].id) allowedIds.add(String(sections[i].id));
12809
- if (sections[i].numericId !== void 0 && sections[i].numericId !== null) {
12810
- allowedIds.add(sections[i].numericId);
12811
- allowedIds.add(String(sections[i].numericId));
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
- const rotation = newStack.reduce((acc, step) => {
12816
- return acc + (step.entryDirection === "left" ? -Math.PI / 2 : Math.PI / 2);
12817
- }, 0);
12818
- handleRenderAncestry(parentAncestryObj, allowedIds, focusTargetId, rotation, false);
12819
- if (popped && popped.nodeId) {
12820
- const nodeMesh = stateRef.current.nodeObjects[String(popped.nodeId)];
12821
- if (nodeMesh) {
12822
- tweenToTarget(nodeMesh);
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
- setReadingMode((prev) => ({
12826
- ...prev,
12827
- branchStack: newStack,
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) return null;
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
- }, [highlightedNodeId, readingMode.ancestry, buildFullAncestryTree, readingMode.branchStack, ancestryDataRef.current]);
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((b) => b.id === step.branchId);
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((f) => f.nodes || []);
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
- }, [readingMode.isActive, readingMode.ancestry, buildFullAncestryTree, sceneVersion]);
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((prev) => prev.visible ? { ...prev, visible: false } : prev);
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: true,
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)((activeSectionId) => {
12975
- const { ancestry, branchStack } = readingMode;
12976
- if (!ancestry || !readingMode.isActive) return;
12977
- let targetObj = ancestry;
12978
- let targetTree = ancestry.tree;
12979
- if (branchStack.length > 0) {
12980
- const allNodes = Object.values(parentDataRef.current).flatMap((f) => f.nodes);
12981
- const fullTree = buildFullAncestryTree(
12982
- ancestry.tree,
12983
- allNodes,
12984
- ancestryDataRef.current
12985
- );
12986
- let currentPtr = fullTree;
12987
- for (const step of branchStack) {
12988
- const found = findNodePath3(currentPtr, step.nodeId);
12989
- if (found && found.node && found.node.parallel_branches) {
12990
- const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
12991
- if (branch) {
12992
- targetObj = branch;
12993
- targetTree = branch.tree;
12994
- currentPtr = branch.tree;
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
- const descriptionText = targetObj.description || "";
13000
- const savedSections = targetObj.description_sections || [];
13001
- const sections = parseDescriptionSections(descriptionText, savedSections);
13002
- let activeIndex = sections.findIndex((s) => String(s.id) === String(activeSectionId));
13003
- if (activeIndex === -1 && !isNaN(parseInt(activeSectionId))) {
13004
- activeIndex = sections.findIndex((s) => s.numericId === parseInt(activeSectionId));
13005
- }
13006
- if (activeIndex === -1) activeIndex = 0;
13007
- stateRef.current.readMode.currentMaxIndex = activeIndex;
13008
- stateRef.current.maxAncestryRenderIndex = activeIndex;
13009
- const renderLimitIndex = stateRef.current.maxAncestryRenderIndex;
13010
- const allowedIds = /* @__PURE__ */ new Set();
13011
- allowedIds.add("preamble");
13012
- allowedIds.add(0);
13013
- allowedIds.add("0");
13014
- for (let i = 0; i <= renderLimitIndex; i++) {
13015
- if (sections[i]) {
13016
- if (sections[i].id) allowedIds.add(String(sections[i].id));
13017
- if (sections[i].numericId !== void 0 && sections[i].numericId !== null) {
13018
- allowedIds.add(sections[i].numericId);
13019
- allowedIds.add(String(sections[i].numericId));
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
- const activeSection = sections[activeIndex];
13024
- let focusTargetId = activeSectionId;
13025
- if (activeSection && activeSection.numericId !== void 0 && activeSection.numericId !== null) {
13026
- focusTargetId = activeSection.numericId;
13027
- }
13028
- const currentStackItem = branchStack.length > 0 ? branchStack[branchStack.length - 1] : null;
13029
- const renderPayload = {
13030
- ...targetObj,
13031
- ancestry_id: targetObj.ancestry_id || targetObj.id,
13032
- ancestral_node: targetTree.node ? targetTree.node.id : targetTree.node_id,
13033
- tree: targetTree,
13034
- _originNodeId: currentStackItem ? currentStackItem.nodeId : null,
13035
- _branchDirection: currentStackItem ? currentStackItem.entryDirection : null,
13036
- _forceUpdate: true
13037
- };
13038
- const rotation = branchStack.reduce((acc, step) => {
13039
- return acc + (step.entryDirection === "left" ? -Math.PI / 2 : Math.PI / 2);
13040
- }, 0);
13041
- handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
13042
- }, [readingMode, handleRenderAncestry, buildFullAncestryTree, ancestryDataRef.current]);
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)((activeSectionId, ancestryOverride = null, rotation = 0) => {
13047
- var _a2, _b2;
13048
- const currentMode = stateRef.current.ancestry;
13049
- let targetObj = ancestryOverride;
13050
- if (!targetObj) {
13051
- const currentAncestryId = currentMode.currentAncestryId;
13052
- const ancestryObj = (ancestryDataRef.current || []).find((a) => String(a.ancestry_id) === String(currentAncestryId));
13053
- targetObj = ancestryObj || (currentMode.isActive ? {
13054
- ...currentMode,
13055
- ancestry_id: "temp_creating",
13056
- ancestral_node: (_b2 = (_a2 = currentMode.tree) == null ? void 0 : _a2.node) == null ? void 0 : _b2.id
13057
- } : null);
13058
- }
13059
- if (!targetObj) return;
13060
- const targetId = targetObj.ancestry_id || targetObj.id;
13061
- if (stateRef.current.lastRenderedAncestryId !== targetId) {
13062
- stateRef.current.maxAncestryRenderIndex = 0;
13063
- stateRef.current.lastRenderedAncestryId = targetId;
13064
- }
13065
- const descriptionText = (ancestryOverride ? targetObj.description : currentMode.ancestryDescription) || targetObj.description || "";
13066
- const savedSections = (ancestryOverride ? targetObj.description_sections : currentMode.ancestryDescriptionSections) || targetObj.description_sections || [];
13067
- const sections = parseDescriptionSections(descriptionText, savedSections);
13068
- let activeIndex = sections.findIndex((s) => String(s.id) === String(activeSectionId));
13069
- if (activeIndex === -1 && !isNaN(parseInt(activeSectionId))) {
13070
- activeIndex = sections.findIndex((s) => s.numericId === parseInt(activeSectionId));
13071
- }
13072
- if (activeIndex === -1) activeIndex = 0;
13073
- if (stateRef.current.maxAncestryRenderIndex === void 0) stateRef.current.maxAncestryRenderIndex = 0;
13074
- stateRef.current.maxAncestryRenderIndex = activeIndex;
13075
- const renderLimitIndex = stateRef.current.maxAncestryRenderIndex;
13076
- const allowedIds = /* @__PURE__ */ new Set();
13077
- allowedIds.add("preamble");
13078
- allowedIds.add(0);
13079
- allowedIds.add("0");
13080
- for (let i = 0; i <= renderLimitIndex; i++) {
13081
- if (sections[i]) {
13082
- if (sections[i].id) allowedIds.add(String(sections[i].id));
13083
- if (sections[i].numericId !== void 0 && sections[i].numericId !== null) {
13084
- allowedIds.add(sections[i].numericId);
13085
- allowedIds.add(String(sections[i].numericId));
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
- const activeSection = sections[activeIndex];
13090
- let focusTargetId = activeSectionId;
13091
- if (activeSection && activeSection.numericId !== void 0 && activeSection.numericId !== null) {
13092
- focusTargetId = activeSection.numericId;
13093
- }
13094
- const treeToRender = ancestryOverride ? ancestryOverride.tree : currentMode.isActive && currentMode.tree ? currentMode.tree : targetObj.tree;
13095
- const renderPayload = { ...targetObj, tree: treeToRender };
13096
- handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
13097
- }, [handleRenderAncestry]);
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((prev) => prev.visible ? { ...prev, visible: false } : prev);
13713
+ setContextMenu(
13714
+ (prev) => prev.visible ? { ...prev, visible: false } : prev
13715
+ );
13101
13716
  if (!ancestryObject || !ancestryObject.tree) {
13102
- alert("N\xE3o foi poss\xEDvel carregar os dados desta ancestralidade para edi\xE7\xE3o.");
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((fileData) => fileData.nodes);
13725
+ const allParentNodes = Object.values(parentDataRef.current).flatMap(
13726
+ (fileData) => fileData.nodes
13727
+ );
13109
13728
  const allAncestries = ancestryDataRef.current || [];
13110
- const fullTree = buildFullAncestryTree(ancestryObject.tree, allParentNodes, allAncestries);
13729
+ const fullTree = buildFullAncestryTree(
13730
+ ancestryObject.tree,
13731
+ allParentNodes,
13732
+ allAncestries
13733
+ );
13111
13734
  if (!fullTree) {
13112
- alert("Falha ao reconstruir a \xE1rvore de ancestralidade. Alguns Nodes podem estar faltando.");
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(ancestryObject.abstraction_tree, allParentNodes, allAncestries) : { node: fullTree.node, children: [] };
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("Erro: A estrutura da ancestralidade \xE9 inv\xE1lida (Node raiz ausente).");
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(ancestryMode.abstraction_tree);
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((anc) => String(anc.ancestry_id) === String(currentAncestryId));
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(targetFileIdForCache, targetOwnerIdForCache);
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("Arquivo de destino n\xE3o existe ou erro ao buscar, criando novo:", fetchErr);
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((a) => String(a.ancestry_id) === String(ancestryObjectToSave.ancestry_id));
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({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
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
- [ancestryMode, ancestry_save_url, handleRenderAncestry, save_view_data, sceneConfigId, ownerId, get_ancestry_file]
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((err) => console.error("Erro ao deletar arquivos da ancestralidade:", err));
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("N\xE3o foi poss\xEDvel identificar o arquivo de origem desta ancestralidade.");
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(finalSaveUrl, updatedAncestriesForFile);
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((a) => String(a.id) === String(ancestryIdToDelete));
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((a) => a.lines);
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(result.error || "Ocorreu um erro desconhecido ao excluir.");
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({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "" });
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)((ancestry) => {
13432
- setIsAncestryBoardOpen(false);
13433
- setIsSidebarOpen(false);
13434
- handleStartReadingAncestry(ancestry);
13435
- }, [handleStartReadingAncestry]);
13436
- const handleSaveAncestryBoard = (0, import_react26.useCallback)(async (groups) => {
13437
- if (!sceneConfigId || !viewParams || !session) return;
13438
- const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
13439
- await save_ancestry_board_action(sceneConfigId, sceneType, groups, session, ownerId);
13440
- }, [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]);
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((fileData) => fileData.nodes.flatMap((node) => {
13446
- if (Array.isArray(node.type)) return node.type;
13447
- return [node.type];
13448
- })).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
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(actionHandlerContext, nodeId);
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("N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente.");
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((fileData) => fileData.nodes || []);
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)((referenceData) => {
13513
- const { type, id } = referenceData;
13514
- if (type === "node") {
13515
- const targetNode = allAvailableNodes.find((n) => String(n.id) === String(id));
13516
- if (targetNode) {
13517
- setAncestryLinkDetails(null);
13518
- setDetailsLink(null);
13519
- setDetailsNode(targetNode);
13520
- const sceneMesh = stateRef.current.nodeObjects[String(id)];
13521
- if (sceneMesh) {
13522
- tweenToTarget(sceneMesh);
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
- }, [allAvailableNodes, allAvailableAncestries, handleEditAncestry, tweenToTarget]);
14245
+ },
14246
+ [
14247
+ allAvailableNodes,
14248
+ allAvailableAncestries,
14249
+ handleEditAncestry,
14250
+ tweenToTarget
14251
+ ]
14252
+ );
13539
14253
  const handleToggleAncestryAddMode = (0, import_react26.useCallback)(() => {
13540
- setAncestryMode((prev) => ({ ...prev, isAddingNodes: !prev.isAddingNodes }));
14254
+ setAncestryMode((prev) => ({
14255
+ ...prev,
14256
+ isAddingNodes: !prev.isAddingNodes
14257
+ }));
13541
14258
  }, []);
13542
- const handleFocusNode = (0, import_react26.useCallback)((nodeData) => {
13543
- if (!nodeData) return;
13544
- const nodeMesh = stateRef.current.nodeObjects[String(nodeData.id)];
13545
- if (nodeMesh) {
13546
- tweenToTarget(nodeMesh, 1.2);
13547
- }
13548
- }, [tweenToTarget]);
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(String(creationMode.sourceNodeData.id))) == null ? void 0 : _b.parentFileId : null;
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
- }, [isInitialized, sceneVersion, focusNodeId, hasFocusedInitial, tweenToTarget]);
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((a) => String(a.ancestry_id) === String(focusAncestryId));
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
- }, [isInitialized, sceneVersion, focusAncestryId, hasOpenedInitialAncestry, handleStartReadingAncestry]);
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) userActionHandlers.handleCancelConnection(context);
13595
- if (stateRef.current.relink.isActive) userActionHandlers.handleCancelRelink(context);
13596
- if (stateRef.current.creation.isActive) userActionHandlers.handleCancelCreation(context);
13597
- if ((_a2 = stateRef.current.versionMode) == null ? void 0 : _a2.isActive) userActionHandlers.handleCancelVersioning(context);
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({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
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((prev) => prev.visible ? { ...prev, visible: false } : prev);
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((mesh) => mesh.position.distanceTo(ghostPosition) < MIN_CLEARANCE);
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(ghostData, ghostPosition, glowTexture);
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("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", className: "w-16 h-16 mx-auto" }, /* @__PURE__ */ import_react26.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", 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" }))), /* @__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(
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("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", className: "w-5 h-5" }, /* @__PURE__ */ import_react26.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" })),
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: { position: "absolute", left: `${formPosition.left}px`, top: `${formPosition.top}px`, opacity: formPosition.opacity, zIndex: 20, transition: "opacity 200ms ease-out" },
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: { position: "absolute", left: `${formPosition.left}px`, top: `${formPosition.top}px`, opacity: formPosition.opacity, zIndex: 20, transition: "opacity 200ms ease-out" },
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: { position: "absolute", left: `16px`, top: `16px`, zIndex: 20, transition: "opacity 200ms ease-out" },
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: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${readModeWidth}px`, maxWidth: "92vw" }
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({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", isAddingNodes: false });
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 = { ...detailsNode, useImageAsTexture: useImage, textureImageUrl: url, color: currentColorOverride || detailsNode.color };
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((prev) => prev.visible ? { ...prev, visible: false } : prev),
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(actionHandlerContext, sourceNode, links),
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(actionHandlerContext, ids),
14021
- onDismissOtherNodes: (ids) => userActionHandlers.handleDismissOtherMultipleNodes(actionHandlerContext, ids),
14022
- onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(actionHandlerContext, ids)
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(ImageViewer, { data: imageViewer, onClose: () => setImageViewer({ ...imageViewer, visible: false }) }),
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
  {