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

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.
Files changed (3) hide show
  1. package/dist/index.js +164 -71
  2. package/dist/index.mjs +164 -71
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1334,6 +1334,15 @@ var createNodeMesh = (nodeData, position, glowTexture) => {
1334
1334
  label.name = "label";
1335
1335
  mesh.userData.labelObject = label;
1336
1336
  mesh.userData.labelOffset = new THREE.Vector3(0, 3.8, 0);
1337
+ if (nodeData.is_quest && nodeData.Date) {
1338
+ const timeInfo = parseDateProp(nodeData.Date);
1339
+ if (!timeInfo.isUndated && timeInfo.label) {
1340
+ const dateSprite = createTextSprite(timeInfo.label, 36);
1341
+ dateSprite.name = "questDateLabel";
1342
+ dateSprite.position.set(0, -5.5, 0);
1343
+ mesh.add(dateSprite);
1344
+ }
1345
+ }
1337
1346
  return mesh;
1338
1347
  };
1339
1348
  var updateExistingNodeVisuals = (state, updatedNode) => {
@@ -3321,9 +3330,14 @@ var userActionHandlers = {
3321
3330
  };
3322
3331
  specificParentData.nodes.push(nextQuestNode);
3323
3332
  if (stateRef.current.nodeObjects[String(nodeToSave.id)]) {
3324
- const pos = stateRef.current.nodeObjects[String(nodeToSave.id)].position.clone();
3325
- pos.x += 12;
3326
- addStandaloneNodeToScene(stateRef.current, nextQuestNode, pos);
3333
+ const oldMeshPosition = stateRef.current.nodeObjects[String(nodeToSave.id)].position.clone();
3334
+ setTimeout(() => {
3335
+ if (stateRef.current && stateRef.current.graphGroup) {
3336
+ const pos = oldMeshPosition.clone();
3337
+ pos.x += 12;
3338
+ addStandaloneNodeToScene(stateRef.current, nextQuestNode, pos);
3339
+ }
3340
+ }, 2e3);
3327
3341
  }
3328
3342
  }
3329
3343
  }
@@ -4260,8 +4274,84 @@ function calculateNextRecurrenceDate(config) {
4260
4274
  const d = String(nextDate.getDate()).padStart(2, "0");
4261
4275
  const m = String(nextDate.getMonth() + 1).padStart(2, "0");
4262
4276
  const y = nextDate.getFullYear();
4263
- return { date: `${d}/${m}/${y}` };
4277
+ return {
4278
+ type: "Data",
4279
+ value: `${d}/${m}/${y}`,
4280
+ confirmed: true
4281
+ };
4264
4282
  }
4283
+ var parseDate = (str) => {
4284
+ if (!str) return null;
4285
+ const parts = str.split("/");
4286
+ if (parts.length === 3) {
4287
+ const day = parseInt(parts[0], 10);
4288
+ const month = parseInt(parts[1], 10) - 1;
4289
+ const year = parseInt(parts[2], 10);
4290
+ if (!isNaN(day) && !isNaN(month) && !isNaN(year)) {
4291
+ return new Date(year, month, day);
4292
+ }
4293
+ }
4294
+ return null;
4295
+ };
4296
+ var parseDateProp = (dateProp) => {
4297
+ let info = { isUndated: true, label: "", type: "point" };
4298
+ if (!dateProp) return info;
4299
+ if (dateProp.type === "Data") {
4300
+ const d = parseDate(dateProp.value);
4301
+ if (d) {
4302
+ info = { startDate: d, endDate: d, label: dateProp.value, type: "point", isUndated: false };
4303
+ }
4304
+ } else if (dateProp.type === "Date Interval" || dateProp.type === "Date Range" || dateProp.type === "interval") {
4305
+ const sd = parseDate(dateProp.start || dateProp.value);
4306
+ const ed = parseDate(dateProp.end);
4307
+ if (sd) {
4308
+ info = {
4309
+ startDate: sd,
4310
+ endDate: ed || sd,
4311
+ label: `${dateProp.start || dateProp.value}${ed ? " - " + dateProp.end : ""}`,
4312
+ type: ed ? "interval" : "point",
4313
+ isUndated: false
4314
+ };
4315
+ }
4316
+ } else if (dateProp.date) {
4317
+ const d = parseDate(dateProp.date);
4318
+ if (d)
4319
+ info = {
4320
+ startDate: d,
4321
+ endDate: d,
4322
+ label: dateProp.date,
4323
+ type: "point",
4324
+ isUndated: false
4325
+ };
4326
+ } else if (dateProp.year) {
4327
+ const y = parseInt(dateProp.year, 10);
4328
+ if (!isNaN(y)) {
4329
+ const d = new Date(y, 0, 1);
4330
+ info = {
4331
+ startDate: d,
4332
+ endDate: d,
4333
+ label: String(y),
4334
+ type: "point",
4335
+ isUndated: false
4336
+ };
4337
+ }
4338
+ } else if (dateProp.date_interval && dateProp.date_interval.start) {
4339
+ const sY = parseInt(dateProp.date_interval.start, 10);
4340
+ const eY = parseInt(dateProp.date_interval.end, 10) || sY;
4341
+ if (!isNaN(sY)) {
4342
+ const sd = new Date(sY, 0, 1);
4343
+ const ed = new Date(eY, 11, 31);
4344
+ info = {
4345
+ startDate: sd,
4346
+ endDate: ed,
4347
+ label: `${sY} - ${eY}`,
4348
+ type: "interval",
4349
+ isUndated: false
4350
+ };
4351
+ }
4352
+ }
4353
+ return info;
4354
+ };
4265
4355
 
4266
4356
  // src/components/CustomPropertyDisplay.jsx
4267
4357
  var import_react4 = __toESM(require("react"));
@@ -9468,7 +9558,7 @@ function InSceneQuestForm({
9468
9558
  textureImageUrl: null,
9469
9559
  reviewStack,
9470
9560
  timeline: initialTimeline,
9471
- Date: questDate,
9561
+ Date: questDate ? { ...questDate, confirmed: true } : null,
9472
9562
  recurrence_config: recurrenceConfig,
9473
9563
  ...additionalData
9474
9564
  });
@@ -10932,7 +11022,7 @@ ${noteText}` : noteText : entry.notes,
10932
11022
  description_sections: processedSections,
10933
11023
  intensity,
10934
11024
  recurrence_config: currentRecurrenceConfig,
10935
- Date: questDate,
11025
+ Date: questDate ? { ...questDate, confirmed: true } : null,
10936
11026
  useImageAsTexture: false,
10937
11027
  textureImageUrl: null,
10938
11028
  is_quest: true,
@@ -13495,7 +13585,7 @@ function XViewScene({
13495
13585
  }
13496
13586
  }
13497
13587
  Object.values(nodeObjects).forEach((mesh) => {
13498
- const oldLabel = mesh.getObjectByName("timelineLabel") || mesh.getObjectByName("questDateLabel");
13588
+ const oldLabel = mesh.getObjectByName("timelineLabel");
13499
13589
  if (oldLabel) {
13500
13590
  mesh.remove(oldLabel);
13501
13591
  if (oldLabel.material.map) oldLabel.material.map.dispose();
@@ -13506,7 +13596,7 @@ function XViewScene({
13506
13596
  });
13507
13597
  const timelineNodes = [];
13508
13598
  const allTimePoints = /* @__PURE__ */ new Set();
13509
- const parseDate = (str) => {
13599
+ const parseDate2 = (str) => {
13510
13600
  const parts = str.split("/");
13511
13601
  if (parts.length === 3) {
13512
13602
  const day = parseInt(parts[0], 10);
@@ -13523,7 +13613,7 @@ function XViewScene({
13523
13613
  let nodeInfo = { mesh, type: "point", label: "", isUndated: true };
13524
13614
  if (dateProp) {
13525
13615
  if (dateProp.date) {
13526
- const date = parseDate(dateProp.date);
13616
+ const date = parseDate2(dateProp.date);
13527
13617
  if (date) {
13528
13618
  nodeInfo.startDate = date;
13529
13619
  nodeInfo.endDate = date;
@@ -13669,7 +13759,7 @@ function XViewScene({
13669
13759
  });
13670
13760
  const timelineNodes = [];
13671
13761
  const allTimePoints = /* @__PURE__ */ new Set();
13672
- const parseDate = (str) => {
13762
+ const parseDate2 = (str) => {
13673
13763
  const parts = str.split("/");
13674
13764
  if (parts.length === 3) {
13675
13765
  const day = parseInt(parts[0], 10);
@@ -13686,7 +13776,7 @@ function XViewScene({
13686
13776
  if (!dateProp) return;
13687
13777
  let nodeInfo = { mesh, type: "point", label: "" };
13688
13778
  if (dateProp.date) {
13689
- const date = parseDate(dateProp.date);
13779
+ const date = parseDate2(dateProp.date);
13690
13780
  if (date) {
13691
13781
  nodeInfo.startDate = date;
13692
13782
  nodeInfo.endDate = date;
@@ -13928,16 +14018,8 @@ function XViewScene({
13928
14018
  );
13929
14019
  const handleActivateQuestLens = (0, import_react28.useCallback)(({ assigneeId, status: status2 }) => {
13930
14020
  var _a2;
13931
- const { nodeObjects, tweenGroup, graphGroup, timelineIntervalsGroup } = stateRef.current;
14021
+ const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
13932
14022
  if (!nodeObjects || !tweenGroup || !graphGroup) return;
13933
- Object.values(nodeObjects).forEach((mesh) => {
13934
- const oldLabel = mesh.getObjectByName("questDateLabel") || mesh.getObjectByName("timelineLabel");
13935
- if (oldLabel) {
13936
- mesh.remove(oldLabel);
13937
- if (oldLabel.material.map) oldLabel.material.map.dispose();
13938
- oldLabel.material.dispose();
13939
- }
13940
- });
13941
14023
  const allQuests = ((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || [];
13942
14024
  const filteredQuests = allQuests.filter((q) => {
13943
14025
  const matchAssignee = !assigneeId || String(q.assignee_id) === String(assigneeId);
@@ -13959,61 +14041,39 @@ function XViewScene({
13959
14041
  questsByStatus[q.status].push(q);
13960
14042
  }
13961
14043
  });
13962
- const parseDate = (str) => {
13963
- if (!str) return null;
13964
- const parts = str.split("/");
13965
- if (parts.length === 3) {
13966
- const day = parseInt(parts[0], 10);
13967
- const month = parseInt(parts[1], 10) - 1;
13968
- const year = parseInt(parts[2], 10);
13969
- if (!isNaN(day) && !isNaN(month) && !isNaN(year)) {
13970
- return new Date(year, month, day);
13971
- }
13972
- }
13973
- return null;
13974
- };
13975
- const timePoints = /* @__PURE__ */ new Set();
13976
14044
  const questTimeInfos = /* @__PURE__ */ new Map();
14045
+ const allActiveTimePoints = /* @__PURE__ */ new Set();
13977
14046
  filteredQuests.forEach((q) => {
13978
- const dateProp = q.Date;
13979
- let info = { isUndated: true, label: "" };
13980
- if (dateProp) {
13981
- if (dateProp.date) {
13982
- const d = parseDate(dateProp.date);
13983
- if (d) {
13984
- info = { startDate: d, endDate: d, label: dateProp.date, isUndated: false };
13985
- timePoints.add(d.getTime());
13986
- }
13987
- } else if (dateProp.year) {
13988
- const y = parseInt(dateProp.year, 10);
13989
- if (!isNaN(y)) {
13990
- const d = new Date(y, 0, 1);
13991
- info = { startDate: d, endDate: d, label: String(y), isUndated: false };
13992
- timePoints.add(d.getTime());
13993
- }
13994
- } else if (dateProp.date_interval && dateProp.date_interval.start) {
13995
- const sY = parseInt(dateProp.date_interval.start, 10);
13996
- const eY = parseInt(dateProp.date_interval.end, 10) || sY;
13997
- if (!isNaN(sY)) {
13998
- const sd = new Date(sY, 0, 1);
13999
- const ed = new Date(eY, 11, 31);
14000
- info = { startDate: sd, endDate: ed, label: `${sY}-${eY}`, isUndated: false };
14001
- timePoints.add(sd.getTime());
14002
- timePoints.add(ed.getTime());
14003
- }
14047
+ const info = parseDateProp(q.Date);
14048
+ questTimeInfos.set(String(q.id), info);
14049
+ if (!info.isUndated) {
14050
+ allActiveTimePoints.add(info.startDate.getTime());
14051
+ if (info.endDate && info.type === "interval") {
14052
+ allActiveTimePoints.add(info.endDate.getTime());
14004
14053
  }
14005
14054
  }
14006
- questTimeInfos.set(String(q.id), info);
14007
14055
  });
14008
- const sortedTimePoints = Array.from(timePoints).sort((a, b) => a - b);
14056
+ const sortedTimePoints = Array.from(allActiveTimePoints).sort((a, b) => a - b);
14009
14057
  const timeToYMap = /* @__PURE__ */ new Map();
14010
- if (sortedTimePoints.length > 0) {
14011
- const maxIdx = sortedTimePoints.length - 1;
14012
- sortedTimePoints.forEach((t, i) => {
14013
- timeToYMap.set(t, (i - maxIdx) * (QUEST_LENS_ROW_SPACING || 30));
14014
- });
14015
- }
14058
+ sortedTimePoints.forEach((ms, idx) => {
14059
+ timeToYMap.set(ms, idx * TIMELINE_LAYER_SPACING_Y);
14060
+ });
14016
14061
  const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
14062
+ Object.values(nodeObjects).forEach((mesh) => {
14063
+ const oldLabel = mesh.getObjectByName("questDateLabel") || mesh.getObjectByName("timelineLabel");
14064
+ if (oldLabel) {
14065
+ mesh.remove(oldLabel);
14066
+ if (oldLabel.material) oldLabel.material.dispose();
14067
+ }
14068
+ if (mesh.userData.timelineIntervalBar) {
14069
+ if (graphGroup) graphGroup.remove(mesh.userData.timelineIntervalBar);
14070
+ mesh.userData.timelineIntervalBar = null;
14071
+ }
14072
+ if (mesh.userData.timelineEndLabel) {
14073
+ if (graphGroup) graphGroup.remove(mesh.userData.timelineEndLabel);
14074
+ mesh.userData.timelineEndLabel = null;
14075
+ }
14076
+ });
14017
14077
  Object.keys(nodeObjects).forEach((id) => {
14018
14078
  const mesh = nodeObjects[id];
14019
14079
  const isFilteredQuest = filteredQuests.some(
@@ -14055,20 +14115,53 @@ function XViewScene({
14055
14115
  targetY = timeToYMap.get(timeInfo.startDate.getTime());
14056
14116
  } else {
14057
14117
  const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
14058
- targetY = -80 - rowIndex * (QUEST_LENS_ROW_SPACING || 30) - undatedOffset;
14118
+ targetY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
14059
14119
  }
14060
14120
  const lensTween = new import_tween2.Tween(mesh.position).to({ x: colX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
14061
14121
  tweenGroup.add(lensTween);
14062
14122
  lensTween.start();
14063
- if (!timeInfo.isUndated && timeInfo.label) {
14123
+ if (!timeInfo.isUndated && timeInfo.label && !mesh.getObjectByName("questDateLabel")) {
14064
14124
  const dateSprite = createTextSprite(timeInfo.label, 36);
14065
14125
  dateSprite.name = "questDateLabel";
14066
14126
  dateSprite.position.set(0, -5.5, 0);
14067
14127
  mesh.add(dateSprite);
14068
14128
  }
14129
+ if (timeInfo.type === "interval" && timeToYMap.has(timeInfo.endDate.getTime())) {
14130
+ const endY = timeToYMap.get(timeInfo.endDate.getTime());
14131
+ if (Math.abs(endY - targetY) > 0.1) {
14132
+ const barHeight = Math.abs(endY - targetY);
14133
+ const barGeometry = new THREE3.CylinderGeometry(
14134
+ TIMELINE_INTERVAL_BAR_RADIUS,
14135
+ TIMELINE_INTERVAL_BAR_RADIUS,
14136
+ 1,
14137
+ 16
14138
+ );
14139
+ const barMaterial = new THREE3.MeshStandardMaterial({
14140
+ color: TIMELINE_GOLD_COLOR,
14141
+ emissive: 12092939,
14142
+ emissiveIntensity: 0.4,
14143
+ transparent: true,
14144
+ opacity: TIMELINE_INTERVAL_BAR_OPACITY,
14145
+ roughness: 0.3,
14146
+ metalness: 0.8
14147
+ });
14148
+ const intervalBar = new THREE3.Mesh(barGeometry, barMaterial);
14149
+ 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);
14152
+ intervalBar.scale.y = barHeight;
14153
+ graphGroup.add(intervalBar);
14154
+ mesh.userData.timelineIntervalBar = intervalBar;
14155
+ const endLabel = createTextSprite(timeInfo.label.split(" - ")[1] || "", 30);
14156
+ endLabel.name = "timelineEndLabel";
14157
+ endLabel.position.set(colX, endY + 4, 0);
14158
+ graphGroup.add(endLabel);
14159
+ mesh.userData.timelineEndLabel = endLabel;
14160
+ }
14161
+ }
14069
14162
  if (mesh.userData.labelObject) {
14070
14163
  const labelTargetPos = new THREE3.Vector3(colX, targetY, 0).add(
14071
- mesh.userData.labelOffset || new THREE3.Vector3(0, -2.5, 0)
14164
+ mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
14072
14165
  );
14073
14166
  const labelTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(import_tween2.Easing.Cubic.InOut);
14074
14167
  tweenGroup.add(labelTween);
package/dist/index.mjs CHANGED
@@ -1295,6 +1295,15 @@ var createNodeMesh = (nodeData, position, glowTexture) => {
1295
1295
  label.name = "label";
1296
1296
  mesh.userData.labelObject = label;
1297
1297
  mesh.userData.labelOffset = new THREE.Vector3(0, 3.8, 0);
1298
+ if (nodeData.is_quest && nodeData.Date) {
1299
+ const timeInfo = parseDateProp(nodeData.Date);
1300
+ if (!timeInfo.isUndated && timeInfo.label) {
1301
+ const dateSprite = createTextSprite(timeInfo.label, 36);
1302
+ dateSprite.name = "questDateLabel";
1303
+ dateSprite.position.set(0, -5.5, 0);
1304
+ mesh.add(dateSprite);
1305
+ }
1306
+ }
1298
1307
  return mesh;
1299
1308
  };
1300
1309
  var updateExistingNodeVisuals = (state, updatedNode) => {
@@ -3282,9 +3291,14 @@ var userActionHandlers = {
3282
3291
  };
3283
3292
  specificParentData.nodes.push(nextQuestNode);
3284
3293
  if (stateRef.current.nodeObjects[String(nodeToSave.id)]) {
3285
- const pos = stateRef.current.nodeObjects[String(nodeToSave.id)].position.clone();
3286
- pos.x += 12;
3287
- addStandaloneNodeToScene(stateRef.current, nextQuestNode, pos);
3294
+ const oldMeshPosition = stateRef.current.nodeObjects[String(nodeToSave.id)].position.clone();
3295
+ setTimeout(() => {
3296
+ if (stateRef.current && stateRef.current.graphGroup) {
3297
+ const pos = oldMeshPosition.clone();
3298
+ pos.x += 12;
3299
+ addStandaloneNodeToScene(stateRef.current, nextQuestNode, pos);
3300
+ }
3301
+ }, 2e3);
3288
3302
  }
3289
3303
  }
3290
3304
  }
@@ -4221,8 +4235,84 @@ function calculateNextRecurrenceDate(config) {
4221
4235
  const d = String(nextDate.getDate()).padStart(2, "0");
4222
4236
  const m = String(nextDate.getMonth() + 1).padStart(2, "0");
4223
4237
  const y = nextDate.getFullYear();
4224
- return { date: `${d}/${m}/${y}` };
4238
+ return {
4239
+ type: "Data",
4240
+ value: `${d}/${m}/${y}`,
4241
+ confirmed: true
4242
+ };
4225
4243
  }
4244
+ var parseDate = (str) => {
4245
+ if (!str) return null;
4246
+ const parts = str.split("/");
4247
+ if (parts.length === 3) {
4248
+ const day = parseInt(parts[0], 10);
4249
+ const month = parseInt(parts[1], 10) - 1;
4250
+ const year = parseInt(parts[2], 10);
4251
+ if (!isNaN(day) && !isNaN(month) && !isNaN(year)) {
4252
+ return new Date(year, month, day);
4253
+ }
4254
+ }
4255
+ return null;
4256
+ };
4257
+ var parseDateProp = (dateProp) => {
4258
+ let info = { isUndated: true, label: "", type: "point" };
4259
+ if (!dateProp) return info;
4260
+ if (dateProp.type === "Data") {
4261
+ const d = parseDate(dateProp.value);
4262
+ if (d) {
4263
+ info = { startDate: d, endDate: d, label: dateProp.value, type: "point", isUndated: false };
4264
+ }
4265
+ } else if (dateProp.type === "Date Interval" || dateProp.type === "Date Range" || dateProp.type === "interval") {
4266
+ const sd = parseDate(dateProp.start || dateProp.value);
4267
+ const ed = parseDate(dateProp.end);
4268
+ if (sd) {
4269
+ info = {
4270
+ startDate: sd,
4271
+ endDate: ed || sd,
4272
+ label: `${dateProp.start || dateProp.value}${ed ? " - " + dateProp.end : ""}`,
4273
+ type: ed ? "interval" : "point",
4274
+ isUndated: false
4275
+ };
4276
+ }
4277
+ } else if (dateProp.date) {
4278
+ const d = parseDate(dateProp.date);
4279
+ if (d)
4280
+ info = {
4281
+ startDate: d,
4282
+ endDate: d,
4283
+ label: dateProp.date,
4284
+ type: "point",
4285
+ isUndated: false
4286
+ };
4287
+ } else if (dateProp.year) {
4288
+ const y = parseInt(dateProp.year, 10);
4289
+ if (!isNaN(y)) {
4290
+ const d = new Date(y, 0, 1);
4291
+ info = {
4292
+ startDate: d,
4293
+ endDate: d,
4294
+ label: String(y),
4295
+ type: "point",
4296
+ isUndated: false
4297
+ };
4298
+ }
4299
+ } else if (dateProp.date_interval && dateProp.date_interval.start) {
4300
+ const sY = parseInt(dateProp.date_interval.start, 10);
4301
+ const eY = parseInt(dateProp.date_interval.end, 10) || sY;
4302
+ if (!isNaN(sY)) {
4303
+ const sd = new Date(sY, 0, 1);
4304
+ const ed = new Date(eY, 11, 31);
4305
+ info = {
4306
+ startDate: sd,
4307
+ endDate: ed,
4308
+ label: `${sY} - ${eY}`,
4309
+ type: "interval",
4310
+ isUndated: false
4311
+ };
4312
+ }
4313
+ }
4314
+ return info;
4315
+ };
4226
4316
 
4227
4317
  // src/components/CustomPropertyDisplay.jsx
4228
4318
  import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
@@ -9487,7 +9577,7 @@ function InSceneQuestForm({
9487
9577
  textureImageUrl: null,
9488
9578
  reviewStack,
9489
9579
  timeline: initialTimeline,
9490
- Date: questDate,
9580
+ Date: questDate ? { ...questDate, confirmed: true } : null,
9491
9581
  recurrence_config: recurrenceConfig,
9492
9582
  ...additionalData
9493
9583
  });
@@ -10963,7 +11053,7 @@ ${noteText}` : noteText : entry.notes,
10963
11053
  description_sections: processedSections,
10964
11054
  intensity,
10965
11055
  recurrence_config: currentRecurrenceConfig,
10966
- Date: questDate,
11056
+ Date: questDate ? { ...questDate, confirmed: true } : null,
10967
11057
  useImageAsTexture: false,
10968
11058
  textureImageUrl: null,
10969
11059
  is_quest: true,
@@ -13539,7 +13629,7 @@ function XViewScene({
13539
13629
  }
13540
13630
  }
13541
13631
  Object.values(nodeObjects).forEach((mesh) => {
13542
- const oldLabel = mesh.getObjectByName("timelineLabel") || mesh.getObjectByName("questDateLabel");
13632
+ const oldLabel = mesh.getObjectByName("timelineLabel");
13543
13633
  if (oldLabel) {
13544
13634
  mesh.remove(oldLabel);
13545
13635
  if (oldLabel.material.map) oldLabel.material.map.dispose();
@@ -13550,7 +13640,7 @@ function XViewScene({
13550
13640
  });
13551
13641
  const timelineNodes = [];
13552
13642
  const allTimePoints = /* @__PURE__ */ new Set();
13553
- const parseDate = (str) => {
13643
+ const parseDate2 = (str) => {
13554
13644
  const parts = str.split("/");
13555
13645
  if (parts.length === 3) {
13556
13646
  const day = parseInt(parts[0], 10);
@@ -13567,7 +13657,7 @@ function XViewScene({
13567
13657
  let nodeInfo = { mesh, type: "point", label: "", isUndated: true };
13568
13658
  if (dateProp) {
13569
13659
  if (dateProp.date) {
13570
- const date = parseDate(dateProp.date);
13660
+ const date = parseDate2(dateProp.date);
13571
13661
  if (date) {
13572
13662
  nodeInfo.startDate = date;
13573
13663
  nodeInfo.endDate = date;
@@ -13713,7 +13803,7 @@ function XViewScene({
13713
13803
  });
13714
13804
  const timelineNodes = [];
13715
13805
  const allTimePoints = /* @__PURE__ */ new Set();
13716
- const parseDate = (str) => {
13806
+ const parseDate2 = (str) => {
13717
13807
  const parts = str.split("/");
13718
13808
  if (parts.length === 3) {
13719
13809
  const day = parseInt(parts[0], 10);
@@ -13730,7 +13820,7 @@ function XViewScene({
13730
13820
  if (!dateProp) return;
13731
13821
  let nodeInfo = { mesh, type: "point", label: "" };
13732
13822
  if (dateProp.date) {
13733
- const date = parseDate(dateProp.date);
13823
+ const date = parseDate2(dateProp.date);
13734
13824
  if (date) {
13735
13825
  nodeInfo.startDate = date;
13736
13826
  nodeInfo.endDate = date;
@@ -13972,16 +14062,8 @@ function XViewScene({
13972
14062
  );
13973
14063
  const handleActivateQuestLens = useCallback4(({ assigneeId, status: status2 }) => {
13974
14064
  var _a2;
13975
- const { nodeObjects, tweenGroup, graphGroup, timelineIntervalsGroup } = stateRef.current;
14065
+ const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
13976
14066
  if (!nodeObjects || !tweenGroup || !graphGroup) return;
13977
- Object.values(nodeObjects).forEach((mesh) => {
13978
- const oldLabel = mesh.getObjectByName("questDateLabel") || mesh.getObjectByName("timelineLabel");
13979
- if (oldLabel) {
13980
- mesh.remove(oldLabel);
13981
- if (oldLabel.material.map) oldLabel.material.map.dispose();
13982
- oldLabel.material.dispose();
13983
- }
13984
- });
13985
14067
  const allQuests = ((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || [];
13986
14068
  const filteredQuests = allQuests.filter((q) => {
13987
14069
  const matchAssignee = !assigneeId || String(q.assignee_id) === String(assigneeId);
@@ -14003,61 +14085,39 @@ function XViewScene({
14003
14085
  questsByStatus[q.status].push(q);
14004
14086
  }
14005
14087
  });
14006
- const parseDate = (str) => {
14007
- if (!str) return null;
14008
- const parts = str.split("/");
14009
- if (parts.length === 3) {
14010
- const day = parseInt(parts[0], 10);
14011
- const month = parseInt(parts[1], 10) - 1;
14012
- const year = parseInt(parts[2], 10);
14013
- if (!isNaN(day) && !isNaN(month) && !isNaN(year)) {
14014
- return new Date(year, month, day);
14015
- }
14016
- }
14017
- return null;
14018
- };
14019
- const timePoints = /* @__PURE__ */ new Set();
14020
14088
  const questTimeInfos = /* @__PURE__ */ new Map();
14089
+ const allActiveTimePoints = /* @__PURE__ */ new Set();
14021
14090
  filteredQuests.forEach((q) => {
14022
- const dateProp = q.Date;
14023
- let info = { isUndated: true, label: "" };
14024
- if (dateProp) {
14025
- if (dateProp.date) {
14026
- const d = parseDate(dateProp.date);
14027
- if (d) {
14028
- info = { startDate: d, endDate: d, label: dateProp.date, isUndated: false };
14029
- timePoints.add(d.getTime());
14030
- }
14031
- } else if (dateProp.year) {
14032
- const y = parseInt(dateProp.year, 10);
14033
- if (!isNaN(y)) {
14034
- const d = new Date(y, 0, 1);
14035
- info = { startDate: d, endDate: d, label: String(y), isUndated: false };
14036
- timePoints.add(d.getTime());
14037
- }
14038
- } else if (dateProp.date_interval && dateProp.date_interval.start) {
14039
- const sY = parseInt(dateProp.date_interval.start, 10);
14040
- const eY = parseInt(dateProp.date_interval.end, 10) || sY;
14041
- if (!isNaN(sY)) {
14042
- const sd = new Date(sY, 0, 1);
14043
- const ed = new Date(eY, 11, 31);
14044
- info = { startDate: sd, endDate: ed, label: `${sY}-${eY}`, isUndated: false };
14045
- timePoints.add(sd.getTime());
14046
- timePoints.add(ed.getTime());
14047
- }
14091
+ const info = parseDateProp(q.Date);
14092
+ questTimeInfos.set(String(q.id), info);
14093
+ if (!info.isUndated) {
14094
+ allActiveTimePoints.add(info.startDate.getTime());
14095
+ if (info.endDate && info.type === "interval") {
14096
+ allActiveTimePoints.add(info.endDate.getTime());
14048
14097
  }
14049
14098
  }
14050
- questTimeInfos.set(String(q.id), info);
14051
14099
  });
14052
- const sortedTimePoints = Array.from(timePoints).sort((a, b) => a - b);
14100
+ const sortedTimePoints = Array.from(allActiveTimePoints).sort((a, b) => a - b);
14053
14101
  const timeToYMap = /* @__PURE__ */ new Map();
14054
- if (sortedTimePoints.length > 0) {
14055
- const maxIdx = sortedTimePoints.length - 1;
14056
- sortedTimePoints.forEach((t, i) => {
14057
- timeToYMap.set(t, (i - maxIdx) * (QUEST_LENS_ROW_SPACING || 30));
14058
- });
14059
- }
14102
+ sortedTimePoints.forEach((ms, idx) => {
14103
+ timeToYMap.set(ms, idx * TIMELINE_LAYER_SPACING_Y);
14104
+ });
14060
14105
  const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
14106
+ Object.values(nodeObjects).forEach((mesh) => {
14107
+ const oldLabel = mesh.getObjectByName("questDateLabel") || mesh.getObjectByName("timelineLabel");
14108
+ if (oldLabel) {
14109
+ mesh.remove(oldLabel);
14110
+ if (oldLabel.material) oldLabel.material.dispose();
14111
+ }
14112
+ if (mesh.userData.timelineIntervalBar) {
14113
+ if (graphGroup) graphGroup.remove(mesh.userData.timelineIntervalBar);
14114
+ mesh.userData.timelineIntervalBar = null;
14115
+ }
14116
+ if (mesh.userData.timelineEndLabel) {
14117
+ if (graphGroup) graphGroup.remove(mesh.userData.timelineEndLabel);
14118
+ mesh.userData.timelineEndLabel = null;
14119
+ }
14120
+ });
14061
14121
  Object.keys(nodeObjects).forEach((id) => {
14062
14122
  const mesh = nodeObjects[id];
14063
14123
  const isFilteredQuest = filteredQuests.some(
@@ -14099,20 +14159,53 @@ function XViewScene({
14099
14159
  targetY = timeToYMap.get(timeInfo.startDate.getTime());
14100
14160
  } else {
14101
14161
  const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
14102
- targetY = -80 - rowIndex * (QUEST_LENS_ROW_SPACING || 30) - undatedOffset;
14162
+ targetY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
14103
14163
  }
14104
14164
  const lensTween = new Tween2(mesh.position).to({ x: colX, y: targetY, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
14105
14165
  tweenGroup.add(lensTween);
14106
14166
  lensTween.start();
14107
- if (!timeInfo.isUndated && timeInfo.label) {
14167
+ if (!timeInfo.isUndated && timeInfo.label && !mesh.getObjectByName("questDateLabel")) {
14108
14168
  const dateSprite = createTextSprite(timeInfo.label, 36);
14109
14169
  dateSprite.name = "questDateLabel";
14110
14170
  dateSprite.position.set(0, -5.5, 0);
14111
14171
  mesh.add(dateSprite);
14112
14172
  }
14173
+ if (timeInfo.type === "interval" && timeToYMap.has(timeInfo.endDate.getTime())) {
14174
+ const endY = timeToYMap.get(timeInfo.endDate.getTime());
14175
+ if (Math.abs(endY - targetY) > 0.1) {
14176
+ const barHeight = Math.abs(endY - targetY);
14177
+ const barGeometry = new THREE3.CylinderGeometry(
14178
+ TIMELINE_INTERVAL_BAR_RADIUS,
14179
+ TIMELINE_INTERVAL_BAR_RADIUS,
14180
+ 1,
14181
+ 16
14182
+ );
14183
+ const barMaterial = new THREE3.MeshStandardMaterial({
14184
+ color: TIMELINE_GOLD_COLOR,
14185
+ emissive: 12092939,
14186
+ emissiveIntensity: 0.4,
14187
+ transparent: true,
14188
+ opacity: TIMELINE_INTERVAL_BAR_OPACITY,
14189
+ roughness: 0.3,
14190
+ metalness: 0.8
14191
+ });
14192
+ const intervalBar = new THREE3.Mesh(barGeometry, barMaterial);
14193
+ 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);
14196
+ intervalBar.scale.y = barHeight;
14197
+ graphGroup.add(intervalBar);
14198
+ mesh.userData.timelineIntervalBar = intervalBar;
14199
+ const endLabel = createTextSprite(timeInfo.label.split(" - ")[1] || "", 30);
14200
+ endLabel.name = "timelineEndLabel";
14201
+ endLabel.position.set(colX, endY + 4, 0);
14202
+ graphGroup.add(endLabel);
14203
+ mesh.userData.timelineEndLabel = endLabel;
14204
+ }
14205
+ }
14113
14206
  if (mesh.userData.labelObject) {
14114
14207
  const labelTargetPos = new THREE3.Vector3(colX, targetY, 0).add(
14115
- mesh.userData.labelOffset || new THREE3.Vector3(0, -2.5, 0)
14208
+ mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
14116
14209
  );
14117
14210
  const labelTween = new Tween2(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(Easing2.Cubic.InOut);
14118
14211
  tweenGroup.add(labelTween);
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.42",
3
+ "version": "1.2.5-dev.44",
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",