@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 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 handleClickOutsideQuest = (event) => {
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", handleClickOutsideQuest);
4040
+ if (isQuestLensMenuOpen || isReshapeLensMenuOpen) {
4041
+ document.addEventListener("mousedown", handleClickOutsideQuestAndReshape);
4032
4042
  }
4033
- return () => document.removeEventListener("mousedown", handleClickOutsideQuest);
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 handleClickOutsideQuest = (event) => {
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", handleClickOutsideQuest);
4001
+ if (isQuestLensMenuOpen || isReshapeLensMenuOpen) {
4002
+ document.addEventListener("mousedown", handleClickOutsideQuestAndReshape);
3993
4003
  }
3994
- return () => document.removeEventListener("mousedown", handleClickOutsideQuest);
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.50",
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",