@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.
Files changed (3) hide show
  1. package/dist/index.js +971 -808
  2. package/dist/index.mjs +412 -249
  3. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/XViewScene.jsx
2
- import React23, { useCallback as useCallback3, useEffect as useEffect21, useRef as useRef17, useState as useState22, useMemo as useMemo12 } from "react";
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 useState8, useEffect as useEffect8, useRef as useRef7 } from "react";
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 useState3, useRef as useRef3, useEffect as useEffect3 } from "react";
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] = useState3(prop.isEditing ?? false);
3020
- const [tempProp, setTempProp] = useState3(prop);
3021
- const [isHovered, setIsHovered] = useState3(false);
3022
- const [isTypeDropdownOpen, setIsTypeDropdownOpen] = useState3(false);
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] = useState3(null);
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 useState5, useEffect as useEffect5, useRef as useRef5, useMemo as useMemo4 } from "react";
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 useState4, useMemo as useMemo3, useRef as useRef4, useEffect as useEffect4 } from "react";
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] = useState4(false);
3378
- const [copied, setCopied] = useState4(false);
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] = useState4("");
3442
- const [selectedItem, setSelectedItem] = useState4(null);
3443
- const [searchHistory, setSearchHistory] = useState4([]);
3444
- const [activeIndex, setActiveIndex] = useState4(0);
3445
- const [selectedIndices, setSelectedIndices] = useState4(/* @__PURE__ */ new Set([0]));
3446
- const [lastSelectedIndex, setLastSelectedIndex] = useState4(0);
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] = useState4(false);
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 [text, setText] = useState5(initialValue || "");
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] = useState5(false);
3790
- const [isMentionModalOpen, setIsMentionModalOpen] = useState5(false);
3791
- const [mentionSearch, setMentionSearch] = useState5("");
3792
- const [mentionTriggerIndex, setMentionTriggerIndex] = useState5(null);
3793
- const [isImageModalOpen, setIsImageModalOpen] = useState5(false);
3794
- const [manualImageUrl, setManualImageUrl] = useState5("");
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] = useState5(null);
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: "ui-overlay pointer-events-auto relative group h-full w-[min(90vw,700px)] border-l border-white/10 bg-slate-950/95 shadow-2xl text-white flex flex-col",
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 useState6, useEffect as useEffect6, useRef as useRef6 } from "react";
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] = useState6(false);
4159
- const [copied, setCopied] = useState6(false);
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: "pl-2 text-slate-200 break-words" }, /* @__PURE__ */ React6.createElement("span", { className: "text-indigo-400 font-bold mr-1.5" }, "\u2022"), processContent(content));
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 sections = useMemo5(() => parseDescriptionSections(description, savedSections), [description, savedSections]);
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] = useState6(0);
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
- "span",
4583
+ "div",
4479
4584
  {
4480
4585
  ref: isActiveSection && activeMentionIndex === -1 && partIndex === 0 && lineIndex === 0 ? setRef : null,
4481
- onClick: () => {
4482
- const idx = flatNavigation.findIndex((item) => item.type === "section" && item.sectionIndex === parentIndex);
4483
- if (idx !== -1) setCurrentStepIndex(idx);
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/20 text-white ring-1 ring-indigo-500/30" : "hover:bg-white/5 hover:text-slate-200"}
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
- ), !isLastLine && /* @__PURE__ */ React6.createElement("br", null));
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
- return /* @__PURE__ */ React6.createElement("div", { className: "w-full text-sm leading-relaxed text-slate-300 break-words whitespace-pre-wrap px-3 pt-1 pb-2 pr-9" }, sections.map((section, index) => {
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 useState7, useMemo as useMemo6, useEffect as useEffect7 } from "react";
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] = useState7(false);
4642
- const [showAbstraction, setShowAbstraction] = useState7(false);
4643
- const [targetRenderNodeId, setTargetRenderNodeId] = useState7(null);
4644
- const [isLinkCopied, setIsLinkCopied] = useState7(false);
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] = useState8((data == null ? void 0 : data.description) ?? "");
4900
- const [customProps, setCustomProps] = useState8(() => extractCustomPropsFromNode(data || {}));
4901
- const [existingSections, setExistingSections] = useState8((data == null ? void 0 : data.description_sections) || []);
4902
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState8(false);
4903
- const [isReadMode, setIsReadMode] = useState8(false);
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 useState10, useEffect as useEffect10, useMemo as useMemo8, useRef as useRef8, useCallback } from "react";
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 useState9, useMemo as useMemo7, useEffect as useEffect9 } from "react";
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] = useState9("");
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] = useState10(false);
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] = useState10(false);
5297
- const [isLinkCopied, setIsLinkCopied] = useState10(false);
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] = useState10(false);
5312
- const [customProps, setCustomProps] = useState10([]);
5433
+ const [isPickerOpen, setIsPickerOpen] = useState11(false);
5434
+ const [customProps, setCustomProps] = useState11([]);
5313
5435
  const propsEndRef = useRef8(null);
5314
- const [branchStack, setBranchStack] = useState10([]);
5315
- const [targetRenderNodeId, setTargetRenderNodeId] = useState10(null);
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] = useState10(null);
5330
- const [internalHighlightedNodeId, setInternalHighlightedNodeId] = useState10(null);
5331
- const [ancestryName, setAncestryName] = useState10(initialName);
5332
- const [description, setDescription] = useState10(initialDescription || "");
5333
- const [existingSections, setExistingSections] = useState10(initialSections || []);
5334
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState10(false);
5335
- const [isReadMode, setIsReadMode] = useState10(false);
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] = useState10(null);
5339
- const [isPrivate, setIsPrivate] = useState10(ancestryMode.is_private || false);
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 = useCallback((pathToRemove, isAbstraction = false) => {
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
- ${isReadMode ? "w-[min(92vw,700px)]" : "w-[min(92vw,440px)]"}
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 useState11, useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useCallback as useCallback2 } from "react";
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] = useState11(startIndex);
6628
- const [isLoading, setIsLoading] = useState11(false);
6629
- const [loadedSrc, setLoadedSrc] = useState11(null);
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 = useCallback2(() => {
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 = useCallback2(() => {
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 useState13, useEffect as useEffect13, useRef as useRef10 } from "react";
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 useState12, useEffect as useEffect12, useRef as useRef9 } from "react";
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] = useState12(false);
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] = useState13("");
6869
- const [types, setTypes] = useState13([]);
6870
- const [typeInput, setTypeInput] = useState13("");
6871
- const [color, setColor] = useState13(initialColor || "#cccccc");
6872
- const [size, setSize] = useState13("medium");
6873
- const [intensity, setIntensity] = useState13(0);
6874
- const [description, setDescription] = useState13("");
6875
- const [customProps, setCustomProps] = useState13([]);
6876
- const [showTypeSuggestions, setShowTypeSuggestions] = useState13(false);
6877
- const [filteredTypes, setFilteredTypes] = useState13([]);
6878
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState13(false);
6879
- const [useImageAsTexture, setUseImageAsTexture] = useState13(false);
6880
- const [selectedImageUrl, setSelectedImageUrl] = useState13(null);
6881
- const [targetDatasetId, setTargetDatasetId] = useState13(sourceNodeDatasetId || "");
6882
- const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] = useState13(false);
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 useState14, useEffect as useEffect14, useRef as useRef11 } from "react";
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] = useState14("");
7234
- const [size, setSize] = useState14("medium");
7235
- const [description, setDescription] = useState14("");
7236
- const [customProps, setCustomProps] = useState14([{ id: v4_default(), key: "Date", type: "date", value: { type: "Data", value: "" }, isEditing: true }]);
7237
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState14(false);
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] = useState14(false);
7240
- const [selectedImageUrl, setSelectedImageUrl] = useState14(null);
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 useState15, useEffect as useEffect15, useRef as useRef12 } from "react";
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] = useState15((node == null ? void 0 : node.name) ?? "");
7456
- const [types, setTypes] = useState15([]);
7457
- const [typeInput, setTypeInput] = useState15("");
7458
- const [color, setColor] = useState15((node == null ? void 0 : node.color) ?? "#8b5cf6");
7459
- const [size, setSize] = useState15((node == null ? void 0 : node.size) ?? "medium");
7460
- const [description, setDescription] = useState15((node == null ? void 0 : node.description) ?? "");
7461
- const [intensity, setIntensity] = useState15((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
7462
- const [customProps, setCustomProps] = useState15(() => extractCustomPropsFromNode(node || {}));
7463
- const [showTypeSuggestions, setShowTypeSuggestions] = useState15(false);
7464
- const [filteredTypes, setFilteredTypes] = useState15([]);
7465
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState15(false);
7466
- const [isReadMode, setIsReadMode] = useState15(false);
7467
- const [existingSections, setExistingSections] = useState15((node == null ? void 0 : node.description_sections) || []);
7468
- const [isSaving, setIsSaving] = useState15(false);
7469
- const [isLinkCopied, setIsLinkCopied] = useState15(false);
7470
- const [useImageAsTexture, setUseImageAsTexture] = useState15(() => {
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] = useState15((node == null ? void 0 : node.textureImageUrl) ?? null);
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
- ${isReadMode ? "w-[min(92vw,700px)]" : "w-[min(92vw,440px)]"}
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 useState16, useEffect as useEffect16 } from "react";
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] = useState16({ left: 0, top: 0 });
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 useState17, useEffect as useEffect17, useRef as useRef14, useMemo as useMemo9 } from "react";
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] = useState17((link == null ? void 0 : link.name) ?? "");
7973
- const [description, setDescription] = useState17((link == null ? void 0 : link.description) ?? "");
7974
- const [customProps, setCustomProps] = useState17(() => extractCustomPropsFromNode(link || {}));
7975
- const [existingSections, setExistingSections] = useState17((link == null ? void 0 : link.description_sections) || []);
7976
- const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState17(false);
7977
- const [isSaving, setIsSaving] = useState17(false);
7978
- const [isReadMode, setIsReadMode] = useState17(false);
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 useState18, useEffect as useEffect18, useMemo as useMemo10 } from "react";
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] = useState18({ left: 0, top: 0 });
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 useState19 } from "react";
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] = useState19("databases");
8407
- const [availableDbs, setAvailableDbs] = useState19([]);
8408
- const [availableViews, setAvailableViews] = useState19([]);
8409
- const [selectedItem, setSelectedItem] = useState19(null);
8410
- const [isLoading, setIsLoading] = useState19(false);
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 useState20 } from "react";
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] = useState20(false);
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 useState21, useMemo as useMemo11, useEffect as useEffect20, useRef as useRef16 } from "react";
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] = useState21("");
8810
- const [groups, setGroups] = useState21([]);
8811
- const [isLoaded, setIsLoaded] = useState21(false);
8812
- const [pickingGroupId, setPickingGroupId] = useState21(null);
8813
- const [saveStatus, setSaveStatus] = useState21("idle");
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] = useState22(true);
9264
- const [permissionStatus, setPermissionStatus] = useState22("loading");
9265
- const [userPermissionRole, setUserPermissionRole] = useState22(null);
9266
- const [isInitialized, setIsInitialized] = useState22(false);
9267
- const [sceneVersion, setSceneVersion] = useState22(0);
9268
- const [contextMenu, setContextMenu] = useState22({ visible: false, x: 0, y: 0, nodeData: null });
9269
- const [multiContextMenu, setMultiContextMenu] = useState22({ visible: false, x: 0, y: 0, nodeIds: null });
9270
- const [relationshipMenu, setRelationshipMenu] = useState22({ visible: false, x: 0, y: 0, linkObject: null });
9271
- const [creationMode, setCreationMode] = useState22({ isActive: false, sourceNodeData: null });
9272
- const [versionMode, setVersionMode] = useState22({ isActive: false, sourceNodeData: null });
9273
- const [hasFocusedInitial, setHasFocusedInitial] = useState22(false);
9274
- const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState22(false);
9275
- const [ancestryMode, setAncestryMode] = useState22({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
9276
- const [readingMode, setReadingMode] = useState22({
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] = useState22({ left: 16, top: 16, opacity: 0 });
9283
- const [detailsNode, setDetailsNode] = useState22(null);
9284
- const [detailsLink, setDetailsLink] = useState22(null);
9285
- const [ancestryLinkDetails, setAncestryLinkDetails] = useState22(null);
9286
- const [imageViewer, setImageViewer] = useState22({ visible: false, images: [], startIndex: 0 });
9287
- const [editingAncestryRel, setEditingAncestryRel] = useState22({ visible: false, data: null, path: null });
9288
- const [isImportModalOpen, setIsImportModalOpen] = useState22(false);
9289
- const [importSuccessMessage, setImportSuccessMessage] = useState22("");
9290
- const [highlightedNodeId, setHighlightedNodeId] = useState22(null);
9291
- const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState22(false);
9292
- const [ancestryBoardData, setAncestryBoardData] = useState22([]);
9293
- const [isSidebarOpen, setIsSidebarOpen] = useState22(false);
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 = useCallback3(() => {
9531
+ const handleNavigateBack = useCallback4(() => {
9361
9532
  router.push("/dashboard/scenes");
9362
9533
  }, [router]);
9363
- const handleConfirmImport = useCallback3(
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 = useCallback3((target, zoomFactor = 1, forcedDirection = null) => {
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 = useCallback3((idTree, nodes, ancestries = []) => {
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 = useCallback3(() => {
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 = useCallback3((sourceMesh, versionMeshes) => {
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 = useCallback3((id) => {
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 = useCallback3((nodeData, position, suppressVersionUpdate = false) => {
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 = useCallback3((useImage, imageUrl) => {
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 = useCallback3((newIntensity) => {
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 = useCallback3((nodeId, newIntensity) => {
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 = useCallback3((newTree, extraData = null) => {
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 = useCallback3((ancestryId) => {
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 = useCallback3(
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 = useCallback3((ancestryObject, targetNodeId = null) => {
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 = useCallback3((nodeId, action, direction = "right") => {
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 = useCallback3((nodeId) => {
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 = useCallback3(
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 = useCallback3((activeSectionId) => {
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 = useCallback3(() => {
11855
+ const handleCloseReadMode = useCallback4(() => {
11700
11856
  setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
11701
11857
  }, []);
11702
- const handleAncestrySectionChange = useCallback3((activeSectionId, ancestryOverride = null, rotation = 0) => {
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 = useCallback3(
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 = useCallback3((pathToRemove) => {
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 = useCallback3(
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 = useCallback3(
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 = useCallback3(() => {
12240
+ const handleOpenAncestryBoard = useCallback4(() => {
12088
12241
  setIsAncestryBoardOpen(true);
12089
12242
  }, []);
12090
- const handleSelectAncestryFromBoard = useCallback3((ancestry) => {
12243
+ const handleSelectAncestryFromBoard = useCallback4((ancestry) => {
12091
12244
  setIsAncestryBoardOpen(false);
12092
12245
  setIsSidebarOpen(false);
12093
12246
  handleStartReadingAncestry(ancestry);
12094
12247
  }, [handleStartReadingAncestry]);
12095
- const handleSaveAncestryBoard = useCallback3(async (groups) => {
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 = useCallback3(
12272
+ const handleAddExistingNode = useCallback4(
12120
12273
  (nodeId) => {
12121
12274
  return userActionHandlers.handleAddExistingNodeById(actionHandlerContext, nodeId);
12122
12275
  },
12123
12276
  [actionHandlerContext]
12124
12277
  );
12125
- const handleSaveCurrentView = useCallback3(async () => {
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 = useCallback3((referenceData) => {
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 = useCallback3(() => {
12345
+ const handleToggleAncestryAddMode = useCallback4(() => {
12193
12346
  setAncestryMode((prev) => ({ ...prev, isAddingNodes: !prev.isAddingNodes }));
12194
12347
  }, []);
12195
- const handleFocusNode = useCallback3((nodeData) => {
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: "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 w-[min(92vw,700px)]",
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
  {