@lv-x-software-house/x_view 1.2.6-dev.50 → 1.2.6-dev.51
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 +202 -5
- package/dist/index.mjs +202 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3896,6 +3896,8 @@ function XViewSidebar({
|
|
|
3896
3896
|
},
|
|
3897
3897
|
milestones = [],
|
|
3898
3898
|
onOpenMilestoneManager = () => {
|
|
3899
|
+
},
|
|
3900
|
+
onActivateReshapeLens = () => {
|
|
3899
3901
|
}
|
|
3900
3902
|
}) {
|
|
3901
3903
|
const [query, setQuery] = (0, import_react3.useState)("");
|
|
@@ -3910,6 +3912,10 @@ function XViewSidebar({
|
|
|
3910
3912
|
const [questFilterStatus, setQuestFilterStatus] = (0, import_react3.useState)("");
|
|
3911
3913
|
const [isQuestLensMenuOpen, setIsQuestLensMenuOpen] = (0, import_react3.useState)(false);
|
|
3912
3914
|
const [questFilterMilestone, setQuestFilterMilestone] = (0, import_react3.useState)("");
|
|
3915
|
+
const [isReshapeLensMenuOpen, setIsReshapeLensMenuOpen] = (0, import_react3.useState)(false);
|
|
3916
|
+
const [reshapeLayoutType, setReshapeLayoutType] = (0, import_react3.useState)("Star");
|
|
3917
|
+
const [reshapeColumnCount, setReshapeColumnCount] = (0, import_react3.useState)(4);
|
|
3918
|
+
const [reshapeCenterNodeId, setReshapeCenterNodeId] = (0, import_react3.useState)("");
|
|
3913
3919
|
const [isTypeDropdownOpen, setIsTypeDropdownOpen] = (0, import_react3.useState)(false);
|
|
3914
3920
|
const [highlightedTypeIndex, setHighlightedTypeIndex] = (0, import_react3.useState)(-1);
|
|
3915
3921
|
const containerRef = (0, import_react3.useRef)(null);
|
|
@@ -3917,6 +3923,7 @@ function XViewSidebar({
|
|
|
3917
3923
|
const filterMenuRef = (0, import_react3.useRef)(null);
|
|
3918
3924
|
const typeDropdownRef = (0, import_react3.useRef)(null);
|
|
3919
3925
|
const questLensRef = (0, import_react3.useRef)(null);
|
|
3926
|
+
const reshapeLensRef = (0, import_react3.useRef)(null);
|
|
3920
3927
|
const ability = (0, import_react3.useMemo)(() => {
|
|
3921
3928
|
return defineAbilityFor(userRole);
|
|
3922
3929
|
}, [userRole]);
|
|
@@ -4022,16 +4029,19 @@ function XViewSidebar({
|
|
|
4022
4029
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
4023
4030
|
}, [isFilterMenuOpen, isTypeDropdownOpen]);
|
|
4024
4031
|
(0, import_react3.useEffect)(() => {
|
|
4025
|
-
const
|
|
4032
|
+
const handleClickOutsideQuestAndReshape = (event) => {
|
|
4026
4033
|
if (questLensRef.current && !questLensRef.current.contains(event.target)) {
|
|
4027
4034
|
setIsQuestLensMenuOpen(false);
|
|
4028
4035
|
}
|
|
4036
|
+
if (reshapeLensRef.current && !reshapeLensRef.current.contains(event.target)) {
|
|
4037
|
+
setIsReshapeLensMenuOpen(false);
|
|
4038
|
+
}
|
|
4029
4039
|
};
|
|
4030
|
-
if (isQuestLensMenuOpen) {
|
|
4031
|
-
document.addEventListener("mousedown",
|
|
4040
|
+
if (isQuestLensMenuOpen || isReshapeLensMenuOpen) {
|
|
4041
|
+
document.addEventListener("mousedown", handleClickOutsideQuestAndReshape);
|
|
4032
4042
|
}
|
|
4033
|
-
return () => document.removeEventListener("mousedown",
|
|
4034
|
-
}, [isQuestLensMenuOpen]);
|
|
4043
|
+
return () => document.removeEventListener("mousedown", handleClickOutsideQuestAndReshape);
|
|
4044
|
+
}, [isQuestLensMenuOpen, isReshapeLensMenuOpen]);
|
|
4035
4045
|
(0, import_react3.useEffect)(() => {
|
|
4036
4046
|
if (!query) setSelectedNodeId(null);
|
|
4037
4047
|
}, [query]);
|
|
@@ -4371,6 +4381,71 @@ function XViewSidebar({
|
|
|
4371
4381
|
className: "flex-[2] py-2 bg-indigo-600 hover:bg-indigo-500 text-white text-[11px] font-bold rounded-lg shadow-lg shadow-indigo-500/20 transition-all hover:scale-[1.02] active:scale-95"
|
|
4372
4382
|
},
|
|
4373
4383
|
"Aplicar Lente"
|
|
4384
|
+
)))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative", ref: reshapeLensRef }, /* @__PURE__ */ import_react3.default.createElement(
|
|
4385
|
+
"button",
|
|
4386
|
+
{
|
|
4387
|
+
onClick: () => setIsReshapeLensMenuOpen(!isReshapeLensMenuOpen),
|
|
4388
|
+
className: `${buttonBaseClass} ${isReshapeLensMenuOpen ? "bg-indigo-500/30 border-indigo-400" : ""}`,
|
|
4389
|
+
title: "Abrir op\xE7\xF5es de Reshape"
|
|
4390
|
+
},
|
|
4391
|
+
/* @__PURE__ */ import_react3.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react3.default.createElement("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }), /* @__PURE__ */ import_react3.default.createElement("polyline", { points: "2 17 12 22 22 17" }), /* @__PURE__ */ import_react3.default.createElement("polyline", { points: "2 12 12 17 22 12" })),
|
|
4392
|
+
"Reshape Lens"
|
|
4393
|
+
), isReshapeLensMenuOpen && /* @__PURE__ */ import_react3.default.createElement("div", { className: "absolute left-0 bottom-full mb-2 w-full p-4 rounded-xl bg-slate-900 border border-white/10 shadow-2xl z-50 flex flex-col gap-4 animate-in fade-in slide-in-from-bottom-2 duration-200" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react3.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-bold tracking-widest" }, "Layout Type"), /* @__PURE__ */ import_react3.default.createElement(
|
|
4394
|
+
"select",
|
|
4395
|
+
{
|
|
4396
|
+
value: reshapeLayoutType,
|
|
4397
|
+
onChange: (e) => setReshapeLayoutType(e.target.value),
|
|
4398
|
+
className: "w-full bg-slate-800 p-2 text-xs rounded border border-white/10 focus:outline-none focus:border-indigo-500/50 text-white appearance-none cursor-pointer"
|
|
4399
|
+
},
|
|
4400
|
+
/* @__PURE__ */ import_react3.default.createElement("option", { value: "Star" }, "Star"),
|
|
4401
|
+
/* @__PURE__ */ import_react3.default.createElement("option", { value: "Circle" }, "Circle"),
|
|
4402
|
+
/* @__PURE__ */ import_react3.default.createElement("option", { value: "Column" }, "Column")
|
|
4403
|
+
)), reshapeLayoutType === "Column" && /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react3.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-bold tracking-widest" }, "Colunas"), /* @__PURE__ */ import_react3.default.createElement(
|
|
4404
|
+
"input",
|
|
4405
|
+
{
|
|
4406
|
+
type: "number",
|
|
4407
|
+
min: "1",
|
|
4408
|
+
max: "12",
|
|
4409
|
+
value: reshapeColumnCount,
|
|
4410
|
+
onChange: (e) => setReshapeColumnCount(parseInt(e.target.value) || 4),
|
|
4411
|
+
className: "w-full bg-slate-800 p-2 text-xs rounded border border-white/10 focus:outline-none focus:border-indigo-500/50 text-white"
|
|
4412
|
+
}
|
|
4413
|
+
)), reshapeLayoutType === "Star" && /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react3.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-bold tracking-widest" }, "N\xF3 Central"), /* @__PURE__ */ import_react3.default.createElement(
|
|
4414
|
+
"select",
|
|
4415
|
+
{
|
|
4416
|
+
value: reshapeCenterNodeId,
|
|
4417
|
+
onChange: (e) => setReshapeCenterNodeId(e.target.value),
|
|
4418
|
+
className: "w-full bg-slate-800 p-2 text-xs rounded border border-white/10 focus:outline-none focus:border-indigo-500/50 text-white appearance-none cursor-pointer"
|
|
4419
|
+
},
|
|
4420
|
+
/* @__PURE__ */ import_react3.default.createElement("option", { value: "" }, "Selecione..."),
|
|
4421
|
+
(Array.isArray(dbNodes) ? dbNodes.filter((n) => isNodeInView(n.id)) : []).map((n) => /* @__PURE__ */ import_react3.default.createElement("option", { key: n.id, value: n.id }, n.name))
|
|
4422
|
+
)), /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex gap-2 pt-1" }, /* @__PURE__ */ import_react3.default.createElement(
|
|
4423
|
+
"button",
|
|
4424
|
+
{
|
|
4425
|
+
onClick: () => {
|
|
4426
|
+
setReshapeLayoutType("Star");
|
|
4427
|
+
setReshapeColumnCount(4);
|
|
4428
|
+
setReshapeCenterNodeId("");
|
|
4429
|
+
},
|
|
4430
|
+
className: "flex-1 py-2 bg-white/5 hover:bg-white/10 text-slate-300 text-[11px] font-medium rounded-lg transition-colors border border-white/5"
|
|
4431
|
+
},
|
|
4432
|
+
"Resetar"
|
|
4433
|
+
), /* @__PURE__ */ import_react3.default.createElement(
|
|
4434
|
+
"button",
|
|
4435
|
+
{
|
|
4436
|
+
onClick: () => {
|
|
4437
|
+
onActivateReshapeLens({
|
|
4438
|
+
type: reshapeLayoutType,
|
|
4439
|
+
columns: reshapeColumnCount,
|
|
4440
|
+
centerNodeId: reshapeCenterNodeId
|
|
4441
|
+
});
|
|
4442
|
+
setIsReshapeLensMenuOpen(false);
|
|
4443
|
+
onToggle(false);
|
|
4444
|
+
},
|
|
4445
|
+
disabled: reshapeLayoutType === "Star" && !reshapeCenterNodeId,
|
|
4446
|
+
className: "flex-[2] py-2 bg-indigo-600 hover:bg-indigo-500 text-white text-[11px] font-bold rounded-lg shadow-lg shadow-indigo-500/20 transition-all hover:scale-[1.02] active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
4447
|
+
},
|
|
4448
|
+
"Aplicar Lente"
|
|
4374
4449
|
)))), /* @__PURE__ */ import_react3.default.createElement(
|
|
4375
4450
|
"button",
|
|
4376
4451
|
{
|
|
@@ -15132,6 +15207,127 @@ function XViewScene({
|
|
|
15132
15207
|
},
|
|
15133
15208
|
[]
|
|
15134
15209
|
);
|
|
15210
|
+
const handleActivateReshapeLens = (0, import_react31.useCallback)(({ type, columns, centerNodeId }) => {
|
|
15211
|
+
const { nodeObjects, tweenGroup, camera, controls } = stateRef.current;
|
|
15212
|
+
if (!nodeObjects || !tweenGroup || !camera || !controls) return;
|
|
15213
|
+
const activeNodeIds = Object.keys(nodeObjects);
|
|
15214
|
+
if (activeNodeIds.length === 0) return;
|
|
15215
|
+
let sumX = 0;
|
|
15216
|
+
let sumY = 0;
|
|
15217
|
+
let nodeCount = 0;
|
|
15218
|
+
activeNodeIds.forEach((id) => {
|
|
15219
|
+
const mesh = nodeObjects[id];
|
|
15220
|
+
if (mesh && mesh.material) {
|
|
15221
|
+
const opacityTween = new import_tween2.Tween(mesh.material).to({ opacity: 1 }, 1200).easing(import_tween2.Easing.Cubic.Out);
|
|
15222
|
+
tweenGroup.add(opacityTween);
|
|
15223
|
+
opacityTween.start();
|
|
15224
|
+
}
|
|
15225
|
+
if (mesh && mesh.userData && mesh.userData.labelObject) {
|
|
15226
|
+
mesh.userData.labelObject.visible = true;
|
|
15227
|
+
}
|
|
15228
|
+
});
|
|
15229
|
+
if (type === "Column") {
|
|
15230
|
+
const colSpacing = 80;
|
|
15231
|
+
const rowSpacing = 80;
|
|
15232
|
+
const numCols = columns || 4;
|
|
15233
|
+
activeNodeIds.forEach((id, index) => {
|
|
15234
|
+
const mesh = nodeObjects[id];
|
|
15235
|
+
const col = index % numCols;
|
|
15236
|
+
const row = Math.floor(index / numCols);
|
|
15237
|
+
const targetX = (col - (numCols - 1) / 2) * colSpacing;
|
|
15238
|
+
const targetY = -(row * rowSpacing) + 50;
|
|
15239
|
+
const posTween = new import_tween2.Tween(mesh.position).to({ x: targetX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
15240
|
+
tweenGroup.add(posTween);
|
|
15241
|
+
posTween.start();
|
|
15242
|
+
if (mesh.userData.labelObject) {
|
|
15243
|
+
const labelTarget = new THREE3.Vector3(targetX, targetY, 0).add(mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
15244
|
+
const lblTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTarget, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
15245
|
+
tweenGroup.add(lblTween);
|
|
15246
|
+
lblTween.start();
|
|
15247
|
+
}
|
|
15248
|
+
sumX += targetX;
|
|
15249
|
+
sumY += targetY;
|
|
15250
|
+
nodeCount++;
|
|
15251
|
+
});
|
|
15252
|
+
} else if (type === "Circle") {
|
|
15253
|
+
const total = activeNodeIds.length;
|
|
15254
|
+
const radius = Math.max(80, total * 8);
|
|
15255
|
+
activeNodeIds.forEach((id, index) => {
|
|
15256
|
+
const mesh = nodeObjects[id];
|
|
15257
|
+
const angle = index / total * Math.PI * 2;
|
|
15258
|
+
const targetX = Math.cos(angle) * radius;
|
|
15259
|
+
const targetY = Math.sin(angle) * radius;
|
|
15260
|
+
const posTween = new import_tween2.Tween(mesh.position).to({ x: targetX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
15261
|
+
tweenGroup.add(posTween);
|
|
15262
|
+
posTween.start();
|
|
15263
|
+
if (mesh.userData.labelObject) {
|
|
15264
|
+
const labelTarget = new THREE3.Vector3(targetX, targetY, 0).add(mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
15265
|
+
const lblTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTarget, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
15266
|
+
tweenGroup.add(lblTween);
|
|
15267
|
+
lblTween.start();
|
|
15268
|
+
}
|
|
15269
|
+
sumX += targetX;
|
|
15270
|
+
sumY += targetY;
|
|
15271
|
+
nodeCount++;
|
|
15272
|
+
});
|
|
15273
|
+
} else if (type === "Star") {
|
|
15274
|
+
const centerMesh = centerNodeId ? nodeObjects[String(centerNodeId)] : null;
|
|
15275
|
+
const orbitingNodeIds = activeNodeIds.filter((id) => id !== String(centerNodeId));
|
|
15276
|
+
const totalOrbiting = orbitingNodeIds.length;
|
|
15277
|
+
const radius = Math.max(80, totalOrbiting * 10);
|
|
15278
|
+
if (centerMesh) {
|
|
15279
|
+
const posTween = new import_tween2.Tween(centerMesh.position).to({ x: 0, y: 0, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
15280
|
+
tweenGroup.add(posTween);
|
|
15281
|
+
posTween.start();
|
|
15282
|
+
if (centerMesh.userData.labelObject) {
|
|
15283
|
+
const labelTarget = new THREE3.Vector3(0, 0, 0).add(centerMesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
15284
|
+
const lblTween = new import_tween2.Tween(centerMesh.userData.labelObject.position).to(labelTarget, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
15285
|
+
tweenGroup.add(lblTween);
|
|
15286
|
+
lblTween.start();
|
|
15287
|
+
}
|
|
15288
|
+
sumX += 0;
|
|
15289
|
+
sumY += 0;
|
|
15290
|
+
nodeCount++;
|
|
15291
|
+
}
|
|
15292
|
+
orbitingNodeIds.forEach((id, index) => {
|
|
15293
|
+
const mesh = nodeObjects[id];
|
|
15294
|
+
const angle = totalOrbiting > 0 ? index / totalOrbiting * Math.PI * 2 : 0;
|
|
15295
|
+
const targetX = Math.cos(angle) * radius;
|
|
15296
|
+
const targetY = Math.sin(angle) * radius;
|
|
15297
|
+
const posTween = new import_tween2.Tween(mesh.position).to({ x: targetX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
15298
|
+
tweenGroup.add(posTween);
|
|
15299
|
+
posTween.start();
|
|
15300
|
+
if (mesh.userData.labelObject) {
|
|
15301
|
+
const labelTarget = new THREE3.Vector3(targetX, targetY, 0).add(mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
15302
|
+
const lblTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTarget, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
15303
|
+
tweenGroup.add(lblTween);
|
|
15304
|
+
lblTween.start();
|
|
15305
|
+
}
|
|
15306
|
+
sumX += targetX;
|
|
15307
|
+
sumY += targetY;
|
|
15308
|
+
nodeCount++;
|
|
15309
|
+
});
|
|
15310
|
+
}
|
|
15311
|
+
if (nodeCount > 0) {
|
|
15312
|
+
const centerX = sumX / nodeCount;
|
|
15313
|
+
const centerY = sumY / nodeCount;
|
|
15314
|
+
const targetFocus = new THREE3.Vector3(centerX, centerY, 0);
|
|
15315
|
+
const targetTween = new import_tween2.Tween(controls.target).to({ x: targetFocus.x, y: targetFocus.y, z: targetFocus.z }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
15316
|
+
tweenGroup.add(targetTween);
|
|
15317
|
+
targetTween.start();
|
|
15318
|
+
let zoomZ = 140;
|
|
15319
|
+
if (type === "Column") {
|
|
15320
|
+
const numRows = Math.ceil(nodeCount / (columns || 4));
|
|
15321
|
+
zoomZ = Math.max(140, numRows * 50);
|
|
15322
|
+
} else if (type === "Circle" || type === "Star") {
|
|
15323
|
+
const radius = Math.max(80, nodeCount * 8);
|
|
15324
|
+
zoomZ = radius * 2.5;
|
|
15325
|
+
}
|
|
15326
|
+
const camTween = new import_tween2.Tween(camera.position).to({ x: targetFocus.x, y: targetFocus.y, z: zoomZ }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
15327
|
+
tweenGroup.add(camTween);
|
|
15328
|
+
camTween.start();
|
|
15329
|
+
}
|
|
15330
|
+
}, []);
|
|
15135
15331
|
const handleActivateQuestLens = (0, import_react31.useCallback)(({ assigneeId, status: status2, milestoneId }) => {
|
|
15136
15332
|
var _a2;
|
|
15137
15333
|
const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
|
|
@@ -18703,6 +18899,7 @@ function XViewScene({
|
|
|
18703
18899
|
importSuccessMessage,
|
|
18704
18900
|
onActivateTimeline: handleActivateTimeline,
|
|
18705
18901
|
onActivateQuestLens: handleActivateQuestLens,
|
|
18902
|
+
onActivateReshapeLens: handleActivateReshapeLens,
|
|
18706
18903
|
onOpenBoards: handleOpenBoards,
|
|
18707
18904
|
viewType: viewParams == null ? void 0 : viewParams.type,
|
|
18708
18905
|
viewName: viewParams == null ? void 0 : viewParams.name,
|
package/dist/index.mjs
CHANGED
|
@@ -3857,6 +3857,8 @@ function XViewSidebar({
|
|
|
3857
3857
|
},
|
|
3858
3858
|
milestones = [],
|
|
3859
3859
|
onOpenMilestoneManager = () => {
|
|
3860
|
+
},
|
|
3861
|
+
onActivateReshapeLens = () => {
|
|
3860
3862
|
}
|
|
3861
3863
|
}) {
|
|
3862
3864
|
const [query, setQuery] = useState3("");
|
|
@@ -3871,6 +3873,10 @@ function XViewSidebar({
|
|
|
3871
3873
|
const [questFilterStatus, setQuestFilterStatus] = useState3("");
|
|
3872
3874
|
const [isQuestLensMenuOpen, setIsQuestLensMenuOpen] = useState3(false);
|
|
3873
3875
|
const [questFilterMilestone, setQuestFilterMilestone] = useState3("");
|
|
3876
|
+
const [isReshapeLensMenuOpen, setIsReshapeLensMenuOpen] = useState3(false);
|
|
3877
|
+
const [reshapeLayoutType, setReshapeLayoutType] = useState3("Star");
|
|
3878
|
+
const [reshapeColumnCount, setReshapeColumnCount] = useState3(4);
|
|
3879
|
+
const [reshapeCenterNodeId, setReshapeCenterNodeId] = useState3("");
|
|
3874
3880
|
const [isTypeDropdownOpen, setIsTypeDropdownOpen] = useState3(false);
|
|
3875
3881
|
const [highlightedTypeIndex, setHighlightedTypeIndex] = useState3(-1);
|
|
3876
3882
|
const containerRef = useRef2(null);
|
|
@@ -3878,6 +3884,7 @@ function XViewSidebar({
|
|
|
3878
3884
|
const filterMenuRef = useRef2(null);
|
|
3879
3885
|
const typeDropdownRef = useRef2(null);
|
|
3880
3886
|
const questLensRef = useRef2(null);
|
|
3887
|
+
const reshapeLensRef = useRef2(null);
|
|
3881
3888
|
const ability = useMemo2(() => {
|
|
3882
3889
|
return defineAbilityFor(userRole);
|
|
3883
3890
|
}, [userRole]);
|
|
@@ -3983,16 +3990,19 @@ function XViewSidebar({
|
|
|
3983
3990
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
3984
3991
|
}, [isFilterMenuOpen, isTypeDropdownOpen]);
|
|
3985
3992
|
useEffect2(() => {
|
|
3986
|
-
const
|
|
3993
|
+
const handleClickOutsideQuestAndReshape = (event) => {
|
|
3987
3994
|
if (questLensRef.current && !questLensRef.current.contains(event.target)) {
|
|
3988
3995
|
setIsQuestLensMenuOpen(false);
|
|
3989
3996
|
}
|
|
3997
|
+
if (reshapeLensRef.current && !reshapeLensRef.current.contains(event.target)) {
|
|
3998
|
+
setIsReshapeLensMenuOpen(false);
|
|
3999
|
+
}
|
|
3990
4000
|
};
|
|
3991
|
-
if (isQuestLensMenuOpen) {
|
|
3992
|
-
document.addEventListener("mousedown",
|
|
4001
|
+
if (isQuestLensMenuOpen || isReshapeLensMenuOpen) {
|
|
4002
|
+
document.addEventListener("mousedown", handleClickOutsideQuestAndReshape);
|
|
3993
4003
|
}
|
|
3994
|
-
return () => document.removeEventListener("mousedown",
|
|
3995
|
-
}, [isQuestLensMenuOpen]);
|
|
4004
|
+
return () => document.removeEventListener("mousedown", handleClickOutsideQuestAndReshape);
|
|
4005
|
+
}, [isQuestLensMenuOpen, isReshapeLensMenuOpen]);
|
|
3996
4006
|
useEffect2(() => {
|
|
3997
4007
|
if (!query) setSelectedNodeId(null);
|
|
3998
4008
|
}, [query]);
|
|
@@ -4332,6 +4342,71 @@ function XViewSidebar({
|
|
|
4332
4342
|
className: "flex-[2] py-2 bg-indigo-600 hover:bg-indigo-500 text-white text-[11px] font-bold rounded-lg shadow-lg shadow-indigo-500/20 transition-all hover:scale-[1.02] active:scale-95"
|
|
4333
4343
|
},
|
|
4334
4344
|
"Aplicar Lente"
|
|
4345
|
+
)))), /* @__PURE__ */ React2.createElement("div", { className: "relative", ref: reshapeLensRef }, /* @__PURE__ */ React2.createElement(
|
|
4346
|
+
"button",
|
|
4347
|
+
{
|
|
4348
|
+
onClick: () => setIsReshapeLensMenuOpen(!isReshapeLensMenuOpen),
|
|
4349
|
+
className: `${buttonBaseClass} ${isReshapeLensMenuOpen ? "bg-indigo-500/30 border-indigo-400" : ""}`,
|
|
4350
|
+
title: "Abrir op\xE7\xF5es de Reshape"
|
|
4351
|
+
},
|
|
4352
|
+
/* @__PURE__ */ React2.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React2.createElement("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }), /* @__PURE__ */ React2.createElement("polyline", { points: "2 17 12 22 22 17" }), /* @__PURE__ */ React2.createElement("polyline", { points: "2 12 12 17 22 12" })),
|
|
4353
|
+
"Reshape Lens"
|
|
4354
|
+
), isReshapeLensMenuOpen && /* @__PURE__ */ React2.createElement("div", { className: "absolute left-0 bottom-full mb-2 w-full p-4 rounded-xl bg-slate-900 border border-white/10 shadow-2xl z-50 flex flex-col gap-4 animate-in fade-in slide-in-from-bottom-2 duration-200" }, /* @__PURE__ */ React2.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React2.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-bold tracking-widest" }, "Layout Type"), /* @__PURE__ */ React2.createElement(
|
|
4355
|
+
"select",
|
|
4356
|
+
{
|
|
4357
|
+
value: reshapeLayoutType,
|
|
4358
|
+
onChange: (e) => setReshapeLayoutType(e.target.value),
|
|
4359
|
+
className: "w-full bg-slate-800 p-2 text-xs rounded border border-white/10 focus:outline-none focus:border-indigo-500/50 text-white appearance-none cursor-pointer"
|
|
4360
|
+
},
|
|
4361
|
+
/* @__PURE__ */ React2.createElement("option", { value: "Star" }, "Star"),
|
|
4362
|
+
/* @__PURE__ */ React2.createElement("option", { value: "Circle" }, "Circle"),
|
|
4363
|
+
/* @__PURE__ */ React2.createElement("option", { value: "Column" }, "Column")
|
|
4364
|
+
)), reshapeLayoutType === "Column" && /* @__PURE__ */ React2.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React2.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-bold tracking-widest" }, "Colunas"), /* @__PURE__ */ React2.createElement(
|
|
4365
|
+
"input",
|
|
4366
|
+
{
|
|
4367
|
+
type: "number",
|
|
4368
|
+
min: "1",
|
|
4369
|
+
max: "12",
|
|
4370
|
+
value: reshapeColumnCount,
|
|
4371
|
+
onChange: (e) => setReshapeColumnCount(parseInt(e.target.value) || 4),
|
|
4372
|
+
className: "w-full bg-slate-800 p-2 text-xs rounded border border-white/10 focus:outline-none focus:border-indigo-500/50 text-white"
|
|
4373
|
+
}
|
|
4374
|
+
)), reshapeLayoutType === "Star" && /* @__PURE__ */ React2.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React2.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-bold tracking-widest" }, "N\xF3 Central"), /* @__PURE__ */ React2.createElement(
|
|
4375
|
+
"select",
|
|
4376
|
+
{
|
|
4377
|
+
value: reshapeCenterNodeId,
|
|
4378
|
+
onChange: (e) => setReshapeCenterNodeId(e.target.value),
|
|
4379
|
+
className: "w-full bg-slate-800 p-2 text-xs rounded border border-white/10 focus:outline-none focus:border-indigo-500/50 text-white appearance-none cursor-pointer"
|
|
4380
|
+
},
|
|
4381
|
+
/* @__PURE__ */ React2.createElement("option", { value: "" }, "Selecione..."),
|
|
4382
|
+
(Array.isArray(dbNodes) ? dbNodes.filter((n) => isNodeInView(n.id)) : []).map((n) => /* @__PURE__ */ React2.createElement("option", { key: n.id, value: n.id }, n.name))
|
|
4383
|
+
)), /* @__PURE__ */ React2.createElement("div", { className: "flex gap-2 pt-1" }, /* @__PURE__ */ React2.createElement(
|
|
4384
|
+
"button",
|
|
4385
|
+
{
|
|
4386
|
+
onClick: () => {
|
|
4387
|
+
setReshapeLayoutType("Star");
|
|
4388
|
+
setReshapeColumnCount(4);
|
|
4389
|
+
setReshapeCenterNodeId("");
|
|
4390
|
+
},
|
|
4391
|
+
className: "flex-1 py-2 bg-white/5 hover:bg-white/10 text-slate-300 text-[11px] font-medium rounded-lg transition-colors border border-white/5"
|
|
4392
|
+
},
|
|
4393
|
+
"Resetar"
|
|
4394
|
+
), /* @__PURE__ */ React2.createElement(
|
|
4395
|
+
"button",
|
|
4396
|
+
{
|
|
4397
|
+
onClick: () => {
|
|
4398
|
+
onActivateReshapeLens({
|
|
4399
|
+
type: reshapeLayoutType,
|
|
4400
|
+
columns: reshapeColumnCount,
|
|
4401
|
+
centerNodeId: reshapeCenterNodeId
|
|
4402
|
+
});
|
|
4403
|
+
setIsReshapeLensMenuOpen(false);
|
|
4404
|
+
onToggle(false);
|
|
4405
|
+
},
|
|
4406
|
+
disabled: reshapeLayoutType === "Star" && !reshapeCenterNodeId,
|
|
4407
|
+
className: "flex-[2] py-2 bg-indigo-600 hover:bg-indigo-500 text-white text-[11px] font-bold rounded-lg shadow-lg shadow-indigo-500/20 transition-all hover:scale-[1.02] active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
4408
|
+
},
|
|
4409
|
+
"Aplicar Lente"
|
|
4335
4410
|
)))), /* @__PURE__ */ React2.createElement(
|
|
4336
4411
|
"button",
|
|
4337
4412
|
{
|
|
@@ -15188,6 +15263,127 @@ function XViewScene({
|
|
|
15188
15263
|
},
|
|
15189
15264
|
[]
|
|
15190
15265
|
);
|
|
15266
|
+
const handleActivateReshapeLens = useCallback6(({ type, columns, centerNodeId }) => {
|
|
15267
|
+
const { nodeObjects, tweenGroup, camera, controls } = stateRef.current;
|
|
15268
|
+
if (!nodeObjects || !tweenGroup || !camera || !controls) return;
|
|
15269
|
+
const activeNodeIds = Object.keys(nodeObjects);
|
|
15270
|
+
if (activeNodeIds.length === 0) return;
|
|
15271
|
+
let sumX = 0;
|
|
15272
|
+
let sumY = 0;
|
|
15273
|
+
let nodeCount = 0;
|
|
15274
|
+
activeNodeIds.forEach((id) => {
|
|
15275
|
+
const mesh = nodeObjects[id];
|
|
15276
|
+
if (mesh && mesh.material) {
|
|
15277
|
+
const opacityTween = new Tween2(mesh.material).to({ opacity: 1 }, 1200).easing(Easing2.Cubic.Out);
|
|
15278
|
+
tweenGroup.add(opacityTween);
|
|
15279
|
+
opacityTween.start();
|
|
15280
|
+
}
|
|
15281
|
+
if (mesh && mesh.userData && mesh.userData.labelObject) {
|
|
15282
|
+
mesh.userData.labelObject.visible = true;
|
|
15283
|
+
}
|
|
15284
|
+
});
|
|
15285
|
+
if (type === "Column") {
|
|
15286
|
+
const colSpacing = 80;
|
|
15287
|
+
const rowSpacing = 80;
|
|
15288
|
+
const numCols = columns || 4;
|
|
15289
|
+
activeNodeIds.forEach((id, index) => {
|
|
15290
|
+
const mesh = nodeObjects[id];
|
|
15291
|
+
const col = index % numCols;
|
|
15292
|
+
const row = Math.floor(index / numCols);
|
|
15293
|
+
const targetX = (col - (numCols - 1) / 2) * colSpacing;
|
|
15294
|
+
const targetY = -(row * rowSpacing) + 50;
|
|
15295
|
+
const posTween = new Tween2(mesh.position).to({ x: targetX, y: targetY, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
|
|
15296
|
+
tweenGroup.add(posTween);
|
|
15297
|
+
posTween.start();
|
|
15298
|
+
if (mesh.userData.labelObject) {
|
|
15299
|
+
const labelTarget = new THREE3.Vector3(targetX, targetY, 0).add(mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
15300
|
+
const lblTween = new Tween2(mesh.userData.labelObject.position).to(labelTarget, 1500).easing(Easing2.Cubic.InOut);
|
|
15301
|
+
tweenGroup.add(lblTween);
|
|
15302
|
+
lblTween.start();
|
|
15303
|
+
}
|
|
15304
|
+
sumX += targetX;
|
|
15305
|
+
sumY += targetY;
|
|
15306
|
+
nodeCount++;
|
|
15307
|
+
});
|
|
15308
|
+
} else if (type === "Circle") {
|
|
15309
|
+
const total = activeNodeIds.length;
|
|
15310
|
+
const radius = Math.max(80, total * 8);
|
|
15311
|
+
activeNodeIds.forEach((id, index) => {
|
|
15312
|
+
const mesh = nodeObjects[id];
|
|
15313
|
+
const angle = index / total * Math.PI * 2;
|
|
15314
|
+
const targetX = Math.cos(angle) * radius;
|
|
15315
|
+
const targetY = Math.sin(angle) * radius;
|
|
15316
|
+
const posTween = new Tween2(mesh.position).to({ x: targetX, y: targetY, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
|
|
15317
|
+
tweenGroup.add(posTween);
|
|
15318
|
+
posTween.start();
|
|
15319
|
+
if (mesh.userData.labelObject) {
|
|
15320
|
+
const labelTarget = new THREE3.Vector3(targetX, targetY, 0).add(mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
15321
|
+
const lblTween = new Tween2(mesh.userData.labelObject.position).to(labelTarget, 1500).easing(Easing2.Cubic.InOut);
|
|
15322
|
+
tweenGroup.add(lblTween);
|
|
15323
|
+
lblTween.start();
|
|
15324
|
+
}
|
|
15325
|
+
sumX += targetX;
|
|
15326
|
+
sumY += targetY;
|
|
15327
|
+
nodeCount++;
|
|
15328
|
+
});
|
|
15329
|
+
} else if (type === "Star") {
|
|
15330
|
+
const centerMesh = centerNodeId ? nodeObjects[String(centerNodeId)] : null;
|
|
15331
|
+
const orbitingNodeIds = activeNodeIds.filter((id) => id !== String(centerNodeId));
|
|
15332
|
+
const totalOrbiting = orbitingNodeIds.length;
|
|
15333
|
+
const radius = Math.max(80, totalOrbiting * 10);
|
|
15334
|
+
if (centerMesh) {
|
|
15335
|
+
const posTween = new Tween2(centerMesh.position).to({ x: 0, y: 0, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
|
|
15336
|
+
tweenGroup.add(posTween);
|
|
15337
|
+
posTween.start();
|
|
15338
|
+
if (centerMesh.userData.labelObject) {
|
|
15339
|
+
const labelTarget = new THREE3.Vector3(0, 0, 0).add(centerMesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
15340
|
+
const lblTween = new Tween2(centerMesh.userData.labelObject.position).to(labelTarget, 1500).easing(Easing2.Cubic.InOut);
|
|
15341
|
+
tweenGroup.add(lblTween);
|
|
15342
|
+
lblTween.start();
|
|
15343
|
+
}
|
|
15344
|
+
sumX += 0;
|
|
15345
|
+
sumY += 0;
|
|
15346
|
+
nodeCount++;
|
|
15347
|
+
}
|
|
15348
|
+
orbitingNodeIds.forEach((id, index) => {
|
|
15349
|
+
const mesh = nodeObjects[id];
|
|
15350
|
+
const angle = totalOrbiting > 0 ? index / totalOrbiting * Math.PI * 2 : 0;
|
|
15351
|
+
const targetX = Math.cos(angle) * radius;
|
|
15352
|
+
const targetY = Math.sin(angle) * radius;
|
|
15353
|
+
const posTween = new Tween2(mesh.position).to({ x: targetX, y: targetY, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
|
|
15354
|
+
tweenGroup.add(posTween);
|
|
15355
|
+
posTween.start();
|
|
15356
|
+
if (mesh.userData.labelObject) {
|
|
15357
|
+
const labelTarget = new THREE3.Vector3(targetX, targetY, 0).add(mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
15358
|
+
const lblTween = new Tween2(mesh.userData.labelObject.position).to(labelTarget, 1500).easing(Easing2.Cubic.InOut);
|
|
15359
|
+
tweenGroup.add(lblTween);
|
|
15360
|
+
lblTween.start();
|
|
15361
|
+
}
|
|
15362
|
+
sumX += targetX;
|
|
15363
|
+
sumY += targetY;
|
|
15364
|
+
nodeCount++;
|
|
15365
|
+
});
|
|
15366
|
+
}
|
|
15367
|
+
if (nodeCount > 0) {
|
|
15368
|
+
const centerX = sumX / nodeCount;
|
|
15369
|
+
const centerY = sumY / nodeCount;
|
|
15370
|
+
const targetFocus = new THREE3.Vector3(centerX, centerY, 0);
|
|
15371
|
+
const targetTween = new Tween2(controls.target).to({ x: targetFocus.x, y: targetFocus.y, z: targetFocus.z }, 1500).easing(Easing2.Cubic.InOut);
|
|
15372
|
+
tweenGroup.add(targetTween);
|
|
15373
|
+
targetTween.start();
|
|
15374
|
+
let zoomZ = 140;
|
|
15375
|
+
if (type === "Column") {
|
|
15376
|
+
const numRows = Math.ceil(nodeCount / (columns || 4));
|
|
15377
|
+
zoomZ = Math.max(140, numRows * 50);
|
|
15378
|
+
} else if (type === "Circle" || type === "Star") {
|
|
15379
|
+
const radius = Math.max(80, nodeCount * 8);
|
|
15380
|
+
zoomZ = radius * 2.5;
|
|
15381
|
+
}
|
|
15382
|
+
const camTween = new Tween2(camera.position).to({ x: targetFocus.x, y: targetFocus.y, z: zoomZ }, 1500).easing(Easing2.Cubic.InOut);
|
|
15383
|
+
tweenGroup.add(camTween);
|
|
15384
|
+
camTween.start();
|
|
15385
|
+
}
|
|
15386
|
+
}, []);
|
|
15191
15387
|
const handleActivateQuestLens = useCallback6(({ assigneeId, status: status2, milestoneId }) => {
|
|
15192
15388
|
var _a2;
|
|
15193
15389
|
const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
|
|
@@ -18759,6 +18955,7 @@ function XViewScene({
|
|
|
18759
18955
|
importSuccessMessage,
|
|
18760
18956
|
onActivateTimeline: handleActivateTimeline,
|
|
18761
18957
|
onActivateQuestLens: handleActivateQuestLens,
|
|
18958
|
+
onActivateReshapeLens: handleActivateReshapeLens,
|
|
18762
18959
|
onOpenBoards: handleOpenBoards,
|
|
18763
18960
|
viewType: viewParams == null ? void 0 : viewParams.type,
|
|
18764
18961
|
viewName: viewParams == null ? void 0 : viewParams.name,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lv-x-software-house/x_view",
|
|
3
|
-
"version": "1.2.6-dev.
|
|
3
|
+
"version": "1.2.6-dev.51",
|
|
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",
|