@philomelcc/dsh-workbench 0.1.4 → 0.1.6
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/README.md +11 -14
- package/client.js +100 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
# @philomelcc/dsh-workbench
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
small API modules register against.
|
|
3
|
+
外壳本体:顶部第二行的标签切换、每个模块一整页,以及模块注册用的那套小 API。
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
one module:
|
|
5
|
+
它单独装没什么用——至少配一个模块:
|
|
8
6
|
|
|
9
7
|
```powershell
|
|
10
8
|
dsh plugin --profile web add @philomelcc/dsh-workbench
|
|
11
9
|
dsh plugin --profile web add @philomelcc/dsh-status-monitor
|
|
12
10
|
```
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
契约:[`docs/SPEC.md`](../../docs/SPEC.md) · 模板:[`template/`](../../template) ·
|
|
13
|
+
现成模块:[状态监控](../status-monitor)、[下载中心](../download-center)。
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
外壳提供:
|
|
18
16
|
|
|
19
|
-
- `registerView({ id, title, icon, component, order, subtitle, badge, tab })`
|
|
20
|
-
|
|
21
|
-
- `
|
|
22
|
-
- `
|
|
23
|
-
- `
|
|
24
|
-
- `refresh()` — repaint the tab row after a badge changed.
|
|
17
|
+
- `registerView({ id, title, icon, component, order, subtitle, badge, tab })` —— 一个标签、一整页;
|
|
18
|
+
- `components`(StatusDot / Card / SectionHeader / EmptyState / Spinner / Button / Field);
|
|
19
|
+
- `tokens`(跟随明暗主题的颜色 token);
|
|
20
|
+
- `apiVersion` —— 目前是 `1`;
|
|
21
|
+
- `refresh()` —— 角标变化后重绘标签行。
|
|
25
22
|
|
|
26
|
-
MIT
|
|
23
|
+
MIT。
|
package/client.js
CHANGED
|
@@ -442,10 +442,10 @@ window.__ModuleLoader__.load({
|
|
|
442
442
|
// localStorage by us.
|
|
443
443
|
const PAPER_KEY = 'dsh-workbench:paper';
|
|
444
444
|
const PAPER_TOKENS = {
|
|
445
|
-
'--dsw-alias-bg-base': '#
|
|
446
|
-
'--dsw-alias-bg-layer-1': '#
|
|
447
|
-
'--dsw-alias-bg-layer-2': '#
|
|
448
|
-
'--dsw-alias-bg-overlay': '#
|
|
445
|
+
'--dsw-alias-bg-base': '#f7f3ea',
|
|
446
|
+
'--dsw-alias-bg-layer-1': '#f2ece0',
|
|
447
|
+
'--dsw-alias-bg-layer-2': '#ece5d6',
|
|
448
|
+
'--dsw-alias-bg-overlay': '#faf5e9',
|
|
449
449
|
'--dsw-alias-border-l1': '#d8cfba',
|
|
450
450
|
'--dsw-alias-border-l2': '#c6bba2',
|
|
451
451
|
'--dsw-alias-brand-primary': '#8a6a45',
|
|
@@ -455,7 +455,33 @@ window.__ModuleLoader__.load({
|
|
|
455
455
|
'--dsw-alias-state-warn-primary': '#a8792c',
|
|
456
456
|
'--dsw-alias-state-success-primary': '#4f7a5a',
|
|
457
457
|
'--dsw-alias-state-idle-primary': '#a49a89',
|
|
458
|
-
'--dsw-specific-sidebar-fill': '#
|
|
458
|
+
'--dsw-specific-sidebar-fill': '#f2ece0',
|
|
459
|
+
// Chat bubbles: the light base uses a pale DeepSeek blue, which looks
|
|
460
|
+
// wrong on paper. These two are outside the alias layer.
|
|
461
|
+
'--dsw-specific-bubble': '#f2ecdf',
|
|
462
|
+
'--dsw-specific-bubble-highlight': '#e9dfcb',
|
|
463
|
+
// Pale blue surfaces the alias list does not cover: command chips,
|
|
464
|
+
// reference pills, selected file tabs, "load earlier", tool cards.
|
|
465
|
+
'--dsw-alias-state-business-tertiary': '#f1e9da',
|
|
466
|
+
'--dsw-alias-state-business-primary': '#8a6a45',
|
|
467
|
+
'--dsw-specific-sidebar-nav-item-active-accent': '#f1e9da',
|
|
468
|
+
'--dsw-specific-sidebar-nav-item-active': '#efe9db',
|
|
469
|
+
'--dsw-specific-selector': '#f1e9da',
|
|
470
|
+
'--dsw-specific-input-major': '#f2ece0',
|
|
471
|
+
'--dsw-specific-tip': '#f7f2e7',
|
|
472
|
+
'--dsw-specific-menu': '#fcf9f3',
|
|
473
|
+
// The neutral greys are blue-tinted. Buttons ("load earlier"), inputs,
|
|
474
|
+
// chips and cards read their pale surfaces from this ramp, so warm it up
|
|
475
|
+
// too; deep steps stay untouched because they are text/borders.
|
|
476
|
+
'--dsw-static-neutral-bluish-00': '#fbf6ea',
|
|
477
|
+
'--dsw-static-neutral-bluish-50': '#faf6ee',
|
|
478
|
+
'--dsw-static-neutral-bluish-55': '#f8f4ea',
|
|
479
|
+
'--dsw-static-neutral-bluish-60': '#f7f3ea',
|
|
480
|
+
'--dsw-static-neutral-bluish-75': '#f4eee1',
|
|
481
|
+
'--dsw-static-neutral-bluish-90': '#f2ecdf',
|
|
482
|
+
'--dsw-static-neutral-bluish-100': '#efe9db',
|
|
483
|
+
'--dsw-static-neutral-bluish-150': '#ece6d7',
|
|
484
|
+
'--dsw-static-neutral-bluish-200': '#e7dfcd',
|
|
459
485
|
};
|
|
460
486
|
|
|
461
487
|
// Swatches double as both the current-state indicator and the toggle.
|
|
@@ -504,12 +530,55 @@ window.__ModuleLoader__.load({
|
|
|
504
530
|
try { paperDispose(); } catch (_error) { /* already gone */ }
|
|
505
531
|
paperDispose = null;
|
|
506
532
|
}
|
|
533
|
+
// Marker for paper-only rules (code surfaces) that tokens cannot reach.
|
|
534
|
+
try {
|
|
535
|
+
if (on) document.body.setAttribute('data-wb-paper', '1');
|
|
536
|
+
else document.body.removeAttribute('data-wb-paper');
|
|
537
|
+
} catch (_error) { /* body not ready */ }
|
|
507
538
|
}
|
|
508
539
|
|
|
509
540
|
function ThemeSwitcher() {
|
|
541
|
+
const boxRef = React.useRef(null);
|
|
510
542
|
const [paper, setPaperState] = React.useState(readPaper);
|
|
511
543
|
const [preference, setPreference] = React.useState(readPreference);
|
|
512
544
|
|
|
545
|
+
// The account block is fixed to the right and changes width (a reconnect
|
|
546
|
+
// banner widens it), so park the swatches against its measured left edge
|
|
547
|
+
// instead of a guessed margin.
|
|
548
|
+
React.useEffect(() => {
|
|
549
|
+
const box = boxRef.current;
|
|
550
|
+
if (!box) return undefined;
|
|
551
|
+
const place = () => {
|
|
552
|
+
const settings = document.querySelector('[class*="settingsArea"]');
|
|
553
|
+
if (!settings) {
|
|
554
|
+
box.style.right = '150px';
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
const rect = settings.getBoundingClientRect();
|
|
558
|
+
if (rect.width > 0) box.style.right = (rect.width + 16 + 12) + 'px';
|
|
559
|
+
// Same box as the account block, so `align-items: center` lands on
|
|
560
|
+
// the account's optical center instead of a guessed offset.
|
|
561
|
+
if (rect.height > 0) {
|
|
562
|
+
box.style.top = rect.top + 'px';
|
|
563
|
+
box.style.height = rect.height + 'px';
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
place();
|
|
567
|
+
let observer = null;
|
|
568
|
+
const settings = document.querySelector('[class*="settingsArea"]');
|
|
569
|
+
if (settings && typeof ResizeObserver !== 'undefined') {
|
|
570
|
+
observer = new ResizeObserver(place);
|
|
571
|
+
// border-box: the account's width changes through its chrome, not
|
|
572
|
+
// just its text content.
|
|
573
|
+
observer.observe(settings, { box: 'border-box' });
|
|
574
|
+
}
|
|
575
|
+
window.addEventListener('resize', place);
|
|
576
|
+
return () => {
|
|
577
|
+
if (observer) observer.disconnect();
|
|
578
|
+
window.removeEventListener('resize', place);
|
|
579
|
+
};
|
|
580
|
+
}, []);
|
|
581
|
+
|
|
513
582
|
// Re-apply the saved paper layer after a reload / remount.
|
|
514
583
|
React.useEffect(() => {
|
|
515
584
|
if (readPaper()) setPaper(true);
|
|
@@ -555,7 +624,11 @@ window.__ModuleLoader__.load({
|
|
|
555
624
|
};
|
|
556
625
|
|
|
557
626
|
return h('div', {
|
|
558
|
-
|
|
627
|
+
ref: boxRef,
|
|
628
|
+
style: {
|
|
629
|
+
position: 'fixed', top: 2, height: 40, zIndex: 301,
|
|
630
|
+
display: 'inline-flex', alignItems: 'center', gap: 8,
|
|
631
|
+
},
|
|
559
632
|
title: '主题',
|
|
560
633
|
},
|
|
561
634
|
THEME_SWATCHES.map((swatch) => {
|
|
@@ -593,7 +666,9 @@ window.__ModuleLoader__.load({
|
|
|
593
666
|
const tone = snap.phase === 'ready' ? balanceTone(snap.amount) : 'muted';
|
|
594
667
|
const value = snap.phase === 'ready' && typeof snap.amount === 'number' ? snap.amount.toFixed(2) : (snap.phase === 'loading' ? '…' : '—');
|
|
595
668
|
const toneColor = tone === 'green' ? '#4ade80' : tone === 'amber' ? '#e3b341' : tone === 'red' ? '#f87171' : 'var(--dsw-alias-label-secondary)';
|
|
596
|
-
|
|
669
|
+
// The border follows the theme: hard-coded dark greens read as a black
|
|
670
|
+
// ring on light/paper backgrounds.
|
|
671
|
+
const borderBase = 'var(--dsw-alias-border-l2)';
|
|
597
672
|
const at = new Date(snap.updatedAt || Date.now()).toLocaleTimeString('zh-CN', { hour12: false });
|
|
598
673
|
return h('div', {
|
|
599
674
|
style: { position: 'relative', display: 'inline-flex' },
|
|
@@ -789,7 +864,7 @@ window.__ModuleLoader__.load({
|
|
|
789
864
|
iconBtn('plugins', '插件', IconPlugins),
|
|
790
865
|
iconBtn('schedules', '自动化任务', IconClock),
|
|
791
866
|
),
|
|
792
|
-
h(
|
|
867
|
+
h(ThemeSwitcher),
|
|
793
868
|
),
|
|
794
869
|
h('div', { style: { height: 45, display: 'flex', alignItems: 'center', gap: 8, padding: '0 14px', borderTop: '1px solid var(--dsw-alias-border-l1)' } },
|
|
795
870
|
h('div', { ref: tabsRef, style: { position: 'relative', display: 'flex', alignItems: 'center', gap: 4, flex: 1, overflowX: 'auto', overflowY: 'hidden' } },
|
|
@@ -1116,6 +1191,23 @@ div[data-row-key^="session:"]:has(svg[data-state="ongoing"]) svg[data-state="ong
|
|
|
1116
1191
|
.dsh-glow-on > span:first-child > svg {
|
|
1117
1192
|
display: none !important;
|
|
1118
1193
|
}
|
|
1194
|
+
/* paper: every card-like surface follows the paper base; the code surface is
|
|
1195
|
+
deeper and overrides the card rule below (same specificity, later wins). */
|
|
1196
|
+
body[data-wb-paper="1"] [class*="_tile"],
|
|
1197
|
+
body[data-wb-paper="1"] [class*="_card"],
|
|
1198
|
+
body[data-wb-paper="1"] [class*="_Card"],
|
|
1199
|
+
body[data-wb-paper="1"] [class*="_fileCard"],
|
|
1200
|
+
body[data-wb-paper="1"] [class*="hz8-rW_header"] {
|
|
1201
|
+
background: #f2ece0 !important;
|
|
1202
|
+
}
|
|
1203
|
+
body[data-wb-paper="1"] .md-code-block,
|
|
1204
|
+
body[data-wb-paper="1"] pre,
|
|
1205
|
+
body[data-wb-paper="1"] [class*="_header_1mqf1"] {
|
|
1206
|
+
background: #ece2cc !important;
|
|
1207
|
+
}
|
|
1208
|
+
body[data-wb-paper="1"] :not(pre) > code {
|
|
1209
|
+
background: #efe6d4 !important;
|
|
1210
|
+
}
|
|
1119
1211
|
`;
|
|
1120
1212
|
|
|
1121
1213
|
function installGlow(ctx) {
|
package/package.json
CHANGED