@danielng23/dsh-studio-client-ui-edex 0.1.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/lib/index.js ADDED
@@ -0,0 +1,77 @@
1
+ import { settingsNamespace } from "@deepseek-ai/dsh-settings";
2
+ import z from "@deepseek-ai/schemastery";
3
+ //#region src/settings.ts
4
+ /**
5
+ * eDEX theme-color setting: the single durable accent that drives both the
6
+ * shell frame's palette (`--edex-*`) and the terminal token override layer
7
+ * over the original UI (`--dsw-alias-*`). One color in, a full CRT family
8
+ * out — primary, dim midtone, dark border, and a faint tinted panel tone —
9
+ * while the semantic accents (amber warn, red error, cyan info) stay fixed.
10
+ * Shared by the Host loader entry (schema registration) and the browser half
11
+ * (scope binding, token overrides, and the settings row).
12
+ */
13
+ /** Settings namespace owned by the eDEX shell plugin. */
14
+ const EDEX_SETTINGS_NAMESPACE = "ui-edex";
15
+ /** Field carrying the selected theme color. */
16
+ const THEME_COLOR_FIELD = "themeColor";
17
+ /** The default theme color — the LateNight console's amber/gold VU accent. */
18
+ const DEFAULT_THEME_COLOR = "#f0bb2b";
19
+ /** Durable theme-color schema; also the wire envelope the browser scope validates against. */
20
+ const EdexSettingsSchema = z.object({ [THEME_COLOR_FIELD]: z.string().default(DEFAULT_THEME_COLOR) });
21
+ Object.freeze([
22
+ {
23
+ id: "analyzed",
24
+ labelKey: "edex.preset.analyzed",
25
+ color: "#f0bb2b"
26
+ },
27
+ {
28
+ id: "terminal",
29
+ labelKey: "edex.preset.terminal",
30
+ color: "#46f282"
31
+ },
32
+ {
33
+ id: "amber",
34
+ labelKey: "edex.preset.amber",
35
+ color: "#e6c85c"
36
+ },
37
+ {
38
+ id: "cyan",
39
+ labelKey: "edex.preset.cyan",
40
+ color: "#5ad1e0"
41
+ },
42
+ {
43
+ id: "violet",
44
+ labelKey: "edex.preset.violet",
45
+ color: "#c792ea"
46
+ }
47
+ ]);
48
+ Object.freeze({
49
+ amber: "#f0bb2b",
50
+ red: "#d00000",
51
+ cyan: "#00c8ff",
52
+ led: "#159a43",
53
+ blue: "#1767d8"
54
+ });
55
+ Object.freeze({
56
+ canvas: "#0e0e0e",
57
+ card: "#1b1b1c",
58
+ inset: "#101010",
59
+ border: "#3c3c3c",
60
+ divider: "#2a2a2a",
61
+ titleStrip: "#242424"
62
+ });
63
+ //#endregion
64
+ //#region src/index.ts
65
+ /**
66
+ * Register the durable theme-color section when the settings service is
67
+ * composed. The browser half binds a scope to this namespace, so the user's
68
+ * Theme Color choice persists in the user-settings document.
69
+ * @param ctx - Host context that may acquire the settings service.
70
+ */
71
+ function apply(ctx) {
72
+ ctx.inject(["settings"], (settingsCtx) => {
73
+ settingsCtx.settings.register(settingsNamespace(EDEX_SETTINGS_NAMESPACE), EdexSettingsSchema);
74
+ });
75
+ }
76
+ //#endregion
77
+ export { apply };
@@ -0,0 +1,10 @@
1
+ import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import type { FilesState } from '../shared/types.ts';
3
+ /** The bottom-left content (rendered inside the eDEX shell's bottom-left cell). */
4
+ export declare function BottomPanel({ useFiles, refresh, navigate, selectFile, }: {
5
+ useFiles: SnapshotSelectorHook<FilesState>;
6
+ refresh: () => void;
7
+ navigate: (name: string) => void;
8
+ selectFile: (name: string) => void;
9
+ }): import("react").JSX.Element;
10
+ //# sourceMappingURL=BottomPanel.d.ts.map
@@ -0,0 +1,12 @@
1
+ import type { EditorStatus } from '../shared/types.ts';
2
+ export declare function EditorPane({ path, content, readOnly, editor, onMarkDirty, onSave, onDiscard, onCancelDiscard, }: {
3
+ path: string;
4
+ content: string;
5
+ readOnly: boolean;
6
+ editor: EditorStatus;
7
+ onMarkDirty: () => void;
8
+ onSave: (content: string) => void;
9
+ onDiscard: () => void;
10
+ onCancelDiscard: () => void;
11
+ }): import("react").JSX.Element;
12
+ //# sourceMappingURL=EditorPane.d.ts.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Bottom-right preview pane: renders the file selected in the bottom-left
3
+ * browser — text files open a vim-capable CodeMirror editor (see EditorPane),
4
+ * images and videos render from their data: payloads, and a message shows for
5
+ * everything else. Empty until a file is selected.
6
+ */
7
+ import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
8
+ import type { FilesState } from '../shared/types.ts';
9
+ /** The bottom-right content (rendered inside the eDEX shell's bottom-right cell). */
10
+ export declare function PreviewPane({ useFiles, markDirty, saveEditor, confirmDiscard, cancelDiscard, }: {
11
+ useFiles: SnapshotSelectorHook<FilesState>;
12
+ /** Mark the open buffer dirty (called by the editor on doc changes). */
13
+ markDirty: () => void;
14
+ /** Persist the editor buffer through the host `writeFile` Remote. */
15
+ saveEditor: (content: string) => void;
16
+ /** Discard the dirty buffer and continue the paused navigation. */
17
+ confirmDiscard: () => void;
18
+ /** Keep the dirty buffer and cancel the paused navigation. */
19
+ cancelDiscard: () => void;
20
+ }): import("react").JSX.Element;
21
+ //# sourceMappingURL=PreviewPane.d.ts.map
@@ -0,0 +1,10 @@
1
+ import type { CommandResult } from '@danielng23/dsh-studio-host-system-metrics/types';
2
+ export interface TerminalPanelProps {
3
+ /** Run one shell command on the host (`systemMetrics.runCommand`). */
4
+ runCommand: (command: string) => Promise<CommandResult>;
5
+ /** The initial directory (the host process cwd); '/ 'when unknown. */
6
+ initialCwd?: string | undefined;
7
+ }
8
+ /** The bottom-right content (rendered inside the eDEX shell's bottom-right cell). */
9
+ export declare function TerminalPanel({ runCommand, initialCwd }: TerminalPanelProps): import("react").JSX.Element;
10
+ //# sourceMappingURL=TerminalPanel.d.ts.map
@@ -0,0 +1,47 @@
1
+ import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import type { SessionListState, WorkspaceListState } from '@deepseek-ai/dsh-client-runtime/client';
3
+ import type { CommandResult } from '@danielng23/dsh-studio-host-system-metrics/types';
4
+ import type { FilesState, NetworkSnapshot, ObservableSource, PanelSnapshot } from '../shared/types.ts';
5
+ import '../theme/TerminalComposer.module.css';
6
+ import '../theme/TerminalSidebar.module.css';
7
+ import '../theme/ConversationScrollbar.module.css';
8
+ import '../theme/TerminalToolRows.module.css';
9
+ /** The frame region the original UI is squeezed into (grid-column track of the viewport). */
10
+ export declare const CENTER_LEFT = "17vw";
11
+ export declare const CENTER_RIGHT = "21.25vw";
12
+ export declare const CENTER_BOTTOM = "36vh";
13
+ /** The shell entry's inject face: panel actions plus the four hook seats. */
14
+ export interface EdexShellInjected {
15
+ /** Fetch storage + the current directory listing. */
16
+ refreshFiles: () => void;
17
+ /** Navigate into a directory (or '..' up). */
18
+ navigateFiles: (name: string) => void;
19
+ /** Select a file in the current directory (highlights the list row). */
20
+ selectFile: (name: string) => void;
21
+ /** Mark the open editor buffer dirty (called by the editor on doc changes). */
22
+ markDirty: () => void;
23
+ /** Persist the editor buffer through the host `writeFile` Remote. */
24
+ saveEditor: (content: string) => void;
25
+ /** Discard the dirty buffer and continue the paused navigation. */
26
+ confirmDiscard: () => void;
27
+ /** Keep the dirty buffer and cancel the paused navigation. */
28
+ cancelDiscard: () => void;
29
+ /** Run one shell command on the host for the bottom-right terminal. */
30
+ runCommand: (command: string) => Promise<CommandResult>;
31
+ hooks: {
32
+ panel: ObservableSource<PanelSnapshot>;
33
+ network: ObservableSource<NetworkSnapshot>;
34
+ files: ObservableSource<FilesState>;
35
+ /** Workspace list snapshot — feeds the terminal path prompt at the input's left edge. */
36
+ workspaces: ObservableSource<WorkspaceListState>;
37
+ /** Session list snapshot — the prompt follows the ACTIVE conversation's workspace. */
38
+ sessions: ObservableSource<SessionListState>;
39
+ /** Current theme color (the user's Settings → General → Theme Color pick). */
40
+ themeColor: ObservableSource<string>;
41
+ };
42
+ }
43
+ /** Full composed props of the shell entry (hooks arrive as `use*` selector hooks). */
44
+ export type EdexShellProps = InjectFace<EdexShellInjected>;
45
+ /** The full eDEX frame: left/right bars + bottom cells around the original UI. */
46
+ export declare function EdexShell({ usePanel, useNetwork, useFiles, useWorkspaces, useSessions, useThemeColor, refreshFiles, navigateFiles, selectFile, markDirty, saveEditor, confirmDiscard, cancelDiscard, runCommand, }: EdexShellProps): import("react").JSX.Element;
47
+ //# sourceMappingURL=EdexShell.d.ts.map
@@ -0,0 +1,23 @@
1
+ /**
2
+ * eDEX shell plugin, browser half: mounts the `systemMetrics` Host Remote
3
+ * contribution, runs one shared overview poller (left system panel + right
4
+ * network panel), and registers the shell frame into the root `shell.overlay`
5
+ * list slot. The user's Theme Color setting (Settings → General → Theme
6
+ * Color) drives one palette shared by the shell frame (`--edex-*` inline on
7
+ * the shell root) and a token override layer over the original UI
8
+ * (`--dsw-alias-*` on body) — icons included. Purely additive — the default
9
+ * surface stays composed, and the frame only reshapes it visually (restored
10
+ * on unload).
11
+ */
12
+ import type { Context } from '@deepseek-ai/cordis';
13
+ /** Required services: the slot registry, the theme service, the sessions and workspaces runtimes, the locale and settings transport, and the Remote carrier (namespace mounted in apply). */
14
+ export declare const inject: string[];
15
+ /**
16
+ * Client plugin body: mount the systemMetrics contribution, start the shared
17
+ * poller, apply the theme-color override layer, and register the shell frame
18
+ * and the Theme Color settings row.
19
+ * @param ctx - client root context.
20
+ * @returns disposer that unmounts the Remote namespace on unload.
21
+ */
22
+ export declare function apply(ctx: Context): Promise<() => Promise<void>>;
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,7 @@
1
+ import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import type { PanelSnapshot } from '../shared/types.ts';
3
+ /** The left column content (rendered inside the eDEX shell's left bar). */
4
+ export declare function LeftBar({ usePanel }: {
5
+ usePanel: SnapshotSelectorHook<PanelSnapshot>;
6
+ }): import("react").JSX.Element;
7
+ //# sourceMappingURL=LeftBar.d.ts.map
@@ -0,0 +1,8 @@
1
+ import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import type { NetworkSnapshot } from '../shared/types.ts';
3
+ /** The right column content (rendered inside the eDEX shell's right bar). */
4
+ export declare function RightBar({ useNetwork, color }: {
5
+ useNetwork: SnapshotSelectorHook<NetworkSnapshot>;
6
+ color: string;
7
+ }): import("react").JSX.Element;
8
+ //# sourceMappingURL=RightBar.d.ts.map
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Theme Color settings row, registered into the General section item slot: the
3
+ * label plus a swatch row of presets and a native color input for a custom
4
+ * accent. Selecting a swatch (or picking a color) writes the themeColor field
5
+ * through the eDEX settings scope; the current value rides the inject face's
6
+ * observable hook, so the row stays in step with every change — including
7
+ * ones made in the Host document while the dialog is open.
8
+ */
9
+ import type { InjectFace, PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
10
+ import type { ObservableSource } from '../shared/types.ts';
11
+ /** The row's inject face: the write plus the current-color hook source. */
12
+ export interface ThemeColorRowInjected {
13
+ /** Persist one theme color (scope.set('themeColor', color)). */
14
+ setColor: (color: string) => void;
15
+ /** Bare observable "current theme color" source bound to useColor. */
16
+ hooks: {
17
+ color: ObservableSource<string>;
18
+ };
19
+ }
20
+ /** Full composed props of the row. */
21
+ export type ThemeColorRowProps = PropsLocale<'settings.edex'> & InjectFace<ThemeColorRowInjected>;
22
+ /** The Theme Color row: label + presets + custom picker. */
23
+ export declare function ThemeColorRow({ useColor, setColor, t }: ThemeColorRowProps): import("react").JSX.Element;
24
+ //# sourceMappingURL=ThemeColorRow.d.ts.map
@@ -0,0 +1,32 @@
1
+ /** `settings.edex` namespace dictionaries (the Theme Color row's copy). */
2
+ /** Dictionary namespace owned by the eDEX shell plugin. */
3
+ export declare const NS = "settings.edex";
4
+ /** Simplified Chinese dictionary (the key-set source of truth). */
5
+ export declare const zh: {
6
+ 'edex.themeColor': string;
7
+ 'edex.custom': string;
8
+ 'edex.preset.terminal': string;
9
+ 'edex.preset.amber': string;
10
+ 'edex.preset.cyan': string;
11
+ 'edex.preset.violet': string;
12
+ 'edex.preset.blue': string;
13
+ };
14
+ /** The settings.edex namespace key union. */
15
+ export type EdexThemeKey = keyof typeof zh;
16
+ /** English dictionary, checked complete against the zh key set. */
17
+ export declare const en: {
18
+ 'edex.themeColor': string;
19
+ 'edex.custom': string;
20
+ 'edex.preset.terminal': string;
21
+ 'edex.preset.amber': string;
22
+ 'edex.preset.cyan': string;
23
+ 'edex.preset.violet': string;
24
+ 'edex.preset.blue': string;
25
+ };
26
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
27
+ interface LocaleNamespaceMap {
28
+ /** The eDEX Theme Color settings row's copy. */
29
+ 'settings.edex': EdexThemeKey;
30
+ }
31
+ }
32
+ //# sourceMappingURL=locales.d.ts.map
@@ -0,0 +1,28 @@
1
+ import type { FilesState, ObservableSource, SystemMetricsRemote } from './types.ts';
2
+ /** Lists directories, tracks the storage indicator, and owns editor saves. */
3
+ export declare class FilesController {
4
+ private readonly remote;
5
+ private readonly source;
6
+ private currentPath;
7
+ private pending;
8
+ constructor(remote: SystemMetricsRemote);
9
+ /** Bare observable files state source bound to the `useFiles` hook. */
10
+ get files(): ObservableSource<FilesState>;
11
+ /** Fetch storage + list the current (or first) directory. */
12
+ refresh(): Promise<void>;
13
+ /** List one directory and remember it as current. A dirty editor pauses the navigation. */
14
+ list(path: string): Promise<void>;
15
+ /** Navigate into a directory entry (or up for '..'). */
16
+ navigate(name: string): void;
17
+ /** Select a file in the current directory and load its preview (or the editor for text). */
18
+ selectFile(name: string): Promise<void>;
19
+ /** Mark the open buffer dirty (called by the editor on every doc change). */
20
+ markDirty(): void;
21
+ /** Persist the editor buffer through the `writeFile` Remote. */
22
+ saveEditor(content: string): Promise<void>;
23
+ /** Discard the dirty buffer and run the paused navigation. */
24
+ confirmDiscard(): void;
25
+ /** Keep the dirty buffer and drop the paused navigation. */
26
+ cancelDiscard(): void;
27
+ }
28
+ //# sourceMappingURL=files.d.ts.map
@@ -0,0 +1,29 @@
1
+ import type { NetworkSnapshot, ObservableSource, PanelSnapshot, SystemMetricsRemote } from './types.ts';
2
+ /** Poll cadence for the system overview. */
3
+ export declare const POLL_INTERVAL_MS = 2000;
4
+ /**
5
+ * Polls the overview Remote and derives the panel + network snapshots.
6
+ */
7
+ export declare class EdexPoller {
8
+ private readonly remote;
9
+ private readonly intervalMs;
10
+ private readonly panelSource;
11
+ private readonly networkSource;
12
+ private timer;
13
+ private previousCores;
14
+ private history;
15
+ private previousTraffic;
16
+ private upHistory;
17
+ private downHistory;
18
+ constructor(remote: SystemMetricsRemote, intervalMs?: number);
19
+ /** Bare observable panel snapshot source bound to the `usePanel` hook. */
20
+ get panel(): ObservableSource<PanelSnapshot>;
21
+ /** Bare observable network snapshot source bound to the `useNetwork` hook. */
22
+ get network(): ObservableSource<NetworkSnapshot>;
23
+ /** Start polling; the first overview is fetched immediately. */
24
+ start(): void;
25
+ /** Stop polling; the last snapshots stay readable. */
26
+ stop(): void;
27
+ private poll;
28
+ }
29
+ //# sourceMappingURL=monitor.d.ts.map
@@ -0,0 +1,17 @@
1
+ /** One hexasphere tile as the encom globe's particle builder consumes it. */
2
+ export interface GlobeTile {
3
+ lat: number;
4
+ lon: number;
5
+ b: readonly {
6
+ x: number;
7
+ y: number;
8
+ z: number;
9
+ }[];
10
+ }
11
+ /**
12
+ * Build the globe's hex-tile grid. Per-tile edge shrink varies slightly so
13
+ * the surface keeps the organic encom look instead of a uniform mesh.
14
+ * @returns tiles for the Globe `tiles` option.
15
+ */
16
+ export declare function generateGlobeTiles(): GlobeTile[];
17
+ //# sourceMappingURL=tiles.d.ts.map
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Shared client vocabulary for the eDEX shell: observable sources, the
3
+ * derived panel/network snapshots, the filesystem browser state, and the
4
+ * narrowed Remote face this plugin calls. All data originates from the
5
+ * `systemMetrics` Host Remote (host/system-metrics); the client only derives
6
+ * deltas and history.
7
+ */
8
+ import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
9
+ import type { CommandResult, DirectoryListing, FilePreview, HardwareInfo, NetworkInfo, ProcessSample, StorageInfo, SystemOverview, WriteResult } from '@danielng23/dsh-studio-host-system-metrics/types';
10
+ export type { FilePreview };
11
+ /** Bare observable snapshot source (getSnapshot + subscribe), the slot hooks seat. */
12
+ export interface ObservableSource<T> {
13
+ getSnapshot(): T;
14
+ subscribe(listener: () => void): () => void;
15
+ }
16
+ /** The generated systemMetrics Remote face narrowed to what this plugin calls. */
17
+ export interface SystemMetricsRemote {
18
+ overview: () => Promise<RemoteResult<SystemOverview>>;
19
+ listDirectory: (path: string) => Promise<RemoteResult<DirectoryListing>>;
20
+ readFile: (path: string) => Promise<RemoteResult<FilePreview>>;
21
+ writeFile: (path: string, content: string) => Promise<RemoteResult<WriteResult>>;
22
+ runCommand: (command: string) => Promise<RemoteResult<CommandResult>>;
23
+ }
24
+ /** Left-bar system telemetry snapshot (host overview + client-derived deltas/history). */
25
+ export interface PanelSnapshot {
26
+ readonly ok: boolean;
27
+ readonly timestamp: number;
28
+ readonly platform: string;
29
+ readonly uptimeSeconds: number;
30
+ readonly loadavg: readonly [number, number, number];
31
+ readonly memoryUsedGiB: number;
32
+ readonly memoryTotalGiB: number;
33
+ readonly swapUsedGiB: number;
34
+ readonly swapTotalGiB: number;
35
+ /** Current per-core busy percentage (0..100), one per logical core. */
36
+ readonly cpuBusy: readonly number[];
37
+ /** Per-core sparkline history (0..100), one array per logical core. */
38
+ readonly cpuHistory: readonly (readonly number[])[];
39
+ /** Min/max of the current per-core busy percentages. */
40
+ readonly cpuMin: number;
41
+ readonly cpuMax: number;
42
+ readonly thermalLevel: number | null;
43
+ readonly powerState: string | null;
44
+ readonly hardware: HardwareInfo;
45
+ readonly tasks: number;
46
+ /** Top processes by CPU, descending (capped at ten). */
47
+ readonly processes: readonly ProcessSample[];
48
+ }
49
+ /** Right-bar network snapshot (interface status + derived traffic history). */
50
+ export interface NetworkSnapshot {
51
+ readonly ok: boolean;
52
+ readonly network: NetworkInfo;
53
+ /** Recent up/down throughput samples in MB/s (oldest first). */
54
+ readonly upHistory: readonly number[];
55
+ readonly downHistory: readonly number[];
56
+ readonly upMbs: number;
57
+ readonly downMbs: number;
58
+ }
59
+ /** Bottom-left filesystem browser state. */
60
+ export interface FilesState {
61
+ readonly path: string;
62
+ readonly entries: readonly {
63
+ readonly name: string;
64
+ readonly isDirectory: boolean;
65
+ }[];
66
+ readonly storage: StorageInfo;
67
+ readonly error: string | null;
68
+ readonly phase: 'loading' | 'ready';
69
+ /** Currently selected file name (for the bottom-right preview), or null. */
70
+ readonly selected: string | null;
71
+ /** Preview payload of the selected file, or null while none is selected. */
72
+ readonly preview: FilePreview | null;
73
+ /** Bottom-right editor status (buffer content lives in the editor itself). */
74
+ readonly editor: EditorStatus;
75
+ }
76
+ /**
77
+ * Bottom-right editor status surfaced to the shell. The buffer CONTENT lives
78
+ * in the CodeMirror view (never re-rendered through React); this slice only
79
+ * carries the save-related state the shell needs for the status bar and the
80
+ * navigation discard guard.
81
+ */
82
+ export interface EditorStatus {
83
+ /** Open file path, or null when no editor is open. */
84
+ readonly path: string | null;
85
+ /** Whether the buffer has unsaved changes. */
86
+ readonly dirty: boolean;
87
+ /** Truncated (or otherwise read-only) files cannot be saved. */
88
+ readonly readOnly: boolean;
89
+ /** True while a save request is in flight. */
90
+ readonly saving: boolean;
91
+ /** Last save error (cleared on success); null while clean. */
92
+ readonly error: string | null;
93
+ /** Last successful save (wall-clock ms + bytes written); null until one happens. */
94
+ readonly savedAt: {
95
+ readonly at: number;
96
+ readonly sizeBytes: number;
97
+ } | null;
98
+ /** True while the shell asks to discard the dirty buffer before navigating. */
99
+ readonly pendingDiscard: boolean;
100
+ }
101
+ /** Empty editor status (no editor open). */
102
+ export declare const EMPTY_EDITOR: EditorStatus;
103
+ /** Empty snapshot values rendered before the first successful overview. */
104
+ export declare const EMPTY_PANEL: PanelSnapshot;
105
+ /** Empty snapshot values rendered before the first successful overview. */
106
+ export declare const EMPTY_NETWORK: NetworkSnapshot;
107
+ /** Empty snapshot values rendered before the first successful overview. */
108
+ export declare const EMPTY_FILES: FilesState;
109
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,10 @@
1
+ /** Host loader entry for the eDEX shell plugin. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ /**
4
+ * Register the durable theme-color section when the settings service is
5
+ * composed. The browser half binds a scope to this namespace, so the user's
6
+ * Theme Color choice persists in the user-settings document.
7
+ * @param ctx - Host context that may acquire the settings service.
8
+ */
9
+ export declare function apply(ctx: Context): void;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,75 @@
1
+ /**
2
+ * eDEX theme-color setting: the single durable accent that drives both the
3
+ * shell frame's palette (`--edex-*`) and the terminal token override layer
4
+ * over the original UI (`--dsw-alias-*`). One color in, a full CRT family
5
+ * out — primary, dim midtone, dark border, and a faint tinted panel tone —
6
+ * while the semantic accents (amber warn, red error, cyan info) stay fixed.
7
+ * Shared by the Host loader entry (schema registration) and the browser half
8
+ * (scope binding, token overrides, and the settings row).
9
+ */
10
+ import z from '@deepseek-ai/schemastery';
11
+ import type { ThemeTokenOverrides } from '@deepseek-ai/dsh-client-ui-theme/client';
12
+ /** Settings namespace owned by the eDEX shell plugin. */
13
+ export declare const EDEX_SETTINGS_NAMESPACE = "ui-edex";
14
+ /** Field carrying the selected theme color. */
15
+ export declare const THEME_COLOR_FIELD = "themeColor";
16
+ /** The default theme color — the classic terminal green. */
17
+ export declare const DEFAULT_THEME_COLOR = "#46f282";
18
+ /** Durable theme-color section shared by the Host schema and the browser scope. */
19
+ export interface EdexSettings {
20
+ /** The accent color driving the whole eDEX palette. */
21
+ themeColor: string;
22
+ }
23
+ /** Durable theme-color schema; also the wire envelope the browser scope validates against. */
24
+ export declare const EdexSettingsSchema: z<EdexSettings>;
25
+ /** One selectable preset swatch. */
26
+ export interface ThemeColorPreset {
27
+ /** Stable preset id (the swatch key). */
28
+ id: string;
29
+ /** Locale key for the swatch's accessible name. */
30
+ labelKey: string;
31
+ /** The accent color this preset applies. */
32
+ color: string;
33
+ }
34
+ /** Preset swatches offered in the Theme Color settings row. */
35
+ export declare const THEME_COLOR_PRESETS: readonly ThemeColorPreset[];
36
+ /** The semantic accents that stay fixed across theme colors. */
37
+ export declare const FIXED_ACCENTS: Readonly<{
38
+ amber: "#e6c85c";
39
+ red: "#e65a5a";
40
+ cyan: "#5ad1e0";
41
+ }>;
42
+ /** The full eDEX palette derived from one accent color. */
43
+ export interface EdexPalette {
44
+ /** The primary accent (text, icons, fills). */
45
+ primary: string;
46
+ /** Muted midtone (secondary text, icon tints). */
47
+ dim: string;
48
+ /** Dark border tone. */
49
+ border: string;
50
+ /** Faint tinted panel background. */
51
+ panel2: string;
52
+ }
53
+ /** Normalize an #rgb/#rrggbb hex to lowercase #rrggbb, or null when invalid. */
54
+ export declare function normalizeHex(value: string): string | null;
55
+ /** Derive the full CRT family from one accent color. */
56
+ export declare function paletteFor(color: string): EdexPalette;
57
+ /** The eDEX shell frame's CSS variables for one palette (amber/red/cyan stay in the stylesheet). */
58
+ export declare function shellVarsFor(palette: EdexPalette): Record<string, string>;
59
+ /**
60
+ * The full `--edex-*` variable set for the ORIGINAL UI (the composer, sidebar,
61
+ * and conversation scrollbar live outside the shell frame, so the theme CSS
62
+ * resolves these from `body` — set there by the browser half, with the static
63
+ * accents joining the dynamic palette). The shell frame defines its own copy
64
+ * on `.shell` and overrides it inline, so the two never fight.
65
+ */
66
+ export declare function bodyVarsFor(palette: EdexPalette): Record<string, string>;
67
+ /**
68
+ * The token override layer that recolors the whole original UI — every label
69
+ * token that feeds icon glyphs included — from one palette. `label-tertiary`
70
+ * and `label-caption` are the specific tokens behind the small icons beside
71
+ * tool names (Bash / Read / Think / …) and their separators, so overriding
72
+ * them is what makes those glyphs theme-colored like every other icon.
73
+ */
74
+ export declare function tokenOverridesFor(palette: EdexPalette): ThemeTokenOverrides;
75
+ //# sourceMappingURL=settings.d.ts.map
package/package.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "name": "@danielng23/dsh-studio-client-ui-edex",
3
+ "description": "Studio console shell frame over the web client: VU meter left bar, deck waveform right bar, filesystem browser bottom-left, original UI centered (LateNight amber/gold theme)",
4
+ "version": "0.1.0",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/ph4310822/dsh-edex-studio-ui.git",
11
+ "directory": "packages/ui-edex"
12
+ },
13
+ "type": "module",
14
+ "main": "lib/index.js",
15
+ "types": "lib/types/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./lib/types/index.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "./client": {
22
+ "types": "./lib/types/client/index.d.ts",
23
+ "default": "./lib/client.js"
24
+ },
25
+ "./src/*": "./src/*",
26
+ "./package.json": "./package.json"
27
+ },
28
+ "dsh": {
29
+ "client": {
30
+ "inject": [
31
+ "@deepseek-ai/dsh-client-connection",
32
+ "@deepseek-ai/dsh-client-locale",
33
+ "@deepseek-ai/dsh-client-runtime",
34
+ "@deepseek-ai/dsh-client-ui-settings",
35
+ "@deepseek-ai/dsh-api-remotes"
36
+ ],
37
+ "platform": "web"
38
+ }
39
+ },
40
+ "files": [
41
+ "lib/index.js",
42
+ "lib/client.js",
43
+ "lib/types/**/*.d.ts"
44
+ ],
45
+ "scripts": {
46
+ "bundle": "tsdown",
47
+ "watch": "tsdown --watch"
48
+ },
49
+ "license": "MIT",
50
+ "dependencies": {
51
+ "@codemirror/lang-css": "^6.3.1",
52
+ "@codemirror/lang-html": "^6.4.9",
53
+ "@codemirror/lang-javascript": "^6.2.2",
54
+ "@codemirror/lang-json": "^6.0.1",
55
+ "@codemirror/lang-markdown": "^6.3.1",
56
+ "@codemirror/lang-python": "^6.2.1",
57
+ "@codemirror/legacy-modes": "^6.5.3",
58
+ "@replit/codemirror-vim": "^6.4.0",
59
+ "codemirror": "^6.0.2",
60
+ "react": "^18.2.0"
61
+ },
62
+ "peerDependencies": {
63
+ "@deepseek-ai/dsh-api-remotes": "*",
64
+ "@deepseek-ai/dsh-client-locale": "*",
65
+ "@deepseek-ai/dsh-client-runtime": "*",
66
+ "@deepseek-ai/dsh-client-ui-layout": "*",
67
+ "@deepseek-ai/dsh-client-ui-settings": "*",
68
+ "@deepseek-ai/dsh-client-ui-slots": "*",
69
+ "@deepseek-ai/dsh-client-ui-theme": "*",
70
+ "@deepseek-ai/dsh-invariants": "*",
71
+ "@deepseek-ai/dsh-settings": "*",
72
+ "@deepseek-ai/dsh-typert-protocol": "*",
73
+ "@deepseek-ai/schemastery": "*",
74
+ "@deepseek-ai/cordis": "*",
75
+ "react": "^18.2.0",
76
+ "react-dom": "^18.2.0",
77
+ "@danielng23/dsh-studio-host-system-metrics": "*"
78
+ },
79
+ "devDependencies": {
80
+ "@deepseek-ai/dsh-api-remotes": "*",
81
+ "@deepseek-ai/dsh-client-locale": "*",
82
+ "@deepseek-ai/dsh-client-runtime": "*",
83
+ "@deepseek-ai/dsh-client-ui-layout": "*",
84
+ "@deepseek-ai/dsh-client-ui-settings": "*",
85
+ "@deepseek-ai/dsh-client-ui-slots": "*",
86
+ "@deepseek-ai/dsh-client-ui-theme": "*",
87
+ "@deepseek-ai/dsh-invariants": "*",
88
+ "@deepseek-ai/dsh-typert-protocol": "*",
89
+ "@deepseek-ai/cordis": "*",
90
+ "@types/react": "~18.3.1",
91
+ "@types/react-dom": "~18.3.0",
92
+ "react": "^18.2.0",
93
+ "react-dom": "^18.2.0",
94
+ "@danielng23/dsh-studio-host-system-metrics": "*"
95
+ }
96
+ }