@meiyukichan/dsh-sandore 0.1.0-rc.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/LICENSE +201 -0
- package/cordis.patch.yml +39 -0
- package/dsh.plugin.json +16 -0
- package/lib/client/CommandEditor.d.ts +19 -0
- package/lib/client/DagEditor.d.ts +22 -0
- package/lib/client/DefinitionDetail.d.ts +13 -0
- package/lib/client/DefinitionList.d.ts +19 -0
- package/lib/client/DiscussionInput.d.ts +63 -0
- package/lib/client/DragHandle.d.ts +16 -0
- package/lib/client/EditorPane.d.ts +13 -0
- package/lib/client/FlowEditor.d.ts +31 -0
- package/lib/client/InstanceList.d.ts +24 -0
- package/lib/client/NewInstanceDialog.d.ts +19 -0
- package/lib/client/PreviewPanel.d.ts +13 -0
- package/lib/client/RunView.d.ts +79 -0
- package/lib/client/StepChatPanel.d.ts +34 -0
- package/lib/client/TreeNav.d.ts +27 -0
- package/lib/client/UnifiedTimeline.d.ts +11 -0
- package/lib/client/WorkflowButton.d.ts +11 -0
- package/lib/client/WorkflowList.d.ts +18 -0
- package/lib/client/WorkflowOverlay.d.ts +6 -0
- package/lib/client/chat/AssistantMarkdown.d.ts +22 -0
- package/lib/client/chat/CompactionItem.d.ts +24 -0
- package/lib/client/chat/ContextBody.d.ts +136 -0
- package/lib/client/chat/ContextInjectionRow.d.ts +25 -0
- package/lib/client/chat/GenericCommandCard.d.ts +10 -0
- package/lib/client/chat/MessageIconActions.d.ts +41 -0
- package/lib/client/chat/MessageItem.d.ts +65 -0
- package/lib/client/chat/ReasoningRow.d.ts +13 -0
- package/lib/client/chat/TurnTailNodeView.d.ts +29 -0
- package/lib/client/chat/UserMessageRow.d.ts +18 -0
- package/lib/client/chat/attachment/ImageLightbox.d.ts +26 -0
- package/lib/client/chat/attachment/MessageImage.d.ts +56 -0
- package/lib/client/chat/attachment/image-attachment.d.ts +41 -0
- package/lib/client/chat/attachment/image-labels.d.ts +21 -0
- package/lib/client/chat/message-chrome.d.ts +51 -0
- package/lib/client/chat/reference/ReferenceIcon.d.ts +20 -0
- package/lib/client/chat/turn-assistant.d.ts +12 -0
- package/lib/client/chat/turn-metrics.d.ts +42 -0
- package/lib/client/chat/use-calendar-day.d.ts +5 -0
- package/lib/client/chat/use-throttled-visual-update.d.ts +7 -0
- package/lib/client/chat-flow.d.ts +110 -0
- package/lib/client/composer-selects.d.ts +17 -0
- package/lib/client/dag-editor-model.d.ts +141 -0
- package/lib/client/describe-error.d.ts +9 -0
- package/lib/client/index.d.ts +6 -0
- package/lib/client/locales.d.ts +777 -0
- package/lib/client/model-faces.d.ts +156 -0
- package/lib/client/open-discussion.d.ts +24 -0
- package/lib/client/panel-model.d.ts +34 -0
- package/lib/client/remote.d.ts +34 -0
- package/lib/client/run-view-model.d.ts +304 -0
- package/lib/client/sandore-save.d.ts +41 -0
- package/lib/client/sandore-sse.d.ts +15 -0
- package/lib/client/step-chat-retry.d.ts +44 -0
- package/lib/client/tool/GenericToolCard.d.ts +28 -0
- package/lib/client/tool/ToolRow.d.ts +95 -0
- package/lib/client/tool/diff-card-model.d.ts +63 -0
- package/lib/client/tool/read-card-model.d.ts +67 -0
- package/lib/client/tool/search-card-model.d.ts +94 -0
- package/lib/client/tool/terminal-card-model.d.ts +86 -0
- package/lib/client/tool/tool-call-model.d.ts +74 -0
- package/lib/client/tool/web-card-model.d.ts +44 -0
- package/lib/client/use-focus-refresh.d.ts +1 -0
- package/lib/client/workflow-face.d.ts +68 -0
- package/lib/client/workflow-store.d.ts +80 -0
- package/lib/client/workspace-path.d.ts +15 -0
- package/lib/client.js +38389 -0
- package/lib/index.js +8854 -0
- package/lib/microflow/branch-evaluator.d.ts +290 -0
- package/lib/microflow/concurrency-limiter.d.ts +39 -0
- package/lib/microflow/errors.d.ts +39 -0
- package/lib/microflow/file-utils.d.ts +210 -0
- package/lib/microflow/finalize-manager.d.ts +414 -0
- package/lib/microflow/fork-session.d.ts +151 -0
- package/lib/microflow/index.d.ts +17 -0
- package/lib/microflow/internal.d.ts +56 -0
- package/lib/microflow/loop-manager.d.ts +127 -0
- package/lib/microflow/rules-resolver.d.ts +28 -0
- package/lib/microflow/stage-executor.d.ts +362 -0
- package/lib/microflow/step-navigator.d.ts +108 -0
- package/lib/microflow/step-runner.d.ts +190 -0
- package/lib/microflow/subagents.d.ts +380 -0
- package/lib/tool/index.d.ts +65 -0
- package/lib/typert.host.d.ts +16 -0
- package/lib/typert.host.js +25 -0
- package/lib/typert.remote-client.d.ts +114 -0
- package/lib/typert.remote-client.js +399 -0
- package/lib/workflow/ask-tool.d.ts +78 -0
- package/lib/workflow/dag-navigator.d.ts +136 -0
- package/lib/workflow/domain.d.ts +304 -0
- package/lib/workflow/engine-surface.d.ts +70 -0
- package/lib/workflow/errors.d.ts +13 -0
- package/lib/workflow/host-agent.d.ts +53 -0
- package/lib/workflow/index.d.ts +23 -0
- package/lib/workflow/interaction-manager.d.ts +170 -0
- package/lib/workflow/lifecycle-manager.d.ts +111 -0
- package/lib/workflow/persistence.d.ts +35 -0
- package/lib/workflow/plugin.d.ts +27 -0
- package/lib/workflow/reactive-state.d.ts +27 -0
- package/lib/workflow/recovery-manager.d.ts +158 -0
- package/lib/workflow/remote.d.ts +139 -0
- package/lib/workflow/schema.d.ts +1917 -0
- package/lib/workflow/seam.d.ts +254 -0
- package/lib/workflow/shell.d.ts +127 -0
- package/lib/workflow/sse.d.ts +16 -0
- package/lib/workflow/typert/typert.host.d.ts +16 -0
- package/lib/workflow/typert/typert.remote-client.d.ts +114 -0
- package/lib/workflow/types.d.ts +187 -0
- package/lib/workflow/wire.d.ts +256 -0
- package/lib/workflow/workflow-engine.d.ts +373 -0
- package/lib/workflow/yaml-error.d.ts +22 -0
- package/lib/workflow/yaml-parser.d.ts +23 -0
- package/package.json +140 -0
- package/packages/client/CommandEditor.tsx +73 -0
- package/packages/client/DagEditor.module.css +711 -0
- package/packages/client/DagEditor.tsx +1203 -0
- package/packages/client/DefinitionDetail.module.css +110 -0
- package/packages/client/DefinitionDetail.tsx +126 -0
- package/packages/client/DefinitionList.tsx +173 -0
- package/packages/client/DiscussionInput.tsx +763 -0
- package/packages/client/DragHandle.tsx +92 -0
- package/packages/client/EditorPane.tsx +70 -0
- package/packages/client/FlowEditor.tsx +227 -0
- package/packages/client/InstanceList.tsx +250 -0
- package/packages/client/NewInstanceDialog.module.css +244 -0
- package/packages/client/NewInstanceDialog.tsx +478 -0
- package/packages/client/PreviewPanel.tsx +55 -0
- package/packages/client/RunView.module.css +246 -0
- package/packages/client/RunView.tsx +314 -0
- package/packages/client/StepChatPanel.tsx +486 -0
- package/packages/client/TreeNav.tsx +294 -0
- package/packages/client/UnifiedTimeline.tsx +484 -0
- package/packages/client/WorkflowButton.module.css +72 -0
- package/packages/client/WorkflowButton.tsx +50 -0
- package/packages/client/WorkflowList.tsx +158 -0
- package/packages/client/WorkflowOverlay.module.css +390 -0
- package/packages/client/WorkflowOverlay.tsx +136 -0
- package/packages/client/WorkflowPanel.module.css +247 -0
- package/packages/client/chat/AssistantMarkdown.module.css +38 -0
- package/packages/client/chat/AssistantMarkdown.tsx +120 -0
- package/packages/client/chat/ChatView.module.css +198 -0
- package/packages/client/chat/CompactionItem.tsx +85 -0
- package/packages/client/chat/ContextBody.module.css +162 -0
- package/packages/client/chat/ContextBody.tsx +598 -0
- package/packages/client/chat/ContextInjectionRow.module.css +63 -0
- package/packages/client/chat/ContextInjectionRow.tsx +78 -0
- package/packages/client/chat/GenericCommandCard.module.css +87 -0
- package/packages/client/chat/GenericCommandCard.tsx +76 -0
- package/packages/client/chat/MessageIconActions.module.css +84 -0
- package/packages/client/chat/MessageIconActions.tsx +147 -0
- package/packages/client/chat/MessageItem.module.css +293 -0
- package/packages/client/chat/MessageItem.tsx +384 -0
- package/packages/client/chat/ReasoningRow.module.css +82 -0
- package/packages/client/chat/ReasoningRow.tsx +70 -0
- package/packages/client/chat/TurnTailNodeView.module.css +10 -0
- package/packages/client/chat/TurnTailNodeView.tsx +63 -0
- package/packages/client/chat/UserMessageRow.module.css +75 -0
- package/packages/client/chat/UserMessageRow.tsx +92 -0
- package/packages/client/chat/accessibility.module.css +9 -0
- package/packages/client/chat/attachment/ImageLightbox.module.css +45 -0
- package/packages/client/chat/attachment/ImageLightbox.tsx +70 -0
- package/packages/client/chat/attachment/MessageImage.module.css +70 -0
- package/packages/client/chat/attachment/MessageImage.tsx +136 -0
- package/packages/client/chat/attachment/image-attachment.ts +98 -0
- package/packages/client/chat/attachment/image-labels.ts +34 -0
- package/packages/client/chat/message-chrome.ts +96 -0
- package/packages/client/chat/reference/ReferenceIcon.tsx +40 -0
- package/packages/client/chat/turn-assistant.ts +15 -0
- package/packages/client/chat/turn-metrics.ts +102 -0
- package/packages/client/chat/use-calendar-day.ts +27 -0
- package/packages/client/chat/use-throttled-visual-update.ts +44 -0
- package/packages/client/chat-flow.spec.ts +357 -0
- package/packages/client/chat-flow.ts +278 -0
- package/packages/client/composer-selects.module.css +376 -0
- package/packages/client/composer-selects.tsx +531 -0
- package/packages/client/dag-editor-model.spec.ts +173 -0
- package/packages/client/dag-editor-model.ts +359 -0
- package/packages/client/describe-error.spec.ts +18 -0
- package/packages/client/describe-error.ts +12 -0
- package/packages/client/index.ts +144 -0
- package/packages/client/input.module.css +854 -0
- package/packages/client/is-conditional-check.spec.ts +34 -0
- package/packages/client/locales.ts +789 -0
- package/packages/client/model-faces.ts +225 -0
- package/packages/client/open-discussion.spec.ts +39 -0
- package/packages/client/open-discussion.ts +32 -0
- package/packages/client/panel-model.spec.ts +152 -0
- package/packages/client/panel-model.ts +72 -0
- package/packages/client/preview.module.css +95 -0
- package/packages/client/react-dom.d.ts +11 -0
- package/packages/client/reactflow-theme.css +91 -0
- package/packages/client/remote.spec.ts +41 -0
- package/packages/client/remote.ts +46 -0
- package/packages/client/run-view-model.spec.ts +641 -0
- package/packages/client/run-view-model.ts +636 -0
- package/packages/client/sandore-save.spec.ts +146 -0
- package/packages/client/sandore-save.ts +97 -0
- package/packages/client/sandore-sse.ts +59 -0
- package/packages/client/step-chat-retry.spec.ts +70 -0
- package/packages/client/step-chat-retry.ts +65 -0
- package/packages/client/timeline.module.css +503 -0
- package/packages/client/tool/GenericToolCard.tsx +99 -0
- package/packages/client/tool/ToolRow.module.css +308 -0
- package/packages/client/tool/ToolRow.tsx +328 -0
- package/packages/client/tool/diff-card-model.ts +103 -0
- package/packages/client/tool/read-card-model.ts +86 -0
- package/packages/client/tool/search-card-model.ts +166 -0
- package/packages/client/tool/terminal-card-model.ts +225 -0
- package/packages/client/tool/tool-call-model.ts +267 -0
- package/packages/client/tool/web-card-model.ts +80 -0
- package/packages/client/tree-nav.module.css +282 -0
- package/packages/client/use-focus-refresh.ts +23 -0
- package/packages/client/workflow-face.ts +72 -0
- package/packages/client/workflow-store.spec.ts +49 -0
- package/packages/client/workflow-store.ts +161 -0
- package/packages/client/workspace-path.ts +27 -0
- package/packages/css-modules.d.ts +6 -0
- package/packages/microflow/branch-evaluator.spec.ts +745 -0
- package/packages/microflow/branch-evaluator.ts +1037 -0
- package/packages/microflow/concurrency-limiter.ts +70 -0
- package/packages/microflow/errors.ts +64 -0
- package/packages/microflow/file-utils.spec.ts +604 -0
- package/packages/microflow/file-utils.ts +521 -0
- package/packages/microflow/finalize-manager.spec.ts +1977 -0
- package/packages/microflow/finalize-manager.ts +1464 -0
- package/packages/microflow/fork-session.spec.ts +184 -0
- package/packages/microflow/fork-session.ts +316 -0
- package/packages/microflow/index.ts +17 -0
- package/packages/microflow/internal.ts +166 -0
- package/packages/microflow/loop-manager.spec.ts +294 -0
- package/packages/microflow/loop-manager.ts +255 -0
- package/packages/microflow/rules-resolver.spec.ts +147 -0
- package/packages/microflow/rules-resolver.ts +58 -0
- package/packages/microflow/stage-executor.spec.ts +1577 -0
- package/packages/microflow/stage-executor.ts +1478 -0
- package/packages/microflow/step-navigator.spec.ts +301 -0
- package/packages/microflow/step-navigator.ts +300 -0
- package/packages/microflow/step-runner.spec.ts +1132 -0
- package/packages/microflow/step-runner.ts +752 -0
- package/packages/microflow/subagents.spec.ts +215 -0
- package/packages/microflow/subagents.ts +422 -0
- package/packages/tests/fixtures/test-workflow.yaml +128 -0
- package/packages/tests/mocks/agents.ts +206 -0
- package/packages/tests/mocks/llm.ts +46 -0
- package/packages/tests/mocks/session-title.ts +31 -0
- package/packages/tests/mocks/sessions.ts +131 -0
- package/packages/tests/mocks/shell.ts +60 -0
- package/packages/tests/mocks/storage-domain.ts +101 -0
- package/packages/tests/mocks/subagents.ts +197 -0
- package/packages/tests/mocks/subprocess.ts +59 -0
- package/packages/tests/mocks/user-questions.ts +33 -0
- package/packages/tests/mocks/workspace.ts +52 -0
- package/packages/tool/index.spec.ts +287 -0
- package/packages/tool/index.ts +348 -0
- package/packages/workflow/ask-tool.ts +173 -0
- package/packages/workflow/dag-navigator.spec.ts +236 -0
- package/packages/workflow/dag-navigator.ts +425 -0
- package/packages/workflow/domain.ts +26 -0
- package/packages/workflow/engine-surface.ts +71 -0
- package/packages/workflow/errors.ts +13 -0
- package/packages/workflow/host-agent.spec.ts +92 -0
- package/packages/workflow/host-agent.ts +62 -0
- package/packages/workflow/index.ts +25 -0
- package/packages/workflow/interaction-manager.spec.ts +390 -0
- package/packages/workflow/interaction-manager.ts +397 -0
- package/packages/workflow/lifecycle-manager.spec.ts +683 -0
- package/packages/workflow/lifecycle-manager.ts +288 -0
- package/packages/workflow/persistence.spec.ts +109 -0
- package/packages/workflow/persistence.ts +64 -0
- package/packages/workflow/plugin.ts +39 -0
- package/packages/workflow/reactive-state.spec.ts +69 -0
- package/packages/workflow/reactive-state.ts +52 -0
- package/packages/workflow/recovery-manager.spec.ts +606 -0
- package/packages/workflow/recovery-manager.ts +471 -0
- package/packages/workflow/remote.spec.ts +1045 -0
- package/packages/workflow/remote.ts +479 -0
- package/packages/workflow/schema.spec.ts +303 -0
- package/packages/workflow/schema.ts +562 -0
- package/packages/workflow/seam.ts +293 -0
- package/packages/workflow/shell.ts +142 -0
- package/packages/workflow/sse.ts +110 -0
- package/packages/workflow/typert/typert.host.d.ts +16 -0
- package/packages/workflow/typert/typert.host.js +25 -0
- package/packages/workflow/typert/typert.remote-client.d.ts +114 -0
- package/packages/workflow/typert/typert.remote-client.js +399 -0
- package/packages/workflow/types.ts +258 -0
- package/packages/workflow/wire.ts +267 -0
- package/packages/workflow/workflow-engine-e2e.spec.ts +262 -0
- package/packages/workflow/workflow-engine-real-e2e.spec.ts +922 -0
- package/packages/workflow/workflow-engine.spec.ts +4389 -0
- package/packages/workflow/workflow-engine.ts +2133 -0
- package/packages/workflow/yaml-error.ts +29 -0
- package/packages/workflow/yaml-parser.spec.ts +757 -0
- package/packages/workflow/yaml-parser.ts +287 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/* ReasoningRow.module.css:抄自 DSH ui-conversation chat/ReasoningRow.module.css。 */
|
|
2
|
+
.root {
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.row {
|
|
8
|
+
position: relative;
|
|
9
|
+
overflow: hidden;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.root[data-state='running'] .row::after {
|
|
13
|
+
content: '';
|
|
14
|
+
position: absolute;
|
|
15
|
+
inset-block: 0;
|
|
16
|
+
left: 0;
|
|
17
|
+
width: 300px;
|
|
18
|
+
background: linear-gradient(
|
|
19
|
+
90deg,
|
|
20
|
+
transparent 0%,
|
|
21
|
+
color-mix(in srgb, var(--dsw-alias-bg-base) 60%, transparent) 55%,
|
|
22
|
+
transparent 100%
|
|
23
|
+
);
|
|
24
|
+
animation: dsh-reasoning-row-sweep 2.6s ease-out infinite;
|
|
25
|
+
pointer-events: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@keyframes dsh-reasoning-row-sweep {
|
|
29
|
+
0% { left: -300px; }
|
|
30
|
+
90%, 100% { left: 100%; }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.leading {
|
|
34
|
+
flex-shrink: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.chevron {
|
|
38
|
+
color: var(--dsw-alias-label-secondary);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.title {
|
|
42
|
+
font-weight: 400;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.separator {
|
|
46
|
+
flex: none;
|
|
47
|
+
width: 2px;
|
|
48
|
+
height: 2px;
|
|
49
|
+
margin: 0 8px;
|
|
50
|
+
border-radius: 1px;
|
|
51
|
+
background: var(--dsw-alias-label-caption);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.summary {
|
|
55
|
+
min-width: 0;
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
flex: 1 1 auto;
|
|
58
|
+
color: var(--dsw-alias-label-tertiary);
|
|
59
|
+
font-size: 14px;
|
|
60
|
+
line-height: 24px;
|
|
61
|
+
text-overflow: ellipsis;
|
|
62
|
+
white-space: nowrap;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.summary[data-follow-end] {
|
|
66
|
+
text-overflow: clip;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.thinkBody {
|
|
70
|
+
padding: 4px 0 4px 22px;
|
|
71
|
+
color: var(--dsw-alias-label-tertiary);
|
|
72
|
+
font-size: 14px;
|
|
73
|
+
line-height: 24px;
|
|
74
|
+
white-space: pre-wrap;
|
|
75
|
+
word-break: break-word;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@media (prefers-reduced-motion: reduce) {
|
|
79
|
+
.root[data-state='running'] .row::after {
|
|
80
|
+
animation: none;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReasoningRow:抄自 DSH `packages/client/ui-conversation/src/client/chat/ReasoningRow.tsx`。
|
|
3
|
+
* assistant reasoning 披露行(Think 摘要行,展开=缩进灰字),独立于工具卡片呈现。
|
|
4
|
+
* locale 面收窄为 sandore 命名空间,其余逐字保留。
|
|
5
|
+
* @module @deepseek-ai/dsh-client-ui-sandore/src/client/chat/ReasoningRow
|
|
6
|
+
*/
|
|
7
|
+
import { useEffect, useRef, useState } from 'react'
|
|
8
|
+
import { DisclosureRow, IconThinkOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'
|
|
9
|
+
import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'
|
|
10
|
+
import { useThrottledVisualUpdate } from './use-throttled-visual-update.ts'
|
|
11
|
+
import a11yCss from './accessibility.module.css'
|
|
12
|
+
import css from './ReasoningRow.module.css'
|
|
13
|
+
|
|
14
|
+
function firstLine(text: string): string {
|
|
15
|
+
const newline = text.indexOf('\n')
|
|
16
|
+
return newline === -1 ? text : text.slice(0, newline)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function latestLine(text: string): string {
|
|
20
|
+
const visible = text.trimEnd()
|
|
21
|
+
const newline = visible.lastIndexOf('\n')
|
|
22
|
+
return newline === -1 ? visible : visible.slice(newline + 1)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Render one assistant reasoning block as the Think disclosure row.
|
|
27
|
+
* @param props.text - complete or streaming reasoning text.
|
|
28
|
+
* @param props.running - whether this block is the streaming tail.
|
|
29
|
+
* @param props.t - sandore locale seat for the running status.
|
|
30
|
+
* @returns the reasoning disclosure.
|
|
31
|
+
*/
|
|
32
|
+
export function ReasoningRow({ text, running, t }: { text: string; running: boolean; t: TranslateNS<'sandore'> }) {
|
|
33
|
+
const [expanded, setExpanded] = useState(false)
|
|
34
|
+
const summaryRef = useRef<HTMLSpanElement>(null)
|
|
35
|
+
const summary = running ? latestLine(text) : firstLine(text)
|
|
36
|
+
const scheduleSummaryScroll = useThrottledVisualUpdate(() => {
|
|
37
|
+
const element = summaryRef.current
|
|
38
|
+
if (element === null) return
|
|
39
|
+
element.scrollLeft = running ? element.scrollWidth - element.clientWidth : 0
|
|
40
|
+
})
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
scheduleSummaryScroll()
|
|
43
|
+
}, [running, scheduleSummaryScroll, summary])
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div className={css.root} data-variant="think" data-state={running ? 'running' : 'ok'}>
|
|
47
|
+
{running && <span className={a11yCss.visuallyHidden}>{t('row.running')}</span>}
|
|
48
|
+
<DisclosureRow
|
|
49
|
+
rowClassName={css.row}
|
|
50
|
+
leadingClassName={css.leading}
|
|
51
|
+
titleClassName={css.title}
|
|
52
|
+
chevronClassName={css.chevron}
|
|
53
|
+
icon={<IconThinkOutline14 size={14} />}
|
|
54
|
+
title="Think"
|
|
55
|
+
open={expanded}
|
|
56
|
+
expandable
|
|
57
|
+
expandOnRowClick
|
|
58
|
+
onToggle={() => { setExpanded(value => !value) }}
|
|
59
|
+
collapsedContent={(
|
|
60
|
+
<>
|
|
61
|
+
<span className={css.separator} aria-hidden />
|
|
62
|
+
<span ref={summaryRef} className={css.summary} data-follow-end={running || undefined}>{summary}</span>
|
|
63
|
+
</>
|
|
64
|
+
)}
|
|
65
|
+
>
|
|
66
|
+
<div className={css.thinkBody}>{text}</div>
|
|
67
|
+
</DisclosureRow>
|
|
68
|
+
</div>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TurnTailNodeView:抄自 DSH `packages/client/ui-conversation/src/client/chat/TurnTailNodeView.tsx`。
|
|
3
|
+
* 已完结 turn 的本地动作与特性尾部:时间 + 运行时长/TTFT/吞吐 + 复制 + 分支(fork)。
|
|
4
|
+
* 裁剪:`conversation.chat.turnTail` chain 与 `conversation.chat.assistant-actions` list
|
|
5
|
+
* 两个 slot(sandore 面板不注册任何会话级 slot,等价于 DSH 无条目注入时的空链);
|
|
6
|
+
* `hasLaterChatNode` 判断由 chat-flow 派生为 `branchUnavailable` 传入。locale 面收窄为
|
|
7
|
+
* sandore 命名空间。其余逐字保留。
|
|
8
|
+
* @module @deepseek-ai/dsh-client-ui-sandore/src/client/chat/TurnTailNodeView
|
|
9
|
+
*/
|
|
10
|
+
import { memo } from 'react'
|
|
11
|
+
import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'
|
|
12
|
+
import { MessageIconActions } from './MessageIconActions.tsx'
|
|
13
|
+
import css from './TurnTailNodeView.module.css'
|
|
14
|
+
|
|
15
|
+
/** turn-tail 展示数据(chat-flow 派生;字段对齐 DSH TurnTailChatData 的展示面)。 */
|
|
16
|
+
export interface StepChatTailData {
|
|
17
|
+
/** 已完结 turn 号。 */
|
|
18
|
+
turn: number
|
|
19
|
+
/** 结算 assistant 节点 seq(分支锚点)。 */
|
|
20
|
+
seq: number
|
|
21
|
+
/** 结算时间(Unix epoch ms;时钟用)。 */
|
|
22
|
+
time: number
|
|
23
|
+
/** 结算 assistant 的拼接文本(复制按钮取文本)。 */
|
|
24
|
+
text: string
|
|
25
|
+
/** Turn 壁钟时长 ms;turn/start|end 均在窗口内时可用。 */
|
|
26
|
+
runMs?: number | undefined
|
|
27
|
+
/** Turn 首步 TTFT ms;未记录时省略。 */
|
|
28
|
+
ttftMs?: number | undefined
|
|
29
|
+
/** Turn 解码吞吐;未记录时省略。 */
|
|
30
|
+
tokensPerSecond?: number | undefined
|
|
31
|
+
/** 分支不可用(结算 assistant 非 turn 尾部等;chat-flow 派生)。 */
|
|
32
|
+
branchUnavailable: boolean
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Turn-local actions and feature tail over the closing Assistant, independent of Assistant placement. */
|
|
36
|
+
export const TurnTailNodeView = memo(function TurnTailNodeView({
|
|
37
|
+
data, onBranch, t,
|
|
38
|
+
}: {
|
|
39
|
+
/** 由 chat-flow 派生的 turn-tail 展示数据。 */
|
|
40
|
+
data: StepChatTailData
|
|
41
|
+
/** 分支回调:以结算 seq 为锚 fork 会话(`sessions.fork`,与 DSH forkAt 同语义)。 */
|
|
42
|
+
onBranch: (seq: number) => void
|
|
43
|
+
/** sandore locale seat。 */
|
|
44
|
+
t: TranslateNS<'sandore'>
|
|
45
|
+
}) {
|
|
46
|
+
const runMs = data.runMs
|
|
47
|
+
return (
|
|
48
|
+
<div className={css.root} data-turn-tail={data.turn} data-time-hover-root>
|
|
49
|
+
<MessageIconActions
|
|
50
|
+
text={data.text}
|
|
51
|
+
time={data.time}
|
|
52
|
+
runMs={runMs}
|
|
53
|
+
ttftMs={data.ttftMs}
|
|
54
|
+
tokensPerSecond={data.tokensPerSecond}
|
|
55
|
+
clock="end"
|
|
56
|
+
onBranch={() => { onBranch(data.seq) }}
|
|
57
|
+
branchUnavailable={data.branchUnavailable}
|
|
58
|
+
className={css.actions}
|
|
59
|
+
t={t}
|
|
60
|
+
/>
|
|
61
|
+
</div>
|
|
62
|
+
)
|
|
63
|
+
})
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* UserMessageRow.module.css:sandore 面板的用户消息行式样式(非 DSH 抄入——DSH 用户消息是
|
|
2
|
+
右侧气泡;面板按「左侧行式」需求实现,视觉对齐 ToolRow / ContextInjectionRow 的
|
|
3
|
+
DisclosureRow 体系:24px 单行、16px leading 槽、2x2 分隔点、单行省略摘要、展开体)。 */
|
|
4
|
+
|
|
5
|
+
/* 展开时行底留 4px,与上下文注入行的展开节奏一致。 */
|
|
6
|
+
.root[data-open] {
|
|
7
|
+
padding-bottom: 4px;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* 展开/悬停预览的 chevron 颜色(与 ToolRow / ContextInjectionRow 一致)。 */
|
|
11
|
+
.chevron {
|
|
12
|
+
color: var(--dsw-alias-label-secondary);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* 标题与摘要之间的分隔点(ToolRow / ContextInjectionRow 同款 2x2 圆点)。 */
|
|
16
|
+
.sep {
|
|
17
|
+
flex: none;
|
|
18
|
+
width: 2px;
|
|
19
|
+
height: 2px;
|
|
20
|
+
margin: 0 8px;
|
|
21
|
+
border-radius: 1px;
|
|
22
|
+
background: var(--dsw-alias-label-caption);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* 单行用户消息摘要:FILL 截断 + 省略号;多行文本(换行)被 `white-space: nowrap`
|
|
26
|
+
折叠为单行,超宽时 `text-overflow: ellipsis` 截断。 */
|
|
27
|
+
.summary {
|
|
28
|
+
flex: 1 1 auto;
|
|
29
|
+
min-width: 0;
|
|
30
|
+
overflow: hidden;
|
|
31
|
+
color: var(--dsw-alias-label-tertiary);
|
|
32
|
+
font-size: 14px;
|
|
33
|
+
line-height: 24px;
|
|
34
|
+
text-overflow: ellipsis;
|
|
35
|
+
white-space: nowrap;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* 尾部时钟(同用户气泡的时钟 chrome):flex:none 不参与省略——窄行先截摘要再截时钟,
|
|
39
|
+
ToolRow summarySuffix 同款语义;tabular-nums 让时钟宽度稳定。 */
|
|
40
|
+
.clock {
|
|
41
|
+
flex: none;
|
|
42
|
+
margin-left: 8px;
|
|
43
|
+
color: var(--dsw-alias-label-caption);
|
|
44
|
+
font-size: 12px;
|
|
45
|
+
line-height: 18px;
|
|
46
|
+
font-variant-numeric: tabular-nums;
|
|
47
|
+
white-space: nowrap;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* 展开体:完整用户消息文本框。几何对齐 ContextInjectionRow 的展开体(22px 缩进、圆角 8、
|
|
51
|
+
code-block 底),但用正文字号(14/24)而非代码字号;pre-wrap 保留用户消息的换行分段。 */
|
|
52
|
+
.body {
|
|
53
|
+
box-sizing: border-box;
|
|
54
|
+
display: flex;
|
|
55
|
+
flex-direction: column;
|
|
56
|
+
gap: 8px;
|
|
57
|
+
width: calc(100% - 22px);
|
|
58
|
+
max-height: 240px;
|
|
59
|
+
margin: 4px 0 0 22px;
|
|
60
|
+
overflow: auto;
|
|
61
|
+
padding: 10px 16px 12px 12px;
|
|
62
|
+
border: none;
|
|
63
|
+
border-radius: 8px;
|
|
64
|
+
background: var(--dsw-alias-markdown-code-block);
|
|
65
|
+
color: var(--dsw-alias-label-secondary);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* 完整消息文本:保留换行 + 任意位置断行(长 URL/长词不撑破文本框)。 */
|
|
69
|
+
.bodyText {
|
|
70
|
+
white-space: pre-wrap;
|
|
71
|
+
overflow-wrap: anywhere;
|
|
72
|
+
font-size: 14px;
|
|
73
|
+
line-height: 24px;
|
|
74
|
+
color: var(--dsw-alias-label-secondary);
|
|
75
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UserMessageRow:sandore 面板的用户消息行式渲染(非 DSH 抄入——DSH 的用户消息是右侧气泡,
|
|
3
|
+
* 面板按「左侧行式」需求实现,视觉对齐 ToolRow / ContextInjectionRow 的 DisclosureRow
|
|
4
|
+
* chrome:16px leading 槽(用户图标,hover/展开变 chevron)+ "User Message" 标签 + 分隔点 +
|
|
5
|
+
* 单行省略摘要 + 尾部时钟;整行点击(Enter/Space)展开完整用户消息文本框)。
|
|
6
|
+
*
|
|
7
|
+
* 数据面:`UserMessageNode` / `SteeringMessageNode`(公开 `ConversationNode`,二者同走
|
|
8
|
+
* 用户行渲染)——`content: ContentBlock[]` 提取纯文本(text 块以换行拼接)作单行摘要
|
|
9
|
+
* (CSS 单行省略,换行被折叠);展开体显示完整文本(pre-wrap 保留换行)+ 图片画廊
|
|
10
|
+
* (align start,与左对齐行式一致)+ 其余块经 JsonBlock 披露(与右气泡的 extra block 同款)。
|
|
11
|
+
* 展开态为组件本地 view state。
|
|
12
|
+
* @module @deepseek-ai/dsh-client-ui-sandore/src/client/chat/UserMessageRow
|
|
13
|
+
*/
|
|
14
|
+
import { memo, useState } from 'react'
|
|
15
|
+
import type { ConversationNode } from '@deepseek-ai/dsh-client-runtime/client'
|
|
16
|
+
import { DisclosureRow, IconUserOutline16, JsonBlock } from '@deepseek-ai/dsh-client-ui-primitives'
|
|
17
|
+
import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'
|
|
18
|
+
import type { SandoreRenderMessageImages } from './attachment/MessageImage.tsx'
|
|
19
|
+
import { formatMessageClock } from './message-chrome.ts'
|
|
20
|
+
import css from './UserMessageRow.module.css'
|
|
21
|
+
|
|
22
|
+
type UserNode = Extract<ConversationNode, { kind: 'user' | 'steering' }>
|
|
23
|
+
type UserImage = Extract<UserNode['content'][number], { type: 'image' }>
|
|
24
|
+
|
|
25
|
+
/** 内容块拆分:text 纯文本拼接 / image 附件(供画廊)/ 其余块(JsonBlock 披露)。 */
|
|
26
|
+
function contentParts(content: readonly unknown[]): {
|
|
27
|
+
text: string
|
|
28
|
+
images: { attachment: UserImage['attachment'] }[]
|
|
29
|
+
rest: unknown[]
|
|
30
|
+
} {
|
|
31
|
+
const texts: string[] = []
|
|
32
|
+
const images: { attachment: UserImage['attachment'] }[] = []
|
|
33
|
+
const rest: unknown[] = []
|
|
34
|
+
for (const block of content) {
|
|
35
|
+
const b = block as { type?: string; text?: string; attachment?: unknown }
|
|
36
|
+
if (b.type === 'text' && typeof b.text === 'string') texts.push(b.text)
|
|
37
|
+
else if (b.type === 'image' && b.attachment !== undefined) {
|
|
38
|
+
images.push({ attachment: (b as UserImage).attachment })
|
|
39
|
+
}
|
|
40
|
+
else rest.push(block)
|
|
41
|
+
}
|
|
42
|
+
// 多 text 块以换行拼接:单行摘要由 CSS `white-space: nowrap` 折叠换行,展开体 pre-wrap 保留分段。
|
|
43
|
+
return { text: texts.join('\n'), images, rest }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 用户消息行:DisclosureRow 行式(左对齐)——用户图标 + "User Message" 标签 + 分隔点 +
|
|
48
|
+
* 单行省略的用户消息文本 + 尾部时钟;点击整行展开完整用户消息文本框。
|
|
49
|
+
* @param props - 用户/steering 节点、图片画廊渲染器与 locale。
|
|
50
|
+
* @returns 折叠为单行的用户消息披露行。
|
|
51
|
+
*/
|
|
52
|
+
export const UserMessageRow = memo(function UserMessageRow({ node, renderMessageImages, t }: {
|
|
53
|
+
node: UserNode
|
|
54
|
+
renderMessageImages: SandoreRenderMessageImages
|
|
55
|
+
t: TranslateNS<'sandore'>
|
|
56
|
+
}) {
|
|
57
|
+
const [expanded, setExpanded] = useState(false)
|
|
58
|
+
const { text, images, rest } = contentParts(node.content)
|
|
59
|
+
const truncated = (total: number): string => t('json.truncated', { total })
|
|
60
|
+
// 空消息(无文本/图片/其他块)只有标题,不可展开。
|
|
61
|
+
const expandable = text !== '' || images.length > 0 || rest.length > 0
|
|
62
|
+
return (
|
|
63
|
+
<DisclosureRow
|
|
64
|
+
className={css.root}
|
|
65
|
+
chevronClassName={css.chevron}
|
|
66
|
+
icon={<IconUserOutline16 size={16} />}
|
|
67
|
+
title={t('message.userMessage')}
|
|
68
|
+
open={expanded}
|
|
69
|
+
expandable={expandable}
|
|
70
|
+
expandOnRowClick
|
|
71
|
+
onToggle={() => { setExpanded(value => !value) }}
|
|
72
|
+
collapsedContent={text !== '' && (
|
|
73
|
+
/* ToolRow / ContextInjectionRow 的摘要形态:分隔点 + 单行省略文本;时钟 flex:none
|
|
74
|
+
排在摘要之后,窄行先截摘要再截时钟(summarySuffix 同款语义)。 */
|
|
75
|
+
<>
|
|
76
|
+
<span className={css.sep} aria-hidden />
|
|
77
|
+
<span className={css.summary} data-user-summary>{text}</span>
|
|
78
|
+
<span className={css.clock} data-user-clock>{formatMessageClock(node.time, t)}</span>
|
|
79
|
+
</>
|
|
80
|
+
)}
|
|
81
|
+
>
|
|
82
|
+
{/* 展开体(DisclosureRow children):完整用户消息内容——图片画廊 + 完整文本 + 其余块。 */}
|
|
83
|
+
<div className={css.body} data-user-message-body>
|
|
84
|
+
{images.length > 0 && renderMessageImages({ images, align: 'start' })}
|
|
85
|
+
{text !== '' && <div className={css.bodyText} data-user-body-text>{text}</div>}
|
|
86
|
+
{rest.map((block, i) => (
|
|
87
|
+
<JsonBlock key={i} label={t('message.extraBlock')} payload={block} truncatedLabel={truncated} />
|
|
88
|
+
))}
|
|
89
|
+
</div>
|
|
90
|
+
</DisclosureRow>
|
|
91
|
+
)
|
|
92
|
+
})
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* ImageLightbox.module.css:抄自 DSH ui-attachment ImageLightbox.module.css(逐字)。 */
|
|
2
|
+
.backdrop {
|
|
3
|
+
position: fixed;
|
|
4
|
+
inset: 0;
|
|
5
|
+
z-index: 1000;
|
|
6
|
+
display: grid;
|
|
7
|
+
place-items: center;
|
|
8
|
+
padding: 40px;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/* Same mask recipe as the Modal primitive and the settings dialog. A separate
|
|
12
|
+
layer, not a background on .backdrop: backdrop-filter there would blur the
|
|
13
|
+
previewed image and the close control along with the page. */
|
|
14
|
+
.mask {
|
|
15
|
+
position: absolute;
|
|
16
|
+
inset: 0;
|
|
17
|
+
background: var(--dsw-alias-bg-mask-1);
|
|
18
|
+
backdrop-filter: var(--dsw-mask-blur);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.image {
|
|
22
|
+
position: relative;
|
|
23
|
+
max-width: min(100%, 1600px);
|
|
24
|
+
max-height: calc(100vh - 80px);
|
|
25
|
+
object-fit: contain;
|
|
26
|
+
border-radius: 12px;
|
|
27
|
+
background: var(--dsw-specific-input-major);
|
|
28
|
+
box-shadow: var(--dsw-shadow-lv3);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.close {
|
|
32
|
+
position: fixed;
|
|
33
|
+
top: 20px;
|
|
34
|
+
right: 20px;
|
|
35
|
+
z-index: 1;
|
|
36
|
+
display: grid;
|
|
37
|
+
place-items: center;
|
|
38
|
+
width: 36px;
|
|
39
|
+
height: 36px;
|
|
40
|
+
border: 1px solid var(--dsw-alias-border-l2-darkmode-thin);
|
|
41
|
+
border-radius: 999px;
|
|
42
|
+
background: var(--dsw-specific-input-major);
|
|
43
|
+
color: var(--dsw-alias-label-primary);
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ImageLightbox:抄自 DSH `packages/client/ui-attachment/src/ImageLightbox.tsx`(逐字)。
|
|
3
|
+
* 点击缩略图打开的文档级原图预览:Esc / 背景按下 / 关闭按钮关闭,卸载时恢复焦点到
|
|
4
|
+
* 打开者;经 body portal 渲染(避免被 transform/filter 祖先困住)。
|
|
5
|
+
* @module @deepseek-ai/dsh-client-ui-sandore/src/client/chat/attachment/ImageLightbox
|
|
6
|
+
*/
|
|
7
|
+
import { useEffect, useRef } from 'react'
|
|
8
|
+
import { createPortal } from 'react-dom'
|
|
9
|
+
import { IconCloseOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
|
|
10
|
+
import css from './ImageLightbox.module.css'
|
|
11
|
+
|
|
12
|
+
/** Lightbox strings the owner resolves from its own locale namespace. */
|
|
13
|
+
export interface ImageLightboxLabels {
|
|
14
|
+
/** Accessible name of the preview dialog. */
|
|
15
|
+
dialog: string
|
|
16
|
+
/** Accessible label of the close control. */
|
|
17
|
+
close: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Document-level original-image preview opened by clicking a thumbnail.
|
|
22
|
+
* Closes on Escape, backdrop press, or the close control, and restores focus
|
|
23
|
+
* to the opener on unmount. Rendered through a body portal: an opener inside
|
|
24
|
+
* a transformed or filtered ancestor would otherwise trap the fixed backdrop
|
|
25
|
+
* in that ancestor's box instead of covering the viewport.
|
|
26
|
+
*
|
|
27
|
+
* @param props.src - the original image URL.
|
|
28
|
+
* @param props.alt - the image's alt text.
|
|
29
|
+
* @param props.labels - dialog and close-control strings.
|
|
30
|
+
* @param props.onClose - dismiss callback owned by the opener.
|
|
31
|
+
* @returns the modal preview dialog.
|
|
32
|
+
*/
|
|
33
|
+
export function ImageLightbox({ src, alt, labels, onClose }: {
|
|
34
|
+
src: string
|
|
35
|
+
alt: string
|
|
36
|
+
labels: ImageLightboxLabels
|
|
37
|
+
onClose: () => void
|
|
38
|
+
}) {
|
|
39
|
+
const closeRef = useRef<HTMLButtonElement | null>(null)
|
|
40
|
+
const restoreRef = useRef<HTMLElement | null>(null)
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
restoreRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null
|
|
44
|
+
closeRef.current?.focus()
|
|
45
|
+
const onKeyDown = (event: globalThis.KeyboardEvent): void => {
|
|
46
|
+
if (event.key === 'Escape') onClose()
|
|
47
|
+
}
|
|
48
|
+
window.addEventListener('keydown', onKeyDown)
|
|
49
|
+
return () => {
|
|
50
|
+
window.removeEventListener('keydown', onKeyDown)
|
|
51
|
+
restoreRef.current?.focus()
|
|
52
|
+
}
|
|
53
|
+
}, [onClose])
|
|
54
|
+
|
|
55
|
+
return createPortal(
|
|
56
|
+
<div
|
|
57
|
+
className={css.backdrop}
|
|
58
|
+
role="dialog"
|
|
59
|
+
aria-modal="true"
|
|
60
|
+
aria-label={labels.dialog}
|
|
61
|
+
>
|
|
62
|
+
<div className={css.mask} aria-hidden="true" onMouseDown={onClose} />
|
|
63
|
+
<img className={css.image} src={src} alt={alt} />
|
|
64
|
+
<button ref={closeRef} type="button" className={css.close} aria-label={labels.close} onClick={onClose}>
|
|
65
|
+
<IconCloseOutline16 size={16} />
|
|
66
|
+
</button>
|
|
67
|
+
</div>,
|
|
68
|
+
document.body,
|
|
69
|
+
)
|
|
70
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* MessageImage.module.css:抄自 DSH ui-attachment MessageImage.module.css(逐字)。 */
|
|
2
|
+
.gallery {
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-wrap: wrap;
|
|
5
|
+
gap: 10px;
|
|
6
|
+
max-width: 100%;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.gallery[data-align='end'] {
|
|
10
|
+
justify-content: flex-end;
|
|
11
|
+
align-self: flex-end;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.gallery[data-align='start'] {
|
|
15
|
+
justify-content: flex-start;
|
|
16
|
+
align-self: flex-start;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.frame {
|
|
20
|
+
display: grid;
|
|
21
|
+
flex: 0 0 auto;
|
|
22
|
+
place-items: center;
|
|
23
|
+
min-width: 44px;
|
|
24
|
+
min-height: 44px;
|
|
25
|
+
padding: 0;
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
border: 1px solid var(--dsw-alias-border-l2-darkmode-thin);
|
|
28
|
+
border-radius: 16px;
|
|
29
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
30
|
+
cursor: zoom-in;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.frame[data-variant='tile'] {
|
|
34
|
+
width: 64px;
|
|
35
|
+
height: 64px;
|
|
36
|
+
min-width: 64px;
|
|
37
|
+
min-height: 64px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.frame img {
|
|
41
|
+
display: block;
|
|
42
|
+
width: 100%;
|
|
43
|
+
height: 100%;
|
|
44
|
+
object-fit: cover;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.loading,
|
|
48
|
+
.error {
|
|
49
|
+
color: var(--dsw-alias-label-tertiary);
|
|
50
|
+
font-size: 12px;
|
|
51
|
+
line-height: 18px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.error {
|
|
55
|
+
max-width: 240px;
|
|
56
|
+
padding: 10px 12px;
|
|
57
|
+
border: 1px solid var(--dsw-alias-border-l2-darkmode-thin);
|
|
58
|
+
border-radius: 10px;
|
|
59
|
+
background: var(--dsw-alias-interactive-bg-hover-danger);
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* A failed tile keeps the 64px grid cell instead of growing to its copy. */
|
|
64
|
+
.error[data-variant='tile'] {
|
|
65
|
+
width: 64px;
|
|
66
|
+
height: 64px;
|
|
67
|
+
padding: 4px;
|
|
68
|
+
overflow: hidden;
|
|
69
|
+
border-radius: 16px;
|
|
70
|
+
}
|