@lv-x-software-house/x_view 1.2.2-dev.14 → 1.2.2-dev.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +104 -21
- package/dist/index.mjs +106 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3216,8 +3216,8 @@ function CustomPropertyDisplay({
|
|
|
3216
3216
|
const availableOptions = [
|
|
3217
3217
|
{ value: "links", label: "Links", unique: true },
|
|
3218
3218
|
{ value: "images", label: "Images", unique: true },
|
|
3219
|
-
{ value: "documents", label: "Documents", unique: true },
|
|
3220
3219
|
{ value: "date", label: "Data", unique: true },
|
|
3220
|
+
{ value: "documents", label: "Documents", unique: true },
|
|
3221
3221
|
{ value: "text", label: "Texto", unique: false },
|
|
3222
3222
|
{ value: "number", label: "N\xFAmero", unique: false },
|
|
3223
3223
|
{ value: "list", label: "Lista", unique: false }
|
|
@@ -4080,6 +4080,24 @@ function DescriptionEditModal({
|
|
|
4080
4080
|
},
|
|
4081
4081
|
/* @__PURE__ */ import_react6.default.createElement(import_fi4.FiList, { size: 12 }),
|
|
4082
4082
|
" Lista"
|
|
4083
|
+
), /* @__PURE__ */ import_react6.default.createElement(
|
|
4084
|
+
"button",
|
|
4085
|
+
{
|
|
4086
|
+
onClick: () => insertAtCursor("1. "),
|
|
4087
|
+
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",
|
|
4088
|
+
title: "Lista Numerada"
|
|
4089
|
+
},
|
|
4090
|
+
/* @__PURE__ */ import_react6.default.createElement("span", { className: "text-[10px] font-bold" }, "1."),
|
|
4091
|
+
" Numerada"
|
|
4092
|
+
), /* @__PURE__ */ import_react6.default.createElement(
|
|
4093
|
+
"button",
|
|
4094
|
+
{
|
|
4095
|
+
onClick: () => insertAtCursor("- [ ] "),
|
|
4096
|
+
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",
|
|
4097
|
+
title: "Checklist (Checkbox)"
|
|
4098
|
+
},
|
|
4099
|
+
/* @__PURE__ */ import_react6.default.createElement(import_fi4.FiCheckSquare, { size: 12 }),
|
|
4100
|
+
" Checklist"
|
|
4083
4101
|
), /* @__PURE__ */ import_react6.default.createElement(
|
|
4084
4102
|
"button",
|
|
4085
4103
|
{
|
|
@@ -4386,7 +4404,7 @@ var renderTextWithMentions = (text, availableNodes, onMentionClick, activeMentio
|
|
|
4386
4404
|
);
|
|
4387
4405
|
});
|
|
4388
4406
|
};
|
|
4389
|
-
var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick) => {
|
|
4407
|
+
var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick, onToggleCheckbox, globalCheckboxCounterRef) => {
|
|
4390
4408
|
const trimmedLine = line.replace(/\r$/, "");
|
|
4391
4409
|
const processContent = (content) => renderTextWithMentions(content, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick);
|
|
4392
4410
|
if (line.startsWith("# ")) {
|
|
@@ -4397,9 +4415,33 @@ var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionInd
|
|
|
4397
4415
|
const content = line.replace("## ", "");
|
|
4398
4416
|
return /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-sm sm:text-base font-semibold text-indigo-200 leading-tight break-words" }, processContent(content));
|
|
4399
4417
|
}
|
|
4418
|
+
const checkboxMatch = trimmedLine.match(/^(\s*)- \[([ xX])\]\s+(.*)/);
|
|
4419
|
+
if (checkboxMatch) {
|
|
4420
|
+
const [_, space, state, content] = checkboxMatch;
|
|
4421
|
+
const isChecked = state.toLowerCase() === "x";
|
|
4422
|
+
const currentIdx = globalCheckboxCounterRef.current;
|
|
4423
|
+
globalCheckboxCounterRef.current += 1;
|
|
4424
|
+
return /* @__PURE__ */ import_react7.default.createElement("span", { className: "flex items-start gap-2.5 my-1 break-words ml-1" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
4425
|
+
"input",
|
|
4426
|
+
{
|
|
4427
|
+
type: "checkbox",
|
|
4428
|
+
checked: isChecked,
|
|
4429
|
+
onChange: (e) => {
|
|
4430
|
+
e.stopPropagation();
|
|
4431
|
+
if (onToggleCheckbox) onToggleCheckbox(currentIdx);
|
|
4432
|
+
},
|
|
4433
|
+
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"
|
|
4434
|
+
}
|
|
4435
|
+
), /* @__PURE__ */ import_react7.default.createElement("span", { className: `transition-all duration-200 ${isChecked ? "line-through text-slate-500" : "text-slate-200"}` }, processContent(content)));
|
|
4436
|
+
}
|
|
4437
|
+
const numberMatch = trimmedLine.match(/^(\s*)(\d+\.)\s+(.*)/);
|
|
4438
|
+
if (numberMatch) {
|
|
4439
|
+
const [_, space, numberStr, content] = numberMatch;
|
|
4440
|
+
return /* @__PURE__ */ import_react7.default.createElement("span", { className: "flex items-start gap-2 my-0.5 break-words ml-1" }, /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-indigo-400 font-mono font-bold text-xs mt-[3px] shrink-0" }, numberStr), /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-slate-200" }, processContent(content)));
|
|
4441
|
+
}
|
|
4400
4442
|
if (trimmedLine.trim().startsWith("- ") || trimmedLine.trim().startsWith("* ")) {
|
|
4401
4443
|
const content = trimmedLine.trim().substring(2);
|
|
4402
|
-
return /* @__PURE__ */ import_react7.default.createElement("span", { className: "
|
|
4444
|
+
return /* @__PURE__ */ import_react7.default.createElement("span", { className: "flex items-start gap-2 my-0.5 break-words ml-1 text-slate-200" }, /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-indigo-400 font-bold shrink-0 mt-[2px] text-xs" }, "\u2022"), /* @__PURE__ */ import_react7.default.createElement("span", null, processContent(content)));
|
|
4403
4445
|
}
|
|
4404
4446
|
return /* @__PURE__ */ import_react7.default.createElement("span", { className: "break-words" }, processContent(line));
|
|
4405
4447
|
};
|
|
@@ -4411,14 +4453,32 @@ function DescriptionDisplay({
|
|
|
4411
4453
|
onOpenReference,
|
|
4412
4454
|
onMentionClick,
|
|
4413
4455
|
onImageClick,
|
|
4414
|
-
// <--- NOVA PROP RECEBIDA
|
|
4415
4456
|
onSectionChange,
|
|
4416
4457
|
onBranchNav,
|
|
4417
4458
|
onHighlightNode,
|
|
4418
4459
|
initialSectionId,
|
|
4419
|
-
currentBranchDirection = null
|
|
4460
|
+
currentBranchDirection = null,
|
|
4461
|
+
onSaveDescription
|
|
4462
|
+
// NOVO: Prop para salvar checklist
|
|
4420
4463
|
}) {
|
|
4421
|
-
const
|
|
4464
|
+
const [localDescription, setLocalDescription] = (0, import_react7.useState)(description || "");
|
|
4465
|
+
(0, import_react7.useEffect)(() => {
|
|
4466
|
+
setLocalDescription(description || "");
|
|
4467
|
+
}, [description]);
|
|
4468
|
+
const sections = (0, import_react7.useMemo)(() => parseDescriptionSections(localDescription, savedSections), [localDescription, savedSections]);
|
|
4469
|
+
const globalCheckboxCounterRef = (0, import_react7.useRef)(0);
|
|
4470
|
+
const handleToggleCheckbox = (targetIndex) => {
|
|
4471
|
+
let currentIndex = 0;
|
|
4472
|
+
const newDesc = localDescription.replace(/^(\s*)- \[([ xX])\]/gm, (match, space, state) => {
|
|
4473
|
+
if (currentIndex === targetIndex) {
|
|
4474
|
+
currentIndex++;
|
|
4475
|
+
return state === " " ? `${space}- [x]` : `${space}- [ ]`;
|
|
4476
|
+
}
|
|
4477
|
+
currentIndex++;
|
|
4478
|
+
return match;
|
|
4479
|
+
});
|
|
4480
|
+
setLocalDescription(newDesc);
|
|
4481
|
+
};
|
|
4422
4482
|
const flatNavigation = (0, import_react7.useMemo)(() => {
|
|
4423
4483
|
const navItems = [];
|
|
4424
4484
|
sections.forEach((section, sIdx) => {
|
|
@@ -4559,26 +4619,27 @@ function DescriptionDisplay({
|
|
|
4559
4619
|
}
|
|
4560
4620
|
const lines = part.replace(/\n$/, "").split("\n");
|
|
4561
4621
|
return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, { key: `text-${parentIndex}-${partIndex}` }, lines.map((line, lineIndex) => {
|
|
4562
|
-
const isLastLine = lineIndex === lines.length - 1;
|
|
4563
4622
|
const isEmptyLine = line.trim() === "";
|
|
4564
4623
|
if (isEmptyLine) {
|
|
4565
4624
|
return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, { key: `${parentIndex}-${partIndex}-${lineIndex}` }, /* @__PURE__ */ import_react7.default.createElement("br", null));
|
|
4566
4625
|
}
|
|
4567
4626
|
return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, { key: `${parentIndex}-${partIndex}-${lineIndex}` }, /* @__PURE__ */ import_react7.default.createElement(
|
|
4568
|
-
"
|
|
4627
|
+
"div",
|
|
4569
4628
|
{
|
|
4570
4629
|
ref: isActiveSection && activeMentionIndex === -1 && partIndex === 0 && lineIndex === 0 ? setRef : null,
|
|
4571
|
-
onClick: () => {
|
|
4572
|
-
|
|
4573
|
-
|
|
4630
|
+
onClick: (e) => {
|
|
4631
|
+
if (e.target.type !== "checkbox") {
|
|
4632
|
+
const idx = flatNavigation.findIndex((item) => item.type === "section" && item.sectionIndex === parentIndex);
|
|
4633
|
+
if (idx !== -1) setCurrentStepIndex(idx);
|
|
4634
|
+
}
|
|
4574
4635
|
},
|
|
4575
4636
|
className: `
|
|
4576
|
-
transition-colors duration-200 cursor-pointer rounded-md px-1 py-0.5 -mx-1 box-decoration-clone
|
|
4577
|
-
${isActiveSection ? "bg-indigo-500/
|
|
4637
|
+
transition-colors duration-200 cursor-pointer rounded-md px-1 py-0.5 -mx-1 box-decoration-clone inline-block w-full
|
|
4638
|
+
${isActiveSection ? "bg-indigo-500/10 text-white ring-1 ring-indigo-500/30" : "hover:bg-white/5 hover:text-slate-200"}
|
|
4578
4639
|
`
|
|
4579
4640
|
},
|
|
4580
|
-
formatLineContent2(line, availableNodes, onMentionClick, isActiveSection ? activeMentionIndex : -1, mentionCounterRef, setRef, onImageClick)
|
|
4581
|
-
)
|
|
4641
|
+
formatLineContent2(line, availableNodes, onMentionClick, isActiveSection ? activeMentionIndex : -1, mentionCounterRef, setRef, onImageClick, handleToggleCheckbox, globalCheckboxCounterRef)
|
|
4642
|
+
));
|
|
4582
4643
|
}));
|
|
4583
4644
|
});
|
|
4584
4645
|
};
|
|
@@ -4606,7 +4667,9 @@ function DescriptionDisplay({
|
|
|
4606
4667
|
${isActiveSection ? "opacity-100" : "opacity-90"}
|
|
4607
4668
|
` }, renderMixedContent(resolved.content, index, isActiveSection, -1, setRef)));
|
|
4608
4669
|
};
|
|
4609
|
-
|
|
4670
|
+
globalCheckboxCounterRef.current = 0;
|
|
4671
|
+
const hasUnsavedChanges = localDescription !== (description || "");
|
|
4672
|
+
return /* @__PURE__ */ import_react7.default.createElement("div", { className: "relative w-full h-full min-h-[100px]" }, /* @__PURE__ */ import_react7.default.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) => {
|
|
4610
4673
|
const currentNavItem = flatNavigation[currentStepIndex];
|
|
4611
4674
|
const isSectionContextActive = currentNavItem && currentNavItem.sectionIndex === index;
|
|
4612
4675
|
const activeMentionIndex = isSectionContextActive && currentNavItem.type === "mention" ? currentNavItem.mentionIndex : -1;
|
|
@@ -4622,7 +4685,18 @@ function DescriptionDisplay({
|
|
|
4622
4685
|
if (index === 0) leadingSpace = "";
|
|
4623
4686
|
const isRef = bodyText.trim().match(/^\[\[REF:(node|ancestry):([a-zA-Z0-9\-_]+):([a-zA-Z0-9\-_]+)\]\]$/);
|
|
4624
4687
|
return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, { key: index }, /* @__PURE__ */ import_react7.default.createElement("span", null, leadingSpace), isRef ? renderReferenceSection(bodyText, index, isSectionContextActive, setRef) : renderMixedContent(bodyText, index, isSectionContextActive, activeMentionIndex, setRef), /* @__PURE__ */ import_react7.default.createElement("span", null, trailingSpace));
|
|
4625
|
-
}))
|
|
4688
|
+
})), hasUnsavedChanges && onSaveDescription && /* @__PURE__ */ import_react7.default.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__ */ import_react7.default.createElement(
|
|
4689
|
+
"button",
|
|
4690
|
+
{
|
|
4691
|
+
onClick: (e) => {
|
|
4692
|
+
e.stopPropagation();
|
|
4693
|
+
onSaveDescription(localDescription);
|
|
4694
|
+
},
|
|
4695
|
+
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"
|
|
4696
|
+
},
|
|
4697
|
+
/* @__PURE__ */ import_react7.default.createElement(import_fi5.FiSave, { size: 16 }),
|
|
4698
|
+
" Salvar Checklist"
|
|
4699
|
+
)));
|
|
4626
4700
|
}
|
|
4627
4701
|
|
|
4628
4702
|
// src/components/DescriptionReadModePanel.jsx
|
|
@@ -4712,7 +4786,8 @@ function DescriptionReadModePanel({
|
|
|
4712
4786
|
userRole,
|
|
4713
4787
|
abstractionTree = null,
|
|
4714
4788
|
onRenderAbstractionTree = null,
|
|
4715
|
-
initialShowAbstraction = false
|
|
4789
|
+
initialShowAbstraction = false,
|
|
4790
|
+
onSaveDescription
|
|
4716
4791
|
}) {
|
|
4717
4792
|
const [showProperties, setShowProperties] = (0, import_react8.useState)(false);
|
|
4718
4793
|
const [showAbstraction, setShowAbstraction] = (0, import_react8.useState)(false);
|
|
@@ -4930,7 +5005,8 @@ function DescriptionReadModePanel({
|
|
|
4930
5005
|
onHighlightNode,
|
|
4931
5006
|
initialSectionId,
|
|
4932
5007
|
currentBranchDirection,
|
|
4933
|
-
onImageClick
|
|
5008
|
+
onImageClick,
|
|
5009
|
+
onSaveDescription
|
|
4934
5010
|
}
|
|
4935
5011
|
)),
|
|
4936
5012
|
leftAction && !showAbstraction && !showProperties && /* @__PURE__ */ import_react8.default.createElement(
|
|
@@ -7712,6 +7788,11 @@ function NodeDetailsPanel({
|
|
|
7712
7788
|
textureImageUrl: url
|
|
7713
7789
|
});
|
|
7714
7790
|
};
|
|
7791
|
+
const handleSaveDescriptionInline = (newDescription) => {
|
|
7792
|
+
setDescription(newDescription);
|
|
7793
|
+
onDataUpdate({ ...node, description: newDescription });
|
|
7794
|
+
triggerAutoSave({ description: newDescription });
|
|
7795
|
+
};
|
|
7715
7796
|
const handleSave = async (keepOpen = false, overrides = {}) => {
|
|
7716
7797
|
const currentName = overrides.name !== void 0 ? overrides.name : name;
|
|
7717
7798
|
const currentTypes = overrides.types !== void 0 ? overrides.types : types;
|
|
@@ -7806,7 +7887,8 @@ function NodeDetailsPanel({
|
|
|
7806
7887
|
availableAncestries,
|
|
7807
7888
|
onOpenReference,
|
|
7808
7889
|
onMentionClick,
|
|
7809
|
-
onImageClick: handleImageClickFromText
|
|
7890
|
+
onImageClick: handleImageClickFromText,
|
|
7891
|
+
onSaveDescription: handleSaveDescriptionInline
|
|
7810
7892
|
}
|
|
7811
7893
|
) : /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react16.default.createElement("div", null, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node"), /* @__PURE__ */ import_react16.default.createElement(
|
|
7812
7894
|
"button",
|
|
@@ -7874,7 +7956,8 @@ function NodeDetailsPanel({
|
|
|
7874
7956
|
availableAncestries,
|
|
7875
7957
|
onOpenReference,
|
|
7876
7958
|
onMentionClick,
|
|
7877
|
-
onImageClick: handleImageClickFromText
|
|
7959
|
+
onImageClick: handleImageClickFromText,
|
|
7960
|
+
onSaveDescription: handleSaveDescriptionInline
|
|
7878
7961
|
}
|
|
7879
7962
|
), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(
|
|
7880
7963
|
"button",
|
package/dist/index.mjs
CHANGED
|
@@ -3172,8 +3172,8 @@ function CustomPropertyDisplay({
|
|
|
3172
3172
|
const availableOptions = [
|
|
3173
3173
|
{ value: "links", label: "Links", unique: true },
|
|
3174
3174
|
{ value: "images", label: "Images", unique: true },
|
|
3175
|
-
{ value: "documents", label: "Documents", unique: true },
|
|
3176
3175
|
{ value: "date", label: "Data", unique: true },
|
|
3176
|
+
{ value: "documents", label: "Documents", unique: true },
|
|
3177
3177
|
{ value: "text", label: "Texto", unique: false },
|
|
3178
3178
|
{ value: "number", label: "N\xFAmero", unique: false },
|
|
3179
3179
|
{ value: "list", label: "Lista", unique: false }
|
|
@@ -3396,7 +3396,7 @@ import { FiPlus, FiEdit2 as FiEdit22, FiBookOpen } from "react-icons/fi";
|
|
|
3396
3396
|
|
|
3397
3397
|
// src/components/DescriptionEditModal.jsx
|
|
3398
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 } from "react-icons/fi";
|
|
3399
|
+
import { FiType, FiList, FiCode, FiLink as FiLink2, FiAtSign, FiSearch as FiSearch2, FiHexagon as FiHexagon2, FiGlobe, FiImage, FiCheckSquare } from "react-icons/fi";
|
|
3400
3400
|
|
|
3401
3401
|
// src/components/SectionImportModal.jsx
|
|
3402
3402
|
import React4, { useState as useState5, useMemo as useMemo3, useRef as useRef4, useEffect as useEffect4 } from "react";
|
|
@@ -4036,6 +4036,24 @@ function DescriptionEditModal({
|
|
|
4036
4036
|
},
|
|
4037
4037
|
/* @__PURE__ */ React5.createElement(FiList, { size: 12 }),
|
|
4038
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"
|
|
4039
4057
|
), /* @__PURE__ */ React5.createElement(
|
|
4040
4058
|
"button",
|
|
4041
4059
|
{
|
|
@@ -4199,7 +4217,7 @@ function DescriptionEditModal({
|
|
|
4199
4217
|
|
|
4200
4218
|
// src/components/DescriptionDisplay.jsx
|
|
4201
4219
|
import React6, { useMemo as useMemo5, useState as useState7, useEffect as useEffect6, useRef as useRef6 } from "react";
|
|
4202
|
-
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";
|
|
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";
|
|
4203
4221
|
var CodeBlock2 = ({ content, isActive, onClick }) => {
|
|
4204
4222
|
const [isExpanded, setIsExpanded] = useState7(false);
|
|
4205
4223
|
const [copied, setCopied] = useState7(false);
|
|
@@ -4342,7 +4360,7 @@ var renderTextWithMentions = (text, availableNodes, onMentionClick, activeMentio
|
|
|
4342
4360
|
);
|
|
4343
4361
|
});
|
|
4344
4362
|
};
|
|
4345
|
-
var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick) => {
|
|
4363
|
+
var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick, onToggleCheckbox, globalCheckboxCounterRef) => {
|
|
4346
4364
|
const trimmedLine = line.replace(/\r$/, "");
|
|
4347
4365
|
const processContent = (content) => renderTextWithMentions(content, availableNodes, onMentionClick, activeMentionIndex, mentionCounterRef, setRef, onImageClick);
|
|
4348
4366
|
if (line.startsWith("# ")) {
|
|
@@ -4353,9 +4371,33 @@ var formatLineContent2 = (line, availableNodes, onMentionClick, activeMentionInd
|
|
|
4353
4371
|
const content = line.replace("## ", "");
|
|
4354
4372
|
return /* @__PURE__ */ React6.createElement("span", { className: "text-sm sm:text-base font-semibold text-indigo-200 leading-tight break-words" }, processContent(content));
|
|
4355
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
|
+
}
|
|
4356
4398
|
if (trimmedLine.trim().startsWith("- ") || trimmedLine.trim().startsWith("* ")) {
|
|
4357
4399
|
const content = trimmedLine.trim().substring(2);
|
|
4358
|
-
return /* @__PURE__ */ React6.createElement("span", { className: "
|
|
4400
|
+
return /* @__PURE__ */ React6.createElement("span", { className: "flex items-start gap-2 my-0.5 break-words ml-1 text-slate-200" }, /* @__PURE__ */ React6.createElement("span", { className: "text-indigo-400 font-bold shrink-0 mt-[2px] text-xs" }, "\u2022"), /* @__PURE__ */ React6.createElement("span", null, processContent(content)));
|
|
4359
4401
|
}
|
|
4360
4402
|
return /* @__PURE__ */ React6.createElement("span", { className: "break-words" }, processContent(line));
|
|
4361
4403
|
};
|
|
@@ -4367,14 +4409,32 @@ function DescriptionDisplay({
|
|
|
4367
4409
|
onOpenReference,
|
|
4368
4410
|
onMentionClick,
|
|
4369
4411
|
onImageClick,
|
|
4370
|
-
// <--- NOVA PROP RECEBIDA
|
|
4371
4412
|
onSectionChange,
|
|
4372
4413
|
onBranchNav,
|
|
4373
4414
|
onHighlightNode,
|
|
4374
4415
|
initialSectionId,
|
|
4375
|
-
currentBranchDirection = null
|
|
4416
|
+
currentBranchDirection = null,
|
|
4417
|
+
onSaveDescription
|
|
4418
|
+
// NOVO: Prop para salvar checklist
|
|
4376
4419
|
}) {
|
|
4377
|
-
const
|
|
4420
|
+
const [localDescription, setLocalDescription] = useState7(description || "");
|
|
4421
|
+
useEffect6(() => {
|
|
4422
|
+
setLocalDescription(description || "");
|
|
4423
|
+
}, [description]);
|
|
4424
|
+
const sections = useMemo5(() => parseDescriptionSections(localDescription, savedSections), [localDescription, savedSections]);
|
|
4425
|
+
const globalCheckboxCounterRef = useRef6(0);
|
|
4426
|
+
const handleToggleCheckbox = (targetIndex) => {
|
|
4427
|
+
let currentIndex = 0;
|
|
4428
|
+
const newDesc = localDescription.replace(/^(\s*)- \[([ xX])\]/gm, (match, space, state) => {
|
|
4429
|
+
if (currentIndex === targetIndex) {
|
|
4430
|
+
currentIndex++;
|
|
4431
|
+
return state === " " ? `${space}- [x]` : `${space}- [ ]`;
|
|
4432
|
+
}
|
|
4433
|
+
currentIndex++;
|
|
4434
|
+
return match;
|
|
4435
|
+
});
|
|
4436
|
+
setLocalDescription(newDesc);
|
|
4437
|
+
};
|
|
4378
4438
|
const flatNavigation = useMemo5(() => {
|
|
4379
4439
|
const navItems = [];
|
|
4380
4440
|
sections.forEach((section, sIdx) => {
|
|
@@ -4515,26 +4575,27 @@ function DescriptionDisplay({
|
|
|
4515
4575
|
}
|
|
4516
4576
|
const lines = part.replace(/\n$/, "").split("\n");
|
|
4517
4577
|
return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: `text-${parentIndex}-${partIndex}` }, lines.map((line, lineIndex) => {
|
|
4518
|
-
const isLastLine = lineIndex === lines.length - 1;
|
|
4519
4578
|
const isEmptyLine = line.trim() === "";
|
|
4520
4579
|
if (isEmptyLine) {
|
|
4521
4580
|
return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: `${parentIndex}-${partIndex}-${lineIndex}` }, /* @__PURE__ */ React6.createElement("br", null));
|
|
4522
4581
|
}
|
|
4523
4582
|
return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: `${parentIndex}-${partIndex}-${lineIndex}` }, /* @__PURE__ */ React6.createElement(
|
|
4524
|
-
"
|
|
4583
|
+
"div",
|
|
4525
4584
|
{
|
|
4526
4585
|
ref: isActiveSection && activeMentionIndex === -1 && partIndex === 0 && lineIndex === 0 ? setRef : null,
|
|
4527
|
-
onClick: () => {
|
|
4528
|
-
|
|
4529
|
-
|
|
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
|
+
}
|
|
4530
4591
|
},
|
|
4531
4592
|
className: `
|
|
4532
|
-
transition-colors duration-200 cursor-pointer rounded-md px-1 py-0.5 -mx-1 box-decoration-clone
|
|
4533
|
-
${isActiveSection ? "bg-indigo-500/
|
|
4593
|
+
transition-colors duration-200 cursor-pointer rounded-md px-1 py-0.5 -mx-1 box-decoration-clone inline-block w-full
|
|
4594
|
+
${isActiveSection ? "bg-indigo-500/10 text-white ring-1 ring-indigo-500/30" : "hover:bg-white/5 hover:text-slate-200"}
|
|
4534
4595
|
`
|
|
4535
4596
|
},
|
|
4536
|
-
formatLineContent2(line, availableNodes, onMentionClick, isActiveSection ? activeMentionIndex : -1, mentionCounterRef, setRef, onImageClick)
|
|
4537
|
-
)
|
|
4597
|
+
formatLineContent2(line, availableNodes, onMentionClick, isActiveSection ? activeMentionIndex : -1, mentionCounterRef, setRef, onImageClick, handleToggleCheckbox, globalCheckboxCounterRef)
|
|
4598
|
+
));
|
|
4538
4599
|
}));
|
|
4539
4600
|
});
|
|
4540
4601
|
};
|
|
@@ -4562,7 +4623,9 @@ function DescriptionDisplay({
|
|
|
4562
4623
|
${isActiveSection ? "opacity-100" : "opacity-90"}
|
|
4563
4624
|
` }, renderMixedContent(resolved.content, index, isActiveSection, -1, setRef)));
|
|
4564
4625
|
};
|
|
4565
|
-
|
|
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) => {
|
|
4566
4629
|
const currentNavItem = flatNavigation[currentStepIndex];
|
|
4567
4630
|
const isSectionContextActive = currentNavItem && currentNavItem.sectionIndex === index;
|
|
4568
4631
|
const activeMentionIndex = isSectionContextActive && currentNavItem.type === "mention" ? currentNavItem.mentionIndex : -1;
|
|
@@ -4578,7 +4641,18 @@ function DescriptionDisplay({
|
|
|
4578
4641
|
if (index === 0) leadingSpace = "";
|
|
4579
4642
|
const isRef = bodyText.trim().match(/^\[\[REF:(node|ancestry):([a-zA-Z0-9\-_]+):([a-zA-Z0-9\-_]+)\]\]$/);
|
|
4580
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));
|
|
4581
|
-
}))
|
|
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
|
+
)));
|
|
4582
4656
|
}
|
|
4583
4657
|
|
|
4584
4658
|
// src/components/DescriptionReadModePanel.jsx
|
|
@@ -4682,7 +4756,8 @@ function DescriptionReadModePanel({
|
|
|
4682
4756
|
userRole,
|
|
4683
4757
|
abstractionTree = null,
|
|
4684
4758
|
onRenderAbstractionTree = null,
|
|
4685
|
-
initialShowAbstraction = false
|
|
4759
|
+
initialShowAbstraction = false,
|
|
4760
|
+
onSaveDescription
|
|
4686
4761
|
}) {
|
|
4687
4762
|
const [showProperties, setShowProperties] = useState8(false);
|
|
4688
4763
|
const [showAbstraction, setShowAbstraction] = useState8(false);
|
|
@@ -4900,7 +4975,8 @@ function DescriptionReadModePanel({
|
|
|
4900
4975
|
onHighlightNode,
|
|
4901
4976
|
initialSectionId,
|
|
4902
4977
|
currentBranchDirection,
|
|
4903
|
-
onImageClick
|
|
4978
|
+
onImageClick,
|
|
4979
|
+
onSaveDescription
|
|
4904
4980
|
}
|
|
4905
4981
|
)),
|
|
4906
4982
|
leftAction && !showAbstraction && !showProperties && /* @__PURE__ */ React7.createElement(
|
|
@@ -7698,6 +7774,11 @@ function NodeDetailsPanel({
|
|
|
7698
7774
|
textureImageUrl: url
|
|
7699
7775
|
});
|
|
7700
7776
|
};
|
|
7777
|
+
const handleSaveDescriptionInline = (newDescription) => {
|
|
7778
|
+
setDescription(newDescription);
|
|
7779
|
+
onDataUpdate({ ...node, description: newDescription });
|
|
7780
|
+
triggerAutoSave({ description: newDescription });
|
|
7781
|
+
};
|
|
7701
7782
|
const handleSave = async (keepOpen = false, overrides = {}) => {
|
|
7702
7783
|
const currentName = overrides.name !== void 0 ? overrides.name : name;
|
|
7703
7784
|
const currentTypes = overrides.types !== void 0 ? overrides.types : types;
|
|
@@ -7792,7 +7873,8 @@ function NodeDetailsPanel({
|
|
|
7792
7873
|
availableAncestries,
|
|
7793
7874
|
onOpenReference,
|
|
7794
7875
|
onMentionClick,
|
|
7795
|
-
onImageClick: handleImageClickFromText
|
|
7876
|
+
onImageClick: handleImageClickFromText,
|
|
7877
|
+
onSaveDescription: handleSaveDescriptionInline
|
|
7796
7878
|
}
|
|
7797
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(
|
|
7798
7880
|
"button",
|
|
@@ -7860,7 +7942,8 @@ function NodeDetailsPanel({
|
|
|
7860
7942
|
availableAncestries,
|
|
7861
7943
|
onOpenReference,
|
|
7862
7944
|
onMentionClick,
|
|
7863
|
-
onImageClick: handleImageClickFromText
|
|
7945
|
+
onImageClick: handleImageClickFromText,
|
|
7946
|
+
onSaveDescription: handleSaveDescriptionInline
|
|
7864
7947
|
}
|
|
7865
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(
|
|
7866
7949
|
"button",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lv-x-software-house/x_view",
|
|
3
|
-
"version": "1.2.2-dev.
|
|
3
|
+
"version": "1.2.2-dev.15",
|
|
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",
|