dsh-claude-desktop-theme 0.3.0 → 0.4.1

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.
Files changed (36) hide show
  1. package/README.md +9 -5
  2. package/lib/client.js +9031 -3944
  3. package/lib/types/client/compat/account-menu.d.ts +4 -4
  4. package/lib/types/client/compat/account-more.d.ts +3 -0
  5. package/lib/types/client/compat/account-theme.d.ts +3 -0
  6. package/lib/types/client/compat/browser-header.d.ts +16 -0
  7. package/lib/types/client/compat/browser-menu.d.ts +15 -0
  8. package/lib/types/client/compat/files-pane.d.ts +78 -0
  9. package/lib/types/client/compat/header-menu-actions.d.ts +14 -0
  10. package/lib/types/client/compat/header-menus.d.ts +4 -0
  11. package/lib/types/client/compat/host-dom.d.ts +116 -0
  12. package/lib/types/client/compat/pane-chrome.d.ts +29 -0
  13. package/lib/types/client/compat/pane-icons.d.ts +23 -0
  14. package/lib/types/client/compat/pane-labels.d.ts +81 -0
  15. package/lib/types/client/compat/pane-tiles.d.ts +37 -0
  16. package/lib/types/client/compat/relative-file-path.d.ts +2 -0
  17. package/lib/types/client/compat/right-panes.d.ts +16 -0
  18. package/lib/types/client/compat/scroll-pill.d.ts +70 -0
  19. package/lib/types/client/compat/settings-section.d.ts +21 -0
  20. package/lib/types/client/compat/sidebar-action-alignment.d.ts +3 -0
  21. package/lib/types/client/compat/sidebar-session-icons.d.ts +3 -0
  22. package/lib/types/client/compat/view-switch.d.ts +46 -5
  23. package/lib/types/client/contracts/ports.d.ts +29 -1
  24. package/lib/types/client/features/conversation/index.d.ts +5 -3
  25. package/lib/types/client/features/conversation/view-switch-icons.d.ts +13 -0
  26. package/lib/types/client/features/settings/locales.d.ts +2 -1
  27. package/lib/types/client/features/settings/mount.d.ts +1 -1
  28. package/lib/types/client/features/settings/register.d.ts +3 -15
  29. package/lib/types/client/features/shell/index.d.ts +9 -3
  30. package/lib/types/client/features/sidebar/index.d.ts +1 -1
  31. package/lib/types/client/features/statistics/books.d.ts +1 -2
  32. package/lib/types/client/features/statistics/format.d.ts +4 -4
  33. package/lib/types/client/theme/mount.d.ts +2 -2
  34. package/lib/types/client/theme/palette.d.ts +2 -1
  35. package/package.json +2 -1
  36. package/lib/types/client/compat/plugin-manager.d.ts +0 -32
@@ -0,0 +1,3 @@
1
+ import type { Disposer } from '../contracts/ports.ts';
2
+ /** Share the tree's actual trailing edge, including its native scrollbar gutter. */
3
+ export declare function mountSidebarActionAlignment(document: Document): Disposer;
@@ -0,0 +1,3 @@
1
+ import type { Disposer } from '../contracts/ports.ts';
2
+ /** Identify the two shared Claude actions; unknown/localized actions keep host art. */
3
+ export declare function mountSidebarSessionIcons(document: Document): Disposer;
@@ -6,9 +6,50 @@ export declare const VIEW_WIDTH_PROPERTY = "--ccd-view-w";
6
6
  /** Animate selection changes; layout corrections must be immediate. */
7
7
  export declare const VIEW_DURATION_PROPERTY = "--ccd-view-duration";
8
8
  /**
9
- * Measure the selected ui-conversation tab and publish slider geometry.
10
- * MutationObserver handles tablist replacement and layout changes synchronously,
11
- * including occluded windows where animation frames are throttled.
12
- * @returns disposer that clears the observer and published properties.
9
+ * Marker on the tablist while it is parked in the sidebar's window-control row.
10
+ * `conversation.css` draws the fixed-position state from it; its absence means
11
+ * the host's own row (the header, or whatever the platform still offers) keeps
12
+ * the switcher.
13
13
  */
14
- export declare function mountViewSwitch(document: Document, report: (error: unknown) => void): Disposer;
14
+ export declare const VIEW_DOCK_ATTRIBUTE = "data-ccd-view-dock";
15
+ /** Custom property carrying the parked tablist's inset from the window's right edge. */
16
+ export declare const VIEW_DOCK_RIGHT_PROPERTY = "--ccd-view-dock-right";
17
+ /** Marker on a tab whose label is drawn as artwork, naming the View it selects. */
18
+ export declare const VIEW_TAB_ATTRIBUTE = "data-ccd-view";
19
+ /** Marker on the artwork seat injected into a decorated tab. */
20
+ export declare const VIEW_GLYPH_ATTRIBUTE = "data-ccd-view-glyph";
21
+ /**
22
+ * The parked pill's inset from the sidebar column's right edge, in px. Measured
23
+ * at @2x on the reference: the column's divider sits 16 device px right of the
24
+ * pill's right edge (docs/issues/img/todo-sidebar-sessions-target.webp).
25
+ */
26
+ export declare const VIEW_DOCK_INSET = 8;
27
+ /** Bundled artwork, one per shipped View; see features/conversation/view-switch-icons.ts. */
28
+ export interface ViewSwitchIcons {
29
+ readonly chat: string;
30
+ readonly trajectory: string;
31
+ }
32
+ /**
33
+ * Shape the host's View switcher, and park it where the reference has it.
34
+ *
35
+ * Three jobs, one observer:
36
+ * - Publish the selected segment's geometry for the sliding thumb
37
+ * (`--ccd-view-x` / `-w` / `-duration`), measured against the tablist.
38
+ * - Replace each shipped tab's text label with bundled artwork (the host draws
39
+ * the labels itself; a tab has no icon of its own), reversibly.
40
+ * - Park the tablist in the sidebar column's top-right corner — the reference
41
+ * keeps the View switcher on the window-control row — by measuring the
42
+ * column and publishing its inset (`data-ccd-view-dock` +
43
+ * `--ccd-view-dock-right`). The node stays where React put it: only CSS moves
44
+ * it, exactly as the macOS sidebar toggle is parked.
45
+ *
46
+ * The mutation observer covers tablist replacement, selection, frame drags
47
+ * (inline grid tracks) and the collapse flag, synchronously, including occluded
48
+ * windows where animation frames are throttled. A ResizeObserver on the sidebar
49
+ * column covers what no attribute says: the column's own width while the grid
50
+ * track animates between 0 and its settled value.
51
+ *
52
+ * @returns disposer that clears the observers, every injected node, every
53
+ * written attribute and every published property.
54
+ */
55
+ export declare function mountViewSwitch(document: Document, icons: ViewSwitchIcons, report: (error: unknown) => void): Disposer;
@@ -82,9 +82,16 @@ export interface SidebarRightPort {
82
82
  }): void;
83
83
  /** Focus a tab and the pane holding it; a missing tab is left alone. */
84
84
  focus(tabId: string): void;
85
- /** Open tab metadata across adopted Sessions. */
85
+ /**
86
+ * Open tab metadata across adopted Sessions — and, in the shipped face, the
87
+ * snapshot store behind it: the plugin's pane layer re-reads the layout
88
+ * whenever that list changes, which covers every way a tab opens, closes or
89
+ * changes pane. A build whose source cannot be observed is read once per
90
+ * mutation instead.
91
+ */
86
92
  readonly openTabs: {
87
93
  getSnapshot(): readonly SidebarTabRecord[];
94
+ subscribe?(listener: () => void): Disposer;
88
95
  };
89
96
  /**
90
97
  * Collapse the column, or expand it and focus its active dock pane.
@@ -95,6 +102,27 @@ export interface SidebarRightPort {
95
102
  * keeps that row out rather than offering one that cannot act.
96
103
  */
97
104
  toggleExpanded?(): void;
105
+ /**
106
+ * Take one docked tab out into a floating pane, and put one back.
107
+ *
108
+ * The panel's own renderer draws at most one pane or two horizontal panes —
109
+ * its layout component throws on anything else — so a vertical split or a
110
+ * third pane cannot be asked of it. A floating pane has no such limit (the
111
+ * layout stores a rectangle per float and the package allows any number), so
112
+ * `compat/right-panes.ts` builds the panel's panes out of these two calls and
113
+ * draws their boxes itself. A missing `float` means a build that cannot host
114
+ * panes at all: the panel keeps its tabs, exactly as it does today.
115
+ * Source: packages/client/ui-sidebar-right/src/client/controller.ts
116
+ * (`float(tabId, rect)`, `dock(paneId)`).
117
+ */
118
+ float?(tabId: string, rect?: {
119
+ x: number;
120
+ y: number;
121
+ width: number;
122
+ height: number;
123
+ }): void;
124
+ /** Return one floating pane's tab to the panel's docked column. */
125
+ dock?(paneId: string): void;
98
126
  }
99
127
  /**
100
128
  * The tab-type registry that face publishes as `ctx.sidebarRightTabs`. A header
@@ -5,9 +5,11 @@ import type { ImplementedFeature } from '../../contracts/feature.ts';
5
5
  * adapts the header chrome, the transcript column and the message surfaces.
6
6
  *
7
7
  * The header keeps DSH's own View switcher: the host still owns which View is
8
- * selected and how it is rendered, and this module only moves the tablist onto
9
- * the title line and publishes the selected segment's geometry so the
10
- * stylesheet can slide the thumb onto it.
8
+ * selected and how it is rendered. This module swaps the two shipped Views'
9
+ * text labels for bundled artwork, publishes the selected segment's geometry so
10
+ * the stylesheet can slide the thumb onto it, and parks the tablist in the
11
+ * sidebar's window-control row while that column has a corner to hold it
12
+ * (`compat/view-switch.ts`).
11
13
  *
12
14
  * The transcript's own edge fade is published the same way: the host owns the
13
15
  * scroll position, `compat/conversation-fade.ts` turns it into two attributes,
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The two View switcher glyphs, bundled as trusted static markup.
3
+ *
4
+ * Drawn to the reference's own segments (docs/issues/img/todo-sidebar-sessions-target.webp,
5
+ * @2x): a pair of speech bubbles for the chat View and the `</>` pair for the
6
+ * trajectory View, both on the CCD 16 grid — 1–1.2px stroke (each glyph's own
7
+ * weight read off the reference), round caps and joins, `currentColor` ink,
8
+ * ink box ≈ 12.5 × 11px inside the 16px artwork.
9
+ */
10
+ export declare const VIEW_SWITCH_ICONS: Readonly<{
11
+ chat: "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M10.4 8.3a2.6 2.6 0 0 1-2.6 2.6H5.7L3.3 12.5V5.9a2.6 2.6 0 0 1 2.6-2.6h1.9a2.6 2.6 0 0 1 2.6 2.6Z\"/>\n <path d=\"M10.3 5.9H12.1a2.1 2.1 0 0 1 2.1 2.1V10.4a2.1 2.1 0 0 1-2.1 2.1H10.25L9.1 13.1\"/>\n</svg>";
12
+ trajectory: "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M5.3 5.8 3.05 8l2.25 2.2\"/>\n <path d=\"M9.1 3.8 6.9 12.2\"/>\n <path d=\"M10.7 5.8 12.95 8l-2.25 2.2\"/>\n</svg>";
13
+ }>;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copy for the row configuration page.
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,6 +9,7 @@
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': '模块';
@@ -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 the configuration page for this plugin's own loader row.
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 { RowConfigPageProps } from '../../compat/plugin-manager.ts';
4
- /**
5
- * Register the configuration page for one plugin row.
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'>;
@@ -1,8 +1,14 @@
1
1
  import type { ImplementedFeature } from '../../contracts/feature.ts';
2
2
  /**
3
3
  * Window frame and column geometry: flat surfaces, the sidebar column and its
4
- * divider. The three tracks stay entirely `ui-layout`'s solve, so resizing the
5
- * sidebar with the handle moves the divider the pointer is on; the plugin only
6
- * paints the columns.
4
+ * divider, and the right panel's floating card. The three tracks stay entirely
5
+ * `ui-layout`'s solve, so resizing the sidebar with the handle moves the divider
6
+ * the pointer is on; the plugin only paints the columns.
7
+ *
8
+ * The right panel is a column's occupant rather than a track, so its card is
9
+ * two sheets: `shell.css` insets the panel's box and paints the surface, and
10
+ * `right-panel.css` dresses what the panel draws inside it — the file tree's
11
+ * rows included, which belong to no feature of this plugin's own. Both mount
12
+ * with the frame, because neither has a switch of its own to lose.
7
13
  */
8
14
  export declare const shellFeature: ImplementedFeature;
@@ -3,7 +3,7 @@ import type { ImplementedFeature } from '../../contracts/feature.ts';
3
3
  * Sidebar presentation: compact navigation rows, flat project groups and a
4
4
  * calmer foot. Every entry DSH registers — New Session, the global panel list,
5
5
  * the workspace browser and Settings — stays exactly where the host put it; the
6
- * account menu is reshaped, never re-authored.
6
+ * account menu gains a More submenu that forwards the host feedback action.
7
7
  *
8
8
  * The one list policy this module owns is the provisional New Session row: DSH
9
9
  * creates the Session as soon as New Session is used, and the host marks that
@@ -13,8 +13,7 @@
13
13
  * ```
14
14
  *
15
15
  * Only the sentence is copied; nothing is fetched and no book text is
16
- * involved. The copy stays English, exactly as the reference writes it —
17
- * including its typographic apostrophe and multiplication sign.
16
+ * involved. Titles and sentences are localized into Simplified Chinese.
18
17
  */
19
18
  /** One comparable book: the title as printed, and the tokens it would take. */
20
19
  export interface Book {
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Number and date formatting for the statistics card.
3
3
  *
4
- * The card's copy is English, so its separators and its 12-hour clock are too:
5
- * every formatter here is fixed to `en-US`, which is what the reference uses.
4
+ * The card uses Simplified Chinese dates and a 24-hour clock. Compact token
5
+ * units stay unchanged so the metrics and chart labels fit the card.
6
6
  * They live in their own module because both the data layer (`view.ts`) and the
7
7
  * DOM layer (`card.ts`) need them, and neither should import the other.
8
8
  */
@@ -21,14 +21,14 @@ export declare function formatCount(value: number): string;
21
21
  */
22
22
  export declare function formatTokens(value: number): string;
23
23
  /**
24
- * One hour of the day, as the reference labels it (`11 AM`).
24
+ * One hour of the day in the 24-hour clock (`11:00`).
25
25
  *
26
26
  * @param hour - local hour, 0-23.
27
27
  * @returns the label.
28
28
  */
29
29
  export declare function formatHour(hour: number): string;
30
30
  /**
31
- * One `YYYY-MM-DD` key as the reference labels a chart day (`Sep 30`).
31
+ * One `YYYY-MM-DD` key as a Chinese chart date (`9月30日`).
32
32
  *
33
33
  * @param date - local day key.
34
34
  * @returns the short label.
@@ -3,8 +3,8 @@ import type { CleanupScope } from '../core/cleanup.ts';
3
3
  /**
4
4
  * Plugin-scoped presentation base: the root activation marker, the design
5
5
  * variables, the shared Composer geometry two features depend on (siblings must
6
- * not import each other), the host popup chrome (DESIGN.md §6.7) and the
7
- * semantic token overrides.
6
+ * not import each other), the host popup chrome (DESIGN.md §6.7), the ink the
7
+ * window's scrollbars are painted in and the semantic token overrides.
8
8
  *
9
9
  * The override layer is recomputed on every mount, so a configuration change
10
10
  * releases the previous layer through the same scope that owns the stylesheets
@@ -24,6 +24,7 @@ export interface Palette {
24
24
  readonly track: string;
25
25
  readonly raised: string;
26
26
  readonly hover: string;
27
+ readonly hoverStrong: string;
27
28
  readonly selected: string;
28
29
  readonly border: string;
29
30
  readonly borderStrong: string;
@@ -37,7 +38,7 @@ export interface Palette {
37
38
  */
38
39
  export declare const BUILT_IN_SURFACES: Readonly<{
39
40
  canvas: "#fcfcfb";
40
- sidebar: "#fbfbfa";
41
+ sidebar: "#fbfbf9";
41
42
  border: "#e3e3e1";
42
43
  }>;
43
44
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-claude-desktop-theme",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
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;