@prettier-ai/dsh-client-ui-layout 0.1.2-alpha.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.
- package/LICENSE +21 -0
- package/README.i18n.yaml +6 -0
- package/README.md +88 -0
- package/README.zh.md +88 -0
- package/lib/client.js +490 -0
- package/lib/index.js +6 -0
- package/lib/invariant.js +24 -0
- package/lib/types/client/AppFrame.d.ts +7 -0
- package/lib/types/client/DocumentTitle.d.ts +15 -0
- package/lib/types/client/columns.d.ts +60 -0
- package/lib/types/client/index.d.ts +105 -0
- package/lib/types/client/service.d.ts +47 -0
- package/lib/types/client/stores.d.ts +48 -0
- package/lib/types/client/theme-presenter.d.ts +37 -0
- package/lib/types/index.d.ts +4 -0
- package/lib/types/invariant.d.ts +16 -0
- package/package.json +74 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DeepSeek
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
|
2
|
+
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
|
+
# after editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write packages/client/ui-layout/README.md
|
|
5
|
+
README.md: 5eba9ac8ce793092053d9b8c84daa8f737597c26
|
|
6
|
+
README.zh.md: 1af81cea580d97cfa89365bdd79659933c0b2ae1
|
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Shell layout for the Web GUI: the three-column AppFrame with drag handles, concession behavior, the panel-geometry service, and theme presentation; for users and maintainers of the window chrome."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-client-ui-layout
|
|
7
|
+
|
|
8
|
+
English | [中文](README.zh.md)
|
|
9
|
+
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
This package provides the shell layout of the Web GUI: a three-column AppFrame with resizable sidebar and details panels, a concession chain that shrinks the details column and then auto-closes it when space runs out, and the `ctx.layout` panel-geometry service other plugins call to open or close the details column. It also seats the theme presenter, which projects the resolved color scheme, alias tokens, content font size, and `theme-color` metadata onto the document. Choose it for the standard window chrome; panel geometry is transient and resets on reload.
|
|
13
|
+
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Use this package](#use-this-package)
|
|
17
|
+
- [Understand the implementation](#understand-the-implementation)
|
|
18
|
+
- [Further Exploration](#further-exploration)
|
|
19
|
+
- [Model Experience](#model-experience)
|
|
20
|
+
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
21
|
+
- [Dev Note](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## Use this package
|
|
27
|
+
|
|
28
|
+
Mount this plugin at the root slot; it then renders the app frame around whatever occupies the sidebar, conversation, and details columns. Users resize the sidebar by dragging its invisible hit strip and the details panel by dragging its floating pill; when the window narrows, only details shrinks, then auto-closes. A closed sidebar retains a 56px control rail; details closes to zero width.
|
|
29
|
+
|
|
30
|
+
### Theme presentation
|
|
31
|
+
|
|
32
|
+
The presenter consumes resolved theme snapshots and projects them onto the document: `html { color-scheme }` for native UA chrome, `body[data-ds-dark-theme]` from the active color scheme, the theme's alias tokens and `--dsh-content-font-size` as inline variables on body, and one owned `<meta name="theme-color">` whose content follows the computed body background. Disposing the presenter removes its metadata node with its other global writes.
|
|
33
|
+
|
|
34
|
+
-----
|
|
35
|
+
|
|
36
|
+
<a id="understand-the-implementation"></a>
|
|
37
|
+
## Understand the implementation
|
|
38
|
+
|
|
39
|
+
<details>
|
|
40
|
+
<summary>Implementation internals — click to expand</summary>
|
|
41
|
+
|
|
42
|
+
One `register()` call contributes `AppFrame` into the runtime's built-in `'root'` slot and, in the same breath, declares the four child slots (`sidebar`, `conversation`, `details`, `shell.overlay`), seats the layout store (panel geometry), and wires the `ctx.layout` panel-action service. The transient layout store starts the sidebar at its default width and details closed, and never reads or writes `localStorage`. AppFrame always mounts the conversation and details columns; a connected Session renders through `SessionProvider`. It projects the selected Session title over the build-configured product title or the localized `common.brand.localBuild` fallback, so locale revisions update document metadata with the root entry. The theme presenter is a second effect: pure DOM writes from resolved snapshots — initial state through the getter once, then event-driven only, with no React path. It applies palette, font-size, and token variables before measuring the rendered background as the single color authority.
|
|
43
|
+
|
|
44
|
+
</details>
|
|
45
|
+
|
|
46
|
+
-----
|
|
47
|
+
|
|
48
|
+
<a id="further-exploration"></a>
|
|
49
|
+
## Further Exploration
|
|
50
|
+
|
|
51
|
+
Read these pages when the layout surface is not enough. They move from the frame to the columns it renders and the theme it presents.
|
|
52
|
+
|
|
53
|
+
- [ui-sidebar](../ui-sidebar/README.md) — occupies the `sidebar` column and its seats.
|
|
54
|
+
- [ui-conversation](../ui-conversation/README.md) — occupies the `conversation` and `details` columns.
|
|
55
|
+
- [ui-theme](../ui-theme/README.md) — the theme seam whose resolved snapshots the presenter consumes.
|
|
56
|
+
- [Web client architecture](../../../.agents/notes/implemented/architecture/2026-07-19-gui-web-client-architecture.md) — how browser plugin rows load and register slots.
|
|
57
|
+
|
|
58
|
+
-----
|
|
59
|
+
|
|
60
|
+
<a id="model-experience"></a>
|
|
61
|
+
## Model Experience
|
|
62
|
+
|
|
63
|
+
None, as the layout shell manages browser viewing state; nothing here reaches a model request.
|
|
64
|
+
|
|
65
|
+
#### KV Cache effect
|
|
66
|
+
|
|
67
|
+
None; this package neither assembles nor sends a provider request.
|
|
68
|
+
|
|
69
|
+
## Known Limitations and Deferred Work
|
|
70
|
+
|
|
71
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
These limits define the current layout behavior. They are current package constraints, not a general window-manager comparison or a task backlog.
|
|
75
|
+
|
|
76
|
+
- **Panel geometry is transient** — reload restores the sidebar default and details closed; switching between distinct Session ids also closes details and forgets its dragged width, while unselected surfaces render details at zero width without modifying geometry.
|
|
77
|
+
- **Concession-chain auto-close derives a zero width without touching the preferred width** — the panel restores itself when the window widens; consumers must not read the stored details width as the rendered truth.
|
|
78
|
+
- **No scroll anchoring during squeeze reflow** — layout changes may move the reader's viewport.
|
|
79
|
+
|
|
80
|
+
<a id="dev-note"></a>
|
|
81
|
+
### Dev Note
|
|
82
|
+
|
|
83
|
+
<details>
|
|
84
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
85
|
+
|
|
86
|
+
None.
|
|
87
|
+
|
|
88
|
+
</details>
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Web GUI 的外壳布局:三栏 AppFrame、拖动手柄与让步行为、面板几何服务与主题呈现;供窗口外观的用户与维护者阅读。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-client-ui-layout
|
|
7
|
+
|
|
8
|
+
[English](README.md) | 中文
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
本包提供 Web GUI 的外壳布局:一个三栏 AppFrame,带可缩放的侧栏与详情面板;一条让步链,在空间不足时先收缩详情栏、随后自动关闭它;以及 `ctx.layout` 面板几何服务,供其他插件调用以打开或关闭详情栏。它还承载主题呈现器,把解析后的配色方案、别名 token、正文字号与 `theme-color` 元数据投影到 document。需要标准窗口外观时选择它;面板几何是瞬时的,重新加载即重置。
|
|
13
|
+
|
|
14
|
+
## 目录
|
|
15
|
+
|
|
16
|
+
- [使用本包](#use-this-package)
|
|
17
|
+
- [理解实现](#understand-the-implementation)
|
|
18
|
+
- [进一步探索](#further-exploration)
|
|
19
|
+
- [模型体验](#model-experience)
|
|
20
|
+
- [已知限制与延期工作](#known-limitations-and-deferred-work)
|
|
21
|
+
- [开发备注](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## 使用本包
|
|
27
|
+
|
|
28
|
+
在 root 槽位挂载本插件;它随即围绕占据侧栏、会话与详情栏的内容渲染应用框架。用户拖动不可见命中条带缩放侧栏、拖动浮动胶囊缩放详情面板;窗口变窄时只有详情栏收缩,随后自动关闭。关闭的侧栏保留 56px 控制栏;详情栏关闭到零宽度。
|
|
29
|
+
|
|
30
|
+
### 主题呈现
|
|
31
|
+
|
|
32
|
+
呈现器消费解析后的主题快照,并投影到 document:`html { color-scheme }` 驱动原生 UA 控件,依据当前配色方案设置 `body[data-ds-dark-theme]`,把主题的别名 token 与 `--dsh-content-font-size` 设为 body 上的内联变量,并持有一个 `<meta name="theme-color">`,其内容随计算后的 body 背景色更新。释放呈现器时,它会连同其他全局写入一起移除自己的元数据节点。
|
|
33
|
+
|
|
34
|
+
-----
|
|
35
|
+
|
|
36
|
+
<a id="understand-the-implementation"></a>
|
|
37
|
+
## 理解实现
|
|
38
|
+
|
|
39
|
+
<details>
|
|
40
|
+
<summary>实现细节——点击展开</summary>
|
|
41
|
+
|
|
42
|
+
一次 `register()` 调用把 `AppFrame` 贡献进运行时的内建 `'root'` 槽位,并在同一刻声明四个子槽位(`sidebar`、`conversation`、`details`、`shell.overlay`)、安放布局 store(面板几何)并接好 `ctx.layout` 面板动作服务。瞬时布局 store 以默认宽度启动侧栏、保持详情栏关闭,从不读写 `localStorage`。AppFrame 始终挂载会话与详情两栏;已连接 Session 经 `SessionProvider` 渲染。它把所选 Session 标题投影到构建配置的产品标题或本地化 `common.brand.localBuild` 回退值之上,因此 locale revision 会随根 entry 一起更新文档元数据。主题呈现器是第二个 effect:从解析后的快照做纯 DOM 写入——初始状态经 getter 读取一次,此后仅事件驱动,不经过 React。它先应用调色板、字号与 token 变量,再把渲染出的背景测量为唯一的颜色依据。
|
|
43
|
+
|
|
44
|
+
</details>
|
|
45
|
+
|
|
46
|
+
-----
|
|
47
|
+
|
|
48
|
+
<a id="further-exploration"></a>
|
|
49
|
+
## 进一步探索
|
|
50
|
+
|
|
51
|
+
当布局面不够用时阅读以下页面。它们从框架进入它所渲染的栏与它所呈现的主题。
|
|
52
|
+
|
|
53
|
+
- [ui-sidebar](../ui-sidebar/README.zh.md)——占据 `sidebar` 栏及其座位。
|
|
54
|
+
- [ui-conversation](../ui-conversation/README.zh.md)——占据 `conversation` 与 `details` 栏。
|
|
55
|
+
- [ui-theme](../ui-theme/README.zh.md)——呈现器消费其解析快照的主题 seam。
|
|
56
|
+
- [Web 客户端架构](../../../.agents/notes/implemented/architecture/2026-07-19-gui-web-client-architecture.zh.md)——浏览器插件行如何加载并注册槽位。
|
|
57
|
+
|
|
58
|
+
-----
|
|
59
|
+
|
|
60
|
+
<a id="model-experience"></a>
|
|
61
|
+
## 模型体验
|
|
62
|
+
|
|
63
|
+
无。布局外壳管理浏览器查看状态;这里没有任何内容进入模型请求。
|
|
64
|
+
|
|
65
|
+
#### KV Cache 影响
|
|
66
|
+
|
|
67
|
+
无;该包既不组装也不发送提供方请求。
|
|
68
|
+
|
|
69
|
+
## 已知限制与延期工作
|
|
70
|
+
|
|
71
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
这些限制界定了当前布局行为。它们是当前包约束,不是通用窗口管理器对比或任务积压。
|
|
75
|
+
|
|
76
|
+
- **面板几何是瞬时状态**——重新加载会恢复侧栏默认值并保持详情栏关闭;在不同会话 id 之间切换同样会关闭详情栏并忘记拖动后的宽度,而未选中表面以零宽度渲染详情栏却不修改几何。
|
|
77
|
+
- **让步链自动关闭通过推导零宽度实现,不触碰偏好宽度**——窗口变宽时面板自行恢复;消费方不得把 store 中的详情宽度当作渲染真值。
|
|
78
|
+
- **挤压重排期间无滚动锚定**——布局变化可能移动读者的视口。
|
|
79
|
+
|
|
80
|
+
<a id="dev-note"></a>
|
|
81
|
+
### 开发备注
|
|
82
|
+
|
|
83
|
+
<details>
|
|
84
|
+
<summary>维护者的工作上下文——点击展开</summary>
|
|
85
|
+
|
|
86
|
+
无。
|
|
87
|
+
|
|
88
|
+
</details>
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "@prettier-ai/dsh-client-ui-layout",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let react = require("react");
|
|
9
|
+
let _prettier_ai_dsh_client_store = require("@prettier-ai/dsh-client-store");
|
|
10
|
+
/** Viewport width below which the sidebar auto-collapses to the rail (deepsuite
|
|
11
|
+
* LG breakpoint); a manual toggle below it re-expands over the squeezed center
|
|
12
|
+
* (stores.ts narrowExpanded). */
|
|
13
|
+
const SIDEBAR_AUTO_COLLAPSE = 1024;
|
|
14
|
+
/**
|
|
15
|
+
* Clamp a panel width into its contract range.
|
|
16
|
+
* @param px - requested width.
|
|
17
|
+
* @param min - range lower bound.
|
|
18
|
+
* @param max - range upper bound.
|
|
19
|
+
* @returns the clamped width.
|
|
20
|
+
*/
|
|
21
|
+
function clampWidth(px, min, max) {
|
|
22
|
+
return Math.min(max, Math.max(min, Math.round(px)));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Solve the three column widths for one viewport frame. Pure: no hysteresis —
|
|
26
|
+
* the output is a function of (viewport, preferences) only, so recovery on
|
|
27
|
+
* re-widening is automatic. Preferences re-clamp here because they cross the
|
|
28
|
+
* store boundary and callers may still supply stale ranges.
|
|
29
|
+
* @param viewport - available frame width in px.
|
|
30
|
+
* @param sidebar - sidebar width preference in px (0 = closed).
|
|
31
|
+
* @param details - details width preference in px (0 = closed).
|
|
32
|
+
* @returns resolved widths; details 0 means visually closed (never unmounted), while a closed sidebar keeps its compact rail.
|
|
33
|
+
*/
|
|
34
|
+
function computeColumns(viewport, sidebar, details) {
|
|
35
|
+
const s = sidebar === 0 ? 56 : clampWidth(sidebar, 264, 420);
|
|
36
|
+
const d0 = details === 0 ? 0 : clampWidth(details, 300, 520);
|
|
37
|
+
if (s + d0 + 640 <= viewport) return {
|
|
38
|
+
sidebar: s,
|
|
39
|
+
center: viewport - s - d0,
|
|
40
|
+
details: d0
|
|
41
|
+
};
|
|
42
|
+
const d1 = d0 === 0 ? 0 : Math.max(300, viewport - s - 640);
|
|
43
|
+
if (s + d1 + 640 <= viewport) return {
|
|
44
|
+
sidebar: s,
|
|
45
|
+
center: 640,
|
|
46
|
+
details: d1
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
sidebar: s,
|
|
50
|
+
center: Math.max(0, viewport - s),
|
|
51
|
+
details: 0
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region lib/types/client/DocumentTitle.js
|
|
56
|
+
/**
|
|
57
|
+
* Project the selected durable session title into the browser title and
|
|
58
|
+
* restore the build-selected product title when unmounted.
|
|
59
|
+
* @param props - Selected session title projection.
|
|
60
|
+
* @returns No rendered content.
|
|
61
|
+
*/
|
|
62
|
+
function DocumentTitle({ title, productTitle }) {
|
|
63
|
+
(0, react.useEffect)(() => {
|
|
64
|
+
document.title = title === void 0 ? productTitle : `${title} — ${productTitle}`;
|
|
65
|
+
return () => {
|
|
66
|
+
document.title = productTitle;
|
|
67
|
+
};
|
|
68
|
+
}, [productTitle, title]);
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region \0dsh-css:/home/runner/work/dsh-publisher/dsh-publisher/upstream/packages/client/ui-layout/src/client/AppFrame.module.css.mjs
|
|
73
|
+
const css = ".OCJTjG_frame{background:var(--dsw-alias-bg-base);height:100%;transition:grid-template-columns var(--ds-transition-duration-slow) var(--ds-ease-in-out);grid-template-rows:100%;display:grid;position:relative;overflow:hidden}.OCJTjG_frame[data-dragging]{transition:none}@media (prefers-reduced-motion:reduce){.OCJTjG_frame{transition:none}}.OCJTjG_sidebarCol{background:var(--dsw-specific-sidebar-fill);border-right:1px solid var(--dsw-alias-border-l1);min-width:0;overflow:hidden}.OCJTjG_centerCol{flex-direction:column;min-width:0;display:flex;overflow:hidden}.OCJTjG_detailsCol{border-left:1px solid var(--dsw-alias-border-l2);min-width:0;overflow:hidden}.OCJTjG_frame[data-details-collapsed] .OCJTjG_detailsCol{border-left:none}.OCJTjG_handle{cursor:col-resize;z-index:2;touch-action:none;width:8px;transition:left var(--ds-transition-duration-slow) var(--ds-ease-in-out);margin-left:-4px;position:absolute;top:0;bottom:0}.OCJTjG_frame[data-dragging] .OCJTjG_handle{transition:none}@media (prefers-reduced-motion:reduce){.OCJTjG_handle{transition:none}}.OCJTjG_handle[data-side=details]:after{content:\"\";box-sizing:border-box;background:var(--dsw-alias-button-floating-fill);border:1px solid var(--dsw-alias-border-l2-darkmode-thin);opacity:0;width:12px;height:32px;transition:opacity var(--ds-transition-duration-slow) var(--ds-ease-in-out), background var(--ds-transition-duration-slow) var(--ds-ease-in-out);border-radius:10px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.OCJTjG_detailsCol:hover~.OCJTjG_handle[data-side=details]:after,.OCJTjG_handle[data-side=details]:hover:after,.OCJTjG_handle[data-side=details][data-dragging=true]:after{opacity:1}.OCJTjG_handle[data-side=details]:hover:after,.OCJTjG_handle[data-side=details][data-dragging=true]:after{background:var(--dsw-alias-button-floating-hover);border-color:var(--dsw-alias-border-l3)}.OCJTjG_overlayLayer{z-index:20;pointer-events:none;position:absolute;inset:0}.OCJTjG_overlayLayer>*{pointer-events:auto}";
|
|
74
|
+
const tagId = "@prettier-ai/dsh-client-ui-layout/AppFrame.module.css";
|
|
75
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
76
|
+
const tag = document.createElement("style");
|
|
77
|
+
tag.dataset.plugin = "@prettier-ai/dsh-client-ui-layout";
|
|
78
|
+
tag.dataset.pluginCss = tagId;
|
|
79
|
+
tag.textContent = css;
|
|
80
|
+
document.head.appendChild(tag);
|
|
81
|
+
}
|
|
82
|
+
var AppFrame_module_css_default = {
|
|
83
|
+
"centerCol": "OCJTjG_centerCol",
|
|
84
|
+
"detailsCol": "OCJTjG_detailsCol",
|
|
85
|
+
"frame": "OCJTjG_frame",
|
|
86
|
+
"handle": "OCJTjG_handle",
|
|
87
|
+
"overlayLayer": "OCJTjG_overlayLayer",
|
|
88
|
+
"sidebarCol": "OCJTjG_sidebarCol"
|
|
89
|
+
};
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region lib/types/client/AppFrame.js
|
|
92
|
+
/**
|
|
93
|
+
* Three-column shell frame, registered into the built-in 'root' slot (the web
|
|
94
|
+
* shell renders only 'root'). Owns the grid tracks (sidebar | center |
|
|
95
|
+
* details), the drag handles (pointer capture + rAF throttle), the concession
|
|
96
|
+
* chain (columns.ts), and the child-slot render decisions: the sidebar slot
|
|
97
|
+
* renders HERE with live parameters from the concession solve, and the
|
|
98
|
+
* session-aware occupants render in fixed column positions; strict entries
|
|
99
|
+
* gate themselves on current-session availability while session-maybe
|
|
100
|
+
* entries retain identity. Pure component: everything arrives
|
|
101
|
+
* through the three framework shares — zero cordis or framework imports,
|
|
102
|
+
* zero self-made hooks.
|
|
103
|
+
*/
|
|
104
|
+
/** Center column grid item (session-body building block). */
|
|
105
|
+
function CenterColumn(props) {
|
|
106
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
107
|
+
className: AppFrame_module_css_default.centerCol,
|
|
108
|
+
children: props.children
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/** Details column grid item; width 0 keeps the subtree mounted (never unmount on close). */
|
|
112
|
+
function DetailsColumn(props) {
|
|
113
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
114
|
+
className: AppFrame_module_css_default.detailsCol,
|
|
115
|
+
children: props.children
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* One drag handle: pointer capture, rAF-throttled dx reports against the drag-start origin.
|
|
120
|
+
* `side` keys the hover-reveal CSS to the owning column.
|
|
121
|
+
*/
|
|
122
|
+
function DragHandle(props) {
|
|
123
|
+
const [dragging, setDragging] = (0, react.useState)(false);
|
|
124
|
+
const origin = (0, react.useRef)(0);
|
|
125
|
+
const latest = (0, react.useRef)(0);
|
|
126
|
+
const frame = (0, react.useRef)(null);
|
|
127
|
+
const callbacks = (0, react.useRef)({
|
|
128
|
+
onStart: props.onStart,
|
|
129
|
+
onDrag: props.onDrag,
|
|
130
|
+
onEnd: props.onEnd
|
|
131
|
+
});
|
|
132
|
+
callbacks.current = {
|
|
133
|
+
onStart: props.onStart,
|
|
134
|
+
onDrag: props.onDrag,
|
|
135
|
+
onEnd: props.onEnd
|
|
136
|
+
};
|
|
137
|
+
const onPointerDown = (0, react.useCallback)((e) => {
|
|
138
|
+
e.preventDefault();
|
|
139
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
140
|
+
origin.current = e.clientX;
|
|
141
|
+
latest.current = e.clientX;
|
|
142
|
+
callbacks.current.onStart();
|
|
143
|
+
setDragging(true);
|
|
144
|
+
}, []);
|
|
145
|
+
const onPointerMove = (0, react.useCallback)((e) => {
|
|
146
|
+
if (!e.currentTarget.hasPointerCapture(e.pointerId)) return;
|
|
147
|
+
latest.current = e.clientX;
|
|
148
|
+
frame.current ??= requestAnimationFrame(() => {
|
|
149
|
+
frame.current = null;
|
|
150
|
+
callbacks.current.onDrag(latest.current - origin.current);
|
|
151
|
+
});
|
|
152
|
+
}, []);
|
|
153
|
+
const onPointerUp = (0, react.useCallback)((e) => {
|
|
154
|
+
if (!e.currentTarget.hasPointerCapture(e.pointerId)) return;
|
|
155
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
156
|
+
if (frame.current !== null) {
|
|
157
|
+
cancelAnimationFrame(frame.current);
|
|
158
|
+
frame.current = null;
|
|
159
|
+
}
|
|
160
|
+
callbacks.current.onDrag(latest.current - origin.current);
|
|
161
|
+
setDragging(false);
|
|
162
|
+
callbacks.current.onEnd();
|
|
163
|
+
}, []);
|
|
164
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
165
|
+
className: AppFrame_module_css_default.handle,
|
|
166
|
+
style: { left: props.left },
|
|
167
|
+
"data-side": props.side,
|
|
168
|
+
"data-dragging": dragging || void 0,
|
|
169
|
+
onPointerDown,
|
|
170
|
+
onPointerMove,
|
|
171
|
+
onPointerUp
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/** The three-column frame (see module doc). */
|
|
175
|
+
function AppFrame({ useStore, useSessions, actions, renderSlot, SessionProvider, t }) {
|
|
176
|
+
const panels = useStore((s) => s);
|
|
177
|
+
const detailsSession = useSessions((s) => {
|
|
178
|
+
const current = s.current;
|
|
179
|
+
return current !== void 0 && s.byId[current]?.blank === false ? current : void 0;
|
|
180
|
+
});
|
|
181
|
+
const documentTitle = useSessions((s) => {
|
|
182
|
+
const current = s.current;
|
|
183
|
+
return current === void 0 ? void 0 : s.byId[current]?.title;
|
|
184
|
+
});
|
|
185
|
+
const frameRef = (0, react.useRef)(null);
|
|
186
|
+
const [viewport, setViewport] = (0, react.useState)(() => window.innerWidth);
|
|
187
|
+
const lastSession = (0, react.useRef)(detailsSession);
|
|
188
|
+
(0, react.useLayoutEffect)(() => {
|
|
189
|
+
if (detailsSession === void 0) return;
|
|
190
|
+
if (lastSession.current !== void 0 && lastSession.current !== detailsSession) actions.closeDetails();
|
|
191
|
+
lastSession.current = detailsSession;
|
|
192
|
+
}, [actions, detailsSession]);
|
|
193
|
+
(0, react.useEffect)(() => {
|
|
194
|
+
const el = frameRef.current;
|
|
195
|
+
/* v8 ignore next -- the ref is always attached by effect time: the frame div renders unconditionally. */
|
|
196
|
+
if (el === null) return;
|
|
197
|
+
let raf = null;
|
|
198
|
+
const observer = new ResizeObserver(() => {
|
|
199
|
+
raf ??= requestAnimationFrame(() => {
|
|
200
|
+
raf = null;
|
|
201
|
+
const width = el.getBoundingClientRect().width;
|
|
202
|
+
if (width > 0) setViewport(width);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
observer.observe(el);
|
|
206
|
+
return () => {
|
|
207
|
+
observer.disconnect();
|
|
208
|
+
if (raf !== null) cancelAnimationFrame(raf);
|
|
209
|
+
};
|
|
210
|
+
}, []);
|
|
211
|
+
const narrow = viewport < SIDEBAR_AUTO_COLLAPSE;
|
|
212
|
+
(0, react.useEffect)(() => {
|
|
213
|
+
actions.setNarrow(narrow);
|
|
214
|
+
}, [actions, narrow]);
|
|
215
|
+
const sidebarCollapsed = narrow ? !panels.narrowExpanded : panels.sidebar === 0;
|
|
216
|
+
const cols = computeColumns(viewport, sidebarCollapsed ? 0 : panels.sidebar === 0 ? 280 : panels.sidebar, detailsSession === void 0 ? 0 : panels.details);
|
|
217
|
+
const colsRef = (0, react.useRef)(cols);
|
|
218
|
+
colsRef.current = cols;
|
|
219
|
+
const sidebarBase = (0, react.useRef)(0);
|
|
220
|
+
const detailsBase = (0, react.useRef)(0);
|
|
221
|
+
const [dragging, setDragging] = (0, react.useState)(false);
|
|
222
|
+
const onDragEnd = (0, react.useCallback)(() => {
|
|
223
|
+
setDragging(false);
|
|
224
|
+
}, []);
|
|
225
|
+
const onSidebarStart = (0, react.useCallback)(() => {
|
|
226
|
+
sidebarBase.current = colsRef.current.sidebar;
|
|
227
|
+
setDragging(true);
|
|
228
|
+
}, []);
|
|
229
|
+
const onDetailsStart = (0, react.useCallback)(() => {
|
|
230
|
+
detailsBase.current = colsRef.current.details;
|
|
231
|
+
setDragging(true);
|
|
232
|
+
}, []);
|
|
233
|
+
const onSidebarDrag = (0, react.useCallback)((dx) => {
|
|
234
|
+
actions.setSidebar(sidebarBase.current + dx);
|
|
235
|
+
}, [actions]);
|
|
236
|
+
const onDetailsDrag = (0, react.useCallback)((dx) => {
|
|
237
|
+
actions.setDetails(detailsBase.current - dx);
|
|
238
|
+
}, [actions]);
|
|
239
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
240
|
+
ref: frameRef,
|
|
241
|
+
className: AppFrame_module_css_default.frame,
|
|
242
|
+
style: { gridTemplateColumns: `${cols.sidebar}px minmax(0, 1fr) ${cols.details}px` },
|
|
243
|
+
"data-sidebar-collapsed": sidebarCollapsed || void 0,
|
|
244
|
+
"data-details-collapsed": cols.details === 0 || void 0,
|
|
245
|
+
"data-dragging": dragging || void 0,
|
|
246
|
+
children: [
|
|
247
|
+
(0, react_jsx_runtime.jsx)(DocumentTitle, {
|
|
248
|
+
productTitle: "DeepSeek Harness",
|
|
249
|
+
...documentTitle === void 0 ? {} : { title: documentTitle }
|
|
250
|
+
}),
|
|
251
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
252
|
+
className: AppFrame_module_css_default.sidebarCol,
|
|
253
|
+
children: renderSlot("sidebar", {
|
|
254
|
+
collapsed: sidebarCollapsed,
|
|
255
|
+
width: cols.sidebar
|
|
256
|
+
})
|
|
257
|
+
}),
|
|
258
|
+
(0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(CenterColumn, { children: renderSlot("conversation", {}) }), (0, react_jsx_runtime.jsx)(DetailsColumn, { children: (0, react_jsx_runtime.jsx)(SessionProvider, { children: renderSlot("details", {}) }) })] }),
|
|
259
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
260
|
+
className: AppFrame_module_css_default.overlayLayer,
|
|
261
|
+
"data-shell-overlay": true,
|
|
262
|
+
children: renderSlot("shell.overlay", {})
|
|
263
|
+
}),
|
|
264
|
+
!sidebarCollapsed && (0, react_jsx_runtime.jsx)(DragHandle, {
|
|
265
|
+
side: "sidebar",
|
|
266
|
+
left: cols.sidebar,
|
|
267
|
+
onStart: onSidebarStart,
|
|
268
|
+
onDrag: onSidebarDrag,
|
|
269
|
+
onEnd: onDragEnd
|
|
270
|
+
}),
|
|
271
|
+
cols.details > 0 && (0, react_jsx_runtime.jsx)(DragHandle, {
|
|
272
|
+
side: "details",
|
|
273
|
+
left: viewport - cols.details,
|
|
274
|
+
onStart: onDetailsStart,
|
|
275
|
+
onDrag: onDetailsDrag,
|
|
276
|
+
onEnd: onDragEnd
|
|
277
|
+
})
|
|
278
|
+
]
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
//#endregion
|
|
282
|
+
//#region lib/types/client/stores.js
|
|
283
|
+
/**
|
|
284
|
+
* The root entry's transient layout store: panel geometry as plain widths in
|
|
285
|
+
* px (0 = closed). Module level exports the factory only — a module-level
|
|
286
|
+
* handle would pin the store's identity in the module
|
|
287
|
+
* cache (a de-facto singleton surviving plugin reloads). register() receives
|
|
288
|
+
* the factory (exclusive use: the framework instantiates per entry), AppFrame
|
|
289
|
+
* derives its PropsStore share from the return type, and the service face
|
|
290
|
+
* receives the bound actions through the registration's inject hook.
|
|
291
|
+
*/
|
|
292
|
+
/**
|
|
293
|
+
* Create the layout panel store handle. The preference IS the width, so
|
|
294
|
+
* closing a panel forgets its drag width — reopening restores the contract
|
|
295
|
+
* default. Actions are the complete write set: drag writes clamp
|
|
296
|
+
* into the panel's contract range and never cross the open/closed line;
|
|
297
|
+
* open/close transitions write 0 / the default explicitly. Below the
|
|
298
|
+
* auto-collapse breakpoint (AppFrame feeds setNarrow) the sidebar toggle
|
|
299
|
+
* flips the narrowExpanded override instead of the preference.
|
|
300
|
+
* @returns the store handle (spec + type + identity + factory in one).
|
|
301
|
+
*/
|
|
302
|
+
function createLayoutStore() {
|
|
303
|
+
return (0, _prettier_ai_dsh_client_store.defineStore)({
|
|
304
|
+
init: () => ({
|
|
305
|
+
sidebar: 280,
|
|
306
|
+
details: 0,
|
|
307
|
+
narrow: false,
|
|
308
|
+
narrowExpanded: false
|
|
309
|
+
}),
|
|
310
|
+
actions: {
|
|
311
|
+
setSidebar: (d, px) => {
|
|
312
|
+
d.sidebar = clampWidth(px, 264, 420);
|
|
313
|
+
},
|
|
314
|
+
setDetails: (d, px) => {
|
|
315
|
+
d.details = clampWidth(px, 300, 520);
|
|
316
|
+
},
|
|
317
|
+
toggleSidebar: (d) => {
|
|
318
|
+
if (d.narrow) d.narrowExpanded = !d.narrowExpanded;
|
|
319
|
+
else d.sidebar = d.sidebar === 0 ? 280 : 0;
|
|
320
|
+
},
|
|
321
|
+
setNarrow: (d, narrow) => {
|
|
322
|
+
if (d.narrow === narrow) return;
|
|
323
|
+
d.narrow = narrow;
|
|
324
|
+
d.narrowExpanded = false;
|
|
325
|
+
},
|
|
326
|
+
openDetails: (d) => {
|
|
327
|
+
if (d.details === 0) d.details = 360;
|
|
328
|
+
},
|
|
329
|
+
closeDetails: (d) => {
|
|
330
|
+
d.details = 0;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
//#endregion
|
|
336
|
+
//#region lib/types/client/service.js
|
|
337
|
+
/** Cross-plugin panel-action face (ctx.layout). */
|
|
338
|
+
var LayoutController = class {
|
|
339
|
+
#panels;
|
|
340
|
+
/**
|
|
341
|
+
* Adopt the root entry's bound store actions. Called from the root
|
|
342
|
+
* registration's inject hook (a sanctioned assembly side effect), so the
|
|
343
|
+
* face is live from the entry's first render; on entry re-register the
|
|
344
|
+
* fresh actions overwrite the stale set.
|
|
345
|
+
* @param actions - bound actions of the entry's layout store instance.
|
|
346
|
+
*/
|
|
347
|
+
attachPanels(actions) {
|
|
348
|
+
this.#panels = actions;
|
|
349
|
+
}
|
|
350
|
+
/** Toggle the sidebar panel (closed ⟷ contract default width). */
|
|
351
|
+
toggleSidebar() {
|
|
352
|
+
this.#require().toggleSidebar();
|
|
353
|
+
}
|
|
354
|
+
/** Open the details panel (no-op when already open). */
|
|
355
|
+
openDetails() {
|
|
356
|
+
this.#require().openDetails();
|
|
357
|
+
}
|
|
358
|
+
/** Close the details panel. */
|
|
359
|
+
closeDetails() {
|
|
360
|
+
this.#require().closeDetails();
|
|
361
|
+
}
|
|
362
|
+
#require() {
|
|
363
|
+
if (this.#panels === void 0) throw new Error("layout: panel actions not wired (root entry not mounted)");
|
|
364
|
+
return this.#panels;
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
//#endregion
|
|
368
|
+
//#region lib/types/client/theme-presenter.js
|
|
369
|
+
/** Body attribute selecting the dark base palette in the token stylesheets. */
|
|
370
|
+
const DARK_ATTRIBUTE = "data-ds-dark-theme";
|
|
371
|
+
/** Body variable carrying the user's content font size in px. */
|
|
372
|
+
const CONTENT_FONT_SIZE_VARIABLE = "--dsh-content-font-size";
|
|
373
|
+
/** Applies theme snapshots to the document; one instance per plugin fiber. */
|
|
374
|
+
var ThemePresenter = class {
|
|
375
|
+
/** Token names this presenter wrote in the last apply (its retraction set). */
|
|
376
|
+
appliedTokens = [];
|
|
377
|
+
/** The single metadata node this presenter inserts and removes. */
|
|
378
|
+
themeColorMeta;
|
|
379
|
+
/** Create the presenter-owned metadata node before the first snapshot arrives. */
|
|
380
|
+
constructor() {
|
|
381
|
+
this.themeColorMeta = document.createElement("meta");
|
|
382
|
+
this.themeColorMeta.name = "theme-color";
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Project a snapshot onto the document: set root `color-scheme` and the body
|
|
386
|
+
* palette attribute from `active.colorScheme` (never the id — `system` is
|
|
387
|
+
* resolved upstream), publish the content font-size axis, then replace the
|
|
388
|
+
* previously applied token variables with `active.tokens`. Browser
|
|
389
|
+
* theme-color metadata follows the computed body background after those
|
|
390
|
+
* writes, so the rendered palette remains the color authority.
|
|
391
|
+
* @param snapshot - resolved theme snapshot from ctx.theme.
|
|
392
|
+
*/
|
|
393
|
+
apply(snapshot) {
|
|
394
|
+
const scheme = snapshot.active.colorScheme;
|
|
395
|
+
document.documentElement.style.colorScheme = scheme;
|
|
396
|
+
const body = document.body;
|
|
397
|
+
if (scheme === "dark") body.setAttribute(DARK_ATTRIBUTE, "");
|
|
398
|
+
else body.removeAttribute(DARK_ATTRIBUTE);
|
|
399
|
+
body.style.setProperty(CONTENT_FONT_SIZE_VARIABLE, `${snapshot.fontSize}px`);
|
|
400
|
+
for (const name of this.appliedTokens) body.style.removeProperty(name);
|
|
401
|
+
this.appliedTokens = [];
|
|
402
|
+
for (const [name, value] of Object.entries(snapshot.active.tokens)) {
|
|
403
|
+
body.style.setProperty(name, value);
|
|
404
|
+
this.appliedTokens.push(name);
|
|
405
|
+
}
|
|
406
|
+
this.themeColorMeta.content = getComputedStyle(body).backgroundColor;
|
|
407
|
+
if (!this.themeColorMeta.isConnected) document.head.append(this.themeColorMeta);
|
|
408
|
+
}
|
|
409
|
+
/** Retract root color-scheme, the palette attribute, token variables, the font-size axis, and the owned metadata node. */
|
|
410
|
+
dispose() {
|
|
411
|
+
document.documentElement.style.removeProperty("color-scheme");
|
|
412
|
+
const body = document.body;
|
|
413
|
+
body.removeAttribute(DARK_ATTRIBUTE);
|
|
414
|
+
body.style.removeProperty(CONTENT_FONT_SIZE_VARIABLE);
|
|
415
|
+
for (const name of this.appliedTokens) body.style.removeProperty(name);
|
|
416
|
+
this.appliedTokens = [];
|
|
417
|
+
this.themeColorMeta.remove();
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
//#endregion
|
|
421
|
+
//#region lib/types/client/index.js
|
|
422
|
+
/** Required services (cordis fiber inject — the loader passes all module exports as an object plugin). */
|
|
423
|
+
const inject = [
|
|
424
|
+
"slots",
|
|
425
|
+
"theme",
|
|
426
|
+
"locale"
|
|
427
|
+
];
|
|
428
|
+
/**
|
|
429
|
+
* Client plugin body: provide ctx.layout, then one register() call — AppFrame
|
|
430
|
+
* into 'root' with the four child-slot declarations, the layout store seat,
|
|
431
|
+
* and the inject hook that hands the store's bound actions to the service.
|
|
432
|
+
* @param ctx - client root context.
|
|
433
|
+
*/
|
|
434
|
+
function apply(ctx) {
|
|
435
|
+
const layout = new LayoutController();
|
|
436
|
+
ctx.effect(() => {
|
|
437
|
+
const disposeService = ctx.reflect.provide("layout", layout);
|
|
438
|
+
const disposeRegistration = ctx.slots.register({
|
|
439
|
+
name: "root",
|
|
440
|
+
locale: "common",
|
|
441
|
+
children: {
|
|
442
|
+
"sidebar": {
|
|
443
|
+
kind: "single",
|
|
444
|
+
scope: "root"
|
|
445
|
+
},
|
|
446
|
+
"conversation": {
|
|
447
|
+
kind: "single",
|
|
448
|
+
scope: "session-maybe"
|
|
449
|
+
},
|
|
450
|
+
"details": {
|
|
451
|
+
kind: "single",
|
|
452
|
+
scope: "session"
|
|
453
|
+
},
|
|
454
|
+
"shell.overlay": {
|
|
455
|
+
kind: "list",
|
|
456
|
+
scope: "root"
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
store: createLayoutStore,
|
|
460
|
+
inject: (actions) => {
|
|
461
|
+
layout.attachPanels(actions);
|
|
462
|
+
return {};
|
|
463
|
+
}
|
|
464
|
+
}, AppFrame);
|
|
465
|
+
return () => {
|
|
466
|
+
disposeRegistration();
|
|
467
|
+
disposeService();
|
|
468
|
+
};
|
|
469
|
+
}, "ui-layout: service + root registration");
|
|
470
|
+
ctx.effect(() => {
|
|
471
|
+
const presenter = new ThemePresenter();
|
|
472
|
+
presenter.apply(ctx.theme.getTheme());
|
|
473
|
+
const off = ctx.on("theme/change", (snapshot) => {
|
|
474
|
+
presenter.apply(snapshot);
|
|
475
|
+
});
|
|
476
|
+
return () => {
|
|
477
|
+
off();
|
|
478
|
+
presenter.dispose();
|
|
479
|
+
};
|
|
480
|
+
}, "ui-layout: theme presenter");
|
|
481
|
+
}
|
|
482
|
+
//#endregion
|
|
483
|
+
exports.LayoutController = LayoutController;
|
|
484
|
+
exports.apply = apply;
|
|
485
|
+
exports.inject = inject;
|
|
486
|
+
return module.exports;
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
//# sourceMappingURL=client.js.map
|
package/lib/index.js
ADDED
package/lib/invariant.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region lib/types/invariant.js
|
|
2
|
+
/**
|
|
3
|
+
* Package-owned invariant companion for `@prettier-ai/dsh-client-ui-layout`.
|
|
4
|
+
* @module @prettier-ai/dsh-client-ui-layout/invariant
|
|
5
|
+
*/
|
|
6
|
+
const PACKAGE_NAME = "@prettier-ai/dsh-client-ui-layout";
|
|
7
|
+
/** Cordis companion plugin name. */
|
|
8
|
+
const name = "client-ui-layout-invariant";
|
|
9
|
+
/** Service required before the companion can reserve package ownership. */
|
|
10
|
+
const inject = ["invariants"];
|
|
11
|
+
/**
|
|
12
|
+
* No runtime invariant: the shell viewing-state store behind ctx.layout emits
|
|
13
|
+
* no cordis events; clamp/prune/concession-chain
|
|
14
|
+
* sequencing is asserted directly by this package's columns and service specs.
|
|
15
|
+
*/
|
|
16
|
+
const install = () => {};
|
|
17
|
+
/**
|
|
18
|
+
* Register this package's invariant companion.
|
|
19
|
+
* @param ctx - Cordis context carrying the invariant service.
|
|
20
|
+
* @returns the installed registration's disposer after setup succeeds.
|
|
21
|
+
*/
|
|
22
|
+
const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
23
|
+
//#endregion
|
|
24
|
+
export { apply, inject, name };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PropsLocale, PropsRenderSlots, PropsRuntime, PropsStore } from '@prettier-ai/dsh-client-ui-slots';
|
|
2
|
+
import type { createLayoutStore } from './stores.ts';
|
|
3
|
+
/** Full composed props: runtime share + child-slot render share + store share. */
|
|
4
|
+
export type AppFrameProps = PropsRuntime<'root'> & PropsRenderSlots<'sidebar' | 'conversation' | 'details' | 'shell.overlay'> & PropsStore<ReturnType<typeof createLayoutStore>> & PropsLocale<'common'>;
|
|
5
|
+
/** The three-column frame (see module doc). */
|
|
6
|
+
export declare function AppFrame({ useStore, useSessions, actions, renderSlot, SessionProvider, t, }: AppFrameProps): import("react").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=AppFrame.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Props for the browser title projection. */
|
|
2
|
+
export interface DocumentTitleProps {
|
|
3
|
+
/** Durable title of the selected session, or undefined for the product title. */
|
|
4
|
+
title?: string;
|
|
5
|
+
/** Build-configured or localized product title. */
|
|
6
|
+
productTitle: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Project the selected durable session title into the browser title and
|
|
10
|
+
* restore the build-selected product title when unmounted.
|
|
11
|
+
* @param props - Selected session title projection.
|
|
12
|
+
* @returns No rendered content.
|
|
13
|
+
*/
|
|
14
|
+
export declare function DocumentTitle({ title, productTitle }: DocumentTitleProps): null;
|
|
15
|
+
//# sourceMappingURL=DocumentTitle.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure concession-chain column solver for the three-column AppFrame.
|
|
3
|
+
* Chain order is fixed by contract: keep center >= CENTER_MIN by shrinking
|
|
4
|
+
* details, then auto-closing it (derived zero width — preferred width
|
|
5
|
+
* preferences are never rewritten, so widening the window restores them).
|
|
6
|
+
* The sidebar never concedes: its rendered width is always the drag
|
|
7
|
+
* preference (or the collapsed rail), and center absorbs any remaining
|
|
8
|
+
* deficit as the last resort. Inputs are the layout store's plain width
|
|
9
|
+
* preferences (0 = closed); a closed sidebar resolves to the fixed
|
|
10
|
+
* SIDEBAR_COLLAPSED control rail while closed details resolve to zero width.
|
|
11
|
+
* The SIDEBAR_AUTO_COLLAPSE breakpoint is consumed by AppFrame, which decides
|
|
12
|
+
* the effective sidebar preference before solving; the solver itself stays
|
|
13
|
+
* breakpoint-free.
|
|
14
|
+
*/
|
|
15
|
+
/** Resolved widths for one frame; center may drop below CENTER_MIN only at the final fallback. */
|
|
16
|
+
export interface Columns {
|
|
17
|
+
sidebar: number;
|
|
18
|
+
center: number;
|
|
19
|
+
details: number;
|
|
20
|
+
}
|
|
21
|
+
/** Center column floor; only the final fallback may go below it. */
|
|
22
|
+
export declare const CENTER_MIN = 640;
|
|
23
|
+
/** Sidebar drag clamp floor. */
|
|
24
|
+
export declare const SIDEBAR_MIN = 264;
|
|
25
|
+
/** Sidebar drag clamp ceiling. */
|
|
26
|
+
export declare const SIDEBAR_MAX = 420;
|
|
27
|
+
/** Sidebar width before any user drag. */
|
|
28
|
+
export declare const SIDEBAR_DEFAULT = 280;
|
|
29
|
+
/** Closed-sidebar rail: a 24px icon column between 16px horizontal paddings. */
|
|
30
|
+
export declare const SIDEBAR_COLLAPSED = 56;
|
|
31
|
+
/** Viewport width below which the sidebar auto-collapses to the rail (deepsuite
|
|
32
|
+
* LG breakpoint); a manual toggle below it re-expands over the squeezed center
|
|
33
|
+
* (stores.ts narrowExpanded). */
|
|
34
|
+
export declare const SIDEBAR_AUTO_COLLAPSE = 1024;
|
|
35
|
+
/** Details drag clamp floor. */
|
|
36
|
+
export declare const DETAILS_MIN = 300;
|
|
37
|
+
/** Details drag clamp ceiling. */
|
|
38
|
+
export declare const DETAILS_MAX = 520;
|
|
39
|
+
/** Details width before any user drag. */
|
|
40
|
+
export declare const DETAILS_DEFAULT = 360;
|
|
41
|
+
/**
|
|
42
|
+
* Clamp a panel width into its contract range.
|
|
43
|
+
* @param px - requested width.
|
|
44
|
+
* @param min - range lower bound.
|
|
45
|
+
* @param max - range upper bound.
|
|
46
|
+
* @returns the clamped width.
|
|
47
|
+
*/
|
|
48
|
+
export declare function clampWidth(px: number, min: number, max: number): number;
|
|
49
|
+
/**
|
|
50
|
+
* Solve the three column widths for one viewport frame. Pure: no hysteresis —
|
|
51
|
+
* the output is a function of (viewport, preferences) only, so recovery on
|
|
52
|
+
* re-widening is automatic. Preferences re-clamp here because they cross the
|
|
53
|
+
* store boundary and callers may still supply stale ranges.
|
|
54
|
+
* @param viewport - available frame width in px.
|
|
55
|
+
* @param sidebar - sidebar width preference in px (0 = closed).
|
|
56
|
+
* @param details - details width preference in px (0 = closed).
|
|
57
|
+
* @returns resolved widths; details 0 means visually closed (never unmounted), while a closed sidebar keeps its compact rail.
|
|
58
|
+
*/
|
|
59
|
+
export declare function computeColumns(viewport: number, sidebar: number, details: number): Columns;
|
|
60
|
+
//# sourceMappingURL=columns.d.ts.map
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout plugin, browser half: one register() call contributes AppFrame into
|
|
3
|
+
* the runtime's built-in 'root' slot and, in the same breath, declares the
|
|
4
|
+
* four child slots (declaration = exclusive render authority), seats the
|
|
5
|
+
* layout store (panel geometry), and wires the panel-action service face.
|
|
6
|
+
* ctx.layout is the cross-plugin panel-action contract; navigation state lives
|
|
7
|
+
* with the runtime sessions service. A second effect seats the theme
|
|
8
|
+
* presenter, which projects ctx.theme snapshots onto document.body.
|
|
9
|
+
*/
|
|
10
|
+
import type { Context as ClientContext } from '@prettier-ai/cordis';
|
|
11
|
+
export { LayoutController } from './service.ts';
|
|
12
|
+
export type { ILayout } from './service.ts';
|
|
13
|
+
declare module '@prettier-ai/cordis' {
|
|
14
|
+
interface Context {
|
|
15
|
+
/** The outward face only; the concrete service stays inside this plugin. */
|
|
16
|
+
layout: import('./service.ts').ILayout;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
declare module '@prettier-ai/dsh-client-ui-slots' {
|
|
20
|
+
interface SlotMap {
|
|
21
|
+
/**
|
|
22
|
+
* The whole left column. OCCUPIED by ui-sidebar's SidebarRoot, which
|
|
23
|
+
* declares the workspace and settings seats inside it — registering here
|
|
24
|
+
* replaces the navigation column outright rather than adding to it, and
|
|
25
|
+
* the seats it declares disappear with it. To add something to the
|
|
26
|
+
* sidebar, register into one of those inner seats instead.
|
|
27
|
+
*
|
|
28
|
+
* The occupant receives the frame's live column state (collapsed, width)
|
|
29
|
+
* and is expected to render the compact control rail while collapsed.
|
|
30
|
+
*/
|
|
31
|
+
'sidebar': {
|
|
32
|
+
kind: 'single';
|
|
33
|
+
scope: 'root';
|
|
34
|
+
owner: SidebarOwnerProps;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* The whole center column, across both the no-session hero and a live
|
|
38
|
+
* conversation. OCCUPIED by ui-conversation's ConversationRoot, which
|
|
39
|
+
* declares the session body, composer, and input seats inside it —
|
|
40
|
+
* registering here replaces the entire conversation surface (and removes
|
|
41
|
+
* every seat it declares) rather than adding to it.
|
|
42
|
+
*
|
|
43
|
+
* Current-session-optional: the occupant owns both states without
|
|
44
|
+
* changing its React identity, so it keeps its own state across a session
|
|
45
|
+
* switch. It receives no owner props; session facts arrive through the
|
|
46
|
+
* framework hooks of the `session-maybe` scope.
|
|
47
|
+
*/
|
|
48
|
+
'conversation': {
|
|
49
|
+
kind: 'single';
|
|
50
|
+
scope: 'session-maybe';
|
|
51
|
+
owner: ConvOwnerProps;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* The right details column, shown when the layout opens it. OCCUPIED by
|
|
55
|
+
* ui-conversation's DetailsPanel, which declares the tool-details seat
|
|
56
|
+
* inside it — registering here replaces the column and takes that seat
|
|
57
|
+
* with it. Absent an occupant the column renders nothing.
|
|
58
|
+
*
|
|
59
|
+
* No owner props: the framework injects the session id and hooks for the
|
|
60
|
+
* `session` scope, and `ctx.layout` owns whether the column is open.
|
|
61
|
+
*/
|
|
62
|
+
'details': {
|
|
63
|
+
kind: 'single';
|
|
64
|
+
scope: 'session';
|
|
65
|
+
owner: DetailsOwnerProps;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Frame-wide floating layer, above every column and outside their scroll
|
|
69
|
+
* containers. Deliberately generic and unowned by any feature: a badge, a
|
|
70
|
+
* toast stack or a status pill all belong here, and entries order among
|
|
71
|
+
* themselves. The layer itself is click-through — entries opt back into
|
|
72
|
+
* pointer events — so an occupant never blocks the app underneath.
|
|
73
|
+
*
|
|
74
|
+
* This is the additive seat for a frame-wide surface of your own: a fresh
|
|
75
|
+
* `id` is added beside the shipped entries instead of replacing them.
|
|
76
|
+
*/
|
|
77
|
+
'shell.overlay': {
|
|
78
|
+
kind: 'list';
|
|
79
|
+
scope: 'root';
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** Sidebar owner share: live column state from the frame's concession solve. */
|
|
84
|
+
export interface SidebarOwnerProps {
|
|
85
|
+
/** True when the sidebar is closed (the column renders the compact control rail). */
|
|
86
|
+
collapsed: boolean;
|
|
87
|
+
/** Rendered column width in px (SIDEBAR_COLLAPSED when collapsed). */
|
|
88
|
+
width: number;
|
|
89
|
+
}
|
|
90
|
+
/** Conversation owner share: business state and actions belong to the registrant. */
|
|
91
|
+
export interface ConvOwnerProps {
|
|
92
|
+
}
|
|
93
|
+
/** Details owner share: empty — sessionId arrives as a framework-standard prop. */
|
|
94
|
+
export interface DetailsOwnerProps {
|
|
95
|
+
}
|
|
96
|
+
/** Required services (cordis fiber inject — the loader passes all module exports as an object plugin). */
|
|
97
|
+
export declare const inject: string[];
|
|
98
|
+
/**
|
|
99
|
+
* Client plugin body: provide ctx.layout, then one register() call — AppFrame
|
|
100
|
+
* into 'root' with the four child-slot declarations, the layout store seat,
|
|
101
|
+
* and the inject hook that hands the store's bound actions to the service.
|
|
102
|
+
* @param ctx - client root context.
|
|
103
|
+
*/
|
|
104
|
+
export declare function apply(ctx: ClientContext): void;
|
|
105
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LayoutController: the cross-plugin panel-action face behind ctx.layout.
|
|
3
|
+
* Panel geometry itself lives in the root entry's layout store (stores.ts);
|
|
4
|
+
* the current-session selection lives with the runtime sessions service, and
|
|
5
|
+
* the per-session active view dissolved into ui-conversation's session store
|
|
6
|
+
* (its only consumer). What remains here is the contract other plugins'
|
|
7
|
+
* apply worlds reach for panel transitions (sidebar toggle from ui-sidebar,
|
|
8
|
+
* details open/close from ui-conversation) — writes stay inside the store's
|
|
9
|
+
* declared action set, delivered as the registration's bound actions.
|
|
10
|
+
*/
|
|
11
|
+
import type { BoundActions } from '@prettier-ai/dsh-client-ui-slots';
|
|
12
|
+
import type { createLayoutStore } from './stores.ts';
|
|
13
|
+
/** The layout store's bound action set (framework-baked, draft params peeled). */
|
|
14
|
+
export type PanelActions = BoundActions<ReturnType<typeof createLayoutStore>>;
|
|
15
|
+
/**
|
|
16
|
+
* The outward layout face (`ctx.layout`): the panel transitions other
|
|
17
|
+
* plugins may trigger — and exactly what a test fake must supply. The
|
|
18
|
+
* attachPanels wiring hook stays on the concrete class (root-entry assembly
|
|
19
|
+
* only).
|
|
20
|
+
*/
|
|
21
|
+
export interface ILayout {
|
|
22
|
+
/** Toggle the sidebar panel (closed ⟷ contract default width). */
|
|
23
|
+
toggleSidebar(): void;
|
|
24
|
+
/** Open the details panel (no-op when already open). */
|
|
25
|
+
openDetails(): void;
|
|
26
|
+
/** Close the details panel. */
|
|
27
|
+
closeDetails(): void;
|
|
28
|
+
}
|
|
29
|
+
/** Cross-plugin panel-action face (ctx.layout). */
|
|
30
|
+
export declare class LayoutController implements ILayout {
|
|
31
|
+
#private;
|
|
32
|
+
/**
|
|
33
|
+
* Adopt the root entry's bound store actions. Called from the root
|
|
34
|
+
* registration's inject hook (a sanctioned assembly side effect), so the
|
|
35
|
+
* face is live from the entry's first render; on entry re-register the
|
|
36
|
+
* fresh actions overwrite the stale set.
|
|
37
|
+
* @param actions - bound actions of the entry's layout store instance.
|
|
38
|
+
*/
|
|
39
|
+
attachPanels(actions: PanelActions): void;
|
|
40
|
+
/** Toggle the sidebar panel (closed ⟷ contract default width). */
|
|
41
|
+
toggleSidebar(): void;
|
|
42
|
+
/** Open the details panel (no-op when already open). */
|
|
43
|
+
openDetails(): void;
|
|
44
|
+
/** Close the details panel. */
|
|
45
|
+
closeDetails(): void;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The root entry's transient layout store: panel geometry as plain widths in
|
|
3
|
+
* px (0 = closed). Module level exports the factory only — a module-level
|
|
4
|
+
* handle would pin the store's identity in the module
|
|
5
|
+
* cache (a de-facto singleton surviving plugin reloads). register() receives
|
|
6
|
+
* the factory (exclusive use: the framework instantiates per entry), AppFrame
|
|
7
|
+
* derives its PropsStore share from the return type, and the service face
|
|
8
|
+
* receives the bound actions through the registration's inject hook.
|
|
9
|
+
*/
|
|
10
|
+
import { type EngineStoreHandle } from '@prettier-ai/dsh-client-store';
|
|
11
|
+
/**
|
|
12
|
+
* Layout store state: panel width preferences in px (0 = closed), plus the
|
|
13
|
+
* narrow-viewport pair — `narrow` mirrors AppFrame's breakpoint reading
|
|
14
|
+
* (viewport < SIDEBAR_AUTO_COLLAPSE) so toggleSidebar can pick semantics, and
|
|
15
|
+
* `narrowExpanded` is the manual override that re-expands the auto-collapsed
|
|
16
|
+
* sidebar over the squeezed center without rewriting the width preference.
|
|
17
|
+
*/
|
|
18
|
+
type LayoutState = {
|
|
19
|
+
sidebar: number;
|
|
20
|
+
details: number;
|
|
21
|
+
narrow: boolean;
|
|
22
|
+
narrowExpanded: boolean;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Annotation twin of the actions literal below (the export needs a declared
|
|
26
|
+
* return type); drift fails assignability at the defineStore call.
|
|
27
|
+
*/
|
|
28
|
+
type LayoutActions = {
|
|
29
|
+
setSidebar: (draft: LayoutState, px: number) => void;
|
|
30
|
+
setDetails: (draft: LayoutState, px: number) => void;
|
|
31
|
+
toggleSidebar: (draft: LayoutState) => void;
|
|
32
|
+
setNarrow: (draft: LayoutState, narrow: boolean) => void;
|
|
33
|
+
openDetails: (draft: LayoutState) => void;
|
|
34
|
+
closeDetails: (draft: LayoutState) => void;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Create the layout panel store handle. The preference IS the width, so
|
|
38
|
+
* closing a panel forgets its drag width — reopening restores the contract
|
|
39
|
+
* default. Actions are the complete write set: drag writes clamp
|
|
40
|
+
* into the panel's contract range and never cross the open/closed line;
|
|
41
|
+
* open/close transitions write 0 / the default explicitly. Below the
|
|
42
|
+
* auto-collapse breakpoint (AppFrame feeds setNarrow) the sidebar toggle
|
|
43
|
+
* flips the narrowExpanded override instead of the preference.
|
|
44
|
+
* @returns the store handle (spec + type + identity + factory in one).
|
|
45
|
+
*/
|
|
46
|
+
export declare function createLayoutStore(): EngineStoreHandle<LayoutState, LayoutActions>;
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=stores.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global theme DOM applier: projects the resolved ThemeSnapshot onto the
|
|
3
|
+
* document — `html { color-scheme }` for native UA chrome (scrollbars, form
|
|
4
|
+
* controls), `body[data-ds-dark-theme]` for the token palette, the active
|
|
5
|
+
* theme's alias-token overrides as inline CSS variables on body, the content
|
|
6
|
+
* font-size axis (`--dsh-content-font-size`), and one presenter-owned
|
|
7
|
+
* `meta[name="theme-color"]` for surrounding browser UI. Pure DOM writes, no
|
|
8
|
+
* React involvement; the presenter only ever retracts what it wrote itself,
|
|
9
|
+
* so foreign attributes, metadata, and inline styles survive.
|
|
10
|
+
*/
|
|
11
|
+
import type { ThemeSnapshot } from '@prettier-ai/dsh-client-ui-theme/client';
|
|
12
|
+
/** Body attribute selecting the dark base palette in the token stylesheets. */
|
|
13
|
+
export declare const DARK_ATTRIBUTE = "data-ds-dark-theme";
|
|
14
|
+
/** Body variable carrying the user's content font size in px. */
|
|
15
|
+
export declare const CONTENT_FONT_SIZE_VARIABLE = "--dsh-content-font-size";
|
|
16
|
+
/** Applies theme snapshots to the document; one instance per plugin fiber. */
|
|
17
|
+
export declare class ThemePresenter {
|
|
18
|
+
/** Token names this presenter wrote in the last apply (its retraction set). */
|
|
19
|
+
private appliedTokens;
|
|
20
|
+
/** The single metadata node this presenter inserts and removes. */
|
|
21
|
+
private readonly themeColorMeta;
|
|
22
|
+
/** Create the presenter-owned metadata node before the first snapshot arrives. */
|
|
23
|
+
constructor();
|
|
24
|
+
/**
|
|
25
|
+
* Project a snapshot onto the document: set root `color-scheme` and the body
|
|
26
|
+
* palette attribute from `active.colorScheme` (never the id — `system` is
|
|
27
|
+
* resolved upstream), publish the content font-size axis, then replace the
|
|
28
|
+
* previously applied token variables with `active.tokens`. Browser
|
|
29
|
+
* theme-color metadata follows the computed body background after those
|
|
30
|
+
* writes, so the rendered palette remains the color authority.
|
|
31
|
+
* @param snapshot - resolved theme snapshot from ctx.theme.
|
|
32
|
+
*/
|
|
33
|
+
apply(snapshot: ThemeSnapshot): void;
|
|
34
|
+
/** Retract root color-scheme, the palette attribute, token variables, the font-size axis, and the owned metadata node. */
|
|
35
|
+
dispose(): void;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=theme-presenter.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package-owned invariant companion for `@prettier-ai/dsh-client-ui-layout`.
|
|
3
|
+
* @module @prettier-ai/dsh-client-ui-layout/invariant
|
|
4
|
+
*/
|
|
5
|
+
import type { Context } from '@prettier-ai/cordis';
|
|
6
|
+
/** Cordis companion plugin name. */
|
|
7
|
+
export declare const name = "client-ui-layout-invariant";
|
|
8
|
+
/** Service required before the companion can reserve package ownership. */
|
|
9
|
+
export declare const inject: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Register this package's invariant companion.
|
|
12
|
+
* @param ctx - Cordis context carrying the invariant service.
|
|
13
|
+
* @returns the installed registration's disposer after setup succeeds.
|
|
14
|
+
*/
|
|
15
|
+
export declare const apply: (ctx: Context) => Promise<() => void>;
|
|
16
|
+
//# sourceMappingURL=invariant.d.ts.map
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prettier-ai/dsh-client-ui-layout",
|
|
3
|
+
"description": "Shell plugin: three-column AppFrame with drag handles, ctx.layout viewing-state service (navigation + panels)",
|
|
4
|
+
"version": "0.1.2-alpha.1",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
|
11
|
+
"directory": "packages/client/ui-layout"
|
|
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
|
+
"./invariant": {
|
|
22
|
+
"types": "./lib/types/invariant.d.ts",
|
|
23
|
+
"default": "./lib/invariant.js"
|
|
24
|
+
},
|
|
25
|
+
"./client": {
|
|
26
|
+
"types": "./lib/types/client/index.d.ts",
|
|
27
|
+
"default": "./lib/client.js"
|
|
28
|
+
},
|
|
29
|
+
"./src/*": "./src/*",
|
|
30
|
+
"./package.json": "./package.json"
|
|
31
|
+
},
|
|
32
|
+
"dsh": {
|
|
33
|
+
"client": {
|
|
34
|
+
"inject": [
|
|
35
|
+
"@prettier-ai/dsh-client-locale",
|
|
36
|
+
"@prettier-ai/dsh-client-ui-renderer",
|
|
37
|
+
"@prettier-ai/dsh-client-ui-session",
|
|
38
|
+
"@prettier-ai/dsh-client-ui-theme"
|
|
39
|
+
],
|
|
40
|
+
"platform": "web"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@prettier-ai/dsh-client-locale": "^0.1.2-alpha.1",
|
|
46
|
+
"@prettier-ai/dsh-client-ui-renderer": "^0.1.2-alpha.1",
|
|
47
|
+
"@prettier-ai/dsh-client-ui-session": "^0.1.2-alpha.1",
|
|
48
|
+
"@prettier-ai/dsh-invariants": "^0.1.2-alpha.1",
|
|
49
|
+
"@prettier-ai/dsh-client-ui-theme": "^0.1.2-alpha.1",
|
|
50
|
+
"@prettier-ai/cordis": "^4.0.1"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/react": "~18.3.1",
|
|
54
|
+
"react": "^18.2.0",
|
|
55
|
+
"@prettier-ai/dsh-client-store": "^0.1.2-alpha.1",
|
|
56
|
+
"@prettier-ai/dsh-client-locale": "^0.1.2-alpha.1",
|
|
57
|
+
"@prettier-ai/dsh-client-ui-renderer": "^0.1.2-alpha.1",
|
|
58
|
+
"@prettier-ai/dsh-client-ui-session": "^0.1.2-alpha.1",
|
|
59
|
+
"@prettier-ai/dsh-client-ui-slots": "^0.1.2-alpha.1",
|
|
60
|
+
"@prettier-ai/dsh-client-ui-theme": "^0.1.2-alpha.1",
|
|
61
|
+
"@prettier-ai/cordis": "^4.0.1",
|
|
62
|
+
"@prettier-ai/dsh-invariants": "^0.1.2-alpha.1"
|
|
63
|
+
},
|
|
64
|
+
"files": [
|
|
65
|
+
"lib/index.js",
|
|
66
|
+
"lib/invariant.js",
|
|
67
|
+
"lib/client.js",
|
|
68
|
+
"lib/types/**/*.d.ts"
|
|
69
|
+
],
|
|
70
|
+
"scripts": {
|
|
71
|
+
"bundle": "tsdown",
|
|
72
|
+
"watch": "tsdown --watch"
|
|
73
|
+
}
|
|
74
|
+
}
|