dsh-width-tiers 1.0.8 → 2.0.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/README.md CHANGED
@@ -1,55 +1,46 @@
1
- # dsh-width-tiers
1
+ <h1 align="center">dsh-width-tiers</h1>
2
2
 
3
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
3
+ <p align="center">Chat content-width tiers for the DeepSeek Harness Web GUI.</p>
4
4
 
5
- A client plugin for the **DeepSeek Harness Web GUI** that adds **chat content
6
- width tiers** with a floating picker button (bottom-right, above the
7
- composer): 标准 / 中等 / 宽 / 超宽 / 全宽 / 自定义 (standard / medium / wide /
8
- ultra / full / custom).
5
+ <p align="center">
6
+ <a href="README.md">English</a> | <a href="README.zh.md">中文</a>
7
+ </p>
9
8
 
10
- ## Why
9
+ <p align="center">
10
+ <a href="https://www.npmjs.com/package/dsh-width-tiers"><img alt="npm" src="https://img.shields.io/npm/v/dsh-width-tiers?style=flat-square"></a>
11
+ <a href="https://github.com/aaronlei/dsh-width-tiers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/aaronlei/dsh-width-tiers?style=flat-square"></a>
12
+ <a href="LICENSE"><img alt="MIT" src="https://img.shields.io/badge/license-MIT-yellow?style=flat-square"></a>
13
+ <a href="https://www.npmjs.com/package/dsh-width-tiers"><img alt="Node version" src="https://img.shields.io/node/v/dsh-width-tiers?style=flat-square"></a>
14
+ <a href="#compatibility"><img alt="DSH 0.2.x" src="https://img.shields.io/badge/DSH-0.2.x-blue?style=flat-square"></a>
15
+ </p>
11
16
 
12
- The DSH Web app caps the message column — and every table inside it — at
13
- `--dsh-chat-content-width` (0.1.7–0.2.0 default `clamp(680px, column × 0.64,
14
- 920px)`), no matter how wide your window is, so wide tables always need
15
- horizontal scrolling.
16
-
17
- This plugin sets the width per tier through the app's **native width axis**
18
- (`--dsh-chat-user-width` + the app's `dsh.conversation.contentWidth`
19
- preference), letting the app clamp every value to "column − 176px handle
20
- budget" — so the built-in drag handles keep working:
17
+ ## Tiers
21
18
 
22
19
  | Tier | Content width | Sidebar |
23
- |---|---|---|
24
- | standard 标准 | app default | untouched |
25
- | medium 中等 | 1120px | untouched |
26
- | wide 宽 | 1280px | untouched |
27
- | ultra 超宽 | 1400px | untouched |
28
- | full 全宽 | column minus the handle budget (fills the available width) | collapsed to the icon rail |
29
- | custom 自定义 | your dragged width, re-selectable from the menu | untouched |
30
-
31
- The menu and the button title show nominal px for the fixed tiers (medium
32
- 1120px, wide 1280px, ultra 1400px). Standard shows the app default px it
33
- resolves right now (`clamp(680px, column × 0.64, 920px)`, e.g. 710px); full
34
- shows the live maximum (`column − 176px`, e.g. 934px); custom shows its
35
- recorded width or "Not set". The app still clamps the applied width to
36
- "column − 176px"; on a narrow window a higher tier therefore behaves like
37
- "full".
38
-
39
- On narrow windows wider tiers are clamped to the available column, so nothing
40
- overflows under the sidebar.
41
-
42
- The choice persists in `localStorage` and is restored on the next visit; the
43
- menu highlights the current tier, and the button's five level-bars show it at
44
- a glance (all lit for custom). Dragging one of the app's native edge handles
45
- switches the picker to the custom tier — the plugin stands aside for native
46
- drags.
47
-
48
- Before the first drag, picking custom does not silently keep a width: a guide
49
- appears at the conversation's right edge and highlights the width handle.
50
- While dragging, a bubble shows the live transcript width; releasing records it
51
- as the custom value. Every later handle drag opens the same highlight + live
52
- readout, no matter which tier was active.
20
+ | --- | --- | --- |
21
+ | Standard 标准 | App default: `max(680px, min(column × 0.64, 920px))` | unchanged |
22
+ | Medium 中等 | 1120px | unchanged |
23
+ | Wide 宽 | 1280px | unchanged |
24
+ | Ultra 超宽 | 1400px | unchanged |
25
+ | Full 全宽 | `max(640px, column − 176px)` | collapsed to icon rail |
26
+ | Custom 自定义 | width recorded from a native drag | unchanged |
27
+
28
+ Fixed and custom widths are clamped by the app to
29
+ `max(640px, column − 176px)`; the standard tier follows the app default
30
+ (680–920px). On a narrow window a wider fixed tier therefore behaves like
31
+ `full`.
32
+
33
+ ## Features
34
+
35
+ - Uses the app's native width axis (`--dsh-chat-user-width` and
36
+ `dsh.conversation.contentWidth`), so the built-in drag handles keep working.
37
+ - Persists the selected tier and restores it on the next visit.
38
+ - Follows **Settings → Language** (中文 / English).
39
+ - Menu supports ArrowUp/Down, Home/End, Escape and Tab, with focus restoration.
40
+ - Tier changes sync across tabs.
41
+ - Respects `prefers-reduced-motion`.
42
+ - Never touches the right panel. Only `full` collapses the left sidebar, and
43
+ you can expand it again at any time.
53
44
 
54
45
  ## Install
55
46
 
@@ -57,68 +48,69 @@ readout, no matter which tier was active.
57
48
  dsh plugin --profile web add dsh-width-tiers
58
49
  ```
59
50
 
60
- The bundle patch then inserts the `dsh-width-tiers` loader entry itself — no
61
- manual `cordis.patch.yml` edits needed.
51
+ Restart `dsh web`, then hard-refresh the page. A six-bar picker appears at the
52
+ bottom-right.
62
53
 
63
- Restart `dsh web` (the plugin loads at boot) and hard-refresh the page
64
- (Ctrl+Shift+R). A round button with five bars appears at the bottom-right.
54
+ For a local checkout:
65
55
 
66
- > Installing from a local checkout: `dsh plugin --profile web add file:/path/to/dsh-width-tiers`.
67
- > Local-development gotcha: `file:` dependencies are **copied** into the
68
- > profile's `node_modules` (pnpm does not symlink them). After editing the
69
- > plugin source, re-sync the copy (e.g. `rsync -a --delete --exclude .git
70
- > /path/to/dsh-width-tiers/ ~/.dsh/profiles/web/node_modules/dsh-width-tiers/`)
71
- > or re-install after removing it, then restart `dsh web` and hard-refresh.
56
+ ```bash
57
+ dsh plugin --profile web add link:/path/to/dsh-width-tiers
58
+ ```
72
59
 
73
60
  ## Usage
74
61
 
75
- - Click the round button → pick a tier; the current one is highlighted.
76
- - `full` collapses the sidebar to the icon rail through the app's own toggle
77
- — it is never force-hidden or locked: click a rail icon any time to expand
78
- it, and it stays expanded.
79
- - The right panel (rightbar) is never touched: its track and panel are fully
80
- owned by the app, and the conversation yields space to it on its own.
81
- `standard` leaves the layout entirely to the app.
62
+ - Click the picker and choose a tier.
63
+ - Picking `Custom` before the first drag opens a guide at the right edge; drag
64
+ a native handle to record a width.
65
+ - Dragging any native handle switches to `Custom`; the plugin steps aside while
66
+ you drag.
67
+ - `Standard` clears the width preference and returns to the app default.
68
+ - `Full` collapses the left sidebar; the icon rail stays available.
69
+
70
+ ## How it works
82
71
 
83
- ## Language
72
+ - Mounts the picker into the frame-wide `shell.overlay` slot; the plugin fiber
73
+ owns the controller lifetime, so no listeners or timers outlive it.
74
+ - The controller publishes an immutable snapshot (tier, menu, guide); the React
75
+ picker renders it and dispatches actions, so the view can remount without
76
+ rebuilding observers.
77
+ - Locates the conversation body that declares `--dsh-chat-content-width`
78
+ (prefers `[data-conversation-content]`, skips the right sidebar's embedded
79
+ conversation), then writes `--dsh-chat-user-width` on its parent.
80
+ - Stores the configured target in the app preference; only the inline width is
81
+ clamped to `max(640px, column − 176px)`.
82
+ - Watches the column with `ResizeObserver` so `full` follows sidebar, rightbar
83
+ and window changes.
84
+ - Drives panels through `ctx.layout` and registers copy through `ctx.locale`.
84
85
 
85
- All picker copy (tier labels, button `aria-label` and title) follows the
86
- app's **Settings → Language** (中文 / English), through the app's own locale
87
- service. Switching the language re-renders the button and menu immediately;
88
- when no explicit language is chosen the app falls back to the browser's
89
- language, and Chinese is the last resort. No plugin-side setting needed.
86
+ ## Compatibility
90
87
 
91
- ## How it works
88
+ - DSH Web 0.2.x with a `web` profile (`shell.overlay` slot and `slots` service).
89
+ - Width axis checked against DSH 0.2.1-rc.2: 640px floor, 176px handle budget,
90
+ `--dsh-chat-*` variables, `data-width-handle`, layout/locale services.
92
91
 
93
- - The element that defines `--dsh-chat-content-width` is **located at
94
- runtime** (the first element whose computed value is non-empty) and the
95
- tier is applied as an inline override — no hashed class names, so it
96
- survives bundle upgrades.
97
- - Panels are driven through the **layout service** (`ctx.layout`), never by
98
- simulating clicks.
99
- - The sidebar is only ever collapsed by the `full` tier; returning to
100
- `standard` restores it only if this plugin collapsed it.
101
- - Dictionaries are registered with the app's **locale service**
102
- (`ctx.locale.register` / `bind`) and re-rendered through its change
103
- subscription, so the copy always matches the app's active language.
104
-
105
- ## Limitations
106
-
107
- - Content width cannot exceed the window: on a narrow window, wider tiers are
108
- capped by the available column (the picker keeps showing the nominal value;
109
- the live bubble during a drag shows the applied width). Use `full` (which
110
- also collapses the sidebar) for the maximum.
111
- - Requires the DSH Web client plugin system (dsh ≥ 0.1.0-rc.x with a `web`
112
- profile). Verified on dsh 0.1.7-alpha.1 and 0.2.0-rc.2; the 0.2.1-rc.1
113
- width axis matches by bundle diff.
114
-
115
- ## Uninstall
92
+ ## Development
116
93
 
117
94
  ```bash
118
- dsh plugin --profile web remove dsh-width-tiers
95
+ pnpm install
96
+ pnpm build # src/ -> lib/ (host entry + loader-wrapped client bundle)
97
+ pnpm typecheck
98
+ pnpm test # vitest: controller (jsdom) + picker component suites
99
+ pnpm verify:client
119
100
  ```
120
101
 
121
- then restart `dsh web`.
102
+ The sources live in `src/` (`src/index.ts` is the no-op host entry, the
103
+ feature lives in `src/client/`); `lib/` is the built, published payload. The
104
+ vitest suites import the sources directly: the controller runs under jsdom and
105
+ the picker is rendered with Testing Library, so no live DSH instance is
106
+ required. `verify:client` checks the built bundle contract. Development needs
107
+ Node 22+ and pnpm.
108
+
109
+ ## Notes
110
+
111
+ - Wider fixed tiers are clamped on narrow windows.
112
+ - A custom width dragged on a narrow window is clamped by the app before it is
113
+ recorded.
122
114
 
123
115
  ## License
124
116
 
package/README.zh.md CHANGED
@@ -1,45 +1,43 @@
1
- # dsh-width-tiers(对话区宽度档位)
1
+ <h1 align="center">dsh-width-tiers</h1>
2
2
 
3
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
3
+ <p align="center">DeepSeek Harness Web GUI 的对话区内容宽度档位插件。</p>
4
4
 
5
- DeepSeek Harness Web GUI 的客户端插件:给对话区加**内容宽度档位选择器**
6
- (右下角圆形按钮,输入框上方),共 6 档:
7
- 标准 / 中等 / 宽 / 超宽 / 全宽 / 自定义。
5
+ <p align="center">
6
+ <a href="README.md">English</a> | <a href="README.zh.md">中文</a>
7
+ </p>
8
8
 
9
- ## 为什么需要它
9
+ <p align="center">
10
+ <a href="https://www.npmjs.com/package/dsh-width-tiers"><img alt="npm" src="https://img.shields.io/npm/v/dsh-width-tiers?style=flat-square"></a>
11
+ <a href="https://github.com/aaronlei/dsh-width-tiers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/aaronlei/dsh-width-tiers?style=flat-square"></a>
12
+ <a href="LICENSE"><img alt="MIT" src="https://img.shields.io/badge/license-MIT-yellow?style=flat-square"></a>
13
+ <a href="https://www.npmjs.com/package/dsh-width-tiers"><img alt="Node version" src="https://img.shields.io/node/v/dsh-width-tiers?style=flat-square"></a>
14
+ <a href="#兼容性"><img alt="DSH 0.2.x" src="https://img.shields.io/badge/DSH-0.2.x-blue?style=flat-square"></a>
15
+ </p>
10
16
 
11
- DSH Web 把消息列——包括里面的所有表格——的宽度限制在
12
- `--dsh-chat-content-width`(0.1.7–0.2.0 默认
13
- `clamp(680px, 列宽 × 0.64, 920px)`),不管窗口多宽都不变,宽表格只能横向滚动。
14
-
15
- 本插件通过应用自身的**原生宽度通道**(`--dsh-chat-user-width` +
16
- `dsh.conversation.contentWidth` 偏好)按档位设定宽度,由应用自身钳制到
17
- 「列宽 − 176px 手柄预留」,因此自带的原生拖拽手柄始终可用:
17
+ ## 档位
18
18
 
19
19
  | 档位 | 内容宽度 | 侧边栏 |
20
- |---|---|---|
21
- | 标准 | 应用默认 | 不动 |
20
+ | --- | --- | --- |
21
+ | 标准 | 应用默认:`max(680px, min(列宽 × 0.64, 920px))` | 不动 |
22
22
  | 中等 | 1120px | 不动 |
23
23
  | 宽 | 1280px | 不动 |
24
24
  | 超宽 | 1400px | 不动 |
25
- | 全宽 | 列宽减手柄预留(占满可用宽度) | 收起为图标轨道 |
26
- | 自定义 | 拖拽原生手柄得出,可在菜单回切 | 不动 |
27
-
28
- 菜单与按钮标题中:中等 / 宽 / 超宽显示**固定标称值**(1120 / 1280 / 1400px),
29
- 标准显示应用当前默认值(`clamp(680px, 列宽 × 0.64, 920px)`,如 710px),全宽
30
- 显示当前列宽下的最大实际值(列宽 − 176px,如 934px),自定义显示已记录的
31
- 宽度或「未设置」。实际生效宽度仍由应用按「列宽 − 176px」钳制;窄窗口下
32
- 选定较高档位时,效果等同于「全宽」。
25
+ | 全宽 | `max(640px, 列宽 − 176px)` | 收起为图标轨道 |
26
+ | 自定义 | 原生拖拽记录的宽度 | 不动 |
33
27
 
34
- 窄窗口下超宽档位会自动被钳到可用宽度,不会溢出被侧栏覆盖。
28
+ 固定档和自定义宽度会被应用钳制到 `max(640px, 列宽 − 176px)`;标准档
29
+ 使用应用默认的 680–920px。窄窗口下较宽的固定档等同「全宽」。
35
30
 
36
- 选择会记住(localStorage),下次打开自动恢复;菜单里当前档位高亮,按钮上
37
- 的五条横条图标也直观显示当前档位(自定义档全亮)。拖动应用自带的
38
- 对话区边缘手柄会自动切到「自定义」档,插件让位于原生拖拽。
31
+ ## 特性
39
32
 
40
- 若从未拖拽过,点击「自定义」不会静默套用某个宽度:右侧对话边缘会出现
41
- 拖拽引导,手柄高亮;拖拽时气泡实时显示对话列宽度,松开后记为该档的值。
42
- 之后每次拖拽手柄(无论从哪个档位开始)都会重新高亮手柄并显示实时宽度。
33
+ - 走应用原生宽度通道(`--dsh-chat-user-width` 与
34
+ `dsh.conversation.contentWidth`),自带拖拽手柄始终可用。
35
+ - 记住当前档位,下次打开自动恢复。
36
+ - 跟随 **设置 → 语言**(中文 / English)。
37
+ - 菜单支持方向键、Home/End、Esc、Tab,并恢复焦点。
38
+ - 档位选择跨标签页同步。
39
+ - 支持 `prefers-reduced-motion`。
40
+ - 不碰右侧面板;只有「全宽」会收起左侧栏,随时可以再展开。
43
41
 
44
42
  ## 安装
45
43
 
@@ -47,61 +45,61 @@ DSH Web 把消息列——包括里面的所有表格——的宽度限制在
47
45
  dsh plugin --profile web add dsh-width-tiers
48
46
  ```
49
47
 
50
- bundle patch 会自动插入 `dsh-width-tiers` 加载项——无需手动改
51
- `cordis.patch.yml`。
48
+ 重启 `dsh web` 并硬刷新页面。右下角会出现六条横条的圆形按钮。
52
49
 
53
- **重启 `dsh web`**(插件在启动时加载),再硬刷新页面(Ctrl+Shift+R)。
54
- 右下角会出现五条横条的圆形按钮。
50
+ 本地目录:
55
51
 
56
- > 本地目录安装:`dsh plugin --profile web add file:/path/to/dsh-width-tiers`。
57
- > 本地开发注意:`file:` 依赖会被 **拷贝** 进 profile 的 node_modules(pnpm
58
- > 不会建软链)。改完插件源码后,需要重新同步拷贝(例如 `rsync -a --delete
59
- > --exclude .git /path/to/dsh-width-tiers/
60
- > ~/.dsh/profiles/web/node_modules/dsh-width-tiers/`)或先 remove 再 add,
61
- > 然后重启 `dsh web` 并硬刷新。
52
+ ```bash
53
+ dsh plugin --profile web add link:/path/to/dsh-width-tiers
54
+ ```
62
55
 
63
56
  ## 使用
64
57
 
65
- - 点圆形按钮 → 选择档位,当前档位高亮。
66
- - 「全宽」通过应用自己的收起按钮把侧边栏收成图标轨道——**不会被锁死**:
67
- 随时点轨道图标展开,展开后保持展开。
68
- - 插件**不碰右侧面板**:右栏的轨道与面板完全由应用管理,展开时对话内容
69
- 自适应让位;「标准」档完全交给应用。
70
-
71
- ## 多语言
72
-
73
- 选择器里的所有文案(档位名、按钮的 `aria-label` 和标题)跟随应用的
74
- **设置 → 语言**(中文 / English),通过应用自身的 locale 服务实现。切换
75
- 语言后按钮和菜单会立即重渲染;未显式选择语言时,应用会回退到浏览器语言,
76
- 最后兜底中文。无需插件侧单独设置。
58
+ - 点击圆形按钮选择档位。
59
+ - 首次选择「自定义」会在右侧边缘显示引导;拖动原生手柄记录宽度。
60
+ - 拖动任意原生手柄都会切换到「自定义」;拖拽期间插件让位于应用。
61
+ - 「标准」清除宽度偏好,回到应用默认宽度。
62
+ - 「全宽」收起左侧栏,图标轨道仍可随时展开。
77
63
 
78
64
  ## 原理
79
65
 
80
- - 运行时**自动定位**定义 `--dsh-chat-content-width` 的元素(第一个计算值
81
- 非空的元素),以行内样式覆盖——**不依赖哈希类名**,dsh 升级后依旧有效。
82
- - 面板操作走 **layout 服务**(`ctx.layout`),从不模拟点击。
83
- - 侧边栏只被「全宽」档收起;回到「标准」时,只有本插件自己收起的侧边栏
84
- 才会被恢复展开(你手动收的不动)。
85
- - 字典注册到应用的 **locale 服务**(`ctx.locale.register` / `bind`),并
86
- 订阅其变更事件重渲染,文案始终与应用的当前语言一致。
66
+ - 挂载到 frame 级 `shell.overlay` 插槽,由插件 fiber 持有 controller 生命周期;
67
+ 插件卸载后不残留监听器或定时器。
68
+ - controller 发布不可变快照(档位、菜单、引导),React picker 只负责渲染并
69
+ 派发动作;视图重挂载不需要重建观察者。
70
+ - 定位声明 `--dsh-chat-content-width` 的对话 body(优先
71
+ `[data-conversation-content]`,跳过右侧栏的 embedded 对话),在它的
72
+ 父级写入 `--dsh-chat-user-width`。
73
+ - 应用偏好保存设定值,只有行内宽度按 `max(640px, 列宽 − 176px)` 钳制。
74
+ - 用 `ResizeObserver` 观察列宽,让「全宽」跟随左右栏与窗口变化。
75
+ - 面板操作走 `ctx.layout`,文案注册走 `ctx.locale`。
87
76
 
88
- ## 已知限制
77
+ ## 兼容性
89
78
 
90
- - 内容宽度不可能超过窗口:窗口窄时,高档位会被可用列宽截断(选择器仍显示
91
- 标称值,实际宽度以拖拽气泡/窗口效果为准);想要最大空间请用「全宽」
92
- (同时收起侧边栏)。
93
- - 依赖 DSH Web 客户端插件体系(带 web profile 的 dsh ≥ 0.1.0-rc.x)。
94
- 已在 dsh 0.1.7-alpha.1、0.2.0-rc.2 上验证;0.2.1-rc.1 的宽度轴经 bundle
95
- 对比确认一致。
79
+ - DSH Web 0.2.x,带 `web` profile(`shell.overlay` 插槽与 `slots` 服务)。
80
+ - 宽度轴已按 DSH 0.2.1-rc.2 对照:640px 下限、176px 手柄预留、
81
+ `--dsh-chat-*` 变量、`data-width-handle`、layout/locale 服务。
96
82
 
97
- ## 卸载
83
+ ## 开发
98
84
 
99
85
  ```bash
100
- dsh plugin --profile web remove dsh-width-tiers
86
+ pnpm install
87
+ pnpm build # src/ -> lib/(宿主入口 + loader 包装的客户端 bundle)
88
+ pnpm typecheck
89
+ pnpm test # vitest:controller(jsdom)+ picker 组件测试
90
+ pnpm verify:client
101
91
  ```
102
92
 
103
- 然后重启 `dsh web`。
93
+ 源码在 `src/`(`src/index.ts` 是无副作用的宿主入口,功能在
94
+ `src/client/`),`lib/` 是构建后的发布内容。vitest 直接测试源码:
95
+ controller 跑在 jsdom 下,picker 用 Testing Library 渲染,不需要启动真实
96
+ DSH。`verify:client` 校验构建产物的 loader 契约。开发需要 Node 22+ 与 pnpm。
97
+
98
+ ## 注意
99
+
100
+ - 窄窗口下较宽的固定档位会被应用钳制。
101
+ - 窄窗口下拖出的自定义宽度会先被应用钳制,再被记录。
104
102
 
105
103
  ## 许可证
106
104
 
107
- MIT —— 见 [LICENSE](LICENSE)。Copyright (c) 2026 aaronlei。
105
+ MIT — 见 [LICENSE](LICENSE)。Copyright (c) 2026 aaronlei。