dsh-quick-actions 0.2.0-rc.1 → 0.2.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +7 -6
- package/README.md +7 -6
- package/lib/client.js +95 -29
- package/lib/client.js.map +1 -1
- package/lib/types/client/dsh.d.ts +4 -2
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/surfaces/entries.d.ts +2 -1
- package/lib/types/client/surfaces/layout.d.ts +7 -0
- package/lib/types/styles/index.d.ts +20 -12
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -9,7 +9,7 @@ Preset Quick Actions ship with the package and are read-only — you can hide or
|
|
|
9
9
|
## What it does
|
|
10
10
|
|
|
11
11
|
- **Send Actions**: load a piece of static text into the draft and submit it through the official path. There is exactly one loading path, `setDraft(text)` → `submit()`.
|
|
12
|
-
- **Three layouts**: a ribbon above the input, a bar
|
|
12
|
+
- **Three layouts**: a ribbon above the input, a bar under it, or a single launcher opening a searchable panel. Switch at any time.
|
|
13
13
|
- **Per-action send confirmation**, on by default and yours to change.
|
|
14
14
|
- **Text starting with `/` is a valid Command Send Action**, adjudicated by DSH itself.
|
|
15
15
|
- Presets and customs are capped at **50 combined**. At the cap, adding and cloning stop; if an upgrade or a config change pushes existing state past it, **no data is lost** — adding and cloning are simply refused until you are back under it.
|
|
@@ -28,7 +28,7 @@ This release has **no insert action** (insert at the selection, keep the editing
|
|
|
28
28
|
| DSH UI primitives (browser side) | `>=0.1.7-alpha.2`, also supplied by the module table |
|
|
29
29
|
| Platform | `web` profile only |
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
The send and Settings contracts have no legacy compatibility layer. **`0.2.0-rc.3`** also supports the optional `conversation.composer.footer`: a locally patched core places the bar below the statistics row, with the action group centered within the input's width; an unpatched core keeps the existing placement. Official `0.1.7-rc.2` does not include this slot, and installing the plugin alone does not add it.
|
|
32
32
|
|
|
33
33
|
The floor is the DSH release whose Settings form this plugin reads. **Do not run it against anything older**: `0.1.7-alpha.1` rewrote Settings — plugins no longer register namespaces of their own, and user data became the plugin's own Config, written into the profile. This release reads and writes the new model only, and on the `0.1.5` and `0.1.6` lines its Client never starts. For those lines, install this plugin's `0.1.0`.
|
|
34
34
|
|
|
@@ -45,7 +45,7 @@ No upper bound is declared, but **that is not a promise of forward compatibility
|
|
|
45
45
|
dsh plugin --profile web add dsh-quick-actions@next
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
**Keep the `@next`.**
|
|
48
|
+
**Keep the `@next`.** The plugin's `0.2.0` line remains a prerelease and uses the `next` dist-tag. Without the tag you get the plugin's `0.1.0` from `latest`, which supports only DSH `0.1.5` and `0.1.6` and fails to activate on `0.1.7`. DSH's own `latest` is now `0.1.7-rc.2`, but that does not automatically change this plugin's release channel. This release has not been verified against the DSH `0.2.0` prerelease line.
|
|
49
49
|
|
|
50
50
|
Then restart the web profile. One package is the whole thing: it carries `dsh.bundle.patch`, which inserts its Host half into the profile, while its `dsh.client` declaration makes the web app load the browser half.
|
|
51
51
|
|
|
@@ -54,7 +54,7 @@ Then restart the web profile. One package is the whole thing: it carries `dsh.bu
|
|
|
54
54
|
```sh
|
|
55
55
|
mkdir -p /tmp/quick-actions
|
|
56
56
|
pnpm --filter dsh-quick-actions pack --pack-destination /tmp/quick-actions
|
|
57
|
-
dsh plugin --profile web add /tmp/quick-actions/dsh-quick-actions-0.2.0-rc.
|
|
57
|
+
dsh plugin --profile web add /tmp/quick-actions/dsh-quick-actions-0.2.0-rc.3.tgz
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
The `--filter` form works from anywhere in the repository; from the package directory itself, `pnpm pack --pack-destination /tmp/quick-actions` is the same thing.
|
|
@@ -123,6 +123,7 @@ Field rules:
|
|
|
123
123
|
- `label` and `text` are required; `icon` and `confirm` are optional, and `confirm` defaults to `true`.
|
|
124
124
|
- An invalid preset (a missing field, a duplicate `id`, a catalog over 50 entries) makes **plugin loading fail loudly** and lists every problem at once, rather than truncating silently.
|
|
125
125
|
- `presets` sits under the same row's `config` as your action data (see "Settings paths" below), and this plugin never writes it. It is a DSH volatile field: editing it while the profile runs reaches the Quick Actions immediately; an invalid catalog written that way shows a catalog error in the Quick Actions area, and the next profile restart fails plugin loading with the list of problems.
|
|
126
|
+
- **Declare them in the active profile's own `cordis.patch.yml` only.** Do not put this plugin's `config` in the home patch (`<DSH_HOME>/cordis.patch.yml`) or a `dsh --patch` overlay: DSH replaces a patch row's `config` whole, so that layer hides the action data stored on this row (the UI falls back to defaults; the data on disk is still there), and DSH refuses every save from then on — the UI reports the save as refused, and retrying never succeeds. Remove this plugin's row from that layer and restart the profile to recover.
|
|
126
127
|
|
|
127
128
|
Users can hide or clone a preset but never edit or delete it; a clone becomes an ordinary Custom Quick Action.
|
|
128
129
|
|
|
@@ -133,7 +134,7 @@ Layout is a global persisted setting, switched in the management panel:
|
|
|
133
134
|
| Value | Name | Where |
|
|
134
135
|
|---|---|---|
|
|
135
136
|
| `ribbon` (default) | Action ribbon | One row above the input, matching its width |
|
|
136
|
-
| `bar` | Action bar |
|
|
137
|
+
| `bar` | Action bar | With the footer core patch: a separate row below statistics, with controls centered within the input's width. Without it: the existing placement beside usage info. Actions that do not fit fold into "more" |
|
|
137
138
|
| `launcher` | Single launcher | One entry button opening a searchable panel |
|
|
138
139
|
|
|
139
140
|
`bar` and `launcher` share the same searchable panel, and the search matches labels and texts only. The management panel is where you reorder, hide, restore and clone presets, create, edit, enable and delete custom actions, and switch layout.
|
|
@@ -193,7 +194,7 @@ Cross-version data compatibility is the Host's job: new presets are appended to
|
|
|
193
194
|
dsh plugin --profile web remove dsh-quick-actions
|
|
194
195
|
```
|
|
195
196
|
|
|
196
|
-
Both the dependency and the layer in `dsh.profile.bundles` go away. After a profile restart the actions are gone. The `id: composer-quick-actions` row in `cordis.patch.yml` stays as it is — your actions live in its `config`, and a reinstall picks the row back up by id, so they come back. If you uninstall without reinstalling,
|
|
197
|
+
Both the dependency and the layer in `dsh.profile.bundles` go away. After a profile restart the actions are gone. The `id: composer-quick-actions` row in `cordis.patch.yml` stays as it is — your actions live in its `config`, and a reinstall picks the row back up by id, so they come back. If you uninstall without reinstalling, that row is left addressing nothing: it does not block startup, `dsh --profile web --dump-config` reports it as `patch: entry "composer-quick-actions" not found`, and step 1 below removes it.
|
|
197
198
|
|
|
198
199
|
**Full manual cleanup** (uninstalling does none of this, because a reinstall should restore your actions):
|
|
199
200
|
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
## 能做什么
|
|
10
10
|
|
|
11
11
|
- **发送动作**:把一段静态文本装载进草稿并按官方路径提交,装载路径只有一条 `setDraft(text)` → `submit()`。
|
|
12
|
-
-
|
|
12
|
+
- **三种布局**:输入框上方的动作带、输入框下方的操作栏、单入口的可搜索面板,随时切换。
|
|
13
13
|
- **每个动作可单独设置发送确认**,默认开启,之后由你决定。
|
|
14
14
|
- **`/` 开头的文本是合法的命令发送动作**,交给 DSH 官方裁决。
|
|
15
15
|
- 预置与自定义**合计上限 50 个**。达到上限后不能再新增或克隆;若升级或配置变化把既有状态推过上限,**已有数据一个都不会丢**,只是在回到上限以内之前禁止新增和克隆。
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
| DSH UI primitives(浏览器侧) | `>=0.1.7-alpha.2`,同样由模块表提供 |
|
|
29
29
|
| 平台 | 只支持 `web` profile |
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
发送与 Settings 契约不做旧版兼容。**`0.2.0-rc.3`** 另支持可选的 `conversation.composer.footer`:带本地核心补丁的 DSH 将 bar 放到统计行下方、动作组水平居中;未打补丁的核心保留原位置。该挂载点不是官方 `0.1.7-rc.2` 自带能力,也不会仅因安装插件而出现。
|
|
32
32
|
|
|
33
33
|
下界取的是本插件读取其 Settings 表单的那个 DSH 版本。**不要在更低版本上使用**:`0.1.7-alpha.1` 重写了 Settings——插件不再自己注册命名空间,用户数据改为插件自己的 Config、写进 profile。本版只按新模型读写,在 `0.1.5`、`0.1.6` 线上 Client 根本不会启动。要在那两条线上用,请装本插件的 `0.1.0`。
|
|
34
34
|
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
dsh plugin --profile web add dsh-quick-actions@next
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
**`@next` 不能省。**
|
|
48
|
+
**`@next` 不能省。** 插件 `0.2.0` 仍处于预发布阶段,本版使用 `next` dist-tag;不带 tag 装到的是插件 `latest` 上的 `0.1.0`,它只支持 DSH `0.1.5`、`0.1.6` 线,在 `0.1.7` 上激活失败。DSH 的 `latest` 已是 `0.1.7-rc.2`,但这不会自动改变插件的发布通道。本版尚未验证 DSH `0.2.0` 预发布线。
|
|
49
49
|
|
|
50
50
|
然后重启 web profile。一个包就是全部:它自带 `dsh.bundle.patch` 把自己的 Host 半边插进 profile,`dsh.client` 声明让 web 端加载浏览器半边。
|
|
51
51
|
|
|
@@ -54,7 +54,7 @@ dsh plugin --profile web add dsh-quick-actions@next
|
|
|
54
54
|
```sh
|
|
55
55
|
mkdir -p /tmp/quick-actions
|
|
56
56
|
pnpm --filter dsh-quick-actions pack --pack-destination /tmp/quick-actions
|
|
57
|
-
dsh plugin --profile web add /tmp/quick-actions/dsh-quick-actions-0.2.0-rc.
|
|
57
|
+
dsh plugin --profile web add /tmp/quick-actions/dsh-quick-actions-0.2.0-rc.3.tgz
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
上面的 `--filter` 形式在仓库任意位置都能用;如果你已经在包目录里,`pnpm pack --pack-destination /tmp/quick-actions` 即可。
|
|
@@ -123,6 +123,7 @@ pnpm 有一条供应链策略:拒绝发布时间在冷却窗口内(默认 24
|
|
|
123
123
|
- `label`、`text` 必填;`icon`、`confirm` 可选,`confirm` 默认 `true`。
|
|
124
124
|
- 预置无效(缺字段、`id` 重复、目录超过 50 条)会让**插件加载响亮失败**并一次列出所有问题,而不是静默截断。
|
|
125
125
|
- `presets` 与你的动作数据同在这一行 `config` 下(见下文「Settings 路径」),本插件从不写它。它是 DSH 的 volatile 字段:profile 运行期间改动会即时反映到快捷动作上;此时若改出无效目录,快捷动作区域显示目录错误,重启 profile 时插件加载失败并列出问题。
|
|
126
|
+
- **只写在 active profile 自己的这份 `cordis.patch.yml` 里。** 不要把本插件的 `config` 写进 home patch(`<DSH_HOME>/cordis.patch.yml`)或 `dsh --patch` 的 overlay:DSH 的 patch 行 `config` 是整份替换,那一层会盖住这一行里存的你的动作数据(界面回到默认,磁盘上的数据还在),而且 DSH 会拒绝此后的每一次保存,界面报「保存被拒绝」,重试也不会成功。删掉那一层里本插件的行并重启 profile 即可恢复。
|
|
126
127
|
|
|
127
128
|
用户对预置只能隐藏或克隆,不能编辑或删除;克隆出来的是一条普通的自定义动作。
|
|
128
129
|
|
|
@@ -133,7 +134,7 @@ pnpm 有一条供应链策略:拒绝发布时间在冷却窗口内(默认 24
|
|
|
133
134
|
| 值 | 名称 | 位置 |
|
|
134
135
|
|---|---|---|
|
|
135
136
|
| `ribbon`(默认) | 上方动作带 | 输入框上方一行,与输入框等宽 |
|
|
136
|
-
| `bar` | 下方操作栏 |
|
|
137
|
+
| `bar` | 下方操作栏 | 带 footer 核心补丁时:统计行下方独占新行,动作组在输入框宽度内居中;未打补丁时:保留与用量信息并排的原位置。装不下的动作折进「更多」 |
|
|
137
138
|
| `launcher` | 单入口面板 | 一个入口按钮,点开可搜索的动作面板 |
|
|
138
139
|
|
|
139
140
|
`bar` 与 `launcher` 共用同一个可搜索面板,搜索只匹配标签和文本。管理面板里可以给预置排序、隐藏、恢复、克隆,增删改自定义动作并启停它们,以及切换布局。
|
|
@@ -193,7 +194,7 @@ dsh plugin --profile web add dsh-quick-actions@<version>
|
|
|
193
194
|
dsh plugin --profile web remove dsh-quick-actions
|
|
194
195
|
```
|
|
195
196
|
|
|
196
|
-
依赖与 `dsh.profile.bundles` 里的那一层会同时去掉,重启 profile 后动作不再出现。`cordis.patch.yml` 里 `id: composer-quick-actions` 那一行原样保留——你的动作都在它的 `config` 里,重装后按 id
|
|
197
|
+
依赖与 `dsh.profile.bundles` 里的那一层会同时去掉,重启 profile 后动作不再出现。`cordis.patch.yml` 里 `id: composer-quick-actions` 那一行原样保留——你的动作都在它的 `config` 里,重装后按 id 接回,所以动作会回来。只卸不装时,这一行就成了找不到目标的孤儿行:不影响启动,`dsh --profile web --dump-config` 会为它报 `patch: entry "composer-quick-actions" not found`;按下面第 1 步删掉即可。
|
|
197
198
|
|
|
198
199
|
**手工彻底清理**(卸载不做这些,因为重装应当恢复你的动作):
|
|
199
200
|
|
package/lib/client.js
CHANGED
|
@@ -1685,6 +1685,11 @@ window.__ModuleLoader__.load({
|
|
|
1685
1685
|
* no layout — every width reads as zero. That answers "all of them": showing the
|
|
1686
1686
|
* full row and letting the browser's own overflow handle it for one frame is
|
|
1687
1687
|
* better than flashing a "more" button that the next frame withdraws.
|
|
1688
|
+
*
|
|
1689
|
+
* A control fits when it overruns the row by less than `FIT_TOLERANCE`. Whenever
|
|
1690
|
+
* the bar is content-sized (spec 22.9) the row it measures is exactly as wide as
|
|
1691
|
+
* the controls it shows, and fractional layout can report that a hair short;
|
|
1692
|
+
* folding a face over the difference would narrow the row and start a cascade.
|
|
1688
1693
|
*/
|
|
1689
1694
|
function fitActionCount(input) {
|
|
1690
1695
|
const { available, widths, reserved, gap } = input;
|
|
@@ -1694,7 +1699,7 @@ window.__ModuleLoader__.load({
|
|
|
1694
1699
|
let shown = 0;
|
|
1695
1700
|
for (const width of widths) {
|
|
1696
1701
|
const next = used + width + (shown === 0 && reserved === 0 ? 0 : gap);
|
|
1697
|
-
if (next > available) break;
|
|
1702
|
+
if (next > available + .5) break;
|
|
1698
1703
|
used = next;
|
|
1699
1704
|
shown += 1;
|
|
1700
1705
|
}
|
|
@@ -2053,7 +2058,7 @@ window.__ModuleLoader__.load({
|
|
|
2053
2058
|
* | layout | Slot | body |
|
|
2054
2059
|
* |------------|-----------------------------|-------------------------------------------------------------|
|
|
2055
2060
|
* | `ribbon` | `conversation.input.dock` | title, the actions in shared order, and "manage" on one line |
|
|
2056
|
-
* | `bar` |
|
|
2061
|
+
* | `bar` | composer footer (dock fallback) | the leading actions that fit, then "more", then "manage" |
|
|
2057
2062
|
* | `launcher` | `conversation.input.dock` | one compact entry carrying the Composer projection's count |
|
|
2058
2063
|
*
|
|
2059
2064
|
* Three rules hold across all of them:
|
|
@@ -2087,10 +2092,13 @@ window.__ModuleLoader__.load({
|
|
|
2087
2092
|
});
|
|
2088
2093
|
}
|
|
2089
2094
|
/**
|
|
2090
|
-
* Measure one element's
|
|
2091
|
-
*
|
|
2092
|
-
*
|
|
2093
|
-
*
|
|
2095
|
+
* Measure one element's width, republishing on every resize. Used twice: on the
|
|
2096
|
+
* whole row for the density rule, and on the action region alone for the bar's
|
|
2097
|
+
* overflow split — the region is `flex: 1 1 auto`, so its width is already what
|
|
2098
|
+
* is left after the controls that must stay visible.
|
|
2099
|
+
*
|
|
2100
|
+
* Fractional, like the control widths it is compared with: `clientWidth` rounds,
|
|
2101
|
+
* and a region reported a pixel short of the faces it holds folds one of them.
|
|
2094
2102
|
*/
|
|
2095
2103
|
function useElementWidth() {
|
|
2096
2104
|
const ref = (0, react.useRef)(null);
|
|
@@ -2099,10 +2107,10 @@ window.__ModuleLoader__.load({
|
|
|
2099
2107
|
const element = ref.current;
|
|
2100
2108
|
if (element === null || typeof ResizeObserver === "undefined") return;
|
|
2101
2109
|
const observer = new ResizeObserver(() => {
|
|
2102
|
-
setWidth(element.
|
|
2110
|
+
setWidth(element.getBoundingClientRect().width);
|
|
2103
2111
|
});
|
|
2104
2112
|
observer.observe(element);
|
|
2105
|
-
setWidth(element.
|
|
2113
|
+
setWidth(element.getBoundingClientRect().width);
|
|
2106
2114
|
return () => {
|
|
2107
2115
|
observer.disconnect();
|
|
2108
2116
|
};
|
|
@@ -2123,7 +2131,7 @@ window.__ModuleLoader__.load({
|
|
|
2123
2131
|
let changed = false;
|
|
2124
2132
|
for (const node of Array.from(fitRef.current?.querySelectorAll("[data-quick-action]") ?? [])) {
|
|
2125
2133
|
const key = node.dataset["quickAction"];
|
|
2126
|
-
const value = node.
|
|
2134
|
+
const value = node.getBoundingClientRect().width;
|
|
2127
2135
|
if (key === void 0 || value <= 0 || widths.current.get(key) === value) continue;
|
|
2128
2136
|
widths.current.set(key, value);
|
|
2129
2137
|
changed = true;
|
|
@@ -2194,6 +2202,7 @@ window.__ModuleLoader__.load({
|
|
|
2194
2202
|
className: layout === "bar" ? "dsh-cqa-bar" : layout === "launcher" ? "dsh-cqa-launcher" : "dsh-cqa-ribbon",
|
|
2195
2203
|
"data-quick-actions-layout": layout,
|
|
2196
2204
|
"data-quick-actions-density": density,
|
|
2205
|
+
"data-quick-actions-overflow": layout === "bar" && overflow.length > 0 ? "" : void 0,
|
|
2197
2206
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2198
2207
|
className: "dsh-cqa-row",
|
|
2199
2208
|
ref: rowRef,
|
|
@@ -3264,7 +3273,7 @@ window.__ModuleLoader__.load({
|
|
|
3264
3273
|
//#endregion
|
|
3265
3274
|
//#region src/client/surfaces/entries.tsx
|
|
3266
3275
|
/**
|
|
3267
|
-
* The
|
|
3276
|
+
* The dock entries and optional composer footer (spec 7.3, 8.1, 23).
|
|
3268
3277
|
*
|
|
3269
3278
|
* Both are always registered; which one renders the layout is decided at render
|
|
3270
3279
|
* time from the authoritative Settings snapshot, and both render nothing at all
|
|
@@ -3272,12 +3281,14 @@ window.__ModuleLoader__.load({
|
|
|
3272
3281
|
*
|
|
3273
3282
|
* - `conversation.composer.dock` is the residency beacon. Its mount is DSH's own
|
|
3274
3283
|
* statement that this Session's composer is in its resident variant, so it
|
|
3275
|
-
* marks the Session while mounted and
|
|
3284
|
+
* marks the Session while mounted and renders `bar` only without a footer.
|
|
3285
|
+
* - `conversation.composer.footer`, when provided by the local core patch,
|
|
3286
|
+
* renders `bar` on its own row and suppresses that Session's dock fallback.
|
|
3276
3287
|
* - `conversation.input.dock` renders `ribbon` or `launcher`, but only while the
|
|
3277
3288
|
* beacon's mark stands — that Slot also mounts on the blank-session hero, and
|
|
3278
3289
|
* the first release must never appear there.
|
|
3279
3290
|
*
|
|
3280
|
-
*
|
|
3291
|
+
* Another entry rides the same input dock: the centralized management overlay,
|
|
3281
3292
|
* which spec 8.1 requires to be registered independently of the layout entries.
|
|
3282
3293
|
* It is a separate Slot cell with its own id, order and error boundary, so a
|
|
3283
3294
|
* failure in the management panel cannot take a Composer layout down with it and
|
|
@@ -3378,8 +3389,9 @@ window.__ModuleLoader__.load({
|
|
|
3378
3389
|
}
|
|
3379
3390
|
/** Build both Slot entry components over one set of fiber-owned dependencies. */
|
|
3380
3391
|
function createQuickActionDockEntries(deps) {
|
|
3392
|
+
const footers = createResidentComposerRegistry();
|
|
3381
3393
|
function Body(props) {
|
|
3382
|
-
const { owns, ...slot } = props;
|
|
3394
|
+
const { owns, footer, ...slot } = props;
|
|
3383
3395
|
const client = useControllerState(deps.controller);
|
|
3384
3396
|
const projection = client.projection;
|
|
3385
3397
|
const onRetry = (0, react.useCallback)(() => {
|
|
@@ -3391,12 +3403,16 @@ window.__ModuleLoader__.load({
|
|
|
3391
3403
|
onRetry
|
|
3392
3404
|
}) : null;
|
|
3393
3405
|
if (!owns.includes(projection.layout)) return null;
|
|
3394
|
-
|
|
3406
|
+
const surface = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionSurface, {
|
|
3395
3407
|
...slot,
|
|
3396
3408
|
deps,
|
|
3397
3409
|
layout: projection.layout,
|
|
3398
3410
|
actions: projection.composer
|
|
3399
3411
|
});
|
|
3412
|
+
return footer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3413
|
+
className: "dsh-cqa-footer",
|
|
3414
|
+
children: surface
|
|
3415
|
+
}) : surface;
|
|
3400
3416
|
}
|
|
3401
3417
|
function InputDock(props) {
|
|
3402
3418
|
const resident = useResident(deps.residency, props.sessionId);
|
|
@@ -3410,15 +3426,29 @@ window.__ModuleLoader__.load({
|
|
|
3410
3426
|
}
|
|
3411
3427
|
function ComposerDock(props) {
|
|
3412
3428
|
const { sessionId } = props;
|
|
3429
|
+
const hasFooter = useResident(footers, sessionId);
|
|
3413
3430
|
(0, react.useLayoutEffect)(() => deps.residency.mark(sessionId), [sessionId]);
|
|
3414
3431
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SurfaceErrorBoundary, {
|
|
3415
3432
|
t: props.t,
|
|
3416
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Body, {
|
|
3433
|
+
children: hasFooter ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Body, {
|
|
3417
3434
|
...props,
|
|
3418
3435
|
owns: COMPOSER_DOCK_LAYOUTS
|
|
3419
3436
|
})
|
|
3420
3437
|
});
|
|
3421
3438
|
}
|
|
3439
|
+
function FooterDock(props) {
|
|
3440
|
+
const { sessionId } = props;
|
|
3441
|
+
const ready = useResident(footers, sessionId);
|
|
3442
|
+
(0, react.useLayoutEffect)(() => footers.mark(sessionId), [sessionId]);
|
|
3443
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SurfaceErrorBoundary, {
|
|
3444
|
+
t: props.t,
|
|
3445
|
+
children: ready ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Body, {
|
|
3446
|
+
...props,
|
|
3447
|
+
owns: COMPOSER_DOCK_LAYOUTS,
|
|
3448
|
+
footer: true
|
|
3449
|
+
}) : null
|
|
3450
|
+
});
|
|
3451
|
+
}
|
|
3422
3452
|
/**
|
|
3423
3453
|
* The centralized management overlay (spec 8.1, 8.3).
|
|
3424
3454
|
*
|
|
@@ -3441,6 +3471,7 @@ window.__ModuleLoader__.load({
|
|
|
3441
3471
|
return {
|
|
3442
3472
|
InputDock,
|
|
3443
3473
|
ComposerDock,
|
|
3474
|
+
FooterDock,
|
|
3444
3475
|
ManagerDock
|
|
3445
3476
|
};
|
|
3446
3477
|
}
|
|
@@ -3463,20 +3494,28 @@ window.__ModuleLoader__.load({
|
|
|
3463
3494
|
* Colours are DSH alias theme tokens only — nothing here defines a palette, and
|
|
3464
3495
|
* nothing overrides a global theme (spec 8.4).
|
|
3465
3496
|
*
|
|
3466
|
-
* ## The width rule (spec 8.2)
|
|
3497
|
+
* ## The width rule (spec 8.2, 22.9)
|
|
3467
3498
|
*
|
|
3468
|
-
*
|
|
3469
|
-
*
|
|
3499
|
+
* `.dsh-cqa-ribbon` (and the launcher, in the same box) renders in the composer
|
|
3500
|
+
* stack, outside the InputBar, which is the element that owns
|
|
3501
|
+
* `--dsh-composer-side-clearance` as padding. It therefore subtracts that
|
|
3502
|
+
* clearance from both sides itself, is capped at `--dsh-composer-card-max-width`
|
|
3503
|
+
* — the same cap the composer card uses — and is centred, so its left and right
|
|
3504
|
+
* edges coincide with the input box exactly rather than approximately.
|
|
3470
3505
|
*
|
|
3471
|
-
*
|
|
3472
|
-
*
|
|
3473
|
-
*
|
|
3474
|
-
* - `.dsh-cqa-bar` renders as the InputBar's last child, inside that padding, so
|
|
3475
|
-
* it is simply `100%` wide.
|
|
3506
|
+
* In the optional composer footer, the core owns card alignment and the bar
|
|
3507
|
+
* fills that row; its control group is centred (spec 23.1). The rules below
|
|
3508
|
+
* still apply to the fallback for unpatched cores.
|
|
3476
3509
|
*
|
|
3477
|
-
*
|
|
3478
|
-
*
|
|
3479
|
-
* the
|
|
3510
|
+
* `.dsh-cqa-bar` in that fallback makes no such claim. Since DSH 0.1.6-alpha.2 the composer dock is
|
|
3511
|
+
* a row under the card that DSH centres and sizes to its content, shared with
|
|
3512
|
+
* DSH's own stats pills and context meter, so the bar is a content-sized member of
|
|
3513
|
+
* that row (spec 22.9). It only has to stay inside it: `min-width: 0` lets it
|
|
3514
|
+
* shrink when the row reaches the composer's width, which is what hands the
|
|
3515
|
+
* overflow split a smaller region to fold into "more". Once it folds it claims
|
|
3516
|
+
* the card's width (`[data-quick-actions-overflow]`), capped by the row's own
|
|
3517
|
+
* `max-width: 100%`: content-sized, the region the split measures would only be
|
|
3518
|
+
* as wide as what it already shows, and a wider window could never unfold it.
|
|
3480
3519
|
*/
|
|
3481
3520
|
const TAG_ID = "dsh-quick-actions/surfaces.css";
|
|
3482
3521
|
const QUICK_ACTIONS_CSS = `
|
|
@@ -3489,9 +3528,30 @@ window.__ModuleLoader__.load({
|
|
|
3489
3528
|
}
|
|
3490
3529
|
.dsh-cqa-bar {
|
|
3491
3530
|
box-sizing: border-box;
|
|
3492
|
-
width:
|
|
3531
|
+
min-width: 0;
|
|
3493
3532
|
max-width: var(--dsh-composer-card-max-width);
|
|
3494
|
-
|
|
3533
|
+
}
|
|
3534
|
+
/* Folding: claim the card's width, for the dock row's own max-width to cap. */
|
|
3535
|
+
.dsh-cqa-bar[data-quick-actions-overflow] {
|
|
3536
|
+
width: var(--dsh-composer-card-max-width);
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3539
|
+
/* The optional footer is already aligned to the card by its core owner.
|
|
3540
|
+
Only this plugin's row shrinks and centres the whole control group. */
|
|
3541
|
+
.dsh-cqa-footer {
|
|
3542
|
+
width: 100%;
|
|
3543
|
+
min-width: 0;
|
|
3544
|
+
}
|
|
3545
|
+
.dsh-cqa-footer > .dsh-cqa-bar {
|
|
3546
|
+
width: 100%;
|
|
3547
|
+
}
|
|
3548
|
+
.dsh-cqa-footer .dsh-cqa-row {
|
|
3549
|
+
width: fit-content;
|
|
3550
|
+
max-width: 100%;
|
|
3551
|
+
margin-inline: auto;
|
|
3552
|
+
}
|
|
3553
|
+
.dsh-cqa-footer [data-quick-actions-overflow] .dsh-cqa-row {
|
|
3554
|
+
width: 100%;
|
|
3495
3555
|
}
|
|
3496
3556
|
|
|
3497
3557
|
.dsh-cqa-row {
|
|
@@ -4000,7 +4060,7 @@ window.__ModuleLoader__.load({
|
|
|
4000
4060
|
}, "composer-quick-actions: client controller");
|
|
4001
4061
|
ctx.effect(() => ctx.locale.register(QUICK_ACTIONS_LOCALE_NAMESPACE, quickActionsDictionaries), "composer-quick-actions: dictionaries");
|
|
4002
4062
|
ctx.effect(installQuickActionStyles, "composer-quick-actions: surface styles");
|
|
4003
|
-
const { InputDock, ComposerDock, ManagerDock } = createQuickActionDockEntries({
|
|
4063
|
+
const { InputDock, ComposerDock, FooterDock, ManagerDock } = createQuickActionDockEntries({
|
|
4004
4064
|
controller,
|
|
4005
4065
|
sessions,
|
|
4006
4066
|
residency,
|
|
@@ -4023,6 +4083,12 @@ window.__ModuleLoader__.load({
|
|
|
4023
4083
|
order: DOCK_ORDER,
|
|
4024
4084
|
locale: QUICK_ACTIONS_LOCALE_NAMESPACE
|
|
4025
4085
|
}, ComposerDock));
|
|
4086
|
+
ctx.slots.inject("conversation.composer.footer", () => ctx.slots.register({
|
|
4087
|
+
name: "conversation.composer.footer",
|
|
4088
|
+
id: "composer-quick-actions",
|
|
4089
|
+
order: DOCK_ORDER,
|
|
4090
|
+
locale: QUICK_ACTIONS_LOCALE_NAMESPACE
|
|
4091
|
+
}, FooterDock));
|
|
4026
4092
|
}
|
|
4027
4093
|
//#endregion
|
|
4028
4094
|
exports.apply = apply;
|