@zhhoceanfly/protoview 0.1.3 → 0.1.4
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/dist/cli.js +6 -2
- package/package.json +1 -1
- package/public/app.js +52 -0
- package/public/index.html +1 -0
- package/public/styles.css +99 -12
package/dist/cli.js
CHANGED
|
@@ -41,7 +41,8 @@ function parseArgs(argv) {
|
|
|
41
41
|
git: "",
|
|
42
42
|
branch: "main",
|
|
43
43
|
port: 3920,
|
|
44
|
-
|
|
44
|
+
// 开发 watch 会反复重启进程;默认不弹浏览器,避免每次开新标签
|
|
45
|
+
open: process.env.PROTOVIEW_DEV !== "1",
|
|
45
46
|
showGoogle: false,
|
|
46
47
|
help: false,
|
|
47
48
|
};
|
|
@@ -59,6 +60,8 @@ function parseArgs(argv) {
|
|
|
59
60
|
args.port = Math.max(1, Number(argv[++i] || 3920) || 3920);
|
|
60
61
|
else if (a === "--no-open")
|
|
61
62
|
args.open = false;
|
|
63
|
+
else if (a === "--open")
|
|
64
|
+
args.open = true;
|
|
62
65
|
else if (a === "--show-google")
|
|
63
66
|
args.showGoogle = true;
|
|
64
67
|
else if (!a.startsWith("-"))
|
|
@@ -77,7 +80,8 @@ Options:
|
|
|
77
80
|
--git, -g <url> Use Git repo as proto source (clone to temp dir)
|
|
78
81
|
--branch, -b <name> Git branch (default: main)
|
|
79
82
|
--port <n> HTTP port (default: 3920)
|
|
80
|
-
--no-open Do not open browser
|
|
83
|
+
--no-open Do not open browser (default in npm run dev:cli)
|
|
84
|
+
--open Open browser on start
|
|
81
85
|
--show-google Include google.* packages in tree
|
|
82
86
|
-h, --help Show help
|
|
83
87
|
|
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
const isVsCodeWebview = typeof acquireVsCodeApi === "function";
|
|
3
3
|
const vscode = isVsCodeWebview ? acquireVsCodeApi() : createWsBridge();
|
|
4
4
|
const THEME_KEY = "protoview.client.theme";
|
|
5
|
+
const SIDEBAR_BREAKPOINT = 960;
|
|
5
6
|
const DRAFT_KEY = "protoview.client.drafts";
|
|
6
7
|
const SPLIT_KEY = "protoview.client.split";
|
|
8
|
+
/** null=跟宽度走;true/false=手动覆盖(窗口跨过断点后清除) */
|
|
9
|
+
let sidebarManual = null;
|
|
10
|
+
let sidebarWasNarrow = null;
|
|
7
11
|
|
|
8
12
|
/** Browser / CLI: talk to local Node host over WebSocket (same message protocol as the extension). */
|
|
9
13
|
function createWsBridge() {
|
|
@@ -178,6 +182,52 @@
|
|
|
178
182
|
els.themeBtn.textContent = next === "light" ? "☾" : "◐";
|
|
179
183
|
}
|
|
180
184
|
|
|
185
|
+
function isSidebarCollapsed() {
|
|
186
|
+
return document.getElementById("app")?.classList.contains("sidebar-collapsed");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function setSidebarCollapsed(collapsed) {
|
|
190
|
+
const app = document.getElementById("app");
|
|
191
|
+
if (!app) return;
|
|
192
|
+
app.classList.toggle("sidebar-collapsed", Boolean(collapsed));
|
|
193
|
+
const toggle = $("sidebarToggleBtn");
|
|
194
|
+
if (toggle) {
|
|
195
|
+
toggle.textContent = collapsed ? "⟩" : "⟨";
|
|
196
|
+
toggle.title = collapsed ? "展开侧栏" : "收起侧栏";
|
|
197
|
+
toggle.setAttribute("aria-label", toggle.title);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function appWidth() {
|
|
202
|
+
return document.getElementById("app")?.clientWidth || window.innerWidth || 0;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function syncSidebarByWidth() {
|
|
206
|
+
const narrow = appWidth() < SIDEBAR_BREAKPOINT;
|
|
207
|
+
if (sidebarWasNarrow !== null && sidebarWasNarrow !== narrow) {
|
|
208
|
+
sidebarManual = null;
|
|
209
|
+
}
|
|
210
|
+
sidebarWasNarrow = narrow;
|
|
211
|
+
const collapsed = sidebarManual !== null ? sidebarManual : narrow;
|
|
212
|
+
setSidebarCollapsed(collapsed);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function initSidebarCollapsed() {
|
|
216
|
+
syncSidebarByWidth();
|
|
217
|
+
const app = document.getElementById("app");
|
|
218
|
+
if (!app || typeof ResizeObserver === "undefined") {
|
|
219
|
+
window.addEventListener("resize", syncSidebarByWidth);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const ro = new ResizeObserver(() => syncSidebarByWidth());
|
|
223
|
+
ro.observe(app);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function toggleSidebar() {
|
|
227
|
+
sidebarManual = !isSidebarCollapsed();
|
|
228
|
+
setSidebarCollapsed(sidebarManual);
|
|
229
|
+
}
|
|
230
|
+
|
|
181
231
|
function esc(value) {
|
|
182
232
|
return String(value ?? "")
|
|
183
233
|
.replace(/&/g, "&")
|
|
@@ -1165,7 +1215,9 @@
|
|
|
1165
1215
|
|
|
1166
1216
|
// events
|
|
1167
1217
|
initTheme();
|
|
1218
|
+
initSidebarCollapsed();
|
|
1168
1219
|
els.themeBtn.addEventListener("click", toggleTheme);
|
|
1220
|
+
$("sidebarToggleBtn")?.addEventListener("click", toggleSidebar);
|
|
1169
1221
|
$("aiBtn").addEventListener("click", openAi);
|
|
1170
1222
|
$("closeAiBtn").addEventListener("click", closeAi);
|
|
1171
1223
|
$("aiShuffle").addEventListener("click", () => {
|
package/public/index.html
CHANGED
package/public/styles.css
CHANGED
|
@@ -53,14 +53,44 @@ button { cursor: pointer; }
|
|
|
53
53
|
button:disabled { opacity: .45; cursor: not-allowed; }
|
|
54
54
|
|
|
55
55
|
#app {
|
|
56
|
+
--sidebar-w: 260px;
|
|
57
|
+
--rail-w: 22px;
|
|
56
58
|
display: grid;
|
|
57
|
-
grid-template-columns:
|
|
59
|
+
grid-template-columns: var(--sidebar-w) var(--rail-w) minmax(0, 1fr);
|
|
58
60
|
grid-template-rows: minmax(0, 1fr);
|
|
59
61
|
height: 100%;
|
|
60
62
|
min-height: 0;
|
|
63
|
+
min-width: 0;
|
|
64
|
+
overflow: hidden;
|
|
65
|
+
}
|
|
66
|
+
#app > .sidebar {
|
|
67
|
+
grid-column: 1;
|
|
68
|
+
grid-row: 1;
|
|
69
|
+
min-height: 0;
|
|
70
|
+
min-width: 0;
|
|
71
|
+
overflow: hidden;
|
|
72
|
+
}
|
|
73
|
+
#app > .sidebar-rail {
|
|
74
|
+
grid-column: 2;
|
|
75
|
+
grid-row: 1;
|
|
76
|
+
}
|
|
77
|
+
#app > .main {
|
|
78
|
+
grid-column: 3;
|
|
79
|
+
grid-row: 1;
|
|
80
|
+
min-height: 0;
|
|
81
|
+
min-width: 0;
|
|
82
|
+
overflow: hidden;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* 收起:侧栏宽度归零,轨道按钮始终占一列,右侧自适应 */
|
|
86
|
+
#app.sidebar-collapsed {
|
|
87
|
+
--sidebar-w: 0px;
|
|
88
|
+
}
|
|
89
|
+
#app.sidebar-collapsed .sidebar {
|
|
90
|
+
visibility: hidden;
|
|
91
|
+
pointer-events: none;
|
|
92
|
+
border-right: 0;
|
|
61
93
|
}
|
|
62
|
-
#app > .sidebar { grid-column: 1; grid-row: 1; min-height: 0; }
|
|
63
|
-
#app > .main { grid-column: 2; grid-row: 1; min-height: 0; }
|
|
64
94
|
|
|
65
95
|
.sidebar {
|
|
66
96
|
border-right: 1px solid var(--border);
|
|
@@ -69,6 +99,30 @@ button:disabled { opacity: .45; cursor: not-allowed; }
|
|
|
69
99
|
flex-direction: column;
|
|
70
100
|
min-height: 0;
|
|
71
101
|
}
|
|
102
|
+
.sidebar-rail {
|
|
103
|
+
z-index: 2;
|
|
104
|
+
width: 100%;
|
|
105
|
+
height: 100%;
|
|
106
|
+
margin: 0;
|
|
107
|
+
padding: 0;
|
|
108
|
+
border: 0;
|
|
109
|
+
border-right: 1px solid var(--border);
|
|
110
|
+
border-left: 1px solid var(--border);
|
|
111
|
+
border-radius: 0;
|
|
112
|
+
background: var(--panel-2);
|
|
113
|
+
color: var(--muted);
|
|
114
|
+
font-size: 12px;
|
|
115
|
+
line-height: 1;
|
|
116
|
+
display: inline-flex;
|
|
117
|
+
align-items: center;
|
|
118
|
+
justify-content: center;
|
|
119
|
+
cursor: pointer;
|
|
120
|
+
}
|
|
121
|
+
.sidebar-rail:hover {
|
|
122
|
+
color: var(--text);
|
|
123
|
+
background: var(--hover);
|
|
124
|
+
border-color: var(--accent);
|
|
125
|
+
}
|
|
72
126
|
.side-head {
|
|
73
127
|
padding: 12px 12px 8px;
|
|
74
128
|
border-bottom: 1px solid var(--border);
|
|
@@ -80,8 +134,17 @@ button:disabled { opacity: .45; cursor: not-allowed; }
|
|
|
80
134
|
align-items: center;
|
|
81
135
|
justify-content: space-between;
|
|
82
136
|
gap: 8px;
|
|
137
|
+
min-width: 0;
|
|
138
|
+
}
|
|
139
|
+
.brand {
|
|
140
|
+
font-weight: 700;
|
|
141
|
+
font-size: 14px;
|
|
142
|
+
letter-spacing: .02em;
|
|
143
|
+
min-width: 0;
|
|
144
|
+
overflow: hidden;
|
|
145
|
+
text-overflow: ellipsis;
|
|
146
|
+
white-space: nowrap;
|
|
83
147
|
}
|
|
84
|
-
.brand { font-weight: 700; font-size: 14px; letter-spacing: .02em; }
|
|
85
148
|
.brand span { color: var(--accent-2); }
|
|
86
149
|
.icon-btn {
|
|
87
150
|
width: 30px; height: 30px;
|
|
@@ -658,7 +721,13 @@ button:disabled { opacity: .45; cursor: not-allowed; }
|
|
|
658
721
|
.stress-path { flex: 1 1 100%; }
|
|
659
722
|
.stress-path .source-dir-row { max-width: min(560px, 100%); }
|
|
660
723
|
.stress-path .source-dir-row input { width: 100%; flex: 1; }
|
|
661
|
-
.side-tools {
|
|
724
|
+
.side-tools {
|
|
725
|
+
display: flex;
|
|
726
|
+
gap: 6px;
|
|
727
|
+
align-items: center;
|
|
728
|
+
flex-wrap: nowrap;
|
|
729
|
+
flex-shrink: 0;
|
|
730
|
+
}
|
|
662
731
|
.side-search {
|
|
663
732
|
width: 100%;
|
|
664
733
|
padding: 7px 10px;
|
|
@@ -759,15 +828,15 @@ button:disabled { opacity: .45; cursor: not-allowed; }
|
|
|
759
828
|
border-radius: 8px;
|
|
760
829
|
padding: 7px 10px;
|
|
761
830
|
}
|
|
762
|
-
.addr { flex: 1 1
|
|
831
|
+
.addr { flex: 1 1 140px; font-family: var(--mono); min-width: 100px; }
|
|
763
832
|
.method {
|
|
764
|
-
flex: 1 1
|
|
833
|
+
flex: 1 1 140px;
|
|
765
834
|
font-family: var(--mono);
|
|
766
835
|
color: var(--muted);
|
|
767
836
|
overflow: hidden;
|
|
768
837
|
text-overflow: ellipsis;
|
|
769
838
|
white-space: nowrap;
|
|
770
|
-
min-width:
|
|
839
|
+
min-width: 96px;
|
|
771
840
|
}
|
|
772
841
|
.btn {
|
|
773
842
|
border: 1px solid var(--border);
|
|
@@ -1369,8 +1438,17 @@ textarea.editor {
|
|
|
1369
1438
|
background: linear-gradient(120deg, #0f172a, #1d4ed8 45%, #0891b2);
|
|
1370
1439
|
color: #f8fafc;
|
|
1371
1440
|
animation: aiPulse 2.4s ease-in-out infinite;
|
|
1441
|
+
display: inline-flex;
|
|
1442
|
+
align-items: center;
|
|
1443
|
+
white-space: nowrap;
|
|
1444
|
+
flex-shrink: 0;
|
|
1445
|
+
}
|
|
1446
|
+
.ai-spark {
|
|
1447
|
+
display: inline-block;
|
|
1448
|
+
margin-right: 4px;
|
|
1449
|
+
flex-shrink: 0;
|
|
1450
|
+
animation: aiSpin 3.2s linear infinite;
|
|
1372
1451
|
}
|
|
1373
|
-
.ai-spark { display: inline-block; margin-right: 4px; animation: aiSpin 3.2s linear infinite; }
|
|
1374
1452
|
@keyframes aiPulse {
|
|
1375
1453
|
0%, 100% { box-shadow: 0 0 0 0 transparent; }
|
|
1376
1454
|
50% { box-shadow: 0 0 14px 1px color-mix(in srgb, #38bdf8 45%, transparent); }
|
|
@@ -1475,7 +1553,16 @@ textarea.editor {
|
|
|
1475
1553
|
.env-item strong { display: block; }
|
|
1476
1554
|
.env-item span { color: var(--muted); font-size: 12px; font-family: var(--mono); }
|
|
1477
1555
|
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1556
|
+
/* 窄宽不再上下堆叠侧栏;由 JS 自动收起,右侧自适应 */
|
|
1557
|
+
@media (max-width: 900px) {
|
|
1558
|
+
#app { --sidebar-w: 220px; }
|
|
1559
|
+
.side-meta-row { flex-wrap: wrap; }
|
|
1560
|
+
.topbar { gap: 6px; padding: 8px; }
|
|
1561
|
+
.pill { padding: 6px 8px; }
|
|
1562
|
+
.tabs { overflow-x: auto; flex-wrap: nowrap; }
|
|
1563
|
+
.tab { padding: 8px 10px; white-space: nowrap; }
|
|
1564
|
+
}
|
|
1565
|
+
@media (max-width: 560px), (max-height: 420px) {
|
|
1566
|
+
.brand { font-size: 12px; }
|
|
1567
|
+
.toolbar .hint { display: none; }
|
|
1481
1568
|
}
|