@hanzlaa/rcode 3.5.0 → 3.6.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.
- package/package.json +7 -1
- package/server/dashboard.js +105 -3
- package/server/lib/html/client/agents-data.js +27 -0
- package/server/lib/html/client/app.js +15 -0
- package/server/lib/html/client/components/App.js +211 -0
- package/server/lib/html/client/components/OrchPanel.js +293 -0
- package/server/lib/html/client/components/Sidebar.js +73 -0
- package/server/lib/html/client/components/Topbar.js +53 -0
- package/server/lib/html/client/components/XtermPanel.js +220 -0
- package/server/lib/html/client/components/shared.js +330 -0
- package/server/lib/html/client/icons-client.js +85 -0
- package/server/lib/html/client/orchestrator.js +279 -0
- package/server/lib/html/client/preact.js +34 -0
- package/server/lib/html/client/store.js +91 -0
- package/server/lib/html/client/util.js +186 -0
- package/server/lib/html/client/views/AgentsView.js +83 -0
- package/server/lib/html/client/views/DecisionsView.js +102 -0
- package/server/lib/html/client/views/FilesView.js +223 -0
- package/server/lib/html/client/views/KanbanView.js +236 -0
- package/server/lib/html/client/views/MemoryView.js +157 -0
- package/server/lib/html/client/views/MilestonesView.js +136 -0
- package/server/lib/html/client/views/OrchestrationView.js +167 -0
- package/server/lib/html/client/views/OverviewView.js +221 -0
- package/server/lib/html/client/views/PhasesView.js +184 -0
- package/server/lib/html/client/views/RoadmapView.js +238 -0
- package/server/lib/html/client/views/SprintsView.js +178 -0
- package/server/lib/html/client/views/TasksView.js +148 -0
- package/server/lib/html/client.js +41 -1775
- package/server/lib/html/css.js +264 -44
- package/server/lib/html/icons.js +68 -0
- package/server/lib/html/shell.js +9 -296
- package/server/lib/scanner.js +76 -0
- package/server/orchestrator.js +237 -313
package/server/lib/html/css.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* CLAUDE.md exemption: pure CSS data file, no logic — 1000-line limit does not apply */
|
|
1
2
|
/**
|
|
2
3
|
* Dashboard CSS — Linear design system.
|
|
3
4
|
* Dark-first (Linear-style). Rihal accent: #5e6ad2 (Aether Blue).
|
|
@@ -62,6 +63,11 @@ function renderCss() {
|
|
|
62
63
|
--text-sm: 14px;
|
|
63
64
|
--text-xs: 13px;
|
|
64
65
|
--text-2xs: 11px;
|
|
66
|
+
--text-stat: 28px; /* stat card value — large metric numeral */
|
|
67
|
+
|
|
68
|
+
/* Component dimensions */
|
|
69
|
+
--h-header-btn: 26px; /* topbar button height */
|
|
70
|
+
--size-icon-btn: 32px; /* square icon button (hamburger, etc.) */
|
|
65
71
|
|
|
66
72
|
/* Spacing (4px base) */
|
|
67
73
|
--space-1: 2px;
|
|
@@ -236,9 +242,9 @@ html, body {
|
|
|
236
242
|
.hamburger-btn {
|
|
237
243
|
display: none;
|
|
238
244
|
flex-direction: column;
|
|
239
|
-
gap:
|
|
240
|
-
width:
|
|
241
|
-
height:
|
|
245
|
+
gap: var(--space-2);
|
|
246
|
+
width: var(--size-icon-btn);
|
|
247
|
+
height: var(--size-icon-btn);
|
|
242
248
|
align-items: center;
|
|
243
249
|
justify-content: center;
|
|
244
250
|
background: none;
|
|
@@ -261,7 +267,7 @@ html, body {
|
|
|
261
267
|
display: none;
|
|
262
268
|
position: fixed;
|
|
263
269
|
inset: 0;
|
|
264
|
-
background: rgba(0,0,0,0.5);
|
|
270
|
+
background: rgba(0,0,0,0.5); /* intentional: one-off overlay tint; translucency can't be expressed as a theme token */
|
|
265
271
|
z-index: 15;
|
|
266
272
|
}
|
|
267
273
|
|
|
@@ -276,7 +282,7 @@ html, body {
|
|
|
276
282
|
|
|
277
283
|
/* ── Topbar / header ───────────────────────────────────────────── */
|
|
278
284
|
header {
|
|
279
|
-
background: rgba(8,9,10,0.8);
|
|
285
|
+
background: rgba(8,9,10,0.8); /* intentional: frosted glass tied to --bg-page exact value; alpha can't be expressed as a theme token */
|
|
280
286
|
backdrop-filter: blur(12px);
|
|
281
287
|
-webkit-backdrop-filter: blur(12px);
|
|
282
288
|
border-bottom: 1px solid var(--border-subtle);
|
|
@@ -291,7 +297,7 @@ header {
|
|
|
291
297
|
}
|
|
292
298
|
|
|
293
299
|
[data-theme="light"] header {
|
|
294
|
-
background: rgba(245,245,247,0.85);
|
|
300
|
+
background: rgba(245,245,247,0.85); /* intentional: light frosted glass; alpha channel can't be expressed as a theme token */
|
|
295
301
|
}
|
|
296
302
|
|
|
297
303
|
.brand {
|
|
@@ -328,6 +334,17 @@ header {
|
|
|
328
334
|
gap: var(--space-2);
|
|
329
335
|
}
|
|
330
336
|
|
|
337
|
+
.topbar-start-group {
|
|
338
|
+
display: flex;
|
|
339
|
+
align-items: center;
|
|
340
|
+
gap: var(--space-4); /* --space-4 = 12px */
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.updated-ago {
|
|
344
|
+
font-size: var(--text-2xs); /* --text-2xs = 11px */
|
|
345
|
+
color: var(--text-muted);
|
|
346
|
+
}
|
|
347
|
+
|
|
331
348
|
.live {
|
|
332
349
|
width: 6px;
|
|
333
350
|
height: 6px;
|
|
@@ -344,8 +361,8 @@ header {
|
|
|
344
361
|
.header-btn {
|
|
345
362
|
display: inline-flex;
|
|
346
363
|
align-items: center;
|
|
347
|
-
gap:
|
|
348
|
-
height:
|
|
364
|
+
gap: var(--space-2);
|
|
365
|
+
height: var(--h-header-btn);
|
|
349
366
|
padding: 0 var(--space-3);
|
|
350
367
|
background: var(--bg-elev-2);
|
|
351
368
|
border: 1px solid var(--border-default);
|
|
@@ -445,7 +462,7 @@ section .body {
|
|
|
445
462
|
color: var(--text-muted);
|
|
446
463
|
}
|
|
447
464
|
.stat .value {
|
|
448
|
-
font-size:
|
|
465
|
+
font-size: var(--text-stat);
|
|
449
466
|
font-weight: 700;
|
|
450
467
|
letter-spacing: -0.025em;
|
|
451
468
|
color: var(--text-primary);
|
|
@@ -1566,6 +1583,21 @@ footer {
|
|
|
1566
1583
|
text-align: center;
|
|
1567
1584
|
}
|
|
1568
1585
|
|
|
1586
|
+
.orch-empty-tab {
|
|
1587
|
+
padding: var(--space-2) var(--space-3); /* 6px 8px via space tokens */
|
|
1588
|
+
font-size: var(--text-2xs); /* 11px */
|
|
1589
|
+
color: var(--text-muted);
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
.orch-footer-spacer {
|
|
1593
|
+
flex: 1;
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
.orch-footer-status {
|
|
1597
|
+
font-size: var(--text-2xs); /* 11px */
|
|
1598
|
+
color: var(--text-muted);
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1569
1601
|
/* Terminal log lines */
|
|
1570
1602
|
.kt-line { color: #a0c4a0; word-break: break-word; }
|
|
1571
1603
|
.kt-line.tool { color: #7cb8ff; }
|
|
@@ -1921,6 +1953,49 @@ footer {
|
|
|
1921
1953
|
flex-direction: column;
|
|
1922
1954
|
}
|
|
1923
1955
|
.term-panel.open { display: flex; }
|
|
1956
|
+
.term-panel.fullscreen {
|
|
1957
|
+
inset: 0;
|
|
1958
|
+
left: 0;
|
|
1959
|
+
height: 100vh;
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
/* Minimized terminal pill */
|
|
1963
|
+
.term-pill {
|
|
1964
|
+
display: none;
|
|
1965
|
+
position: fixed;
|
|
1966
|
+
bottom: var(--space-4);
|
|
1967
|
+
right: var(--space-4);
|
|
1968
|
+
z-index: 201;
|
|
1969
|
+
align-items: center;
|
|
1970
|
+
gap: var(--space-2);
|
|
1971
|
+
padding: var(--space-2) var(--space-4);
|
|
1972
|
+
background: var(--bg-elev-3);
|
|
1973
|
+
border: 1px solid var(--accent-primary);
|
|
1974
|
+
border-radius: var(--radius-4);
|
|
1975
|
+
color: var(--text-primary);
|
|
1976
|
+
font-size: var(--text-xs);
|
|
1977
|
+
cursor: pointer;
|
|
1978
|
+
box-shadow: 0 6px 20px rgba(0,0,0,0.45);
|
|
1979
|
+
}
|
|
1980
|
+
.term-pill.show { display: flex; }
|
|
1981
|
+
.term-pill:hover { background: var(--bg-hover); }
|
|
1982
|
+
.term-pill-icon { color: var(--text-muted); }
|
|
1983
|
+
|
|
1984
|
+
/* "running" badge for phase / sprint / task cards */
|
|
1985
|
+
.run-badge {
|
|
1986
|
+
display: inline-flex;
|
|
1987
|
+
align-items: center;
|
|
1988
|
+
gap: 4px;
|
|
1989
|
+
margin-left: var(--space-2);
|
|
1990
|
+
padding: 1px var(--space-2);
|
|
1991
|
+
background: rgba(63,185,80,0.15);
|
|
1992
|
+
border: 1px solid rgba(63,185,80,0.4);
|
|
1993
|
+
border-radius: var(--radius-2);
|
|
1994
|
+
color: var(--accent-green);
|
|
1995
|
+
font-size: var(--text-2xs);
|
|
1996
|
+
font-weight: 600;
|
|
1997
|
+
white-space: nowrap;
|
|
1998
|
+
}
|
|
1924
1999
|
.term-header {
|
|
1925
2000
|
display: flex;
|
|
1926
2001
|
align-items: center;
|
|
@@ -1975,47 +2050,14 @@ footer {
|
|
|
1975
2050
|
padding: 6px 8px;
|
|
1976
2051
|
background: #0c0c0e;
|
|
1977
2052
|
}
|
|
1978
|
-
.term-
|
|
1979
|
-
display: flex;
|
|
1980
|
-
align-items: center;
|
|
1981
|
-
gap: var(--space-2);
|
|
2053
|
+
.term-hint {
|
|
1982
2054
|
padding: var(--space-2) var(--space-3);
|
|
1983
2055
|
background: var(--bg-elev-2);
|
|
1984
2056
|
border-top: 1px solid var(--border-subtle);
|
|
1985
|
-
|
|
1986
|
-
}
|
|
1987
|
-
.term-prompt {
|
|
1988
|
-
color: var(--accent-primary);
|
|
1989
|
-
font-family: var(--font-mono);
|
|
2057
|
+
color: var(--text-muted);
|
|
1990
2058
|
font-size: var(--text-xs);
|
|
1991
2059
|
flex-shrink: 0;
|
|
1992
2060
|
}
|
|
1993
|
-
.term-input-field {
|
|
1994
|
-
flex: 1;
|
|
1995
|
-
height: 26px;
|
|
1996
|
-
background: transparent;
|
|
1997
|
-
border: none;
|
|
1998
|
-
color: var(--text-primary);
|
|
1999
|
-
font-family: var(--font-mono);
|
|
2000
|
-
font-size: var(--text-xs);
|
|
2001
|
-
outline: none;
|
|
2002
|
-
letter-spacing: 0;
|
|
2003
|
-
}
|
|
2004
|
-
.term-input-field::placeholder { color: var(--text-muted); }
|
|
2005
|
-
.term-send-btn {
|
|
2006
|
-
height: 24px;
|
|
2007
|
-
padding: 0 var(--space-3);
|
|
2008
|
-
background: var(--accent-primary);
|
|
2009
|
-
border: none;
|
|
2010
|
-
border-radius: var(--radius-2);
|
|
2011
|
-
color: white;
|
|
2012
|
-
font-size: 10px;
|
|
2013
|
-
font-family: var(--font-mono);
|
|
2014
|
-
cursor: pointer;
|
|
2015
|
-
opacity: 0.85;
|
|
2016
|
-
white-space: nowrap;
|
|
2017
|
-
}
|
|
2018
|
-
.term-send-btn:hover { opacity: 1; }
|
|
2019
2061
|
/* Run / Terminal action buttons (used on sprint/phase detail) */
|
|
2020
2062
|
.term-run-btn {
|
|
2021
2063
|
display: inline-flex;
|
|
@@ -2040,12 +2082,133 @@ footer {
|
|
|
2040
2082
|
color: var(--text-secondary);
|
|
2041
2083
|
}
|
|
2042
2084
|
.term-run-btn.outline:hover { background: var(--bg-hover); color: var(--text-primary); }
|
|
2085
|
+
.term-run-btn.danger {
|
|
2086
|
+
background: transparent;
|
|
2087
|
+
border-color: rgba(255,107,107,0.4);
|
|
2088
|
+
color: #ff6b6b;
|
|
2089
|
+
}
|
|
2090
|
+
.term-run-btn.danger:hover { background: rgba(255,107,107,0.12); opacity: 1; }
|
|
2043
2091
|
.term-action-bar {
|
|
2044
2092
|
display: flex;
|
|
2045
2093
|
align-items: center;
|
|
2046
2094
|
gap: var(--space-3);
|
|
2047
2095
|
margin-bottom: var(--space-5);
|
|
2048
2096
|
}
|
|
2097
|
+
.term-status-dot.exited { background: #ff4444; animation: none; }
|
|
2098
|
+
.term-status-dot.waiting { background: var(--accent-amber); animation: pulse 1.2s infinite; }
|
|
2099
|
+
|
|
2100
|
+
/* Compact ▶ Run button on phase / sprint / task list cards */
|
|
2101
|
+
.card-run-btn {
|
|
2102
|
+
float: right;
|
|
2103
|
+
margin-left: var(--space-3);
|
|
2104
|
+
height: 20px;
|
|
2105
|
+
padding: 0 var(--space-3);
|
|
2106
|
+
background: transparent;
|
|
2107
|
+
border: 1px solid var(--border-default);
|
|
2108
|
+
border-radius: var(--radius-2);
|
|
2109
|
+
color: var(--text-tertiary);
|
|
2110
|
+
font-size: 10px;
|
|
2111
|
+
font-weight: 500;
|
|
2112
|
+
cursor: pointer;
|
|
2113
|
+
transition: background var(--t-fast) var(--ease),
|
|
2114
|
+
color var(--t-fast) var(--ease),
|
|
2115
|
+
border-color var(--t-fast) var(--ease);
|
|
2116
|
+
}
|
|
2117
|
+
.card-run-btn:hover {
|
|
2118
|
+
background: var(--accent-green);
|
|
2119
|
+
border-color: var(--accent-green);
|
|
2120
|
+
color: #fff;
|
|
2121
|
+
}
|
|
2122
|
+
.ms-actions {
|
|
2123
|
+
display: inline-flex;
|
|
2124
|
+
align-items: center;
|
|
2125
|
+
gap: var(--space-2);
|
|
2126
|
+
margin-left: var(--space-3);
|
|
2127
|
+
}
|
|
2128
|
+
.ms-audit-btn:hover {
|
|
2129
|
+
background: var(--accent-primary);
|
|
2130
|
+
border-color: var(--accent-primary);
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
/* ── Orchestration view ─────────────────────────────────────── */
|
|
2134
|
+
.orch-subtitle {
|
|
2135
|
+
color: var(--text-tertiary);
|
|
2136
|
+
font-size: var(--text-sm);
|
|
2137
|
+
margin-bottom: var(--space-5);
|
|
2138
|
+
}
|
|
2139
|
+
.orch-grid {
|
|
2140
|
+
display: grid;
|
|
2141
|
+
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
2142
|
+
gap: var(--space-4);
|
|
2143
|
+
}
|
|
2144
|
+
.orch-card {
|
|
2145
|
+
background: var(--bg-elev-2);
|
|
2146
|
+
border: 1px solid var(--border-subtle);
|
|
2147
|
+
border-left: 3px solid var(--text-muted);
|
|
2148
|
+
border-radius: var(--radius-4);
|
|
2149
|
+
padding: var(--space-4) var(--space-5);
|
|
2150
|
+
display: flex;
|
|
2151
|
+
flex-direction: column;
|
|
2152
|
+
gap: var(--space-3);
|
|
2153
|
+
}
|
|
2154
|
+
.orch-card.orch-running { border-left-color: var(--accent-green); }
|
|
2155
|
+
.orch-card.orch-waiting {
|
|
2156
|
+
border-left-color: var(--accent-amber);
|
|
2157
|
+
background: rgba(245,158,11,0.05);
|
|
2158
|
+
}
|
|
2159
|
+
.orch-card.orch-waiting .orch-card-badge { color: var(--accent-amber); }
|
|
2160
|
+
.orch-card.orch-error,
|
|
2161
|
+
.orch-card.orch-exited { border-left-color: #ff4444; }
|
|
2162
|
+
.orch-card.orch-stopped { border-left-color: var(--accent-amber); }
|
|
2163
|
+
.orch-card.orch-done { border-left-color: var(--accent-blue); }
|
|
2164
|
+
.orch-card-head {
|
|
2165
|
+
display: flex;
|
|
2166
|
+
align-items: center;
|
|
2167
|
+
gap: var(--space-3);
|
|
2168
|
+
}
|
|
2169
|
+
.orch-card-id {
|
|
2170
|
+
font-weight: 600;
|
|
2171
|
+
font-size: var(--text-sm);
|
|
2172
|
+
color: var(--text-primary);
|
|
2173
|
+
}
|
|
2174
|
+
.orch-card-badge {
|
|
2175
|
+
margin-left: auto;
|
|
2176
|
+
font-size: var(--text-2xs);
|
|
2177
|
+
text-transform: uppercase;
|
|
2178
|
+
letter-spacing: 0.06em;
|
|
2179
|
+
color: var(--text-muted);
|
|
2180
|
+
}
|
|
2181
|
+
.orch-card-cmd {
|
|
2182
|
+
font-family: var(--font-mono);
|
|
2183
|
+
font-size: var(--text-xs);
|
|
2184
|
+
color: var(--text-secondary);
|
|
2185
|
+
background: var(--bg-elev-1);
|
|
2186
|
+
border-radius: var(--radius-2);
|
|
2187
|
+
padding: var(--space-2) var(--space-3);
|
|
2188
|
+
word-break: break-all;
|
|
2189
|
+
}
|
|
2190
|
+
.orch-card-meta {
|
|
2191
|
+
font-size: var(--text-2xs);
|
|
2192
|
+
color: var(--text-tertiary);
|
|
2193
|
+
}
|
|
2194
|
+
.orch-card-actions {
|
|
2195
|
+
display: flex;
|
|
2196
|
+
gap: var(--space-2);
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
/* ── Icon alignment helpers (for sprint 32.2 SVG icon sweep) ── */
|
|
2200
|
+
.ic {
|
|
2201
|
+
display: inline-block;
|
|
2202
|
+
vertical-align: -0.15em; /* optical baseline alignment with surrounding text */
|
|
2203
|
+
flex-shrink: 0;
|
|
2204
|
+
}
|
|
2205
|
+
.btn-icon { display: inline-block; vertical-align: -0.1em; flex-shrink: 0; }
|
|
2206
|
+
.section-icon {
|
|
2207
|
+
display: inline-flex;
|
|
2208
|
+
align-items: center;
|
|
2209
|
+
gap: var(--space-2);
|
|
2210
|
+
}
|
|
2211
|
+
.tree-icon .ic { vertical-align: -0.15em; }
|
|
2049
2212
|
|
|
2050
2213
|
/* ── Scrollbar global ───────────────────────────────────────── */
|
|
2051
2214
|
::-webkit-scrollbar { width: 6px; height: 6px; }
|
|
@@ -2053,6 +2216,63 @@ footer {
|
|
|
2053
2216
|
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 3px; }
|
|
2054
2217
|
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
|
|
2055
2218
|
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
|
|
2219
|
+
|
|
2220
|
+
/* ── Command runner (Sprint 33.2) ───────────────────────────────────────────── */
|
|
2221
|
+
.cmd-runner {
|
|
2222
|
+
background: var(--bg-card);
|
|
2223
|
+
border: 1px solid var(--border);
|
|
2224
|
+
border-radius: var(--radius-md);
|
|
2225
|
+
padding: var(--space-4);
|
|
2226
|
+
margin-bottom: var(--space-5);
|
|
2227
|
+
}
|
|
2228
|
+
.cmd-runner-title {
|
|
2229
|
+
font-size: var(--text-sm);
|
|
2230
|
+
font-weight: 600;
|
|
2231
|
+
color: var(--text-muted);
|
|
2232
|
+
text-transform: uppercase;
|
|
2233
|
+
letter-spacing: 0.05em;
|
|
2234
|
+
margin-bottom: var(--space-3);
|
|
2235
|
+
display: flex;
|
|
2236
|
+
align-items: center;
|
|
2237
|
+
gap: var(--space-2);
|
|
2238
|
+
}
|
|
2239
|
+
.cmd-runner-row {
|
|
2240
|
+
display: flex;
|
|
2241
|
+
gap: var(--space-3);
|
|
2242
|
+
align-items: center;
|
|
2243
|
+
}
|
|
2244
|
+
.cmd-runner-select {
|
|
2245
|
+
flex: 1;
|
|
2246
|
+
background: var(--bg-input, var(--bg-elev-2));
|
|
2247
|
+
border: 1px solid var(--border);
|
|
2248
|
+
border-radius: var(--radius-sm);
|
|
2249
|
+
color: var(--text-primary);
|
|
2250
|
+
padding: var(--space-2) var(--space-3);
|
|
2251
|
+
font-size: var(--text-sm);
|
|
2252
|
+
cursor: pointer;
|
|
2253
|
+
}
|
|
2254
|
+
.cmd-runner-select:focus {
|
|
2255
|
+
outline: none;
|
|
2256
|
+
border-color: var(--accent-blue);
|
|
2257
|
+
}
|
|
2258
|
+
.cmd-runner-btn {
|
|
2259
|
+
background: var(--accent-blue);
|
|
2260
|
+
color: #fff;
|
|
2261
|
+
border: none;
|
|
2262
|
+
border-radius: var(--radius-sm);
|
|
2263
|
+
padding: var(--space-2) var(--space-4);
|
|
2264
|
+
font-size: var(--text-sm);
|
|
2265
|
+
font-weight: 600;
|
|
2266
|
+
cursor: pointer;
|
|
2267
|
+
display: flex;
|
|
2268
|
+
align-items: center;
|
|
2269
|
+
gap: var(--space-2);
|
|
2270
|
+
transition: opacity 0.15s;
|
|
2271
|
+
white-space: nowrap;
|
|
2272
|
+
}
|
|
2273
|
+
.cmd-runner-btn:hover:not(:disabled) { opacity: 0.85; }
|
|
2274
|
+
.cmd-runner-btn:disabled,
|
|
2275
|
+
.cmd-runner-btn--busy { opacity: 0.6; cursor: not-allowed; }
|
|
2056
2276
|
</style>`;
|
|
2057
2277
|
}
|
|
2058
2278
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline SVG icon set (Lucide-style stroke icons).
|
|
3
|
+
*
|
|
4
|
+
* No CDN, no font — just path data rendered into a <svg>. Used server-side
|
|
5
|
+
* by shell.js for static chrome, and embedded as window.__ICONS__ so the
|
|
6
|
+
* client modules can render the same icons in dynamic markup.
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT: The ICONS map is duplicated in the ESM client counterpart:
|
|
9
|
+
* server/lib/html/client/icons-client.js (in sync with this file)
|
|
10
|
+
* Keep both files in sync when adding or changing icon paths. The duplication
|
|
11
|
+
* is the no-build-step cost — the browser cannot import a CJS module as ESM.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// name → inner SVG markup (viewBox 0 0 24 24, stroke = currentColor)
|
|
15
|
+
// Keep in sync with server/lib/html/client/icons-client.js
|
|
16
|
+
const ICONS = {
|
|
17
|
+
home: '<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><path d="M9 22V12h6v10"/>',
|
|
18
|
+
activity: '<path d="M22 12h-4l-3 9L9 3l-3 9H2"/>',
|
|
19
|
+
map: '<polygon points="3 6 9 3 15 6 21 3 21 18 15 21 9 18 3 21"/><line x1="9" y1="3" x2="9" y2="18"/><line x1="15" y1="6" x2="15" y2="21"/>',
|
|
20
|
+
target: '<circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/>',
|
|
21
|
+
layers: '<polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/>',
|
|
22
|
+
zap: '<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>',
|
|
23
|
+
checkSquare: '<polyline points="9 11 12 14 22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/>',
|
|
24
|
+
kanban: '<rect x="3" y="4" width="5" height="16" rx="1"/><rect x="10" y="4" width="5" height="11" rx="1"/><rect x="17" y="4" width="5" height="14" rx="1"/>',
|
|
25
|
+
file: '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/>',
|
|
26
|
+
users: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
|
|
27
|
+
scale: '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="8" y1="13" x2="16" y2="13"/><line x1="8" y1="17" x2="13" y2="17"/>',
|
|
28
|
+
database: '<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/><path d="M3 12c0 1.66 4 3 9 3s9-1.34 9-3"/>',
|
|
29
|
+
play: '<polygon points="6 3 20 12 6 21 6 3"/>',
|
|
30
|
+
terminal: '<polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/>',
|
|
31
|
+
square: '<rect x="6" y="6" width="12" height="12" rx="1"/>',
|
|
32
|
+
x: '<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>',
|
|
33
|
+
minimize: '<line x1="5" y1="14" x2="19" y2="14"/>',
|
|
34
|
+
maximize: '<path d="M8 3H5a2 2 0 0 0-2 2v3"/><path d="M21 8V5a2 2 0 0 0-2-2h-3"/><path d="M3 16v3a2 2 0 0 0 2 2h3"/><path d="M16 21h3a2 2 0 0 0 2-2v-3"/>',
|
|
35
|
+
clock: '<circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/>',
|
|
36
|
+
eye: '<path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7z"/><circle cx="12" cy="12" r="3"/>',
|
|
37
|
+
filePen: '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h7"/><polyline points="14 2 14 8 20 8"/><path d="M18.4 12.6a2 2 0 0 1 3 3L17 20l-4 1 1-4z"/>',
|
|
38
|
+
hourglass: '<path d="M5 22h14M5 2h14M17 22v-4.17a2 2 0 0 0-.59-1.42L12 12l-4.41 4.41A2 2 0 0 0 7 17.83V22M7 2v4.17a2 2 0 0 0 .59 1.42L12 12l4.41-4.41A2 2 0 0 0 17 6.17V2"/>',
|
|
39
|
+
|
|
40
|
+
// Added in sprint 32.2 — emoji-to-SVG sweep
|
|
41
|
+
building: '<rect x="4" y="2" width="16" height="20" rx="2"/><path d="M9 22V12h6v10"/><path d="M8 7h.01M12 7h.01M16 7h.01M8 11h.01M12 11h.01M16 11h.01"/>',
|
|
42
|
+
link: '<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>',
|
|
43
|
+
'alert-triangle':'<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>',
|
|
44
|
+
brain: '<path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96-.46 2.5 2.5 0 0 1-1.28-4.56A3 3 0 0 1 5 12c0-.56.15-1.1.42-1.57a2.5 2.5 0 0 1-.42-4.93V5.5A2.5 2.5 0 0 1 9.5 2z"/><path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96-.46 2.5 2.5 0 0 0 1.28-4.56A3 3 0 0 0 19 12c0-.56-.15-1.1-.42-1.57a2.5 2.5 0 0 0 .42-4.93V5.5A2.5 2.5 0 0 0 14.5 2z"/>',
|
|
45
|
+
'clipboard-list':'<rect x="8" y="2" width="8" height="4" rx="1" ry="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><line x1="12" y1="11" x2="12" y2="17"/><line x1="9" y1="14" x2="15" y2="14"/>',
|
|
46
|
+
flag: '<path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/>',
|
|
47
|
+
monitor: '<rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/>',
|
|
48
|
+
'file-text': '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/>',
|
|
49
|
+
copy: '<rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>',
|
|
50
|
+
lightbulb: '<line x1="9" y1="18" x2="15" y2="18"/><line x1="10" y1="22" x2="14" y2="22"/><path d="M15.09 14c.18-.98.65-1.74 1.41-2.5A4.65 4.65 0 0 0 18 8 6 6 0 0 0 6 8c0 1 .23 2.23 1.5 3.5A4.61 4.61 0 0 1 8.91 14"/>',
|
|
51
|
+
'edit-3': '<path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>',
|
|
52
|
+
|
|
53
|
+
// Added in sprint 32.3 — App/Topbar theme toggle icons
|
|
54
|
+
moon: '<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>',
|
|
55
|
+
sun: '<circle cx="12" cy="12" r="4"/><line x1="12" y1="2" x2="12" y2="6"/><line x1="12" y1="18" x2="12" y2="22"/><line x1="4.22" y1="4.22" x2="7.05" y2="7.05"/><line x1="16.95" y1="16.95" x2="19.78" y2="19.78"/><line x1="2" y1="12" x2="6" y2="12"/><line x1="18" y1="12" x2="22" y2="12"/><line x1="4.22" y1="19.78" x2="7.05" y2="16.95"/><line x1="16.95" y1="7.05" x2="19.78" y2="4.22"/>',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Render an icon as an inline <svg>. size in px; cls adds extra classes.
|
|
59
|
+
function icon(name, size, cls) {
|
|
60
|
+
const p = ICONS[name];
|
|
61
|
+
if (!p) return '';
|
|
62
|
+
const s = size || 16;
|
|
63
|
+
return '<svg class="ic' + (cls ? ' ' + cls : '') + '" width="' + s + '" height="' + s +
|
|
64
|
+
'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" ' +
|
|
65
|
+
'stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' + p + '</svg>';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = { ICONS, icon };
|