@mindexec/cli 0.2.435 → 0.2.437

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 (19) hide show
  1. package/package.json +1 -1
  2. package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +28 -16
  3. package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +2 -2
  4. package/wwwroot/_content/MindExecution.Shared/js/mind-map-interactions.js +57 -66
  5. package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-renderer.js +153 -233
  6. package/wwwroot/_content/MindExecution.Shared/js/mind-map-logic-workers.js +26 -5
  7. package/wwwroot/_content/MindExecution.Shared/js/mind-map-normal-boundary-optimizer.js +624 -0
  8. package/wwwroot/_content/MindExecution.Shared/js/mind-map-render-plan.js +40 -23
  9. package/wwwroot/_content/MindExecution.Shared/js/mind-map-visibility-worker.js +10 -5
  10. package/wwwroot/_content/MindExecution.Shared/js/renderers/CSS3DRenderer.js +10 -1
  11. package/wwwroot/_framework/{MindExecution.Plugins.Concept.7uhld08zkc.dll → MindExecution.Plugins.Concept.vbnlpkxcoo.dll} +0 -0
  12. package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.y1sj1ifw0z.dll → MindExecution.Plugins.PlanMaster.k3xu6iqktj.dll} +0 -0
  13. package/wwwroot/_framework/{MindExecution.Plugins.YouTube.ij0uk05x1o.dll → MindExecution.Plugins.YouTube.dqlboez3y6.dll} +0 -0
  14. package/wwwroot/_framework/{MindExecution.Shared.1h72etbxec.dll → MindExecution.Shared.6xss0iwsn1.dll} +0 -0
  15. package/wwwroot/_framework/{MindExecution.Web.18xe2efznc.dll → MindExecution.Web.22pax8j6l6.dll} +0 -0
  16. package/wwwroot/_framework/blazor.boot.json +11 -11
  17. package/wwwroot/index.html +3 -2
  18. package/wwwroot/service-worker-assets.js +25 -21
  19. package/wwwroot/service-worker.js +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindexec/cli",
3
- "version": "0.2.435",
3
+ "version": "0.2.437",
4
4
  "description": "MindExec local runtime and bridge CLI",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -3148,6 +3148,8 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
3148
3148
  this._workerVisibilitySeq = 0;
3149
3149
  this._lastVisibilityEnteredIds = [];
3150
3150
  this._lastVisibilityExitedIds = [];
3151
+ this._lastVisibilityDiffVersion = -1;
3152
+ this._lastVisibilityDiffComplete = false;
3151
3153
  this._workerHitTestRangeKey = '';
3152
3154
  this._workerHitTestBoardId = '';
3153
3155
  this._workerHitTestCandidateIds = [];
@@ -5265,15 +5267,19 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
5265
5267
  this._lastVisibilityCullingProfile = result.profile || null;
5266
5268
  this._lastVisibilityViewportWorldRect = result.viewportRect || null;
5267
5269
  this._lastVisibilityNodeCount = Number(result.lastVisibilityNodeCount || this.nodeObjectsById?.size || 0);
5268
- this._lastVisibilityEnteredIds = enteredIds.slice(0, 128);
5269
- this._lastVisibilityExitedIds = exitedIds.slice(0, 128);
5270
- this._workerVisibilityPriorityIds = Array.isArray(result.priorityIds)
5271
- ? result.priorityIds.map((nodeId) => String(nodeId || '').trim()).filter(Boolean)
5272
- : [];
5270
+ if (Array.isArray(result.priorityIds)) {
5271
+ this._workerVisibilityPriorityIds = result.priorityIds
5272
+ .map((nodeId) => String(nodeId || '').trim())
5273
+ .filter(Boolean);
5274
+ }
5273
5275
  this._workerVisibilitySeq = Number(result.seq || 0);
5274
5276
 
5275
5277
  if (visibilityChanged) {
5276
5278
  this._visibilityVersion = (this._visibilityVersion || 0) + 1;
5279
+ this._lastVisibilityEnteredIds = enteredIds;
5280
+ this._lastVisibilityExitedIds = exitedIds;
5281
+ this._lastVisibilityDiffVersion = this._visibilityVersion;
5282
+ this._lastVisibilityDiffComplete = true;
5277
5283
  this._applyVisibilityOverlayInvalidation(prevVisibleSize, nextVisible.size);
5278
5284
  }
5279
5285
 
@@ -5742,20 +5748,22 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
5742
5748
  });
5743
5749
  }
5744
5750
 
5745
- let visibilityChanged = prevVisible.size !== nextVisible.size;
5746
- if (!visibilityChanged) {
5747
- for (const nodeId of nextVisible) {
5748
- if (!prevVisible.has(nodeId)) {
5749
- visibilityChanged = true;
5750
- break;
5751
- }
5752
- }
5753
- }
5751
+ const enteredIds = [];
5752
+ const exitedIds = [];
5753
+ nextVisible.forEach((nodeId) => {
5754
+ if (!prevVisible.has(nodeId)) enteredIds.push(nodeId);
5755
+ });
5756
+ prevVisible.forEach((nodeId) => {
5757
+ if (!nextVisible.has(nodeId)) exitedIds.push(nodeId);
5758
+ });
5759
+ const visibilityChanged = enteredIds.length > 0 || exitedIds.length > 0;
5754
5760
 
5755
5761
  if (visibilityChanged) {
5756
5762
  this._visibilityVersion = (this._visibilityVersion || 0) + 1;
5757
- this._lastVisibilityEnteredIds = [];
5758
- this._lastVisibilityExitedIds = [];
5763
+ this._lastVisibilityEnteredIds = enteredIds;
5764
+ this._lastVisibilityExitedIds = exitedIds;
5765
+ this._lastVisibilityDiffVersion = this._visibilityVersion;
5766
+ this._lastVisibilityDiffComplete = true;
5759
5767
  this._applyVisibilityOverlayInvalidation(prevVisible.size, nextVisible.size);
5760
5768
  }
5761
5769
 
@@ -7814,6 +7822,8 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
7814
7822
  this._workerVisibilitySeq = 0;
7815
7823
  this._lastVisibilityEnteredIds = [];
7816
7824
  this._lastVisibilityExitedIds = [];
7825
+ this._lastVisibilityDiffVersion = -1;
7826
+ this._lastVisibilityDiffComplete = false;
7817
7827
  this.logicWorkerBridge?.dispose?.();
7818
7828
  this.logicWorkerBridge = null;
7819
7829
 
@@ -9644,6 +9654,8 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
9644
9654
  moduleInstance._workerVisibilitySeq = 0;
9645
9655
  moduleInstance._lastVisibilityEnteredIds = [];
9646
9656
  moduleInstance._lastVisibilityExitedIds = [];
9657
+ moduleInstance._lastVisibilityDiffVersion = -1;
9658
+ moduleInstance._lastVisibilityDiffComplete = false;
9647
9659
  if (moduleInstance.lodRenderer && typeof moduleInstance.lodRenderer.resetState === 'function') {
9648
9660
  moduleInstance.lodRenderer.resetState();
9649
9661
  }
@@ -5231,7 +5231,7 @@
5231
5231
  function setTextOverlaySourceActive(nodeEntry, isActive) {
5232
5232
  if (isCss3dMediaNode(nodeEntry?.model)) {
5233
5233
  restoreCss3dMediaOverlayState(nodeEntry.model, nodeEntry.cssObject);
5234
- nodeEntry._textOverlayActive = false;
5234
+ nodeEntry._textOverlayActive = false; nodeEntry._css3dSourceSuspended = false;
5235
5235
  return;
5236
5236
  }
5237
5237
 
@@ -5248,7 +5248,7 @@
5248
5248
  restoreTextOverlaySourceTarget(target);
5249
5249
  }
5250
5250
  });
5251
- nodeEntry._textOverlayActive = !!isActive;
5251
+ nodeEntry._textOverlayActive = nodeEntry._css3dSourceSuspended = !!isActive;
5252
5252
  }
5253
5253
 
5254
5254
  function getTextOverlayPlacementInfo(module, element) {
@@ -1279,7 +1279,48 @@ window.MindMapInteractions = (function () {
1279
1279
  }
1280
1280
 
1281
1281
 
1282
- // ▼▼▼ [New] Double-click event handler ▼▼▼
1282
+ function resolveDoubleClickNodeId(module, e) {
1283
+ const domNodeId = getGuardedTargetNodeId(module, e?.target, e);
1284
+ if (domNodeId) return domNodeId;
1285
+ if (!module?.raycaster || !module?.camera || !module?.plane || !e) return null;
1286
+ updatePointer(module, e);
1287
+ module.raycaster.setFromCamera(module.pointer, module.camera);
1288
+ const meshes = [];
1289
+ let residentHit = null;
1290
+ if (module.raycaster.ray.intersectPlane(module.plane, module.intersectPoint)) {
1291
+ meshes.push(...getNearbyMeshes(module, module.intersectPoint));
1292
+ if (meshes.length === 0 && module.nodeObjectsById?.size > 0) {
1293
+ module.nodeObjectsById.forEach((entry) => {
1294
+ const glObject = entry?.glObject;
1295
+ if (glObject && (glObject.isMesh || glObject.children?.length > 0)) {
1296
+ meshes.push(glObject);
1297
+ }
1298
+ });
1299
+ }
1300
+ residentHit = module.lodRenderer?.pickResidentNodeAtWorldPoint?.(module.intersectPoint) || null;
1301
+ }
1302
+ const topHit = getTopIntersectionHit(module, module.raycaster.intersectObjects(meshes, true));
1303
+ const topNodeId = resolveNodeIdFromHitObject(topHit?.object);
1304
+ const topPriority = topHit ? getIntersectionInteractionPriority(module, topHit) : -Infinity;
1305
+ const cssHit = findCssNodeHitAtClientPoint(module, e.clientX, e.clientY);
1306
+ if (cssHit?.nodeId && (!topHit || (cssHit.nodeId !== topNodeId && (cssHit.priority ?? -Infinity) >= topPriority))) {
1307
+ return cssHit.nodeId;
1308
+ }
1309
+ return residentHit?.nodeId && (!topHit || getResidentLodHitPriority(module, residentHit) >= topPriority)
1310
+ ? residentHit.nodeId : topNodeId;
1311
+ }
1312
+
1313
+ function activateDoubleClickedNode(module, nodeId, target) {
1314
+ const nodeEntry = module?.nodeObjectsById?.get?.(nodeId) || null;
1315
+ if (!nodeEntry) return false;
1316
+ if (module.selectedNodeIdJs !== nodeId) {
1317
+ finalizeSingleSelection(module, nodeId, { notifyBlazor: true, bringToFront: true, showMenu: true });
1318
+ }
1319
+ const isLink = !!(target && (target.tagName === 'A' || target.closest?.('a')));
1320
+ handleSelectedNodeActivation(module, nodeId, nodeEntry, { isLink, target });
1321
+ return true;
1322
+ }
1323
+
1283
1324
  async function onDoubleClick(module, e) {
1284
1325
  cancelPendingPrimaryClick(module);
1285
1326
  if (module) {
@@ -1294,13 +1335,22 @@ window.MindMapInteractions = (function () {
1294
1335
  return;
1295
1336
  }
1296
1337
 
1338
+ if (e.target?.closest?.('textarea,input,select,[contenteditable="true"]')) {
1339
+ e.stopPropagation();
1340
+ return;
1341
+ }
1342
+
1297
1343
  e.preventDefault();
1298
1344
  e.stopPropagation();
1299
1345
 
1346
+ const nodeId = resolveDoubleClickNodeId(module, e);
1347
+ if (nodeId && activateDoubleClickedNode(module, nodeId, e.target)) {
1348
+ return;
1349
+ }
1350
+
1300
1351
  focusCanvasForClipboard(module);
1301
- moveCursorToEvent(module, e, 'double-click');
1352
+ moveCursorToEvent(module, e, 'grid double-click');
1302
1353
  }
1303
- // ▲▲▲ [New] ▲▲▲
1304
1354
 
1305
1355
  // ▼▼▼ [New] Helper to clean up an in-progress edit node ▼▼▼
1306
1356
  /**
@@ -3478,7 +3528,6 @@ window.MindMapInteractions = (function () {
3478
3528
 
3479
3529
  if (isDoubleClickPointerEvent(pointerEvent)) {
3480
3530
  cancelPendingPrimaryClick(module);
3481
- moveCursorToEvent(module, pointerEvent, 'overlay double-click');
3482
3531
  return { handled: true, suppressDefault: true };
3483
3532
  }
3484
3533
 
@@ -3540,7 +3589,7 @@ window.MindMapInteractions = (function () {
3540
3589
  }
3541
3590
 
3542
3591
  function beginOverlayNodeDrag(module, event, nodeId) {
3543
- if (!module || !event || event.button !== 0 || !nodeId) {
3592
+ if (!module || !event || Number(event.button) !== 0 || isDoubleClickPointerEvent(event) || !nodeId) {
3544
3593
  return false;
3545
3594
  }
3546
3595
 
@@ -3586,7 +3635,7 @@ window.MindMapInteractions = (function () {
3586
3635
 
3587
3636
  function startNodeDragFromDom(module, event, nodeId, options = {}) {
3588
3637
  const normalizedNodeId = String(nodeId || '').trim();
3589
- if (!module || !event || Number(event.button) !== 0 || !normalizedNodeId) {
3638
+ if (!module || !event || Number(event.button) !== 0 || isDoubleClickPointerEvent(event) || !normalizedNodeId) {
3590
3639
  return false;
3591
3640
  }
3592
3641
 
@@ -4646,70 +4695,12 @@ window.MindMapInteractions = (function () {
4646
4695
  // fallback이 너무 공격적으로 작동하여 노드 주변(배경) 클릭 시에도 노드를 선택하는 문제 발생.
4647
4696
  // 모든 노드는 Mesh를 가지고 있으므로 Raycast로 충분함.
4648
4697
  else if (module.intersectPoint && module.nodeObjectsById.size > 0) {
4649
- const clickX = module.intersectPoint.x;
4650
- const clickY = module.intersectPoint.y;
4651
- let foundNodeId = null;
4652
- let foundEntry = null;
4653
- let highestZ = -Infinity;
4654
-
4655
4698
  // 모든 노드를 순회하며 클릭 좌표가 노드 영역 내에 있는지 확인
4656
- module.nodeObjectsById.forEach((entry, nodeId) => {
4657
- if (!entry || !entry.glObject) return;
4658
-
4659
- const pos = entry.glObject.position;
4660
- const width = entry.model?.width || entry.glObject.userData?.worldWidth || 300;
4661
- const height = entry.model?.height || entry.glObject.userData?.worldHeight || 200;
4662
-
4663
4699
  // Three.js 좌표계: Y가 위로 증가, 노드 position은 좌상단
4664
- const left = pos.x;
4665
- const right = pos.x + width;
4666
- const top = pos.y;
4667
- const bottom = pos.y - height;
4668
-
4669
- if (clickX >= left && clickX <= right && clickY <= top && clickY >= bottom) {
4700
+ if (false) {
4670
4701
  // Z-order로 가장 위에 있는 노드 선택
4671
- const zOrder = entry.glObject.renderOrder || 0;
4672
- if (zOrder > highestZ) {
4673
- highestZ = zOrder;
4674
- foundNodeId = nodeId;
4675
- foundEntry = entry;
4676
- }
4677
- }
4678
- });
4679
-
4680
- if (foundNodeId && foundEntry) {
4681
- // If we found a node by coordinates, check if we hit a handle area?
4682
- // But handles are visible objects, so raycast should have caught them.
4683
- // If we are here, it means raycast failed (no mesh hit), but we are effectively clicking "Through" the empty space of a node?
4684
- // Or maybe the mesh was invisible.
4685
-
4686
- // However, for image resizing, the handles ARE visible now (opacity 0.01).
4687
- // So if we are here, it's likely dragging the body.
4688
-
4689
- console.log(`[onMouseDown] Coordinate-based hit: ${foundNodeId}`);
4690
- e.stopPropagation();
4691
- e.preventDefault();
4692
-
4693
- module.isShiftClick = e.shiftKey;
4694
-
4702
+ }
4695
4703
  // 다중 선택 해제 및 단일 선택 처리
4696
- const isAlreadySelected = (module.selectedNodeIdJs === foundNodeId);
4697
- if (!e.shiftKey && !isAlreadySelected && module.multiSelectedNodeIds?.size > 0) {
4698
- if (MindMapNodes.clearMultiSelection) {
4699
- MindMapNodes.clearMultiSelection(module);
4700
- }
4701
- module.multiSelectedNodeIds?.clear?.();
4702
- if (window.MindMapMultiSelect) {
4703
- window.MindMapMultiSelect.hide();
4704
- }
4705
- }
4706
-
4707
- if (!isAlreadySelected && !module.multiSelectedNodeIds?.has(foundNodeId)) {
4708
- setSingleSelection(module, foundNodeId, true);
4709
- }
4710
-
4711
- startNodeDrag(module, e, foundNodeId, foundEntry, foundEntry.glObject);
4712
- return; // Return to prevent falling through
4713
4704
  } else {
4714
4705
  // Background click
4715
4706