@mindexec/cli 0.2.435 → 0.2.436

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindexec/cli",
3
- "version": "0.2.435",
3
+ "version": "0.2.436",
4
4
  "description": "MindExec local runtime and bridge CLI",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -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
 
@@ -579,7 +579,7 @@
579
579
  }
580
580
 
581
581
  const base = '_content/MindExecution.Shared/js/';
582
- const scriptVersion = '20260712-pan-smoothing-v926';
582
+ const scriptVersion = '20260712-pan-doubleclick-v928';
583
583
  const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
584
584
  console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
585
585
  const criticalScripts = [
@@ -1,5 +1,5 @@
1
1
  self.assetsManifest = {
2
- "version": "6c1WQjRz",
2
+ "version": "awQM6oT9",
3
3
  "assets": [
4
4
  {
5
5
  "hash": "sha256-+CSYMcqLNTsq3VnH11jgYyOCCdxvHzL74CBmo4sCmMU=",
@@ -106,7 +106,7 @@
106
106
  "url": "_content/MindExecution.Shared/js/mind-map-glow-shader.js"
107
107
  },
108
108
  {
109
- "hash": "sha256-BRHeAFheJ2u1jOUCpURNhA1j0q4VEW8QHSMPleasr28=",
109
+ "hash": "sha256-nl8vYaz/QSNryxyzuaeEyQewlPRL25ERqb/vuZSxWrY=",
110
110
  "url": "_content/MindExecution.Shared/js/mind-map-interactions.js"
111
111
  },
112
112
  {
@@ -826,7 +826,7 @@
826
826
  "url": "icon-512.png"
827
827
  },
828
828
  {
829
- "hash": "sha256-DHFD2bw+0sIZ77FHp9yqyo5GQ1MJwl+JGgmP0XXZIv0=",
829
+ "hash": "sha256-VrQGjuztaCMaHrSZpe+32iwhc6BNIeClZw5/8sHYp28=",
830
830
  "url": "index.html"
831
831
  },
832
832
  {
@@ -1,4 +1,4 @@
1
- /* Manifest version: 6c1WQjRz */
1
+ /* Manifest version: awQM6oT9 */
2
2
  // Hosted deployments should prefer the network over stale offline caches.
3
3
  // This service worker immediately clears old Blazor offline caches and unregisters itself.
4
4