@mindexec/cli 0.2.26 → 0.2.28

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.26",
3
+ "version": "0.2.28",
4
4
  "description": "MindExec local runtime and bridge CLI",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -5,7 +5,7 @@
5
5
  const DEBUG = false;
6
6
  const FPS_DEBUG = false;
7
7
  const FRAME_PERF_DEBUG = false;
8
- const MINDMAP_CORE_BUILD_ID = '20260610-template-board-ready-v205';
8
+ const MINDMAP_CORE_BUILD_ID = '20260613-dom-cursor-v207';
9
9
  const CanvasPhase = Object.freeze({
10
10
  Booting: 'booting',
11
11
  BoardFileLoading: 'board-file-loading',
@@ -83,6 +83,7 @@
83
83
  const PASSIVE_OVERLAY_INTERACTIVE_DENSE_VISIBLE_THRESHOLD = 40;
84
84
  const PASSIVE_OVERLAY_IDLE_DELAY_MS = 500;
85
85
  const PASSIVE_OVERLAY_PAN_IDLE_DELAY_MS = 500;
86
+ const CURSOR_DOM_BLINK_DURATION_MS = 1000;
86
87
  const HOME_CAMERA_NORMAL_MID_Z = 8250;
87
88
  const HOME_DENSE_CLUSTER_MIN_CELL_SIZE = 1200;
88
89
  const HOME_DENSE_CLUSTER_MAX_CELL_SIZE = 3600;
@@ -234,6 +235,111 @@
234
235
  });
235
236
  }
236
237
 
238
+ let cursorDomStyleInstalled = false;
239
+
240
+ function ensureCursorDomStyle() {
241
+ if (cursorDomStyleInstalled || typeof document === 'undefined') {
242
+ return;
243
+ }
244
+
245
+ if (document.getElementById('mind-map-cursor-dom-style')) {
246
+ cursorDomStyleInstalled = true;
247
+ return;
248
+ }
249
+
250
+ const style = document.createElement('style');
251
+ style.id = 'mind-map-cursor-dom-style';
252
+ style.textContent = `
253
+ @keyframes mindMapCursorDomBlink {
254
+ 0%, 49% { opacity: 1; }
255
+ 50%, 100% { opacity: 0; }
256
+ }
257
+ .mind-map-cursor-dom {
258
+ position: absolute;
259
+ left: 0;
260
+ top: 0;
261
+ width: 20px;
262
+ height: 20px;
263
+ box-sizing: border-box;
264
+ border-top: 4px solid #000;
265
+ border-left: 4px solid #000;
266
+ pointer-events: none;
267
+ z-index: 2147483000;
268
+ animation: mindMapCursorDomBlink ${CURSOR_DOM_BLINK_DURATION_MS}ms steps(1, end) infinite;
269
+ will-change: transform;
270
+ contain: layout style paint;
271
+ }
272
+ `;
273
+ document.head?.appendChild(style);
274
+ cursorDomStyleInstalled = true;
275
+ }
276
+
277
+ function ensureCursorDomElement(module) {
278
+ if (!module?.container || typeof document === 'undefined') {
279
+ return null;
280
+ }
281
+
282
+ ensureCursorDomStyle();
283
+
284
+ if (module.cursorDomElement?.isConnected) {
285
+ return module.cursorDomElement;
286
+ }
287
+
288
+ const element = document.createElement('div');
289
+ element.className = 'mind-map-cursor-dom';
290
+ element.setAttribute('aria-hidden', 'true');
291
+ module.container.appendChild(element);
292
+ module.cursorDomElement = element;
293
+ module._lastCursorDomPositionKey = '';
294
+ return element;
295
+ }
296
+
297
+ function updateCursorDomElement(module) {
298
+ if (!module?.container || !module.camera || !module.cursorPosition) {
299
+ return false;
300
+ }
301
+
302
+ const element = ensureCursorDomElement(module);
303
+ if (!element) {
304
+ return false;
305
+ }
306
+
307
+ const width = Math.max(1, Number(module.container.clientWidth || 0));
308
+ const height = Math.max(1, Number(module.container.clientHeight || 0));
309
+ const camera = module.camera;
310
+ const cursor = module.cursorPosition;
311
+ const vfov = (camera.fov * Math.PI) / 180;
312
+ const viewHeight = 2 * Math.tan(vfov / 2) * camera.position.z;
313
+ const viewWidth = viewHeight * camera.aspect;
314
+ const ndcX = ((cursor.x - camera.position.x) * 2) / viewWidth;
315
+ const ndcY = ((cursor.y - camera.position.y) * 2) / viewHeight;
316
+ const x = ((ndcX + 1) / 2) * width;
317
+ const y = ((1 - ndcY) / 2) * height;
318
+ const visible = ndcX >= -1.1 && ndcX <= 1.1 && ndcY >= -1.1 && ndcY <= 1.1;
319
+ const positionKey = `${visible ? 1 : 0}|${Math.round(x)}|${Math.round(y)}|${width}|${height}`;
320
+
321
+ if (positionKey === module._lastCursorDomPositionKey) {
322
+ return false;
323
+ }
324
+
325
+ module._lastCursorDomPositionKey = positionKey;
326
+ element.style.display = visible ? 'block' : 'none';
327
+ if (visible) {
328
+ element.style.transform = `translate3d(${x.toFixed(2)}px, ${y.toFixed(2)}px, 0)`;
329
+ }
330
+ return true;
331
+ }
332
+
333
+ function removeCursorDomElement(module) {
334
+ if (module?.cursorDomElement) {
335
+ module.cursorDomElement.remove();
336
+ module.cursorDomElement = null;
337
+ }
338
+ if (module) {
339
+ module._lastCursorDomPositionKey = '';
340
+ }
341
+ }
342
+
237
343
  function shouldYieldWorkSlice(sliceStartedAt, processedCount, budgetMs, minItems, maxItems) {
238
344
  if (processedCount < minItems) {
239
345
  return false;
@@ -2497,6 +2603,8 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
2497
2603
  this.cursorMesh = null;
2498
2604
  this.cursorMaterial = null;
2499
2605
  this.cursorLineMaterial = null;
2606
+ this.cursorDomElement = null;
2607
+ this._lastCursorDomPositionKey = '';
2500
2608
  this._viewStatePersistTimer = null;
2501
2609
  this._pendingViewStateSnapshot = null;
2502
2610
  this._pendingViewStateKey = null;
@@ -3003,6 +3111,8 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
3003
3111
  this.container = target;
3004
3112
  this.dotNetHelper = helper;
3005
3113
  window.dotNetHelper = helper; // Expose globally for NativeDropHandler access
3114
+ ensureCursorDomElement(this);
3115
+ updateCursorDomElement(this);
3006
3116
  if (this.useTextOverlayV2 && window.MindMapTextOverlayV2?.init) {
3007
3117
  window.MindMapTextOverlayV2.init(this);
3008
3118
  }
@@ -3078,19 +3188,19 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
3078
3188
  const thickness = 4; // Cursor thickness
3079
3189
 
3080
3190
  // Mesh material (background / thickness)
3081
- this.cursorMaterial = new THREE.MeshBasicMaterial({
3082
- color: 0xffffff,
3083
- transparent: true,
3084
- opacity: 1.0,
3085
- depthTest: false
3086
- });
3087
-
3088
- // Line material (centerline)
3089
- this.cursorLineMaterial = new THREE.LineBasicMaterial({
3090
- color: 0xffffff,
3091
- transparent: false,
3092
- opacity: 1,
3093
- depthTest: false
3191
+ this.cursorMaterial = new THREE.MeshBasicMaterial({
3192
+ color: 0x000000,
3193
+ transparent: true,
3194
+ opacity: 1.0,
3195
+ depthTest: false
3196
+ });
3197
+
3198
+ // Line material (centerline)
3199
+ this.cursorLineMaterial = new THREE.LineBasicMaterial({
3200
+ color: 0x000000,
3201
+ transparent: false,
3202
+ opacity: 1,
3203
+ depthTest: false
3094
3204
  });
3095
3205
 
3096
3206
  // Mesh geometry (vertical/horizontal bars)
@@ -3117,9 +3227,10 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
3117
3227
  line.position.z = 0; // [Fix] Z=0 for parallax elimination
3118
3228
  line.renderOrder = 9999;
3119
3229
  this.cursorMesh.add(line);
3120
-
3121
- this.cursorMesh.position.set(0, 0, 0); // [Fix] Z=0 for parallax elimination
3122
- this.cursorMesh.renderOrder = 9999;
3230
+
3231
+ this.cursorMesh.position.set(0, 0, 0); // [Fix] Z=0 for parallax elimination
3232
+ this.cursorMesh.renderOrder = 9999;
3233
+ this.cursorMesh.visible = false;
3123
3234
  this.scene.add(this.cursorMesh);
3124
3235
 
3125
3236
  if (this.updateCursorPosition) {
@@ -3226,7 +3337,10 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
3226
3337
  }
3227
3338
 
3228
3339
  // 4. [중요] 강제 리사이즈 호출 (초기화 시점의 0x0 사이즈 보정)
3229
- setTimeout(() => {
3340
+ ensureCursorDomElement(this);
3341
+ updateCursorDomElement(this);
3342
+
3343
+ setTimeout(() => {
3230
3344
  if (this && this.onWindowResize) {
3231
3345
  console.log("[Init] Forcing resize to fix 0 height issue");
3232
3346
  this.onWindowResize();
@@ -5059,25 +5173,9 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
5059
5173
  allowAnimation: shouldAnimateImageStatusTextures
5060
5174
  });
5061
5175
 
5062
- // 5. Cursor Animation
5176
+ // 5. Cursor DOM position
5063
5177
  // ----------------------------------------------------------------
5064
- let cursorAnimatedThisFrame = false;
5065
- const shouldAnimateCursor =
5066
- !!this.cursorMaterial &&
5067
- (
5068
- (isContinuousTheme === true && allowContinuousThemeAnimationThisFrame === true) ||
5069
- isInteractiveFrame === true ||
5070
- shouldUpdate === true ||
5071
- hasForcedUpdate === true ||
5072
- isBoardLoading === true
5073
- );
5074
- if (shouldAnimateCursor) {
5075
- const time = Date.now() * 0.005;
5076
- const val = (Math.sin(time) * 0.5) + 0.5;
5077
- this.cursorMaterial.color.setRGB(val, val, val);
5078
- if (this.cursorLineMaterial) this.cursorLineMaterial.color.setRGB(val, val, val);
5079
- cursorAnimatedThisFrame = true;
5080
- }
5178
+ updateCursorDomElement(this);
5081
5179
 
5082
5180
  // 6. Theme Animation
5083
5181
  // ----------------------------------------------------------------
@@ -5126,21 +5224,13 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
5126
5224
  // 7. Render
5127
5225
  // ----------------------------------------------------------------
5128
5226
  _profileSection('css3dSync');
5129
- const hasContinuousThemeAnimationFrame =
5130
- allowContinuousThemeAnimationThisFrame === true &&
5131
- (
5132
- shouldForceGpuParticleAnimation === true ||
5133
- (isThemeAnimationEnabled === true && isContinuousTheme === true)
5134
- );
5135
5227
  const shouldRenderWebglFrame =
5136
5228
  isWebglRenderEnabled &&
5137
5229
  (
5138
5230
  isBoardLoading === true ||
5139
5231
  shouldUpdate === true ||
5140
5232
  isInteractiveFrame === true ||
5141
- themeAnimatedThisFrame === true ||
5142
- cursorAnimatedThisFrame === true ||
5143
- hasContinuousThemeAnimationFrame === true
5233
+ themeAnimatedThisFrame === true
5144
5234
  );
5145
5235
  if (shouldRenderWebglFrame) {
5146
5236
  this.renderer.render(this.scene, this.camera);
@@ -5469,7 +5559,6 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
5469
5559
  isInteractiveFrame !== true &&
5470
5560
  shouldUpdate !== true &&
5471
5561
  themeAnimatedThisFrame !== true &&
5472
- cursorAnimatedThisFrame !== true &&
5473
5562
  shouldRenderWebglFrame !== true &&
5474
5563
  shouldRenderCss3dFrame !== true &&
5475
5564
  shouldSyncTextOverlays !== true &&
@@ -5619,8 +5708,9 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
5619
5708
 
5620
5709
  this.cursorPosition.set(snappedX, snappedY, 0);
5621
5710
  if (this.cursorMesh) {
5622
- this.cursorMesh.position.set(snappedX, snappedY, 0); // [Fix] Z=0 for parallax elimination
5623
- }
5711
+ this.cursorMesh.position.set(snappedX, snappedY, 0); // [Fix] Z=0 for parallax elimination
5712
+ }
5713
+ updateCursorDomElement(this);
5624
5714
 
5625
5715
  if (moveCamera) {
5626
5716
  let targetCenterX = snappedX;
@@ -5749,6 +5839,7 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
5749
5839
  cleanupAndDispose() {
5750
5840
  if (!this.container) return;
5751
5841
  this.pauseAnimationLoop();
5842
+ removeCursorDomElement(this);
5752
5843
  if (this._viewStatePersistTimer) {
5753
5844
  clearTimeout(this._viewStatePersistTimer);
5754
5845
  this._viewStatePersistTimer = null;
@@ -6182,6 +6182,10 @@
6182
6182
 
6183
6183
  function getMemoIconKey(nodeModel) {
6184
6184
  const semanticType = getNodeSemanticType(nodeModel);
6185
+ if (semanticType === REMOTE_FLEET_SEMANTIC_TYPE) {
6186
+ return 'network-wired';
6187
+ }
6188
+
6185
6189
  if (semanticType === 'MindCanvasAgent' || semanticType === 'AgentCommand') {
6186
6190
  return 'robot';
6187
6191
  }
@@ -558,7 +558,7 @@
558
558
  }
559
559
 
560
560
  const base = '_content/MindExecution.Shared/js/';
561
- const scriptVersion = '20260613-remote-screen-monitor-v492';
561
+ const scriptVersion = '20260613-dom-cursor-v494';
562
562
  const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
563
563
  console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
564
564
  const criticalScripts = [
@@ -1,5 +1,5 @@
1
1
  self.assetsManifest = {
2
- "version": "pdZBY4HV",
2
+ "version": "m4oKu8Nx",
3
3
  "assets": [
4
4
  {
5
5
  "hash": "sha256-+CSYMcqLNTsq3VnH11jgYyOCCdxvHzL74CBmo4sCmMU=",
@@ -78,7 +78,7 @@
78
78
  "url": "_content/MindExecution.Shared/js/marked.min.js"
79
79
  },
80
80
  {
81
- "hash": "sha256-OmYQpvRRLwtglr/vxtxNehzAsxu7ff8XxkT2YNxwLWs=",
81
+ "hash": "sha256-UeeqiZXN9Iv1e/DRq1gyWRCbQUwzduNrpf5aSQido00=",
82
82
  "url": "_content/MindExecution.Shared/js/mind-map-core.js"
83
83
  },
84
84
  {
@@ -86,7 +86,7 @@
86
86
  "url": "_content/MindExecution.Shared/js/mind-map-core.js.backup"
87
87
  },
88
88
  {
89
- "hash": "sha256-evnO3l4V8QouakV955IY87wMR6kYuXQU5LEAjOjONO0=",
89
+ "hash": "sha256-wZrUQUYTsiH7hkHaZPeEBdqG+r+e2UDR9vqZmyARSFg=",
90
90
  "url": "_content/MindExecution.Shared/js/mind-map-css3d-manager.js"
91
91
  },
92
92
  {
@@ -834,7 +834,7 @@
834
834
  "url": "image-manifest.json"
835
835
  },
836
836
  {
837
- "hash": "sha256-BUjUsG/CTn5wyAwuO52yc0McqhRH8QVA7dDCN+LuIBE=",
837
+ "hash": "sha256-6CFY94JBwL0ucGyOLKGUhtHcboWlYd/I3J3bnSVjxjM=",
838
838
  "url": "index.html"
839
839
  },
840
840
  {
@@ -1,4 +1,4 @@
1
- /* Manifest version: pdZBY4HV */
1
+ /* Manifest version: m4oKu8Nx */
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