@roaming-ai/dsh-group-chat 0.2.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/LICENSE +21 -0
- package/README.md +56 -0
- package/cordis.patch.yml +12 -0
- package/lib/client.js +3308 -0
- package/lib/client.js.map +1 -0
- package/lib/index.js +2583 -0
- package/lib/types/client/Bubble.d.ts +10 -0
- package/lib/types/client/Glyph.d.ts +12 -0
- package/lib/types/client/GroupChatPanel.d.ts +10 -0
- package/lib/types/client/GroupChatPanel.old.d.ts +10 -0
- package/lib/types/client/GroupChatSettingsSection.d.ts +15 -0
- package/lib/types/client/PermissionSelect.d.ts +13 -0
- package/lib/types/client/RoleDrawer.d.ts +17 -0
- package/lib/types/client/ThinkRow.d.ts +9 -0
- package/lib/types/client/ToolRow.d.ts +9 -0
- package/lib/types/client/api.d.ts +8 -0
- package/lib/types/client/components/AsidePanel.d.ts +31 -0
- package/lib/types/client/components/Bubble.d.ts +19 -0
- package/lib/types/client/components/ChatPanel.d.ts +57 -0
- package/lib/types/client/components/Composer.d.ts +48 -0
- package/lib/types/client/components/Glyph.d.ts +12 -0
- package/lib/types/client/components/GroupChatSettingsSection.d.ts +15 -0
- package/lib/types/client/components/MessageFlow.d.ts +15 -0
- package/lib/types/client/components/NavPanel.d.ts +40 -0
- package/lib/types/client/components/PermissionSelect.d.ts +13 -0
- package/lib/types/client/components/RoleDrawer.d.ts +17 -0
- package/lib/types/client/components/ThinkRow.d.ts +9 -0
- package/lib/types/client/components/ToolRow.d.ts +9 -0
- package/lib/types/client/components/index.d.ts +9 -0
- package/lib/types/client/components.d.ts +22 -0
- package/lib/types/client/drawer.d.ts +17 -0
- package/lib/types/client/glyph.d.ts +12 -0
- package/lib/types/client/hooks/index.d.ts +6 -0
- package/lib/types/client/hooks/useComposer.d.ts +27 -0
- package/lib/types/client/hooks/useFileSearch.d.ts +19 -0
- package/lib/types/client/hooks/useGroupChatState.d.ts +95 -0
- package/lib/types/client/hooks/useMentionState.d.ts +27 -0
- package/lib/types/client/index.d.ts +52 -0
- package/lib/types/client/lib/api.d.ts +8 -0
- package/lib/types/client/lib/model.d.ts +80 -0
- package/lib/types/client/lib/styles.d.ts +10 -0
- package/lib/types/client/lib/ui.d.ts +17 -0
- package/lib/types/client/model.d.ts +78 -0
- package/lib/types/client/panel.d.ts +10 -0
- package/lib/types/client/settings.d.ts +15 -0
- package/lib/types/client/styles.d.ts +10 -0
- package/lib/types/client/ui.d.ts +17 -0
- package/lib/types/client/utils/utils.d.ts +29 -0
- package/lib/types/client/utils.d.ts +22 -0
- package/lib/types/core/json.d.ts +9 -0
- package/lib/types/core/status.d.ts +18 -0
- package/lib/types/core/tools.d.ts +59 -0
- package/lib/types/core/types.d.ts +256 -0
- package/lib/types/host/actions.d.ts +34 -0
- package/lib/types/host/api/actions.d.ts +36 -0
- package/lib/types/host/api/http.d.ts +16 -0
- package/lib/types/host/api/index.d.ts +7 -0
- package/lib/types/host/api/routes.d.ts +11 -0
- package/lib/types/host/broadcast.d.ts +20 -0
- package/lib/types/host/conversation.d.ts +25 -0
- package/lib/types/host/engine/conversation.d.ts +25 -0
- package/lib/types/host/engine/index.d.ts +7 -0
- package/lib/types/host/engine/retitle.d.ts +20 -0
- package/lib/types/host/http.d.ts +16 -0
- package/lib/types/host/index.d.ts +8 -0
- package/lib/types/host/materials/index.d.ts +6 -0
- package/lib/types/host/materials/materials.d.ts +40 -0
- package/lib/types/host/materials.d.ts +32 -0
- package/lib/types/host/persistence/index.d.ts +6 -0
- package/lib/types/host/persistence/persistence.d.ts +31 -0
- package/lib/types/host/persistence/store.d.ts +65 -0
- package/lib/types/host/persistence.d.ts +31 -0
- package/lib/types/host/routes.d.ts +11 -0
- package/lib/types/host/service.d.ts +28 -0
- package/lib/types/host/state.d.ts +45 -0
- package/lib/types/host/store.d.ts +65 -0
- package/lib/types/host/tools/index.d.ts +6 -0
- package/lib/types/host/tools/tools.d.ts +28 -0
- package/lib/types/host/tools.d.ts +28 -0
- package/lib/types/index.d.ts +41 -0
- package/lib/types/mount-once.d.ts +9 -0
- package/lib/types/shared/file-mention-grammar.d.ts +37 -0
- package/lib/types/shared/file-mention-grammar.test.d.ts +5 -0
- package/package.json +98 -0
- package/src/client/GroupChatPanel.tsx +385 -0
- package/src/client/components/AsidePanel.tsx +188 -0
- package/src/client/components/Bubble.tsx +76 -0
- package/src/client/components/ChatPanel.tsx +214 -0
- package/src/client/components/Composer.tsx +238 -0
- package/src/client/components/Glyph.tsx +27 -0
- package/src/client/components/GroupChatSettingsSection.tsx +74 -0
- package/src/client/components/MessageFlow.tsx +97 -0
- package/src/client/components/NavPanel.tsx +249 -0
- package/src/client/components/PermissionSelect.tsx +159 -0
- package/src/client/components/RoleDrawer.tsx +186 -0
- package/src/client/components/ThinkRow.tsx +32 -0
- package/src/client/components/ToolRow.tsx +51 -0
- package/src/client/components/index.ts +10 -0
- package/src/client/hooks/index.ts +7 -0
- package/src/client/hooks/useComposer.ts +272 -0
- package/src/client/hooks/useFileSearch.ts +115 -0
- package/src/client/hooks/useGroupChatState.ts +214 -0
- package/src/client/hooks/useMentionState.ts +56 -0
- package/src/client/index.ts +110 -0
- package/src/client/lib/api.ts +23 -0
- package/src/client/lib/model.ts +119 -0
- package/src/client/lib/styles.ts +317 -0
- package/src/client/lib/ui.ts +27 -0
- package/src/client/react-dom-shim.d.ts +13 -0
- package/src/client/utils/utils.ts +104 -0
- package/src/core/json.ts +28 -0
- package/src/core/status.ts +33 -0
- package/src/core/tools.ts +41 -0
- package/src/core/types.ts +222 -0
- package/src/host/api/actions.ts +335 -0
- package/src/host/api/http.ts +80 -0
- package/src/host/api/index.ts +8 -0
- package/src/host/api/routes.ts +95 -0
- package/src/host/broadcast.ts +65 -0
- package/src/host/engine/conversation.ts +331 -0
- package/src/host/engine/index.ts +8 -0
- package/src/host/engine/retitle.ts +135 -0
- package/src/host/index.ts +9 -0
- package/src/host/materials/index.ts +7 -0
- package/src/host/materials/materials.ts +193 -0
- package/src/host/persistence/index.ts +7 -0
- package/src/host/persistence/persistence.ts +311 -0
- package/src/host/persistence/store.ts +375 -0
- package/src/host/service.ts +78 -0
- package/src/host/state.ts +85 -0
- package/src/host/tools/index.ts +7 -0
- package/src/host/tools/tools.ts +194 -0
- package/src/index.ts +99 -0
- package/src/mount-once.ts +49 -0
- package/src/shared/file-mention-grammar.test.ts +77 -0
- package/src/shared/file-mention-grammar.ts +82 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-group-chat — 浏览器半(web 客户端模块)。
|
|
3
|
+
*
|
|
4
|
+
* 经 window.__ModuleLoader__.load 注册(由 tsdown 预设的 banner/footer 闭包
|
|
5
|
+
* 工厂外壳生成);factory 返回 Cordis 客户端插件:
|
|
6
|
+
* - 「模型群聊」设置页(settings.section):启停开关,写 host 的 group-chat
|
|
7
|
+
* 设置命名空间(settings.yaml 持久化)
|
|
8
|
+
* - 启用时挂载:侧边栏「群聊」入口(sidebar.panellist)+ 中央主面板(main)
|
|
9
|
+
* - 面板数据走 /api/group-chat/*(fetch + SSE),Host 半持有全部状态
|
|
10
|
+
* - DSW 原语(@deepseek-ai/dsh-client-ui-primitives,shell 静态种子模块)
|
|
11
|
+
* 提供按钮/输入/开关/菜单/图标与 MarkdownText 渲染器
|
|
12
|
+
*
|
|
13
|
+
* 设计契约(impeccable direction contract;seed key 76db9e37,surface roll
|
|
14
|
+
* 第 4/6/1 手中用户锁定 C「三区工作台」,代码先行):
|
|
15
|
+
* THESIS 三区工作台;FIRST VIEWPORT 左 232px 导航 + 中央会话流 + 右 304px
|
|
16
|
+
* 上下文栏(窄容器覆盖式、可收起)。完整契约见 docs/DESIGN.md。
|
|
17
|
+
*
|
|
18
|
+
* @module dsh-group-chat/client
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis'
|
|
22
|
+
import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client'
|
|
23
|
+
// Type-only:拉入浏览器面的 Context 合并(ctx.settingsScope)。
|
|
24
|
+
import type {} from '@deepseek-ai/dsh-client-ui-settings/client'
|
|
25
|
+
// Type-only:拉入 ctx.slots 合并(renderer 自 0.1.2 起拥有槽位注册表)。
|
|
26
|
+
import type {} from '@deepseek-ai/dsh-client-ui-renderer/client'
|
|
27
|
+
import { createElement as h } from 'react'
|
|
28
|
+
import { injectStyles } from './lib/styles.ts'
|
|
29
|
+
import { GroupChatPanel } from './GroupChatPanel.tsx'
|
|
30
|
+
import { GroupChatSettingsSection } from './components/GroupChatSettingsSection.tsx'
|
|
31
|
+
import { Glyph } from './components/Glyph.tsx'
|
|
32
|
+
|
|
33
|
+
/** Host 侧注册的设置命名空间 shape 与命名名(与宿主半拼写同一值,两边不共享代码)。 */
|
|
34
|
+
interface GroupChatSettings {
|
|
35
|
+
enabled?: boolean
|
|
36
|
+
}
|
|
37
|
+
const SETTINGS_NAMESPACE = 'group-chat'
|
|
38
|
+
|
|
39
|
+
/** Client plugin id. */
|
|
40
|
+
export const name = 'group-chat-client'
|
|
41
|
+
|
|
42
|
+
/** Required services. */
|
|
43
|
+
export const inject = ['slots', 'settingsScope']
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Shell 布局槽位的类型声明镜像(运行时由外壳的 layout/sidebar 包声明):
|
|
47
|
+
* 中央主面板为 keyed 槽(按 key 挂载),侧边栏面板列表为 list 槽
|
|
48
|
+
* (id + order + label)。参照 dsh-web 家族外部包的自声明模式。
|
|
49
|
+
*/
|
|
50
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
51
|
+
interface SlotMap {
|
|
52
|
+
/** 中央主面板:按 key 挂载一个面板组件。 */
|
|
53
|
+
'main': { kind: 'keyed', scope: 'root', owner: Record<string, never> }
|
|
54
|
+
/** 侧边栏面板列表行:图标 + 标签入口。 */
|
|
55
|
+
'sidebar.panellist': { kind: 'list', scope: 'root', owner: { size?: number } }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 客户端插件体:设置页常驻注册 + 启用门控挂载侧边栏入口与主面板。
|
|
61
|
+
* @param ctx - client root context.
|
|
62
|
+
*/
|
|
63
|
+
export function apply(ctx: ClientContext): void {
|
|
64
|
+
injectStyles()
|
|
65
|
+
|
|
66
|
+
const scope: SettingsScope<GroupChatSettings> = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE })
|
|
67
|
+
|
|
68
|
+
// 设置页常驻注册(禁用时也保留入口,便于重新启用)
|
|
69
|
+
ctx.slots.inject('settings.section', () =>
|
|
70
|
+
ctx.slots.register(
|
|
71
|
+
{
|
|
72
|
+
name: 'settings.section',
|
|
73
|
+
id: 'dsh-group-chat',
|
|
74
|
+
order: 60,
|
|
75
|
+
label: () => '模型群聊',
|
|
76
|
+
inject: () => ({ settingsScope: scope }),
|
|
77
|
+
},
|
|
78
|
+
(props: { settingsScope: SettingsScope<GroupChatSettings> }) => h(GroupChatSettingsSection, props),
|
|
79
|
+
),
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
// 启用门控:enabled 为 false 时卸载侧边栏入口与主面板
|
|
83
|
+
let uiDisposer: (() => void) | undefined
|
|
84
|
+
const mountUi = (): void => {
|
|
85
|
+
if (uiDisposer !== undefined) return
|
|
86
|
+
const disposers: (() => void)[] = []
|
|
87
|
+
try {
|
|
88
|
+
disposers.push(ctx.slots.inject('main', () =>
|
|
89
|
+
ctx.slots.register({ name: 'main', key: 'group-chat' }, () => h(GroupChatPanel, null))))
|
|
90
|
+
disposers.push(ctx.slots.inject('sidebar.panellist', () =>
|
|
91
|
+
ctx.slots.register({ name: 'sidebar.panellist', id: 'group-chat', order: 50, label: '群聊' }, (props: { size?: number }) => h(Glyph, props))))
|
|
92
|
+
} catch (e) {
|
|
93
|
+
console.error('[dsh-group-chat] mount failed:', e)
|
|
94
|
+
}
|
|
95
|
+
uiDisposer = () => {
|
|
96
|
+
uiDisposer = undefined
|
|
97
|
+
for (const dispose of disposers.splice(0)) dispose()
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const syncEnabled = (): void => {
|
|
101
|
+
const snapshot = scope.getSnapshot()
|
|
102
|
+
const on = snapshot.status === 'ready'
|
|
103
|
+
? (snapshot.value && snapshot.value.enabled) !== false
|
|
104
|
+
: snapshot.status === 'unavailable'
|
|
105
|
+
if (on) mountUi()
|
|
106
|
+
else if (uiDisposer !== undefined) uiDisposer()
|
|
107
|
+
}
|
|
108
|
+
scope.subscribe(syncEnabled)
|
|
109
|
+
syncEnabled()
|
|
110
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 浏览器半 transport:/api/group-chat/* 同源 JSON 端点。
|
|
3
|
+
* @module dsh-group-chat/client/api
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { API_PREFIX } from './model.ts'
|
|
7
|
+
|
|
8
|
+
async function readJson<T>(fetchPromise: Promise<Response>): Promise<T> {
|
|
9
|
+
const response = await fetchPromise
|
|
10
|
+
const body = await response.json() as { error?: string }
|
|
11
|
+
if (!response.ok) throw new Error(body && body.error ? body.error : '请求失败(HTTP ' + response.status + '),请稍后重试')
|
|
12
|
+
return body as unknown as T
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const api = {
|
|
16
|
+
state: (): Promise<unknown> => readJson(fetch(API_PREFIX + '/state', { cache: 'no-store' })),
|
|
17
|
+
action: (payload: Record<string, unknown>, signal?: AbortSignal): Promise<unknown> => readJson(fetch(API_PREFIX + '/action', {
|
|
18
|
+
method: 'POST',
|
|
19
|
+
headers: { 'content-type': 'application/json' },
|
|
20
|
+
body: JSON.stringify(payload),
|
|
21
|
+
signal,
|
|
22
|
+
})),
|
|
23
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 浏览器半共享常量与小工具(纯函数,无 React 依赖)。
|
|
3
|
+
* @module dsh-group-chat/client/model
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { RoleRecord, Snapshot, ToolCallRecord } from '../../core/types.ts'
|
|
7
|
+
|
|
8
|
+
/** 会话列表状态派生与文案(core 纯函数,供 NavPanel 渲染)。 */
|
|
9
|
+
export { sessStatus, SESS_STATUS_LABEL, type SessStatus } from '../../core/status.ts'
|
|
10
|
+
|
|
11
|
+
/** 角色标识色调色板(与宿主半一致)。 */
|
|
12
|
+
export const PALETTE = ['#5b8def', '#22a06b', '#e8912d', '#c678dd', '#e05661', '#56b6c2', '#98c379', '#d19a66']
|
|
13
|
+
|
|
14
|
+
/** Host HTTP API 前缀。 */
|
|
15
|
+
export const API_PREFIX = '/api/group-chat'
|
|
16
|
+
|
|
17
|
+
/** MarkdownText 渲染文案。 */
|
|
18
|
+
export const MD_LABELS = Object.freeze({ code: { copyLabel: '复制', copiedLabel: '已复制' }, footnotes: '脚注' })
|
|
19
|
+
|
|
20
|
+
/** 快照的 wire 形态(响应里带 ok 标记)。 */
|
|
21
|
+
export type ClientSnapshot = Snapshot & { ok: boolean }
|
|
22
|
+
|
|
23
|
+
/** models action 的响应形态。 */
|
|
24
|
+
export interface ModelsResponse {
|
|
25
|
+
ok: boolean
|
|
26
|
+
providers?: { id: string, name?: string }[]
|
|
27
|
+
modelsByProvider?: Record<string, { id: string, name?: string }[]>
|
|
28
|
+
error?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** efforts action 的响应形态。 */
|
|
32
|
+
export interface EffortsResponse {
|
|
33
|
+
ok: boolean
|
|
34
|
+
efforts?: { id: string, name: string, description?: string }[]
|
|
35
|
+
defaultEffort?: string
|
|
36
|
+
error?: string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** 快照内的角色/会话/群组视图行。 */
|
|
40
|
+
export type SnapshotRole = Snapshot['roles'][number]
|
|
41
|
+
export type SnapshotSession = Snapshot['sessions'][number]
|
|
42
|
+
export type SnapshotGroup = Snapshot['groups'][number]
|
|
43
|
+
export type SnapshotMessage = Snapshot['messages'][number]
|
|
44
|
+
|
|
45
|
+
export function roleById(s: ClientSnapshot, id: string | null): SnapshotRole | null {
|
|
46
|
+
for (const r of s.roles) if (r.id === id) return r
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function sessById(s: ClientSnapshot, id: string): SnapshotSession | null {
|
|
51
|
+
for (const x of s.sessions) if (x.id === id) return x
|
|
52
|
+
return null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function groupById(s: ClientSnapshot, id: string): SnapshotGroup | null {
|
|
56
|
+
for (const g of s.groups) if (g.id === id) return g
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function escapeRegExp(v: string): string {
|
|
61
|
+
return String(v).replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function firstLine(text: string): string {
|
|
65
|
+
const i = text.indexOf('\n')
|
|
66
|
+
return i === -1 ? text : text.slice(0, i)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function latestLine(text: string): string {
|
|
70
|
+
const visible = text.trimEnd()
|
|
71
|
+
const i = visible.lastIndexOf('\n')
|
|
72
|
+
return i === -1 ? visible : visible.slice(i + 1)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function fmtTime(ts: number): string {
|
|
76
|
+
const delta = Math.max(0, Date.now() - ts)
|
|
77
|
+
if (delta < 60000) return '刚刚'
|
|
78
|
+
if (delta < 3600000) return Math.floor(delta / 60000) + ' 分钟前'
|
|
79
|
+
if (delta < 86400000) return Math.floor(delta / 3600000) + ' 小时前'
|
|
80
|
+
const d = new Date(ts)
|
|
81
|
+
const sameYear = d.getFullYear() === new Date().getFullYear()
|
|
82
|
+
const pad = (n: number): string => (n < 10 ? '0' + n : '' + n)
|
|
83
|
+
return sameYear ? (d.getMonth() + 1) + '月' + d.getDate() + '日' : d.getFullYear() + '/' + (d.getMonth() + 1) + '/' + d.getDate()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** 角色编辑抽屉的草稿形态(编辑与新建共用)。 */
|
|
87
|
+
export interface RoleDraft {
|
|
88
|
+
id?: string
|
|
89
|
+
name: string
|
|
90
|
+
color: string | null
|
|
91
|
+
persona: string
|
|
92
|
+
provider: string
|
|
93
|
+
model: string
|
|
94
|
+
temperature?: number
|
|
95
|
+
reasoningEffort: string
|
|
96
|
+
enabled?: boolean
|
|
97
|
+
thinking: boolean
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function draftFromRole(role: SnapshotRole): RoleDraft {
|
|
101
|
+
return { id: role.id, name: role.name, color: role.color ?? null, persona: role.persona, provider: role.provider, model: role.model, temperature: role.temperature, reasoningEffort: role.reasoningEffort || 'default', enabled: role.enabled, thinking: role.thinking === true }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function blankDraft(): RoleDraft {
|
|
105
|
+
return { name: '', color: null, persona: '', provider: '', model: '', temperature: undefined, reasoningEffort: 'default', enabled: true, thinking: false }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** 工具调用行的展示参数。 */
|
|
109
|
+
export type ToolCallView = ToolCallRecord
|
|
110
|
+
|
|
111
|
+
/** 草稿是否可作为角色落库(宿主侧再校验一次)。 */
|
|
112
|
+
export function draftMissing(draft: RoleDraft): string {
|
|
113
|
+
if (!draft.name.trim()) return '角色名称不能为空'
|
|
114
|
+
if (!draft.provider || !draft.model) return '请选择角色绑定的模型'
|
|
115
|
+
return ''
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** RoleRecord 兼容视图(快照角色行即其展示子集)。 */
|
|
119
|
+
export type RoleView = RoleRecord
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 浏览器半样式:CSS 以内联字符串承载(刻意不迁移 CSS Modules 管线——
|
|
3
|
+
* 类名需保持原样,侧栏入口的 “newSession” 类名是任务看板等 DOM 注入式
|
|
4
|
+
* 面板识别“侧边栏导航点击”的跨插件标记,哈希化会破坏该约定)。
|
|
5
|
+
* 工厂执行时幂等注入 <style>,loader 卸载时按 data-plugin 摘除标签。
|
|
6
|
+
* @module dsh-group-chat/client/styles
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** 注入标签的唯一 id。 */
|
|
10
|
+
const TAG_ID = 'dsh-group-chat/styles.css'
|
|
11
|
+
|
|
12
|
+
export const CSS = [
|
|
13
|
+
/* ===== 布局骨架:三区工作台;卡片只用于内容单元,导航用平铺行 ===== */
|
|
14
|
+
'.dsgc-root{display:flex;height:100%;min-height:0;background:var(--dsw-alias-bg-base,transparent);color:var(--dsw-alias-label-primary,inherit);font-size:var(--dsh-content-font-size,14px);container-type:inline-size;position:relative}',
|
|
15
|
+
'.dsgc-loading{padding:24px;color:var(--dsw-alias-label-tertiary,inherit);display:flex;gap:8px;align-items:center;opacity:0;animation:dsgc-loading-in .18s ease-out .15s forwards}',
|
|
16
|
+
/* 首开加载态延迟 150ms 淡入:本机回路通常数毫秒内数据即达并卸载本元素,
|
|
17
|
+
快路径完全不可见(无闪现,等同移除);慢路径才出现反馈,空白面板不再是唯一信号 */
|
|
18
|
+
'@keyframes dsgc-loading-in{to{opacity:1}}',
|
|
19
|
+
'.dsgc-loading svg{animation:dsgc-spin 1s linear infinite}',
|
|
20
|
+
'@keyframes dsgc-spin{to{transform:rotate(360deg)}}',
|
|
21
|
+
/* ===== 左导航栏(可收起,收合动画与右栏同款配方) ===== */
|
|
22
|
+
'.dsgc-nav{width:232px;flex:none;display:flex;flex-direction:column;gap:8px;border-right:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2));padding:12px 10px;min-height:0;min-width:0;transition:width .28s cubic-bezier(.16,1,.3,1),opacity .18s ease,padding .28s cubic-bezier(.16,1,.3,1),border-right-width .28s cubic-bezier(.16,1,.3,1)}',
|
|
23
|
+
/* 子元素经 flex 列默认 stretch 填满内容区(不写死宽度:内容区实宽 232px——
|
|
24
|
+
宿主无全局 border-box,面板为 content-box,旧版写死 212px 曾致右侧多出
|
|
25
|
+
20px 死区、左右内距失衡);收合动画期间内容随面板收缩,行内 ellipsis
|
|
26
|
+
渐进截断 + visibility 0.22s 切断,无溢出涂抹 */
|
|
27
|
+
'.dsgc-nav>*{flex:none}',
|
|
28
|
+
'.dsgc-nav.closed{width:0;opacity:0;padding-left:0;padding-right:0;border-right-width:0;visibility:hidden;transition:width .24s ease-in,opacity .16s ease-in,padding .24s ease-in,border-right-width .24s ease-in,visibility 0s .22s}',
|
|
29
|
+
'.dsgc-search{flex:none}',
|
|
30
|
+
'.dsgc-search input{font-size:13px}',
|
|
31
|
+
'.dsgc-search:focus-within{border-color:var(--dsw-alias-state-business-primary,#4f6ef7)}',
|
|
32
|
+
'.dsgc-tree{display:flex;flex-direction:column;gap:6px;flex:1;overflow-y:auto;min-height:0;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',
|
|
33
|
+
'.dsgc-grow-row{display:flex;align-items:center;gap:2px;min-width:0;border:none;background:none;border-radius:6px;padding:5px 6px;color:var(--dsw-alias-label-secondary,inherit);transition:background-color .12s,color .12s;cursor:pointer;font:inherit;text-align:left}',
|
|
34
|
+
'.dsgc-grow-row:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',
|
|
35
|
+
'.dsgc-grow-row.on{color:var(--dsw-alias-label-primary,inherit);font-weight:600}',
|
|
36
|
+
'.dsgc-twist{flex:none;width:16px;height:16px;border:none;background:none;color:inherit;cursor:pointer;padding:0;display:inline-flex;align-items:center;justify-content:center}',
|
|
37
|
+
'.dsgc-twist svg{transition:transform .16s ease}',
|
|
38
|
+
'.dsgc-twist.closed svg{transform:rotate(-90deg)}',
|
|
39
|
+
'.dsgc-gname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
|
40
|
+
'.dsgc-nodeops{display:none;gap:2px;flex:none}',
|
|
41
|
+
'.dsgc-grow-row:hover .dsgc-nodeops,.dsgc-sess-row:hover .dsgc-nodeops{display:inline-flex}',
|
|
42
|
+
'.dsgc-opbtn{border:none;background:none;color:var(--dsw-alias-label-tertiary,inherit);cursor:pointer;padding:2px;border-radius:4px;line-height:0;transition:background-color .12s,color .12s}',
|
|
43
|
+
'.dsgc-opbtn:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit)}',
|
|
44
|
+
'.dsgc-opbtn.danger{color:var(--dsw-alias-state-error-primary,#e5484d)}',
|
|
45
|
+
'.dsgc-sess-list{display:flex;flex-direction:column;gap:2px;margin:4px 0 2px 4px;padding-left:12px;border-left:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.15))}',
|
|
46
|
+
'.dsgc-sess-row{display:flex;align-items:center;gap:6px;min-width:0;border:none;background:none;border-radius:6px;padding:6px 8px;font-size:12.5px;line-height:1.5;color:var(--dsw-alias-label-secondary,inherit);transition:background-color .12s,color .12s;cursor:pointer;text-align:left;font-family:inherit}',
|
|
47
|
+
'.dsgc-sess-row:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',
|
|
48
|
+
'.dsgc-sess-row.on{background:var(--dsw-alias-interactive-bg-active,rgba(128,128,128,.2));color:var(--dsw-alias-label-primary,inherit);font-weight:600}',
|
|
49
|
+
'.dsgc-sess-status{flex:none;width:8px;height:8px;display:inline-flex;justify-content:center;align-items:center}',
|
|
50
|
+
'.dsgc-sess-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
|
51
|
+
'.dsgc-addsess{border:none;background:none;color:var(--dsw-alias-label-tertiary,inherit);cursor:pointer;text-align:left;font-size:12px;line-height:1.5;padding:5px 8px;border-radius:6px;transition:background-color .12s,color .12s;font-family:inherit;display:flex;align-items:center;gap:5px;white-space:nowrap;overflow:hidden}',
|
|
52
|
+
'.dsgc-addsess:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',
|
|
53
|
+
'.dsgc-rename{font:inherit;font-size:12.5px;min-width:0;flex:1;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-3,transparent));color:inherit;border-radius:6px;padding:1px 6px;outline:none;transition:border-color .16s}',
|
|
54
|
+
'.dsgc-rename:focus{border-color:var(--dsw-alias-state-business-primary,#4f6ef7)}',
|
|
55
|
+
'.dsgc-hint{font-size:12px;color:var(--dsw-alias-label-tertiary,inherit);line-height:1.5;text-wrap:balance}',
|
|
56
|
+
/* ===== 中央会话区 ===== */
|
|
57
|
+
'.dsgc-chat{flex:1;display:flex;flex-direction:column;min-width:0;min-height:0;position:relative}',
|
|
58
|
+
/* 接缝收合钮:钉在会话区两缘、垂直居中、各控其侧(图标方向相反的 chevron)。
|
|
59
|
+
宽模式下面板宽度过渡 → 中栏连续变宽,绝对定位的钮贴缘自动随接缝滑行(布局驱动);
|
|
60
|
+
窄模式右栏为覆盖层,钮用同曲线 right 过渡跟踪其左缘。浮层配方:实底 + border-l2 + 轻方向性软影 */
|
|
61
|
+
'.dsgc-seambtn{position:absolute;top:50%;transform:translateY(-50%);z-index:14;width:24px;height:56px;display:flex;align-items:center;justify-content:center;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-3,#fff);color:var(--dsw-alias-label-secondary,inherit);cursor:pointer;transition:background-color .12s,color .12s,border-color .12s,right .3s cubic-bezier(.16,1,.3,1)}',
|
|
62
|
+
'.dsgc-seambtn:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit);border-color:var(--dsw-alias-border-l3,rgba(128,128,128,.4))}',
|
|
63
|
+
'.dsgc-seambtn.left{left:0;border-left:none;border-radius:0 8px 8px 0;box-shadow:3px 0 10px rgba(0,0,0,.07)}',
|
|
64
|
+
'.dsgc-seambtn.right{right:0;border-right:none;border-radius:8px 0 0 8px;box-shadow:-3px 0 10px rgba(0,0,0,.07)}',
|
|
65
|
+
'.dsgc-chathead{display:flex;gap:10px;align-items:center;padding:12px 16px;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2))}',
|
|
66
|
+
'.dsgc-sess-title{flex:none;font-weight:600;font-size:14px;color:var(--dsw-alias-label-primary,inherit);max-width:30%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
|
67
|
+
'.dsgc-topic{flex:1;background:transparent;border:none;border-bottom:1px solid transparent;padding:2px;min-height:20px;color:var(--dsw-alias-label-secondary,inherit);font:inherit;outline:none;min-width:0;transition:color .12s,border-color .12s}',
|
|
68
|
+
'.dsgc-topic:hover{border-bottom-color:var(--dsw-alias-border-l2,rgba(128,128,128,.3))}',
|
|
69
|
+
'.dsgc-topic:focus{color:var(--dsw-alias-label-primary,inherit);border-bottom-color:var(--dsw-alias-state-business-primary,#4f6ef7)}',
|
|
70
|
+
'.dsgc-topic::placeholder{color:var(--dsw-alias-label-tertiary,inherit)}',
|
|
71
|
+
/* 清空按钮:破坏性操作的 hover/active 反馈——宿主 ghost hover 是低强度灰底(在本
|
|
72
|
+
面板底色上近透明、无感知),改为 danger 色文字 + 淡红底,与弹窗内 danger 确认
|
|
73
|
+
按钮同语言;特异性高于原语 .ghost:hover:not(:disabled) */
|
|
74
|
+
'.dsgc-chathead .dsgc-clearbtn{transition:background-color .12s,color .12s}',
|
|
75
|
+
'.dsgc-chathead .dsgc-clearbtn:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 10%,transparent);color:var(--dsw-alias-state-error-primary,#e5484d)}',
|
|
76
|
+
'.dsgc-chathead .dsgc-clearbtn:active:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 16%,transparent)}',
|
|
77
|
+
'.dsgc-msgs{flex:1;overflow-y:auto;padding:20px 24px 16px;display:flex;flex-direction:column;gap:16px;min-height:0;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',
|
|
78
|
+
'.dsgc-msg{display:flex;gap:10px;align-items:flex-start;max-width:100%;animation:dsgc-msg-in .22s cubic-bezier(.16,1,.3,1)}',
|
|
79
|
+
'.dsgc-msg.mine{flex-direction:row-reverse}',
|
|
80
|
+
'.dsgc-avatar{width:28px;height:28px;box-sizing:border-box;border:2px solid var(--dsw-alias-border-l3,rgba(128,128,128,.4));border-radius:50%;background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:600;flex:none;margin-top:1px}',
|
|
81
|
+
'.dsgc-avatar.mine{border-color:transparent;background:var(--dsw-alias-button-info-fill,#4f6ef7);color:var(--dsw-alias-label-primary-foreground,#fff)}',
|
|
82
|
+
'.dsgc-msgbody{max-width:76%;min-width:0;display:flex;flex-direction:column;gap:5px}',
|
|
83
|
+
'.dsgc-msg.mine .dsgc-msgbody{align-items:flex-end}',
|
|
84
|
+
'.dsgc-msghead{display:flex;gap:6px;align-items:center;min-width:0;font-size:12px;color:var(--dsw-alias-label-secondary,inherit)}',
|
|
85
|
+
'.dsgc-msgname{font-weight:600;color:var(--dsw-alias-label-primary,inherit);white-space:nowrap}',
|
|
86
|
+
'.dsgc-msgmodel{background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.12));border-radius:999px;padding:0 7px;font-size:10.5px;font-weight:500;line-height:16px;color:var(--dsw-alias-label-secondary,inherit);white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}',
|
|
87
|
+
'.dsgc-msgtime{font-size:10.5px;color:var(--dsw-alias-label-tertiary,inherit);white-space:nowrap}',
|
|
88
|
+
/* 流式「深度求索...」(对标宿主 TurnStatus「深度求索中...」签名动画):DeepSeek
|
|
89
|
+
品牌蓝渐变带扫过文字的微光——background-clip:text + background-position
|
|
90
|
+
1.8s linear 无限扫动;令牌取宿主静态品牌色 --dsw-static-deepseek-*(非主题
|
|
91
|
+
别名,回退为品牌字面值),贯穿首轮 token 前与流式全程 */
|
|
92
|
+
'.dsgc-typing{background:linear-gradient(90deg,var(--dsw-static-deepseek-500,#4176e6) 0%,var(--dsw-static-deepseek-500,#4176e6) 40%,var(--dsw-static-deepseek-200,#d3e2ff) 50%,var(--dsw-static-deepseek-500,#4176e6) 60%,var(--dsw-static-deepseek-500,#4176e6) 100%);color:#0000;-webkit-text-fill-color:transparent;background-position:100% 0;background-size:250% 100%;-webkit-background-clip:text;background-clip:text;font-weight:600;animation:dsgc-typing-shimmer 1.2s linear infinite}',
|
|
93
|
+
'@keyframes dsgc-typing-shimmer{to{background-position:0 0}}',
|
|
94
|
+
'.dsgc-msgtext{background:var(--dsw-alias-bg-layer-3,rgba(128,128,128,.06));border:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.15));padding:10px 14px;border-radius:12px;line-height:1.6;text-align:left;color:var(--dsw-alias-label-primary,inherit);min-width:0;overflow-wrap:anywhere}',
|
|
95
|
+
'.dsgc-msg.mine .dsgc-msgtext{background:var(--dsw-alias-button-info-fill,#4f6ef7);border-color:transparent;color:var(--dsw-alias-label-primary-foreground,#fff);white-space:pre-wrap;word-break:break-word}',
|
|
96
|
+
'.dsgc-msgtext.live{opacity:.92}',
|
|
97
|
+
'.dsgc-msg.live .dsgc-avatar{--presence-ring:color-mix(in srgb,var(--role-color,#4f6ef7) 22%,transparent);animation:dsgc-presence 1.8s ease-in-out infinite}',
|
|
98
|
+
'.dsgc-think{margin:2px 0}',
|
|
99
|
+
'.dsgc-think .dsgc-thinkrow{font-size:12px;color:var(--dsw-alias-label-secondary,inherit);border-radius:8px;padding:3px 8px;transition:background-color .12s}',
|
|
100
|
+
'.dsgc-think .dsgc-thinkrow:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.1))}',
|
|
101
|
+
'.dsgc-think .dsgc-thinksummary{color:var(--dsw-alias-label-tertiary,inherit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:44ch;font-size:11.5px;margin-left:6px}',
|
|
102
|
+
'.dsgc-think .dsgc-thinkbody{font-size:12.5px;line-height:1.7;color:var(--dsw-alias-label-secondary,inherit);white-space:pre-wrap;word-break:break-word;border-left:2px solid var(--dsw-alias-border-l2,rgba(128,128,128,.25));margin:2px 0 4px;padding:2px 0 2px 10px;max-height:320px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent;animation:dsgc-think-in .2s ease-out}',
|
|
103
|
+
/* 首 delta 前的「思考中」占位行:ThinkRow 同语言(思考图标 + 次要色 12px 小字)
|
|
104
|
+
+ 三点交错呼吸动画——深度思考模型首字节可能等数秒到数十秒,空白气泡会被
|
|
105
|
+
感知为卡死;delta 到达后被真实思考行/正文自然替换 */
|
|
106
|
+
'.dsgc-pending{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--dsw-alias-label-secondary,inherit)}',
|
|
107
|
+
'.dsgc-pending svg{flex:none}',
|
|
108
|
+
'.dsgc-pendingdots{display:inline-flex;gap:2px;align-items:center}',
|
|
109
|
+
'.dsgc-pendingdots i{width:3px;height:3px;border-radius:50%;background:currentColor;opacity:.3;animation:dsgc-dot-breathe 1.2s ease-in-out infinite}',
|
|
110
|
+
'.dsgc-pendingdots i:nth-child(2){animation-delay:.2s}',
|
|
111
|
+
'.dsgc-pendingdots i:nth-child(3){animation-delay:.4s}',
|
|
112
|
+
'@keyframes dsgc-dot-breathe{0%,100%{opacity:.25}50%{opacity:1}}',
|
|
113
|
+
'.dsgc-sysmsg{align-self:center;font-size:11.5px;color:var(--dsw-alias-label-secondary,inherit);background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.1));border-radius:999px;padding:2px 10px;text-align:center;max-width:90%;animation:dsgc-sys-in .24s ease-out}',
|
|
114
|
+
/* ===== 工具调用行 / 确认卡片(对标思考折叠语言) ===== */
|
|
115
|
+
'.dsgc-tool{margin:2px 0}',
|
|
116
|
+
'.dsgc-tool .dsgc-toolrow{font-size:12px;color:var(--dsw-alias-label-secondary,inherit);border-radius:8px;padding:3px 8px;transition:background-color .12s}',
|
|
117
|
+
'.dsgc-tool .dsgc-toolrow:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.1))}',
|
|
118
|
+
'.dsgc-tool .dsgc-toolsummary{color:var(--dsw-alias-label-tertiary,inherit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:40ch;font-size:11.5px;margin-left:6px}',
|
|
119
|
+
'.dsgc-tool .dsgc-toolbody{font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,inherit);white-space:pre-wrap;word-break:break-word;border-left:2px solid var(--dsw-alias-border-l2,rgba(128,128,128,.25));margin:2px 0 4px;padding:2px 0 2px 10px;max-height:260px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',
|
|
120
|
+
'.dsgc-confirm{border:1px solid var(--dsw-alias-state-business-primary,#4f6ef7);border-radius:12px;background:var(--dsw-alias-bg-layer-3,rgba(128,128,128,.06));padding:10px 12px;display:flex;flex-direction:column;gap:8px;max-width:76%;animation:dsgc-fade-in .18s ease-out}',
|
|
121
|
+
'.dsgc-confirmtitle{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary,inherit);display:flex;align-items:center;gap:6px}',
|
|
122
|
+
'.dsgc-confirmcmd{font-size:12px;line-height:1.6;white-space:pre-wrap;word-break:break-word;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));border-radius:8px;padding:8px 10px;background:var(--dsw-alias-bg-layer-2,transparent);color:var(--dsw-alias-label-primary,inherit);max-height:240px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',
|
|
123
|
+
'.dsgc-confirmops{display:flex;gap:8px;justify-content:flex-end}',
|
|
124
|
+
'.dsgc-sysmsg.err{color:var(--dsw-alias-state-error-primary,#e5484d)}',
|
|
125
|
+
/* 清空确认弹窗内的说明列表 */
|
|
126
|
+
'.dsgc-clearnotes{margin:0;padding-left:18px;font-size:13px;line-height:1.8;color:var(--dsw-alias-label-secondary,inherit);display:flex;flex-direction:column;gap:2px}',
|
|
127
|
+
'.dsgc-err{font-size:12px;color:var(--dsw-alias-state-error-primary,#e5484d);animation:dsgc-fade-in .18s ease-out}',
|
|
128
|
+
'.dsgc-empty{margin:auto;display:flex;flex-direction:column;align-items:center;gap:10px;color:var(--dsw-alias-label-tertiary,inherit);text-align:center;max-width:40ch;padding:24px;animation:dsgc-fade-in .3s ease-out}',
|
|
129
|
+
'.dsgc-empty svg{opacity:.5}',
|
|
130
|
+
'.dsgc-empty .dsgc-emptytitle{font-size:13px;font-weight:600;color:var(--dsw-alias-label-secondary,inherit)}',
|
|
131
|
+
'.dsgc-empty .dsgc-hint{text-wrap:balance}',
|
|
132
|
+
'.dsgc-tobottom{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);z-index:12;animation:dsgc-rise-in .18s cubic-bezier(.16,1,.3,1)}',
|
|
133
|
+
/* 回到底部:实底浮动胶囊(@弹层同款浮层配方——实底 + border-l2 + shadow-lv3),不与消息内容相互透底 */
|
|
134
|
+
'.dsgc-tobtn{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-3,#fff);color:var(--dsw-alias-label-secondary,inherit);border-radius:999px;padding:5px 12px;font:inherit;font-size:12px;line-height:1.4;cursor:pointer;box-shadow:var(--dsw-shadow-lv3,0 8px 24px rgba(0,0,0,.18));transition:color .12s,border-color .12s}',
|
|
135
|
+
'.dsgc-tobtn:hover{color:var(--dsw-alias-label-primary,inherit);border-color:var(--dsw-alias-border-l3,rgba(128,128,128,.4))}',
|
|
136
|
+
/* ===== composer ===== */
|
|
137
|
+
'.dsgc-composer{padding:12px 16px 14px;display:flex;flex-direction:column;gap:10px;position:relative}',
|
|
138
|
+
/* 输入卡(对标主会话 composer 卡):22px 圆角独立卡、input-major 实底、
|
|
139
|
+
elevation-soft 软影(DESIGN.md 输入面豁免——输入面遵循宿主输入面语言,
|
|
140
|
+
其余静止表面仍零阴影);chips 等配置行留卡外 */
|
|
141
|
+
'.dsgc-card{background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-3,transparent));--dsw-elevation-stroke-color:var(--dsw-alias-border-l2,rgba(128,128,128,.3));box-shadow:var(--dsw-elevation-soft,0 1px 3px rgba(0,0,0,.08));border-radius:22px;padding:8px 0 0;display:flex;flex-direction:column;gap:8px;position:relative}',
|
|
142
|
+
/* 输入区:非受控 contenteditable(React 不管子节点);白空间与换行规则
|
|
143
|
+
与序列化契约对齐(pre-wrap + <br>→\n) */
|
|
144
|
+
'.dsgc-edit{display:block;box-sizing:border-box;width:100%;min-height:36px;max-height:180px;overflow-y:auto;outline:none;white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;font:inherit;font-size:13px;line-height:24px;color:var(--dsw-alias-label-primary,inherit);caret-color:var(--dsw-alias-state-business-primary,#4f6ef7);scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent;position:relative;z-index:1}',
|
|
145
|
+
'.dsgc-card .dsgc-edit{padding:6px 8px 0 14px}',
|
|
146
|
+
/* 占位符 = 独立覆盖层(对齐主会话):不用 ::before——生成内容会把聚焦光标
|
|
147
|
+
顶到占位文字之后;覆盖层 pointer-events:none 不参与光标布局,
|
|
148
|
+
与输入区同 padding 基准(左 14 / 上 6) */
|
|
149
|
+
'.dsgc-ph{position:absolute;left:14px;top:6px;max-width:calc(100% - 22px);color:var(--dsw-alias-label-tertiary,inherit);pointer-events:none;user-select:none;font-size:13px;line-height:24px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}',
|
|
150
|
+
/* @提及芯片(输入区内原子元素):色点 + 角色色淡底胶囊——弹层候选行同语言 */
|
|
151
|
+
'.dsgc-chipin{display:inline-flex;align-items:center;gap:4px;background:color-mix(in srgb,var(--role-color,#888) 15%,transparent);border-radius:999px;padding:1px 7px 1px 5px;margin:0 1px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary,inherit);white-space:nowrap;user-select:all}',
|
|
152
|
+
'.dsgc-card .dsgc-sendrow{padding:0 12px 10px}',
|
|
153
|
+
'.dsgc-stopbtn{background:var(--dsw-alias-state-error-primary,#e5484d);border-color:transparent;color:#fff;font-weight:600}',
|
|
154
|
+
'.dsgc-stopbtn:hover:not(:disabled){filter:brightness(1.08);color:#fff}',
|
|
155
|
+
'.dsgc-parts{display:flex;gap:6px;flex-wrap:wrap;align-items:center;row-gap:4px;height:24px}',
|
|
156
|
+
'.dsgc-partslabel{font-size:12px;color:var(--dsw-alias-label-tertiary,inherit);flex:none}',
|
|
157
|
+
'.dsgc-partchip{display:inline-flex;gap:6px;align-items:center;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:transparent;color:var(--dsw-alias-label-secondary,inherit);border-radius:999px;padding:2px 10px;font-size:12px;line-height:1.5;cursor:pointer;transition:background-color .12s,color .12s,border-color .12s;font-family:inherit}',
|
|
158
|
+
'.dsgc-partchip:hover{color:var(--dsw-alias-label-primary,inherit)}',
|
|
159
|
+
'.dsgc-partchip.on{background:var(--dsw-alias-interactive-bg-active,rgba(128,128,128,.18));color:var(--dsw-alias-label-primary,inherit);border-color:var(--dsw-alias-border-l2,rgba(128,128,128,.3))}',
|
|
160
|
+
'.dsgc-partchip:disabled{opacity:.5;cursor:default}',
|
|
161
|
+
'.dsgc-chipdot{width:8px;height:8px;border-radius:50%;flex:none;display:inline-block}',
|
|
162
|
+
'.dsgc-sendrow{display:flex;gap:8px;align-items:center;justify-content:flex-end}',
|
|
163
|
+
'.dsgc-sendrow button{white-space:nowrap}',
|
|
164
|
+
/* ===== 权限档位选择器(对齐主会话 composer 左下角芯片) ===== */
|
|
165
|
+
'.dsgc-permtrigger{min-width:0;max-width:220px;height:28px;color:var(--dsw-alias-label-secondary,inherit);cursor:pointer;background:transparent;border:none;border-radius:999px;outline:none;align-items:center;gap:4px;padding:0 4px 0 8px;font-size:13px;font-weight:500;line-height:20px;display:inline-flex;font-family:inherit;transition:background-color .12s,color .12s}',
|
|
166
|
+
'.dsgc-permtrigger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit)}',
|
|
167
|
+
'.dsgc-permtrigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3,rgba(128,128,128,.4))}',
|
|
168
|
+
'.dsgc-permtrigger:disabled{color:var(--dsw-alias-label-dimmed,inherit);cursor:default}',
|
|
169
|
+
'.dsgc-permicon{flex:none;display:inline-flex}',
|
|
170
|
+
'.dsgc-permicon svg{width:14px;height:14px}',
|
|
171
|
+
'.dsgc-permlabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}',
|
|
172
|
+
'.dsgc-permchevron{color:var(--dsw-alias-label-caption,inherit);flex:none;transition:transform .12s;display:inline-flex}',
|
|
173
|
+
'.dsgc-permchevron.open{transform:rotate(180deg)}',
|
|
174
|
+
'.dsgc-rounds{display:flex;gap:2px;align-items:center;font-size:12px;color:var(--dsw-alias-label-secondary,inherit);flex:none;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));border-radius:8px;padding:2px}',
|
|
175
|
+
'.dsgc-rounds .dsgc-roundbtn{border:none;background:none;color:var(--dsw-alias-label-secondary,inherit);cursor:pointer;padding:3px;border-radius:5px;line-height:0;transition:background-color .12s,color .12s}',
|
|
176
|
+
'.dsgc-rounds .dsgc-roundbtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit)}',
|
|
177
|
+
'.dsgc-rounds .dsgc-roundbtn:disabled{opacity:.4;cursor:default}',
|
|
178
|
+
'.dsgc-rounds .dsgc-roundnum{width:26px;text-align:center;font-variant-numeric:tabular-nums;font-weight:600;color:var(--dsw-alias-label-primary,inherit)}',
|
|
179
|
+
/* ===== @成员 / @文件弹层 ===== */
|
|
180
|
+
'.dsgc-mentionwrap{position:relative}',
|
|
181
|
+
'.dsgc-mention{animation:dsgc-pop-in .16s cubic-bezier(.16,1,.3,1);position:absolute;left:0;right:0;bottom:calc(100% + 6px);background:var(--dsw-alias-bg-layer-3,#fff);border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));border-radius:10px;box-shadow:var(--dsw-shadow-lv3,0 8px 24px rgba(0,0,0,.18));max-height:220px;overflow-y:auto;padding:4px;z-index:30;display:flex;flex-direction:column;gap:2px;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',
|
|
182
|
+
'.dsgc-mentionitem{display:flex;align-items:center;gap:8px;border:none;background:none;color:var(--dsw-alias-label-secondary,inherit);font:inherit;font-size:12.5px;text-align:left;cursor:pointer;padding:6px 8px;border-radius:6px;transition:background-color .12s,color .12s}',
|
|
183
|
+
'.dsgc-mentionitem.on,.dsgc-mentionitem:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit)}',
|
|
184
|
+
'.dsgc-mentionname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}',
|
|
185
|
+
'.dsgc-mentionmodel{font-size:11px;color:var(--dsw-alias-label-tertiary,inherit)}',
|
|
186
|
+
'.dsgc-mentionhint{font-size:11px;color:var(--dsw-alias-label-tertiary,inherit);padding:2px 8px 1px}',
|
|
187
|
+
'.dsgc-mention-file .dsgc-mentionitem.dsgc-hint{cursor:default;color:var(--dsw-alias-label-tertiary,inherit);justify-content:center}',
|
|
188
|
+
'.dsgc-mention-file .dsgc-mentionitem.dsgc-hint:hover{background:none}',
|
|
189
|
+
/* 文件检索:宿主 FileTypeIcon 分色字形 + 井位底,文件夹/文件扫一眼可分 */
|
|
190
|
+
'.dsgc-fileglyph{flex:none;width:22px;height:22px;display:inline-flex;align-items:center;justify-content:center;border-radius:5px}',
|
|
191
|
+
'.dsgc-fileglyph.dir{background:color-mix(in srgb,var(--dsw-static-amber-400,#e8912d) 16%,transparent)}',
|
|
192
|
+
'.dsgc-fileglyph.file{background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.12))}',
|
|
193
|
+
'.dsgc-filedrill{flex:none;display:inline-flex;color:var(--dsw-alias-label-tertiary,inherit)}',
|
|
194
|
+
'.dsgc-mentionitem.on .dsgc-filedrill,.dsgc-mentionitem:hover .dsgc-filedrill{color:var(--dsw-alias-label-secondary,inherit)}',
|
|
195
|
+
'.dsgc-chipin-file{background:color-mix(in srgb,var(--dsw-static-neutral-bluish-300,rgba(128,128,128,.55)) 18%,transparent)}',
|
|
196
|
+
'.dsgc-chipin-file[data-dir="1"]{background:color-mix(in srgb,var(--dsw-static-amber-400,#e8912d) 18%,transparent)}',
|
|
197
|
+
'.dsgc-chipglyph{flex:none;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center;overflow:hidden}',
|
|
198
|
+
'.dsgc-chipglyph svg{display:block}',
|
|
199
|
+
/* ===== 右上下文栏 ===== */
|
|
200
|
+
'.dsgc-aside{width:304px;flex:none;display:flex;flex-direction:column;gap:10px;border-left:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2));padding:12px;min-height:0;overflow-y:auto;overflow-x:hidden;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent;transition:width .28s cubic-bezier(.16,1,.3,1),opacity .18s ease,padding .28s cubic-bezier(.16,1,.3,1),border-left-width .28s cubic-bezier(.16,1,.3,1)}',
|
|
201
|
+
/* 子元素经 flex 列默认 stretch 填满内容区(面板为 content-box、内容区实宽
|
|
202
|
+
304px;旧版写死 280px 曾致右侧多出 24px 死区) */
|
|
203
|
+
'.dsgc-aside>*{flex:none}',
|
|
204
|
+
'.dsgc-aside.closed{width:0;opacity:0;padding-left:0;padding-right:0;border-left-width:0;visibility:hidden;transition:width .24s ease-in,opacity .16s ease-in,padding .24s ease-in,border-left-width .24s ease-in,visibility 0s .22s}',
|
|
205
|
+
'.dsgc-sec{display:flex;flex-direction:column;gap:8px;flex:none}',
|
|
206
|
+
'.dsgc-sechead{display:flex;align-items:center;gap:6px;font-weight:600;font-size:12px;color:var(--dsw-alias-label-tertiary,inherit);padding-top:2px}',
|
|
207
|
+
'.dsgc-sechead .dsgc-secspacer{flex:1}',
|
|
208
|
+
'.dsgc-seccount{font-weight:500;color:var(--dsw-alias-label-tertiary,inherit)}',
|
|
209
|
+
'.dsgc-roles{display:flex;flex-direction:column;gap:8px}',
|
|
210
|
+
'.dsgc-role{border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-3,transparent);border-radius:12px;padding:10px 12px;display:flex;flex-direction:column;gap:7px;transition:border-color .16s,background-color .16s;list-style:none;text-align:left;font:inherit;cursor:pointer;color:inherit}',
|
|
211
|
+
'.dsgc-role:hover{border-color:var(--dsw-alias-label-dimmed,rgba(128,128,128,.5))}',
|
|
212
|
+
'.dsgc-rolehead{display:flex;gap:8px;align-items:center}',
|
|
213
|
+
'.dsgc-roledot{width:10px;height:10px;border-radius:50%;flex:none}',
|
|
214
|
+
'.dsgc-rolename{font-weight:600;font-size:13px;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary,inherit)}',
|
|
215
|
+
'.dsgc-role.off .dsgc-rolename{color:var(--dsw-alias-label-tertiary,inherit)}',
|
|
216
|
+
'.dsgc-rolepersona{font-size:11.5px;color:var(--dsw-alias-label-tertiary,inherit);line-height:1.5;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:0}',
|
|
217
|
+
'.dsgc-rolemodel{width:fit-content;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.12));border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px;color:var(--dsw-alias-label-secondary,inherit)}',
|
|
218
|
+
'.dsgc-roleops{display:flex;gap:2px;flex:none;opacity:0;transition:opacity .12s}',
|
|
219
|
+
'.dsgc-role:hover .dsgc-roleops,.dsgc-role:focus-within .dsgc-roleops{opacity:1}',
|
|
220
|
+
'.dsgc-rolemenu{display:flex;align-items:center;justify-content:space-between;gap:8px}',
|
|
221
|
+
/* ===== 表单与控件(角色抽屉内) ===== */
|
|
222
|
+
'.dsgc-field{display:flex;flex-direction:column;gap:5px}',
|
|
223
|
+
'.dsgc-field>label{font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary,inherit)}',
|
|
224
|
+
'.dsgc-input,.dsgc-select,.dsgc-textarea{background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-3,transparent));border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));color:var(--dsw-alias-label-primary,inherit);font:inherit;font-size:13px;border-radius:8px;padding:6px 10px;width:100%;box-sizing:border-box;outline:none;transition:border-color .16s,background-color .16s}',
|
|
225
|
+
'.dsgc-input:focus,.dsgc-select:focus,.dsgc-textarea:focus{border-color:var(--dsw-alias-state-business-primary,#4f6ef7)}',
|
|
226
|
+
'.dsgc-input::placeholder,.dsgc-textarea::placeholder{color:var(--dsw-alias-label-tertiary,inherit)}',
|
|
227
|
+
'.dsgc-textarea{resize:vertical;min-height:76px}',
|
|
228
|
+
'.dsgc-palette{display:flex;gap:6px;flex-wrap:wrap}',
|
|
229
|
+
'.dsgc-dot{width:18px;height:18px;border-radius:50%;border:2px solid transparent;cursor:pointer;padding:0;transition:transform .12s}',
|
|
230
|
+
'.dsgc-dot:hover{transform:scale(1.12)}',
|
|
231
|
+
'.dsgc-dot.on{border-color:var(--dsw-alias-label-primary,#fff)}',
|
|
232
|
+
'.dsgc-form{display:flex;flex-direction:column;gap:12px}',
|
|
233
|
+
'.dsgc-formerr{font-size:12px;color:var(--dsw-alias-state-error-primary,#e5484d);line-height:1.5}',
|
|
234
|
+
'.dsgc-selhint{font-size:12px;color:var(--dsw-alias-label-tertiary,inherit);line-height:1.5;display:flex;gap:6px;align-items:center;flex-wrap:wrap}',
|
|
235
|
+
/* ===== 角色编辑抽屉(右侧滑出) ===== */
|
|
236
|
+
'.dsgc-drawer{position:absolute;top:0;right:0;bottom:0;width:380px;max-width:calc(100% - 40px);z-index:20;background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-bg-base,#fff));border-left:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));box-shadow:-12px 0 32px rgba(0,0,0,.14);display:flex;flex-direction:column;animation:dsgc-drawer-in .22s cubic-bezier(.16,1,.3,1)}',
|
|
237
|
+
'.dsgc-drawer.closing{animation:dsgc-drawer-out .14s ease-in forwards;pointer-events:none}',
|
|
238
|
+
'@keyframes dsgc-drawer-in{from{transform:translateX(32px);opacity:0}to{transform:none;opacity:1}}',
|
|
239
|
+
'@keyframes dsgc-drawer-out{to{transform:translateX(32px);opacity:0}}',
|
|
240
|
+
'@keyframes dsgc-msg-in{from{opacity:0;transform:translateY(6px)}}',
|
|
241
|
+
'@keyframes dsgc-sys-in{from{opacity:0;transform:scale(.96)}}',
|
|
242
|
+
'@keyframes dsgc-think-in{from{opacity:0;transform:translateY(-3px)}}',
|
|
243
|
+
'@keyframes dsgc-pop-in{from{opacity:0;transform:translateY(4px)}}',
|
|
244
|
+
'@keyframes dsgc-rise-in{from{opacity:0;transform:translate(-50%,6px)}}',
|
|
245
|
+
'@keyframes dsgc-fade-in{from{opacity:0}}',
|
|
246
|
+
'@keyframes dsgc-presence{0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--role-color,#4f6ef7) 0%,transparent)}50%{box-shadow:0 0 0 4px var(--presence-ring)}}',
|
|
247
|
+
'.dsgc-drawerhead{display:flex;align-items:center;gap:8px;padding:14px 16px;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2));flex:none}',
|
|
248
|
+
'.dsgc-drawertitle{flex:1;font-size:14px;font-weight:600;color:var(--dsw-alias-label-primary,inherit)}',
|
|
249
|
+
'.dsgc-drawerbody{flex:1;overflow-y:auto;padding:16px;min-height:0;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',
|
|
250
|
+
'.dsgc-drawerfoot{display:flex;gap:8px;justify-content:flex-end;padding:12px 16px;border-top:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2));flex:none}',
|
|
251
|
+
/* ===== 文件浏览器(目录选择) ===== */
|
|
252
|
+
'.dsgc-fb{border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-2,transparent);border-radius:8px;display:flex;flex-direction:column;gap:6px;padding:8px;animation:dsgc-fade-in .2s ease-out}',
|
|
253
|
+
'.dsgc-fbhead{display:flex;align-items:center;justify-content:space-between;gap:8px;min-width:0}',
|
|
254
|
+
'.dsgc-fbhead button{flex:none;white-space:nowrap}',
|
|
255
|
+
'.dsgc-wsrow{display:flex;gap:6px;align-items:center;min-width:0}',
|
|
256
|
+
'.dsgc-wsrow .dsgc-input{width:auto;flex:1;min-width:0}',
|
|
257
|
+
'.dsgc-wsrow>button{flex:none;white-space:nowrap}',
|
|
258
|
+
'.dsgc-nav>button{white-space:nowrap;overflow:hidden}',
|
|
259
|
+
'.dsgc-fbpath{flex:1;min-width:0;font-size:11px;color:var(--dsw-alias-label-secondary,inherit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
|
260
|
+
'.dsgc-fblist{display:flex;flex-direction:column;gap:1px;max-height:220px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',
|
|
261
|
+
'.dsgc-fbrow{display:flex;align-items:center;gap:7px;width:100%;border:none;background:none;color:var(--dsw-alias-label-primary,inherit);font:inherit;font-size:12.5px;text-align:left;cursor:pointer;padding:3px 8px;border-radius:6px;transition:background-color .12s}',
|
|
262
|
+
'.dsgc-fbrow:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15))}',
|
|
263
|
+
'.dsgc-fbrow.dim{opacity:.55}',
|
|
264
|
+
'.dsgc-fbrow.file{cursor:default}',
|
|
265
|
+
'.dsgc-fbrow.file:hover{background:none}',
|
|
266
|
+
'.dsgc-fbname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
|
267
|
+
'.dsgc-fbsize{flex:none;font-size:10.5px;color:var(--dsw-alias-label-tertiary,inherit)}',
|
|
268
|
+
/* ===== 键盘焦点 ===== */
|
|
269
|
+
'.dsgc-partchip:focus-visible,.dsgc-mentionitem:focus-visible,.dsgc-dot:focus-visible,.dsgc-opbtn:focus-visible,.dsgc-twist:focus-visible,.dsgc-addsess:focus-visible,.dsgc-grow-row:focus-visible,.dsgc-sess-row:focus-visible,.dsgc-rename:focus-visible,.dsgc-fbrow:focus-visible,.dsgc-role:focus-visible,.dsgc-roundbtn:focus-visible,.dsgc-tobtn:focus-visible,.dsgc-seambtn:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,var(--dsw-alias-state-business-primary,#4f6ef7));outline-offset:1px}',
|
|
270
|
+
/* ===== 窄容器:右栏覆盖式呈现 ===== */
|
|
271
|
+
'@container (max-width: 880px){.dsgc-aside{position:absolute;top:0;right:0;bottom:0;z-index:15;width:min(304px,88%);box-shadow:-12px 0 32px rgba(0,0,0,.16);border-left:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));transition:transform .3s cubic-bezier(.16,1,.3,1),opacity .2s ease}.dsgc-aside.closed{width:min(304px,88%);padding-left:12px;padding-right:12px;border-left-width:1px;transform:translateX(calc(100% + 14px));opacity:0;transition:transform .26s ease-in,opacity .18s ease-in,visibility 0s .24s}.dsgc-seambtn.right:not(.closed){right:min(304px,88%)}}',
|
|
272
|
+
'@container (max-width: 640px){.dsgc-nav{width:200px}.dsgc-msgbody{max-width:88%}}',
|
|
273
|
+
/* ===== 侧边栏入口对齐(外壳将插槽内容包在 panelGlyph span 内,必须用后代 :has) ===== */
|
|
274
|
+
'[class*="panelList"]:has(.dsgc-entryOverlay){margin-top:4px}',
|
|
275
|
+
'[class*="panelRow"]:has(.dsgc-entryOverlay){position:relative;box-sizing:border-box;height:36px;min-height:36px;padding:0 10px;font-size:13px;transition:background-color .12s,color .12s}',
|
|
276
|
+
'[class*="panelRow"][class*="panelActive"]:has(.dsgc-entryOverlay){font-weight:600}',
|
|
277
|
+
/* 入口 hover:宿主 panelRow:hover 只给灰底、不变文字色(低强度到近无感);
|
|
278
|
+
对齐任务看板入口行——hover 灰底 + 文字/图标转 label-primary */
|
|
279
|
+
'[class*="panelRow"]:has(.dsgc-entryOverlay):hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',
|
|
280
|
+
/* DOM 注入式全幅视图(任务看板 data-dsh-taskboard-active / SSH data-dsh-ssh-active)
|
|
281
|
+
激活时接管中央列:外壳面板状态机未变(activePanelId 仍指向群聊),但视图已被
|
|
282
|
+
覆盖——群聊入口随之视觉复位,避免停留“激活”态误导当前所在视图。两行特异性
|
|
283
|
+
相同(0,4,1),hover 行在后,复位不吞 hover 反馈 */
|
|
284
|
+
'html[data-dsh-taskboard-active] [class*="panelRow"][class*="panelActive"]:has(.dsgc-entryOverlay),html[data-dsh-ssh-active] [class*="panelRow"][class*="panelActive"]:has(.dsgc-entryOverlay){background:transparent;color:var(--dsw-alias-label-secondary,inherit);font-weight:400}',
|
|
285
|
+
'html[data-dsh-taskboard-active] [class*="panelRow"]:has(.dsgc-entryOverlay):hover,html[data-dsh-ssh-active] [class*="panelRow"]:has(.dsgc-entryOverlay):hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',
|
|
286
|
+
/* 收起态例外:外壳把收起栏所有面板图标统一为 primary 色(激活与否不由颜色表达),
|
|
287
|
+
复位规则不得把群聊图标调暗成 secondary;仅去掉激活底色即可 */
|
|
288
|
+
'html[data-dsh-taskboard-active] [data-sidebar-collapsed] [class*="panelRow"]:has(.dsgc-entryOverlay),html[data-dsh-ssh-active] [data-sidebar-collapsed] [class*="panelRow"]:has(.dsgc-entryOverlay),html[data-dsh-taskboard-active] [class*="collapsed"] [class*="panelRow"]:has(.dsgc-entryOverlay),html[data-dsh-ssh-active] [class*="collapsed"] [class*="panelRow"]:has(.dsgc-entryOverlay){color:var(--dsw-alias-label-primary,inherit)}',
|
|
289
|
+
'[class*="panelRow"]:has(.dsgc-entryOverlay) > [class*="panelTitle"]{padding-left:24px}',
|
|
290
|
+
'.dsgc-entryOverlay{position:absolute;inset:0;display:flex;align-items:center;padding:0 10px;box-sizing:border-box}',
|
|
291
|
+
'.dsgc-entryIcon{flex:none;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center}',
|
|
292
|
+
'.dsgc-entryIcon svg{width:18px;height:18px;display:block}',
|
|
293
|
+
'[data-sidebar-collapsed] .dsgc-entryOverlay,[class*="collapsed"] .dsgc-entryOverlay{justify-content:center;padding:0}',
|
|
294
|
+
'[data-sidebar-collapsed] [class*="panelRow"]:has(.dsgc-entryOverlay),[class*="collapsed"] [class*="panelRow"]:has(.dsgc-entryOverlay){margin:0 auto}',
|
|
295
|
+
'@media (prefers-reduced-motion:reduce){.dsgc-dot,.dsgc-partchip,.dsgc-mentionitem,.dsgc-grow-row,.dsgc-sess-row,.dsgc-opbtn,.dsgc-addsess,.dsgc-topic,.dsgc-role,.dsgc-rename,.dsgc-input,.dsgc-select,.dsgc-textarea,.dsgc-fbrow,.dsgc-twist svg,.dsgc-roleops,.dsgc-roundbtn,.dsgc-permtrigger,.dsgc-permchevron,.dsgc-tobtn,.dsgc-seambtn,.dsgc-aside,.dsgc-aside.closed,.dsgc-nav,.dsgc-nav.closed,.dsgc-clearbtn,[class*="panelRow"]:has(.dsgc-entryOverlay){transition:none}.dsgc-dot:hover{transform:none}.dsgc-drawer,.dsgc-msg,.dsgc-sysmsg,.dsgc-mention,.dsgc-tobottom,.dsgc-err,.dsgc-empty,.dsgc-fb,.dsgc-think .dsgc-thinkbody,.dsgc-msg.live .dsgc-avatar,.dsgc-loading svg,.dsgc-pendingdots i,.dsgc-typing{animation:none}.dsgc-typing{background-position:0 0;background-size:100% 100%}}',
|
|
296
|
+
/* ===== 设置页(同一卡片语言) ===== */
|
|
297
|
+
'.dgcs-page{display:flex;flex-direction:column;gap:14px;padding:4px 0}',
|
|
298
|
+
'.dgcs-head{display:flex;flex-direction:column;gap:6px}',
|
|
299
|
+
'.dgcs-title{margin:0;font-size:15px;font-weight:600;line-height:1.4;color:var(--dsw-alias-label-primary,inherit)}',
|
|
300
|
+
'.dgcs-desc{margin:0;font-size:13px;line-height:1.6;color:var(--dsw-alias-label-secondary,inherit)}',
|
|
301
|
+
'.dgcs-card{display:flex;align-items:center;justify-content:space-between;gap:12px;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-3,transparent);border-radius:12px;padding:14px 16px;transition:border-color .16s}',
|
|
302
|
+
'.dgcs-cardtext{display:flex;flex-direction:column;gap:3px;min-width:0}',
|
|
303
|
+
'.dgcs-cardtitle{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary,inherit)}',
|
|
304
|
+
'.dgcs-cardhint{font-size:12px;color:var(--dsw-alias-label-tertiary,inherit)}',
|
|
305
|
+
].join('\n')
|
|
306
|
+
|
|
307
|
+
/** 工厂执行时幂等注入样式标签(loader 卸载时按 data-plugin 摘除)。 */
|
|
308
|
+
export function injectStyles(): void {
|
|
309
|
+
if (typeof document === 'undefined') return
|
|
310
|
+
if (document.querySelector('style[data-plugin-css=' + JSON.stringify(TAG_ID) + ']') === null) {
|
|
311
|
+
const tag = document.createElement('style')
|
|
312
|
+
tag.dataset.plugin = 'dsh-group-chat'
|
|
313
|
+
tag.dataset.pluginCss = TAG_ID
|
|
314
|
+
tag.textContent = CSS
|
|
315
|
+
document.head.appendChild(tag)
|
|
316
|
+
}
|
|
317
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 浏览器半 UI 基座:DSW 原语(shell 静态种子模块,loader 模块表 external)
|
|
3
|
+
* 与动态图标 / 命令式 createElement 辅助。组件主体已 JSX 化(.tsx);此处
|
|
4
|
+
* 仅保留 slot 注册回调与动态图标表需要的少量命令式辅助。
|
|
5
|
+
* @module dsh-group-chat/client/ui
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createElement, type ReactNode } from 'react'
|
|
9
|
+
import * as P from '@deepseek-ai/dsh-client-ui-primitives'
|
|
10
|
+
|
|
11
|
+
export { P }
|
|
12
|
+
|
|
13
|
+
/** 命令式 createElement(仅 slot 注册回调用)。 */
|
|
14
|
+
export const h = createElement as unknown as (type: unknown, props?: Record<string, unknown> | null, ...children: unknown[]) => ReactNode
|
|
15
|
+
|
|
16
|
+
/** 图标组件的调用形态。 */
|
|
17
|
+
export type IconComponent = (props: Record<string, unknown>) => ReactNode
|
|
18
|
+
|
|
19
|
+
/** 按名取 DSW 原语(图标表驱动)。 */
|
|
20
|
+
export function pickPrimitive(name: string): IconComponent {
|
|
21
|
+
return (P as unknown as Record<string, IconComponent>)[name]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** 以统一 size 包装图标组件调用(放在 JSX 子元素位)。 */
|
|
25
|
+
export function Icon(comp: unknown, size: number, extra?: Record<string, unknown>): ReactNode {
|
|
26
|
+
return h(comp as never, Object.assign({ size }, extra || {}))
|
|
27
|
+
}
|