@lijian-ui/dsh-file-manager 0.2.2 → 0.2.3
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/lib/client.js +79 -115
- package/lib/client.js.map +1 -1
- package/lib/tsconfig.client.tsbuildinfo +1 -1
- package/lib/types/client/index.d.ts +0 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/picker/FilePickerModal.d.ts +8 -6
- package/lib/types/client/picker/FilePickerModal.d.ts.map +1 -1
- package/lib/types/client/preview/PreviewPanel.d.ts.map +1 -1
- package/lib/types/client/reference.d.ts +6 -10
- package/lib/types/client/reference.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/client/DockItem.tsx +1 -1
- package/src/client/index.ts +3 -14
- package/src/client/picker/FilePickerModal.tsx +62 -43
- package/src/client/preview/PreviewPanel.tsx +1 -0
- package/src/client/reference.ts +13 -8
- package/src/client/styles/picker.module.css +9 -9
- package/src/client/styles/preview.module.css +15 -10
- package/src/client/styles/tokens.module.css +24 -20
- package/src/client/styles/chip.module.css +0 -38
|
@@ -33,17 +33,13 @@ export interface ConversationService {
|
|
|
33
33
|
export interface FileReference {
|
|
34
34
|
/** Workspace-relative path (what the agent will read). */
|
|
35
35
|
path: string;
|
|
36
|
-
/** First line of the referenced range (1-based, inclusive). */
|
|
37
|
-
startLine
|
|
38
|
-
/** Last line of the referenced range (1-based, inclusive). */
|
|
39
|
-
endLine
|
|
36
|
+
/** First line of the referenced range (1-based, inclusive). Omit for whole-file references. */
|
|
37
|
+
startLine?: number;
|
|
38
|
+
/** Last line of the referenced range (1-based, inclusive). Omit for whole-file references. */
|
|
39
|
+
endLine?: number;
|
|
40
40
|
}
|
|
41
|
-
/** The `@path:lines` model form (what the codec serializes to on submit). */
|
|
42
|
-
export declare function formatFileRefToken(ref:
|
|
43
|
-
path: string;
|
|
44
|
-
startLine: number;
|
|
45
|
-
endLine: number;
|
|
46
|
-
}): string;
|
|
41
|
+
/** The `@path` / `@path:lines` model form (what the codec serializes to on submit). */
|
|
42
|
+
export declare function formatFileRefToken(ref: FileReference): string;
|
|
47
43
|
/** The DRAFT-REV+CAS span the conversation machine expects for chip inserts. */
|
|
48
44
|
export interface RefSpan {
|
|
49
45
|
start: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../../src/client/reference.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAA;AAEtF;;;;;;;;;;GAUG;AAEH;;;;GAIG;AACH,UAAU,UAAU;IAClB,KAAK,EAAE;QAAE,WAAW,IAAI;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAA;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AACD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,UAAU,CAAA;KAAE,CAAA;CAChD;AAED,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,+
|
|
1
|
+
{"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../../src/client/reference.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAA;AAEtF;;;;;;;;;;GAUG;AAEH;;;;GAIG;AACH,UAAU,UAAU;IAClB,KAAK,EAAE;QAAE,WAAW,IAAI;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAA;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AACD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,UAAU,CAAA;KAAE,CAAA;CAChD;AAED,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,+FAA+F;IAC/F,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AA2BD,uFAAuF;AACvF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAI7D;AAYD,gFAAgF;AAChF,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAezG;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,OAAO,GACZ,OAAO,CAmBT;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,GAAG,EAAE,aAAa,GACjB,OAAO,CAcT"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lijian-ui/dsh-file-manager",
|
|
3
3
|
"description": "DSH web GUI right-panel system: a pixel-faithful re-implementation of FileManager's Explorer + Preview columns (file tree, filename search, git changes, multi-tab preview of 10+ formats) driven by real host-side fs/git services, hot-pluggable via a profile bundle without any dsh source changes",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/types/index.d.ts",
|
package/src/client/DockItem.tsx
CHANGED
|
@@ -14,7 +14,7 @@ function ensureStyle(): void {
|
|
|
14
14
|
if (document.getElementById(STYLE_ID) !== null) return
|
|
15
15
|
const tag = document.createElement('style')
|
|
16
16
|
tag.id = STYLE_ID
|
|
17
|
-
tag.textContent = '.dsh-dock-item{width:32px;height:32px;border:none;border-radius:9999px;background:var(--dsw-alias-
|
|
17
|
+
tag.textContent = '.dsh-dock-item{width:32px;height:32px;border:none;border-radius:9999px;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-base);cursor:pointer;position:relative;transition:transform .15s ease,background .18s ease;display:inline-flex;align-items:center;justify-content:center}.dsh-dock-item:hover{transform:scale(1.15);background:color-mix(in srgb,var(--dsw-alias-label-primary) 85%,var(--dsw-alias-bg-base))}.dsh-dock-item-active{background:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-bg-base)}.dsh-dock-tooltip{position:absolute;top:calc(100% + 6px);left:50%;transform:translateX(-50%);padding:2px 8px;font-size:12px;line-height:1.4;white-space:nowrap;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;opacity:0;pointer-events:none;transition:opacity .15s}.dsh-dock-item:hover .dsh-dock-tooltip{opacity:1}'
|
|
18
18
|
document.head.appendChild(tag)
|
|
19
19
|
}
|
|
20
20
|
|
package/src/client/index.ts
CHANGED
|
@@ -37,7 +37,6 @@ import { handleFileRefClick } from './chat/file-ref.ts'
|
|
|
37
37
|
import { appendToDraft, appendFileReferenceChip } from './reference.ts'
|
|
38
38
|
import { registerFileReferenceSource } from './file-source.ts'
|
|
39
39
|
import type { FileReferenceSelection } from './preview/selection.ts'
|
|
40
|
-
import './styles/chip.module.css'
|
|
41
40
|
import { FilePanelDockItem } from './FilePanelDockItem.tsx'
|
|
42
41
|
|
|
43
42
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
@@ -223,9 +222,8 @@ export function apply(ctx: ClientContext): void {
|
|
|
223
222
|
let lastPreviewOpen = false
|
|
224
223
|
|
|
225
224
|
// The Explorer row '@' button: insert a file-reference chip for files
|
|
226
|
-
// (path
|
|
227
|
-
//
|
|
228
|
-
// range; failures fall back to plain text.
|
|
225
|
+
// (plain `@<rel-path>`, no line range) or plain `@<rel-path>/` text for
|
|
226
|
+
// folders.
|
|
229
227
|
const onReference = (path: string, isDir: boolean): void => {
|
|
230
228
|
const sessionId = ctx.sessions.list.getSnapshot().current as SessionId | undefined
|
|
231
229
|
if (sessionId === undefined) {
|
|
@@ -236,16 +234,7 @@ export function apply(ctx: ClientContext): void {
|
|
|
236
234
|
appendToDraft(ctx, sessionId, `@${path}/ `)
|
|
237
235
|
return
|
|
238
236
|
}
|
|
239
|
-
|
|
240
|
-
if (!result.ok) {
|
|
241
|
-
appendToDraft(ctx, sessionId, `@${path} `)
|
|
242
|
-
return
|
|
243
|
-
}
|
|
244
|
-
const text = result.value.content
|
|
245
|
-
const trimmed = text.endsWith('\n') ? text.slice(0, -1) : text
|
|
246
|
-
const lines = trimmed === '' ? 1 : trimmed.split('\n').length
|
|
247
|
-
appendFileReferenceChip(ctx, sessionId, { path, startLine: 1, endLine: lines })
|
|
248
|
-
})
|
|
237
|
+
appendFileReferenceChip(ctx, sessionId, { path })
|
|
249
238
|
}
|
|
250
239
|
|
|
251
240
|
// The preview "添加到对话" action: insert a file-reference chip
|
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Trigger: typing `@` (with nothing after it) in the composer opens this
|
|
6
6
|
* modal directly — no inline trigger menu (the shell's trigger menu is a
|
|
7
|
-
* flat candidate list that cannot host a tree).
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* flat candidate list that cannot host a tree). On open the just-typed `@`
|
|
8
|
+
* is stripped from the composer draft, which permanently silences the
|
|
9
|
+
* shell's own draft-driven `@` menu while the picker is up. The modal owns
|
|
10
|
+
* a recursive tree with lazy expansion, a workspace filename search,
|
|
11
|
+
* per-row checkboxes for multi-selection, and a chip row of the picked
|
|
12
|
+
* paths.
|
|
10
13
|
*
|
|
11
|
-
* Insertion
|
|
12
|
-
*
|
|
13
|
-
* the stray `@`.
|
|
14
|
+
* Insertion lands the picked references at the recorded anchor position
|
|
15
|
+
* (`@a.ts @src/ @b.md`); cancel drops the stray `@`.
|
|
14
16
|
* @module dsh-filemgr/client/picker/FilePickerModal
|
|
15
17
|
*/
|
|
16
18
|
|
|
@@ -399,6 +401,28 @@ export function FilePickerHost({ ctx, api }: { ctx: ClientContext; api: PanelApi
|
|
|
399
401
|
initialDir: '',
|
|
400
402
|
span: { start: mention.start, end: mention.start + 1 },
|
|
401
403
|
})
|
|
404
|
+
// Strip the just-typed `@` from the composer draft. Ordering note: this
|
|
405
|
+
// listener runs on the textarea (target phase) BEFORE the shell's
|
|
406
|
+
// root-delegated handler commits the keystroke into the machine, so a
|
|
407
|
+
// synchronous strip would read a STALE snapshot (guard fails, `@`
|
|
408
|
+
// survives). Defer to a microtask — by then the machine has committed
|
|
409
|
+
// the draft with the `@`, the guard holds, and the shell's draft-driven
|
|
410
|
+
// `@` menu loses its anchor for good. insert() re-checks the anchor
|
|
411
|
+
// idempotently in case this race ever lands the other way.
|
|
412
|
+
queueMicrotask(() => {
|
|
413
|
+
try {
|
|
414
|
+
const actx = ctx.sessions.scope(sessionId)
|
|
415
|
+
const conversation = (ctx as unknown as { conversation?: ConversationService }).conversation
|
|
416
|
+
if (actx === undefined || conversation === undefined) return
|
|
417
|
+
const shellInput = conversation.input.for(actx)
|
|
418
|
+
const snap = shellInput.state.getSnapshot()
|
|
419
|
+
if (snap.draft.charAt(mention.start) === '@') {
|
|
420
|
+
shellInput.setDraft(snap.draft.slice(0, mention.start) + snap.draft.slice(mention.start + 1))
|
|
421
|
+
}
|
|
422
|
+
} catch {
|
|
423
|
+
// Best-effort: insert() re-checks the anchor idempotently.
|
|
424
|
+
}
|
|
425
|
+
})
|
|
402
426
|
}
|
|
403
427
|
const attach = (): void => {
|
|
404
428
|
for (const ta of document.querySelectorAll<HTMLTextAreaElement>('textarea')) {
|
|
@@ -421,58 +445,53 @@ export function FilePickerHost({ ctx, api }: { ctx: ClientContext; api: PanelApi
|
|
|
421
445
|
/**
|
|
422
446
|
* Insert the picked references into the composer draft as file-reference
|
|
423
447
|
* chips (one `slash/input-insert-reference` bail per file; the `file`
|
|
424
|
-
* source codec serializes each to `@path
|
|
425
|
-
* back to plain `@path/ ` text since
|
|
426
|
-
* Multiple selections land as
|
|
448
|
+
* source codec serializes each to `@path` on submit). Whole-file picks
|
|
449
|
+
* carry no line range. Folders fall back to plain `@path/ ` text since
|
|
450
|
+
* the chip has no directory concept. Multiple selections land as
|
|
451
|
+
* adjacent chips. Since open stripped the bare `@` from the draft, every
|
|
452
|
+
* chip inserts at the recorded anchor as a zero-length span.
|
|
427
453
|
*/
|
|
428
454
|
const insert = async (paths: PickedPath[]): Promise<void> => {
|
|
429
455
|
const current = filePicker.getSnapshot()
|
|
430
456
|
if (!current.open || current.req === null || paths.length === 0) return
|
|
431
|
-
const { sessionId,
|
|
457
|
+
const { sessionId, span } = current.req
|
|
432
458
|
try {
|
|
433
459
|
const actx = ctx.sessions.scope(sessionId)
|
|
434
460
|
if (actx === undefined) return
|
|
435
461
|
const conversation = (ctx as unknown as { conversation?: ConversationService }).conversation
|
|
436
462
|
if (conversation === undefined) return
|
|
437
463
|
const shell = conversation.input.for(actx)
|
|
438
|
-
//
|
|
439
|
-
//
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
const lines = trimmed === '' ? 1 : trimmed.split('\n').length
|
|
447
|
-
return { pick, lines }
|
|
448
|
-
}))
|
|
449
|
-
// Walk in original order. The first chip replaces the `@` token; the
|
|
450
|
-
// rest insert at the current cursor (0-length span) so the machine
|
|
451
|
-
// appends each one in turn.
|
|
452
|
-
let cursor = span.end
|
|
453
|
-
let firstSpan = true
|
|
454
|
-
for (const { pick, lines } of lineCounts) {
|
|
455
|
-
if (pick.isDir) {
|
|
456
|
-
appendToDraft(ctx, sessionId, `@${pick.path}/ `)
|
|
457
|
-
continue
|
|
464
|
+
// Idempotent anchor cleanup: the open-time microtask strip usually
|
|
465
|
+
// removed the bare `@` already; if that race ever landed the other way
|
|
466
|
+
// (or was skipped), remove it now so no stray `@` survives next to the
|
|
467
|
+
// inserted chips.
|
|
468
|
+
{
|
|
469
|
+
const snap0 = shell.state.getSnapshot()
|
|
470
|
+
if (snap0.draft.charAt(span.start) === '@') {
|
|
471
|
+
shell.setDraft(snap0.draft.slice(0, span.start) + snap0.draft.slice(span.start + 1))
|
|
458
472
|
}
|
|
459
|
-
|
|
473
|
+
}
|
|
474
|
+
// Walk in REVERSE pick order, every file chip at the SAME zero-length
|
|
475
|
+
// anchor: each machine insert splices the chip's DISPLAY TEXT (`@label`)
|
|
476
|
+
// plus a gap at span.start — the chip look itself is a minted scan
|
|
477
|
+
// decoration, never special characters — pushing earlier-inserted text
|
|
478
|
+
// to the right, so the draft reads in original pick order with no
|
|
479
|
+
// cursor bookkeeping. (A fixed advance of 2 would land the next chip
|
|
480
|
+
// mid-text of the previous one.) Folders keep the plain-text append at
|
|
481
|
+
// the draft tail.
|
|
482
|
+
for (let i = paths.length - 1; i >= 0; i--) {
|
|
483
|
+
const pick = paths[i]
|
|
484
|
+
if (pick.isDir) continue
|
|
460
485
|
const snap = shell.state.getSnapshot()
|
|
461
|
-
|
|
462
|
-
? { start: span.start, end: span.end, draftRev: snap.draftRev }
|
|
463
|
-
: { start: cursor, end: cursor, draftRev: snap.draftRev }
|
|
464
|
-
const ok = insertFileReference(
|
|
486
|
+
insertFileReference(
|
|
465
487
|
ctx,
|
|
466
488
|
sessionId,
|
|
467
|
-
{ path: pick.path
|
|
468
|
-
|
|
489
|
+
{ path: pick.path },
|
|
490
|
+
{ start: span.start, end: span.start, draftRev: snap.draftRev },
|
|
469
491
|
)
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
// trailing space; the cursor advances by 2 for the new characters.
|
|
474
|
-
cursor += 2
|
|
475
|
-
}
|
|
492
|
+
}
|
|
493
|
+
for (const pick of paths) {
|
|
494
|
+
if (pick.isDir) appendToDraft(ctx, sessionId, `@${pick.path}/ `)
|
|
476
495
|
}
|
|
477
496
|
filePicker.close()
|
|
478
497
|
} catch (error) {
|
package/src/client/reference.ts
CHANGED
|
@@ -29,10 +29,10 @@ export interface ConversationService {
|
|
|
29
29
|
export interface FileReference {
|
|
30
30
|
/** Workspace-relative path (what the agent will read). */
|
|
31
31
|
path: string
|
|
32
|
-
/** First line of the referenced range (1-based, inclusive). */
|
|
33
|
-
startLine
|
|
34
|
-
/** Last line of the referenced range (1-based, inclusive). */
|
|
35
|
-
endLine
|
|
32
|
+
/** First line of the referenced range (1-based, inclusive). Omit for whole-file references. */
|
|
33
|
+
startLine?: number
|
|
34
|
+
/** Last line of the referenced range (1-based, inclusive). Omit for whole-file references. */
|
|
35
|
+
endLine?: number
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/** Basename of a `/`-separated relative path ('' when empty). */
|
|
@@ -56,11 +56,13 @@ function formatRefLabel(ref: FileReference): string {
|
|
|
56
56
|
const basename = basenameOf(ref.path)
|
|
57
57
|
const dirname = dirnameOf(ref.path)
|
|
58
58
|
const name = dirname === '' ? basename : `${basename} - ${dirname}`
|
|
59
|
+
if (ref.startLine === undefined || ref.endLine === undefined) return name
|
|
59
60
|
return ref.endLine > ref.startLine ? `${name} ${ref.startLine}-${ref.endLine}` : `${name} ${ref.startLine}`
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
/** The `@path:lines` model form (what the codec serializes to on submit). */
|
|
63
|
-
export function formatFileRefToken(ref:
|
|
63
|
+
/** The `@path` / `@path:lines` model form (what the codec serializes to on submit). */
|
|
64
|
+
export function formatFileRefToken(ref: FileReference): string {
|
|
65
|
+
if (ref.startLine === undefined || ref.endLine === undefined) return `@${ref.path}`
|
|
64
66
|
const range = ref.endLine > ref.startLine ? `${ref.startLine}-${ref.endLine}` : `${ref.startLine}`
|
|
65
67
|
return `@${ref.path}:${range}`
|
|
66
68
|
}
|
|
@@ -71,6 +73,8 @@ interface ConversationReference {
|
|
|
71
73
|
ref: string
|
|
72
74
|
label: string
|
|
73
75
|
clipboardText: string
|
|
76
|
+
/** Official chip appearance: renders the reference icon over the `@` glyph. */
|
|
77
|
+
appearance: 'file'
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
/** The DRAFT-REV+CAS span the conversation machine expects for chip inserts. */
|
|
@@ -86,7 +90,7 @@ export function appendToDraft(ctx: ClientContext, sessionId: SessionId | undefin
|
|
|
86
90
|
if (sessionId === undefined) return false
|
|
87
91
|
const actx = ctx.sessions.scope(sessionId)
|
|
88
92
|
if (actx === undefined) return false
|
|
89
|
-
const conversation = (ctx as unknown as {
|
|
93
|
+
const conversation = (ctx as unknown as { get(name: string): unknown }).get('conversation') as ConversationService | undefined
|
|
90
94
|
if (conversation === undefined) return false
|
|
91
95
|
const input = conversation.input.for(actx as unknown as ClientContext)
|
|
92
96
|
const draft = input.state.getSnapshot().draft
|
|
@@ -122,6 +126,7 @@ export function insertFileReference(
|
|
|
122
126
|
ref: formatFileRefToken(ref),
|
|
123
127
|
label: formatRefLabel(ref),
|
|
124
128
|
clipboardText: formatFileRefToken(ref),
|
|
129
|
+
appearance: 'file',
|
|
125
130
|
}
|
|
126
131
|
return (actx as unknown as {
|
|
127
132
|
bail(target: unknown, event: string, payload: unknown): boolean
|
|
@@ -148,7 +153,7 @@ export function appendFileReferenceChip(
|
|
|
148
153
|
if (sessionId === undefined) return false
|
|
149
154
|
const actx = ctx.sessions.scope(sessionId)
|
|
150
155
|
if (actx === undefined) return false
|
|
151
|
-
const conversation = (ctx as unknown as {
|
|
156
|
+
const conversation = (ctx as unknown as { get(name: string): unknown }).get('conversation') as ConversationService | undefined
|
|
152
157
|
if (conversation === undefined) return false
|
|
153
158
|
const shell = conversation.input.for(actx as unknown as ClientContext)
|
|
154
159
|
const snap = shell.state.getSnapshot()
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
.overlay {
|
|
9
9
|
position: fixed;
|
|
10
10
|
inset: 0;
|
|
11
|
-
background:
|
|
11
|
+
background: var(--dsw-alias-bg-mask-1);
|
|
12
12
|
display: flex;
|
|
13
13
|
align-items: center;
|
|
14
14
|
justify-content: center;
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
background: var(--aion-bg-base);
|
|
25
25
|
border: 1px solid var(--aion-border-base);
|
|
26
26
|
border-radius: 10px;
|
|
27
|
-
box-shadow:
|
|
27
|
+
box-shadow: var(--dsw-shadow-lv3);
|
|
28
28
|
overflow: hidden;
|
|
29
29
|
font-family: var(--aion-font-sans);
|
|
30
30
|
color: var(--aion-text-primary);
|
|
@@ -158,11 +158,11 @@
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
.rowSelected {
|
|
161
|
-
background:
|
|
161
|
+
background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 12%, transparent);
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
.rowSelected:hover {
|
|
165
|
-
background:
|
|
165
|
+
background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 18%, transparent);
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
.chev {
|
|
@@ -220,7 +220,7 @@
|
|
|
220
220
|
height: 16px;
|
|
221
221
|
border: 1px solid var(--aion-border-base);
|
|
222
222
|
border-radius: 4px;
|
|
223
|
-
color:
|
|
223
|
+
color: var(--dsw-alias-label-primary-foreground);
|
|
224
224
|
flex-shrink: 0;
|
|
225
225
|
background: transparent;
|
|
226
226
|
}
|
|
@@ -294,7 +294,7 @@
|
|
|
294
294
|
}
|
|
295
295
|
|
|
296
296
|
.chipX:hover {
|
|
297
|
-
background:
|
|
297
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
298
298
|
color: var(--aion-text-primary);
|
|
299
299
|
}
|
|
300
300
|
|
|
@@ -325,8 +325,8 @@
|
|
|
325
325
|
height: 32px;
|
|
326
326
|
padding: 0 16px;
|
|
327
327
|
border: none;
|
|
328
|
-
background: var(--
|
|
329
|
-
color:
|
|
328
|
+
background: var(--dsw-alias-button-primary-fill);
|
|
329
|
+
color: var(--dsw-alias-label-primary-foreground);
|
|
330
330
|
border-radius: 6px;
|
|
331
331
|
font-size: 13px;
|
|
332
332
|
font-weight: 500;
|
|
@@ -335,7 +335,7 @@
|
|
|
335
335
|
}
|
|
336
336
|
|
|
337
337
|
.insertBtn:hover:not(:disabled) {
|
|
338
|
-
|
|
338
|
+
background: var(--dsw-alias-button-primary-hover);
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
.insertBtn:disabled {
|
|
@@ -504,25 +504,30 @@
|
|
|
504
504
|
border-radius: 4px;
|
|
505
505
|
}
|
|
506
506
|
|
|
507
|
-
/* The "添加到对话" floating action over a preview selection.
|
|
507
|
+
/* The "添加到对话" floating action over a preview selection.
|
|
508
|
+
* Mirrors the official primitives Button primary variant (.sm capsule):
|
|
509
|
+
* geometry h28/r14/p10, fill = button-primary-fill, text = label-primary-foreground,
|
|
510
|
+
* hover = button-primary-hover, shadow = --dsw-shadow-lv1 (floating layer). */
|
|
508
511
|
.addToChat {
|
|
509
512
|
position: fixed;
|
|
510
513
|
z-index: 1000;
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
514
|
+
display: inline-flex;
|
|
515
|
+
align-items: center;
|
|
516
|
+
height: 28px;
|
|
517
|
+
padding: 0 10px;
|
|
518
|
+
background: var(--dsw-alias-button-primary-fill);
|
|
519
|
+
color: var(--dsw-alias-label-primary-foreground);
|
|
520
|
+
border-radius: 14px;
|
|
521
|
+
font-size: 12px;
|
|
522
|
+
line-height: 18px;
|
|
518
523
|
cursor: pointer;
|
|
519
|
-
box-shadow: var(--
|
|
524
|
+
box-shadow: var(--dsw-shadow-lv1);
|
|
520
525
|
user-select: none;
|
|
521
526
|
white-space: nowrap;
|
|
522
527
|
}
|
|
523
528
|
|
|
524
529
|
.addToChat:hover {
|
|
525
|
-
|
|
530
|
+
background: var(--dsw-alias-button-primary-hover);
|
|
526
531
|
}
|
|
527
532
|
|
|
528
533
|
/* Code viewer shell: line gutter + code body in one scroll container. */
|
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
* — dark-mode adaptation is handled by `--dsw-*` itself, so no per-theme
|
|
6
6
|
* override block is needed.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* Scoped to BODY, not :root: since the official theme rc.2 the `--dsw-*`
|
|
9
|
+
* semantic tokens live on `body` (not html), so an alias defined at :root
|
|
10
|
+
* would substitute var() against an undefined name and compute to the
|
|
11
|
+
* guaranteed-invalid value (""), killing every background that consumes it.
|
|
12
|
+
* On body the dsw tokens resolve and the aliases inherit to all visible
|
|
13
|
+
* elements — including the DOM-created chrome (panel columns, drag handles,
|
|
14
|
+
* the '@' picker portal) appended outside any React subtree.
|
|
13
15
|
*/
|
|
14
|
-
:global(
|
|
16
|
+
:global(body) {
|
|
15
17
|
--aion-bg-base: var(--dsw-alias-bg-base);
|
|
16
18
|
--aion-bg-1: var(--dsw-alias-bg-layer-1);
|
|
17
19
|
--aion-bg-2: var(--dsw-alias-bg-layer-2);
|
|
@@ -34,9 +36,9 @@
|
|
|
34
36
|
--aion-fill-3: var(--dsw-alias-interactive-bg-hover-solid);
|
|
35
37
|
--aion-border-base: var(--dsw-alias-border-l2);
|
|
36
38
|
--aion-overlay-shadow: var(--dsw-shadow-lv2);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
--aion-font-mono:
|
|
39
|
+
/* 官方字体 token;mono 用本地栈 —— 当前主题版本尚无 --dsw-alias-font-family-mono */
|
|
40
|
+
--aion-font-sans: var(--dsw-font-family);
|
|
41
|
+
--aion-font-mono: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
|
|
@@ -201,7 +203,7 @@
|
|
|
201
203
|
display: flex;
|
|
202
204
|
align-items: center;
|
|
203
205
|
justify-content: center;
|
|
204
|
-
background:
|
|
206
|
+
background: var(--dsw-alias-bg-mask-1);
|
|
205
207
|
}
|
|
206
208
|
:global(.filemgr-dialog) {
|
|
207
209
|
width: 400px;
|
|
@@ -252,28 +254,30 @@
|
|
|
252
254
|
outline-offset: 2px;
|
|
253
255
|
}
|
|
254
256
|
:global(.filemgr-btn-primary) {
|
|
255
|
-
background: var(--
|
|
256
|
-
border-color: var(--
|
|
257
|
-
color:
|
|
257
|
+
background: var(--dsw-alias-button-primary-fill);
|
|
258
|
+
border-color: var(--dsw-alias-button-primary-fill);
|
|
259
|
+
color: var(--dsw-alias-label-primary-foreground);
|
|
258
260
|
}
|
|
259
261
|
:global(.filemgr-btn-primary:hover) {
|
|
260
|
-
background: var(--
|
|
261
|
-
|
|
262
|
+
background: var(--dsw-alias-button-primary-hover);
|
|
263
|
+
border-color: var(--dsw-alias-button-primary-hover);
|
|
262
264
|
}
|
|
263
265
|
:global(.filemgr-btn-primary:active) {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
+
background: var(--dsw-alias-button-primary-hover);
|
|
267
|
+
border-color: var(--dsw-alias-button-primary-hover);
|
|
266
268
|
}
|
|
267
269
|
:global(.filemgr-btn-danger) {
|
|
268
270
|
background: var(--aion-danger);
|
|
269
271
|
border-color: var(--aion-danger);
|
|
270
|
-
color:
|
|
272
|
+
color: var(--dsw-alias-label-primary-foreground);
|
|
271
273
|
}
|
|
272
274
|
:global(.filemgr-btn-danger:hover) {
|
|
273
|
-
|
|
275
|
+
background: color-mix(in srgb, var(--aion-danger) 88%, black);
|
|
276
|
+
border-color: color-mix(in srgb, var(--aion-danger) 88%, black);
|
|
274
277
|
}
|
|
275
278
|
:global(.filemgr-btn-danger:active) {
|
|
276
|
-
|
|
279
|
+
background: color-mix(in srgb, var(--aion-danger) 78%, black);
|
|
280
|
+
border-color: color-mix(in srgb, var(--aion-danger) 78%, black);
|
|
277
281
|
}
|
|
278
282
|
|
|
279
283
|
/* Context menu (tab right-click / tree right-click). */
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Global restyle of the shell's reference chips to the file-reference look
|
|
3
|
-
* (the user's screenshot): a muted rounded pill with a green `</>` code
|
|
4
|
-
* glyph. The shell renders every U+FFFC chip with `data-decoration="chip"`
|
|
5
|
-
* (InputBar), so this file overrides its default blue tint through that
|
|
6
|
-
* attribute — the hash-scoped `.chip` class stays untouched and alignment
|
|
7
|
-
* (the U+FFFC advance cell) is preserved because the glyph comes from the
|
|
8
|
-
* label cell's ::before, not the placeholder cell's.
|
|
9
|
-
*
|
|
10
|
-
* Side effect: chips of other sources (skills, subagents) pick up the same
|
|
11
|
-
* pill look — a uniform, muted family, which the shell's default blue
|
|
12
|
-
* already intended.
|
|
13
|
-
* @module dsh-filemgr/client/styles/chip
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
:global([data-decoration="chip"]) {
|
|
17
|
-
background: rgba(15, 23, 42, 0.06);
|
|
18
|
-
border-radius: 6px;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
:global(body[data-ds-dark-theme] [data-decoration="chip"]) {
|
|
22
|
-
background: rgba(255, 255, 255, 0.1);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/* The label cell keeps the shell's default 0.72 compensated scale (no
|
|
26
|
-
override here) — the pill text renders at the composer's native size. */
|
|
27
|
-
|
|
28
|
-
/* The green `</>` glyph, drawn inside the label cell (absolute-positioned by
|
|
29
|
-
the shell, so this never shifts the placeholder advance). */
|
|
30
|
-
:global([data-decoration="chip"] > span::before) {
|
|
31
|
-
content: "</>";
|
|
32
|
-
color: var(--aion-success);
|
|
33
|
-
font-family: var(--aion-font-mono);
|
|
34
|
-
font-size: 0.85em;
|
|
35
|
-
font-weight: 700;
|
|
36
|
-
margin-right: 4px;
|
|
37
|
-
letter-spacing: -0.5px;
|
|
38
|
-
}
|