dsh-multi-chat 0.6.8 → 1.0.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/README.md +20 -21
- package/README.zh.md +20 -21
- package/bin/dsh-multi-chat.mjs +5 -9
- package/lib/client.js +778 -0
- package/lib/client.js.map +1 -0
- package/{plugin/dsh-client-ui-multi-wall/lib → lib}/index.js +57 -69
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/client/WallToggle.d.ts +1 -1
- package/lib/types/client/WallToggle.d.ts.map +1 -0
- package/lib/types/client/WallToggle.js +36 -0
- package/lib/types/client/WallToggle.js.map +1 -0
- package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/client/WallView.d.ts +1 -1
- package/lib/types/client/WallView.d.ts.map +1 -0
- package/lib/types/client/WallView.js +218 -0
- package/lib/types/client/WallView.js.map +1 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/client/index.js +59 -0
- package/lib/types/client/index.js.map +1 -0
- package/lib/types/client/locales.d.ts.map +1 -0
- package/lib/types/client/locales.js +96 -0
- package/lib/types/client/locales.js.map +1 -0
- package/lib/types/client/store.d.ts.map +1 -0
- package/lib/types/client/store.js +27 -0
- package/lib/types/client/store.js.map +1 -0
- package/lib/types/client/wall-injected.d.ts.map +1 -0
- package/lib/types/client/wall-injected.js +76 -0
- package/lib/types/client/wall-injected.js.map +1 -0
- package/lib/types/gateway.d.ts +57 -0
- package/lib/types/gateway.d.ts.map +1 -0
- package/lib/types/gateway.js +566 -0
- package/lib/types/gateway.js.map +1 -0
- package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/index.d.ts +1 -16
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +550 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/invariant.d.ts.map +1 -0
- package/lib/types/invariant.js +26 -0
- package/lib/types/invariant.js.map +1 -0
- package/package.json +41 -17
- package/scripts/install-plugin.ps1 +6 -9
- package/src/client/WallToggle.module.css +26 -0
- package/src/client/WallToggle.tsx +52 -0
- package/src/client/WallView.module.css +190 -0
- package/src/client/WallView.tsx +406 -0
- package/src/client/index.ts +103 -0
- package/src/client/locales.ts +100 -0
- package/src/client/store.ts +40 -0
- package/src/client/wall-injected.ts +123 -0
- package/src/css-modules.d.ts +5 -0
- package/src/gateway.ts +627 -0
- package/src/index.ts +618 -0
- package/src/invariant.ts +34 -0
- package/plugin/dsh-client-ui-multi-wall/README.md +0 -26
- package/plugin/dsh-client-ui-multi-wall/README.zh.md +0 -26
- package/plugin/dsh-client-ui-multi-wall/cordis.patch.yml +0 -7
- package/plugin/dsh-client-ui-multi-wall/lib/client.js +0 -781
- package/plugin/dsh-client-ui-multi-wall/lib/invariant.js +0 -27
- package/plugin/dsh-client-ui-multi-wall/package.json +0 -88
- /package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/client/index.d.ts +0 -0
- /package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/client/locales.d.ts +0 -0
- /package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/client/store.d.ts +0 -0
- /package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/client/wall-injected.d.ts +0 -0
- /package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/invariant.d.ts +0 -0
package/package.json
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-multi-chat",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "DSH
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "DSH 多窗口墙:在官方 DeepSeek Harness Web 界面里以多窗口网格并排运行、监控多个对话实例,一屏盯住所有 Agent 的实时进度;内置带口令认证的局域网网关,手机/平板也能看。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"main": "
|
|
7
|
+
"main": "./lib/index.js",
|
|
8
|
+
"types": "./lib/types/index.d.ts",
|
|
8
9
|
"exports": {
|
|
9
10
|
".": {
|
|
10
|
-
"types": "./
|
|
11
|
-
"default": "./
|
|
11
|
+
"types": "./lib/types/index.d.ts",
|
|
12
|
+
"default": "./lib/index.js"
|
|
12
13
|
},
|
|
13
14
|
"./client": {
|
|
14
|
-
"types": "./
|
|
15
|
-
"default": "./
|
|
15
|
+
"types": "./lib/types/client/index.d.ts",
|
|
16
|
+
"default": "./lib/client.js"
|
|
17
|
+
},
|
|
18
|
+
"./invariant": {
|
|
19
|
+
"types": "./lib/types/invariant.d.ts",
|
|
20
|
+
"default": "./lib/invariant.js"
|
|
16
21
|
},
|
|
17
22
|
"./package.json": "./package.json"
|
|
18
23
|
},
|
|
@@ -20,8 +25,20 @@
|
|
|
20
25
|
"bundle": {
|
|
21
26
|
"patch": "./cordis.patch.yml"
|
|
22
27
|
},
|
|
28
|
+
"client": {
|
|
29
|
+
"platform": "web",
|
|
30
|
+
"inject": [
|
|
31
|
+
"@deepseek-ai/dsh-client-runtime",
|
|
32
|
+
"@deepseek-ai/dsh-client-locale",
|
|
33
|
+
"@deepseek-ai/dsh-client-ui-layout",
|
|
34
|
+
"@deepseek-ai/dsh-client-ui-sidebar",
|
|
35
|
+
"@deepseek-ai/dsh-client-ui-primitives"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
23
38
|
"marketplace": {
|
|
24
|
-
"profiles": [
|
|
39
|
+
"profiles": [
|
|
40
|
+
"web"
|
|
41
|
+
],
|
|
25
42
|
"requiresRestart": true,
|
|
26
43
|
"manualSteps": false,
|
|
27
44
|
"requiresBuildApproval": false
|
|
@@ -55,22 +72,29 @@
|
|
|
55
72
|
"scripts/",
|
|
56
73
|
"patches/",
|
|
57
74
|
"assets/",
|
|
75
|
+
"lib/",
|
|
76
|
+
"src/",
|
|
58
77
|
"cordis.patch.yml",
|
|
59
78
|
"README.md",
|
|
60
79
|
"README.zh.md",
|
|
61
|
-
"
|
|
62
|
-
"plugin/dsh-client-ui-multi-wall/README.md",
|
|
63
|
-
"plugin/dsh-client-ui-multi-wall/README.zh.md",
|
|
64
|
-
"plugin/dsh-client-ui-multi-wall/cordis.patch.yml",
|
|
65
|
-
"plugin/dsh-client-ui-multi-wall/lib/index.js",
|
|
66
|
-
"plugin/dsh-client-ui-multi-wall/lib/invariant.js",
|
|
67
|
-
"plugin/dsh-client-ui-multi-wall/lib/client.js",
|
|
68
|
-
"plugin/dsh-client-ui-multi-wall/lib/types/**/*.d.ts"
|
|
80
|
+
"LICENSE"
|
|
69
81
|
],
|
|
70
82
|
"scripts": {
|
|
71
|
-
"
|
|
83
|
+
"build": "tsc -b tsconfig.json && tsdown",
|
|
84
|
+
"clean": "rm -rf lib",
|
|
85
|
+
"test": "vitest run"
|
|
86
|
+
},
|
|
87
|
+
"devDependencies": {
|
|
88
|
+
"@types/node": "^26.2.0",
|
|
89
|
+
"lightningcss": "^1.33.0",
|
|
90
|
+
"tsdown": "^0.11.13",
|
|
91
|
+
"typescript": "^5.9.3",
|
|
92
|
+
"vitest": "^2.1.9"
|
|
72
93
|
},
|
|
73
94
|
"engines": {
|
|
74
95
|
"node": ">=20"
|
|
96
|
+
},
|
|
97
|
+
"dependencies": {
|
|
98
|
+
"clsx": "^2.1.1"
|
|
75
99
|
}
|
|
76
100
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
把多窗口墙插件装进 DSH web profile 并启用(官方声明式 bundle 形态)。
|
|
5
5
|
|
|
6
6
|
.DESCRIPTION
|
|
7
|
-
1) 将
|
|
7
|
+
1) 将 dsh-multi-chat 打包为 tarball;
|
|
8
8
|
2) 用 `dsh plugin --profile web add` 装进 profile;
|
|
9
9
|
3) DSH 自动调和 dsh.profile.bundles:插件包声明了 dsh.bundle.patch
|
|
10
10
|
(指向包内自带 cordis.patch.yml),DSH 启动时自动挂载该 bundle 层,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
侧边栏底部会出现「多窗口墙」按钮)。
|
|
14
14
|
|
|
15
15
|
卸载(一条命令,无需手动删 patch 或文件):
|
|
16
|
-
dsh plugin --profile <Profile> remove
|
|
16
|
+
dsh plugin --profile <Profile> remove dsh-multi-chat
|
|
17
17
|
|
|
18
18
|
.PARAMETER Profile
|
|
19
19
|
profile 名,默认 web。
|
|
@@ -27,13 +27,10 @@ param(
|
|
|
27
27
|
|
|
28
28
|
$ErrorActionPreference = "Stop"
|
|
29
29
|
$root = Split-Path -Parent $PSScriptRoot
|
|
30
|
-
$pluginDir = Join-Path $root "plugin\dsh-client-ui-multi-wall"
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
$tarball = Join-Path $root "dsh-client-ui-multi-wall.tgz"
|
|
36
|
-
Push-Location $pluginDir
|
|
31
|
+
# 1) pack tarball from root directory
|
|
32
|
+
$tarball = Join-Path $root "dsh-multi-chat.tgz"
|
|
33
|
+
Push-Location $root
|
|
37
34
|
npm pack --pack-destination $root | Out-Null
|
|
38
35
|
Pop-Location
|
|
39
36
|
if (-not (Test-Path $tarball)) { throw "npm pack 失败,未生成 $tarball" }
|
|
@@ -49,4 +46,4 @@ Write-Host ""
|
|
|
49
46
|
Write-Host "完成。重启 dsh web 生效:"
|
|
50
47
|
Write-Host " dsh web --port <n>"
|
|
51
48
|
Write-Host "打开后侧边栏底部应出现「多窗口墙」按钮。"
|
|
52
|
-
Write-Host "卸载:dsh plugin --profile $Profile remove
|
|
49
|
+
Write-Host "卸载:dsh plugin --profile $Profile remove dsh-multi-chat"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
.row {
|
|
2
|
+
box-sizing: border-box;
|
|
3
|
+
display: flex;
|
|
4
|
+
align-items: center;
|
|
5
|
+
gap: 8px;
|
|
6
|
+
width: calc(100% + 8px);
|
|
7
|
+
height: 34px;
|
|
8
|
+
margin: 4px -4px;
|
|
9
|
+
padding: 6px 2px 6px 10px;
|
|
10
|
+
border: none;
|
|
11
|
+
border-radius: 12px;
|
|
12
|
+
background: none;
|
|
13
|
+
color: var(--dsw-alias-label-secondary);
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
font: inherit;
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
}
|
|
18
|
+
.row:hover {
|
|
19
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
20
|
+
color: var(--dsw-alias-label-primary);
|
|
21
|
+
}
|
|
22
|
+
.label {
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
text-overflow: ellipsis;
|
|
25
|
+
white-space: nowrap;
|
|
26
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WallToggle: the sidebar-foot shortcut. Clicking it opens the wall view —
|
|
3
|
+
* the `conversation.view` ring switches to the 'multi-wall' entry, which the
|
|
4
|
+
* header renders as the "多窗口" tab. The click is a plain user-equivalent
|
|
5
|
+
* activation: it finds the header's view-ring tab for this plugin's label and
|
|
6
|
+
* clicks it, so the official view-ring state machine (the chat store's active
|
|
7
|
+
* view field) performs the switch. No store is declared: the ring decides
|
|
8
|
+
* what renders, so this row owns no state.
|
|
9
|
+
*
|
|
10
|
+
* Session-scoped by design: the view ring (and its header tabs) only renders
|
|
11
|
+
* with an active session, so the shortcut is inert on the empty-hero screen —
|
|
12
|
+
* the user first opens or creates a session (the official flow), after which
|
|
13
|
+
* the tab is present and the click lands.
|
|
14
|
+
*/
|
|
15
|
+
import { IconFullscreenOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
|
|
16
|
+
import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'
|
|
17
|
+
import css from './WallToggle.module.css'
|
|
18
|
+
|
|
19
|
+
/** Composed props: sidebar column state + locale. */
|
|
20
|
+
export type WallToggleProps =
|
|
21
|
+
& PropsRuntime<'sidebar.footer.action'>
|
|
22
|
+
& PropsLocale<'multiWall'>
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Render the wall shortcut row (icon; label only in the wide column).
|
|
26
|
+
* @param props - composed slot props.
|
|
27
|
+
* @returns the shortcut row.
|
|
28
|
+
*/
|
|
29
|
+
export function WallToggle({ wide, t }: WallToggleProps) {
|
|
30
|
+
return (
|
|
31
|
+
<button
|
|
32
|
+
type="button"
|
|
33
|
+
className={css.row}
|
|
34
|
+
aria-label={t('toggle.aria')}
|
|
35
|
+
title={t('toggle')}
|
|
36
|
+
onClick={() => {
|
|
37
|
+
// The official view ring renders the active entry through
|
|
38
|
+
// `only: <active id>`; the only sanctioned way to move it is the
|
|
39
|
+
// header tab's click handler (actions.setView). Trigger that same
|
|
40
|
+
// element instead of reaching into the chat store from the root
|
|
41
|
+
// scope. No tab (no active session) is a no-op.
|
|
42
|
+
const label = t('view.multiWall')
|
|
43
|
+
const tab = Array.from(document.querySelectorAll<HTMLButtonElement>('[role="tab"]'))
|
|
44
|
+
.find(el => el.textContent?.trim() === label)
|
|
45
|
+
tab?.click()
|
|
46
|
+
}}
|
|
47
|
+
>
|
|
48
|
+
<IconFullscreenOutline16 size={wide ? 16 : 18} />
|
|
49
|
+
{wide && <span className={css.label}>{t('toggle')}</span>}
|
|
50
|
+
</button>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/* Wall view: toolbar over a horizontally-filled pane grid. All colors ride
|
|
2
|
+
the official --dsw-alias-* token sheet; controls are official primitives
|
|
3
|
+
(Button/Input/Menu/StateDot), so the surface matches the app chrome. */
|
|
4
|
+
|
|
5
|
+
/* When the wall view is active, hide the conversation composer seat (the
|
|
6
|
+
input bar and its stats band) so the wall owns the full column height.
|
|
7
|
+
The seat is the official layout's bottom slot ([data-composer-seat] inside
|
|
8
|
+
[data-conversation-scroll]); :has() scopes the rule to the wall being
|
|
9
|
+
present. Pure presentation — no official logic is touched. */
|
|
10
|
+
:global([data-conversation-scroll]:has([data-wall-view]) [data-composer-seat]) {
|
|
11
|
+
display: none;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.wall {
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
flex: 1;
|
|
18
|
+
min-width: 0;
|
|
19
|
+
min-height: 0;
|
|
20
|
+
background: var(--dsw-alias-bg-base);
|
|
21
|
+
color: var(--dsw-alias-label-primary);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.toolbar {
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
gap: 12px;
|
|
28
|
+
padding: 8px 14px;
|
|
29
|
+
border-bottom: 1px solid var(--dsw-alias-border-l2);
|
|
30
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
31
|
+
flex: none;
|
|
32
|
+
flex-wrap: wrap;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.title {
|
|
36
|
+
font-size: 14px;
|
|
37
|
+
font-weight: 600;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* Phone-access link bar: shown under the toolbar after fetching /multi/api/link. */
|
|
41
|
+
.linkBar {
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: 10px;
|
|
45
|
+
padding: 6px 14px;
|
|
46
|
+
border-bottom: 1px solid var(--dsw-alias-border-l2);
|
|
47
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
48
|
+
flex: none;
|
|
49
|
+
flex-wrap: wrap;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.linkText {
|
|
53
|
+
font-size: 12px;
|
|
54
|
+
color: var(--dsw-alias-label-secondary);
|
|
55
|
+
flex: 1;
|
|
56
|
+
min-width: 160px;
|
|
57
|
+
overflow-wrap: anywhere;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.status {
|
|
61
|
+
font-size: 12px;
|
|
62
|
+
color: var(--dsw-alias-label-secondary);
|
|
63
|
+
flex: 1;
|
|
64
|
+
min-width: 120px;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.controls {
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
gap: 8px;
|
|
71
|
+
flex-wrap: wrap;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.field {
|
|
75
|
+
display: inline-flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
gap: 6px;
|
|
78
|
+
font-size: 12px;
|
|
79
|
+
color: var(--dsw-alias-label-secondary);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* The official Input primitive renders a wrapper span; keep the number
|
|
83
|
+
steppers compact inside the toolbar field. */
|
|
84
|
+
.field > span {
|
|
85
|
+
width: 76px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Pane grid: default fills the row with equal columns, wraps only when the
|
|
89
|
+
row is full — no single-column vertical stacking by default. */
|
|
90
|
+
.grid {
|
|
91
|
+
flex: 1;
|
|
92
|
+
overflow: auto;
|
|
93
|
+
padding: 8px;
|
|
94
|
+
display: grid;
|
|
95
|
+
gap: 8px;
|
|
96
|
+
grid-auto-rows: minmax(280px, 1fr);
|
|
97
|
+
align-content: start;
|
|
98
|
+
}
|
|
99
|
+
.grid[data-cols='auto'] { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
|
|
100
|
+
.grid[data-cols='1'] { grid-template-columns: 1fr; }
|
|
101
|
+
.grid[data-cols='2'] { grid-template-columns: repeat(2, 1fr); }
|
|
102
|
+
.grid[data-cols='3'] { grid-template-columns: repeat(3, 1fr); }
|
|
103
|
+
.grid[data-cols='4'] { grid-template-columns: repeat(4, 1fr); }
|
|
104
|
+
.grid[data-cols='6'] { grid-template-columns: repeat(6, 1fr); }
|
|
105
|
+
|
|
106
|
+
.pane {
|
|
107
|
+
display: flex;
|
|
108
|
+
flex-direction: column;
|
|
109
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
110
|
+
border-radius: 8px;
|
|
111
|
+
overflow: hidden;
|
|
112
|
+
min-width: 0;
|
|
113
|
+
min-height: 0;
|
|
114
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
115
|
+
}
|
|
116
|
+
.pane.zoomed {
|
|
117
|
+
grid-column: 1 / -1;
|
|
118
|
+
grid-row: 1 / -1;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.paneHead {
|
|
122
|
+
display: flex;
|
|
123
|
+
align-items: center;
|
|
124
|
+
gap: 8px;
|
|
125
|
+
padding: 4px 8px;
|
|
126
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
127
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
128
|
+
flex: none;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.dot {
|
|
132
|
+
flex: none;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.paneTitle {
|
|
136
|
+
font-size: 12px;
|
|
137
|
+
overflow: hidden;
|
|
138
|
+
text-overflow: ellipsis;
|
|
139
|
+
white-space: nowrap;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.paneActions {
|
|
143
|
+
margin-left: auto;
|
|
144
|
+
display: flex;
|
|
145
|
+
gap: 2px;
|
|
146
|
+
flex: none;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.action {
|
|
150
|
+
border: none;
|
|
151
|
+
background: none;
|
|
152
|
+
color: var(--dsw-alias-label-secondary);
|
|
153
|
+
cursor: pointer;
|
|
154
|
+
padding: 2px 6px;
|
|
155
|
+
border-radius: 4px;
|
|
156
|
+
line-height: 1;
|
|
157
|
+
white-space: nowrap;
|
|
158
|
+
}
|
|
159
|
+
.action:hover { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); }
|
|
160
|
+
.action.danger:hover { color: var(--dsw-static-amber-600); }
|
|
161
|
+
.action.danger.confirm {
|
|
162
|
+
background: var(--dsw-static-amber-500);
|
|
163
|
+
color: var(--dsw-static-neutral-00);
|
|
164
|
+
font-size: 11px;
|
|
165
|
+
padding: 2px 8px;
|
|
166
|
+
}
|
|
167
|
+
.action.danger.confirm:hover { background: var(--dsw-static-amber-600); color: var(--dsw-static-neutral-00); }
|
|
168
|
+
|
|
169
|
+
.paneBody {
|
|
170
|
+
flex: 1;
|
|
171
|
+
min-height: 0;
|
|
172
|
+
position: relative;
|
|
173
|
+
}
|
|
174
|
+
.paneBody iframe {
|
|
175
|
+
width: 100%;
|
|
176
|
+
height: 100%;
|
|
177
|
+
border: none;
|
|
178
|
+
display: block;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.empty {
|
|
182
|
+
grid-column: 1 / -1;
|
|
183
|
+
display: flex;
|
|
184
|
+
flex-direction: column;
|
|
185
|
+
align-items: center;
|
|
186
|
+
justify-content: center;
|
|
187
|
+
gap: 6px;
|
|
188
|
+
color: var(--dsw-alias-label-secondary);
|
|
189
|
+
}
|
|
190
|
+
.empty .hint { font-size: 12px; }
|