dsh-claude-desktop-theme 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/lib/client.js +1385 -287
- package/lib/index.js +7 -1
- package/lib/types/client/compat/account-theme.d.ts +1 -1
- package/lib/types/client/compat/browser-header.d.ts +2 -43
- package/lib/types/client/compat/browser-menu.d.ts +0 -1
- package/lib/types/client/compat/hero-canvas.d.ts +4 -0
- package/lib/types/client/compat/host-dom.d.ts +2 -0
- package/lib/types/client/compat/pane-labels.d.ts +81 -0
- package/lib/types/client/compat/settings-section.d.ts +21 -0
- package/lib/types/client/compat/sidebar-action-alignment.d.ts +3 -0
- package/lib/types/client/compat/sidebar-session-icons.d.ts +3 -0
- package/lib/types/client/compat/slots.d.ts +2 -0
- package/lib/types/client/compat/status-groups.d.ts +19 -0
- package/lib/types/client/contracts/hero-canvas.d.ts +7 -0
- package/lib/types/client/features/conversation/header-actions/visibility.d.ts +5 -0
- package/lib/types/client/features/new-session/index.d.ts +2 -3
- package/lib/types/client/features/new-session/ripples.d.ts +8 -0
- package/lib/types/client/features/settings/locales.d.ts +6 -1
- package/lib/types/client/features/settings/mount.d.ts +1 -1
- package/lib/types/client/features/settings/register.d.ts +3 -15
- package/lib/types/client/features/view-options/ViewOptionsCard.d.ts +6 -3
- package/lib/types/client/features/view-options/mount.d.ts +2 -2
- package/lib/types/client/theme/palette.d.ts +1 -0
- package/lib/types/host/index.d.ts +12 -0
- package/lib/types/shared/config.d.ts +1 -1
- package/package.json +2 -1
- package/lib/types/client/compat/plugin-manager.d.ts +0 -32
package/lib/index.js
CHANGED
|
@@ -23,7 +23,10 @@ var DEFAULT_FONTS = Object.freeze({
|
|
|
23
23
|
code: ""
|
|
24
24
|
});
|
|
25
25
|
var DEFAULT_VIEW = Object.freeze({
|
|
26
|
-
showEmptyGroups: false
|
|
26
|
+
showEmptyGroups: false,
|
|
27
|
+
groupByStatus: false,
|
|
28
|
+
showHeaderSubagents: false,
|
|
29
|
+
showHeaderTeam: false
|
|
27
30
|
});
|
|
28
31
|
var FONT_NAME_MAX_LENGTH = 64;
|
|
29
32
|
|
|
@@ -1008,6 +1011,9 @@ var Config = z.object({
|
|
|
1008
1011
|
code: z.string().default(DEFAULT_FONTS.code).description("\u4EE3\u7801\u4E0E\u7B49\u5BBD\u5B57\u4F53\u540D\uFF08\u7559\u7A7A\u7528\u7CFB\u7EDF\u6808\uFF09").pattern(FONT_NAME)
|
|
1009
1012
|
}).default({ ...DEFAULT_FONTS }).description("\u5B57\u4F53").volatile(),
|
|
1010
1013
|
view: z.object({
|
|
1014
|
+
showHeaderSubagents: z.boolean().default(DEFAULT_VIEW.showHeaderSubagents).description("\u663E\u793A\u9876\u680F\u5B50\u4EE3\u7406\u5165\u53E3\uFF08\u4EC5\u63A7\u5236\u5165\u53E3\u663E\u793A\uFF09"),
|
|
1015
|
+
showHeaderTeam: z.boolean().default(DEFAULT_VIEW.showHeaderTeam).description("\u663E\u793A\u9876\u680F\u56E2\u961F\u5165\u53E3\uFF08\u4EC5\u63A7\u5236\u5165\u53E3\u663E\u793A\uFF09"),
|
|
1016
|
+
groupByStatus: z.boolean().default(DEFAULT_VIEW.groupByStatus).description("\u6309\u4F1A\u8BDD\u72B6\u6001\u5206\u7EC4\uFF08\u4FDD\u7559\u539F\u751F\u9879\u76EE\u89C6\u56FE\u9009\u9879\uFF09"),
|
|
1011
1017
|
showEmptyGroups: z.boolean().default(DEFAULT_VIEW.showEmptyGroups).description("\u663E\u793A\u7A7A\u5206\u7EC4\uFF08\u5173\u6389\u65F6\u6CA1\u6709\u4F1A\u8BDD\u7684\u5DE5\u4F5C\u533A\u4E0D\u518D\u663E\u793A\uFF09")
|
|
1012
1018
|
}).default({ ...DEFAULT_VIEW }).description("\u89C6\u56FE\u9009\u9879").volatile()
|
|
1013
1019
|
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Disposer, ThemePreferencePort } from '../contracts/ports.ts';
|
|
2
|
-
/**
|
|
2
|
+
/** Theme controls beside the account name, sharing the native preference service. */
|
|
3
3
|
export declare function mountAccountTheme(menu: HTMLElement, theme: ThemePreferencePort | null): Disposer;
|
|
@@ -1,45 +1,4 @@
|
|
|
1
1
|
import type { Disposer } from '../contracts/ports.ts';
|
|
2
|
-
/**
|
|
3
|
-
* The browsing region's header line, and the word that names it.
|
|
4
|
-
*
|
|
5
|
-
* The reference draws this region as ONE line: the group's name at the inline
|
|
6
|
-
* start and, at the trailing edge, the plus that starts a Session, Search and
|
|
7
|
-
* the view options. DSH renders those controls on a section header of its own,
|
|
8
|
-
* above a tree whose first row is the first Workspace's, so `sidebar.css` parks
|
|
9
|
-
* the header on that row's line — and this module is what tells it when. The
|
|
10
|
-
* merge holds only while the tree actually leads with a Workspace row: flat
|
|
11
|
-
* mode renders no group at all, and `compat/empty-groups.ts` takes every group
|
|
12
|
-
* off screen when there is nothing to show, so in both the header stays in the
|
|
13
|
-
* flow and is the region's own title line.
|
|
14
|
-
*
|
|
15
|
-
* That title is a word the host serves (`section.workspaces` when the tree is
|
|
16
|
-
* grouped, `section.sessions` when it is a flat list) and the reference's is
|
|
17
|
-
* 最近会话 / Recents. The word is rewritten the way the sidebar's navigation
|
|
18
|
-
* labels are: only a string the host itself rendered is replaced — a locale
|
|
19
|
-
* this module does not know keeps the host's own word — and every write is
|
|
20
|
-
* undone on release. The grouped word takes the reference's name only while the
|
|
21
|
-
* plugin's no-history prompt is up, which `empty-groups.ts` marks
|
|
22
|
-
* `data-ccd-empty-state="new"`; a region that still has groups to show keeps
|
|
23
|
-
* the host's own heading.
|
|
24
|
-
*
|
|
25
|
-
* The state is one marker attribute on the browsing region rather than a style
|
|
26
|
-
* per element, so a single answer covers every re-render the host makes and
|
|
27
|
-
* dropping the attribute restores the host's own two-row layout.
|
|
28
|
-
*
|
|
29
|
-
* The parked band is locked to the tree's content, not to the region's top
|
|
30
|
-
* edge: the header sits on the first Workspace row's line, so it has to leave
|
|
31
|
-
* with that row when the tree scrolls. No attribute reports a scroll, and the
|
|
32
|
-
* scroller is a sibling of the header rather than an ancestor, so CSS cannot
|
|
33
|
-
* see it (a scroll-driven animation timeline resolves against an ancestor);
|
|
34
|
-
* this module therefore listens to the scroller and publishes its distance as
|
|
35
|
-
* `--ccd-header-scroll` for the band's `top`. That is one deliberate listener
|
|
36
|
-
* beside the observers — the same exception `view-switch.ts` records for the
|
|
37
|
-
* column's width — and it writes only when the value changes.
|
|
38
|
-
*/
|
|
39
|
-
/** Marker on the browsing region while its header shares the first row's line. */
|
|
40
|
-
export declare const BROWSER_HEADER_ATTRIBUTE = "data-ccd-header-merged";
|
|
41
|
-
/** Custom property carrying the tree's scrolled distance, in px. */
|
|
42
|
-
export declare const HEADER_SCROLL_PROPERTY = "--ccd-header-scroll";
|
|
43
2
|
/**
|
|
44
3
|
* The name the browsing region's own title line draws.
|
|
45
4
|
* @param text - the host's word, exactly as it rendered it.
|
|
@@ -48,10 +7,10 @@ export declare const HEADER_SCROLL_PROPERTY = "--ccd-header-scroll";
|
|
|
48
7
|
*/
|
|
49
8
|
export declare function browserHeaderWord(text: string, noHistory: boolean): string | null;
|
|
50
9
|
/**
|
|
51
|
-
*
|
|
10
|
+
* Name the browsing region's separate toolbar.
|
|
52
11
|
*
|
|
53
12
|
* @param document - renderer document carrying the sidebar.
|
|
54
13
|
* @param report - sink for observer failures; the host's two-row layout stays.
|
|
55
|
-
* @returns disposer that
|
|
14
|
+
* @returns disposer that restores every label.
|
|
56
15
|
*/
|
|
57
16
|
export declare function mountBrowserHeader(document: Document, report: (error: unknown) => void): Disposer;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Disposer } from '../contracts/ports.ts';
|
|
2
|
+
import type { HeroRippleImpulse } from '../contracts/hero-canvas.ts';
|
|
3
|
+
/** One decorative canvas per visible hero; no timers survive its phase change. */
|
|
4
|
+
export declare function mountHeroCanvas(document: Document, draw: (canvas: HTMLCanvasElement, elapsed: number, impulses: readonly HeroRippleImpulse[]) => void, report: (error: unknown) => void): Disposer;
|
|
@@ -161,6 +161,8 @@ export declare const HOST: Readonly<{
|
|
|
161
161
|
/** WorkspaceBrowser.module.css: the tree's own scroller — the one element
|
|
162
162
|
whose scroll distance the parked header band follows. */
|
|
163
163
|
readonly browserList: '._7514NG_list';
|
|
164
|
+
/** FlatList is the only native body the status presentation reorders. */
|
|
165
|
+
readonly browserFlatList: '._7514NG_flatList';
|
|
164
166
|
/** Rows.module.css: one Workspace's row, the line the merged header shares,
|
|
165
167
|
and its trailing action group (`sidebar.css` parks both). */
|
|
166
168
|
readonly workspaceRow: '.jJkEga_projectRow';
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The words the right panel's panes add (DESIGN.md §6.9).
|
|
3
|
+
*
|
|
4
|
+
* DSH localises its own strings through `ctx.locale`; a third-party plugin may
|
|
5
|
+
* not borrow another package's namespace, so the copy this panel writes follows
|
|
6
|
+
* the document language instead — the same rule the header's labels
|
|
7
|
+
* (`header-labels.ts`) and the permission card follow. Host-owned words keep
|
|
8
|
+
* the host's wording either way: a root path, the reload button, the
|
|
9
|
+
* open-in-app action and a browser page's own text are never renamed here.
|
|
10
|
+
*/
|
|
11
|
+
/** The language a pane writes its own copy in. */
|
|
12
|
+
export type PaneLanguage = 'zh' | 'en';
|
|
13
|
+
/** The Files pane's own words: its card title, field, tree control and landing state. */
|
|
14
|
+
export interface FilesPaneLabels {
|
|
15
|
+
/** The card's title; the host's own tree heading is never touched. */
|
|
16
|
+
readonly title: string;
|
|
17
|
+
/** The filter field's placeholder. */
|
|
18
|
+
readonly filter: string;
|
|
19
|
+
/** The filter field's accessible name. */
|
|
20
|
+
readonly filterLabel: string;
|
|
21
|
+
/** The filter's clear control. */
|
|
22
|
+
readonly clear: string;
|
|
23
|
+
/** The header control while the tree shows. */
|
|
24
|
+
readonly hide: string;
|
|
25
|
+
/** The same control once the tree is away, and the row that brings it back. */
|
|
26
|
+
readonly show: string;
|
|
27
|
+
/** The line under the list when a query matched nothing. */
|
|
28
|
+
readonly noMatch: string;
|
|
29
|
+
/** The landing state: a title, and the line of guidance under it. */
|
|
30
|
+
readonly emptyTitle: string;
|
|
31
|
+
readonly emptyBody: string;
|
|
32
|
+
}
|
|
33
|
+
/** The words on a pane's title bar, its ⋮ menu and the browser's toolbar. */
|
|
34
|
+
export interface PaneChromeLabels {
|
|
35
|
+
readonly more: string;
|
|
36
|
+
readonly expand: string;
|
|
37
|
+
readonly restore: string;
|
|
38
|
+
readonly search: string;
|
|
39
|
+
readonly reload: string;
|
|
40
|
+
readonly back: string;
|
|
41
|
+
readonly forward: string;
|
|
42
|
+
/** The element-picking control, and the notice it answers with. */
|
|
43
|
+
readonly pick: string;
|
|
44
|
+
readonly pickNotice: string;
|
|
45
|
+
/** The globe that focuses the address field. */
|
|
46
|
+
readonly address: string;
|
|
47
|
+
/** The word before a terminal's workspace name, and the tab group's own name. */
|
|
48
|
+
readonly terminal: string;
|
|
49
|
+
readonly terminals: string;
|
|
50
|
+
readonly newTerminal: string;
|
|
51
|
+
/** Prefixes one terminal tab's close control. */
|
|
52
|
+
readonly closeTab: string;
|
|
53
|
+
/** The Files menu's remaining rows. */
|
|
54
|
+
readonly refresh: string;
|
|
55
|
+
readonly openFolder: string;
|
|
56
|
+
readonly hideSidebar: string;
|
|
57
|
+
readonly close: string;
|
|
58
|
+
}
|
|
59
|
+
/** The capture menu's one row, and the webview area's two states. */
|
|
60
|
+
export interface BrowserPaneLabels {
|
|
61
|
+
readonly saveScreenshot: string;
|
|
62
|
+
readonly awaitingServer: string;
|
|
63
|
+
readonly enterAddress: string;
|
|
64
|
+
}
|
|
65
|
+
/** Every word the right panel adds, in one language. */
|
|
66
|
+
export interface PaneLabels {
|
|
67
|
+
readonly files: FilesPaneLabels;
|
|
68
|
+
readonly chrome: PaneChromeLabels;
|
|
69
|
+
readonly browser: BrowserPaneLabels;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* @param document - renderer document whose language DSH sets from the locale
|
|
73
|
+
* (`dsh-client-locale` points `<html lang>` at `zh-CN` for Chinese).
|
|
74
|
+
* @returns `zh` for a Chinese document, `en` for every other language.
|
|
75
|
+
*/
|
|
76
|
+
export declare function paneLanguage(document: Document): PaneLanguage;
|
|
77
|
+
/**
|
|
78
|
+
* @param language - the pane's language, from {@link paneLanguage}.
|
|
79
|
+
* @returns the right panel's copy in it.
|
|
80
|
+
*/
|
|
81
|
+
export declare function paneLabels(language: PaneLanguage): PaneLabels;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { ReactElement } from 'react';
|
|
3
|
+
import type { Disposer } from '../contracts/ports.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Public list slot declared by ui-settings-general's SettingsRoot.
|
|
6
|
+
* Verified against the installed DSH 0.2.0-rc.2 client bundle: the navigation
|
|
7
|
+
* reads id, order and label; the selected section receives close and locale t.
|
|
8
|
+
* This provider is outside our SDK baseline, so keep its boundary structural.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SETTINGS_SECTION_SLOT = "settings.section";
|
|
11
|
+
export interface SettingsSectionProps {
|
|
12
|
+
readonly t?: (key: string, params?: Record<string, unknown>) => string;
|
|
13
|
+
}
|
|
14
|
+
/** Register an independently navigable section once the host declares its slot. */
|
|
15
|
+
export declare function mountSettingsSection(ctx: Context, id: string, locale: string, label: () => string, component: (props: SettingsSectionProps) => ReactElement | null): Disposer;
|
|
16
|
+
/**
|
|
17
|
+
* SettingsRoot hardcodes icons by id, with a gear for extension sections.
|
|
18
|
+
* It emits no section id on navigation buttons. Match our localized label only
|
|
19
|
+
* inside the settings dialog navigation, and leave React's SVG intact.
|
|
20
|
+
*/
|
|
21
|
+
export declare function mountSettingsSectionIcon(document: Document, labels: readonly string[]): Disposer;
|
|
@@ -7,6 +7,8 @@ export declare const DSH_SLOTS: Readonly<{
|
|
|
7
7
|
readonly conversation: 'main.conversation';
|
|
8
8
|
readonly header: 'conversation.header';
|
|
9
9
|
readonly sessionHeader: 'conversation.session.header';
|
|
10
|
+
/** Native subagent-catalog and agent-team entries occupy this list. */
|
|
11
|
+
readonly sessionHeaderActions: 'conversation.session.header.actions';
|
|
10
12
|
/** Trailing header seats: `utilities` is a list the native actions occupy too. */
|
|
11
13
|
readonly sessionHeaderUtilities: 'conversation.session.header.utilities';
|
|
12
14
|
readonly sessionHeaderCorner: 'conversation.session.header.corner';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { Disposer } from '../contracts/ports.ts';
|
|
3
|
+
export type SessionGroup = 'input' | 'working' | 'ended';
|
|
4
|
+
export interface SessionStatus {
|
|
5
|
+
readonly running?: boolean;
|
|
6
|
+
readonly pendingInteraction?: {
|
|
7
|
+
readonly kind: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/** Pending interaction takes precedence over live work, as in DSH's own rows. */
|
|
11
|
+
export declare function sessionGroup(status: SessionStatus | undefined, running: boolean): SessionGroup;
|
|
12
|
+
/**
|
|
13
|
+
* Present the host's flat rows in status sections. React-owned rows never leave
|
|
14
|
+
* their parents: flex order and reading-flow supply visual and accessible order.
|
|
15
|
+
* Native selection, hover cards, menus and rename handlers remain on those rows.
|
|
16
|
+
* uiSession.sessionStatus is the root observable provided by ui-session in the
|
|
17
|
+
* pinned app.asar; it does not acquire or activate any listed Session.
|
|
18
|
+
*/
|
|
19
|
+
export declare function mountStatusGroups(document: Document, ctx: Context, showEmpty: boolean, report: (error: unknown) => void): Disposer;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ViewConfig } from '../../../../shared/config.ts';
|
|
2
|
+
import type { HostServices } from '../../../contracts/ports.ts';
|
|
3
|
+
import type { CleanupScope } from '../../../core/cleanup.ts';
|
|
4
|
+
/** Shadow a hidden entry with an empty renderer; releasing it restores DSH's. */
|
|
5
|
+
export declare function mountHeaderVisibility(slots: HostServices['slots'], view: Pick<ViewConfig, 'showHeaderSubagents' | 'showHeaderTeam'>, cleanup: CleanupScope): void;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { ImplementedFeature } from '../../contracts/feature.ts';
|
|
2
2
|
/**
|
|
3
3
|
* Blank-session page. DSH renders the Conversation shell in its `hero` phase
|
|
4
|
-
* here
|
|
5
|
-
*
|
|
6
|
-
* phase transition itself to the host.
|
|
4
|
+
* here. This module lays out the greeting and Composer and mounts a decorative
|
|
5
|
+
* ASCII ripple field; the phase transition itself belongs to the host.
|
|
7
6
|
*/
|
|
8
7
|
export declare const newSessionFeature: ImplementedFeature;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { HeroRippleImpulse } from '../../contracts/hero-canvas.ts';
|
|
2
|
+
/** One character's stable grain and time-varying light, before the edge fade. */
|
|
3
|
+
export declare function rippleCell(x: number, y: number, elapsed: number, width: number, height: number, impulses?: readonly HeroRippleImpulse[]): {
|
|
4
|
+
alpha: number;
|
|
5
|
+
glyph: string;
|
|
6
|
+
};
|
|
7
|
+
/** Stationary ASCII rows lit by an autonomous, slowly swelling wave field. */
|
|
8
|
+
export declare function drawHeroRipples(canvas: HTMLCanvasElement, elapsed: number, impulses?: readonly HeroRippleImpulse[]): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copy for the
|
|
2
|
+
* Copy for the CCD settings section.
|
|
3
3
|
*
|
|
4
4
|
* The page is the plugin's only owned surface with its own words: everything
|
|
5
5
|
* else mirrors a host label. The dictionary is registered through the locale
|
|
@@ -9,12 +9,17 @@
|
|
|
9
9
|
export declare const SETTINGS_NAMESPACE = "ccdSettings";
|
|
10
10
|
/** Simplified Chinese dictionary; the key set is the source of truth. */
|
|
11
11
|
export declare const zh: {
|
|
12
|
+
readonly nav: 'Claude 主题';
|
|
12
13
|
readonly summary: 'CCD 风格界面 · 外观 · 字体';
|
|
13
14
|
readonly 'section.general': '通用';
|
|
14
15
|
readonly 'section.features': '模块';
|
|
15
16
|
readonly 'section.appearance': '外观';
|
|
16
17
|
readonly 'section.fonts': '字体';
|
|
17
18
|
readonly 'section.view': '视图';
|
|
19
|
+
readonly 'field.showHeaderSubagents': '显示顶栏子代理入口';
|
|
20
|
+
readonly 'hint.showHeaderSubagents': '显示会话顶栏的子代理数量与列表入口,默认关闭;子代理运行与侧栏树不受影响';
|
|
21
|
+
readonly 'field.showHeaderTeam': '显示顶栏团队入口';
|
|
22
|
+
readonly 'hint.showHeaderTeam': '显示会话顶栏的智能体团队入口,默认关闭;团队功能不受影响';
|
|
18
23
|
readonly 'field.showEmptyGroups': '显示空分组';
|
|
19
24
|
readonly 'hint.showEmptyGroups': '关掉时没有会话的工作区不再显示;视图选项菜单里的同一项';
|
|
20
25
|
readonly 'field.enabled': '启用 CCD 风格界面';
|
|
@@ -2,7 +2,7 @@ import type { Context } from '@deepseek-ai/cordis';
|
|
|
2
2
|
import type { ConfigFormPort, DomPort, ThemePreferencePort } from '../../contracts/ports.ts';
|
|
3
3
|
import type { CleanupScope } from '../../core/cleanup.ts';
|
|
4
4
|
/**
|
|
5
|
-
* Register
|
|
5
|
+
* Register this plugin in the main settings navigation.
|
|
6
6
|
*
|
|
7
7
|
* The page lives outside the activation scope on purpose: switching the
|
|
8
8
|
* interface off releases every style resource, and the page has to survive that
|
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis';
|
|
2
2
|
import type { ReactElement } from 'react';
|
|
3
|
-
import type {
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
* The page owns its copy through the locale service and its form through the
|
|
8
|
-
* plugin's own `configForms` handle, so it needs only the slots and locale
|
|
9
|
-
* services. Both are injected as a pair: without an installed locale face a
|
|
10
|
-
* registration that declares a namespace fails loud at render time, so a
|
|
11
|
-
* deployment that lacks the service keeps the page unmounted instead.
|
|
12
|
-
* @param ctx - client context.
|
|
13
|
-
* @param key - `<package>#<row id>` of the row whose configuration page this is.
|
|
14
|
-
* @param component - the bound page component.
|
|
15
|
-
* @returns the injected scope, released with `dispose()`.
|
|
16
|
-
*/
|
|
17
|
-
export declare function registerSettingsPage(ctx: Context, key: string, component: (props: RowConfigPageProps) => ReactElement | null): Pick<ReturnType<Context['inject']>, 'dispose'>;
|
|
3
|
+
import type { SettingsSectionProps } from '../../compat/settings-section.ts';
|
|
4
|
+
/** Register the plugin form as a top-level settings section with localized copy. */
|
|
5
|
+
export declare function registerSettingsPage(ctx: Context, id: string, component: (props: SettingsSectionProps) => ReactElement | null): Pick<ReturnType<Context['inject']>, 'dispose'>;
|
|
@@ -2,6 +2,8 @@ import type { ReactElement } from 'react';
|
|
|
2
2
|
import type { ViewOptionsPort } from '../../contracts/ports.ts';
|
|
3
3
|
export interface ViewOptionsCardProps {
|
|
4
4
|
readonly port: ViewOptionsPort;
|
|
5
|
+
readonly groupByStatus?: boolean;
|
|
6
|
+
readonly setGroupByStatus?: (value: boolean) => void;
|
|
5
7
|
/** `view.showEmptyGroups`: whether empty Workspaces are kept on screen. */
|
|
6
8
|
readonly showEmptyGroups: boolean;
|
|
7
9
|
/** Write the switch back through the settings transport. */
|
|
@@ -21,10 +23,11 @@ export interface ViewOptionsCardProps {
|
|
|
21
23
|
* out of the host's card and renames only the archived-visibility triple, which
|
|
22
24
|
* is the one set the reference names differently (活跃 / 已归档 / 全部).
|
|
23
25
|
*
|
|
24
|
-
*
|
|
25
|
-
* `view.showEmptyGroups` through the settings
|
|
26
|
+
* The empty-group switch and status grouping mode are this plugin's own state:
|
|
27
|
+
* they write `view.showEmptyGroups` / `view.groupByStatus` through the settings
|
|
28
|
+
* transport, and a write re-mounts
|
|
26
29
|
* the plugin, so the card closes behind it. `清除筛选` puts the filter rows back
|
|
27
30
|
* to their defaults and exists only while one of them is off its default, which
|
|
28
31
|
* is what the reference does with `Clear filters`.
|
|
29
32
|
*/
|
|
30
|
-
export declare function ViewOptionsCard({ port, showEmptyGroups, setShowEmptyGroups, }: ViewOptionsCardProps): ReactElement | null;
|
|
33
|
+
export declare function ViewOptionsCard({ port, showEmptyGroups, setShowEmptyGroups, groupByStatus, setGroupByStatus, }: ViewOptionsCardProps): ReactElement | null;
|
|
@@ -7,8 +7,8 @@ import type { ViewOptionsSettingsPort } from '../../contracts/ports.ts';
|
|
|
7
7
|
*
|
|
8
8
|
* The card is this plugin's own surface, so it is registered like one: a React
|
|
9
9
|
* entry in `shell.overlay`, holding the driver that watches the host's trigger
|
|
10
|
-
* and drives the host's own menu (`compat/view-options.ts`).
|
|
11
|
-
*
|
|
10
|
+
* and drives the host's own menu (`compat/view-options.ts`). Its own values,
|
|
11
|
+
* `view.showEmptyGroups` and `view.groupByStatus`, go through the settings
|
|
12
12
|
* transport the same way the configuration page writes its fields — a write
|
|
13
13
|
* re-mounts the plugin, which is why the card closes behind the switch.
|
|
14
14
|
*
|
|
@@ -54,8 +54,14 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
|
54
54
|
code: z<string, string, "defined">;
|
|
55
55
|
}>>>, "volatile-defined">;
|
|
56
56
|
view: z<NoInfer<Schemastery.ObjectS<NoInfer<{
|
|
57
|
+
showHeaderSubagents: z<boolean, boolean, "defined">;
|
|
58
|
+
showHeaderTeam: z<boolean, boolean, "defined">;
|
|
59
|
+
groupByStatus: z<boolean, boolean, "defined">;
|
|
57
60
|
showEmptyGroups: z<boolean, boolean, "defined">;
|
|
58
61
|
}>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
|
|
62
|
+
showHeaderSubagents: z<boolean, boolean, "defined">;
|
|
63
|
+
showHeaderTeam: z<boolean, boolean, "defined">;
|
|
64
|
+
groupByStatus: z<boolean, boolean, "defined">;
|
|
59
65
|
showEmptyGroups: z<boolean, boolean, "defined">;
|
|
60
66
|
}>>>, "volatile-defined">;
|
|
61
67
|
}>>, Schemastery.ObjectT<NoInfer<{
|
|
@@ -99,8 +105,14 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
|
99
105
|
code: z<string, string, "defined">;
|
|
100
106
|
}>>>, "volatile-defined">;
|
|
101
107
|
view: z<NoInfer<Schemastery.ObjectS<NoInfer<{
|
|
108
|
+
showHeaderSubagents: z<boolean, boolean, "defined">;
|
|
109
|
+
showHeaderTeam: z<boolean, boolean, "defined">;
|
|
110
|
+
groupByStatus: z<boolean, boolean, "defined">;
|
|
102
111
|
showEmptyGroups: z<boolean, boolean, "defined">;
|
|
103
112
|
}>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
|
|
113
|
+
showHeaderSubagents: z<boolean, boolean, "defined">;
|
|
114
|
+
showHeaderTeam: z<boolean, boolean, "defined">;
|
|
115
|
+
groupByStatus: z<boolean, boolean, "defined">;
|
|
104
116
|
showEmptyGroups: z<boolean, boolean, "defined">;
|
|
105
117
|
}>>>, "volatile-defined">;
|
|
106
118
|
}>>, "plain">;
|
|
@@ -16,7 +16,7 @@ export declare const APPEARANCE_FIELDS: readonly ['canvas', 'sidebar'];
|
|
|
16
16
|
/** Fields of the typeface section; an empty string means "system stack". */
|
|
17
17
|
export declare const FONT_FIELDS: readonly ['uiLatin', 'uiCjk', 'code'];
|
|
18
18
|
/** Fields of the view-options section. */
|
|
19
|
-
export declare const VIEW_FIELDS: readonly ['showEmptyGroups'];
|
|
19
|
+
export declare const VIEW_FIELDS: readonly ['showEmptyGroups', 'groupByStatus', 'showHeaderSubagents', 'showHeaderTeam'];
|
|
20
20
|
export type AppearanceField = typeof APPEARANCE_FIELDS[number];
|
|
21
21
|
export type FontField = typeof FONT_FIELDS[number];
|
|
22
22
|
export type ViewField = typeof VIEW_FIELDS[number];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-claude-desktop-theme",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Claude Code Desktop-style theme for DeepSeek Harness (DSH) Desktop on macOS and Windows, with light/dark themes, model/effort pickers and an interactive pixel whale",
|
|
6
6
|
"author": "zkforge",
|
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
"check": "npm run typecheck && npm run check:architecture && npm test && npm run build && npm run check:package",
|
|
86
86
|
"prepack": "npm run check",
|
|
87
87
|
"pack:local": "npm pack --pack-destination artifacts",
|
|
88
|
+
"preview:install": "node scripts/install-local.mjs",
|
|
88
89
|
"pet:gifs": "node scripts/pet-gifs.mjs",
|
|
89
90
|
"effort:gifs": "node scripts/effort-gif.mjs"
|
|
90
91
|
},
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
-
import type { ReactElement } from 'react';
|
|
3
|
-
import type { Disposer } from '../contracts/ports.ts';
|
|
4
|
-
/**
|
|
5
|
-
* The Plugins panel's row configuration slot.
|
|
6
|
-
*
|
|
7
|
-
* `@deepseek-ai/dsh-client-ui-plugin-manager` declares it in the child table of
|
|
8
|
-
* its `main` panel registration as `{ kind: 'keyed', scope: 'root' }` and keys
|
|
9
|
-
* it by `<package>#<row id>`; the row then grows a configuration page. The
|
|
10
|
-
* package is not part of this plugin's type baseline, so the two members used
|
|
11
|
-
* here are declared structurally and the real service object is passed through
|
|
12
|
-
* unchanged — the same treatment `contracts/ports.ts` gives the other
|
|
13
|
-
* out-of-baseline providers. Registration waits for the declaration, so a
|
|
14
|
-
* deployment without that panel simply keeps the page unmounted.
|
|
15
|
-
*/
|
|
16
|
-
export declare const ROW_CONFIG_SLOT = "plugins.row.config";
|
|
17
|
-
/** Props the panel renders a row configuration page with. */
|
|
18
|
-
export interface RowConfigPageProps {
|
|
19
|
-
/** `summary` beside a row title without a description, `page` for the form. */
|
|
20
|
-
readonly view?: string;
|
|
21
|
-
/** Locale seat synthesized from the registration's namespace. */
|
|
22
|
-
readonly t?: (key: string, params?: Record<string, unknown>) => string;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Register one row configuration page and wait for the slot to exist.
|
|
26
|
-
* @param ctx - context carrying the slots service.
|
|
27
|
-
* @param key - `<package>#<row id>` of the row whose page this is.
|
|
28
|
-
* @param locale - dictionary namespace for the page's `t` seat, when available.
|
|
29
|
-
* @param component - the page component.
|
|
30
|
-
* @returns the injection's disposer.
|
|
31
|
-
*/
|
|
32
|
-
export declare function mountRowConfigPage(ctx: Context, key: string, locale: string | undefined, component: (props: RowConfigPageProps) => ReactElement | null): Disposer;
|