@lv-x-software-house/x_view 1.2.2-dev.13 → 1.2.2-dev.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +971 -808
- package/dist/index.mjs +412 -249
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/XViewScene.jsx
|
|
2
|
-
import React23, { useCallback as
|
|
2
|
+
import React23, { useCallback as useCallback4, useEffect as useEffect21, useRef as useRef17, useState as useState23, useMemo as useMemo12 } from "react";
|
|
3
3
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
4
4
|
import { useSession } from "next-auth/react";
|
|
5
5
|
import CryptoJS from "crypto-js";
|
|
@@ -735,7 +735,7 @@ function XViewSidebar({
|
|
|
735
735
|
}
|
|
736
736
|
|
|
737
737
|
// src/components/AncestryRelationshipPanel.jsx
|
|
738
|
-
import React8, { useState as
|
|
738
|
+
import React8, { useState as useState9, useEffect as useEffect8, useRef as useRef7 } from "react";
|
|
739
739
|
|
|
740
740
|
// node_modules/uuid/dist/esm-node/rng.js
|
|
741
741
|
import crypto from "crypto";
|
|
@@ -785,6 +785,7 @@ function v4(options, buf, offset) {
|
|
|
785
785
|
var v4_default = v4;
|
|
786
786
|
|
|
787
787
|
// src/logic/x_view_utils.js
|
|
788
|
+
import { useState as useState3, useCallback } from "react";
|
|
788
789
|
import * as THREE2 from "three";
|
|
789
790
|
|
|
790
791
|
// src/logic/x_view_config.js
|
|
@@ -2999,9 +3000,36 @@ var extractFileUrlsFromProperties = (dataObject) => {
|
|
|
2999
3000
|
});
|
|
3000
3001
|
return urlsToDelete;
|
|
3001
3002
|
};
|
|
3003
|
+
function useResizablePanel({ initialWidth, minWidth, maxWidth }) {
|
|
3004
|
+
const [width, setWidth] = useState3(initialWidth);
|
|
3005
|
+
const [isResizing, setIsResizing] = useState3(false);
|
|
3006
|
+
const handlePointerDown = useCallback((e) => {
|
|
3007
|
+
e.preventDefault();
|
|
3008
|
+
e.stopPropagation();
|
|
3009
|
+
setIsResizing(true);
|
|
3010
|
+
const startX = e.clientX;
|
|
3011
|
+
const startWidth = width;
|
|
3012
|
+
const originalUserSelect = document.body.style.userSelect;
|
|
3013
|
+
document.body.style.userSelect = "none";
|
|
3014
|
+
const handlePointerMove = (moveEvent) => {
|
|
3015
|
+
const deltaX = startX - moveEvent.clientX;
|
|
3016
|
+
const newWidth = Math.min(Math.max(startWidth + deltaX, minWidth), maxWidth);
|
|
3017
|
+
setWidth(newWidth);
|
|
3018
|
+
};
|
|
3019
|
+
const handlePointerUp = () => {
|
|
3020
|
+
setIsResizing(false);
|
|
3021
|
+
document.body.style.userSelect = originalUserSelect;
|
|
3022
|
+
document.removeEventListener("pointermove", handlePointerMove);
|
|
3023
|
+
document.removeEventListener("pointerup", handlePointerUp);
|
|
3024
|
+
};
|
|
3025
|
+
document.addEventListener("pointermove", handlePointerMove);
|
|
3026
|
+
document.addEventListener("pointerup", handlePointerUp);
|
|
3027
|
+
}, [width, minWidth, maxWidth]);
|
|
3028
|
+
return { width, isResizing, handlePointerDown, setWidth };
|
|
3029
|
+
}
|
|
3002
3030
|
|
|
3003
3031
|
// src/components/CustomPropertyDisplay.jsx
|
|
3004
|
-
import React3, { useState as
|
|
3032
|
+
import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
3005
3033
|
import { FiCheck, FiX, FiEdit3, FiTrash2, FiExternalLink, FiFileText, FiChevronDown, FiUpload, FiLoader } from "react-icons/fi";
|
|
3006
3034
|
function CustomPropertyDisplay({
|
|
3007
3035
|
prop,
|
|
@@ -3016,12 +3044,12 @@ function CustomPropertyDisplay({
|
|
|
3016
3044
|
},
|
|
3017
3045
|
onUploadFile
|
|
3018
3046
|
}) {
|
|
3019
|
-
const [isEditing, setIsEditing] =
|
|
3020
|
-
const [tempProp, setTempProp] =
|
|
3021
|
-
const [isHovered, setIsHovered] =
|
|
3022
|
-
const [isTypeDropdownOpen, setIsTypeDropdownOpen] =
|
|
3047
|
+
const [isEditing, setIsEditing] = useState4(prop.isEditing ?? false);
|
|
3048
|
+
const [tempProp, setTempProp] = useState4(prop);
|
|
3049
|
+
const [isHovered, setIsHovered] = useState4(false);
|
|
3050
|
+
const [isTypeDropdownOpen, setIsTypeDropdownOpen] = useState4(false);
|
|
3023
3051
|
const dropdownRef = useRef3(null);
|
|
3024
|
-
const [uploadingItemIndex, setUploadingItemIndex] =
|
|
3052
|
+
const [uploadingItemIndex, setUploadingItemIndex] = useState4(null);
|
|
3025
3053
|
const fileInputRef = useRef3(null);
|
|
3026
3054
|
const currentUploadTargetRef = useRef3(null);
|
|
3027
3055
|
useEffect3(() => {
|
|
@@ -3144,8 +3172,8 @@ function CustomPropertyDisplay({
|
|
|
3144
3172
|
const availableOptions = [
|
|
3145
3173
|
{ value: "links", label: "Links", unique: true },
|
|
3146
3174
|
{ value: "images", label: "Images", unique: true },
|
|
3147
|
-
{ value: "documents", label: "Documents", unique: true },
|
|
3148
3175
|
{ value: "date", label: "Data", unique: true },
|
|
3176
|
+
{ value: "documents", label: "Documents", unique: true },
|
|
3149
3177
|
{ value: "text", label: "Texto", unique: false },
|
|
3150
3178
|
{ value: "number", label: "N\xFAmero", unique: false },
|
|
3151
3179
|
{ value: "list", label: "Lista", unique: false }
|
|
@@ -3367,15 +3395,15 @@ function CustomPropertyDisplay({
|
|
|
3367
3395
|
import { FiPlus, FiEdit2 as FiEdit22, FiBookOpen } from "react-icons/fi";
|
|
3368
3396
|
|
|
3369
3397
|
// src/components/DescriptionEditModal.jsx
|
|
3370
|
-
import React5, { useState as
|
|
3371
|
-
import { FiType, FiList, FiCode, FiLink as FiLink2, FiAtSign, FiSearch as FiSearch2, FiHexagon as FiHexagon2, FiGlobe, FiImage } from "react-icons/fi";
|
|
3398
|
+
import React5, { useState as useState6, useEffect as useEffect5, useRef as useRef5, useMemo as useMemo4 } from "react";
|
|
3399
|
+
import { FiType, FiList, FiCode, FiLink as FiLink2, FiAtSign, FiSearch as FiSearch2, FiHexagon as FiHexagon2, FiGlobe, FiImage, FiCheckSquare } from "react-icons/fi";
|
|
3372
3400
|
|
|
3373
3401
|
// src/components/SectionImportModal.jsx
|
|
3374
|
-
import React4, { useState as
|
|
3402
|
+
import React4, { useState as useState5, useMemo as useMemo3, useRef as useRef4, useEffect as useEffect4 } from "react";
|
|
3375
3403
|
import { FiSearch, FiLayers as FiLayers2, FiHexagon, FiClock, FiCheck as FiCheck2, FiCopy, FiTerminal, FiChevronDown as FiChevronDown2, FiChevronRight, FiDownload, FiLink } from "react-icons/fi";
|
|
3376
3404
|
var CodeBlock = ({ content, isActive, onClick }) => {
|
|
3377
|
-
const [isExpanded, setIsExpanded] =
|
|
3378
|
-
const [copied, setCopied] =
|
|
3405
|
+
const [isExpanded, setIsExpanded] = useState5(false);
|
|
3406
|
+
const [copied, setCopied] = useState5(false);
|
|
3379
3407
|
const cleanContent = content.replace(/^```|```$/g, "").trim();
|
|
3380
3408
|
const isLongCode = cleanContent.split("\n").length > 4;
|
|
3381
3409
|
const handleCopy = (e) => {
|
|
@@ -3438,14 +3466,14 @@ var formatLineContent = (line) => {
|
|
|
3438
3466
|
return /* @__PURE__ */ React4.createElement("span", { className: "break-words" }, line);
|
|
3439
3467
|
};
|
|
3440
3468
|
function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], availableAncestries = [] }) {
|
|
3441
|
-
const [searchTerm, setSearchTerm] =
|
|
3442
|
-
const [selectedItem, setSelectedItem] =
|
|
3443
|
-
const [searchHistory, setSearchHistory] =
|
|
3444
|
-
const [activeIndex, setActiveIndex] =
|
|
3445
|
-
const [selectedIndices, setSelectedIndices] =
|
|
3446
|
-
const [lastSelectedIndex, setLastSelectedIndex] =
|
|
3469
|
+
const [searchTerm, setSearchTerm] = useState5("");
|
|
3470
|
+
const [selectedItem, setSelectedItem] = useState5(null);
|
|
3471
|
+
const [searchHistory, setSearchHistory] = useState5([]);
|
|
3472
|
+
const [activeIndex, setActiveIndex] = useState5(0);
|
|
3473
|
+
const [selectedIndices, setSelectedIndices] = useState5(/* @__PURE__ */ new Set([0]));
|
|
3474
|
+
const [lastSelectedIndex, setLastSelectedIndex] = useState5(0);
|
|
3447
3475
|
const sectionRefs = useRef4([]);
|
|
3448
|
-
const [isDropdownOpen, setIsDropdownOpen] =
|
|
3476
|
+
const [isDropdownOpen, setIsDropdownOpen] = useState5(false);
|
|
3449
3477
|
const inputRef = useRef4(null);
|
|
3450
3478
|
useEffect4(() => {
|
|
3451
3479
|
if (!selectedItem) return;
|
|
@@ -3784,16 +3812,22 @@ function DescriptionEditModal({
|
|
|
3784
3812
|
availableAncestries = [],
|
|
3785
3813
|
availableImages = []
|
|
3786
3814
|
}) {
|
|
3787
|
-
const
|
|
3815
|
+
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.9 : 1200;
|
|
3816
|
+
const { width: panelWidth, isResizing, handlePointerDown: handleResize } = useResizablePanel({
|
|
3817
|
+
initialWidth: 700,
|
|
3818
|
+
minWidth: 400,
|
|
3819
|
+
maxWidth: maxPanelW
|
|
3820
|
+
});
|
|
3821
|
+
const [text, setText] = useState6(initialValue || "");
|
|
3788
3822
|
const textareaRef = useRef5(null);
|
|
3789
|
-
const [isImportModalOpen, setIsImportModalOpen] =
|
|
3790
|
-
const [isMentionModalOpen, setIsMentionModalOpen] =
|
|
3791
|
-
const [mentionSearch, setMentionSearch] =
|
|
3792
|
-
const [mentionTriggerIndex, setMentionTriggerIndex] =
|
|
3793
|
-
const [isImageModalOpen, setIsImageModalOpen] =
|
|
3794
|
-
const [manualImageUrl, setManualImageUrl] =
|
|
3823
|
+
const [isImportModalOpen, setIsImportModalOpen] = useState6(false);
|
|
3824
|
+
const [isMentionModalOpen, setIsMentionModalOpen] = useState6(false);
|
|
3825
|
+
const [mentionSearch, setMentionSearch] = useState6("");
|
|
3826
|
+
const [mentionTriggerIndex, setMentionTriggerIndex] = useState6(null);
|
|
3827
|
+
const [isImageModalOpen, setIsImageModalOpen] = useState6(false);
|
|
3828
|
+
const [manualImageUrl, setManualImageUrl] = useState6("");
|
|
3795
3829
|
const hoverTimeoutRef = useRef5(null);
|
|
3796
|
-
const [tooltipData, setTooltipData] =
|
|
3830
|
+
const [tooltipData, setTooltipData] = useState6(null);
|
|
3797
3831
|
useEffect5(() => {
|
|
3798
3832
|
const handleKeyDown = (e) => {
|
|
3799
3833
|
if (e.key === "Escape") {
|
|
@@ -3952,7 +3986,8 @@ function DescriptionEditModal({
|
|
|
3952
3986
|
return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement("div", { className: "fixed inset-0 z-[2000] flex justify-end pointer-events-none bg-transparent" }, /* @__PURE__ */ React5.createElement(
|
|
3953
3987
|
"div",
|
|
3954
3988
|
{
|
|
3955
|
-
className:
|
|
3989
|
+
className: `ui-overlay pointer-events-auto relative group h-full border-l border-white/10 bg-slate-950/95 shadow-2xl text-white flex flex-col ${isResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
|
|
3990
|
+
style: { width: `${panelWidth}px`, maxWidth: "90vw" },
|
|
3956
3991
|
onClick: swallow,
|
|
3957
3992
|
onPointerDown: swallow,
|
|
3958
3993
|
onPointerMove: swallow,
|
|
@@ -3961,6 +3996,17 @@ function DescriptionEditModal({
|
|
|
3961
3996
|
onContextMenu: swallow,
|
|
3962
3997
|
onDoubleClick: swallow
|
|
3963
3998
|
},
|
|
3999
|
+
/* @__PURE__ */ React5.createElement(
|
|
4000
|
+
"div",
|
|
4001
|
+
{
|
|
4002
|
+
onPointerDown: (e) => {
|
|
4003
|
+
e.stopPropagation();
|
|
4004
|
+
handleResize(e);
|
|
4005
|
+
},
|
|
4006
|
+
className: "absolute left-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-indigo-500/50 z-[2000] transition-colors",
|
|
4007
|
+
title: "Arraste para redimensionar"
|
|
4008
|
+
}
|
|
4009
|
+
),
|
|
3964
4010
|
/* @__PURE__ */ React5.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0 shrink-0" }),
|
|
3965
4011
|
/* @__PURE__ */ React5.createElement("div", { className: "px-6 pt-5 pb-3 flex items-center justify-between gap-4 shrink-0" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React5.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80" }), /* @__PURE__ */ React5.createElement("p", { className: "text-sm font-medium text-slate-200" }, title || "Editar Descri\xE7\xE3o")), /* @__PURE__ */ React5.createElement("button", { onClick: handleClose, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")),
|
|
3966
4012
|
/* @__PURE__ */ React5.createElement("div", { className: "px-6 py-3 flex flex-col gap-3 border-b border-white/5 bg-white/5 shrink-0" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 overflow-x-auto custom-scrollbar" }, /* @__PURE__ */ React5.createElement(
|
|
@@ -3990,6 +4036,24 @@ function DescriptionEditModal({
|
|
|
3990
4036
|
},
|
|
3991
4037
|
/* @__PURE__ */ React5.createElement(FiList, { size: 12 }),
|
|
3992
4038
|
" Lista"
|
|
4039
|
+
), /* @__PURE__ */ React5.createElement(
|
|
4040
|
+
"button",
|
|
4041
|
+
{
|
|
4042
|
+
onClick: () => insertAtCursor("1. "),
|
|
4043
|
+
className: "flex items-center gap-1 px-3 py-1.5 rounded bg-slate-800 hover:bg-slate-700 border border-white/10 text-xs font-medium transition-colors whitespace-nowrap",
|
|
4044
|
+
title: "Lista Numerada"
|
|
4045
|
+
},
|
|
4046
|
+
/* @__PURE__ */ React5.createElement("span", { className: "text-[10px] font-bold" }, "1."),
|
|
4047
|
+
" Numerada"
|
|
4048
|
+
), /* @__PURE__ */ React5.createElement(
|
|
4049
|
+
"button",
|
|
4050
|
+
{
|
|
4051
|
+
onClick: () => insertAtCursor("- [ ] "),
|
|
4052
|
+
className: "flex items-center gap-1 px-3 py-1.5 rounded bg-slate-800 hover:bg-slate-700 border border-white/10 text-xs font-medium transition-colors whitespace-nowrap",
|
|
4053
|
+
title: "Checklist (Checkbox)"
|
|
4054
|
+
},
|
|
4055
|
+
/* @__PURE__ */ React5.createElement(FiCheckSquare, { size: 12 }),
|
|
4056
|
+
" Checklist"
|
|
3993
4057
|
), /* @__PURE__ */ React5.createElement(
|
|
3994
4058
|
"button",
|
|
3995
4059
|
{
|
|
@@ -4152,11 +4216,11 @@ function DescriptionEditModal({
|
|
|
4152
4216
|
}
|
|
4153
4217
|
|
|
4154
4218
|
// src/components/DescriptionDisplay.jsx
|
|
4155
|
-
import React6, { useMemo as useMemo5, useState as
|
|
4156
|
-
import { FiCopy as FiCopy2, FiCheck as FiCheck3, FiChevronDown as FiChevronDown3, FiChevronRight as FiChevronRight2, FiTerminal as FiTerminal2, FiCornerDownRight, FiExternalLink as FiExternalLink2, FiImage as FiImage2 } from "react-icons/fi";
|
|
4219
|
+
import React6, { useMemo as useMemo5, useState as useState7, useEffect as useEffect6, useRef as useRef6 } from "react";
|
|
4220
|
+
import { FiCopy as FiCopy2, FiCheck as FiCheck3, FiChevronDown as FiChevronDown3, FiChevronRight as FiChevronRight2, FiTerminal as FiTerminal2, FiCornerDownRight, FiExternalLink as FiExternalLink2, FiImage as FiImage2, FiSave } from "react-icons/fi";
|
|
4157
4221
|
var CodeBlock2 = ({ content, isActive, onClick }) => {
|
|
4158
|
-
const [isExpanded, setIsExpanded] =
|
|
4159
|
-
const [copied, setCopied] =
|
|
4222
|
+
const [isExpanded, setIsExpanded] = useState7(false);
|
|
4223
|
+
const [copied, setCopied] = useState7(false);
|
|
4160
4224
|
const cleanContent = content.replace(/^```|```$/g, "").trim();
|
|
4161
4225
|
const isLongCode = cleanContent.split("\n").length > 4;
|
|
4162
4226
|
const handleCopy = (e) => {
|
|
@@ -4296,7 +4360,7 @@ var renderTextWithMentions = (text, availableNodes, onMentionClick, activeMentio
|
|
|
4296
4360
|
);
|
|
4297
4361
|
});
|
|
4298
4362
|
};
|
|
4299
|
-
var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick) => {
|
|
4363
|
+
var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick, onToggleCheckbox, globalCheckboxCounterRef) => {
|
|
4300
4364
|
const trimmedLine = line.replace(/\r$/, "");
|
|
4301
4365
|
const processContent = (content) => renderTextWithMentions(content, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick);
|
|
4302
4366
|
if (line.startsWith("# ")) {
|
|
@@ -4307,9 +4371,33 @@ var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionInd
|
|
|
4307
4371
|
const content = line.replace("## ", "");
|
|
4308
4372
|
return /* @__PURE__ */ React6.createElement("span", { className: "text-sm sm:text-base font-semibold text-indigo-200 leading-tight break-words" }, processContent(content));
|
|
4309
4373
|
}
|
|
4374
|
+
const checkboxMatch = trimmedLine.match(/^(\s*)- \[([ xX])\]\s+(.*)/);
|
|
4375
|
+
if (checkboxMatch) {
|
|
4376
|
+
const [_, space, state, content] = checkboxMatch;
|
|
4377
|
+
const isChecked = state.toLowerCase() === "x";
|
|
4378
|
+
const currentIdx = globalCheckboxCounterRef.current;
|
|
4379
|
+
globalCheckboxCounterRef.current += 1;
|
|
4380
|
+
return /* @__PURE__ */ React6.createElement("span", { className: "flex items-start gap-2.5 my-1 break-words ml-1" }, /* @__PURE__ */ React6.createElement(
|
|
4381
|
+
"input",
|
|
4382
|
+
{
|
|
4383
|
+
type: "checkbox",
|
|
4384
|
+
checked: isChecked,
|
|
4385
|
+
onChange: (e) => {
|
|
4386
|
+
e.stopPropagation();
|
|
4387
|
+
if (onToggleCheckbox) onToggleCheckbox(currentIdx);
|
|
4388
|
+
},
|
|
4389
|
+
className: "mt-1 cursor-pointer accent-indigo-500 w-3.5 h-3.5 border-white/20 rounded-sm focus:ring-indigo-500 focus:ring-offset-slate-900"
|
|
4390
|
+
}
|
|
4391
|
+
), /* @__PURE__ */ React6.createElement("span", { className: `transition-all duration-200 ${isChecked ? "line-through text-slate-500" : "text-slate-200"}` }, processContent(content)));
|
|
4392
|
+
}
|
|
4393
|
+
const numberMatch = trimmedLine.match(/^(\s*)(\d+\.)\s+(.*)/);
|
|
4394
|
+
if (numberMatch) {
|
|
4395
|
+
const [_, space, numberStr, content] = numberMatch;
|
|
4396
|
+
return /* @__PURE__ */ React6.createElement("span", { className: "flex items-start gap-2 my-0.5 break-words ml-1" }, /* @__PURE__ */ React6.createElement("span", { className: "text-indigo-400 font-mono font-bold text-xs mt-[3px] shrink-0" }, numberStr), /* @__PURE__ */ React6.createElement("span", { className: "text-slate-200" }, processContent(content)));
|
|
4397
|
+
}
|
|
4310
4398
|
if (trimmedLine.trim().startsWith("- ") || trimmedLine.trim().startsWith("* ")) {
|
|
4311
4399
|
const content = trimmedLine.trim().substring(2);
|
|
4312
|
-
return /* @__PURE__ */ React6.createElement("span", { className: "
|
|
4400
|
+
return /* @__PURE__ */ React6.createElement("span", { className: "flex items-start gap-2 my-0.5 break-words ml-1 text-slate-200" }, /* @__PURE__ */ React6.createElement("span", { className: "text-indigo-400 font-bold shrink-0 mt-[2px] text-xs" }, "\u2022"), /* @__PURE__ */ React6.createElement("span", null, processContent(content)));
|
|
4313
4401
|
}
|
|
4314
4402
|
return /* @__PURE__ */ React6.createElement("span", { className: "break-words" }, processContent(line));
|
|
4315
4403
|
};
|
|
@@ -4321,14 +4409,32 @@ function DescriptionDisplay({
|
|
|
4321
4409
|
onOpenReference,
|
|
4322
4410
|
onMentionClick,
|
|
4323
4411
|
onImageClick,
|
|
4324
|
-
// <--- NOVA PROP RECEBIDA
|
|
4325
4412
|
onSectionChange,
|
|
4326
4413
|
onBranchNav,
|
|
4327
4414
|
onHighlightNode,
|
|
4328
4415
|
initialSectionId,
|
|
4329
|
-
currentBranchDirection = null
|
|
4416
|
+
currentBranchDirection = null,
|
|
4417
|
+
onSaveDescription
|
|
4418
|
+
// NOVO: Prop para salvar checklist
|
|
4330
4419
|
}) {
|
|
4331
|
-
const
|
|
4420
|
+
const [localDescription, setLocalDescription] = useState7(description || "");
|
|
4421
|
+
useEffect6(() => {
|
|
4422
|
+
setLocalDescription(description || "");
|
|
4423
|
+
}, [description]);
|
|
4424
|
+
const sections = useMemo5(() => parseDescriptionSections(localDescription, savedSections), [localDescription, savedSections]);
|
|
4425
|
+
const globalCheckboxCounterRef = useRef6(0);
|
|
4426
|
+
const handleToggleCheckbox = (targetIndex) => {
|
|
4427
|
+
let currentIndex = 0;
|
|
4428
|
+
const newDesc = localDescription.replace(/^(\s*)- \[([ xX])\]/gm, (match, space, state) => {
|
|
4429
|
+
if (currentIndex === targetIndex) {
|
|
4430
|
+
currentIndex++;
|
|
4431
|
+
return state === " " ? `${space}- [x]` : `${space}- [ ]`;
|
|
4432
|
+
}
|
|
4433
|
+
currentIndex++;
|
|
4434
|
+
return match;
|
|
4435
|
+
});
|
|
4436
|
+
setLocalDescription(newDesc);
|
|
4437
|
+
};
|
|
4332
4438
|
const flatNavigation = useMemo5(() => {
|
|
4333
4439
|
const navItems = [];
|
|
4334
4440
|
sections.forEach((section, sIdx) => {
|
|
@@ -4355,7 +4461,7 @@ function DescriptionDisplay({
|
|
|
4355
4461
|
});
|
|
4356
4462
|
return navItems;
|
|
4357
4463
|
}, [sections]);
|
|
4358
|
-
const [currentStepIndex, setCurrentStepIndex] =
|
|
4464
|
+
const [currentStepIndex, setCurrentStepIndex] = useState7(0);
|
|
4359
4465
|
const activeRef = useRef6(null);
|
|
4360
4466
|
const lastNotifiedSectionId = useRef6(null);
|
|
4361
4467
|
const isInitialMount = useRef6(true);
|
|
@@ -4469,26 +4575,27 @@ function DescriptionDisplay({
|
|
|
4469
4575
|
}
|
|
4470
4576
|
const lines = part.replace(/\n$/, "").split("\n");
|
|
4471
4577
|
return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: `text-${parentIndex}-${partIndex}` }, lines.map((line, lineIndex) => {
|
|
4472
|
-
const isLastLine = lineIndex === lines.length - 1;
|
|
4473
4578
|
const isEmptyLine = line.trim() === "";
|
|
4474
4579
|
if (isEmptyLine) {
|
|
4475
4580
|
return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: `${parentIndex}-${partIndex}-${lineIndex}` }, /* @__PURE__ */ React6.createElement("br", null));
|
|
4476
4581
|
}
|
|
4477
4582
|
return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: `${parentIndex}-${partIndex}-${lineIndex}` }, /* @__PURE__ */ React6.createElement(
|
|
4478
|
-
"
|
|
4583
|
+
"div",
|
|
4479
4584
|
{
|
|
4480
4585
|
ref: isActiveSection && activeMentionIndex === -1 && partIndex === 0 && lineIndex === 0 ? setRef : null,
|
|
4481
|
-
onClick: () => {
|
|
4482
|
-
|
|
4483
|
-
|
|
4586
|
+
onClick: (e) => {
|
|
4587
|
+
if (e.target.type !== "checkbox") {
|
|
4588
|
+
const idx = flatNavigation.findIndex((item) => item.type === "section" && item.sectionIndex === parentIndex);
|
|
4589
|
+
if (idx !== -1) setCurrentStepIndex(idx);
|
|
4590
|
+
}
|
|
4484
4591
|
},
|
|
4485
4592
|
className: `
|
|
4486
|
-
transition-colors duration-200 cursor-pointer rounded-md px-1 py-0.5 -mx-1 box-decoration-clone
|
|
4487
|
-
${isActiveSection ? "bg-indigo-500/
|
|
4593
|
+
transition-colors duration-200 cursor-pointer rounded-md px-1 py-0.5 -mx-1 box-decoration-clone inline-block w-full
|
|
4594
|
+
${isActiveSection ? "bg-indigo-500/10 text-white ring-1 ring-indigo-500/30" : "hover:bg-white/5 hover:text-slate-200"}
|
|
4488
4595
|
`
|
|
4489
4596
|
},
|
|
4490
|
-
formatLineContent2(line, availableNodes, onMentionClick, isActiveSection ? activeMentionIndex : -1, mentionCounterRef, setRef, onImageClick)
|
|
4491
|
-
)
|
|
4597
|
+
formatLineContent2(line, availableNodes, onMentionClick, isActiveSection ? activeMentionIndex : -1, mentionCounterRef, setRef, onImageClick, handleToggleCheckbox, globalCheckboxCounterRef)
|
|
4598
|
+
));
|
|
4492
4599
|
}));
|
|
4493
4600
|
});
|
|
4494
4601
|
};
|
|
@@ -4516,7 +4623,9 @@ function DescriptionDisplay({
|
|
|
4516
4623
|
${isActiveSection ? "opacity-100" : "opacity-90"}
|
|
4517
4624
|
` }, renderMixedContent(resolved.content, index, isActiveSection, -1, setRef)));
|
|
4518
4625
|
};
|
|
4519
|
-
|
|
4626
|
+
globalCheckboxCounterRef.current = 0;
|
|
4627
|
+
const hasUnsavedChanges = localDescription !== (description || "");
|
|
4628
|
+
return /* @__PURE__ */ React6.createElement("div", { className: "relative w-full h-full min-h-[100px]" }, /* @__PURE__ */ React6.createElement("div", { className: "w-full text-sm leading-relaxed text-slate-300 break-words whitespace-pre-wrap px-3 pt-1 pb-16 pr-9" }, sections.map((section, index) => {
|
|
4520
4629
|
const currentNavItem = flatNavigation[currentStepIndex];
|
|
4521
4630
|
const isSectionContextActive = currentNavItem && currentNavItem.sectionIndex === index;
|
|
4522
4631
|
const activeMentionIndex = isSectionContextActive && currentNavItem.type === "mention" ? currentNavItem.mentionIndex : -1;
|
|
@@ -4532,11 +4641,22 @@ function DescriptionDisplay({
|
|
|
4532
4641
|
if (index === 0) leadingSpace = "";
|
|
4533
4642
|
const isRef = bodyText.trim().match(/^\[\[REF:(node|ancestry):([a-zA-Z0-9\-_]+):([a-zA-Z0-9\-_]+)\]\]$/);
|
|
4534
4643
|
return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: index }, /* @__PURE__ */ React6.createElement("span", null, leadingSpace), isRef ? renderReferenceSection(bodyText, index, isSectionContextActive, setRef) : renderMixedContent(bodyText, index, isSectionContextActive, activeMentionIndex, setRef), /* @__PURE__ */ React6.createElement("span", null, trailingSpace));
|
|
4535
|
-
}))
|
|
4644
|
+
})), hasUnsavedChanges && onSaveDescription && /* @__PURE__ */ React6.createElement("div", { className: "absolute bottom-4 left-1/2 -translate-x-1/2 z-[100] animate-in slide-in-from-bottom-4 fade-in duration-300" }, /* @__PURE__ */ React6.createElement(
|
|
4645
|
+
"button",
|
|
4646
|
+
{
|
|
4647
|
+
onClick: (e) => {
|
|
4648
|
+
e.stopPropagation();
|
|
4649
|
+
onSaveDescription(localDescription);
|
|
4650
|
+
},
|
|
4651
|
+
className: "flex items-center gap-2 px-5 py-2.5 bg-emerald-600 hover:bg-emerald-500 text-white rounded-full shadow-[0_8px_20px_rgba(5,150,105,0.4)] font-semibold text-sm transition-all hover:scale-105 active:scale-95 border border-emerald-400/30"
|
|
4652
|
+
},
|
|
4653
|
+
/* @__PURE__ */ React6.createElement(FiSave, { size: 16 }),
|
|
4654
|
+
" Salvar Checklist"
|
|
4655
|
+
)));
|
|
4536
4656
|
}
|
|
4537
4657
|
|
|
4538
4658
|
// src/components/DescriptionReadModePanel.jsx
|
|
4539
|
-
import React7, { useState as
|
|
4659
|
+
import React7, { useState as useState8, useMemo as useMemo6, useEffect as useEffect7 } from "react";
|
|
4540
4660
|
import {
|
|
4541
4661
|
FiArrowLeft,
|
|
4542
4662
|
FiEdit2,
|
|
@@ -4636,12 +4756,13 @@ function DescriptionReadModePanel({
|
|
|
4636
4756
|
userRole,
|
|
4637
4757
|
abstractionTree = null,
|
|
4638
4758
|
onRenderAbstractionTree = null,
|
|
4639
|
-
initialShowAbstraction = false
|
|
4759
|
+
initialShowAbstraction = false,
|
|
4760
|
+
onSaveDescription
|
|
4640
4761
|
}) {
|
|
4641
|
-
const [showProperties, setShowProperties] =
|
|
4642
|
-
const [showAbstraction, setShowAbstraction] =
|
|
4643
|
-
const [targetRenderNodeId, setTargetRenderNodeId] =
|
|
4644
|
-
const [isLinkCopied, setIsLinkCopied] =
|
|
4762
|
+
const [showProperties, setShowProperties] = useState8(false);
|
|
4763
|
+
const [showAbstraction, setShowAbstraction] = useState8(false);
|
|
4764
|
+
const [targetRenderNodeId, setTargetRenderNodeId] = useState8(null);
|
|
4765
|
+
const [isLinkCopied, setIsLinkCopied] = useState8(false);
|
|
4645
4766
|
const handleCopyLink = (e) => {
|
|
4646
4767
|
e.stopPropagation();
|
|
4647
4768
|
if (!ancestryId) return;
|
|
@@ -4854,7 +4975,8 @@ function DescriptionReadModePanel({
|
|
|
4854
4975
|
onHighlightNode,
|
|
4855
4976
|
initialSectionId,
|
|
4856
4977
|
currentBranchDirection,
|
|
4857
|
-
onImageClick
|
|
4978
|
+
onImageClick,
|
|
4979
|
+
onSaveDescription
|
|
4858
4980
|
}
|
|
4859
4981
|
)),
|
|
4860
4982
|
leftAction && !showAbstraction && !showProperties && /* @__PURE__ */ React7.createElement(
|
|
@@ -4896,11 +5018,11 @@ function AncestryRelationshipPanel({
|
|
|
4896
5018
|
onMentionClick,
|
|
4897
5019
|
onUploadFile
|
|
4898
5020
|
}) {
|
|
4899
|
-
const [description, setDescription] =
|
|
4900
|
-
const [customProps, setCustomProps] =
|
|
4901
|
-
const [existingSections, setExistingSections] =
|
|
4902
|
-
const [isDescriptionModalOpen, setIsDescriptionModalOpen] =
|
|
4903
|
-
const [isReadMode, setIsReadMode] =
|
|
5021
|
+
const [description, setDescription] = useState9((data == null ? void 0 : data.description) ?? "");
|
|
5022
|
+
const [customProps, setCustomProps] = useState9(() => extractCustomPropsFromNode(data || {}));
|
|
5023
|
+
const [existingSections, setExistingSections] = useState9((data == null ? void 0 : data.description_sections) || []);
|
|
5024
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState9(false);
|
|
5025
|
+
const [isReadMode, setIsReadMode] = useState9(false);
|
|
4904
5026
|
const propsEndRef = useRef7(null);
|
|
4905
5027
|
useEffect8(() => {
|
|
4906
5028
|
setDescription((data == null ? void 0 : data.description) ?? "");
|
|
@@ -5042,7 +5164,7 @@ function AncestryRelationshipPanel({
|
|
|
5042
5164
|
}
|
|
5043
5165
|
|
|
5044
5166
|
// src/components/CreateAncestryPanel.jsx
|
|
5045
|
-
import React10, { useState as
|
|
5167
|
+
import React10, { useState as useState11, useEffect as useEffect10, useMemo as useMemo8, useRef as useRef8, useCallback as useCallback2 } from "react";
|
|
5046
5168
|
import {
|
|
5047
5169
|
FiEdit2 as FiEdit23,
|
|
5048
5170
|
FiBookOpen as FiBookOpen2,
|
|
@@ -5062,7 +5184,7 @@ import {
|
|
|
5062
5184
|
} from "react-icons/fi";
|
|
5063
5185
|
|
|
5064
5186
|
// src/components/AncestryPickerModal.jsx
|
|
5065
|
-
import React9, { useState as
|
|
5187
|
+
import React9, { useState as useState10, useMemo as useMemo7, useEffect as useEffect9 } from "react";
|
|
5066
5188
|
import { FiSearch as FiSearch3, FiLayers as FiLayers4, FiCornerUpRight as FiCornerUpRight2 } from "react-icons/fi";
|
|
5067
5189
|
function AncestryPickerModal({
|
|
5068
5190
|
isOpen,
|
|
@@ -5072,7 +5194,7 @@ function AncestryPickerModal({
|
|
|
5072
5194
|
availableNodes = [],
|
|
5073
5195
|
currentAncestryId
|
|
5074
5196
|
}) {
|
|
5075
|
-
const [searchTerm, setSearchTerm] =
|
|
5197
|
+
const [searchTerm, setSearchTerm] = useState10("");
|
|
5076
5198
|
useEffect9(() => {
|
|
5077
5199
|
if (!isOpen) return;
|
|
5078
5200
|
const handleKeyDown = (e) => {
|
|
@@ -5157,7 +5279,7 @@ var NodeItem = ({ nodeData, onSelectParent, onViewSelect, highlightedPathIds = [
|
|
|
5157
5279
|
var _a, _b;
|
|
5158
5280
|
const itemId = nodeData.is_section ? nodeData.id : (_a = nodeData.node) == null ? void 0 : _a.id;
|
|
5159
5281
|
const itemName = nodeData.is_section ? nodeData.name : (_b = nodeData.node) == null ? void 0 : _b.name;
|
|
5160
|
-
const [isDragOver, setIsDragOver] =
|
|
5282
|
+
const [isDragOver, setIsDragOver] = useState11(false);
|
|
5161
5283
|
const isSelectedParent = String(selectedParentId) === String(itemId);
|
|
5162
5284
|
const isTargetViewNode = String(targetRenderNodeId) === String(itemId);
|
|
5163
5285
|
const isHighlightedPath = highlightedPathIds.includes(String(itemId));
|
|
@@ -5293,8 +5415,8 @@ function CreateAncestryPanel({
|
|
|
5293
5415
|
isAddingNodes,
|
|
5294
5416
|
currentAncestryId
|
|
5295
5417
|
} = ancestryMode;
|
|
5296
|
-
const [isSaving, setIsSaving] =
|
|
5297
|
-
const [isLinkCopied, setIsLinkCopied] =
|
|
5418
|
+
const [isSaving, setIsSaving] = useState11(false);
|
|
5419
|
+
const [isLinkCopied, setIsLinkCopied] = useState11(false);
|
|
5298
5420
|
const handleCopyLink = (e) => {
|
|
5299
5421
|
e.stopPropagation();
|
|
5300
5422
|
if (!currentAncestryId || currentAncestryId === "temp_root" || currentAncestryId === "temp_creating") {
|
|
@@ -5308,11 +5430,11 @@ function CreateAncestryPanel({
|
|
|
5308
5430
|
setTimeout(() => setIsLinkCopied(false), 2e3);
|
|
5309
5431
|
}).catch((err) => console.error("Erro ao copiar link:", err));
|
|
5310
5432
|
};
|
|
5311
|
-
const [isPickerOpen, setIsPickerOpen] =
|
|
5312
|
-
const [customProps, setCustomProps] =
|
|
5433
|
+
const [isPickerOpen, setIsPickerOpen] = useState11(false);
|
|
5434
|
+
const [customProps, setCustomProps] = useState11([]);
|
|
5313
5435
|
const propsEndRef = useRef8(null);
|
|
5314
|
-
const [branchStack, setBranchStack] =
|
|
5315
|
-
const [targetRenderNodeId, setTargetRenderNodeId] =
|
|
5436
|
+
const [branchStack, setBranchStack] = useState11([]);
|
|
5437
|
+
const [targetRenderNodeId, setTargetRenderNodeId] = useState11(null);
|
|
5316
5438
|
const highlightedPathIds = useMemo8(() => {
|
|
5317
5439
|
var _a, _b;
|
|
5318
5440
|
if (!targetRenderNodeId || !ancestryMode.abstraction_tree) return [];
|
|
@@ -5326,17 +5448,26 @@ function CreateAncestryPanel({
|
|
|
5326
5448
|
}
|
|
5327
5449
|
return ids;
|
|
5328
5450
|
}, [targetRenderNodeId, ancestryMode.abstraction_tree]);
|
|
5329
|
-
const [targetScrollSectionId, setTargetScrollSectionId] =
|
|
5330
|
-
const [internalHighlightedNodeId, setInternalHighlightedNodeId] =
|
|
5331
|
-
const [ancestryName, setAncestryName] =
|
|
5332
|
-
const [description, setDescription] =
|
|
5333
|
-
const [existingSections, setExistingSections] =
|
|
5334
|
-
const [isDescriptionModalOpen, setIsDescriptionModalOpen] =
|
|
5335
|
-
const [isReadMode, setIsReadMode] =
|
|
5451
|
+
const [targetScrollSectionId, setTargetScrollSectionId] = useState11(null);
|
|
5452
|
+
const [internalHighlightedNodeId, setInternalHighlightedNodeId] = useState11(null);
|
|
5453
|
+
const [ancestryName, setAncestryName] = useState11(initialName);
|
|
5454
|
+
const [description, setDescription] = useState11(initialDescription || "");
|
|
5455
|
+
const [existingSections, setExistingSections] = useState11(initialSections || []);
|
|
5456
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState11(false);
|
|
5457
|
+
const [isReadMode, setIsReadMode] = useState11(false);
|
|
5458
|
+
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
5459
|
+
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
5460
|
+
initialWidth: isReadMode ? 700 : 440,
|
|
5461
|
+
minWidth: 320,
|
|
5462
|
+
maxWidth: maxPanelW
|
|
5463
|
+
});
|
|
5464
|
+
useEffect10(() => {
|
|
5465
|
+
setWidth(isReadMode ? 700 : 440);
|
|
5466
|
+
}, [isReadMode, setWidth]);
|
|
5336
5467
|
const currentMaxRenderIndexRef = useRef8(0);
|
|
5337
5468
|
const branchProgressMapRef = useRef8({});
|
|
5338
|
-
const [lastSavedSnapshot, setLastSavedSnapshot] =
|
|
5339
|
-
const [isPrivate, setIsPrivate] =
|
|
5469
|
+
const [lastSavedSnapshot, setLastSavedSnapshot] = useState11(null);
|
|
5470
|
+
const [isPrivate, setIsPrivate] = useState11(ancestryMode.is_private || false);
|
|
5340
5471
|
const initializedContextIdRef = useRef8(null);
|
|
5341
5472
|
const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
|
|
5342
5473
|
const handleImageClickFromText = (url, name) => {
|
|
@@ -5355,7 +5486,7 @@ function CreateAncestryPanel({
|
|
|
5355
5486
|
}
|
|
5356
5487
|
setAncestryMode((prev) => isAbstraction ? { ...prev, isAddingAbstractionNodes: !prev.isAddingAbstractionNodes } : { ...prev, isAddingNodes: !prev.isAddingNodes });
|
|
5357
5488
|
};
|
|
5358
|
-
const handleRemoveNode =
|
|
5489
|
+
const handleRemoveNode = useCallback2((pathToRemove, isAbstraction = false) => {
|
|
5359
5490
|
if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) return;
|
|
5360
5491
|
const treeKey = isAbstraction ? "abstraction_tree" : "tree";
|
|
5361
5492
|
setAncestryMode((prev) => {
|
|
@@ -6311,10 +6442,8 @@ function CreateAncestryPanel({
|
|
|
6311
6442
|
return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(
|
|
6312
6443
|
"div",
|
|
6313
6444
|
{
|
|
6314
|
-
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 transition-all duration-300 ease-out
|
|
6315
|
-
|
|
6316
|
-
`,
|
|
6317
|
-
style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)" },
|
|
6445
|
+
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 ${isResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
|
|
6446
|
+
style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${panelWidth}px`, maxWidth: "92vw" },
|
|
6318
6447
|
onPointerDown: swallow,
|
|
6319
6448
|
onPointerMove: swallow,
|
|
6320
6449
|
onPointerUp: swallow,
|
|
@@ -6323,6 +6452,17 @@ function CreateAncestryPanel({
|
|
|
6323
6452
|
onContextMenu: swallow,
|
|
6324
6453
|
onDoubleClick: swallow
|
|
6325
6454
|
},
|
|
6455
|
+
/* @__PURE__ */ React10.createElement(
|
|
6456
|
+
"div",
|
|
6457
|
+
{
|
|
6458
|
+
onPointerDown: (e) => {
|
|
6459
|
+
e.stopPropagation();
|
|
6460
|
+
handleResize(e);
|
|
6461
|
+
},
|
|
6462
|
+
className: "absolute left-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-indigo-500/50 z-[2000] transition-colors",
|
|
6463
|
+
title: "Arraste para redimensionar"
|
|
6464
|
+
}
|
|
6465
|
+
),
|
|
6326
6466
|
isReadMode ? /* @__PURE__ */ React10.createElement(
|
|
6327
6467
|
DescriptionReadModePanel,
|
|
6328
6468
|
{
|
|
@@ -6619,25 +6759,25 @@ function CreateAncestryPanel({
|
|
|
6619
6759
|
}
|
|
6620
6760
|
|
|
6621
6761
|
// src/components/ImageViewer.jsx
|
|
6622
|
-
import React11, { useState as
|
|
6762
|
+
import React11, { useState as useState12, useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useCallback as useCallback3 } from "react";
|
|
6623
6763
|
import { FiX as FiX2, FiChevronLeft as FiChevronLeft3, FiChevronRight as FiChevronRight5 } from "react-icons/fi";
|
|
6624
6764
|
function ImageViewer({ data, onClose }) {
|
|
6625
6765
|
var _a;
|
|
6626
6766
|
const { images = [], startIndex = 0, visible } = data;
|
|
6627
|
-
const [currentIndex, setCurrentIndex] =
|
|
6628
|
-
const [isLoading, setIsLoading] =
|
|
6629
|
-
const [loadedSrc, setLoadedSrc] =
|
|
6767
|
+
const [currentIndex, setCurrentIndex] = useState12(startIndex);
|
|
6768
|
+
const [isLoading, setIsLoading] = useState12(false);
|
|
6769
|
+
const [loadedSrc, setLoadedSrc] = useState12(null);
|
|
6630
6770
|
useLayoutEffect2(() => {
|
|
6631
6771
|
if (visible) {
|
|
6632
6772
|
setCurrentIndex(startIndex);
|
|
6633
6773
|
}
|
|
6634
6774
|
}, [visible, startIndex]);
|
|
6635
|
-
const handleNext =
|
|
6775
|
+
const handleNext = useCallback3(() => {
|
|
6636
6776
|
if (images.length > 1) {
|
|
6637
6777
|
setCurrentIndex((prev) => (prev + 1) % images.length);
|
|
6638
6778
|
}
|
|
6639
6779
|
}, [images.length]);
|
|
6640
|
-
const handlePrev =
|
|
6780
|
+
const handlePrev = useCallback3(() => {
|
|
6641
6781
|
if (images.length > 1) {
|
|
6642
6782
|
setCurrentIndex((prev) => (prev - 1 + images.length) % images.length);
|
|
6643
6783
|
}
|
|
@@ -6742,10 +6882,10 @@ function ImageViewer({ data, onClose }) {
|
|
|
6742
6882
|
}
|
|
6743
6883
|
|
|
6744
6884
|
// src/components/InSceneCreationForm.jsx
|
|
6745
|
-
import React13, { useState as
|
|
6885
|
+
import React13, { useState as useState14, useEffect as useEffect13, useRef as useRef10 } from "react";
|
|
6746
6886
|
|
|
6747
6887
|
// src/components/ColorPicker.jsx
|
|
6748
|
-
import React12, { useState as
|
|
6888
|
+
import React12, { useState as useState13, useEffect as useEffect12, useRef as useRef9 } from "react";
|
|
6749
6889
|
import { HexColorPicker } from "react-colorful";
|
|
6750
6890
|
import { FiHash, FiCheck as FiCheck6 } from "react-icons/fi";
|
|
6751
6891
|
var PRESET_COLORS = [
|
|
@@ -6766,7 +6906,7 @@ var PRESET_COLORS = [
|
|
|
6766
6906
|
"#000000"
|
|
6767
6907
|
];
|
|
6768
6908
|
function ColorPicker({ color, onChange, disabled }) {
|
|
6769
|
-
const [isOpen, setIsOpen] =
|
|
6909
|
+
const [isOpen, setIsOpen] = useState13(false);
|
|
6770
6910
|
const popoverRef = useRef9(null);
|
|
6771
6911
|
useEffect12(() => {
|
|
6772
6912
|
const handleClickOutside = (event) => {
|
|
@@ -6865,21 +7005,21 @@ function InSceneCreationForm({
|
|
|
6865
7005
|
viewType
|
|
6866
7006
|
}) {
|
|
6867
7007
|
var _a;
|
|
6868
|
-
const [name, setName] =
|
|
6869
|
-
const [types, setTypes] =
|
|
6870
|
-
const [typeInput, setTypeInput] =
|
|
6871
|
-
const [color, setColor] =
|
|
6872
|
-
const [size, setSize] =
|
|
6873
|
-
const [intensity, setIntensity] =
|
|
6874
|
-
const [description, setDescription] =
|
|
6875
|
-
const [customProps, setCustomProps] =
|
|
6876
|
-
const [showTypeSuggestions, setShowTypeSuggestions] =
|
|
6877
|
-
const [filteredTypes, setFilteredTypes] =
|
|
6878
|
-
const [isDescriptionModalOpen, setIsDescriptionModalOpen] =
|
|
6879
|
-
const [useImageAsTexture, setUseImageAsTexture] =
|
|
6880
|
-
const [selectedImageUrl, setSelectedImageUrl] =
|
|
6881
|
-
const [targetDatasetId, setTargetDatasetId] =
|
|
6882
|
-
const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] =
|
|
7008
|
+
const [name, setName] = useState14("");
|
|
7009
|
+
const [types, setTypes] = useState14([]);
|
|
7010
|
+
const [typeInput, setTypeInput] = useState14("");
|
|
7011
|
+
const [color, setColor] = useState14(initialColor || "#cccccc");
|
|
7012
|
+
const [size, setSize] = useState14("medium");
|
|
7013
|
+
const [intensity, setIntensity] = useState14(0);
|
|
7014
|
+
const [description, setDescription] = useState14("");
|
|
7015
|
+
const [customProps, setCustomProps] = useState14([]);
|
|
7016
|
+
const [showTypeSuggestions, setShowTypeSuggestions] = useState14(false);
|
|
7017
|
+
const [filteredTypes, setFilteredTypes] = useState14([]);
|
|
7018
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState14(false);
|
|
7019
|
+
const [useImageAsTexture, setUseImageAsTexture] = useState14(false);
|
|
7020
|
+
const [selectedImageUrl, setSelectedImageUrl] = useState14(null);
|
|
7021
|
+
const [targetDatasetId, setTargetDatasetId] = useState14(sourceNodeDatasetId || "");
|
|
7022
|
+
const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] = useState14(false);
|
|
6883
7023
|
const datasetDropdownRef = useRef10(null);
|
|
6884
7024
|
useEffect13(() => {
|
|
6885
7025
|
if (sourceNodeDatasetId) setTargetDatasetId(sourceNodeDatasetId);
|
|
@@ -7212,7 +7352,7 @@ function InSceneCreationForm({
|
|
|
7212
7352
|
}
|
|
7213
7353
|
|
|
7214
7354
|
// src/components/InSceneVersionForm.jsx
|
|
7215
|
-
import React14, { useState as
|
|
7355
|
+
import React14, { useState as useState15, useEffect as useEffect14, useRef as useRef11 } from "react";
|
|
7216
7356
|
import { FiPlus as FiPlus4, FiMaximize2 as FiMaximize22, FiCheck as FiCheck8, FiEdit2 as FiEdit25 } from "react-icons/fi";
|
|
7217
7357
|
function InSceneVersionForm({
|
|
7218
7358
|
onSave,
|
|
@@ -7230,14 +7370,14 @@ function InSceneVersionForm({
|
|
|
7230
7370
|
onMentionClick,
|
|
7231
7371
|
onUploadFile
|
|
7232
7372
|
}) {
|
|
7233
|
-
const [name, setName] =
|
|
7234
|
-
const [size, setSize] =
|
|
7235
|
-
const [description, setDescription] =
|
|
7236
|
-
const [customProps, setCustomProps] =
|
|
7237
|
-
const [isDescriptionModalOpen, setIsDescriptionModalOpen] =
|
|
7373
|
+
const [name, setName] = useState15("");
|
|
7374
|
+
const [size, setSize] = useState15("medium");
|
|
7375
|
+
const [description, setDescription] = useState15("");
|
|
7376
|
+
const [customProps, setCustomProps] = useState15([{ id: v4_default(), key: "Date", type: "date", value: { type: "Data", value: "" }, isEditing: true }]);
|
|
7377
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState15(false);
|
|
7238
7378
|
const propsEndRef = useRef11(null);
|
|
7239
|
-
const [useImageAsTexture, setUseImageAsTexture] =
|
|
7240
|
-
const [selectedImageUrl, setSelectedImageUrl] =
|
|
7379
|
+
const [useImageAsTexture, setUseImageAsTexture] = useState15(false);
|
|
7380
|
+
const [selectedImageUrl, setSelectedImageUrl] = useState15(null);
|
|
7241
7381
|
const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
|
|
7242
7382
|
useEffect14(() => {
|
|
7243
7383
|
if (!hasImages && useImageAsTexture) {
|
|
@@ -7430,7 +7570,7 @@ function InSceneVersionForm({
|
|
|
7430
7570
|
}
|
|
7431
7571
|
|
|
7432
7572
|
// src/components/NodeDetailsPanel.jsx
|
|
7433
|
-
import React15, { useState as
|
|
7573
|
+
import React15, { useState as useState16, useEffect as useEffect15, useRef as useRef12 } from "react";
|
|
7434
7574
|
import { FiPlus as FiPlus5, FiMaximize2 as FiMaximize23, FiX as FiX4, FiCheck as FiCheck9, FiImage as FiImage3, FiEdit2 as FiEdit26, FiLoader as FiLoader2, FiBookOpen as FiBookOpen3, FiSun as FiSun2, FiLink as FiLink5, FiDatabase } from "react-icons/fi";
|
|
7435
7575
|
function NodeDetailsPanel({
|
|
7436
7576
|
node,
|
|
@@ -7452,27 +7592,36 @@ function NodeDetailsPanel({
|
|
|
7452
7592
|
userRole,
|
|
7453
7593
|
currentDatasetName
|
|
7454
7594
|
}) {
|
|
7455
|
-
const [name, setName] =
|
|
7456
|
-
const [types, setTypes] =
|
|
7457
|
-
const [typeInput, setTypeInput] =
|
|
7458
|
-
const [color, setColor] =
|
|
7459
|
-
const [size, setSize] =
|
|
7460
|
-
const [description, setDescription] =
|
|
7461
|
-
const [intensity, setIntensity] =
|
|
7462
|
-
const [customProps, setCustomProps] =
|
|
7463
|
-
const [showTypeSuggestions, setShowTypeSuggestions] =
|
|
7464
|
-
const [filteredTypes, setFilteredTypes] =
|
|
7465
|
-
const [isDescriptionModalOpen, setIsDescriptionModalOpen] =
|
|
7466
|
-
const [isReadMode, setIsReadMode] =
|
|
7467
|
-
const [existingSections, setExistingSections] =
|
|
7468
|
-
const [isSaving, setIsSaving] =
|
|
7469
|
-
const [isLinkCopied, setIsLinkCopied] =
|
|
7470
|
-
const [useImageAsTexture, setUseImageAsTexture] =
|
|
7595
|
+
const [name, setName] = useState16((node == null ? void 0 : node.name) ?? "");
|
|
7596
|
+
const [types, setTypes] = useState16([]);
|
|
7597
|
+
const [typeInput, setTypeInput] = useState16("");
|
|
7598
|
+
const [color, setColor] = useState16((node == null ? void 0 : node.color) ?? "#8b5cf6");
|
|
7599
|
+
const [size, setSize] = useState16((node == null ? void 0 : node.size) ?? "medium");
|
|
7600
|
+
const [description, setDescription] = useState16((node == null ? void 0 : node.description) ?? "");
|
|
7601
|
+
const [intensity, setIntensity] = useState16((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
|
|
7602
|
+
const [customProps, setCustomProps] = useState16(() => extractCustomPropsFromNode(node || {}));
|
|
7603
|
+
const [showTypeSuggestions, setShowTypeSuggestions] = useState16(false);
|
|
7604
|
+
const [filteredTypes, setFilteredTypes] = useState16([]);
|
|
7605
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState16(false);
|
|
7606
|
+
const [isReadMode, setIsReadMode] = useState16(false);
|
|
7607
|
+
const [existingSections, setExistingSections] = useState16((node == null ? void 0 : node.description_sections) || []);
|
|
7608
|
+
const [isSaving, setIsSaving] = useState16(false);
|
|
7609
|
+
const [isLinkCopied, setIsLinkCopied] = useState16(false);
|
|
7610
|
+
const [useImageAsTexture, setUseImageAsTexture] = useState16(() => {
|
|
7471
7611
|
if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
|
|
7472
7612
|
if ((node == null ? void 0 : node.useImageAsTexture) === "false") return false;
|
|
7473
7613
|
return !!(node == null ? void 0 : node.useImageAsTexture);
|
|
7474
7614
|
});
|
|
7475
|
-
const [selectedImageUrl, setSelectedImageUrl] =
|
|
7615
|
+
const [selectedImageUrl, setSelectedImageUrl] = useState16((node == null ? void 0 : node.textureImageUrl) ?? null);
|
|
7616
|
+
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
7617
|
+
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
7618
|
+
initialWidth: isReadMode ? 700 : 440,
|
|
7619
|
+
minWidth: 320,
|
|
7620
|
+
maxWidth: maxPanelW
|
|
7621
|
+
});
|
|
7622
|
+
useEffect15(() => {
|
|
7623
|
+
setWidth(isReadMode ? 700 : 440);
|
|
7624
|
+
}, [isReadMode, setWidth]);
|
|
7476
7625
|
const prevNodeIdRef = useRef12(null);
|
|
7477
7626
|
const propsEndRef = useRef12(null);
|
|
7478
7627
|
const canEdit = userRole !== "viewer";
|
|
@@ -7625,6 +7774,11 @@ function NodeDetailsPanel({
|
|
|
7625
7774
|
textureImageUrl: url
|
|
7626
7775
|
});
|
|
7627
7776
|
};
|
|
7777
|
+
const handleSaveDescriptionInline = (newDescription) => {
|
|
7778
|
+
setDescription(newDescription);
|
|
7779
|
+
onDataUpdate({ ...node, description: newDescription });
|
|
7780
|
+
triggerAutoSave({ description: newDescription });
|
|
7781
|
+
};
|
|
7628
7782
|
const handleSave = async (keepOpen = false, overrides = {}) => {
|
|
7629
7783
|
const currentName = overrides.name !== void 0 ? overrides.name : name;
|
|
7630
7784
|
const currentTypes = overrides.types !== void 0 ? overrides.types : types;
|
|
@@ -7680,10 +7834,8 @@ function NodeDetailsPanel({
|
|
|
7680
7834
|
return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(
|
|
7681
7835
|
"div",
|
|
7682
7836
|
{
|
|
7683
|
-
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 transition-all duration-300 ease-out
|
|
7684
|
-
|
|
7685
|
-
`,
|
|
7686
|
-
style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)" },
|
|
7837
|
+
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 ${isResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
|
|
7838
|
+
style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${panelWidth}px`, maxWidth: "92vw" },
|
|
7687
7839
|
onPointerDown: swallow,
|
|
7688
7840
|
onPointerMove: swallow,
|
|
7689
7841
|
onPointerUp: swallow,
|
|
@@ -7692,6 +7844,17 @@ function NodeDetailsPanel({
|
|
|
7692
7844
|
onContextMenu: swallow,
|
|
7693
7845
|
onDoubleClick: swallow
|
|
7694
7846
|
},
|
|
7847
|
+
/* @__PURE__ */ React15.createElement(
|
|
7848
|
+
"div",
|
|
7849
|
+
{
|
|
7850
|
+
onPointerDown: (e) => {
|
|
7851
|
+
e.stopPropagation();
|
|
7852
|
+
handleResize(e);
|
|
7853
|
+
},
|
|
7854
|
+
className: "absolute left-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-indigo-500/50 z-[2000] transition-colors",
|
|
7855
|
+
title: "Arraste para redimensionar"
|
|
7856
|
+
}
|
|
7857
|
+
),
|
|
7695
7858
|
isReadMode ? /* @__PURE__ */ React15.createElement(
|
|
7696
7859
|
DescriptionReadModePanel,
|
|
7697
7860
|
{
|
|
@@ -7710,7 +7873,8 @@ function NodeDetailsPanel({
|
|
|
7710
7873
|
availableAncestries,
|
|
7711
7874
|
onOpenReference,
|
|
7712
7875
|
onMentionClick,
|
|
7713
|
-
onImageClick: handleImageClickFromText
|
|
7876
|
+
onImageClick: handleImageClickFromText,
|
|
7877
|
+
onSaveDescription: handleSaveDescriptionInline
|
|
7714
7878
|
}
|
|
7715
7879
|
) : /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ React15.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React15.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ React15.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node"), /* @__PURE__ */ React15.createElement(
|
|
7716
7880
|
"button",
|
|
@@ -7778,7 +7942,8 @@ function NodeDetailsPanel({
|
|
|
7778
7942
|
availableAncestries,
|
|
7779
7943
|
onOpenReference,
|
|
7780
7944
|
onMentionClick,
|
|
7781
|
-
onImageClick: handleImageClickFromText
|
|
7945
|
+
onImageClick: handleImageClickFromText,
|
|
7946
|
+
onSaveDescription: handleSaveDescriptionInline
|
|
7782
7947
|
}
|
|
7783
7948
|
), /* @__PURE__ */ React15.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ React15.createElement(
|
|
7784
7949
|
"button",
|
|
@@ -7893,7 +8058,7 @@ function NodeDetailsPanel({
|
|
|
7893
8058
|
}
|
|
7894
8059
|
|
|
7895
8060
|
// src/components/MultiNodeContextMenu.jsx
|
|
7896
|
-
import React16, { useLayoutEffect as useLayoutEffect3, useRef as useRef13, useState as
|
|
8061
|
+
import React16, { useLayoutEffect as useLayoutEffect3, useRef as useRef13, useState as useState17, useEffect as useEffect16 } from "react";
|
|
7897
8062
|
function MultiNodeContextMenu({
|
|
7898
8063
|
data,
|
|
7899
8064
|
userRole,
|
|
@@ -7904,7 +8069,7 @@ function MultiNodeContextMenu({
|
|
|
7904
8069
|
onDeleteNodes
|
|
7905
8070
|
}) {
|
|
7906
8071
|
const menuRef = useRef13(null);
|
|
7907
|
-
const [menuPos, setMenuPos] =
|
|
8072
|
+
const [menuPos, setMenuPos] = useState17({ left: 0, top: 0 });
|
|
7908
8073
|
const ability = defineAbilityFor(userRole);
|
|
7909
8074
|
const canDelete = ability.can("delete", "Node");
|
|
7910
8075
|
useLayoutEffect3(() => {
|
|
@@ -7953,7 +8118,7 @@ function MultiNodeContextMenu({
|
|
|
7953
8118
|
}
|
|
7954
8119
|
|
|
7955
8120
|
// src/components/RelationshipDetailsPanel.jsx
|
|
7956
|
-
import React17, { useState as
|
|
8121
|
+
import React17, { useState as useState18, useEffect as useEffect17, useRef as useRef14, useMemo as useMemo9 } from "react";
|
|
7957
8122
|
import { FiPlus as FiPlus6, FiEdit2 as FiEdit27, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4 } from "react-icons/fi";
|
|
7958
8123
|
function RelationshipDetailsPanel({
|
|
7959
8124
|
link,
|
|
@@ -7969,13 +8134,13 @@ function RelationshipDetailsPanel({
|
|
|
7969
8134
|
userRole
|
|
7970
8135
|
// Recebendo userRole via props
|
|
7971
8136
|
}) {
|
|
7972
|
-
const [name, setName] =
|
|
7973
|
-
const [description, setDescription] =
|
|
7974
|
-
const [customProps, setCustomProps] =
|
|
7975
|
-
const [existingSections, setExistingSections] =
|
|
7976
|
-
const [isDescriptionModalOpen, setIsDescriptionModalOpen] =
|
|
7977
|
-
const [isSaving, setIsSaving] =
|
|
7978
|
-
const [isReadMode, setIsReadMode] =
|
|
8137
|
+
const [name, setName] = useState18((link == null ? void 0 : link.name) ?? "");
|
|
8138
|
+
const [description, setDescription] = useState18((link == null ? void 0 : link.description) ?? "");
|
|
8139
|
+
const [customProps, setCustomProps] = useState18(() => extractCustomPropsFromNode(link || {}));
|
|
8140
|
+
const [existingSections, setExistingSections] = useState18((link == null ? void 0 : link.description_sections) || []);
|
|
8141
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState18(false);
|
|
8142
|
+
const [isSaving, setIsSaving] = useState18(false);
|
|
8143
|
+
const [isReadMode, setIsReadMode] = useState18(false);
|
|
7979
8144
|
const propsEndRef = useRef14(null);
|
|
7980
8145
|
const canEdit = useMemo9(() => {
|
|
7981
8146
|
const ability = defineAbilityFor(userRole);
|
|
@@ -8178,7 +8343,7 @@ function RelationshipDetailsPanel({
|
|
|
8178
8343
|
}
|
|
8179
8344
|
|
|
8180
8345
|
// src/components/RelationshipContextMenu.jsx
|
|
8181
|
-
import React18, { useLayoutEffect as useLayoutEffect4, useRef as useRef15, useState as
|
|
8346
|
+
import React18, { useLayoutEffect as useLayoutEffect4, useRef as useRef15, useState as useState19, useEffect as useEffect18, useMemo as useMemo10 } from "react";
|
|
8182
8347
|
function RelationshipContextMenu({
|
|
8183
8348
|
data,
|
|
8184
8349
|
userRole,
|
|
@@ -8190,7 +8355,7 @@ function RelationshipContextMenu({
|
|
|
8190
8355
|
onClose
|
|
8191
8356
|
}) {
|
|
8192
8357
|
const menuRef = useRef15(null);
|
|
8193
|
-
const [menuPos, setMenuPos] =
|
|
8358
|
+
const [menuPos, setMenuPos] = useState19({ left: 0, top: 0 });
|
|
8194
8359
|
const ability = useMemo10(() => defineAbilityFor(userRole), [userRole]);
|
|
8195
8360
|
const sourceName = useMemo10(
|
|
8196
8361
|
() => {
|
|
@@ -8392,7 +8557,7 @@ function LoadingScreen() {
|
|
|
8392
8557
|
}
|
|
8393
8558
|
|
|
8394
8559
|
// src/components/ImportParentFileModal.jsx
|
|
8395
|
-
import React20, { useEffect as useEffect19, useState as
|
|
8560
|
+
import React20, { useEffect as useEffect19, useState as useState20 } from "react";
|
|
8396
8561
|
function ImportParentFileModal({
|
|
8397
8562
|
isOpen,
|
|
8398
8563
|
onClose,
|
|
@@ -8403,11 +8568,11 @@ function ImportParentFileModal({
|
|
|
8403
8568
|
onFetchAvailableFiles,
|
|
8404
8569
|
currentViewName
|
|
8405
8570
|
}) {
|
|
8406
|
-
const [activeTab, setActiveTab] =
|
|
8407
|
-
const [availableDbs, setAvailableDbs] =
|
|
8408
|
-
const [availableViews, setAvailableViews] =
|
|
8409
|
-
const [selectedItem, setSelectedItem] =
|
|
8410
|
-
const [isLoading, setIsLoading] =
|
|
8571
|
+
const [activeTab, setActiveTab] = useState20("databases");
|
|
8572
|
+
const [availableDbs, setAvailableDbs] = useState20([]);
|
|
8573
|
+
const [availableViews, setAvailableViews] = useState20([]);
|
|
8574
|
+
const [selectedItem, setSelectedItem] = useState20(null);
|
|
8575
|
+
const [isLoading, setIsLoading] = useState20(false);
|
|
8411
8576
|
useEffect19(() => {
|
|
8412
8577
|
if (isOpen && session && onFetchAvailableFiles) {
|
|
8413
8578
|
const fetchData = async () => {
|
|
@@ -8553,7 +8718,7 @@ function ImportParentFileModal({
|
|
|
8553
8718
|
}
|
|
8554
8719
|
|
|
8555
8720
|
// src/components/AncestryLinkDetailsPanel.jsx
|
|
8556
|
-
import React21, { useState as
|
|
8721
|
+
import React21, { useState as useState21 } from "react";
|
|
8557
8722
|
import { FiBookOpen as FiBookOpen5 } from "react-icons/fi";
|
|
8558
8723
|
function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile }) {
|
|
8559
8724
|
var _a, _b, _c, _d;
|
|
@@ -8563,7 +8728,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
8563
8728
|
const customProps = extractCustomPropsFromNode(relationshipData);
|
|
8564
8729
|
const sourceName = ((_b = (_a = data.sourceNode) == null ? void 0 : _a.userData) == null ? void 0 : _b.name) || "Origem";
|
|
8565
8730
|
const targetName = ((_d = (_c = data.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) || "Destino";
|
|
8566
|
-
const [isReadMode, setIsReadMode] =
|
|
8731
|
+
const [isReadMode, setIsReadMode] = useState21(false);
|
|
8567
8732
|
const swallow = (e) => e.stopPropagation();
|
|
8568
8733
|
const handleImageClickFromText = (url, name) => {
|
|
8569
8734
|
if (onOpenImageViewer) {
|
|
@@ -8629,7 +8794,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
8629
8794
|
}
|
|
8630
8795
|
|
|
8631
8796
|
// src/components/AncestryBoard.jsx
|
|
8632
|
-
import React22, { useState as
|
|
8797
|
+
import React22, { useState as useState22, useMemo as useMemo11, useEffect as useEffect20, useRef as useRef16 } from "react";
|
|
8633
8798
|
import {
|
|
8634
8799
|
FiSearch as FiSearch4,
|
|
8635
8800
|
FiLayers as FiLayers6,
|
|
@@ -8806,11 +8971,11 @@ function AncestryBoard({
|
|
|
8806
8971
|
userRole
|
|
8807
8972
|
// [NOVO] Recebe a role do usuário
|
|
8808
8973
|
}) {
|
|
8809
|
-
const [searchTerm, setSearchTerm] =
|
|
8810
|
-
const [groups, setGroups] =
|
|
8811
|
-
const [isLoaded, setIsLoaded] =
|
|
8812
|
-
const [pickingGroupId, setPickingGroupId] =
|
|
8813
|
-
const [saveStatus, setSaveStatus] =
|
|
8974
|
+
const [searchTerm, setSearchTerm] = useState22("");
|
|
8975
|
+
const [groups, setGroups] = useState22([]);
|
|
8976
|
+
const [isLoaded, setIsLoaded] = useState22(false);
|
|
8977
|
+
const [pickingGroupId, setPickingGroupId] = useState22(null);
|
|
8978
|
+
const [saveStatus, setSaveStatus] = useState22("idle");
|
|
8814
8979
|
const canEdit = useMemo11(() => {
|
|
8815
8980
|
return userRole !== "viewer";
|
|
8816
8981
|
}, [userRole]);
|
|
@@ -9260,37 +9425,37 @@ function XViewScene({
|
|
|
9260
9425
|
const sceneDataRef = useRef17(null);
|
|
9261
9426
|
const parentDataRef = useRef17(null);
|
|
9262
9427
|
const ancestryDataRef = useRef17(null);
|
|
9263
|
-
const [isLoading, setIsLoading] =
|
|
9264
|
-
const [permissionStatus, setPermissionStatus] =
|
|
9265
|
-
const [userPermissionRole, setUserPermissionRole] =
|
|
9266
|
-
const [isInitialized, setIsInitialized] =
|
|
9267
|
-
const [sceneVersion, setSceneVersion] =
|
|
9268
|
-
const [contextMenu, setContextMenu] =
|
|
9269
|
-
const [multiContextMenu, setMultiContextMenu] =
|
|
9270
|
-
const [relationshipMenu, setRelationshipMenu] =
|
|
9271
|
-
const [creationMode, setCreationMode] =
|
|
9272
|
-
const [versionMode, setVersionMode] =
|
|
9273
|
-
const [hasFocusedInitial, setHasFocusedInitial] =
|
|
9274
|
-
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] =
|
|
9275
|
-
const [ancestryMode, setAncestryMode] =
|
|
9276
|
-
const [readingMode, setReadingMode] =
|
|
9428
|
+
const [isLoading, setIsLoading] = useState23(true);
|
|
9429
|
+
const [permissionStatus, setPermissionStatus] = useState23("loading");
|
|
9430
|
+
const [userPermissionRole, setUserPermissionRole] = useState23(null);
|
|
9431
|
+
const [isInitialized, setIsInitialized] = useState23(false);
|
|
9432
|
+
const [sceneVersion, setSceneVersion] = useState23(0);
|
|
9433
|
+
const [contextMenu, setContextMenu] = useState23({ visible: false, x: 0, y: 0, nodeData: null });
|
|
9434
|
+
const [multiContextMenu, setMultiContextMenu] = useState23({ visible: false, x: 0, y: 0, nodeIds: null });
|
|
9435
|
+
const [relationshipMenu, setRelationshipMenu] = useState23({ visible: false, x: 0, y: 0, linkObject: null });
|
|
9436
|
+
const [creationMode, setCreationMode] = useState23({ isActive: false, sourceNodeData: null });
|
|
9437
|
+
const [versionMode, setVersionMode] = useState23({ isActive: false, sourceNodeData: null });
|
|
9438
|
+
const [hasFocusedInitial, setHasFocusedInitial] = useState23(false);
|
|
9439
|
+
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState23(false);
|
|
9440
|
+
const [ancestryMode, setAncestryMode] = useState23({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
|
|
9441
|
+
const [readingMode, setReadingMode] = useState23({
|
|
9277
9442
|
isActive: false,
|
|
9278
9443
|
ancestry: null,
|
|
9279
9444
|
branchStack: [],
|
|
9280
9445
|
autoAbstraction: false
|
|
9281
9446
|
});
|
|
9282
|
-
const [formPosition, setFormPosition] =
|
|
9283
|
-
const [detailsNode, setDetailsNode] =
|
|
9284
|
-
const [detailsLink, setDetailsLink] =
|
|
9285
|
-
const [ancestryLinkDetails, setAncestryLinkDetails] =
|
|
9286
|
-
const [imageViewer, setImageViewer] =
|
|
9287
|
-
const [editingAncestryRel, setEditingAncestryRel] =
|
|
9288
|
-
const [isImportModalOpen, setIsImportModalOpen] =
|
|
9289
|
-
const [importSuccessMessage, setImportSuccessMessage] =
|
|
9290
|
-
const [highlightedNodeId, setHighlightedNodeId] =
|
|
9291
|
-
const [isAncestryBoardOpen, setIsAncestryBoardOpen] =
|
|
9292
|
-
const [ancestryBoardData, setAncestryBoardData] =
|
|
9293
|
-
const [isSidebarOpen, setIsSidebarOpen] =
|
|
9447
|
+
const [formPosition, setFormPosition] = useState23({ left: 16, top: 16, opacity: 0 });
|
|
9448
|
+
const [detailsNode, setDetailsNode] = useState23(null);
|
|
9449
|
+
const [detailsLink, setDetailsLink] = useState23(null);
|
|
9450
|
+
const [ancestryLinkDetails, setAncestryLinkDetails] = useState23(null);
|
|
9451
|
+
const [imageViewer, setImageViewer] = useState23({ visible: false, images: [], startIndex: 0 });
|
|
9452
|
+
const [editingAncestryRel, setEditingAncestryRel] = useState23({ visible: false, data: null, path: null });
|
|
9453
|
+
const [isImportModalOpen, setIsImportModalOpen] = useState23(false);
|
|
9454
|
+
const [importSuccessMessage, setImportSuccessMessage] = useState23("");
|
|
9455
|
+
const [highlightedNodeId, setHighlightedNodeId] = useState23(null);
|
|
9456
|
+
const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState23(false);
|
|
9457
|
+
const [ancestryBoardData, setAncestryBoardData] = useState23([]);
|
|
9458
|
+
const [isSidebarOpen, setIsSidebarOpen] = useState23(false);
|
|
9294
9459
|
const mountRef = useRef17(null);
|
|
9295
9460
|
const tooltipRef = useRef17(null);
|
|
9296
9461
|
const formRef = useRef17(null);
|
|
@@ -9333,6 +9498,12 @@ function XViewScene({
|
|
|
9333
9498
|
lastDescriptionLength: 0,
|
|
9334
9499
|
highlightedNodeId: null
|
|
9335
9500
|
});
|
|
9501
|
+
const maxReadPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
9502
|
+
const { width: readModeWidth, isResizing: isReadModeResizing, handlePointerDown: handleReadModeResize } = useResizablePanel({
|
|
9503
|
+
initialWidth: 700,
|
|
9504
|
+
minWidth: 320,
|
|
9505
|
+
maxWidth: maxReadPanelW
|
|
9506
|
+
});
|
|
9336
9507
|
useEffect21(() => {
|
|
9337
9508
|
stateRef.current.ancestry = ancestryMode;
|
|
9338
9509
|
}, [ancestryMode]);
|
|
@@ -9357,10 +9528,10 @@ function XViewScene({
|
|
|
9357
9528
|
}
|
|
9358
9529
|
stateRef.current.nodeIdToParentFileMap = map;
|
|
9359
9530
|
}, [isInitialized, sceneVersion]);
|
|
9360
|
-
const handleNavigateBack =
|
|
9531
|
+
const handleNavigateBack = useCallback4(() => {
|
|
9361
9532
|
router.push("/dashboard/scenes");
|
|
9362
9533
|
}, [router]);
|
|
9363
|
-
const handleConfirmImport =
|
|
9534
|
+
const handleConfirmImport = useCallback4(
|
|
9364
9535
|
async (importPayload) => {
|
|
9365
9536
|
var _a2, _b2;
|
|
9366
9537
|
let files = [];
|
|
@@ -9408,7 +9579,6 @@ function XViewScene({
|
|
|
9408
9579
|
if (ancestryResponse.success && Array.isArray(ancestryResponse.data)) {
|
|
9409
9580
|
const viewSpecificAncestries = ancestryResponse.data.filter(
|
|
9410
9581
|
(anc) => anc._source_file_id === viewToImport.id && !anc.is_private
|
|
9411
|
-
// <--- AQUI ESTÁ A TRAVA DE SEGURANÇA
|
|
9412
9582
|
);
|
|
9413
9583
|
const processedAncestries = viewSpecificAncestries.map((anc) => ({
|
|
9414
9584
|
...anc,
|
|
@@ -9459,7 +9629,7 @@ function XViewScene({
|
|
|
9459
9629
|
const handleOpenImageViewer = (images, startIndex) => {
|
|
9460
9630
|
setImageViewer({ visible: true, images, startIndex });
|
|
9461
9631
|
};
|
|
9462
|
-
const tweenToTarget =
|
|
9632
|
+
const tweenToTarget = useCallback4((target, zoomFactor = 1, forcedDirection = null) => {
|
|
9463
9633
|
const { camera, controls, tweenGroup } = stateRef.current;
|
|
9464
9634
|
if (!camera || !controls || !tweenGroup) return;
|
|
9465
9635
|
const targetPos = target instanceof THREE3.Mesh ? target.getWorldPosition(new THREE3.Vector3()) : target;
|
|
@@ -9482,7 +9652,7 @@ function XViewScene({
|
|
|
9482
9652
|
if (!t || typeof t.closest !== "function") return false;
|
|
9483
9653
|
return !!t.closest(".ui-overlay");
|
|
9484
9654
|
};
|
|
9485
|
-
const buildFullAncestryTree =
|
|
9655
|
+
const buildFullAncestryTree = useCallback4((idTree, nodes, ancestries = []) => {
|
|
9486
9656
|
if (!idTree) return null;
|
|
9487
9657
|
const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
|
|
9488
9658
|
const ancestryMap = new Map(ancestries.map((a) => [String(a.ancestry_id), a]));
|
|
@@ -9508,14 +9678,10 @@ function XViewScene({
|
|
|
9508
9678
|
return {
|
|
9509
9679
|
...branch,
|
|
9510
9680
|
name: linkedAncestry.name,
|
|
9511
|
-
// Sobrescreve nome para exibição
|
|
9512
9681
|
description: linkedAncestry.description,
|
|
9513
|
-
// Sobrescreve descrição
|
|
9514
9682
|
description_sections: linkedAncestry.description_sections,
|
|
9515
9683
|
tree: graftedTree,
|
|
9516
|
-
// ENXERTA A ÁRVORE AQUI
|
|
9517
9684
|
isLinked: true
|
|
9518
|
-
// Flag útil
|
|
9519
9685
|
};
|
|
9520
9686
|
}
|
|
9521
9687
|
}
|
|
@@ -9562,7 +9728,7 @@ function XViewScene({
|
|
|
9562
9728
|
}
|
|
9563
9729
|
return recursiveBuild(idTree);
|
|
9564
9730
|
}, []);
|
|
9565
|
-
const handleActivateTimeline =
|
|
9731
|
+
const handleActivateTimeline = useCallback4(() => {
|
|
9566
9732
|
const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
9567
9733
|
if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
|
|
9568
9734
|
while (timelineIntervalsGroup.children.length > 0) {
|
|
@@ -9715,7 +9881,7 @@ function XViewScene({
|
|
|
9715
9881
|
}
|
|
9716
9882
|
});
|
|
9717
9883
|
}, []);
|
|
9718
|
-
const handleVersionTimeline =
|
|
9884
|
+
const handleVersionTimeline = useCallback4((sourceMesh, versionMeshes) => {
|
|
9719
9885
|
const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
9720
9886
|
if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0) return;
|
|
9721
9887
|
versionMeshes.forEach((mesh) => {
|
|
@@ -9908,16 +10074,14 @@ function XViewScene({
|
|
|
9908
10074
|
isInitialized,
|
|
9909
10075
|
permissionStatus,
|
|
9910
10076
|
focusNodeId,
|
|
9911
|
-
// <-- MANTIDO
|
|
9912
10077
|
focusAncestryId
|
|
9913
|
-
// <-- ADICIONADO O focusAncestryId NAS DEPENDÊNCIAS
|
|
9914
10078
|
]);
|
|
9915
|
-
const isNodeInView =
|
|
10079
|
+
const isNodeInView = useCallback4((id) => {
|
|
9916
10080
|
const key = String(id);
|
|
9917
10081
|
const objs = stateRef.current.nodeObjects || {};
|
|
9918
10082
|
return !!objs[key];
|
|
9919
10083
|
}, []);
|
|
9920
|
-
const addOrUpdateNodeMesh =
|
|
10084
|
+
const addOrUpdateNodeMesh = useCallback4((nodeData, position, suppressVersionUpdate = false) => {
|
|
9921
10085
|
const { graphGroup, nodeObjects, clickableNodes, glowTexture, tweenGroup } = stateRef.current;
|
|
9922
10086
|
const nodeId = String(nodeData.id);
|
|
9923
10087
|
if (nodeObjects[nodeId]) {
|
|
@@ -10566,7 +10730,7 @@ function XViewScene({
|
|
|
10566
10730
|
}
|
|
10567
10731
|
};
|
|
10568
10732
|
}, [isInitialized, tweenToTarget, dbSaveUrl, isNodeInView, addOrUpdateNodeMesh, handleActivateTimeline, get_scene_view_data, save_view_data]);
|
|
10569
|
-
const handleGhostNodeImageChange =
|
|
10733
|
+
const handleGhostNodeImageChange = useCallback4((useImage, imageUrl) => {
|
|
10570
10734
|
const { node: ghostNode, line: ghostLine, aura: ghostAura } = stateRef.current.ghostElements;
|
|
10571
10735
|
const { graphGroup, glowTexture } = stateRef.current;
|
|
10572
10736
|
if (!ghostNode || !graphGroup) return;
|
|
@@ -10608,7 +10772,7 @@ function XViewScene({
|
|
|
10608
10772
|
aura: newGhostNode.getObjectByName("aura")
|
|
10609
10773
|
};
|
|
10610
10774
|
}, []);
|
|
10611
|
-
const handleGhostNodeIntensityChange =
|
|
10775
|
+
const handleGhostNodeIntensityChange = useCallback4((newIntensity) => {
|
|
10612
10776
|
const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
|
|
10613
10777
|
if (!ghostNode) return;
|
|
10614
10778
|
const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
|
|
@@ -10629,7 +10793,7 @@ function XViewScene({
|
|
|
10629
10793
|
ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
|
|
10630
10794
|
}
|
|
10631
10795
|
}, []);
|
|
10632
|
-
const handleDetailNodeIntensityChange =
|
|
10796
|
+
const handleDetailNodeIntensityChange = useCallback4((nodeId, newIntensity) => {
|
|
10633
10797
|
const mesh = stateRef.current.nodeObjects[String(nodeId)];
|
|
10634
10798
|
if (!mesh) return;
|
|
10635
10799
|
const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
|
|
@@ -10775,7 +10939,7 @@ function XViewScene({
|
|
|
10775
10939
|
mountRef.current.style.cursor = "default";
|
|
10776
10940
|
}
|
|
10777
10941
|
};
|
|
10778
|
-
const handleAncestryTreeUpdate =
|
|
10942
|
+
const handleAncestryTreeUpdate = useCallback4((newTree, extraData = null) => {
|
|
10779
10943
|
setAncestryMode((prev) => {
|
|
10780
10944
|
const prevTreeStr = JSON.stringify(prev.tree);
|
|
10781
10945
|
const newTreeStr = JSON.stringify(newTree);
|
|
@@ -10845,7 +11009,7 @@ function XViewScene({
|
|
|
10845
11009
|
const handleStartVersioning = (nodeData) => {
|
|
10846
11010
|
userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
|
|
10847
11011
|
};
|
|
10848
|
-
const handleClearAncestryVisuals =
|
|
11012
|
+
const handleClearAncestryVisuals = useCallback4((ancestryId) => {
|
|
10849
11013
|
const { renderedAncestries, ancestryGroup } = stateRef.current;
|
|
10850
11014
|
const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
|
|
10851
11015
|
if (renderIndex !== -1) {
|
|
@@ -10859,7 +11023,7 @@ function XViewScene({
|
|
|
10859
11023
|
stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
|
|
10860
11024
|
}
|
|
10861
11025
|
}, []);
|
|
10862
|
-
const handleRenderAncestry =
|
|
11026
|
+
const handleRenderAncestry = useCallback4(
|
|
10863
11027
|
async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
|
|
10864
11028
|
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
10865
11029
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
@@ -11275,7 +11439,7 @@ function XViewScene({
|
|
|
11275
11439
|
},
|
|
11276
11440
|
[addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, readingMode.isActive, ancestryMode.isActive]
|
|
11277
11441
|
);
|
|
11278
|
-
const handleRenderAbstractionTree =
|
|
11442
|
+
const handleRenderAbstractionTree = useCallback4((ancestryObject, targetNodeId = null) => {
|
|
11279
11443
|
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
11280
11444
|
if (!ancestryObject || !ancestryObject.abstraction_tree) return;
|
|
11281
11445
|
const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
|
|
@@ -11336,7 +11500,7 @@ function XViewScene({
|
|
|
11336
11500
|
stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
|
|
11337
11501
|
tweenToTarget(rootTargetPos, 0.7);
|
|
11338
11502
|
}, [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, handleClearAncestryVisuals]);
|
|
11339
|
-
const handleReadModeBranchNav =
|
|
11503
|
+
const handleReadModeBranchNav = useCallback4((nodeId, action, direction = "right") => {
|
|
11340
11504
|
const { ancestry, branchStack } = readingMode;
|
|
11341
11505
|
if (!ancestry || !ancestry.tree) return;
|
|
11342
11506
|
const allAncestries = ancestryDataRef.current || [];
|
|
@@ -11374,9 +11538,7 @@ function XViewScene({
|
|
|
11374
11538
|
description_sections: branchToOpen.description_sections,
|
|
11375
11539
|
tree: branchToOpen.tree,
|
|
11376
11540
|
_originNodeId: nodeId,
|
|
11377
|
-
// <--- ID do node pai (link visual)
|
|
11378
11541
|
_branchDirection: direction
|
|
11379
|
-
// <--- Direção para cálculo de posição
|
|
11380
11542
|
};
|
|
11381
11543
|
const allowedIds = /* @__PURE__ */ new Set(["preamble", 0, "0"]);
|
|
11382
11544
|
const branchSections = parseDescriptionSections(branchToOpen.description || "", branchToOpen.description_sections || []);
|
|
@@ -11432,7 +11594,6 @@ function XViewScene({
|
|
|
11432
11594
|
const parentAncestryObj = {
|
|
11433
11595
|
...targetAncestryInfo,
|
|
11434
11596
|
tree: targetTreeToRender,
|
|
11435
|
-
// Re-injeta a origem se o pai também for uma branch aninhada
|
|
11436
11597
|
_originNodeId: activeParentStackItem ? activeParentStackItem.nodeId : null,
|
|
11437
11598
|
_branchDirection: activeParentStackItem ? activeParentStackItem.entryDirection : null
|
|
11438
11599
|
};
|
|
@@ -11480,7 +11641,7 @@ function XViewScene({
|
|
|
11480
11641
|
}));
|
|
11481
11642
|
}
|
|
11482
11643
|
}, [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]);
|
|
11483
|
-
const handleReadModeHighlight =
|
|
11644
|
+
const handleReadModeHighlight = useCallback4((nodeId) => {
|
|
11484
11645
|
if (stateRef.current.highlightedNodeId !== nodeId) {
|
|
11485
11646
|
stateRef.current.highlightedNodeId = nodeId;
|
|
11486
11647
|
}
|
|
@@ -11492,7 +11653,6 @@ function XViewScene({
|
|
|
11492
11653
|
readingMode.ancestry.tree,
|
|
11493
11654
|
Object.values(parentDataRef.current).flatMap((f) => f.nodes),
|
|
11494
11655
|
ancestryDataRef.current
|
|
11495
|
-
// <--- Adicionar
|
|
11496
11656
|
);
|
|
11497
11657
|
const findNodeInTree = (tree, targetId) => {
|
|
11498
11658
|
if (!tree) return null;
|
|
@@ -11546,7 +11706,6 @@ function XViewScene({
|
|
|
11546
11706
|
description_sections: ancestry.description_sections,
|
|
11547
11707
|
direction: null,
|
|
11548
11708
|
customProperties: rootProps
|
|
11549
|
-
// <--- ADICIONADO
|
|
11550
11709
|
};
|
|
11551
11710
|
}
|
|
11552
11711
|
const fullTree = buildFullAncestryTree(
|
|
@@ -11575,7 +11734,6 @@ function XViewScene({
|
|
|
11575
11734
|
description_sections: currentMeta.description_sections,
|
|
11576
11735
|
direction: currentDirection,
|
|
11577
11736
|
customProperties: branchProps
|
|
11578
|
-
// <--- ADICIONADO
|
|
11579
11737
|
};
|
|
11580
11738
|
}, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
|
|
11581
11739
|
const readModeAbstractionTree = useMemo12(() => {
|
|
@@ -11590,7 +11748,7 @@ function XViewScene({
|
|
|
11590
11748
|
allAncestries
|
|
11591
11749
|
);
|
|
11592
11750
|
}, [readingMode.isActive, readingMode.ancestry, buildFullAncestryTree, sceneVersion]);
|
|
11593
|
-
const handleStartReadingAncestry =
|
|
11751
|
+
const handleStartReadingAncestry = useCallback4(
|
|
11594
11752
|
async (ancestryObject) => {
|
|
11595
11753
|
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
11596
11754
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
@@ -11611,7 +11769,6 @@ function XViewScene({
|
|
|
11611
11769
|
ancestry: ancestryObject,
|
|
11612
11770
|
branchStack: [],
|
|
11613
11771
|
autoAbstraction: shouldAutoRenderAbstraction
|
|
11614
|
-
// <--- FLAG ENVIADA PARA A UI
|
|
11615
11772
|
});
|
|
11616
11773
|
if (shouldAutoRenderAbstraction) {
|
|
11617
11774
|
handleRenderAbstractionTree(ancestryObject, null);
|
|
@@ -11625,9 +11782,8 @@ function XViewScene({
|
|
|
11625
11782
|
}
|
|
11626
11783
|
},
|
|
11627
11784
|
[handleRenderAncestry, handleRenderAbstractionTree]
|
|
11628
|
-
// <--- DEPENDÊNCIA ADICIONADA
|
|
11629
11785
|
);
|
|
11630
|
-
const handleReadModeSectionChange =
|
|
11786
|
+
const handleReadModeSectionChange = useCallback4((activeSectionId) => {
|
|
11631
11787
|
const { ancestry, branchStack } = readingMode;
|
|
11632
11788
|
if (!ancestry || !readingMode.isActive) return;
|
|
11633
11789
|
let targetObj = ancestry;
|
|
@@ -11696,10 +11852,10 @@ function XViewScene({
|
|
|
11696
11852
|
}, 0);
|
|
11697
11853
|
handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
|
|
11698
11854
|
}, [readingMode, handleRenderAncestry, buildFullAncestryTree, ancestryDataRef.current]);
|
|
11699
|
-
const handleCloseReadMode =
|
|
11855
|
+
const handleCloseReadMode = useCallback4(() => {
|
|
11700
11856
|
setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
|
|
11701
11857
|
}, []);
|
|
11702
|
-
const handleAncestrySectionChange =
|
|
11858
|
+
const handleAncestrySectionChange = useCallback4((activeSectionId, ancestryOverride = null, rotation = 0) => {
|
|
11703
11859
|
var _a2, _b2;
|
|
11704
11860
|
const currentMode = stateRef.current.ancestry;
|
|
11705
11861
|
let targetObj = ancestryOverride;
|
|
@@ -11751,7 +11907,7 @@ function XViewScene({
|
|
|
11751
11907
|
const renderPayload = { ...targetObj, tree: treeToRender };
|
|
11752
11908
|
handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
|
|
11753
11909
|
}, [handleRenderAncestry]);
|
|
11754
|
-
const handleEditAncestry =
|
|
11910
|
+
const handleEditAncestry = useCallback4(
|
|
11755
11911
|
async (ancestryObject) => {
|
|
11756
11912
|
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
11757
11913
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
@@ -11774,10 +11930,8 @@ function XViewScene({
|
|
|
11774
11930
|
...ancestryObject,
|
|
11775
11931
|
tree: fullTree,
|
|
11776
11932
|
abstraction_tree: fullAbstractionTree,
|
|
11777
|
-
// NOVO
|
|
11778
11933
|
selectedParentId: ancestryObject.ancestral_node,
|
|
11779
11934
|
selectedAbstractionParentId: ancestryObject.ancestral_node,
|
|
11780
|
-
// NOVO
|
|
11781
11935
|
isEditMode: true,
|
|
11782
11936
|
currentAncestryId: ancestryObject.ancestry_id,
|
|
11783
11937
|
ancestryName: ancestryObject.name || `Ancestralidade ${fullTree.node.name}`,
|
|
@@ -11785,7 +11939,6 @@ function XViewScene({
|
|
|
11785
11939
|
ancestryDescriptionSections: ancestryObject.description_sections || [],
|
|
11786
11940
|
isAddingNodes: false,
|
|
11787
11941
|
isAddingAbstractionNodes: false
|
|
11788
|
-
// NOVO
|
|
11789
11942
|
});
|
|
11790
11943
|
},
|
|
11791
11944
|
[handleRenderAncestry, buildFullAncestryTree]
|
|
@@ -11793,7 +11946,7 @@ function XViewScene({
|
|
|
11793
11946
|
const handleSelectAncestryParent = (nodeId) => {
|
|
11794
11947
|
setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
|
|
11795
11948
|
};
|
|
11796
|
-
const handleRemoveFromAncestry =
|
|
11949
|
+
const handleRemoveFromAncestry = useCallback4((pathToRemove) => {
|
|
11797
11950
|
if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
|
|
11798
11951
|
console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
|
|
11799
11952
|
return;
|
|
@@ -11818,7 +11971,7 @@ function XViewScene({
|
|
|
11818
11971
|
return { ...prev, tree: newTree };
|
|
11819
11972
|
});
|
|
11820
11973
|
}, []);
|
|
11821
|
-
const handleSaveAncestry =
|
|
11974
|
+
const handleSaveAncestry = useCallback4(
|
|
11822
11975
|
async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
|
|
11823
11976
|
const treeToUse = treeOverride || ancestryMode.tree;
|
|
11824
11977
|
const { isEditMode, currentAncestryId } = ancestryMode;
|
|
@@ -12022,7 +12175,7 @@ function XViewScene({
|
|
|
12022
12175
|
});
|
|
12023
12176
|
setEditingAncestryRel({ visible: false, data: null, path: null });
|
|
12024
12177
|
};
|
|
12025
|
-
const handleDeleteAncestry =
|
|
12178
|
+
const handleDeleteAncestry = useCallback4(
|
|
12026
12179
|
async (ancestryIdToDelete) => {
|
|
12027
12180
|
if (!ancestryIdToDelete) {
|
|
12028
12181
|
alert("ID da ancestralidade n\xE3o encontrado.");
|
|
@@ -12084,15 +12237,15 @@ function XViewScene({
|
|
|
12084
12237
|
},
|
|
12085
12238
|
[save_view_data, delete_file_action]
|
|
12086
12239
|
);
|
|
12087
|
-
const handleOpenAncestryBoard =
|
|
12240
|
+
const handleOpenAncestryBoard = useCallback4(() => {
|
|
12088
12241
|
setIsAncestryBoardOpen(true);
|
|
12089
12242
|
}, []);
|
|
12090
|
-
const handleSelectAncestryFromBoard =
|
|
12243
|
+
const handleSelectAncestryFromBoard = useCallback4((ancestry) => {
|
|
12091
12244
|
setIsAncestryBoardOpen(false);
|
|
12092
12245
|
setIsSidebarOpen(false);
|
|
12093
12246
|
handleStartReadingAncestry(ancestry);
|
|
12094
12247
|
}, [handleStartReadingAncestry]);
|
|
12095
|
-
const handleSaveAncestryBoard =
|
|
12248
|
+
const handleSaveAncestryBoard = useCallback4(async (groups) => {
|
|
12096
12249
|
if (!sceneConfigId || !viewParams || !session) return;
|
|
12097
12250
|
const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
|
|
12098
12251
|
await save_ancestry_board_action(sceneConfigId, sceneType, groups, session, ownerId);
|
|
@@ -12116,13 +12269,13 @@ function XViewScene({
|
|
|
12116
12269
|
return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
|
|
12117
12270
|
});
|
|
12118
12271
|
}, [parentDataRef.current, sceneVersion]);
|
|
12119
|
-
const handleAddExistingNode =
|
|
12272
|
+
const handleAddExistingNode = useCallback4(
|
|
12120
12273
|
(nodeId) => {
|
|
12121
12274
|
return userActionHandlers.handleAddExistingNodeById(actionHandlerContext, nodeId);
|
|
12122
12275
|
},
|
|
12123
12276
|
[actionHandlerContext]
|
|
12124
12277
|
);
|
|
12125
|
-
const handleSaveCurrentView =
|
|
12278
|
+
const handleSaveCurrentView = useCallback4(async () => {
|
|
12126
12279
|
const { nodeObjects, allLinks } = stateRef.current;
|
|
12127
12280
|
if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
|
|
12128
12281
|
console.warn("N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente.");
|
|
@@ -12162,7 +12315,7 @@ function XViewScene({
|
|
|
12162
12315
|
const allAvailableAncestries = useMemo12(() => {
|
|
12163
12316
|
return ancestryDataRef.current || [];
|
|
12164
12317
|
}, [sceneVersion, isInitialized]);
|
|
12165
|
-
const handleOpenReference =
|
|
12318
|
+
const handleOpenReference = useCallback4((referenceData) => {
|
|
12166
12319
|
const { type, id } = referenceData;
|
|
12167
12320
|
if (type === "node") {
|
|
12168
12321
|
const targetNode = allAvailableNodes.find((n) => String(n.id) === String(id));
|
|
@@ -12189,10 +12342,10 @@ function XViewScene({
|
|
|
12189
12342
|
}
|
|
12190
12343
|
}
|
|
12191
12344
|
}, [allAvailableNodes, allAvailableAncestries, handleEditAncestry, tweenToTarget]);
|
|
12192
|
-
const handleToggleAncestryAddMode =
|
|
12345
|
+
const handleToggleAncestryAddMode = useCallback4(() => {
|
|
12193
12346
|
setAncestryMode((prev) => ({ ...prev, isAddingNodes: !prev.isAddingNodes }));
|
|
12194
12347
|
}, []);
|
|
12195
|
-
const handleFocusNode =
|
|
12348
|
+
const handleFocusNode = useCallback4((nodeData) => {
|
|
12196
12349
|
if (!nodeData) return;
|
|
12197
12350
|
const nodeMesh = stateRef.current.nodeObjects[String(nodeData.id)];
|
|
12198
12351
|
if (nodeMesh) {
|
|
@@ -12262,7 +12415,6 @@ function XViewScene({
|
|
|
12262
12415
|
height: "100vh",
|
|
12263
12416
|
position: "relative",
|
|
12264
12417
|
overflow: "hidden",
|
|
12265
|
-
// <--- ADICIONE ESTA LINHA
|
|
12266
12418
|
cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
|
|
12267
12419
|
}
|
|
12268
12420
|
},
|
|
@@ -12329,9 +12481,20 @@ function XViewScene({
|
|
|
12329
12481
|
readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React23.createElement(
|
|
12330
12482
|
"div",
|
|
12331
12483
|
{
|
|
12332
|
-
className:
|
|
12333
|
-
style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)" }
|
|
12484
|
+
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"}`,
|
|
12485
|
+
style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${readModeWidth}px`, maxWidth: "92vw" }
|
|
12334
12486
|
},
|
|
12487
|
+
/* @__PURE__ */ React23.createElement(
|
|
12488
|
+
"div",
|
|
12489
|
+
{
|
|
12490
|
+
onPointerDown: (e) => {
|
|
12491
|
+
e.stopPropagation();
|
|
12492
|
+
handleReadModeResize(e);
|
|
12493
|
+
},
|
|
12494
|
+
className: "absolute left-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-indigo-500/50 z-[2000] transition-colors",
|
|
12495
|
+
title: "Arraste para redimensionar"
|
|
12496
|
+
}
|
|
12497
|
+
),
|
|
12335
12498
|
/* @__PURE__ */ React23.createElement(
|
|
12336
12499
|
DescriptionReadModePanel,
|
|
12337
12500
|
{
|