dsh-better-sidebar 0.10.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 +139 -0
- package/README_EN.md +139 -0
- package/lib/client-docx.js +7649 -0
- package/lib/client-editor.js +32677 -0
- package/lib/client-pptx.js +63438 -0
- package/lib/client-registry.js +8021 -0
- package/lib/client-terminal.js +8060 -0
- package/lib/client-xlsx.js +359755 -0
- package/lib/client.js +8021 -0
- package/lib/index.js +2604 -0
- package/lib/invariant.js +22 -0
- package/lib/types/agent-pty.d.ts +220 -0
- package/lib/types/browser-probe.d.ts +15 -0
- package/lib/types/bundle-route.d.ts +13 -0
- package/lib/types/client/BrowserView.d.ts +22 -0
- package/lib/types/client/DiffTab.d.ts +6 -0
- package/lib/types/client/DiffView.d.ts +51 -0
- package/lib/types/client/EditorHost.d.ts +10 -0
- package/lib/types/client/ExplorerView.d.ts +9 -0
- package/lib/types/client/GitView.d.ts +8 -0
- package/lib/types/client/OrphanedTab.d.ts +11 -0
- package/lib/types/client/PdfView.d.ts +6 -0
- package/lib/types/client/PptxView.d.ts +6 -0
- package/lib/types/client/SandboxStatusBar.d.ts +10 -0
- package/lib/types/client/SideCardSection.d.ts +27 -0
- package/lib/types/client/Sidebar.d.ts +6 -0
- package/lib/types/client/SubagentView.d.ts +16 -0
- package/lib/types/client/TabBar.d.ts +38 -0
- package/lib/types/client/TerminalView.d.ts +8 -0
- package/lib/types/client/TextEditor.d.ts +10 -0
- package/lib/types/client/api.d.ts +170 -0
- package/lib/types/client/binary-download.d.ts +12 -0
- package/lib/types/client/breakpoints.d.ts +12 -0
- package/lib/types/client/browser.d.ts +50 -0
- package/lib/types/client/builtins/index.d.ts +17 -0
- package/lib/types/client/builtins/tabs.d.ts +6 -0
- package/lib/types/client/builtins/viewers.d.ts +3 -0
- package/lib/types/client/chunk-loader.d.ts +74 -0
- package/lib/types/client/chunks/docx.d.ts +8 -0
- package/lib/types/client/chunks/editor.d.ts +9 -0
- package/lib/types/client/chunks/pptx.d.ts +8 -0
- package/lib/types/client/chunks/terminal.d.ts +9 -0
- package/lib/types/client/chunks/xlsx.d.ts +9 -0
- package/lib/types/client/cm-themes.d.ts +24 -0
- package/lib/types/client/conversation-draft.d.ts +14 -0
- package/lib/types/client/docx-view.d.ts +8 -0
- package/lib/types/client/editor-load.d.ts +66 -0
- package/lib/types/client/icons.d.ts +47 -0
- package/lib/types/client/image-types.d.ts +3 -0
- package/lib/types/client/ime-guard.d.ts +36 -0
- package/lib/types/client/index.d.ts +10 -0
- package/lib/types/client/intercept.d.ts +20 -0
- package/lib/types/client/lang.d.ts +12 -0
- package/lib/types/client/lazy-chunk.d.ts +25 -0
- package/lib/types/client/link-intercept.d.ts +35 -0
- package/lib/types/client/locales.d.ts +237 -0
- package/lib/types/client/office-shared.d.ts +33 -0
- package/lib/types/client/office-types.d.ts +36 -0
- package/lib/types/client/office-view.d.ts +12 -0
- package/lib/types/client/openpath-intercept.d.ts +41 -0
- package/lib/types/client/paths.d.ts +19 -0
- package/lib/types/client/pdf-types.d.ts +2 -0
- package/lib/types/client/prefs.d.ts +30 -0
- package/lib/types/client/produced-files.d.ts +27 -0
- package/lib/types/client/selection-payload.d.ts +27 -0
- package/lib/types/client/service.d.ts +214 -0
- package/lib/types/client/split-pane.d.ts +29 -0
- package/lib/types/client/state.d.ts +322 -0
- package/lib/types/client/subagent-activity.d.ts +35 -0
- package/lib/types/client/subagent-detect.d.ts +47 -0
- package/lib/types/client/subagent-jobs.d.ts +63 -0
- package/lib/types/client/theme.d.ts +28 -0
- package/lib/types/client/xlsx-to-univer.d.ts +33 -0
- package/lib/types/client/xlsx-view.d.ts +10 -0
- package/lib/types/config.d.ts +41 -0
- package/lib/types/context-types.d.ts +431 -0
- package/lib/types/fs-tree.d.ts +41 -0
- package/lib/types/git.d.ts +75 -0
- package/lib/types/html-route.d.ts +48 -0
- package/lib/types/index.d.ts +39 -0
- package/lib/types/invariant.d.ts +15 -0
- package/lib/types/jobs-routes.d.ts +45 -0
- package/lib/types/prefs-shared.d.ts +106 -0
- package/lib/types/pty-manager.d.ts +76 -0
- package/lib/types/tools.d.ts +28 -0
- package/lib/types/trust-fence.d.ts +24 -0
- package/lib/types/wire.d.ts +38 -0
- package/package.json +168 -0
- package/src/agent-pty.ts +519 -0
- package/src/browser-probe.ts +26 -0
- package/src/bundle-route.ts +130 -0
- package/src/client/BrowserView.tsx +253 -0
- package/src/client/DiffTab.tsx +110 -0
- package/src/client/DiffView.tsx +266 -0
- package/src/client/EditorHost.tsx +101 -0
- package/src/client/ExplorerView.tsx +283 -0
- package/src/client/GitView.tsx +540 -0
- package/src/client/OrphanedTab.tsx +27 -0
- package/src/client/PdfView.tsx +110 -0
- package/src/client/PptxView.tsx +131 -0
- package/src/client/SandboxStatusBar.tsx +60 -0
- package/src/client/SideCardSection.module.css +271 -0
- package/src/client/SideCardSection.tsx +426 -0
- package/src/client/Sidebar.tsx +861 -0
- package/src/client/SubagentView.module.css +547 -0
- package/src/client/SubagentView.tsx +866 -0
- package/src/client/TabBar.tsx +188 -0
- package/src/client/TerminalView.tsx +233 -0
- package/src/client/TextEditor.tsx +382 -0
- package/src/client/api.ts +215 -0
- package/src/client/binary-download.tsx +23 -0
- package/src/client/breakpoints.ts +51 -0
- package/src/client/browser.ts +119 -0
- package/src/client/builtins/index.ts +33 -0
- package/src/client/builtins/tabs.tsx +211 -0
- package/src/client/builtins/viewers.tsx +151 -0
- package/src/client/chunk-loader.ts +196 -0
- package/src/client/chunks/docx.tsx +8 -0
- package/src/client/chunks/editor.tsx +9 -0
- package/src/client/chunks/pptx.tsx +8 -0
- package/src/client/chunks/terminal.tsx +9 -0
- package/src/client/chunks/xlsx.tsx +9 -0
- package/src/client/cm-themes.ts +129 -0
- package/src/client/conversation-draft.ts +29 -0
- package/src/client/css-modules.d.ts +5 -0
- package/src/client/docx-view.tsx +113 -0
- package/src/client/editor-load.ts +92 -0
- package/src/client/icons.tsx +137 -0
- package/src/client/image-types.ts +8 -0
- package/src/client/ime-guard.ts +47 -0
- package/src/client/index.tsx +238 -0
- package/src/client/intercept.tsx +94 -0
- package/src/client/lang.ts +95 -0
- package/src/client/layout.css +54 -0
- package/src/client/lazy-chunk.tsx +89 -0
- package/src/client/link-intercept.ts +66 -0
- package/src/client/locales.ts +476 -0
- package/src/client/office-shared.tsx +40 -0
- package/src/client/office-types.ts +48 -0
- package/src/client/office-view.tsx +12 -0
- package/src/client/openpath-intercept.ts +62 -0
- package/src/client/paths.ts +28 -0
- package/src/client/pdf-types.ts +4 -0
- package/src/client/prefs.ts +100 -0
- package/src/client/produced-files.ts +87 -0
- package/src/client/selection-payload.ts +86 -0
- package/src/client/service.ts +434 -0
- package/src/client/sidebar.module.css +1917 -0
- package/src/client/split-pane.tsx +292 -0
- package/src/client/state.ts +1048 -0
- package/src/client/subagent-activity.ts +67 -0
- package/src/client/subagent-detect.ts +125 -0
- package/src/client/subagent-jobs.ts +161 -0
- package/src/client/theme.ts +44 -0
- package/src/client/xlsx-to-univer.ts +260 -0
- package/src/client/xlsx-view.tsx +116 -0
- package/src/config.ts +95 -0
- package/src/context-types.ts +445 -0
- package/src/fs-tree.ts +115 -0
- package/src/git.ts +236 -0
- package/src/html-route.ts +70 -0
- package/src/index.ts +897 -0
- package/src/invariant.ts +32 -0
- package/src/jobs-routes.ts +257 -0
- package/src/prefs-shared.ts +127 -0
- package/src/pty-manager.ts +199 -0
- package/src/tools.ts +477 -0
- package/src/trust-fence.ts +77 -0
- package/src/wire.ts +94 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/** High-fidelity browser-native PPTX preview with slide navigation. */
|
|
2
|
+
import { useEffect, useRef, useState } from 'react'
|
|
3
|
+
import { downloadUrl, mediaUrl, type SessionScope } from './api.ts'
|
|
4
|
+
import { t } from './locales.ts'
|
|
5
|
+
import css from './sidebar.module.css'
|
|
6
|
+
|
|
7
|
+
type PptxViewerInstance = import('@aiden0z/pptx-renderer').PptxViewer
|
|
8
|
+
|
|
9
|
+
type LoadState =
|
|
10
|
+
| { status: 'loading' }
|
|
11
|
+
| { status: 'ready'; count: number }
|
|
12
|
+
| { status: 'error'; message: string }
|
|
13
|
+
|
|
14
|
+
export function PptxView(props: { scope: SessionScope; path: string; title: string }) {
|
|
15
|
+
const { scope, path, title } = props
|
|
16
|
+
const hostRef = useRef<HTMLDivElement>(null)
|
|
17
|
+
const viewerRef = useRef<PptxViewerInstance | null>(null)
|
|
18
|
+
const [load, setLoad] = useState<LoadState>({ status: 'loading' })
|
|
19
|
+
const [slide, setSlide] = useState(0)
|
|
20
|
+
const [navigating, setNavigating] = useState(false)
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const controller = new AbortController()
|
|
24
|
+
const host = hostRef.current
|
|
25
|
+
if (host === null) return
|
|
26
|
+
setLoad({ status: 'loading' })
|
|
27
|
+
setSlide(0)
|
|
28
|
+
void (async () => {
|
|
29
|
+
try {
|
|
30
|
+
const response = await fetch(mediaUrl(scope, path), { signal: controller.signal })
|
|
31
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`)
|
|
32
|
+
const bytes = await response.arrayBuffer()
|
|
33
|
+
if (controller.signal.aborted) return
|
|
34
|
+
const { PptxViewer, RECOMMENDED_ZIP_LIMITS } = await import('@aiden0z/pptx-renderer')
|
|
35
|
+
if (controller.signal.aborted) return
|
|
36
|
+
const viewer = await PptxViewer.open(bytes, host, {
|
|
37
|
+
renderMode: 'slide',
|
|
38
|
+
fitMode: 'contain',
|
|
39
|
+
lazyMedia: true,
|
|
40
|
+
lazySlides: true,
|
|
41
|
+
pdfjs: false,
|
|
42
|
+
signal: controller.signal,
|
|
43
|
+
zipLimits: RECOMMENDED_ZIP_LIMITS,
|
|
44
|
+
onSlideChange: (index) => {
|
|
45
|
+
if (!controller.signal.aborted) setSlide(index)
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
if (controller.signal.aborted) {
|
|
49
|
+
viewer.destroy()
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
viewerRef.current = viewer
|
|
53
|
+
setSlide(viewer.currentSlideIndex)
|
|
54
|
+
setLoad({ status: 'ready', count: viewer.slideCount })
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (controller.signal.aborted) return
|
|
57
|
+
try {
|
|
58
|
+
viewerRef.current?.destroy()
|
|
59
|
+
} catch {
|
|
60
|
+
// Partially initialized viewer — ignore disposal errors.
|
|
61
|
+
}
|
|
62
|
+
viewerRef.current = null
|
|
63
|
+
host.innerHTML = ''
|
|
64
|
+
setLoad({ status: 'error', message: error instanceof Error ? error.message : String(error) })
|
|
65
|
+
}
|
|
66
|
+
})()
|
|
67
|
+
return () => {
|
|
68
|
+
controller.abort()
|
|
69
|
+
try {
|
|
70
|
+
viewerRef.current?.destroy()
|
|
71
|
+
} catch {
|
|
72
|
+
// Already destroyed.
|
|
73
|
+
}
|
|
74
|
+
viewerRef.current = null
|
|
75
|
+
host.innerHTML = ''
|
|
76
|
+
}
|
|
77
|
+
}, [scope.sessionId, scope.cwd, path])
|
|
78
|
+
|
|
79
|
+
const navigate = (target: number): void => {
|
|
80
|
+
const viewer = viewerRef.current
|
|
81
|
+
if (viewer === null || load.status !== 'ready' || navigating) return
|
|
82
|
+
const next = Math.max(0, Math.min(load.count - 1, target))
|
|
83
|
+
if (next === slide) return
|
|
84
|
+
setNavigating(true)
|
|
85
|
+
void viewer.goToSlide(next, { behavior: 'auto' }).then(() => {
|
|
86
|
+
setSlide(viewer.currentSlideIndex)
|
|
87
|
+
}).catch((error: unknown) => {
|
|
88
|
+
setLoad({ status: 'error', message: error instanceof Error ? error.message : String(error) })
|
|
89
|
+
}).finally(() => {
|
|
90
|
+
setNavigating(false)
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<div className={css.editorPptx} aria-label={title}>
|
|
96
|
+
<div className={css.editorPptxToolbar}>
|
|
97
|
+
<button
|
|
98
|
+
type="button"
|
|
99
|
+
className={css.editorPptxButton}
|
|
100
|
+
disabled={load.status !== 'ready' || slide <= 0 || navigating}
|
|
101
|
+
onClick={() => { navigate(slide - 1) }}
|
|
102
|
+
>
|
|
103
|
+
{t('previousSlide')}
|
|
104
|
+
</button>
|
|
105
|
+
<span className={css.editorPptxPosition}>
|
|
106
|
+
{load.status === 'ready' ? `${slide + 1} / ${load.count}` : '– / –'}
|
|
107
|
+
</span>
|
|
108
|
+
<button
|
|
109
|
+
type="button"
|
|
110
|
+
className={css.editorPptxButton}
|
|
111
|
+
disabled={load.status !== 'ready' || slide >= load.count - 1 || navigating}
|
|
112
|
+
onClick={() => { navigate(slide + 1) }}
|
|
113
|
+
>
|
|
114
|
+
{t('nextSlide')}
|
|
115
|
+
</button>
|
|
116
|
+
<a className={css.editorDownloadLink} href={downloadUrl(scope, path)} download>
|
|
117
|
+
{t('downloadToView')}
|
|
118
|
+
</a>
|
|
119
|
+
</div>
|
|
120
|
+
<div className={css.editorPptxStage}>
|
|
121
|
+
<div className={css.editorPptxHost} ref={hostRef} />
|
|
122
|
+
{load.status !== 'ready' && (
|
|
123
|
+
<div className={css.editorOfficeOverlay}>
|
|
124
|
+
{load.status === 'loading' && <div className={css.editorPlaceholder}>{t('loading')}</div>}
|
|
125
|
+
{load.status === 'error' && <div className={css.editorError}>{load.message}</div>}
|
|
126
|
+
</div>
|
|
127
|
+
)}
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
)
|
|
131
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The live sandbox status row of the two built-in web surfaces (HTML
|
|
3
|
+
* preview and the browser tab): a green "sandbox on" state with a one-tap
|
|
4
|
+
* TEMPORARY unlock, or a RED "sandbox off" state (global setting or the
|
|
5
|
+
* temporary unlock) with a restore action.
|
|
6
|
+
*
|
|
7
|
+
* The temporary unlock is component state only — it never writes the
|
|
8
|
+
* global side card setting (`htmlViewerNoSandbox` / `browserNoSandbox`);
|
|
9
|
+
* it lasts until the surface unmounts (tab switch / file switch) or the
|
|
10
|
+
* user restores the sandbox from the row. When the global setting already
|
|
11
|
+
* drops the sandbox, no unlock/restore action is offered (changing the
|
|
12
|
+
* global setting is the settings page's job) — the red warning stands.
|
|
13
|
+
*/
|
|
14
|
+
import clsx from 'clsx'
|
|
15
|
+
import { t } from './locales.ts'
|
|
16
|
+
import css from './sidebar.module.css'
|
|
17
|
+
|
|
18
|
+
export function SandboxStatusBar(props: {
|
|
19
|
+
/** The effective sandbox state (global pref OR the local temporary unlock). */
|
|
20
|
+
sandboxed: boolean
|
|
21
|
+
/** Whether the sandbox is off due to the LOCAL temporary unlock (shows the restore action). */
|
|
22
|
+
local: boolean
|
|
23
|
+
/** The red-state explanation (e.g. "the page runs with full GUI privileges"). */
|
|
24
|
+
dangerCopy: string
|
|
25
|
+
onUnlock: () => void
|
|
26
|
+
onRestore: () => void
|
|
27
|
+
}) {
|
|
28
|
+
const { sandboxed, local, dangerCopy, onUnlock, onRestore } = props
|
|
29
|
+
if (sandboxed) {
|
|
30
|
+
const copy = t('sandboxStatusOn')
|
|
31
|
+
return (
|
|
32
|
+
<div className={clsx(css.sandboxStatus, css.sandboxStatusOn)}>
|
|
33
|
+
<span className={css.sandboxDot} />
|
|
34
|
+
<span className={css.sandboxStatusText} title={copy}>{copy}</span>
|
|
35
|
+
<button
|
|
36
|
+
type="button"
|
|
37
|
+
className={css.sandboxAction}
|
|
38
|
+
onClick={onUnlock}
|
|
39
|
+
>
|
|
40
|
+
{t('sandboxUnlock')}
|
|
41
|
+
</button>
|
|
42
|
+
</div>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
return (
|
|
46
|
+
<div className={clsx(css.sandboxStatus, css.sandboxStatusOff)}>
|
|
47
|
+
<span className={css.sandboxDot} />
|
|
48
|
+
<span className={css.sandboxStatusText} title={dangerCopy}>{dangerCopy}</span>
|
|
49
|
+
{local && (
|
|
50
|
+
<button
|
|
51
|
+
type="button"
|
|
52
|
+
className={css.sandboxAction}
|
|
53
|
+
onClick={onRestore}
|
|
54
|
+
>
|
|
55
|
+
{t('sandboxRestore')}
|
|
56
|
+
</button>
|
|
57
|
+
)}
|
|
58
|
+
</div>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Side card settings section chrome (DSH-native tokens throughout):
|
|
3
|
+
* - the feature inventories are responsive GRIDS of small toggle cards
|
|
4
|
+
* (auto-fill columns — several cards per row, wrapping);
|
|
5
|
+
* - a card's on/off state IS its visual state: enabled = brand border +
|
|
6
|
+
* tinted fill + a check badge pinned to the far right of the top row,
|
|
7
|
+
* disabled = neutral hairline + dimmed text;
|
|
8
|
+
* - features that declare related settings carry a gear corner button
|
|
9
|
+
* opening a native Modal whose rows are the DSH settings-row recipe
|
|
10
|
+
* (title/desc left + native accent checkbox, hairline separators);
|
|
11
|
+
* - the width input stays a native settings row (a value, not a switch).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
.section {
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
gap: 8px;
|
|
18
|
+
width: 100%;
|
|
19
|
+
/* Tall inventories (7 tab cards + 9 viewer cards + general rows) must
|
|
20
|
+
never be clipped by the settings shell: fill the shell's options area
|
|
21
|
+
and scroll inside the section when the content outgrows the panel. */
|
|
22
|
+
height: 100%;
|
|
23
|
+
min-height: 0;
|
|
24
|
+
overflow-y: auto;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.section > :last-child {
|
|
28
|
+
border-bottom: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Responsive inventory: as many small cards per row as the width allows. */
|
|
32
|
+
.grid {
|
|
33
|
+
display: grid;
|
|
34
|
+
grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
|
|
35
|
+
gap: 8px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* One small toggle card (visual chrome; the interactive part is .cardMain). */
|
|
39
|
+
.card {
|
|
40
|
+
position: relative;
|
|
41
|
+
display: flex;
|
|
42
|
+
flex-direction: column;
|
|
43
|
+
border-radius: 8px;
|
|
44
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
45
|
+
background: transparent;
|
|
46
|
+
font: inherit;
|
|
47
|
+
color: inherit;
|
|
48
|
+
cursor: pointer;
|
|
49
|
+
transition: background 0.12s ease, border-color 0.12s ease;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Hover affordance on disabled cards only (enabled cards are already lit). */
|
|
53
|
+
.card:not(.cardOn):hover {
|
|
54
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Enabled = highlighted: brand border + tinted fill. */
|
|
58
|
+
.cardOn {
|
|
59
|
+
border-color: var(--dsw-alias-button-primary-fill);
|
|
60
|
+
background: var(--dsw-alias-interactive-bg-active);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* The card's switch: the whole main area (top row + desc) flips the feature. */
|
|
64
|
+
.cardMain {
|
|
65
|
+
display: flex;
|
|
66
|
+
flex-direction: column;
|
|
67
|
+
gap: 2px;
|
|
68
|
+
width: 100%;
|
|
69
|
+
padding: 10px 12px;
|
|
70
|
+
border: 0;
|
|
71
|
+
border-radius: inherit;
|
|
72
|
+
background: transparent;
|
|
73
|
+
font: inherit;
|
|
74
|
+
color: inherit;
|
|
75
|
+
text-align: left;
|
|
76
|
+
cursor: pointer;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.cardMain:focus-visible,
|
|
80
|
+
.cardGear:focus-visible {
|
|
81
|
+
outline: 2px solid var(--dsw-alias-border-l4);
|
|
82
|
+
outline-offset: 2px;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.cardTop {
|
|
86
|
+
display: flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
gap: 6px;
|
|
89
|
+
min-width: 0;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.cardIcon {
|
|
93
|
+
display: inline-flex;
|
|
94
|
+
align-items: center;
|
|
95
|
+
flex: none;
|
|
96
|
+
color: var(--dsw-alias-label-tertiary);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.cardOn .cardIcon {
|
|
100
|
+
color: var(--dsw-alias-button-primary-fill);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.cardTitle {
|
|
104
|
+
flex: 1;
|
|
105
|
+
min-width: 0;
|
|
106
|
+
font-size: 13px;
|
|
107
|
+
line-height: 20px;
|
|
108
|
+
color: var(--dsw-alias-label-secondary);
|
|
109
|
+
white-space: nowrap;
|
|
110
|
+
overflow: hidden;
|
|
111
|
+
text-overflow: ellipsis;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.cardOn .cardTitle {
|
|
115
|
+
color: var(--dsw-alias-label-primary);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* The check badge: pinned to the FAR RIGHT of the top row (enabled only). */
|
|
119
|
+
.cardCheck {
|
|
120
|
+
display: inline-flex;
|
|
121
|
+
align-items: center;
|
|
122
|
+
flex: none;
|
|
123
|
+
color: var(--dsw-alias-button-primary-fill);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.cardDesc {
|
|
127
|
+
font-size: 11px;
|
|
128
|
+
line-height: 16px;
|
|
129
|
+
color: var(--dsw-alias-label-tertiary);
|
|
130
|
+
white-space: nowrap;
|
|
131
|
+
overflow: hidden;
|
|
132
|
+
text-overflow: ellipsis;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.cardOn .cardDesc {
|
|
136
|
+
color: var(--dsw-alias-label-secondary);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* The gear corner button: bottom-right of cards that declare related
|
|
140
|
+
settings; the desc gets right padding so the ellipsis never runs under it. */
|
|
141
|
+
.cardWithGear .cardDesc {
|
|
142
|
+
padding-right: 18px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.cardGear {
|
|
146
|
+
position: absolute;
|
|
147
|
+
right: 6px;
|
|
148
|
+
bottom: 6px;
|
|
149
|
+
display: inline-flex;
|
|
150
|
+
align-items: center;
|
|
151
|
+
justify-content: center;
|
|
152
|
+
width: 20px;
|
|
153
|
+
height: 20px;
|
|
154
|
+
padding: 0;
|
|
155
|
+
border: 0;
|
|
156
|
+
border-radius: 6px;
|
|
157
|
+
background: transparent;
|
|
158
|
+
color: var(--dsw-alias-label-tertiary);
|
|
159
|
+
cursor: pointer;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.cardGear:hover {
|
|
163
|
+
color: var(--dsw-alias-label-primary);
|
|
164
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* Inventory section heading (常规 / 侧边栏内容 / 文件预览). */
|
|
168
|
+
.sectionHeading {
|
|
169
|
+
padding: 14px 0 0;
|
|
170
|
+
font-size: 12px;
|
|
171
|
+
line-height: 17px;
|
|
172
|
+
font-weight: 600;
|
|
173
|
+
letter-spacing: 0.02em;
|
|
174
|
+
color: var(--dsw-alias-label-secondary);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* Native settings row recipe (the width input row + popup rows). */
|
|
178
|
+
.row {
|
|
179
|
+
display: flex;
|
|
180
|
+
align-items: center;
|
|
181
|
+
justify-content: space-between;
|
|
182
|
+
gap: 16px;
|
|
183
|
+
padding: 12px 0;
|
|
184
|
+
border-bottom: 1px solid var(--dsw-alias-border-l2);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.rowText {
|
|
188
|
+
display: flex;
|
|
189
|
+
flex-direction: column;
|
|
190
|
+
gap: 4px;
|
|
191
|
+
min-width: 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.title {
|
|
195
|
+
font-size: 14px;
|
|
196
|
+
line-height: 22px;
|
|
197
|
+
color: var(--dsw-alias-label-primary);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.desc {
|
|
201
|
+
font-size: 12px;
|
|
202
|
+
line-height: 17px;
|
|
203
|
+
color: var(--dsw-alias-label-secondary);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* Native checkbox: 16px, brand accent (the settings-row recipe). */
|
|
207
|
+
.toggle {
|
|
208
|
+
flex: none;
|
|
209
|
+
width: 16px;
|
|
210
|
+
height: 16px;
|
|
211
|
+
margin: 0;
|
|
212
|
+
accent-color: var(--dsw-alias-button-primary-fill);
|
|
213
|
+
cursor: pointer;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.toggle:focus-visible {
|
|
217
|
+
outline: 2px solid var(--dsw-alias-border-l4);
|
|
218
|
+
outline-offset: 2px;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* Secondary settings popup body: stacked native rows, trailing separator
|
|
222
|
+
stripped by the trailing-child rule. */
|
|
223
|
+
.popupRows {
|
|
224
|
+
display: flex;
|
|
225
|
+
flex-direction: column;
|
|
226
|
+
width: 100%;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.popupRow {
|
|
230
|
+
display: flex;
|
|
231
|
+
align-items: center;
|
|
232
|
+
justify-content: space-between;
|
|
233
|
+
gap: 16px;
|
|
234
|
+
padding: 16px 0;
|
|
235
|
+
border-bottom: 1px solid var(--dsw-alias-border-l2);
|
|
236
|
+
cursor: pointer;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.popupRows > :last-child {
|
|
240
|
+
border-bottom: none;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.control {
|
|
244
|
+
flex: none;
|
|
245
|
+
display: flex;
|
|
246
|
+
align-items: center;
|
|
247
|
+
gap: 6px;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.percentInput {
|
|
251
|
+
width: 76px;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.suffix {
|
|
255
|
+
font-size: 14px;
|
|
256
|
+
line-height: 22px;
|
|
257
|
+
color: var(--dsw-alias-label-secondary);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.error {
|
|
261
|
+
padding: 10px 0 2px;
|
|
262
|
+
font-size: 12px;
|
|
263
|
+
line-height: 17px;
|
|
264
|
+
color: var(--dsw-alias-state-error-primary);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
@media (prefers-reduced-motion: reduce) {
|
|
268
|
+
.card {
|
|
269
|
+
transition: none;
|
|
270
|
+
}
|
|
271
|
+
}
|