@lv-x-software-house/x_view 1.2.5-dev.44 → 1.2.5-dev.46

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
@@ -1098,6 +1098,7 @@ function XViewSidebar({
1098
1098
  onClick: () => {
1099
1099
  onActivateQuestLens({ assigneeId: questFilterAssignee, status: questFilterStatus });
1100
1100
  setIsQuestLensMenuOpen(false);
1101
+ onToggle(false);
1101
1102
  },
1102
1103
  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"
1103
1104
  },
@@ -14059,6 +14060,27 @@ function XViewScene({
14059
14060
  timeToYMap.set(ms, idx * TIMELINE_LAYER_SPACING_Y);
14060
14061
  });
14061
14062
  const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
14063
+ let sumX = 0;
14064
+ let sumY = 0;
14065
+ let questCount = 0;
14066
+ const positionGroups = /* @__PURE__ */ new Map();
14067
+ const NODE_X_GAP = 22;
14068
+ QUEST_STATUS_ORDER.forEach((statusName) => {
14069
+ const questsInCol = questsByStatus[statusName];
14070
+ questsInCol.forEach((q, rowIndex) => {
14071
+ const timeInfo = questTimeInfos.get(String(q.id)) || { isUndated: true };
14072
+ let nodeY;
14073
+ if (!timeInfo.isUndated) {
14074
+ nodeY = timeToYMap.get(timeInfo.startDate.getTime());
14075
+ } else {
14076
+ const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
14077
+ nodeY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
14078
+ }
14079
+ const posKey = `${statusName}_${nodeY}`;
14080
+ if (!positionGroups.has(posKey)) positionGroups.set(posKey, []);
14081
+ positionGroups.get(posKey).push(String(q.id));
14082
+ });
14083
+ });
14062
14084
  Object.values(nodeObjects).forEach((mesh) => {
14063
14085
  const oldLabel = mesh.getObjectByName("questDateLabel") || mesh.getObjectByName("timelineLabel");
14064
14086
  if (oldLabel) {
@@ -14074,21 +14096,40 @@ function XViewScene({
14074
14096
  mesh.userData.timelineEndLabel = null;
14075
14097
  }
14076
14098
  });
14077
- Object.keys(nodeObjects).forEach((id) => {
14099
+ const nonFilteredNodeIds = Object.keys(nodeObjects).filter((id) => !filteredQuests.some((q) => String(q.id) === String(id)));
14100
+ const COMMON_START_X = startX - 100;
14101
+ const COMMON_COL_SPACING = 30;
14102
+ const COMMON_ROW_SPACING = 35;
14103
+ const MAX_COMMON_ROWS = 15;
14104
+ nonFilteredNodeIds.forEach((id, idx) => {
14078
14105
  const mesh = nodeObjects[id];
14079
- const isFilteredQuest = filteredQuests.some(
14080
- (q) => String(q.id) === String(id)
14081
- );
14082
- if (!isFilteredQuest) {
14083
- if (mesh.material) {
14084
- const fadeTween = new import_tween2.Tween(mesh.material).to({ opacity: 0.15 }, 1200).easing(import_tween2.Easing.Cubic.Out);
14085
- tweenGroup.add(fadeTween);
14086
- fadeTween.start();
14087
- }
14088
- if (mesh.userData.labelObject) {
14089
- mesh.userData.labelObject.visible = false;
14090
- }
14091
- } else {
14106
+ if (!mesh) return;
14107
+ const col = Math.floor(idx / MAX_COMMON_ROWS);
14108
+ const row = idx % MAX_COMMON_ROWS;
14109
+ const targetX = COMMON_START_X - col * COMMON_COL_SPACING;
14110
+ const targetY = -(row * COMMON_ROW_SPACING) + 50;
14111
+ const targetZ = 0;
14112
+ if (mesh.material) {
14113
+ const opacityTween = new import_tween2.Tween(mesh.material).to({ opacity: 1 }, 1200).easing(import_tween2.Easing.Cubic.Out);
14114
+ tweenGroup.add(opacityTween);
14115
+ opacityTween.start();
14116
+ }
14117
+ if (mesh.userData.labelObject) {
14118
+ mesh.userData.labelObject.visible = true;
14119
+ const labelTargetPos = new THREE3.Vector3(targetX, targetY, targetZ).add(
14120
+ mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
14121
+ );
14122
+ const labelTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(import_tween2.Easing.Cubic.InOut);
14123
+ tweenGroup.add(labelTween);
14124
+ labelTween.start();
14125
+ }
14126
+ const sideTween = new import_tween2.Tween(mesh.position).to({ x: targetX, y: targetY, z: targetZ }, 1500).easing(import_tween2.Easing.Cubic.InOut);
14127
+ tweenGroup.add(sideTween);
14128
+ sideTween.start();
14129
+ });
14130
+ filteredQuests.forEach((q) => {
14131
+ const mesh = nodeObjects[String(q.id)];
14132
+ if (mesh) {
14092
14133
  if (mesh.material) {
14093
14134
  const fadeInTween = new import_tween2.Tween(mesh.material).to({ opacity: 1 }, 1200).easing(import_tween2.Easing.Cubic.Out);
14094
14135
  tweenGroup.add(fadeInTween);
@@ -14106,9 +14147,6 @@ function XViewScene({
14106
14147
  questsInCol.forEach((q, rowIndex) => {
14107
14148
  const nodeId = String(q.id);
14108
14149
  let mesh = nodeObjects[nodeId];
14109
- if (!mesh) {
14110
- mesh = addOrUpdateNodeMesh(q, new THREE3.Vector3(colX, 150, 0), true);
14111
- }
14112
14150
  const timeInfo = questTimeInfos.get(nodeId) || { isUndated: true };
14113
14151
  let targetY;
14114
14152
  if (!timeInfo.isUndated) {
@@ -14117,9 +14155,20 @@ function XViewScene({
14117
14155
  const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
14118
14156
  targetY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
14119
14157
  }
14120
- const lensTween = new import_tween2.Tween(mesh.position).to({ x: colX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
14158
+ const posKey = `${statusName}_${targetY}`;
14159
+ const group = positionGroups.get(posKey) || [nodeId];
14160
+ const indexInGroup = group.indexOf(nodeId);
14161
+ const xOffset = (indexInGroup - (group.length - 1) / 2) * NODE_X_GAP;
14162
+ const finalX = colX + xOffset;
14163
+ if (!mesh) {
14164
+ mesh = addOrUpdateNodeMesh(q, new THREE3.Vector3(finalX, 150, 0), true);
14165
+ }
14166
+ const lensTween = new import_tween2.Tween(mesh.position).to({ x: finalX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
14121
14167
  tweenGroup.add(lensTween);
14122
14168
  lensTween.start();
14169
+ sumX += finalX;
14170
+ sumY += targetY;
14171
+ questCount++;
14123
14172
  if (!timeInfo.isUndated && timeInfo.label && !mesh.getObjectByName("questDateLabel")) {
14124
14173
  const dateSprite = createTextSprite(timeInfo.label, 36);
14125
14174
  dateSprite.name = "questDateLabel";
@@ -14147,20 +14196,19 @@ function XViewScene({
14147
14196
  });
14148
14197
  const intervalBar = new THREE3.Mesh(barGeometry, barMaterial);
14149
14198
  intervalBar.userData.associatedNodeId = mesh.userData.id;
14150
- const endPosition = new THREE3.Vector3(colX, endY, -0.5);
14151
- intervalBar.position.set(colX, (targetY + endY) / 2, -0.5);
14199
+ intervalBar.position.set(finalX, (targetY + endY) / 2, -0.5);
14152
14200
  intervalBar.scale.y = barHeight;
14153
14201
  graphGroup.add(intervalBar);
14154
14202
  mesh.userData.timelineIntervalBar = intervalBar;
14155
14203
  const endLabel = createTextSprite(timeInfo.label.split(" - ")[1] || "", 30);
14156
14204
  endLabel.name = "timelineEndLabel";
14157
- endLabel.position.set(colX, endY + 4, 0);
14205
+ endLabel.position.set(finalX, endY + 4, 0);
14158
14206
  graphGroup.add(endLabel);
14159
14207
  mesh.userData.timelineEndLabel = endLabel;
14160
14208
  }
14161
14209
  }
14162
14210
  if (mesh.userData.labelObject) {
14163
- const labelTargetPos = new THREE3.Vector3(colX, targetY, 0).add(
14211
+ const labelTargetPos = new THREE3.Vector3(finalX, targetY, 0).add(
14164
14212
  mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
14165
14213
  );
14166
14214
  const labelTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(import_tween2.Easing.Cubic.InOut);
@@ -14169,6 +14217,18 @@ function XViewScene({
14169
14217
  }
14170
14218
  });
14171
14219
  });
14220
+ if (questCount > 0) {
14221
+ const { camera, controls } = stateRef.current;
14222
+ const centerX = sumX / questCount;
14223
+ const centerY = sumY / questCount;
14224
+ const targetFocus = new THREE3.Vector3(centerX, centerY, 0);
14225
+ 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);
14226
+ tweenGroup.add(targetTween);
14227
+ targetTween.start();
14228
+ const camTween = new import_tween2.Tween(camera.position).to({ x: targetFocus.x, y: targetFocus.y, z: 140 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
14229
+ tweenGroup.add(camTween);
14230
+ camTween.start();
14231
+ }
14172
14232
  }, [addOrUpdateNodeMesh]);
14173
14233
  (0, import_react28.useEffect)(() => {
14174
14234
  if (!isInitialized || !sceneDataRef.current) return;
package/dist/index.mjs CHANGED
@@ -1059,6 +1059,7 @@ function XViewSidebar({
1059
1059
  onClick: () => {
1060
1060
  onActivateQuestLens({ assigneeId: questFilterAssignee, status: questFilterStatus });
1061
1061
  setIsQuestLensMenuOpen(false);
1062
+ onToggle(false);
1062
1063
  },
1063
1064
  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"
1064
1065
  },
@@ -14103,6 +14104,27 @@ function XViewScene({
14103
14104
  timeToYMap.set(ms, idx * TIMELINE_LAYER_SPACING_Y);
14104
14105
  });
14105
14106
  const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
14107
+ let sumX = 0;
14108
+ let sumY = 0;
14109
+ let questCount = 0;
14110
+ const positionGroups = /* @__PURE__ */ new Map();
14111
+ const NODE_X_GAP = 22;
14112
+ QUEST_STATUS_ORDER.forEach((statusName) => {
14113
+ const questsInCol = questsByStatus[statusName];
14114
+ questsInCol.forEach((q, rowIndex) => {
14115
+ const timeInfo = questTimeInfos.get(String(q.id)) || { isUndated: true };
14116
+ let nodeY;
14117
+ if (!timeInfo.isUndated) {
14118
+ nodeY = timeToYMap.get(timeInfo.startDate.getTime());
14119
+ } else {
14120
+ const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
14121
+ nodeY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
14122
+ }
14123
+ const posKey = `${statusName}_${nodeY}`;
14124
+ if (!positionGroups.has(posKey)) positionGroups.set(posKey, []);
14125
+ positionGroups.get(posKey).push(String(q.id));
14126
+ });
14127
+ });
14106
14128
  Object.values(nodeObjects).forEach((mesh) => {
14107
14129
  const oldLabel = mesh.getObjectByName("questDateLabel") || mesh.getObjectByName("timelineLabel");
14108
14130
  if (oldLabel) {
@@ -14118,21 +14140,40 @@ function XViewScene({
14118
14140
  mesh.userData.timelineEndLabel = null;
14119
14141
  }
14120
14142
  });
14121
- Object.keys(nodeObjects).forEach((id) => {
14143
+ const nonFilteredNodeIds = Object.keys(nodeObjects).filter((id) => !filteredQuests.some((q) => String(q.id) === String(id)));
14144
+ const COMMON_START_X = startX - 100;
14145
+ const COMMON_COL_SPACING = 30;
14146
+ const COMMON_ROW_SPACING = 35;
14147
+ const MAX_COMMON_ROWS = 15;
14148
+ nonFilteredNodeIds.forEach((id, idx) => {
14122
14149
  const mesh = nodeObjects[id];
14123
- const isFilteredQuest = filteredQuests.some(
14124
- (q) => String(q.id) === String(id)
14125
- );
14126
- if (!isFilteredQuest) {
14127
- if (mesh.material) {
14128
- const fadeTween = new Tween2(mesh.material).to({ opacity: 0.15 }, 1200).easing(Easing2.Cubic.Out);
14129
- tweenGroup.add(fadeTween);
14130
- fadeTween.start();
14131
- }
14132
- if (mesh.userData.labelObject) {
14133
- mesh.userData.labelObject.visible = false;
14134
- }
14135
- } else {
14150
+ if (!mesh) return;
14151
+ const col = Math.floor(idx / MAX_COMMON_ROWS);
14152
+ const row = idx % MAX_COMMON_ROWS;
14153
+ const targetX = COMMON_START_X - col * COMMON_COL_SPACING;
14154
+ const targetY = -(row * COMMON_ROW_SPACING) + 50;
14155
+ const targetZ = 0;
14156
+ if (mesh.material) {
14157
+ const opacityTween = new Tween2(mesh.material).to({ opacity: 1 }, 1200).easing(Easing2.Cubic.Out);
14158
+ tweenGroup.add(opacityTween);
14159
+ opacityTween.start();
14160
+ }
14161
+ if (mesh.userData.labelObject) {
14162
+ mesh.userData.labelObject.visible = true;
14163
+ const labelTargetPos = new THREE3.Vector3(targetX, targetY, targetZ).add(
14164
+ mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
14165
+ );
14166
+ const labelTween = new Tween2(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(Easing2.Cubic.InOut);
14167
+ tweenGroup.add(labelTween);
14168
+ labelTween.start();
14169
+ }
14170
+ const sideTween = new Tween2(mesh.position).to({ x: targetX, y: targetY, z: targetZ }, 1500).easing(Easing2.Cubic.InOut);
14171
+ tweenGroup.add(sideTween);
14172
+ sideTween.start();
14173
+ });
14174
+ filteredQuests.forEach((q) => {
14175
+ const mesh = nodeObjects[String(q.id)];
14176
+ if (mesh) {
14136
14177
  if (mesh.material) {
14137
14178
  const fadeInTween = new Tween2(mesh.material).to({ opacity: 1 }, 1200).easing(Easing2.Cubic.Out);
14138
14179
  tweenGroup.add(fadeInTween);
@@ -14150,9 +14191,6 @@ function XViewScene({
14150
14191
  questsInCol.forEach((q, rowIndex) => {
14151
14192
  const nodeId = String(q.id);
14152
14193
  let mesh = nodeObjects[nodeId];
14153
- if (!mesh) {
14154
- mesh = addOrUpdateNodeMesh(q, new THREE3.Vector3(colX, 150, 0), true);
14155
- }
14156
14194
  const timeInfo = questTimeInfos.get(nodeId) || { isUndated: true };
14157
14195
  let targetY;
14158
14196
  if (!timeInfo.isUndated) {
@@ -14161,9 +14199,20 @@ function XViewScene({
14161
14199
  const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
14162
14200
  targetY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
14163
14201
  }
14164
- const lensTween = new Tween2(mesh.position).to({ x: colX, y: targetY, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
14202
+ const posKey = `${statusName}_${targetY}`;
14203
+ const group = positionGroups.get(posKey) || [nodeId];
14204
+ const indexInGroup = group.indexOf(nodeId);
14205
+ const xOffset = (indexInGroup - (group.length - 1) / 2) * NODE_X_GAP;
14206
+ const finalX = colX + xOffset;
14207
+ if (!mesh) {
14208
+ mesh = addOrUpdateNodeMesh(q, new THREE3.Vector3(finalX, 150, 0), true);
14209
+ }
14210
+ const lensTween = new Tween2(mesh.position).to({ x: finalX, y: targetY, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
14165
14211
  tweenGroup.add(lensTween);
14166
14212
  lensTween.start();
14213
+ sumX += finalX;
14214
+ sumY += targetY;
14215
+ questCount++;
14167
14216
  if (!timeInfo.isUndated && timeInfo.label && !mesh.getObjectByName("questDateLabel")) {
14168
14217
  const dateSprite = createTextSprite(timeInfo.label, 36);
14169
14218
  dateSprite.name = "questDateLabel";
@@ -14191,20 +14240,19 @@ function XViewScene({
14191
14240
  });
14192
14241
  const intervalBar = new THREE3.Mesh(barGeometry, barMaterial);
14193
14242
  intervalBar.userData.associatedNodeId = mesh.userData.id;
14194
- const endPosition = new THREE3.Vector3(colX, endY, -0.5);
14195
- intervalBar.position.set(colX, (targetY + endY) / 2, -0.5);
14243
+ intervalBar.position.set(finalX, (targetY + endY) / 2, -0.5);
14196
14244
  intervalBar.scale.y = barHeight;
14197
14245
  graphGroup.add(intervalBar);
14198
14246
  mesh.userData.timelineIntervalBar = intervalBar;
14199
14247
  const endLabel = createTextSprite(timeInfo.label.split(" - ")[1] || "", 30);
14200
14248
  endLabel.name = "timelineEndLabel";
14201
- endLabel.position.set(colX, endY + 4, 0);
14249
+ endLabel.position.set(finalX, endY + 4, 0);
14202
14250
  graphGroup.add(endLabel);
14203
14251
  mesh.userData.timelineEndLabel = endLabel;
14204
14252
  }
14205
14253
  }
14206
14254
  if (mesh.userData.labelObject) {
14207
- const labelTargetPos = new THREE3.Vector3(colX, targetY, 0).add(
14255
+ const labelTargetPos = new THREE3.Vector3(finalX, targetY, 0).add(
14208
14256
  mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
14209
14257
  );
14210
14258
  const labelTween = new Tween2(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(Easing2.Cubic.InOut);
@@ -14213,6 +14261,18 @@ function XViewScene({
14213
14261
  }
14214
14262
  });
14215
14263
  });
14264
+ if (questCount > 0) {
14265
+ const { camera, controls } = stateRef.current;
14266
+ const centerX = sumX / questCount;
14267
+ const centerY = sumY / questCount;
14268
+ const targetFocus = new THREE3.Vector3(centerX, centerY, 0);
14269
+ const targetTween = new Tween2(controls.target).to({ x: targetFocus.x, y: targetFocus.y, z: targetFocus.z }, 1500).easing(Easing2.Cubic.InOut);
14270
+ tweenGroup.add(targetTween);
14271
+ targetTween.start();
14272
+ const camTween = new Tween2(camera.position).to({ x: targetFocus.x, y: targetFocus.y, z: 140 }, 1500).easing(Easing2.Cubic.InOut);
14273
+ tweenGroup.add(camTween);
14274
+ camTween.start();
14275
+ }
14216
14276
  }, [addOrUpdateNodeMesh]);
14217
14277
  useEffect22(() => {
14218
14278
  if (!isInitialized || !sceneDataRef.current) return;
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.44",
3
+ "version": "1.2.5-dev.46",
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",