@lv-x-software-house/x_view 1.2.5-dev.31 → 1.2.5-dev.32

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 CHANGED
@@ -9743,11 +9743,11 @@ function QuestTimeline({
9743
9743
  if (timeline.length === 0) {
9744
9744
  return /* @__PURE__ */ import_react19.default.createElement("div", { className: "py-6 flex flex-col items-center justify-center gap-2 border border-white/5 bg-white/5 rounded-xl" }, /* @__PURE__ */ import_react19.default.createElement(import_fi17.FiAlertCircle, { className: "text-slate-600", size: 16 }), /* @__PURE__ */ import_react19.default.createElement("p", { className: "text-[10px] text-slate-500 font-light uppercase tracking-widest" }, "Nenhum hist\xF3rico dispon\xEDvel"));
9745
9745
  }
9746
- return /* @__PURE__ */ import_react19.default.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ import_react19.default.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider flex items-center gap-2" }, "Hist\xF3rico (Timeline)"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "relative pl-6 space-y-6 before:content-[''] before:absolute before:left-[11px] before:top-2 before:bottom-2 before:w-[2px] before:bg-white/5" }, sortedTimeline.map((event, index) => {
9746
+ return /* @__PURE__ */ import_react19.default.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ import_react19.default.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider flex items-center gap-2" }, "Hist\xF3rico (Timeline)"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "relative pl-10 space-y-6 before:content-[''] before:absolute before:left-[21px] before:top-2 before:bottom-2 before:w-[2px] before:bg-white/5" }, sortedTimeline.map((event, index) => {
9747
9747
  const config = EVENT_ICONS[event.type] || EVENT_ICONS.default;
9748
9748
  const Icon = config.icon;
9749
9749
  const actorName = getMemberName(event.actorId);
9750
- return /* @__PURE__ */ import_react19.default.createElement("div", { key: index, className: "relative animate-in fade-in slide-in-from-left-2 duration-300", style: { animationDelay: `${index * 50}ms` } }, /* @__PURE__ */ import_react19.default.createElement("div", { className: `absolute -left-[27px] top-0 w-8 h-8 rounded-full ${config.bg} flex items-center justify-center ring-4 ring-slate-950 border border-white/5` }, /* @__PURE__ */ import_react19.default.createElement(Icon, { className: config.iconColor || config.color, size: 14 })), /* @__PURE__ */ import_react19.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center justify-between gap-4" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-xs font-semibold text-slate-200" }, actorName), /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-[10px] text-slate-500 tabular-nums" }, formatDate(event.timestamp))), /* @__PURE__ */ import_react19.default.createElement("p", { className: "text-sm text-slate-400 leading-relaxed" }, event.description), (event.from_status || event.to_status) && /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-1.5 py-1 px-2 rounded-md bg-white/5 border border-white/5 w-fit mt-2" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-[10px] text-slate-500" }, event.from_status || "?"), /* @__PURE__ */ import_react19.default.createElement(import_fi17.FiArrowRight, { size: 10, className: "text-slate-600" }), /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-[10px] text-indigo-300 font-bold" }, event.to_status || "?")), event.metadata && Object.keys(event.metadata).length > 0 && /* @__PURE__ */ import_react19.default.createElement("div", { className: "mt-2 text-[10px] grid grid-cols-2 gap-2 p-2 bg-slate-900/50 rounded border border-white/5" }, Object.entries(event.metadata).map(([key, value]) => /* @__PURE__ */ import_react19.default.createElement("div", { key, className: "flex flex-col gap-0.5" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-slate-500 capitalize" }, key.replace(/_/g, " ")), /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-slate-300 truncate font-mono" }, typeof value === "string" ? value : JSON.stringify(value))))), event.links && event.links.length > 0 && /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, event.links.map((link, lIdx) => /* @__PURE__ */ import_react19.default.createElement(
9750
+ return /* @__PURE__ */ import_react19.default.createElement("div", { key: index, className: "relative animate-in fade-in slide-in-from-left-2 duration-300", style: { animationDelay: `${index * 50}ms` } }, /* @__PURE__ */ import_react19.default.createElement("div", { className: `absolute -left-[35px] top-0 w-8 h-8 rounded-full ${config.bg} flex items-center justify-center ring-4 ring-slate-950 border border-white/5` }, /* @__PURE__ */ import_react19.default.createElement(Icon, { className: config.iconColor || config.color, size: 14 })), /* @__PURE__ */ import_react19.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center justify-between gap-4" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-xs font-semibold text-slate-200" }, actorName), /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-[10px] text-slate-500 tabular-nums" }, formatDate(event.timestamp))), /* @__PURE__ */ import_react19.default.createElement("p", { className: "text-sm text-slate-400 leading-relaxed" }, event.description), (event.from_status || event.to_status) && /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-1.5 py-1 px-2 rounded-md bg-white/5 border border-white/5 w-fit mt-2" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-[10px] text-slate-500" }, event.from_status || "?"), /* @__PURE__ */ import_react19.default.createElement(import_fi17.FiArrowRight, { size: 10, className: "text-slate-600" }), /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-[10px] text-indigo-300 font-bold" }, event.to_status || "?")), event.metadata && Object.keys(event.metadata).length > 0 && /* @__PURE__ */ import_react19.default.createElement("div", { className: "mt-2 text-[10px] grid grid-cols-2 gap-2 p-2 bg-slate-900/50 rounded border border-white/5" }, Object.entries(event.metadata).map(([key, value]) => /* @__PURE__ */ import_react19.default.createElement("div", { key, className: "flex flex-col gap-0.5" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-slate-500 capitalize" }, key.replace(/_/g, " ")), /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-slate-300 truncate font-mono" }, typeof value === "string" ? value : JSON.stringify(value))))), event.links && event.links.length > 0 && /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, event.links.map((link, lIdx) => /* @__PURE__ */ import_react19.default.createElement(
9751
9751
  "a",
9752
9752
  {
9753
9753
  key: lIdx,
@@ -9830,6 +9830,8 @@ function QuestDetailsPanel({
9830
9830
  const [isLinkCopied, setIsLinkCopied] = (0, import_react20.useState)(false);
9831
9831
  const [hasUnsavedChanges, setHasUnsavedChanges] = (0, import_react20.useState)(false);
9832
9832
  const [noteText, setNoteText] = (0, import_react20.useState)("");
9833
+ const [noteLinks, setNoteLinks] = (0, import_react20.useState)([]);
9834
+ const [noteImages, setNoteImages] = (0, import_react20.useState)([]);
9833
9835
  const [isNoteFormOpen, setIsNoteFormOpen] = (0, import_react20.useState)(false);
9834
9836
  const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
9835
9837
  const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
@@ -9965,7 +9967,10 @@ function QuestDetailsPanel({
9965
9967
  if (!noteText.trim() || isSaving) return;
9966
9968
  setIsSaving(true);
9967
9969
  const actorId = (currentUser == null ? void 0 : currentUser.id) || "unknown";
9968
- const newEntry = createTimelineEntry(actorId, noteText, "comment");
9970
+ const newEntry = createTimelineEntry(actorId, noteText, "comment", {
9971
+ links: noteLinks,
9972
+ images: noteImages
9973
+ });
9969
9974
  const updatedTimeline = [...timeline, newEntry];
9970
9975
  try {
9971
9976
  const nodeToSave = {
@@ -9976,6 +9981,8 @@ function QuestDetailsPanel({
9976
9981
  setTimeline(updatedTimeline);
9977
9982
  onDataUpdate(nodeToSave);
9978
9983
  setNoteText("");
9984
+ setNoteLinks([]);
9985
+ setNoteImages([]);
9979
9986
  setIsNoteFormOpen(false);
9980
9987
  } catch (error) {
9981
9988
  console.error("Erro ao adicionar nota:", error);
@@ -9983,6 +9990,24 @@ function QuestDetailsPanel({
9983
9990
  setIsSaving(false);
9984
9991
  }
9985
9992
  };
9993
+ const addLinkToNote = () => {
9994
+ setNoteLinks([...noteLinks, { id: v4_default(), name: "", value: "" }]);
9995
+ };
9996
+ const removeLinkFromNote = (id) => {
9997
+ setNoteLinks(noteLinks.filter((l) => l.id !== id));
9998
+ };
9999
+ const updateLinkInNote = (id, field, val) => {
10000
+ setNoteLinks(noteLinks.map((l) => l.id === id ? { ...l, [field]: val } : l));
10001
+ };
10002
+ const addImageToNote = () => {
10003
+ setNoteImages([...noteImages, { id: v4_default(), name: "Image", value: "" }]);
10004
+ };
10005
+ const removeImageFromNote = (id) => {
10006
+ setNoteImages(noteImages.filter((img) => img.id !== id));
10007
+ };
10008
+ const updateImageInNote = (id, val) => {
10009
+ setNoteImages(noteImages.map((img) => img.id === id ? { ...img, value: val } : img));
10010
+ };
9986
10011
  const handleStatusChange = (newStatus) => {
9987
10012
  setStatus(newStatus);
9988
10013
  const newColor = QUEST_STATUS_COLORS3[newStatus];
@@ -10339,7 +10364,34 @@ function QuestDetailsPanel({
10339
10364
  placeholder: "Escreva uma observa\xE7\xE3o no hist\xF3rico...",
10340
10365
  className: "w-full bg-slate-900/50 p-3 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-1 focus:ring-indigo-500/50 min-h-[80px] resize-none"
10341
10366
  }
10342
- ), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex justify-end gap-2" }, /* @__PURE__ */ import_react20.default.createElement(
10367
+ ), /* @__PURE__ */ import_react20.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react20.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase font-bold tracking-tight" }, "Links"), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", onClick: addLinkToNote, className: "text-indigo-400 hover:text-indigo-300 text-[10px] flex items-center gap-1 font-medium" }, /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiPlus, { size: 10 }), " Adicionar Link")), noteLinks.length > 0 && /* @__PURE__ */ import_react20.default.createElement("div", { className: "space-y-2" }, noteLinks.map((link) => /* @__PURE__ */ import_react20.default.createElement("div", { key: link.id, className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-1" }, /* @__PURE__ */ import_react20.default.createElement(
10368
+ "input",
10369
+ {
10370
+ type: "text",
10371
+ placeholder: "T\xEDtulo",
10372
+ value: link.name,
10373
+ onChange: (e) => updateLinkInNote(link.id, "name", e.target.value),
10374
+ className: "w-1/3 bg-slate-950/50 border border-white/5 rounded px-2 py-1 text-[10px] focus:outline-none focus:border-indigo-500/50"
10375
+ }
10376
+ ), /* @__PURE__ */ import_react20.default.createElement(
10377
+ "input",
10378
+ {
10379
+ type: "text",
10380
+ placeholder: "URL (https://...)",
10381
+ value: link.value,
10382
+ onChange: (e) => updateLinkInNote(link.id, "value", e.target.value),
10383
+ className: "flex-1 bg-slate-950/50 border border-white/5 rounded px-2 py-1 text-[10px] focus:outline-none focus:border-indigo-500/50"
10384
+ }
10385
+ ), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", onClick: () => removeLinkFromNote(link.id), className: "text-slate-600 hover:text-red-400 transition-colors" }, /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiX, { size: 12 })))))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react20.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase font-bold tracking-tight" }, "Imagens (URLs)"), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", onClick: addImageToNote, className: "text-indigo-400 hover:text-indigo-300 text-[10px] flex items-center gap-1 font-medium" }, /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiPlus, { size: 10 }), " Adicionar Imagem")), noteImages.length > 0 && /* @__PURE__ */ import_react20.default.createElement("div", { className: "space-y-2" }, noteImages.map((img) => /* @__PURE__ */ import_react20.default.createElement("div", { key: img.id, className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-1" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex-1 flex items-center gap-2 bg-slate-950/50 border border-white/5 rounded px-2 py-1" }, /* @__PURE__ */ import_react20.default.createElement(FiImage, { size: 10, className: "text-slate-600" }), /* @__PURE__ */ import_react20.default.createElement(
10386
+ "input",
10387
+ {
10388
+ type: "text",
10389
+ placeholder: "URL da Imagem (https://...)",
10390
+ value: img.value,
10391
+ onChange: (e) => updateImageInNote(img.id, e.target.value),
10392
+ className: "flex-1 bg-transparent text-[10px] focus:outline-none"
10393
+ }
10394
+ )), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", onClick: () => removeImageFromNote(img.id), className: "text-slate-600 hover:text-red-400 transition-colors" }, /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiX, { size: 12 })))))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex justify-end gap-2 pt-2" }, /* @__PURE__ */ import_react20.default.createElement(
10343
10395
  "button",
10344
10396
  {
10345
10397
  type: "button",
package/dist/index.mjs CHANGED
@@ -4002,7 +4002,7 @@ import { FiPlus, FiEdit2 as FiEdit22, FiBookOpen } from "react-icons/fi";
4002
4002
 
4003
4003
  // src/components/DescriptionEditModal.jsx
4004
4004
  import React5, { useState as useState6, useEffect as useEffect5, useRef as useRef5, useMemo as useMemo4 } from "react";
4005
- import { FiType, FiList, FiCode, FiLink as FiLink2, FiAtSign, FiSearch as FiSearch2, FiHexagon as FiHexagon2, FiGlobe, FiImage, FiCheckSquare } from "react-icons/fi";
4005
+ import { FiType, FiList, FiCode, FiLink as FiLink2, FiAtSign, FiSearch as FiSearch2, FiHexagon as FiHexagon2, FiGlobe, FiImage as FiImage2, FiCheckSquare } from "react-icons/fi";
4006
4006
 
4007
4007
  // src/components/SectionImportModal.jsx
4008
4008
  import React4, { useState as useState5, useMemo as useMemo3, useRef as useRef4, useEffect as useEffect4 } from "react";
@@ -4749,7 +4749,7 @@ ${space}${bullet} `);
4749
4749
  className: "flex items-center gap-1 px-3 py-1.5 rounded bg-indigo-600/30 hover:bg-indigo-600/50 border border-indigo-500/30 text-indigo-200 text-xs font-medium transition-colors whitespace-nowrap",
4750
4750
  title: "Inserir Imagem (Propriedade ou URL)"
4751
4751
  },
4752
- /* @__PURE__ */ React5.createElement(FiImage, { size: 12 }),
4752
+ /* @__PURE__ */ React5.createElement(FiImage2, { size: 12 }),
4753
4753
  " Imagem"
4754
4754
  ), /* @__PURE__ */ React5.createElement(
4755
4755
  "button",
@@ -4888,7 +4888,7 @@ ${space}${bullet} `);
4888
4888
 
4889
4889
  // src/components/DescriptionDisplay.jsx
4890
4890
  import React6, { useMemo as useMemo5, useState as useState7, useEffect as useEffect6, useRef as useRef6 } from "react";
4891
- 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";
4891
+ import { FiCopy as FiCopy2, FiCheck as FiCheck3, FiChevronDown as FiChevronDown3, FiChevronRight as FiChevronRight2, FiTerminal as FiTerminal2, FiCornerDownRight, FiExternalLink as FiExternalLink2, FiImage as FiImage3, FiSave } from "react-icons/fi";
4892
4892
  var CodeBlock2 = ({ content, isActive, onClick }) => {
4893
4893
  const [isExpanded, setIsExpanded] = useState7(false);
4894
4894
  const [copied, setCopied] = useState7(false);
@@ -4985,7 +4985,7 @@ var renderTextWithImages = (text, onImageClick) => {
4985
4985
  },
4986
4986
  className: "inline-flex items-center gap-1 text-emerald-400 hover:text-emerald-300 hover:underline decoration-emerald-500/50 underline-offset-2 transition-colors cursor-pointer align-baseline mx-0.5"
4987
4987
  },
4988
- /* @__PURE__ */ React6.createElement(FiImage2, { size: 11 }),
4988
+ /* @__PURE__ */ React6.createElement(FiImage3, { size: 11 }),
4989
4989
  /* @__PURE__ */ React6.createElement("span", null, name)
4990
4990
  );
4991
4991
  }
@@ -9209,7 +9209,7 @@ function InSceneQuestForm({
9209
9209
 
9210
9210
  // src/components/NodeDetailsPanel.jsx
9211
9211
  import React17, { useState as useState18, useEffect as useEffect15, useRef as useRef13 } from "react";
9212
- import { FiPlus as FiPlus7, FiMaximize2 as FiMaximize23, FiX as FiX6, FiCheck as FiCheck10, FiImage as FiImage3, FiEdit2 as FiEdit27, FiLoader as FiLoader2, FiBookOpen as FiBookOpen3, FiSun as FiSun2, FiLink as FiLink5, FiDatabase } from "react-icons/fi";
9212
+ import { FiPlus as FiPlus7, FiMaximize2 as FiMaximize23, FiX as FiX6, FiCheck as FiCheck10, FiImage as FiImage4, FiEdit2 as FiEdit27, FiLoader as FiLoader2, FiBookOpen as FiBookOpen3, FiSun as FiSun2, FiLink as FiLink5, FiDatabase } from "react-icons/fi";
9213
9213
  function NodeDetailsPanel({
9214
9214
  node,
9215
9215
  onClose,
@@ -9772,11 +9772,11 @@ function QuestTimeline({
9772
9772
  if (timeline.length === 0) {
9773
9773
  return /* @__PURE__ */ React18.createElement("div", { className: "py-6 flex flex-col items-center justify-center gap-2 border border-white/5 bg-white/5 rounded-xl" }, /* @__PURE__ */ React18.createElement(FiAlertCircle, { className: "text-slate-600", size: 16 }), /* @__PURE__ */ React18.createElement("p", { className: "text-[10px] text-slate-500 font-light uppercase tracking-widest" }, "Nenhum hist\xF3rico dispon\xEDvel"));
9774
9774
  }
9775
- return /* @__PURE__ */ React18.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React18.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider flex items-center gap-2" }, "Hist\xF3rico (Timeline)"), /* @__PURE__ */ React18.createElement("div", { className: "relative pl-6 space-y-6 before:content-[''] before:absolute before:left-[11px] before:top-2 before:bottom-2 before:w-[2px] before:bg-white/5" }, sortedTimeline.map((event, index) => {
9775
+ return /* @__PURE__ */ React18.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React18.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider flex items-center gap-2" }, "Hist\xF3rico (Timeline)"), /* @__PURE__ */ React18.createElement("div", { className: "relative pl-10 space-y-6 before:content-[''] before:absolute before:left-[21px] before:top-2 before:bottom-2 before:w-[2px] before:bg-white/5" }, sortedTimeline.map((event, index) => {
9776
9776
  const config = EVENT_ICONS[event.type] || EVENT_ICONS.default;
9777
9777
  const Icon = config.icon;
9778
9778
  const actorName = getMemberName(event.actorId);
9779
- return /* @__PURE__ */ React18.createElement("div", { key: index, className: "relative animate-in fade-in slide-in-from-left-2 duration-300", style: { animationDelay: `${index * 50}ms` } }, /* @__PURE__ */ React18.createElement("div", { className: `absolute -left-[27px] top-0 w-8 h-8 rounded-full ${config.bg} flex items-center justify-center ring-4 ring-slate-950 border border-white/5` }, /* @__PURE__ */ React18.createElement(Icon, { className: config.iconColor || config.color, size: 14 })), /* @__PURE__ */ React18.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center justify-between gap-4" }, /* @__PURE__ */ React18.createElement("span", { className: "text-xs font-semibold text-slate-200" }, actorName), /* @__PURE__ */ React18.createElement("span", { className: "text-[10px] text-slate-500 tabular-nums" }, formatDate(event.timestamp))), /* @__PURE__ */ React18.createElement("p", { className: "text-sm text-slate-400 leading-relaxed" }, event.description), (event.from_status || event.to_status) && /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-1.5 py-1 px-2 rounded-md bg-white/5 border border-white/5 w-fit mt-2" }, /* @__PURE__ */ React18.createElement("span", { className: "text-[10px] text-slate-500" }, event.from_status || "?"), /* @__PURE__ */ React18.createElement(FiArrowRight, { size: 10, className: "text-slate-600" }), /* @__PURE__ */ React18.createElement("span", { className: "text-[10px] text-indigo-300 font-bold" }, event.to_status || "?")), event.metadata && Object.keys(event.metadata).length > 0 && /* @__PURE__ */ React18.createElement("div", { className: "mt-2 text-[10px] grid grid-cols-2 gap-2 p-2 bg-slate-900/50 rounded border border-white/5" }, Object.entries(event.metadata).map(([key, value]) => /* @__PURE__ */ React18.createElement("div", { key, className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React18.createElement("span", { className: "text-slate-500 capitalize" }, key.replace(/_/g, " ")), /* @__PURE__ */ React18.createElement("span", { className: "text-slate-300 truncate font-mono" }, typeof value === "string" ? value : JSON.stringify(value))))), event.links && event.links.length > 0 && /* @__PURE__ */ React18.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, event.links.map((link, lIdx) => /* @__PURE__ */ React18.createElement(
9779
+ return /* @__PURE__ */ React18.createElement("div", { key: index, className: "relative animate-in fade-in slide-in-from-left-2 duration-300", style: { animationDelay: `${index * 50}ms` } }, /* @__PURE__ */ React18.createElement("div", { className: `absolute -left-[35px] top-0 w-8 h-8 rounded-full ${config.bg} flex items-center justify-center ring-4 ring-slate-950 border border-white/5` }, /* @__PURE__ */ React18.createElement(Icon, { className: config.iconColor || config.color, size: 14 })), /* @__PURE__ */ React18.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center justify-between gap-4" }, /* @__PURE__ */ React18.createElement("span", { className: "text-xs font-semibold text-slate-200" }, actorName), /* @__PURE__ */ React18.createElement("span", { className: "text-[10px] text-slate-500 tabular-nums" }, formatDate(event.timestamp))), /* @__PURE__ */ React18.createElement("p", { className: "text-sm text-slate-400 leading-relaxed" }, event.description), (event.from_status || event.to_status) && /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-1.5 py-1 px-2 rounded-md bg-white/5 border border-white/5 w-fit mt-2" }, /* @__PURE__ */ React18.createElement("span", { className: "text-[10px] text-slate-500" }, event.from_status || "?"), /* @__PURE__ */ React18.createElement(FiArrowRight, { size: 10, className: "text-slate-600" }), /* @__PURE__ */ React18.createElement("span", { className: "text-[10px] text-indigo-300 font-bold" }, event.to_status || "?")), event.metadata && Object.keys(event.metadata).length > 0 && /* @__PURE__ */ React18.createElement("div", { className: "mt-2 text-[10px] grid grid-cols-2 gap-2 p-2 bg-slate-900/50 rounded border border-white/5" }, Object.entries(event.metadata).map(([key, value]) => /* @__PURE__ */ React18.createElement("div", { key, className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React18.createElement("span", { className: "text-slate-500 capitalize" }, key.replace(/_/g, " ")), /* @__PURE__ */ React18.createElement("span", { className: "text-slate-300 truncate font-mono" }, typeof value === "string" ? value : JSON.stringify(value))))), event.links && event.links.length > 0 && /* @__PURE__ */ React18.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, event.links.map((link, lIdx) => /* @__PURE__ */ React18.createElement(
9780
9780
  "a",
9781
9781
  {
9782
9782
  key: lIdx,
@@ -9859,6 +9859,8 @@ function QuestDetailsPanel({
9859
9859
  const [isLinkCopied, setIsLinkCopied] = useState19(false);
9860
9860
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState19(false);
9861
9861
  const [noteText, setNoteText] = useState19("");
9862
+ const [noteLinks, setNoteLinks] = useState19([]);
9863
+ const [noteImages, setNoteImages] = useState19([]);
9862
9864
  const [isNoteFormOpen, setIsNoteFormOpen] = useState19(false);
9863
9865
  const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
9864
9866
  const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
@@ -9994,7 +9996,10 @@ function QuestDetailsPanel({
9994
9996
  if (!noteText.trim() || isSaving) return;
9995
9997
  setIsSaving(true);
9996
9998
  const actorId = (currentUser == null ? void 0 : currentUser.id) || "unknown";
9997
- const newEntry = createTimelineEntry(actorId, noteText, "comment");
9999
+ const newEntry = createTimelineEntry(actorId, noteText, "comment", {
10000
+ links: noteLinks,
10001
+ images: noteImages
10002
+ });
9998
10003
  const updatedTimeline = [...timeline, newEntry];
9999
10004
  try {
10000
10005
  const nodeToSave = {
@@ -10005,6 +10010,8 @@ function QuestDetailsPanel({
10005
10010
  setTimeline(updatedTimeline);
10006
10011
  onDataUpdate(nodeToSave);
10007
10012
  setNoteText("");
10013
+ setNoteLinks([]);
10014
+ setNoteImages([]);
10008
10015
  setIsNoteFormOpen(false);
10009
10016
  } catch (error) {
10010
10017
  console.error("Erro ao adicionar nota:", error);
@@ -10012,6 +10019,24 @@ function QuestDetailsPanel({
10012
10019
  setIsSaving(false);
10013
10020
  }
10014
10021
  };
10022
+ const addLinkToNote = () => {
10023
+ setNoteLinks([...noteLinks, { id: v4_default(), name: "", value: "" }]);
10024
+ };
10025
+ const removeLinkFromNote = (id) => {
10026
+ setNoteLinks(noteLinks.filter((l) => l.id !== id));
10027
+ };
10028
+ const updateLinkInNote = (id, field, val) => {
10029
+ setNoteLinks(noteLinks.map((l) => l.id === id ? { ...l, [field]: val } : l));
10030
+ };
10031
+ const addImageToNote = () => {
10032
+ setNoteImages([...noteImages, { id: v4_default(), name: "Image", value: "" }]);
10033
+ };
10034
+ const removeImageFromNote = (id) => {
10035
+ setNoteImages(noteImages.filter((img) => img.id !== id));
10036
+ };
10037
+ const updateImageInNote = (id, val) => {
10038
+ setNoteImages(noteImages.map((img) => img.id === id ? { ...img, value: val } : img));
10039
+ };
10015
10040
  const handleStatusChange = (newStatus) => {
10016
10041
  setStatus(newStatus);
10017
10042
  const newColor = QUEST_STATUS_COLORS3[newStatus];
@@ -10368,7 +10393,34 @@ function QuestDetailsPanel({
10368
10393
  placeholder: "Escreva uma observa\xE7\xE3o no hist\xF3rico...",
10369
10394
  className: "w-full bg-slate-900/50 p-3 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-1 focus:ring-indigo-500/50 min-h-[80px] resize-none"
10370
10395
  }
10371
- ), /* @__PURE__ */ React19.createElement("div", { className: "flex justify-end gap-2" }, /* @__PURE__ */ React19.createElement(
10396
+ ), /* @__PURE__ */ React19.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React19.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React19.createElement("span", { className: "text-[10px] text-slate-500 uppercase font-bold tracking-tight" }, "Links"), /* @__PURE__ */ React19.createElement("button", { type: "button", onClick: addLinkToNote, className: "text-indigo-400 hover:text-indigo-300 text-[10px] flex items-center gap-1 font-medium" }, /* @__PURE__ */ React19.createElement(FiPlus8, { size: 10 }), " Adicionar Link")), noteLinks.length > 0 && /* @__PURE__ */ React19.createElement("div", { className: "space-y-2" }, noteLinks.map((link) => /* @__PURE__ */ React19.createElement("div", { key: link.id, className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-1" }, /* @__PURE__ */ React19.createElement(
10397
+ "input",
10398
+ {
10399
+ type: "text",
10400
+ placeholder: "T\xEDtulo",
10401
+ value: link.name,
10402
+ onChange: (e) => updateLinkInNote(link.id, "name", e.target.value),
10403
+ className: "w-1/3 bg-slate-950/50 border border-white/5 rounded px-2 py-1 text-[10px] focus:outline-none focus:border-indigo-500/50"
10404
+ }
10405
+ ), /* @__PURE__ */ React19.createElement(
10406
+ "input",
10407
+ {
10408
+ type: "text",
10409
+ placeholder: "URL (https://...)",
10410
+ value: link.value,
10411
+ onChange: (e) => updateLinkInNote(link.id, "value", e.target.value),
10412
+ className: "flex-1 bg-slate-950/50 border border-white/5 rounded px-2 py-1 text-[10px] focus:outline-none focus:border-indigo-500/50"
10413
+ }
10414
+ ), /* @__PURE__ */ React19.createElement("button", { type: "button", onClick: () => removeLinkFromNote(link.id), className: "text-slate-600 hover:text-red-400 transition-colors" }, /* @__PURE__ */ React19.createElement(FiX7, { size: 12 })))))), /* @__PURE__ */ React19.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React19.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React19.createElement("span", { className: "text-[10px] text-slate-500 uppercase font-bold tracking-tight" }, "Imagens (URLs)"), /* @__PURE__ */ React19.createElement("button", { type: "button", onClick: addImageToNote, className: "text-indigo-400 hover:text-indigo-300 text-[10px] flex items-center gap-1 font-medium" }, /* @__PURE__ */ React19.createElement(FiPlus8, { size: 10 }), " Adicionar Imagem")), noteImages.length > 0 && /* @__PURE__ */ React19.createElement("div", { className: "space-y-2" }, noteImages.map((img) => /* @__PURE__ */ React19.createElement("div", { key: img.id, className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-1" }, /* @__PURE__ */ React19.createElement("div", { className: "flex-1 flex items-center gap-2 bg-slate-950/50 border border-white/5 rounded px-2 py-1" }, /* @__PURE__ */ React19.createElement(FiImage, { size: 10, className: "text-slate-600" }), /* @__PURE__ */ React19.createElement(
10415
+ "input",
10416
+ {
10417
+ type: "text",
10418
+ placeholder: "URL da Imagem (https://...)",
10419
+ value: img.value,
10420
+ onChange: (e) => updateImageInNote(img.id, e.target.value),
10421
+ className: "flex-1 bg-transparent text-[10px] focus:outline-none"
10422
+ }
10423
+ )), /* @__PURE__ */ React19.createElement("button", { type: "button", onClick: () => removeImageFromNote(img.id), className: "text-slate-600 hover:text-red-400 transition-colors" }, /* @__PURE__ */ React19.createElement(FiX7, { size: 12 })))))), /* @__PURE__ */ React19.createElement("div", { className: "flex justify-end gap-2 pt-2" }, /* @__PURE__ */ React19.createElement(
10372
10424
  "button",
10373
10425
  {
10374
10426
  type: "button",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lv-x-software-house/x_view",
3
- "version": "1.2.5-dev.31",
3
+ "version": "1.2.5-dev.32",
4
4
  "description": "Pacote privado contendo os componentes e lógica de renderização 3D do X View.",
5
5
  "author": "iv.x - Engenharia de Software - ivxsoftwarehouse@gmail.com",
6
6
  "license": "UNLICENSED",