@co0ontty/wand 1.21.19 → 1.22.0

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.
@@ -1350,7 +1350,7 @@
1350
1350
  ) +
1351
1351
  '</div>' +
1352
1352
  '<div class="topbar-right">' +
1353
- (selectedSession && selectedSession.cwd ? '<button id="topbar-file-button" class="topbar-btn square' + (state.filePanelOpen ? ' active' : '') + '" type="button" aria-label="文件" title="文件"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg></button>' : '') +
1353
+ '<button id="topbar-file-button" class="topbar-btn square' + (state.filePanelOpen ? ' active' : '') + '" type="button" aria-label="文件" title="查看文件(可修改路径)"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg></button>' +
1354
1354
  '<span id="topbar-git-slot" class="topbar-git-slot">' + renderTopbarGitBadgeHtml() + '</span>' +
1355
1355
  (selectedSession ? renderTopbarMoreMenuHtml(selectedSession) : '') +
1356
1356
  '</div>' +
@@ -1366,7 +1366,7 @@
1366
1366
  '<div class="file-side-panel-body">' +
1367
1367
  '<div class="file-explorer-header">' +
1368
1368
  '<button class="file-explorer-up" id="file-explorer-up" type="button" title="返回上级目录" aria-label="返回上级目录">⬆</button>' +
1369
- '<span class="file-explorer-path" id="file-explorer-cwd" title="' + escapeHtml(selectedSession && selectedSession.cwd ? selectedSession.cwd : getConfigCwd()) + '">' + escapeHtml(selectedSession && selectedSession.cwd ? selectedSession.cwd : getConfigCwd()) + '</span>' +
1369
+ '<input type="text" class="file-explorer-path" id="file-explorer-cwd" value="' + escapeHtml(selectedSession && selectedSession.cwd ? selectedSession.cwd : getConfigCwd()) + '" title="' + escapeHtml(selectedSession && selectedSession.cwd ? selectedSession.cwd : getConfigCwd()) + '" placeholder="输入路径并回车..." spellcheck="false" autocomplete="off" autocapitalize="off" autocorrect="off" aria-label="当前路径,可直接修改后回车" />' +
1370
1370
  '<button class="file-explorer-toggle-hidden' + (state.fileExplorerShowHidden ? ' active' : '') + '" id="file-explorer-toggle-hidden" type="button" title="' + (state.fileExplorerShowHidden ? "隐藏点开头文件" : "显示隐藏文件") + '" aria-pressed="' + (state.fileExplorerShowHidden ? "true" : "false") + '">' + (state.fileExplorerShowHidden ? "👁" : "👁‍🗨") + '</button>' +
1371
1371
  '<button class="file-explorer-refresh" id="file-explorer-refresh" title="刷新" aria-label="刷新文件列表">↻</button>' +
1372
1372
  '</div>' +
@@ -2877,7 +2877,15 @@
2877
2877
  var cwdEl = document.getElementById("file-explorer-cwd");
2878
2878
  if (!cwdEl) return;
2879
2879
  var cwd = session && session.cwd ? session.cwd : getConfigCwd();
2880
- cwdEl.textContent = cwd;
2880
+ // Don't clobber the user's in-progress edit when the input is focused.
2881
+ if (cwdEl.tagName === "INPUT") {
2882
+ if (document.activeElement !== cwdEl) {
2883
+ cwdEl.value = cwd;
2884
+ }
2885
+ } else {
2886
+ cwdEl.textContent = cwd;
2887
+ }
2888
+ cwdEl.title = cwd;
2881
2889
  }
2882
2890
 
2883
2891
  function closeFilePanel() {
@@ -3029,7 +3037,14 @@
3029
3037
  state.fileExplorerTotal = 0;
3030
3038
  explorer.innerHTML = '<div class="file-explorer"><div class="tree-loading" style="padding:12px;color:var(--text-muted);font-size:0.8125rem;">加载中…</div></div>';
3031
3039
  if (cwdEl) {
3032
- cwdEl.textContent = cwd;
3040
+ if (cwdEl.tagName === "INPUT") {
3041
+ // Avoid clobbering in-progress text while the user is typing.
3042
+ if (document.activeElement !== cwdEl) {
3043
+ cwdEl.value = cwd;
3044
+ }
3045
+ } else {
3046
+ cwdEl.textContent = cwd;
3047
+ }
3033
3048
  cwdEl.title = cwd;
3034
3049
  }
3035
3050
  var url = "/api/directory?q=" + encodeURIComponent(cwd) +
@@ -5084,6 +5099,56 @@
5084
5099
  var fileToggleHidden = document.getElementById("file-explorer-toggle-hidden");
5085
5100
  if (fileToggleHidden) fileToggleHidden.addEventListener("click", toggleExplorerHidden);
5086
5101
 
5102
+ // 路径输入框:支持点击修改路径,回车跳转,Esc 撤销。
5103
+ var fileCwdInput = document.getElementById("file-explorer-cwd");
5104
+ if (fileCwdInput && fileCwdInput.tagName === "INPUT") {
5105
+ var lastCommittedCwd = fileCwdInput.value;
5106
+ var normalizeCwdInput = function(raw) {
5107
+ var s = (raw || "").trim();
5108
+ if (!s) return "";
5109
+ // 折叠重复斜杠,去掉尾随斜杠(根目录除外)。
5110
+ s = s.replace(/\/{2,}/g, "/");
5111
+ if (s.length > 1) s = s.replace(/\/+$/, "");
5112
+ return s;
5113
+ };
5114
+ fileCwdInput.addEventListener("focus", function() {
5115
+ lastCommittedCwd = fileCwdInput.value;
5116
+ // Select all on focus so the user can immediately overwrite.
5117
+ setTimeout(function() {
5118
+ try { fileCwdInput.select(); } catch (e) {}
5119
+ }, 0);
5120
+ });
5121
+ fileCwdInput.addEventListener("keydown", function(e) {
5122
+ if (e.key === "Enter") {
5123
+ e.preventDefault();
5124
+ var next = normalizeCwdInput(fileCwdInput.value);
5125
+ if (!next) return;
5126
+ lastCommittedCwd = next;
5127
+ fileCwdInput.value = next;
5128
+ refreshFileExplorer({ cwd: next });
5129
+ fileCwdInput.blur();
5130
+ } else if (e.key === "Escape") {
5131
+ e.preventDefault();
5132
+ fileCwdInput.value = lastCommittedCwd;
5133
+ fileCwdInput.blur();
5134
+ }
5135
+ });
5136
+ fileCwdInput.addEventListener("blur", function() {
5137
+ var next = normalizeCwdInput(fileCwdInput.value);
5138
+ if (!next) {
5139
+ fileCwdInput.value = lastCommittedCwd;
5140
+ return;
5141
+ }
5142
+ if (next === lastCommittedCwd) {
5143
+ fileCwdInput.value = next;
5144
+ return;
5145
+ }
5146
+ lastCommittedCwd = next;
5147
+ fileCwdInput.value = next;
5148
+ refreshFileExplorer({ cwd: next });
5149
+ });
5150
+ }
5151
+
5087
5152
  // File search
5088
5153
  var fileSearchInput = document.getElementById("file-search-input");
5089
5154
  var fileSearchClear = document.getElementById("file-search-clear");
@@ -685,6 +685,40 @@
685
685
  font-weight: 500;
686
686
  }
687
687
 
688
+ /* When rendered as <input> (editable path) keep the same look but reveal
689
+ an editable affordance on hover/focus. */
690
+ input.file-explorer-path {
691
+ background: transparent;
692
+ border: 1px solid transparent;
693
+ border-radius: var(--radius-sm);
694
+ padding: 4px 8px;
695
+ height: 28px;
696
+ line-height: 1.2;
697
+ cursor: text;
698
+ transition: background-color var(--transition-fast),
699
+ border-color var(--transition-fast),
700
+ color var(--transition-fast);
701
+ outline: none;
702
+ text-overflow: ellipsis;
703
+ width: 100%;
704
+ box-sizing: border-box;
705
+ }
706
+ input.file-explorer-path::placeholder {
707
+ color: var(--text-muted);
708
+ opacity: 0.6;
709
+ }
710
+ input.file-explorer-path:hover {
711
+ background: rgba(255, 255, 255, 0.5);
712
+ border-color: var(--border);
713
+ color: var(--text-secondary);
714
+ }
715
+ input.file-explorer-path:focus {
716
+ background: var(--bg-primary);
717
+ border-color: var(--accent);
718
+ color: var(--text-primary);
719
+ text-overflow: clip;
720
+ }
721
+
688
722
  .file-explorer-actions { display: flex; gap: 4px; margin-left: auto; flex-shrink: 0; }
689
723
 
690
724
  .file-explorer-refresh {
@@ -10473,7 +10507,10 @@
10473
10507
  }
10474
10508
 
10475
10509
  .file-preview-modal {
10476
- width: min(90vw, calc(100vw - 380px));
10510
+ /* 桌面端:留出侧边栏空间,但保证最小宽度,避免在窄视口上塌成一条缝。
10511
+ 之前是 min(90vw, calc(100vw - 380px)),当 100vw < 380px 时整个值为负,
10512
+ 元素直接被收成 0 宽。这里用 max() 兜底一个最小宽度。 */
10513
+ width: min(90vw, max(640px, calc(100vw - 380px)));
10477
10514
  max-width: 1000px;
10478
10515
  height: 80vh;
10479
10516
  max-height: 85vh;
@@ -10492,6 +10529,65 @@
10492
10529
  to { opacity: 1; transform: translateY(0) scale(1); }
10493
10530
  }
10494
10531
 
10532
+ /* 移动端(含竖屏手机):铺满整个视口,去掉圆角和边框,
10533
+ 使用 dvh 兼容浏览器地址栏占用。 */
10534
+ @media (max-width: 768px) {
10535
+ .file-preview-overlay {
10536
+ padding: 0;
10537
+ align-items: stretch;
10538
+ justify-content: stretch;
10539
+ }
10540
+ .file-preview-modal {
10541
+ width: 100vw;
10542
+ max-width: 100vw;
10543
+ height: 100vh;
10544
+ height: 100dvh;
10545
+ max-height: 100vh;
10546
+ max-height: 100dvh;
10547
+ border-radius: 0;
10548
+ border: none;
10549
+ box-shadow: none;
10550
+ animation: fade-in 0.18s ease;
10551
+ }
10552
+ .file-preview-header {
10553
+ padding: 10px 12px;
10554
+ gap: 8px;
10555
+ /* 给安全区让位,例如带刘海的设备 */
10556
+ padding-top: max(10px, env(safe-area-inset-top));
10557
+ padding-left: max(12px, env(safe-area-inset-left));
10558
+ padding-right: max(12px, env(safe-area-inset-right));
10559
+ }
10560
+ .file-preview-title {
10561
+ font-size: 0.875rem;
10562
+ gap: 6px;
10563
+ min-width: 0;
10564
+ flex: 1;
10565
+ }
10566
+ .file-preview-filename {
10567
+ max-width: 100%;
10568
+ }
10569
+ /* 路径在窄屏上极易抢空间,直接隐藏,hover/长按文件名仍可看到完整路径。 */
10570
+ .file-preview-path {
10571
+ display: none;
10572
+ }
10573
+ .file-preview-toolbar {
10574
+ gap: 4px;
10575
+ flex-shrink: 0;
10576
+ }
10577
+ .file-preview-toolbar-btn {
10578
+ padding: 4px 6px;
10579
+ font-size: 0.75rem;
10580
+ }
10581
+ .file-preview-close {
10582
+ font-size: 1.375rem;
10583
+ padding: 6px 10px;
10584
+ }
10585
+ /* 底部安全区(小白条 / 圆角) */
10586
+ .file-preview-body {
10587
+ padding-bottom: env(safe-area-inset-bottom);
10588
+ }
10589
+ }
10590
+
10495
10591
  .file-preview-header {
10496
10592
  display: flex;
10497
10593
  align-items: center;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@co0ontty/wand",
3
- "version": "1.21.19",
3
+ "version": "1.22.0",
4
4
  "description": "A web terminal for local CLI tools like Claude.",
5
5
  "type": "module",
6
6
  "bin": {