@lv-x-software-house/x_view 1.2.5-dev.5 → 1.2.5-dev.7
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 +122 -31
- package/dist/index.mjs +122 -31
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3196,6 +3196,7 @@ function calculateNodePositions(nodes) {
|
|
|
3196
3196
|
return positions;
|
|
3197
3197
|
}
|
|
3198
3198
|
function updateTooltip({ tooltipEl, hoveredNode, hoveredLink, camera, mountEl, isSceneBusy, parentData, ancestryData }) {
|
|
3199
|
+
var _a, _b;
|
|
3199
3200
|
if (!tooltipEl || !camera || !mountEl) return;
|
|
3200
3201
|
let content = "";
|
|
3201
3202
|
let positionTarget = null;
|
|
@@ -3208,17 +3209,21 @@ function updateTooltip({ tooltipEl, hoveredNode, hoveredLink, camera, mountEl, i
|
|
|
3208
3209
|
content = generateTooltipHtml(hoveredNode.userData, parentData, ancestryData);
|
|
3209
3210
|
}
|
|
3210
3211
|
} else if (hoveredLink && !isSceneBusy) {
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3212
|
+
const linkData = hoveredLink.userData.isAncestryLink ? hoveredLink.userData.relationship || {} : hoveredLink.userData;
|
|
3213
|
+
const hasContent = ((_a = linkData.name) == null ? void 0 : _a.trim()) || ((_b = linkData.description) == null ? void 0 : _b.trim());
|
|
3214
|
+
if (hasContent) {
|
|
3215
|
+
currentId = `link_${hoveredLink.userData.id}`;
|
|
3216
|
+
if (hoveredLink.userData.isCurved) {
|
|
3217
|
+
const positions = hoveredLink.geometry.attributes.position.array;
|
|
3218
|
+
const midIndex = Math.floor(positions.length / 2 / 3) * 3;
|
|
3219
|
+
positionTarget = new THREE2.Vector3(positions[midIndex], positions[midIndex + 1], positions[midIndex + 2]);
|
|
3220
|
+
} else {
|
|
3221
|
+
positionTarget = new THREE2.Vector3().addVectors(hoveredLink.userData.sourceNode.position, hoveredLink.userData.targetNode.position).multiplyScalar(0.5);
|
|
3222
|
+
}
|
|
3223
|
+
isLink = true;
|
|
3224
|
+
if (tooltipEl.dataset.currentId !== currentId) {
|
|
3225
|
+
content = generateLinkTooltipHtml(linkData, parentData, ancestryData);
|
|
3226
|
+
}
|
|
3222
3227
|
}
|
|
3223
3228
|
}
|
|
3224
3229
|
if (positionTarget) {
|
|
@@ -3527,9 +3532,9 @@ function CustomPropertyDisplay({
|
|
|
3527
3532
|
};
|
|
3528
3533
|
const handleRemoveListItem = (j) => setTempProp((p) => ({ ...p, value: p.value.filter((_, k) => k !== j) }));
|
|
3529
3534
|
const handleListItemChange = (j, f, v) => setTempProp((p) => {
|
|
3530
|
-
const
|
|
3531
|
-
|
|
3532
|
-
return { ...p, value:
|
|
3535
|
+
const newValue2 = [...p.value];
|
|
3536
|
+
newValue2[j] = { ...newValue2[j], [f]: v };
|
|
3537
|
+
return { ...p, value: newValue2 };
|
|
3533
3538
|
});
|
|
3534
3539
|
const baseInput = "w-full bg-slate-800/70 p-2 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-400/60 transition-all duration-150";
|
|
3535
3540
|
const renderEditView = () => {
|
|
@@ -3583,14 +3588,14 @@ function CustomPropertyDisplay({
|
|
|
3583
3588
|
const inputClass = `${baseInput} ${noSpinnerClass}`;
|
|
3584
3589
|
const handleDateTypeChange = (newDateType) => {
|
|
3585
3590
|
var _a3, _b2, _c2;
|
|
3586
|
-
let
|
|
3591
|
+
let newValue2 = { type: newDateType };
|
|
3587
3592
|
if (newDateType === "Date Interval") {
|
|
3588
|
-
|
|
3589
|
-
|
|
3593
|
+
newValue2.start = ((_a3 = tempProp.value) == null ? void 0 : _a3.start) || "";
|
|
3594
|
+
newValue2.end = ((_b2 = tempProp.value) == null ? void 0 : _b2.end) || "";
|
|
3590
3595
|
} else {
|
|
3591
|
-
|
|
3596
|
+
newValue2.value = ((_c2 = tempProp.value) == null ? void 0 : _c2.type) === newDateType ? tempProp.value.value : "";
|
|
3592
3597
|
}
|
|
3593
|
-
handlePropChange("value",
|
|
3598
|
+
handlePropChange("value", newValue2);
|
|
3594
3599
|
};
|
|
3595
3600
|
const handleDateValueChange = (dateField, dateValue) => {
|
|
3596
3601
|
handlePropChange("value", { ...tempProp.value, [dateField]: dateValue });
|
|
@@ -5788,6 +5793,7 @@ var NodeItem = ({ nodeData, onSelectParent, onViewSelect, highlightedPathIds = [
|
|
|
5788
5793
|
e.stopPropagation();
|
|
5789
5794
|
if (isEditable) {
|
|
5790
5795
|
onSelectParent(itemId);
|
|
5796
|
+
setHasUnsavedChanges(true);
|
|
5791
5797
|
} else if (onViewSelect) {
|
|
5792
5798
|
onViewSelect(itemId);
|
|
5793
5799
|
}
|
|
@@ -5800,9 +5806,11 @@ var NodeItem = ({ nodeData, onSelectParent, onViewSelect, highlightedPathIds = [
|
|
|
5800
5806
|
level > 0 && isEditable && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-1 animate-in fade-in duration-200" }, !nodeData.is_section && /* @__PURE__ */ import_react11.default.createElement("button", { onClick: (e) => {
|
|
5801
5807
|
e.stopPropagation();
|
|
5802
5808
|
onEditRelationship(path, nodeData.relationship || {});
|
|
5809
|
+
setHasUnsavedChanges(true);
|
|
5803
5810
|
}, className: "w-6 h-6 grid place-content-center rounded-full hover:bg-cyan-500/20 text-cyan-400 transition-colors flex-shrink-0", title: "Editar detalhes da rela\xE7\xE3o" }, /* @__PURE__ */ import_react11.default.createElement(import_fi9.FiEdit2, { size: 12 })), /* @__PURE__ */ import_react11.default.createElement("button", { onClick: (e) => {
|
|
5804
5811
|
e.stopPropagation();
|
|
5805
5812
|
onRemoveNode(path);
|
|
5813
|
+
setHasUnsavedChanges(true);
|
|
5806
5814
|
}, className: "w-6 h-6 grid place-content-center rounded-full hover:bg-red-500/20 text-red-400 text-lg transition-colors flex-shrink-0", title: "Remover Node" }, "\xD7"))
|
|
5807
5815
|
), hasChildren && /* @__PURE__ */ import_react11.default.createElement("div", { className: "mt-2 space-y-2 pl-8" }, nodeData.children.map((child, index) => /* @__PURE__ */ import_react11.default.createElement(
|
|
5808
5816
|
NodeItem,
|
|
@@ -5858,6 +5866,7 @@ function CreateAncestryPanel({
|
|
|
5858
5866
|
} = ancestryMode;
|
|
5859
5867
|
const [isSaving, setIsSaving] = (0, import_react11.useState)(false);
|
|
5860
5868
|
const [isLinkCopied, setIsLinkCopied] = (0, import_react11.useState)(false);
|
|
5869
|
+
const [hasUnsavedChanges, setHasUnsavedChanges2] = (0, import_react11.useState)(false);
|
|
5861
5870
|
const [showDeleteBranchConfirm, setShowDeleteBranchConfirm] = (0, import_react11.useState)(false);
|
|
5862
5871
|
const handleCopyLink = (e) => {
|
|
5863
5872
|
e.stopPropagation();
|
|
@@ -5925,12 +5934,14 @@ function CreateAncestryPanel({
|
|
|
5925
5934
|
};
|
|
5926
5935
|
const handleSelectAncestryParent = (nodeId, isAbstraction = false) => {
|
|
5927
5936
|
setAncestryMode((prev) => isAbstraction ? { ...prev, selectedAbstractionParentId: nodeId } : { ...prev, selectedParentId: nodeId });
|
|
5937
|
+
setHasUnsavedChanges2(true);
|
|
5928
5938
|
};
|
|
5929
5939
|
const handleToggleAddMode = (isAbstraction = false) => {
|
|
5930
5940
|
if (isAbstraction && !ancestryMode.isAddingAbstractionNodes) {
|
|
5931
5941
|
setTargetRenderNodeId(null);
|
|
5932
5942
|
}
|
|
5933
5943
|
setAncestryMode((prev) => isAbstraction ? { ...prev, isAddingAbstractionNodes: !prev.isAddingAbstractionNodes } : { ...prev, isAddingNodes: !prev.isAddingNodes });
|
|
5944
|
+
setHasUnsavedChanges2(true);
|
|
5934
5945
|
};
|
|
5935
5946
|
const handleRemoveNode = (0, import_react11.useCallback)((pathToRemove, isAbstraction = false) => {
|
|
5936
5947
|
if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) return;
|
|
@@ -5948,6 +5959,7 @@ function CreateAncestryPanel({
|
|
|
5948
5959
|
const indexToRemove = pathToRemove[pathToRemove.length - 1];
|
|
5949
5960
|
if (currentParent.children && currentParent.children.length > indexToRemove) {
|
|
5950
5961
|
currentParent.children.splice(indexToRemove, 1);
|
|
5962
|
+
setHasUnsavedChanges2(true);
|
|
5951
5963
|
}
|
|
5952
5964
|
return { ...prev, [treeKey]: newTree };
|
|
5953
5965
|
});
|
|
@@ -6006,6 +6018,7 @@ function CreateAncestryPanel({
|
|
|
6006
6018
|
updateGlobalTree(rootTreeClone);
|
|
6007
6019
|
}
|
|
6008
6020
|
setAncestryMode((prev) => ({ ...prev, [treeKey]: rootTreeClone }));
|
|
6021
|
+
setHasUnsavedChanges2(true);
|
|
6009
6022
|
} else {
|
|
6010
6023
|
alert("N\xE3o \xE9 poss\xEDvel mover um node para dentro de seus pr\xF3prios descendentes.");
|
|
6011
6024
|
}
|
|
@@ -6078,6 +6091,7 @@ function CreateAncestryPanel({
|
|
|
6078
6091
|
const handleAddProp = () => {
|
|
6079
6092
|
const newProp = createNewCustomProperty(customProps);
|
|
6080
6093
|
setCustomProps((p) => [...p, newProp]);
|
|
6094
|
+
setHasUnsavedChanges2(true);
|
|
6081
6095
|
setTimeout(() => {
|
|
6082
6096
|
var _a;
|
|
6083
6097
|
(_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
@@ -6086,11 +6100,13 @@ function CreateAncestryPanel({
|
|
|
6086
6100
|
const handleRemoveProp = (i) => {
|
|
6087
6101
|
const newProps = customProps.filter((_, idx) => idx !== i);
|
|
6088
6102
|
setCustomProps(newProps);
|
|
6103
|
+
setHasUnsavedChanges2(true);
|
|
6089
6104
|
};
|
|
6090
6105
|
const handleUpdateProp = (index, updatedProp) => {
|
|
6091
6106
|
const newProps = [...customProps];
|
|
6092
6107
|
newProps[index] = updatedProp;
|
|
6093
6108
|
setCustomProps(newProps);
|
|
6109
|
+
setHasUnsavedChanges2(true);
|
|
6094
6110
|
};
|
|
6095
6111
|
const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
|
|
6096
6112
|
(0, import_react11.useEffect)(() => {
|
|
@@ -6200,6 +6216,7 @@ function CreateAncestryPanel({
|
|
|
6200
6216
|
updateGlobalTree(rootTreeClone);
|
|
6201
6217
|
setBranchStack([...branchStack]);
|
|
6202
6218
|
setIsPickerOpen(false);
|
|
6219
|
+
setHasUnsavedChanges2(true);
|
|
6203
6220
|
try {
|
|
6204
6221
|
setIsSaving(true);
|
|
6205
6222
|
const rootProps = extractCustomPropsFromNode(ancestryMode);
|
|
@@ -6213,6 +6230,7 @@ function CreateAncestryPanel({
|
|
|
6213
6230
|
rootExtras
|
|
6214
6231
|
);
|
|
6215
6232
|
setLastSavedSnapshot(takeSnapshot(rootTreeClone, ancestryName, description, processedSections, [], isPrivate, ancestryMode.abstraction_tree));
|
|
6233
|
+
setHasUnsavedChanges2(false);
|
|
6216
6234
|
if (onRenderFullAncestry) {
|
|
6217
6235
|
const fullTreePayload = {
|
|
6218
6236
|
ancestry_id: ancestryMode.currentAncestryId || "temp_root",
|
|
@@ -6255,6 +6273,7 @@ function CreateAncestryPanel({
|
|
|
6255
6273
|
if (branchIndex !== -1) {
|
|
6256
6274
|
foundParentPath.node.parallel_branches.splice(branchIndex, 1);
|
|
6257
6275
|
updateGlobalTree(rootTreeClone);
|
|
6276
|
+
setHasUnsavedChanges2(true);
|
|
6258
6277
|
try {
|
|
6259
6278
|
setIsSaving(true);
|
|
6260
6279
|
const currentRootProps = extractCustomPropsFromNode(ancestryMode);
|
|
@@ -6276,6 +6295,7 @@ function CreateAncestryPanel({
|
|
|
6276
6295
|
isPrivate,
|
|
6277
6296
|
ancestryMode.abstraction_tree
|
|
6278
6297
|
));
|
|
6298
|
+
setHasUnsavedChanges2(false);
|
|
6279
6299
|
if (onClearAncestryVisuals) {
|
|
6280
6300
|
onClearAncestryVisuals(currentStep.branchId);
|
|
6281
6301
|
}
|
|
@@ -6308,6 +6328,7 @@ function CreateAncestryPanel({
|
|
|
6308
6328
|
if (branchIndex !== -1) {
|
|
6309
6329
|
foundParentPath.node.parallel_branches.splice(branchIndex, 1);
|
|
6310
6330
|
updateGlobalTree(rootTreeClone);
|
|
6331
|
+
setHasUnsavedChanges2(true);
|
|
6311
6332
|
try {
|
|
6312
6333
|
setIsSaving(true);
|
|
6313
6334
|
const currentRootProps = extractCustomPropsFromNode(ancestryMode);
|
|
@@ -6329,6 +6350,7 @@ function CreateAncestryPanel({
|
|
|
6329
6350
|
isPrivate,
|
|
6330
6351
|
ancestryMode.abstraction_tree
|
|
6331
6352
|
));
|
|
6353
|
+
setHasUnsavedChanges2(false);
|
|
6332
6354
|
if (onClearAncestryVisuals) {
|
|
6333
6355
|
onClearAncestryVisuals(currentStep.branchId);
|
|
6334
6356
|
}
|
|
@@ -6590,6 +6612,7 @@ function CreateAncestryPanel({
|
|
|
6590
6612
|
}
|
|
6591
6613
|
setBranchStack(parentStack);
|
|
6592
6614
|
setTargetScrollSectionId(targetFocusId);
|
|
6615
|
+
setHasUnsavedChanges2(true);
|
|
6593
6616
|
if (onRenderFullAncestry) {
|
|
6594
6617
|
const parentStack2 = currentStack;
|
|
6595
6618
|
const rotation = parentStack2.reduce((acc, step) => {
|
|
@@ -6651,7 +6674,6 @@ function CreateAncestryPanel({
|
|
|
6651
6674
|
direction,
|
|
6652
6675
|
tree: {
|
|
6653
6676
|
node: nodeData,
|
|
6654
|
-
node_id: nodeId,
|
|
6655
6677
|
children: [],
|
|
6656
6678
|
relationship: {}
|
|
6657
6679
|
}
|
|
@@ -6673,6 +6695,7 @@ function CreateAncestryPanel({
|
|
|
6673
6695
|
savedMaxIndex: parentIndexToSave,
|
|
6674
6696
|
entryDirection: direction
|
|
6675
6697
|
}]);
|
|
6698
|
+
setHasUnsavedChanges2(true);
|
|
6676
6699
|
if (branch && branch.tree && onRenderFullAncestry) {
|
|
6677
6700
|
const branchAncestryObj = {
|
|
6678
6701
|
ancestry_id: branch.id,
|
|
@@ -6723,6 +6746,10 @@ function CreateAncestryPanel({
|
|
|
6723
6746
|
const currentInputName = overrides.ancestryName !== void 0 ? overrides.ancestryName : ancestryName;
|
|
6724
6747
|
const currentInputDesc = overrides.description !== void 0 ? overrides.description : description;
|
|
6725
6748
|
const currentInputSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
|
|
6749
|
+
if (!keepOpen && !hasUnsavedChanges) {
|
|
6750
|
+
onClose();
|
|
6751
|
+
return;
|
|
6752
|
+
}
|
|
6726
6753
|
if (!currentInputName.trim()) {
|
|
6727
6754
|
alert("O nome n\xE3o pode estar vazio.");
|
|
6728
6755
|
return;
|
|
@@ -6776,6 +6803,7 @@ function CreateAncestryPanel({
|
|
|
6776
6803
|
isPrivate,
|
|
6777
6804
|
ancestryMode.abstraction_tree
|
|
6778
6805
|
));
|
|
6806
|
+
setHasUnsavedChanges2(false);
|
|
6779
6807
|
if (onRenderFullAncestry) {
|
|
6780
6808
|
const rotation = branchStack.reduce((acc, step) => {
|
|
6781
6809
|
return acc + (step.entryDirection === "left" ? -Math.PI / 2 : Math.PI / 2);
|
|
@@ -6827,6 +6855,7 @@ function CreateAncestryPanel({
|
|
|
6827
6855
|
updatedRootTree,
|
|
6828
6856
|
extrasObj
|
|
6829
6857
|
);
|
|
6858
|
+
setHasUnsavedChanges2(false);
|
|
6830
6859
|
setLastSavedSnapshot(takeSnapshot(
|
|
6831
6860
|
updatedRootTree,
|
|
6832
6861
|
currentInputName,
|
|
@@ -6849,6 +6878,7 @@ function CreateAncestryPanel({
|
|
|
6849
6878
|
const newTreeString = JSON.stringify(newRootTree);
|
|
6850
6879
|
if (currentTreeString !== newTreeString) {
|
|
6851
6880
|
updateGlobalTree(newRootTree);
|
|
6881
|
+
setHasUnsavedChanges2(true);
|
|
6852
6882
|
}
|
|
6853
6883
|
}, [description, existingSections]);
|
|
6854
6884
|
const handleTriggerFullRender = () => {
|
|
@@ -6871,6 +6901,7 @@ function CreateAncestryPanel({
|
|
|
6871
6901
|
};
|
|
6872
6902
|
const handleSaveDescriptionInline = (newDesc) => {
|
|
6873
6903
|
setDescription(newDesc);
|
|
6904
|
+
setHasUnsavedChanges2(true);
|
|
6874
6905
|
handleLocalSave(true, { description: newDesc });
|
|
6875
6906
|
};
|
|
6876
6907
|
const swallow = (e) => e.stopPropagation();
|
|
@@ -7000,7 +7031,11 @@ function CreateAncestryPanel({
|
|
|
7000
7031
|
{
|
|
7001
7032
|
type: "text",
|
|
7002
7033
|
value: ancestryName,
|
|
7003
|
-
onChange: (e) =>
|
|
7034
|
+
onChange: (e) => {
|
|
7035
|
+
setAncestryName(e.target.value);
|
|
7036
|
+
setHasUnsavedChanges2(true);
|
|
7037
|
+
},
|
|
7038
|
+
readOnly: isContextLinked,
|
|
7004
7039
|
placeholder: "Nome da Ancestralidade",
|
|
7005
7040
|
className: "text-xl sm:text-2xl font-semibold tracking-tight bg-transparent border-none p-0 focus:ring-2 focus:ring-indigo-500 rounded-md -ml-1.5 px-1.5 w-full outline-none transition-all focus:bg-slate-800/70"
|
|
7006
7041
|
}
|
|
@@ -7649,9 +7684,9 @@ function InSceneCreationForm({
|
|
|
7649
7684
|
};
|
|
7650
7685
|
const handleToggleImageMode = () => {
|
|
7651
7686
|
var _a2, _b;
|
|
7652
|
-
const
|
|
7653
|
-
setUseImageAsTexture(
|
|
7654
|
-
if (
|
|
7687
|
+
const newValue2 = !useImageAsTexture;
|
|
7688
|
+
setUseImageAsTexture(newValue2);
|
|
7689
|
+
if (newValue2) {
|
|
7655
7690
|
const firstImageProp = customProps.find((p) => p.type === "images");
|
|
7656
7691
|
if (firstImageProp && ((_b = (_a2 = firstImageProp.value) == null ? void 0 : _a2[0]) == null ? void 0 : _b.value)) {
|
|
7657
7692
|
const url = firstImageProp.value[0].value;
|
|
@@ -7949,9 +7984,9 @@ function InSceneVersionForm({
|
|
|
7949
7984
|
};
|
|
7950
7985
|
const handleToggleImageMode = () => {
|
|
7951
7986
|
var _a, _b;
|
|
7952
|
-
const
|
|
7953
|
-
setUseImageAsTexture(
|
|
7954
|
-
if (
|
|
7987
|
+
const newValue2 = !useImageAsTexture;
|
|
7988
|
+
setUseImageAsTexture(newValue2);
|
|
7989
|
+
if (newValue2) {
|
|
7955
7990
|
const firstImageProp = customProps.find((p) => p.type === "images");
|
|
7956
7991
|
if (firstImageProp && ((_b = (_a = firstImageProp.value) == null ? void 0 : _a[0]) == null ? void 0 : _b.value)) {
|
|
7957
7992
|
const url = firstImageProp.value[0].value;
|
|
@@ -8371,6 +8406,7 @@ function NodeDetailsPanel({
|
|
|
8371
8406
|
return !!(node == null ? void 0 : node.useImageAsTexture);
|
|
8372
8407
|
});
|
|
8373
8408
|
const [selectedImageUrl, setSelectedImageUrl] = (0, import_react17.useState)((node == null ? void 0 : node.textureImageUrl) ?? null);
|
|
8409
|
+
const [hasUnsavedChanges, setHasUnsavedChanges2] = (0, import_react17.useState)(false);
|
|
8374
8410
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
8375
8411
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
8376
8412
|
initialWidth: isReadMode ? 700 : 440,
|
|
@@ -8408,6 +8444,7 @@ function NodeDetailsPanel({
|
|
|
8408
8444
|
else if ((node == null ? void 0 : node.useImageAsTexture) === "false") setUseImageAsTexture(false);
|
|
8409
8445
|
else setUseImageAsTexture(!!(node == null ? void 0 : node.useImageAsTexture));
|
|
8410
8446
|
setSelectedImageUrl((node == null ? void 0 : node.textureImageUrl) ?? null);
|
|
8447
|
+
setHasUnsavedChanges2(false);
|
|
8411
8448
|
}
|
|
8412
8449
|
}, [node]);
|
|
8413
8450
|
const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
|
|
@@ -8434,6 +8471,7 @@ function NodeDetailsPanel({
|
|
|
8434
8471
|
setIntensity(val);
|
|
8435
8472
|
onIntensityChange == null ? void 0 : onIntensityChange(node.id, val);
|
|
8436
8473
|
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, intensity: val });
|
|
8474
|
+
setHasUnsavedChanges2(true);
|
|
8437
8475
|
};
|
|
8438
8476
|
const handleCopyLink = () => {
|
|
8439
8477
|
if (!(node == null ? void 0 : node.id)) return;
|
|
@@ -8451,14 +8489,17 @@ function NodeDetailsPanel({
|
|
|
8451
8489
|
const v = e.target.value;
|
|
8452
8490
|
setName(v);
|
|
8453
8491
|
onNameChange == null ? void 0 : onNameChange(node.id, v);
|
|
8492
|
+
setHasUnsavedChanges2(true);
|
|
8454
8493
|
};
|
|
8455
8494
|
const handleColorChange = (val) => {
|
|
8456
8495
|
setColor(val);
|
|
8457
8496
|
onColorChange == null ? void 0 : onColorChange(node.id, val);
|
|
8497
|
+
setHasUnsavedChanges2(true);
|
|
8458
8498
|
};
|
|
8459
8499
|
const handleSizeChange = (newSize) => {
|
|
8460
8500
|
setSize(newSize);
|
|
8461
8501
|
onSizeChange == null ? void 0 : onSizeChange(node.id, newSize);
|
|
8502
|
+
setHasUnsavedChanges2(true);
|
|
8462
8503
|
};
|
|
8463
8504
|
const handleAddType = (newType) => {
|
|
8464
8505
|
const trimmed = newType.trim();
|
|
@@ -8466,10 +8507,12 @@ function NodeDetailsPanel({
|
|
|
8466
8507
|
setTypes([...types, trimmed]);
|
|
8467
8508
|
setTypeInput("");
|
|
8468
8509
|
setShowTypeSuggestions(false);
|
|
8510
|
+
setHasUnsavedChanges2(true);
|
|
8469
8511
|
}
|
|
8470
8512
|
};
|
|
8471
8513
|
const handleRemoveType = (indexToRemove) => {
|
|
8472
8514
|
setTypes(types.filter((_, index) => index !== indexToRemove));
|
|
8515
|
+
setHasUnsavedChanges2(true);
|
|
8473
8516
|
};
|
|
8474
8517
|
const handleTypeInputKeyDown = (e) => {
|
|
8475
8518
|
if (e.key === "Enter") {
|
|
@@ -8482,6 +8525,7 @@ function NodeDetailsPanel({
|
|
|
8482
8525
|
const handleAddProp = () => {
|
|
8483
8526
|
const newProp = createNewCustomProperty(customProps);
|
|
8484
8527
|
setCustomProps((p) => [...p, newProp]);
|
|
8528
|
+
setHasUnsavedChanges2(true);
|
|
8485
8529
|
setTimeout(() => {
|
|
8486
8530
|
var _a;
|
|
8487
8531
|
(_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
@@ -8490,19 +8534,21 @@ function NodeDetailsPanel({
|
|
|
8490
8534
|
const handleRemoveProp = (i) => {
|
|
8491
8535
|
const newProps = customProps.filter((_, idx) => idx !== i);
|
|
8492
8536
|
setCustomProps(newProps);
|
|
8537
|
+
setHasUnsavedChanges2(true);
|
|
8493
8538
|
triggerAutoSave({ customProps: newProps });
|
|
8494
8539
|
};
|
|
8495
8540
|
const handleUpdateProp = (index, updatedProp) => {
|
|
8496
8541
|
const newProps = [...customProps];
|
|
8497
8542
|
newProps[index] = updatedProp;
|
|
8498
8543
|
setCustomProps(newProps);
|
|
8544
|
+
setHasUnsavedChanges2(true);
|
|
8499
8545
|
if (!updatedProp.isEditing) {
|
|
8500
8546
|
triggerAutoSave({ customProps: newProps });
|
|
8501
8547
|
}
|
|
8502
8548
|
};
|
|
8503
8549
|
const handleToggleImageMode = () => {
|
|
8504
|
-
const newValue = !useImageAsTexture;
|
|
8505
8550
|
setUseImageAsTexture(newValue);
|
|
8551
|
+
setHasUnsavedChanges2(true);
|
|
8506
8552
|
let activeUrl = null;
|
|
8507
8553
|
if (newValue) {
|
|
8508
8554
|
const firstImageProp = customProps.find((p) => p.type === "images");
|
|
@@ -8524,6 +8570,7 @@ function NodeDetailsPanel({
|
|
|
8524
8570
|
};
|
|
8525
8571
|
const handleSelectTexture = (url) => {
|
|
8526
8572
|
setSelectedImageUrl(url);
|
|
8573
|
+
setHasUnsavedChanges2(true);
|
|
8527
8574
|
onImageChange == null ? void 0 : onImageChange(true, url, color);
|
|
8528
8575
|
onDataUpdate == null ? void 0 : onDataUpdate({
|
|
8529
8576
|
...node,
|
|
@@ -8534,6 +8581,7 @@ function NodeDetailsPanel({
|
|
|
8534
8581
|
};
|
|
8535
8582
|
const handleSaveDescriptionInline = (newDescription) => {
|
|
8536
8583
|
setDescription(newDescription);
|
|
8584
|
+
setHasUnsavedChanges2(true);
|
|
8537
8585
|
onDataUpdate({ ...node, description: newDescription });
|
|
8538
8586
|
triggerAutoSave({ description: newDescription });
|
|
8539
8587
|
};
|
|
@@ -8544,6 +8592,10 @@ function NodeDetailsPanel({
|
|
|
8544
8592
|
const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
|
|
8545
8593
|
const currentExistingSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
|
|
8546
8594
|
const currentIntensity = overrides.intensity !== void 0 ? overrides.intensity : intensity;
|
|
8595
|
+
if (!keepOpen && !hasUnsavedChanges) {
|
|
8596
|
+
onClose();
|
|
8597
|
+
return;
|
|
8598
|
+
}
|
|
8547
8599
|
if (!currentName.trim() || currentTypes.length === 0) {
|
|
8548
8600
|
alert("O campo 'Nome' e pelo menos um 'Tipo' s\xE3o obrigat\xF3rios.");
|
|
8549
8601
|
return;
|
|
@@ -8568,6 +8620,7 @@ function NodeDetailsPanel({
|
|
|
8568
8620
|
};
|
|
8569
8621
|
await onSave(dataToSave, keepOpen);
|
|
8570
8622
|
onDataUpdate(dataToSave);
|
|
8623
|
+
setHasUnsavedChanges2(false);
|
|
8571
8624
|
if (!keepOpen) {
|
|
8572
8625
|
onClose();
|
|
8573
8626
|
}
|
|
@@ -8804,6 +8857,7 @@ function NodeDetailsPanel({
|
|
|
8804
8857
|
initialValue: description,
|
|
8805
8858
|
onSave: (newDescription) => {
|
|
8806
8859
|
setDescription(newDescription);
|
|
8860
|
+
setHasUnsavedChanges2(true);
|
|
8807
8861
|
onDataUpdate((prev) => ({ ...prev, description: newDescription }));
|
|
8808
8862
|
triggerAutoSave({ description: newDescription });
|
|
8809
8863
|
},
|
|
@@ -8863,6 +8917,7 @@ function QuestDetailsPanel({
|
|
|
8863
8917
|
const [existingSections, setExistingSections] = (0, import_react18.useState)((node == null ? void 0 : node.description_sections) || []);
|
|
8864
8918
|
const [isSaving, setIsSaving] = (0, import_react18.useState)(false);
|
|
8865
8919
|
const [isLinkCopied, setIsLinkCopied] = (0, import_react18.useState)(false);
|
|
8920
|
+
const [hasUnsavedChanges, setHasUnsavedChanges2] = (0, import_react18.useState)(false);
|
|
8866
8921
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
8867
8922
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
8868
8923
|
initialWidth: isReadMode ? 700 : 440,
|
|
@@ -8894,6 +8949,7 @@ function QuestDetailsPanel({
|
|
|
8894
8949
|
setIntensity((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
|
|
8895
8950
|
setExistingSections((node == null ? void 0 : node.description_sections) || []);
|
|
8896
8951
|
setCustomProps(extractCustomPropsFromNode(node || {}));
|
|
8952
|
+
setHasUnsavedChanges2(false);
|
|
8897
8953
|
}
|
|
8898
8954
|
}, [node]);
|
|
8899
8955
|
(0, import_react18.useEffect)(() => {
|
|
@@ -8925,16 +8981,19 @@ function QuestDetailsPanel({
|
|
|
8925
8981
|
setRawTitle(val);
|
|
8926
8982
|
const newStandardName = questPrefix ? `${questPrefix} - \xBB ${val || "Sem t\xEDtulo"}` : val;
|
|
8927
8983
|
onNameChange == null ? void 0 : onNameChange(node.id, newStandardName, val);
|
|
8984
|
+
setHasUnsavedChanges2(true);
|
|
8928
8985
|
};
|
|
8929
8986
|
const handleSizeChange = (newSize) => {
|
|
8930
8987
|
setSize(newSize);
|
|
8931
8988
|
onSizeChange == null ? void 0 : onSizeChange(node.id, newSize);
|
|
8989
|
+
setHasUnsavedChanges2(true);
|
|
8932
8990
|
};
|
|
8933
8991
|
const handleStatusChange = (newStatus) => {
|
|
8934
8992
|
setStatus(newStatus);
|
|
8935
8993
|
const newColor = QUEST_STATUS_COLORS3[newStatus];
|
|
8936
8994
|
onColorChange == null ? void 0 : onColorChange(node.id, newColor);
|
|
8937
8995
|
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, status: newStatus, color: newColor });
|
|
8996
|
+
setHasUnsavedChanges2(true);
|
|
8938
8997
|
};
|
|
8939
8998
|
const handleAddType = (newType) => {
|
|
8940
8999
|
const trimmed = newType.trim();
|
|
@@ -8942,11 +9001,13 @@ function QuestDetailsPanel({
|
|
|
8942
9001
|
setTypes([...types, trimmed]);
|
|
8943
9002
|
setTypeInput("");
|
|
8944
9003
|
setShowTypeSuggestions(false);
|
|
9004
|
+
setHasUnsavedChanges2(true);
|
|
8945
9005
|
}
|
|
8946
9006
|
};
|
|
8947
9007
|
const handleRemoveType = (indexToRemove) => {
|
|
8948
9008
|
if (types[indexToRemove] === "quest") return;
|
|
8949
9009
|
setTypes(types.filter((_, index) => index !== indexToRemove));
|
|
9010
|
+
setHasUnsavedChanges2(true);
|
|
8950
9011
|
};
|
|
8951
9012
|
const handleTypeInputKeyDown = (e) => {
|
|
8952
9013
|
if (e.key === "Enter") {
|
|
@@ -8959,6 +9020,7 @@ function QuestDetailsPanel({
|
|
|
8959
9020
|
const handleAddProp = () => {
|
|
8960
9021
|
const newProp = createNewCustomProperty(customProps);
|
|
8961
9022
|
setCustomProps((p) => [...p, newProp]);
|
|
9023
|
+
setHasUnsavedChanges2(true);
|
|
8962
9024
|
setTimeout(() => {
|
|
8963
9025
|
var _a2;
|
|
8964
9026
|
(_a2 = propsEndRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
@@ -8967,18 +9029,21 @@ function QuestDetailsPanel({
|
|
|
8967
9029
|
const handleRemoveProp = (i) => {
|
|
8968
9030
|
const newProps = customProps.filter((_, idx) => idx !== i);
|
|
8969
9031
|
setCustomProps(newProps);
|
|
9032
|
+
setHasUnsavedChanges2(true);
|
|
8970
9033
|
triggerAutoSave({ customProps: newProps });
|
|
8971
9034
|
};
|
|
8972
9035
|
const handleUpdateProp = (index, updatedProp) => {
|
|
8973
9036
|
const newProps = [...customProps];
|
|
8974
9037
|
newProps[index] = updatedProp;
|
|
8975
9038
|
setCustomProps(newProps);
|
|
9039
|
+
setHasUnsavedChanges2(true);
|
|
8976
9040
|
if (!updatedProp.isEditing) {
|
|
8977
9041
|
triggerAutoSave({ customProps: newProps });
|
|
8978
9042
|
}
|
|
8979
9043
|
};
|
|
8980
9044
|
const handleSaveDescriptionInline = (newDescription) => {
|
|
8981
9045
|
setDescription(newDescription);
|
|
9046
|
+
setHasUnsavedChanges2(true);
|
|
8982
9047
|
onDataUpdate({ ...node, description: newDescription });
|
|
8983
9048
|
triggerAutoSave({ description: newDescription });
|
|
8984
9049
|
};
|
|
@@ -8990,6 +9055,10 @@ function QuestDetailsPanel({
|
|
|
8990
9055
|
const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
|
|
8991
9056
|
const currentExistingSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
|
|
8992
9057
|
const currentStatus = overrides.status !== void 0 ? overrides.status : status;
|
|
9058
|
+
if (!keepOpen && !hasUnsavedChanges) {
|
|
9059
|
+
onClose();
|
|
9060
|
+
return;
|
|
9061
|
+
}
|
|
8993
9062
|
if (!currentRawTitle.trim() || currentTypes.length === 0) {
|
|
8994
9063
|
alert("O campo 'T\xEDtulo' e pelo menos um 'Tipo' s\xE3o obrigat\xF3rios.");
|
|
8995
9064
|
return;
|
|
@@ -9019,6 +9088,7 @@ function QuestDetailsPanel({
|
|
|
9019
9088
|
};
|
|
9020
9089
|
await onSave(dataToSave, keepOpen);
|
|
9021
9090
|
onDataUpdate(dataToSave);
|
|
9091
|
+
setHasUnsavedChanges2(false);
|
|
9022
9092
|
if (!keepOpen) {
|
|
9023
9093
|
onClose();
|
|
9024
9094
|
}
|
|
@@ -9255,6 +9325,7 @@ function RelationshipDetailsPanel({
|
|
|
9255
9325
|
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react20.useState)(false);
|
|
9256
9326
|
const [isSaving, setIsSaving] = (0, import_react20.useState)(false);
|
|
9257
9327
|
const [isReadMode, setIsReadMode] = (0, import_react20.useState)(false);
|
|
9328
|
+
const [hasUnsavedChanges, setHasUnsavedChanges2] = (0, import_react20.useState)(false);
|
|
9258
9329
|
const propsEndRef = (0, import_react20.useRef)(null);
|
|
9259
9330
|
const canEdit = (0, import_react20.useMemo)(() => {
|
|
9260
9331
|
const ability = defineAbilityFor(userRole);
|
|
@@ -9267,12 +9338,14 @@ function RelationshipDetailsPanel({
|
|
|
9267
9338
|
setCustomProps(extractCustomPropsFromNode(link || {}));
|
|
9268
9339
|
setSourceLabel((link == null ? void 0 : link.source_label) ?? "");
|
|
9269
9340
|
setTargetLabel((link == null ? void 0 : link.target_label) ?? "");
|
|
9341
|
+
setHasUnsavedChanges2(false);
|
|
9270
9342
|
}, [link]);
|
|
9271
9343
|
const swallow = (e) => e.stopPropagation();
|
|
9272
9344
|
const handleAddProp = () => {
|
|
9273
9345
|
if (!canEdit) return;
|
|
9274
9346
|
const newProp = createNewCustomProperty(customProps);
|
|
9275
9347
|
setCustomProps((p) => [...p, newProp]);
|
|
9348
|
+
setHasUnsavedChanges2(true);
|
|
9276
9349
|
setTimeout(() => {
|
|
9277
9350
|
var _a;
|
|
9278
9351
|
(_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
@@ -9286,6 +9359,10 @@ function RelationshipDetailsPanel({
|
|
|
9286
9359
|
const currentName = overrides.name !== void 0 ? overrides.name : name;
|
|
9287
9360
|
const currentSourceLabel = overrides.sourceLabel !== void 0 ? overrides.sourceLabel : sourceLabel;
|
|
9288
9361
|
const currentTargetLabel = overrides.targetLabel !== void 0 ? overrides.targetLabel : targetLabel;
|
|
9362
|
+
if (!keepOpen && !hasUnsavedChanges) {
|
|
9363
|
+
onClose();
|
|
9364
|
+
return;
|
|
9365
|
+
}
|
|
9289
9366
|
setIsSaving(true);
|
|
9290
9367
|
try {
|
|
9291
9368
|
const extrasObj = toObjectFromCustomProps(currentCustomProps.filter((p) => !p.isEditing));
|
|
@@ -9305,6 +9382,7 @@ function RelationshipDetailsPanel({
|
|
|
9305
9382
|
if (currentTargetLabel.trim()) dataToSave.target_label = currentTargetLabel.trim();
|
|
9306
9383
|
await onSave(dataToSave, keepOpen);
|
|
9307
9384
|
onDataUpdate(dataToSave);
|
|
9385
|
+
setHasUnsavedChanges2(false);
|
|
9308
9386
|
if (!keepOpen) {
|
|
9309
9387
|
onClose();
|
|
9310
9388
|
}
|
|
@@ -9318,18 +9396,21 @@ function RelationshipDetailsPanel({
|
|
|
9318
9396
|
const handleSaveDescriptionInline = (newDescription) => {
|
|
9319
9397
|
if (!canEdit) return;
|
|
9320
9398
|
setDescription(newDescription);
|
|
9399
|
+
setHasUnsavedChanges2(true);
|
|
9321
9400
|
onDataUpdate((prev) => ({ ...prev, description: newDescription }));
|
|
9322
9401
|
triggerAutoSave({ description: newDescription });
|
|
9323
9402
|
};
|
|
9324
9403
|
const handleRemoveProp = (i) => {
|
|
9325
9404
|
const newProps = customProps.filter((_, idx) => idx !== i);
|
|
9326
9405
|
setCustomProps(newProps);
|
|
9406
|
+
setHasUnsavedChanges2(true);
|
|
9327
9407
|
triggerAutoSave({ customProps: newProps });
|
|
9328
9408
|
};
|
|
9329
9409
|
const handleUpdateProp = (index, updatedProp) => {
|
|
9330
9410
|
const newProps = [...customProps];
|
|
9331
9411
|
newProps[index] = updatedProp;
|
|
9332
9412
|
setCustomProps(newProps);
|
|
9413
|
+
setHasUnsavedChanges2(true);
|
|
9333
9414
|
if (!updatedProp.isEditing) {
|
|
9334
9415
|
triggerAutoSave({ customProps: newProps });
|
|
9335
9416
|
}
|
|
@@ -9382,7 +9463,10 @@ function RelationshipDetailsPanel({
|
|
|
9382
9463
|
{
|
|
9383
9464
|
type: "text",
|
|
9384
9465
|
value: name,
|
|
9385
|
-
onChange: (e) =>
|
|
9466
|
+
onChange: (e) => {
|
|
9467
|
+
setName(e.target.value);
|
|
9468
|
+
setHasUnsavedChanges2(true);
|
|
9469
|
+
},
|
|
9386
9470
|
placeholder: "Ex: Controla, Pertence a, Fornece...",
|
|
9387
9471
|
disabled: !canEdit,
|
|
9388
9472
|
className: `w-full bg-slate-800/70 p-2 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-400/60
|
|
@@ -9394,7 +9478,10 @@ function RelationshipDetailsPanel({
|
|
|
9394
9478
|
{
|
|
9395
9479
|
type: "text",
|
|
9396
9480
|
value: sourceLabel,
|
|
9397
|
-
onChange: (e) =>
|
|
9481
|
+
onChange: (e) => {
|
|
9482
|
+
setSourceLabel(e.target.value);
|
|
9483
|
+
setHasUnsavedChanges2(true);
|
|
9484
|
+
},
|
|
9398
9485
|
placeholder: "Ex: Conceitos",
|
|
9399
9486
|
disabled: !canEdit,
|
|
9400
9487
|
className: `w-full bg-slate-900/60 p-2 text-xs rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-violet-400/60 placeholder:text-slate-600
|
|
@@ -9406,7 +9493,10 @@ function RelationshipDetailsPanel({
|
|
|
9406
9493
|
{
|
|
9407
9494
|
type: "text",
|
|
9408
9495
|
value: targetLabel,
|
|
9409
|
-
onChange: (e) =>
|
|
9496
|
+
onChange: (e) => {
|
|
9497
|
+
setTargetLabel(e.target.value);
|
|
9498
|
+
setHasUnsavedChanges2(true);
|
|
9499
|
+
},
|
|
9410
9500
|
placeholder: "Ex: Refer\xEAncias",
|
|
9411
9501
|
disabled: !canEdit,
|
|
9412
9502
|
className: `w-full bg-slate-900/60 p-2 text-xs rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-violet-400/60 placeholder:text-slate-600
|
|
@@ -9483,6 +9573,7 @@ function RelationshipDetailsPanel({
|
|
|
9483
9573
|
onSave: (newDescription) => {
|
|
9484
9574
|
if (!canEdit) return;
|
|
9485
9575
|
setDescription(newDescription);
|
|
9576
|
+
setHasUnsavedChanges2(true);
|
|
9486
9577
|
onDataUpdate((prev) => ({ ...prev, description: newDescription }));
|
|
9487
9578
|
triggerAutoSave({ description: newDescription });
|
|
9488
9579
|
},
|
package/dist/index.mjs
CHANGED
|
@@ -3158,6 +3158,7 @@ function calculateNodePositions(nodes) {
|
|
|
3158
3158
|
return positions;
|
|
3159
3159
|
}
|
|
3160
3160
|
function updateTooltip({ tooltipEl, hoveredNode, hoveredLink, camera, mountEl, isSceneBusy, parentData, ancestryData }) {
|
|
3161
|
+
var _a, _b;
|
|
3161
3162
|
if (!tooltipEl || !camera || !mountEl) return;
|
|
3162
3163
|
let content = "";
|
|
3163
3164
|
let positionTarget = null;
|
|
@@ -3170,17 +3171,21 @@ function updateTooltip({ tooltipEl, hoveredNode, hoveredLink, camera, mountEl, i
|
|
|
3170
3171
|
content = generateTooltipHtml(hoveredNode.userData, parentData, ancestryData);
|
|
3171
3172
|
}
|
|
3172
3173
|
} else if (hoveredLink && !isSceneBusy) {
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3174
|
+
const linkData = hoveredLink.userData.isAncestryLink ? hoveredLink.userData.relationship || {} : hoveredLink.userData;
|
|
3175
|
+
const hasContent = ((_a = linkData.name) == null ? void 0 : _a.trim()) || ((_b = linkData.description) == null ? void 0 : _b.trim());
|
|
3176
|
+
if (hasContent) {
|
|
3177
|
+
currentId = `link_${hoveredLink.userData.id}`;
|
|
3178
|
+
if (hoveredLink.userData.isCurved) {
|
|
3179
|
+
const positions = hoveredLink.geometry.attributes.position.array;
|
|
3180
|
+
const midIndex = Math.floor(positions.length / 2 / 3) * 3;
|
|
3181
|
+
positionTarget = new THREE2.Vector3(positions[midIndex], positions[midIndex + 1], positions[midIndex + 2]);
|
|
3182
|
+
} else {
|
|
3183
|
+
positionTarget = new THREE2.Vector3().addVectors(hoveredLink.userData.sourceNode.position, hoveredLink.userData.targetNode.position).multiplyScalar(0.5);
|
|
3184
|
+
}
|
|
3185
|
+
isLink = true;
|
|
3186
|
+
if (tooltipEl.dataset.currentId !== currentId) {
|
|
3187
|
+
content = generateLinkTooltipHtml(linkData, parentData, ancestryData);
|
|
3188
|
+
}
|
|
3184
3189
|
}
|
|
3185
3190
|
}
|
|
3186
3191
|
if (positionTarget) {
|
|
@@ -3489,9 +3494,9 @@ function CustomPropertyDisplay({
|
|
|
3489
3494
|
};
|
|
3490
3495
|
const handleRemoveListItem = (j) => setTempProp((p) => ({ ...p, value: p.value.filter((_, k) => k !== j) }));
|
|
3491
3496
|
const handleListItemChange = (j, f, v) => setTempProp((p) => {
|
|
3492
|
-
const
|
|
3493
|
-
|
|
3494
|
-
return { ...p, value:
|
|
3497
|
+
const newValue2 = [...p.value];
|
|
3498
|
+
newValue2[j] = { ...newValue2[j], [f]: v };
|
|
3499
|
+
return { ...p, value: newValue2 };
|
|
3495
3500
|
});
|
|
3496
3501
|
const baseInput = "w-full bg-slate-800/70 p-2 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-400/60 transition-all duration-150";
|
|
3497
3502
|
const renderEditView = () => {
|
|
@@ -3545,14 +3550,14 @@ function CustomPropertyDisplay({
|
|
|
3545
3550
|
const inputClass = `${baseInput} ${noSpinnerClass}`;
|
|
3546
3551
|
const handleDateTypeChange = (newDateType) => {
|
|
3547
3552
|
var _a3, _b2, _c2;
|
|
3548
|
-
let
|
|
3553
|
+
let newValue2 = { type: newDateType };
|
|
3549
3554
|
if (newDateType === "Date Interval") {
|
|
3550
|
-
|
|
3551
|
-
|
|
3555
|
+
newValue2.start = ((_a3 = tempProp.value) == null ? void 0 : _a3.start) || "";
|
|
3556
|
+
newValue2.end = ((_b2 = tempProp.value) == null ? void 0 : _b2.end) || "";
|
|
3552
3557
|
} else {
|
|
3553
|
-
|
|
3558
|
+
newValue2.value = ((_c2 = tempProp.value) == null ? void 0 : _c2.type) === newDateType ? tempProp.value.value : "";
|
|
3554
3559
|
}
|
|
3555
|
-
handlePropChange("value",
|
|
3560
|
+
handlePropChange("value", newValue2);
|
|
3556
3561
|
};
|
|
3557
3562
|
const handleDateValueChange = (dateField, dateValue) => {
|
|
3558
3563
|
handlePropChange("value", { ...tempProp.value, [dateField]: dateValue });
|
|
@@ -5781,6 +5786,7 @@ var NodeItem = ({ nodeData, onSelectParent, onViewSelect, highlightedPathIds = [
|
|
|
5781
5786
|
e.stopPropagation();
|
|
5782
5787
|
if (isEditable) {
|
|
5783
5788
|
onSelectParent(itemId);
|
|
5789
|
+
setHasUnsavedChanges(true);
|
|
5784
5790
|
} else if (onViewSelect) {
|
|
5785
5791
|
onViewSelect(itemId);
|
|
5786
5792
|
}
|
|
@@ -5793,9 +5799,11 @@ var NodeItem = ({ nodeData, onSelectParent, onViewSelect, highlightedPathIds = [
|
|
|
5793
5799
|
level > 0 && isEditable && /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-1 animate-in fade-in duration-200" }, !nodeData.is_section && /* @__PURE__ */ React10.createElement("button", { onClick: (e) => {
|
|
5794
5800
|
e.stopPropagation();
|
|
5795
5801
|
onEditRelationship(path, nodeData.relationship || {});
|
|
5802
|
+
setHasUnsavedChanges(true);
|
|
5796
5803
|
}, className: "w-6 h-6 grid place-content-center rounded-full hover:bg-cyan-500/20 text-cyan-400 transition-colors flex-shrink-0", title: "Editar detalhes da rela\xE7\xE3o" }, /* @__PURE__ */ React10.createElement(FiEdit23, { size: 12 })), /* @__PURE__ */ React10.createElement("button", { onClick: (e) => {
|
|
5797
5804
|
e.stopPropagation();
|
|
5798
5805
|
onRemoveNode(path);
|
|
5806
|
+
setHasUnsavedChanges(true);
|
|
5799
5807
|
}, className: "w-6 h-6 grid place-content-center rounded-full hover:bg-red-500/20 text-red-400 text-lg transition-colors flex-shrink-0", title: "Remover Node" }, "\xD7"))
|
|
5800
5808
|
), hasChildren && /* @__PURE__ */ React10.createElement("div", { className: "mt-2 space-y-2 pl-8" }, nodeData.children.map((child, index) => /* @__PURE__ */ React10.createElement(
|
|
5801
5809
|
NodeItem,
|
|
@@ -5851,6 +5859,7 @@ function CreateAncestryPanel({
|
|
|
5851
5859
|
} = ancestryMode;
|
|
5852
5860
|
const [isSaving, setIsSaving] = useState11(false);
|
|
5853
5861
|
const [isLinkCopied, setIsLinkCopied] = useState11(false);
|
|
5862
|
+
const [hasUnsavedChanges, setHasUnsavedChanges2] = useState11(false);
|
|
5854
5863
|
const [showDeleteBranchConfirm, setShowDeleteBranchConfirm] = useState11(false);
|
|
5855
5864
|
const handleCopyLink = (e) => {
|
|
5856
5865
|
e.stopPropagation();
|
|
@@ -5918,12 +5927,14 @@ function CreateAncestryPanel({
|
|
|
5918
5927
|
};
|
|
5919
5928
|
const handleSelectAncestryParent = (nodeId, isAbstraction = false) => {
|
|
5920
5929
|
setAncestryMode((prev) => isAbstraction ? { ...prev, selectedAbstractionParentId: nodeId } : { ...prev, selectedParentId: nodeId });
|
|
5930
|
+
setHasUnsavedChanges2(true);
|
|
5921
5931
|
};
|
|
5922
5932
|
const handleToggleAddMode = (isAbstraction = false) => {
|
|
5923
5933
|
if (isAbstraction && !ancestryMode.isAddingAbstractionNodes) {
|
|
5924
5934
|
setTargetRenderNodeId(null);
|
|
5925
5935
|
}
|
|
5926
5936
|
setAncestryMode((prev) => isAbstraction ? { ...prev, isAddingAbstractionNodes: !prev.isAddingAbstractionNodes } : { ...prev, isAddingNodes: !prev.isAddingNodes });
|
|
5937
|
+
setHasUnsavedChanges2(true);
|
|
5927
5938
|
};
|
|
5928
5939
|
const handleRemoveNode = useCallback2((pathToRemove, isAbstraction = false) => {
|
|
5929
5940
|
if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) return;
|
|
@@ -5941,6 +5952,7 @@ function CreateAncestryPanel({
|
|
|
5941
5952
|
const indexToRemove = pathToRemove[pathToRemove.length - 1];
|
|
5942
5953
|
if (currentParent.children && currentParent.children.length > indexToRemove) {
|
|
5943
5954
|
currentParent.children.splice(indexToRemove, 1);
|
|
5955
|
+
setHasUnsavedChanges2(true);
|
|
5944
5956
|
}
|
|
5945
5957
|
return { ...prev, [treeKey]: newTree };
|
|
5946
5958
|
});
|
|
@@ -5999,6 +6011,7 @@ function CreateAncestryPanel({
|
|
|
5999
6011
|
updateGlobalTree(rootTreeClone);
|
|
6000
6012
|
}
|
|
6001
6013
|
setAncestryMode((prev) => ({ ...prev, [treeKey]: rootTreeClone }));
|
|
6014
|
+
setHasUnsavedChanges2(true);
|
|
6002
6015
|
} else {
|
|
6003
6016
|
alert("N\xE3o \xE9 poss\xEDvel mover um node para dentro de seus pr\xF3prios descendentes.");
|
|
6004
6017
|
}
|
|
@@ -6071,6 +6084,7 @@ function CreateAncestryPanel({
|
|
|
6071
6084
|
const handleAddProp = () => {
|
|
6072
6085
|
const newProp = createNewCustomProperty(customProps);
|
|
6073
6086
|
setCustomProps((p) => [...p, newProp]);
|
|
6087
|
+
setHasUnsavedChanges2(true);
|
|
6074
6088
|
setTimeout(() => {
|
|
6075
6089
|
var _a;
|
|
6076
6090
|
(_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
@@ -6079,11 +6093,13 @@ function CreateAncestryPanel({
|
|
|
6079
6093
|
const handleRemoveProp = (i) => {
|
|
6080
6094
|
const newProps = customProps.filter((_, idx) => idx !== i);
|
|
6081
6095
|
setCustomProps(newProps);
|
|
6096
|
+
setHasUnsavedChanges2(true);
|
|
6082
6097
|
};
|
|
6083
6098
|
const handleUpdateProp = (index, updatedProp) => {
|
|
6084
6099
|
const newProps = [...customProps];
|
|
6085
6100
|
newProps[index] = updatedProp;
|
|
6086
6101
|
setCustomProps(newProps);
|
|
6102
|
+
setHasUnsavedChanges2(true);
|
|
6087
6103
|
};
|
|
6088
6104
|
const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
|
|
6089
6105
|
useEffect10(() => {
|
|
@@ -6193,6 +6209,7 @@ function CreateAncestryPanel({
|
|
|
6193
6209
|
updateGlobalTree(rootTreeClone);
|
|
6194
6210
|
setBranchStack([...branchStack]);
|
|
6195
6211
|
setIsPickerOpen(false);
|
|
6212
|
+
setHasUnsavedChanges2(true);
|
|
6196
6213
|
try {
|
|
6197
6214
|
setIsSaving(true);
|
|
6198
6215
|
const rootProps = extractCustomPropsFromNode(ancestryMode);
|
|
@@ -6206,6 +6223,7 @@ function CreateAncestryPanel({
|
|
|
6206
6223
|
rootExtras
|
|
6207
6224
|
);
|
|
6208
6225
|
setLastSavedSnapshot(takeSnapshot(rootTreeClone, ancestryName, description, processedSections, [], isPrivate, ancestryMode.abstraction_tree));
|
|
6226
|
+
setHasUnsavedChanges2(false);
|
|
6209
6227
|
if (onRenderFullAncestry) {
|
|
6210
6228
|
const fullTreePayload = {
|
|
6211
6229
|
ancestry_id: ancestryMode.currentAncestryId || "temp_root",
|
|
@@ -6248,6 +6266,7 @@ function CreateAncestryPanel({
|
|
|
6248
6266
|
if (branchIndex !== -1) {
|
|
6249
6267
|
foundParentPath.node.parallel_branches.splice(branchIndex, 1);
|
|
6250
6268
|
updateGlobalTree(rootTreeClone);
|
|
6269
|
+
setHasUnsavedChanges2(true);
|
|
6251
6270
|
try {
|
|
6252
6271
|
setIsSaving(true);
|
|
6253
6272
|
const currentRootProps = extractCustomPropsFromNode(ancestryMode);
|
|
@@ -6269,6 +6288,7 @@ function CreateAncestryPanel({
|
|
|
6269
6288
|
isPrivate,
|
|
6270
6289
|
ancestryMode.abstraction_tree
|
|
6271
6290
|
));
|
|
6291
|
+
setHasUnsavedChanges2(false);
|
|
6272
6292
|
if (onClearAncestryVisuals) {
|
|
6273
6293
|
onClearAncestryVisuals(currentStep.branchId);
|
|
6274
6294
|
}
|
|
@@ -6301,6 +6321,7 @@ function CreateAncestryPanel({
|
|
|
6301
6321
|
if (branchIndex !== -1) {
|
|
6302
6322
|
foundParentPath.node.parallel_branches.splice(branchIndex, 1);
|
|
6303
6323
|
updateGlobalTree(rootTreeClone);
|
|
6324
|
+
setHasUnsavedChanges2(true);
|
|
6304
6325
|
try {
|
|
6305
6326
|
setIsSaving(true);
|
|
6306
6327
|
const currentRootProps = extractCustomPropsFromNode(ancestryMode);
|
|
@@ -6322,6 +6343,7 @@ function CreateAncestryPanel({
|
|
|
6322
6343
|
isPrivate,
|
|
6323
6344
|
ancestryMode.abstraction_tree
|
|
6324
6345
|
));
|
|
6346
|
+
setHasUnsavedChanges2(false);
|
|
6325
6347
|
if (onClearAncestryVisuals) {
|
|
6326
6348
|
onClearAncestryVisuals(currentStep.branchId);
|
|
6327
6349
|
}
|
|
@@ -6583,6 +6605,7 @@ function CreateAncestryPanel({
|
|
|
6583
6605
|
}
|
|
6584
6606
|
setBranchStack(parentStack);
|
|
6585
6607
|
setTargetScrollSectionId(targetFocusId);
|
|
6608
|
+
setHasUnsavedChanges2(true);
|
|
6586
6609
|
if (onRenderFullAncestry) {
|
|
6587
6610
|
const parentStack2 = currentStack;
|
|
6588
6611
|
const rotation = parentStack2.reduce((acc, step) => {
|
|
@@ -6644,7 +6667,6 @@ function CreateAncestryPanel({
|
|
|
6644
6667
|
direction,
|
|
6645
6668
|
tree: {
|
|
6646
6669
|
node: nodeData,
|
|
6647
|
-
node_id: nodeId,
|
|
6648
6670
|
children: [],
|
|
6649
6671
|
relationship: {}
|
|
6650
6672
|
}
|
|
@@ -6666,6 +6688,7 @@ function CreateAncestryPanel({
|
|
|
6666
6688
|
savedMaxIndex: parentIndexToSave,
|
|
6667
6689
|
entryDirection: direction
|
|
6668
6690
|
}]);
|
|
6691
|
+
setHasUnsavedChanges2(true);
|
|
6669
6692
|
if (branch && branch.tree && onRenderFullAncestry) {
|
|
6670
6693
|
const branchAncestryObj = {
|
|
6671
6694
|
ancestry_id: branch.id,
|
|
@@ -6716,6 +6739,10 @@ function CreateAncestryPanel({
|
|
|
6716
6739
|
const currentInputName = overrides.ancestryName !== void 0 ? overrides.ancestryName : ancestryName;
|
|
6717
6740
|
const currentInputDesc = overrides.description !== void 0 ? overrides.description : description;
|
|
6718
6741
|
const currentInputSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
|
|
6742
|
+
if (!keepOpen && !hasUnsavedChanges) {
|
|
6743
|
+
onClose();
|
|
6744
|
+
return;
|
|
6745
|
+
}
|
|
6719
6746
|
if (!currentInputName.trim()) {
|
|
6720
6747
|
alert("O nome n\xE3o pode estar vazio.");
|
|
6721
6748
|
return;
|
|
@@ -6769,6 +6796,7 @@ function CreateAncestryPanel({
|
|
|
6769
6796
|
isPrivate,
|
|
6770
6797
|
ancestryMode.abstraction_tree
|
|
6771
6798
|
));
|
|
6799
|
+
setHasUnsavedChanges2(false);
|
|
6772
6800
|
if (onRenderFullAncestry) {
|
|
6773
6801
|
const rotation = branchStack.reduce((acc, step) => {
|
|
6774
6802
|
return acc + (step.entryDirection === "left" ? -Math.PI / 2 : Math.PI / 2);
|
|
@@ -6820,6 +6848,7 @@ function CreateAncestryPanel({
|
|
|
6820
6848
|
updatedRootTree,
|
|
6821
6849
|
extrasObj
|
|
6822
6850
|
);
|
|
6851
|
+
setHasUnsavedChanges2(false);
|
|
6823
6852
|
setLastSavedSnapshot(takeSnapshot(
|
|
6824
6853
|
updatedRootTree,
|
|
6825
6854
|
currentInputName,
|
|
@@ -6842,6 +6871,7 @@ function CreateAncestryPanel({
|
|
|
6842
6871
|
const newTreeString = JSON.stringify(newRootTree);
|
|
6843
6872
|
if (currentTreeString !== newTreeString) {
|
|
6844
6873
|
updateGlobalTree(newRootTree);
|
|
6874
|
+
setHasUnsavedChanges2(true);
|
|
6845
6875
|
}
|
|
6846
6876
|
}, [description, existingSections]);
|
|
6847
6877
|
const handleTriggerFullRender = () => {
|
|
@@ -6864,6 +6894,7 @@ function CreateAncestryPanel({
|
|
|
6864
6894
|
};
|
|
6865
6895
|
const handleSaveDescriptionInline = (newDesc) => {
|
|
6866
6896
|
setDescription(newDesc);
|
|
6897
|
+
setHasUnsavedChanges2(true);
|
|
6867
6898
|
handleLocalSave(true, { description: newDesc });
|
|
6868
6899
|
};
|
|
6869
6900
|
const swallow = (e) => e.stopPropagation();
|
|
@@ -6993,7 +7024,11 @@ function CreateAncestryPanel({
|
|
|
6993
7024
|
{
|
|
6994
7025
|
type: "text",
|
|
6995
7026
|
value: ancestryName,
|
|
6996
|
-
onChange: (e) =>
|
|
7027
|
+
onChange: (e) => {
|
|
7028
|
+
setAncestryName(e.target.value);
|
|
7029
|
+
setHasUnsavedChanges2(true);
|
|
7030
|
+
},
|
|
7031
|
+
readOnly: isContextLinked,
|
|
6997
7032
|
placeholder: "Nome da Ancestralidade",
|
|
6998
7033
|
className: "text-xl sm:text-2xl font-semibold tracking-tight bg-transparent border-none p-0 focus:ring-2 focus:ring-indigo-500 rounded-md -ml-1.5 px-1.5 w-full outline-none transition-all focus:bg-slate-800/70"
|
|
6999
7034
|
}
|
|
@@ -7642,9 +7677,9 @@ function InSceneCreationForm({
|
|
|
7642
7677
|
};
|
|
7643
7678
|
const handleToggleImageMode = () => {
|
|
7644
7679
|
var _a2, _b;
|
|
7645
|
-
const
|
|
7646
|
-
setUseImageAsTexture(
|
|
7647
|
-
if (
|
|
7680
|
+
const newValue2 = !useImageAsTexture;
|
|
7681
|
+
setUseImageAsTexture(newValue2);
|
|
7682
|
+
if (newValue2) {
|
|
7648
7683
|
const firstImageProp = customProps.find((p) => p.type === "images");
|
|
7649
7684
|
if (firstImageProp && ((_b = (_a2 = firstImageProp.value) == null ? void 0 : _a2[0]) == null ? void 0 : _b.value)) {
|
|
7650
7685
|
const url = firstImageProp.value[0].value;
|
|
@@ -7942,9 +7977,9 @@ function InSceneVersionForm({
|
|
|
7942
7977
|
};
|
|
7943
7978
|
const handleToggleImageMode = () => {
|
|
7944
7979
|
var _a, _b;
|
|
7945
|
-
const
|
|
7946
|
-
setUseImageAsTexture(
|
|
7947
|
-
if (
|
|
7980
|
+
const newValue2 = !useImageAsTexture;
|
|
7981
|
+
setUseImageAsTexture(newValue2);
|
|
7982
|
+
if (newValue2) {
|
|
7948
7983
|
const firstImageProp = customProps.find((p) => p.type === "images");
|
|
7949
7984
|
if (firstImageProp && ((_b = (_a = firstImageProp.value) == null ? void 0 : _a[0]) == null ? void 0 : _b.value)) {
|
|
7950
7985
|
const url = firstImageProp.value[0].value;
|
|
@@ -8364,6 +8399,7 @@ function NodeDetailsPanel({
|
|
|
8364
8399
|
return !!(node == null ? void 0 : node.useImageAsTexture);
|
|
8365
8400
|
});
|
|
8366
8401
|
const [selectedImageUrl, setSelectedImageUrl] = useState17((node == null ? void 0 : node.textureImageUrl) ?? null);
|
|
8402
|
+
const [hasUnsavedChanges, setHasUnsavedChanges2] = useState17(false);
|
|
8367
8403
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
8368
8404
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
8369
8405
|
initialWidth: isReadMode ? 700 : 440,
|
|
@@ -8401,6 +8437,7 @@ function NodeDetailsPanel({
|
|
|
8401
8437
|
else if ((node == null ? void 0 : node.useImageAsTexture) === "false") setUseImageAsTexture(false);
|
|
8402
8438
|
else setUseImageAsTexture(!!(node == null ? void 0 : node.useImageAsTexture));
|
|
8403
8439
|
setSelectedImageUrl((node == null ? void 0 : node.textureImageUrl) ?? null);
|
|
8440
|
+
setHasUnsavedChanges2(false);
|
|
8404
8441
|
}
|
|
8405
8442
|
}, [node]);
|
|
8406
8443
|
const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
|
|
@@ -8427,6 +8464,7 @@ function NodeDetailsPanel({
|
|
|
8427
8464
|
setIntensity(val);
|
|
8428
8465
|
onIntensityChange == null ? void 0 : onIntensityChange(node.id, val);
|
|
8429
8466
|
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, intensity: val });
|
|
8467
|
+
setHasUnsavedChanges2(true);
|
|
8430
8468
|
};
|
|
8431
8469
|
const handleCopyLink = () => {
|
|
8432
8470
|
if (!(node == null ? void 0 : node.id)) return;
|
|
@@ -8444,14 +8482,17 @@ function NodeDetailsPanel({
|
|
|
8444
8482
|
const v = e.target.value;
|
|
8445
8483
|
setName(v);
|
|
8446
8484
|
onNameChange == null ? void 0 : onNameChange(node.id, v);
|
|
8485
|
+
setHasUnsavedChanges2(true);
|
|
8447
8486
|
};
|
|
8448
8487
|
const handleColorChange = (val) => {
|
|
8449
8488
|
setColor(val);
|
|
8450
8489
|
onColorChange == null ? void 0 : onColorChange(node.id, val);
|
|
8490
|
+
setHasUnsavedChanges2(true);
|
|
8451
8491
|
};
|
|
8452
8492
|
const handleSizeChange = (newSize) => {
|
|
8453
8493
|
setSize(newSize);
|
|
8454
8494
|
onSizeChange == null ? void 0 : onSizeChange(node.id, newSize);
|
|
8495
|
+
setHasUnsavedChanges2(true);
|
|
8455
8496
|
};
|
|
8456
8497
|
const handleAddType = (newType) => {
|
|
8457
8498
|
const trimmed = newType.trim();
|
|
@@ -8459,10 +8500,12 @@ function NodeDetailsPanel({
|
|
|
8459
8500
|
setTypes([...types, trimmed]);
|
|
8460
8501
|
setTypeInput("");
|
|
8461
8502
|
setShowTypeSuggestions(false);
|
|
8503
|
+
setHasUnsavedChanges2(true);
|
|
8462
8504
|
}
|
|
8463
8505
|
};
|
|
8464
8506
|
const handleRemoveType = (indexToRemove) => {
|
|
8465
8507
|
setTypes(types.filter((_, index) => index !== indexToRemove));
|
|
8508
|
+
setHasUnsavedChanges2(true);
|
|
8466
8509
|
};
|
|
8467
8510
|
const handleTypeInputKeyDown = (e) => {
|
|
8468
8511
|
if (e.key === "Enter") {
|
|
@@ -8475,6 +8518,7 @@ function NodeDetailsPanel({
|
|
|
8475
8518
|
const handleAddProp = () => {
|
|
8476
8519
|
const newProp = createNewCustomProperty(customProps);
|
|
8477
8520
|
setCustomProps((p) => [...p, newProp]);
|
|
8521
|
+
setHasUnsavedChanges2(true);
|
|
8478
8522
|
setTimeout(() => {
|
|
8479
8523
|
var _a;
|
|
8480
8524
|
(_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
@@ -8483,19 +8527,21 @@ function NodeDetailsPanel({
|
|
|
8483
8527
|
const handleRemoveProp = (i) => {
|
|
8484
8528
|
const newProps = customProps.filter((_, idx) => idx !== i);
|
|
8485
8529
|
setCustomProps(newProps);
|
|
8530
|
+
setHasUnsavedChanges2(true);
|
|
8486
8531
|
triggerAutoSave({ customProps: newProps });
|
|
8487
8532
|
};
|
|
8488
8533
|
const handleUpdateProp = (index, updatedProp) => {
|
|
8489
8534
|
const newProps = [...customProps];
|
|
8490
8535
|
newProps[index] = updatedProp;
|
|
8491
8536
|
setCustomProps(newProps);
|
|
8537
|
+
setHasUnsavedChanges2(true);
|
|
8492
8538
|
if (!updatedProp.isEditing) {
|
|
8493
8539
|
triggerAutoSave({ customProps: newProps });
|
|
8494
8540
|
}
|
|
8495
8541
|
};
|
|
8496
8542
|
const handleToggleImageMode = () => {
|
|
8497
|
-
const newValue = !useImageAsTexture;
|
|
8498
8543
|
setUseImageAsTexture(newValue);
|
|
8544
|
+
setHasUnsavedChanges2(true);
|
|
8499
8545
|
let activeUrl = null;
|
|
8500
8546
|
if (newValue) {
|
|
8501
8547
|
const firstImageProp = customProps.find((p) => p.type === "images");
|
|
@@ -8517,6 +8563,7 @@ function NodeDetailsPanel({
|
|
|
8517
8563
|
};
|
|
8518
8564
|
const handleSelectTexture = (url) => {
|
|
8519
8565
|
setSelectedImageUrl(url);
|
|
8566
|
+
setHasUnsavedChanges2(true);
|
|
8520
8567
|
onImageChange == null ? void 0 : onImageChange(true, url, color);
|
|
8521
8568
|
onDataUpdate == null ? void 0 : onDataUpdate({
|
|
8522
8569
|
...node,
|
|
@@ -8527,6 +8574,7 @@ function NodeDetailsPanel({
|
|
|
8527
8574
|
};
|
|
8528
8575
|
const handleSaveDescriptionInline = (newDescription) => {
|
|
8529
8576
|
setDescription(newDescription);
|
|
8577
|
+
setHasUnsavedChanges2(true);
|
|
8530
8578
|
onDataUpdate({ ...node, description: newDescription });
|
|
8531
8579
|
triggerAutoSave({ description: newDescription });
|
|
8532
8580
|
};
|
|
@@ -8537,6 +8585,10 @@ function NodeDetailsPanel({
|
|
|
8537
8585
|
const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
|
|
8538
8586
|
const currentExistingSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
|
|
8539
8587
|
const currentIntensity = overrides.intensity !== void 0 ? overrides.intensity : intensity;
|
|
8588
|
+
if (!keepOpen && !hasUnsavedChanges) {
|
|
8589
|
+
onClose();
|
|
8590
|
+
return;
|
|
8591
|
+
}
|
|
8540
8592
|
if (!currentName.trim() || currentTypes.length === 0) {
|
|
8541
8593
|
alert("O campo 'Nome' e pelo menos um 'Tipo' s\xE3o obrigat\xF3rios.");
|
|
8542
8594
|
return;
|
|
@@ -8561,6 +8613,7 @@ function NodeDetailsPanel({
|
|
|
8561
8613
|
};
|
|
8562
8614
|
await onSave(dataToSave, keepOpen);
|
|
8563
8615
|
onDataUpdate(dataToSave);
|
|
8616
|
+
setHasUnsavedChanges2(false);
|
|
8564
8617
|
if (!keepOpen) {
|
|
8565
8618
|
onClose();
|
|
8566
8619
|
}
|
|
@@ -8797,6 +8850,7 @@ function NodeDetailsPanel({
|
|
|
8797
8850
|
initialValue: description,
|
|
8798
8851
|
onSave: (newDescription) => {
|
|
8799
8852
|
setDescription(newDescription);
|
|
8853
|
+
setHasUnsavedChanges2(true);
|
|
8800
8854
|
onDataUpdate((prev) => ({ ...prev, description: newDescription }));
|
|
8801
8855
|
triggerAutoSave({ description: newDescription });
|
|
8802
8856
|
},
|
|
@@ -8856,6 +8910,7 @@ function QuestDetailsPanel({
|
|
|
8856
8910
|
const [existingSections, setExistingSections] = useState18((node == null ? void 0 : node.description_sections) || []);
|
|
8857
8911
|
const [isSaving, setIsSaving] = useState18(false);
|
|
8858
8912
|
const [isLinkCopied, setIsLinkCopied] = useState18(false);
|
|
8913
|
+
const [hasUnsavedChanges, setHasUnsavedChanges2] = useState18(false);
|
|
8859
8914
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
8860
8915
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
8861
8916
|
initialWidth: isReadMode ? 700 : 440,
|
|
@@ -8887,6 +8942,7 @@ function QuestDetailsPanel({
|
|
|
8887
8942
|
setIntensity((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
|
|
8888
8943
|
setExistingSections((node == null ? void 0 : node.description_sections) || []);
|
|
8889
8944
|
setCustomProps(extractCustomPropsFromNode(node || {}));
|
|
8945
|
+
setHasUnsavedChanges2(false);
|
|
8890
8946
|
}
|
|
8891
8947
|
}, [node]);
|
|
8892
8948
|
useEffect16(() => {
|
|
@@ -8918,16 +8974,19 @@ function QuestDetailsPanel({
|
|
|
8918
8974
|
setRawTitle(val);
|
|
8919
8975
|
const newStandardName = questPrefix ? `${questPrefix} - \xBB ${val || "Sem t\xEDtulo"}` : val;
|
|
8920
8976
|
onNameChange == null ? void 0 : onNameChange(node.id, newStandardName, val);
|
|
8977
|
+
setHasUnsavedChanges2(true);
|
|
8921
8978
|
};
|
|
8922
8979
|
const handleSizeChange = (newSize) => {
|
|
8923
8980
|
setSize(newSize);
|
|
8924
8981
|
onSizeChange == null ? void 0 : onSizeChange(node.id, newSize);
|
|
8982
|
+
setHasUnsavedChanges2(true);
|
|
8925
8983
|
};
|
|
8926
8984
|
const handleStatusChange = (newStatus) => {
|
|
8927
8985
|
setStatus(newStatus);
|
|
8928
8986
|
const newColor = QUEST_STATUS_COLORS3[newStatus];
|
|
8929
8987
|
onColorChange == null ? void 0 : onColorChange(node.id, newColor);
|
|
8930
8988
|
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, status: newStatus, color: newColor });
|
|
8989
|
+
setHasUnsavedChanges2(true);
|
|
8931
8990
|
};
|
|
8932
8991
|
const handleAddType = (newType) => {
|
|
8933
8992
|
const trimmed = newType.trim();
|
|
@@ -8935,11 +8994,13 @@ function QuestDetailsPanel({
|
|
|
8935
8994
|
setTypes([...types, trimmed]);
|
|
8936
8995
|
setTypeInput("");
|
|
8937
8996
|
setShowTypeSuggestions(false);
|
|
8997
|
+
setHasUnsavedChanges2(true);
|
|
8938
8998
|
}
|
|
8939
8999
|
};
|
|
8940
9000
|
const handleRemoveType = (indexToRemove) => {
|
|
8941
9001
|
if (types[indexToRemove] === "quest") return;
|
|
8942
9002
|
setTypes(types.filter((_, index) => index !== indexToRemove));
|
|
9003
|
+
setHasUnsavedChanges2(true);
|
|
8943
9004
|
};
|
|
8944
9005
|
const handleTypeInputKeyDown = (e) => {
|
|
8945
9006
|
if (e.key === "Enter") {
|
|
@@ -8952,6 +9013,7 @@ function QuestDetailsPanel({
|
|
|
8952
9013
|
const handleAddProp = () => {
|
|
8953
9014
|
const newProp = createNewCustomProperty(customProps);
|
|
8954
9015
|
setCustomProps((p) => [...p, newProp]);
|
|
9016
|
+
setHasUnsavedChanges2(true);
|
|
8955
9017
|
setTimeout(() => {
|
|
8956
9018
|
var _a2;
|
|
8957
9019
|
(_a2 = propsEndRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
@@ -8960,18 +9022,21 @@ function QuestDetailsPanel({
|
|
|
8960
9022
|
const handleRemoveProp = (i) => {
|
|
8961
9023
|
const newProps = customProps.filter((_, idx) => idx !== i);
|
|
8962
9024
|
setCustomProps(newProps);
|
|
9025
|
+
setHasUnsavedChanges2(true);
|
|
8963
9026
|
triggerAutoSave({ customProps: newProps });
|
|
8964
9027
|
};
|
|
8965
9028
|
const handleUpdateProp = (index, updatedProp) => {
|
|
8966
9029
|
const newProps = [...customProps];
|
|
8967
9030
|
newProps[index] = updatedProp;
|
|
8968
9031
|
setCustomProps(newProps);
|
|
9032
|
+
setHasUnsavedChanges2(true);
|
|
8969
9033
|
if (!updatedProp.isEditing) {
|
|
8970
9034
|
triggerAutoSave({ customProps: newProps });
|
|
8971
9035
|
}
|
|
8972
9036
|
};
|
|
8973
9037
|
const handleSaveDescriptionInline = (newDescription) => {
|
|
8974
9038
|
setDescription(newDescription);
|
|
9039
|
+
setHasUnsavedChanges2(true);
|
|
8975
9040
|
onDataUpdate({ ...node, description: newDescription });
|
|
8976
9041
|
triggerAutoSave({ description: newDescription });
|
|
8977
9042
|
};
|
|
@@ -8983,6 +9048,10 @@ function QuestDetailsPanel({
|
|
|
8983
9048
|
const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
|
|
8984
9049
|
const currentExistingSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
|
|
8985
9050
|
const currentStatus = overrides.status !== void 0 ? overrides.status : status;
|
|
9051
|
+
if (!keepOpen && !hasUnsavedChanges) {
|
|
9052
|
+
onClose();
|
|
9053
|
+
return;
|
|
9054
|
+
}
|
|
8986
9055
|
if (!currentRawTitle.trim() || currentTypes.length === 0) {
|
|
8987
9056
|
alert("O campo 'T\xEDtulo' e pelo menos um 'Tipo' s\xE3o obrigat\xF3rios.");
|
|
8988
9057
|
return;
|
|
@@ -9012,6 +9081,7 @@ function QuestDetailsPanel({
|
|
|
9012
9081
|
};
|
|
9013
9082
|
await onSave(dataToSave, keepOpen);
|
|
9014
9083
|
onDataUpdate(dataToSave);
|
|
9084
|
+
setHasUnsavedChanges2(false);
|
|
9015
9085
|
if (!keepOpen) {
|
|
9016
9086
|
onClose();
|
|
9017
9087
|
}
|
|
@@ -9248,6 +9318,7 @@ function RelationshipDetailsPanel({
|
|
|
9248
9318
|
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState20(false);
|
|
9249
9319
|
const [isSaving, setIsSaving] = useState20(false);
|
|
9250
9320
|
const [isReadMode, setIsReadMode] = useState20(false);
|
|
9321
|
+
const [hasUnsavedChanges, setHasUnsavedChanges2] = useState20(false);
|
|
9251
9322
|
const propsEndRef = useRef16(null);
|
|
9252
9323
|
const canEdit = useMemo9(() => {
|
|
9253
9324
|
const ability = defineAbilityFor(userRole);
|
|
@@ -9260,12 +9331,14 @@ function RelationshipDetailsPanel({
|
|
|
9260
9331
|
setCustomProps(extractCustomPropsFromNode(link || {}));
|
|
9261
9332
|
setSourceLabel((link == null ? void 0 : link.source_label) ?? "");
|
|
9262
9333
|
setTargetLabel((link == null ? void 0 : link.target_label) ?? "");
|
|
9334
|
+
setHasUnsavedChanges2(false);
|
|
9263
9335
|
}, [link]);
|
|
9264
9336
|
const swallow = (e) => e.stopPropagation();
|
|
9265
9337
|
const handleAddProp = () => {
|
|
9266
9338
|
if (!canEdit) return;
|
|
9267
9339
|
const newProp = createNewCustomProperty(customProps);
|
|
9268
9340
|
setCustomProps((p) => [...p, newProp]);
|
|
9341
|
+
setHasUnsavedChanges2(true);
|
|
9269
9342
|
setTimeout(() => {
|
|
9270
9343
|
var _a;
|
|
9271
9344
|
(_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
@@ -9279,6 +9352,10 @@ function RelationshipDetailsPanel({
|
|
|
9279
9352
|
const currentName = overrides.name !== void 0 ? overrides.name : name;
|
|
9280
9353
|
const currentSourceLabel = overrides.sourceLabel !== void 0 ? overrides.sourceLabel : sourceLabel;
|
|
9281
9354
|
const currentTargetLabel = overrides.targetLabel !== void 0 ? overrides.targetLabel : targetLabel;
|
|
9355
|
+
if (!keepOpen && !hasUnsavedChanges) {
|
|
9356
|
+
onClose();
|
|
9357
|
+
return;
|
|
9358
|
+
}
|
|
9282
9359
|
setIsSaving(true);
|
|
9283
9360
|
try {
|
|
9284
9361
|
const extrasObj = toObjectFromCustomProps(currentCustomProps.filter((p) => !p.isEditing));
|
|
@@ -9298,6 +9375,7 @@ function RelationshipDetailsPanel({
|
|
|
9298
9375
|
if (currentTargetLabel.trim()) dataToSave.target_label = currentTargetLabel.trim();
|
|
9299
9376
|
await onSave(dataToSave, keepOpen);
|
|
9300
9377
|
onDataUpdate(dataToSave);
|
|
9378
|
+
setHasUnsavedChanges2(false);
|
|
9301
9379
|
if (!keepOpen) {
|
|
9302
9380
|
onClose();
|
|
9303
9381
|
}
|
|
@@ -9311,18 +9389,21 @@ function RelationshipDetailsPanel({
|
|
|
9311
9389
|
const handleSaveDescriptionInline = (newDescription) => {
|
|
9312
9390
|
if (!canEdit) return;
|
|
9313
9391
|
setDescription(newDescription);
|
|
9392
|
+
setHasUnsavedChanges2(true);
|
|
9314
9393
|
onDataUpdate((prev) => ({ ...prev, description: newDescription }));
|
|
9315
9394
|
triggerAutoSave({ description: newDescription });
|
|
9316
9395
|
};
|
|
9317
9396
|
const handleRemoveProp = (i) => {
|
|
9318
9397
|
const newProps = customProps.filter((_, idx) => idx !== i);
|
|
9319
9398
|
setCustomProps(newProps);
|
|
9399
|
+
setHasUnsavedChanges2(true);
|
|
9320
9400
|
triggerAutoSave({ customProps: newProps });
|
|
9321
9401
|
};
|
|
9322
9402
|
const handleUpdateProp = (index, updatedProp) => {
|
|
9323
9403
|
const newProps = [...customProps];
|
|
9324
9404
|
newProps[index] = updatedProp;
|
|
9325
9405
|
setCustomProps(newProps);
|
|
9406
|
+
setHasUnsavedChanges2(true);
|
|
9326
9407
|
if (!updatedProp.isEditing) {
|
|
9327
9408
|
triggerAutoSave({ customProps: newProps });
|
|
9328
9409
|
}
|
|
@@ -9375,7 +9456,10 @@ function RelationshipDetailsPanel({
|
|
|
9375
9456
|
{
|
|
9376
9457
|
type: "text",
|
|
9377
9458
|
value: name,
|
|
9378
|
-
onChange: (e) =>
|
|
9459
|
+
onChange: (e) => {
|
|
9460
|
+
setName(e.target.value);
|
|
9461
|
+
setHasUnsavedChanges2(true);
|
|
9462
|
+
},
|
|
9379
9463
|
placeholder: "Ex: Controla, Pertence a, Fornece...",
|
|
9380
9464
|
disabled: !canEdit,
|
|
9381
9465
|
className: `w-full bg-slate-800/70 p-2 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-400/60
|
|
@@ -9387,7 +9471,10 @@ function RelationshipDetailsPanel({
|
|
|
9387
9471
|
{
|
|
9388
9472
|
type: "text",
|
|
9389
9473
|
value: sourceLabel,
|
|
9390
|
-
onChange: (e) =>
|
|
9474
|
+
onChange: (e) => {
|
|
9475
|
+
setSourceLabel(e.target.value);
|
|
9476
|
+
setHasUnsavedChanges2(true);
|
|
9477
|
+
},
|
|
9391
9478
|
placeholder: "Ex: Conceitos",
|
|
9392
9479
|
disabled: !canEdit,
|
|
9393
9480
|
className: `w-full bg-slate-900/60 p-2 text-xs rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-violet-400/60 placeholder:text-slate-600
|
|
@@ -9399,7 +9486,10 @@ function RelationshipDetailsPanel({
|
|
|
9399
9486
|
{
|
|
9400
9487
|
type: "text",
|
|
9401
9488
|
value: targetLabel,
|
|
9402
|
-
onChange: (e) =>
|
|
9489
|
+
onChange: (e) => {
|
|
9490
|
+
setTargetLabel(e.target.value);
|
|
9491
|
+
setHasUnsavedChanges2(true);
|
|
9492
|
+
},
|
|
9403
9493
|
placeholder: "Ex: Refer\xEAncias",
|
|
9404
9494
|
disabled: !canEdit,
|
|
9405
9495
|
className: `w-full bg-slate-900/60 p-2 text-xs rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-violet-400/60 placeholder:text-slate-600
|
|
@@ -9476,6 +9566,7 @@ function RelationshipDetailsPanel({
|
|
|
9476
9566
|
onSave: (newDescription) => {
|
|
9477
9567
|
if (!canEdit) return;
|
|
9478
9568
|
setDescription(newDescription);
|
|
9569
|
+
setHasUnsavedChanges2(true);
|
|
9479
9570
|
onDataUpdate((prev) => ({ ...prev, description: newDescription }));
|
|
9480
9571
|
triggerAutoSave({ description: newDescription });
|
|
9481
9572
|
},
|
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.
|
|
3
|
+
"version": "1.2.5-dev.7",
|
|
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",
|