@kaijia/dsh-sidebar 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +151 -0
- package/cordis.patch.yml +4 -0
- package/lib/client.css +1 -0
- package/lib/client.d.ts +6 -0
- package/lib/client.js +6321 -0
- package/lib/index.d.ts +19 -0
- package/lib/index.js +6167 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kaijia323
|
|
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.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# dsh-sidebar
|
|
2
|
+
|
|
3
|
+
DSH Web Client 的 VSCode 风格文件树侧栏。作为 `#root` 的兄弟节点挂载在 `document.body` 上,通过 CSS layout push 让 DSH 原生界面让出右侧空间;不占用 DSH 原生 `details` slot,因此 blank 会话也能打开。特性:
|
|
4
|
+
|
|
5
|
+
- 侧栏最右侧提供常驻的 VSCode 风格 Activity Bar 图标栏,可切换“文件资源管理器”和“Git 追踪”两个视图;点击当前视图图标可收起/展开侧栏
|
|
6
|
+
- 以当前会话工作区目录(session cwd)为根展示文件树
|
|
7
|
+
- 目录按需懒加载,树与代码视图都做了虚拟滚动
|
|
8
|
+
- 默认不显示内容预览区;点击文件后,在右栏下方预览内容(上方为文件树)
|
|
9
|
+
- 支持多文件 tabs:可同时打开多个文件、横向滚动、点击 `×` 关闭
|
|
10
|
+
- “Git 追踪”视图提供 VSCode 风格的三个子页:**改动**(当前分支、暂存区改动、工作区未暂存改动与未跟踪文件,点击可预览带行级高亮的 diff 或未跟踪文件内容)、**历史**(提交记录、提交信息与单次提交 diff,支持加载更多)、**分支**(本地/远端分支列表,可切换分支或把远端分支检出为本地追踪分支);面板头部提供拉取(pull)与推送(push)操作,执行前会弹出确认框;状态、diff、历史与分支都会随文件监听和 Git 操作自动刷新,无需手动刷新
|
|
11
|
+
- 支持文本/代码(带行号与基础语法高亮)、Markdown 渲染 / 源码切换、常见图片预览
|
|
12
|
+
- 使用 `chokidar` 监听当前工作区文件变化,文件/目录的新增、修改、删除会自动刷新文件树,并自动重读当前激活的文件预览;未激活的 tab 在切换时读取最新内容,因此面板内不再保留手动刷新按钮
|
|
13
|
+
- 不预置目录忽略规则,文件系统里有什么就展示什么(`node_modules` 等大目录靠懒加载 + 虚拟化抗压;文件监听默认忽略 `node_modules` 和 `.git`,并自动遵循工作区 `.gitignore` 声明的忽略路径,避免监听构建产物等大目录;可通过 `watchIgnored` 追加忽略规则)
|
|
14
|
+
|
|
15
|
+
## 架构
|
|
16
|
+
|
|
17
|
+
插件分两半:
|
|
18
|
+
|
|
19
|
+
- **Host half(`src/index.ts`)**:注入 `fs`、`connection` 与 `webServer`,在 `/dsh-sidebar` 注册一个仅 loopback 可访问的 Connection RPC channel,提供 `meta` / `list` / `read` / `git-status` / `git-diff` / `git-log` / `git-show` / `git-branches` / `git-switch` / `git-pull` / `git-push` 等端点;同时在 `/dsh-sidebar/events` 注册同源 SSE 通道,用 `chokidar` 监听当前工作区并把文件变化推送给浏览器。
|
|
20
|
+
- **Browser half(`src/client.tsx`)**:注入 `sessions`、`workspaces`、`connection`,在 `document.body` 上创建自己的 React root 并挂载右侧栏;通过 `EventSource` 订阅文件变化事件,自动失效并重载受影响的目录,同时重读当前激活的预览。右侧栏是 `#root` 的兄弟节点,不注册任何 DSH slot:
|
|
21
|
+
- 打开时通过 `--dsh-sidebar-width` 让 `#root` 让出宽度,形成“真占位”的 VSCode 式侧栏,而不是 overlay;收起时至少让出 40px 给常驻 Activity Bar;
|
|
22
|
+
- 面板本身可拖拽调整宽度(280–640px),宽度与开关状态按 localStorage 持久化;
|
|
23
|
+
- 最右侧是 40px 的 Activity Bar,可在“文件资源管理器”和“Git 追踪”间切换;点击当前视图图标收起侧栏,再次点击展开或切换视图;
|
|
24
|
+
- 两个视图保持挂载以保留文件树/预览状态,当前视图也会持久化;面板头部不显示刷新和关闭按钮;
|
|
25
|
+
- 不依赖 `ctx.layout.openDetails()`,所以 blank / 无消息会话也能打开。
|
|
26
|
+
|
|
27
|
+
> 不修改 DSH 源码,也不替换 DSH 原生 `details` 面板;原生 `details` 是否打开与本插件互不影响。
|
|
28
|
+
|
|
29
|
+
源码按职责拆分,入口文件只保留插件注册逻辑:
|
|
30
|
+
|
|
31
|
+
- `src/index.ts`:Host 插件入口;RPC、文件系统、Git、配置等逻辑在 `src/host/`(`config` / `fs` / `git` / `handlers` / `rpc` / `result` / `utils`)。
|
|
32
|
+
- `src/client.tsx`:Browser 插件入口;React 组件、状态与 API 封装在 `src/client/`(`api` / `activity-bar` / `git-panel` / `diff-view` / `tree` / `preview` / `sidebar-shell` / `styles` 等)。
|
|
33
|
+
- `src/client-model.ts`:与 React 无关的纯模型(路径、扁平化、树交互 reducer),可独立单测。
|
|
34
|
+
|
|
35
|
+
前端样式直接消费 DSH 的主题 alias token(`--dsw-alias-*`),不维护独立色板;组件使用 Tailwind CSS 编写,构建时由 `tailwindcss` 从 `src/client.css` 生成 utility CSS 并内联进客户端 bundle。
|
|
36
|
+
|
|
37
|
+
## 安装
|
|
38
|
+
|
|
39
|
+
要求 DSH `0.1.0-rc.8` 或更新版本、pnpm 10+ 与 Node.js 20+。
|
|
40
|
+
|
|
41
|
+
### 本地安装(源码 / 开发)
|
|
42
|
+
|
|
43
|
+
从仓库或本地源码安装:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/kaijia323/dsh-sidebar.git
|
|
47
|
+
cd dsh-sidebar
|
|
48
|
+
pnpm install
|
|
49
|
+
pnpm build
|
|
50
|
+
dsh plugin --profile web add .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
重启 `dsh web` 后,右侧文件树会自动作为 body 兄弟节点打开并展示;即使当前会话是 blank 也能打开。侧栏最右侧的 Activity Bar 常驻:点击当前视图图标可收起/展开,点击另一个图标切换视图;展开状态下左侧边缘可拖拽调整宽度。
|
|
54
|
+
|
|
55
|
+
### 正式安装(npm 发布版 / 分发制品)
|
|
56
|
+
|
|
57
|
+
正式版已发布到 npm,直接安装:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
dsh plugin --profile web add @kaijia/dsh-sidebar
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`dsh plugin` 会将该包安装到 `$DSH_HOME/profiles/web`,识别 `dsh.bundle` 配置并自动激活插件层。如果不想依赖 npm registry,也可以先用 `pnpm pack` 生成 tarball 来做正式分发(文件名中的版本号以当前 `package.json` 的 `version` 为准):
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pnpm build
|
|
67
|
+
pnpm pack
|
|
68
|
+
dsh plugin --profile web add ./kaijia-dsh-sidebar-0.1.0.tgz
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
两种方式安装后,都可以用以下命令确认配置层已生效:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
dsh --profile web --dump-config
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
输出中应能看到 `# == @kaijia/dsh-sidebar` 层;随后重启 `dsh web` 即可使用。卸载时执行:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
dsh plugin --profile web remove @kaijia/dsh-sidebar
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
> npm 发布包名为 `@kaijia/dsh-sidebar`。
|
|
84
|
+
|
|
85
|
+
## 开发
|
|
86
|
+
|
|
87
|
+
本地开发时修改源码后重跑 `pnpm build`,然后重启 `dsh web`。只改 `cordis.yml` 里的 `config` 时 DSH 会热替换插件实例。
|
|
88
|
+
|
|
89
|
+
### Tailwind 与主题
|
|
90
|
+
|
|
91
|
+
- `src/client.css` 是 Tailwind 入口:只开启 `components` + `utilities`,**不注入 `base` preflight**,避免污染 DSH 宿主样式。
|
|
92
|
+
- 颜色、边框、背景、状态色全部使用 `var(--dsw-alias-*)`,随 DSH 明暗主题自动切换。
|
|
93
|
+
- `pnpm build` 会优先调用 Tailwind CLI 生成 `lib/client.css` 并内联到 `lib/client.js`;如果当前环境尚未安装 Tailwind(如未执行 `pnpm install`),会自动回退到 `src/client.fallback.css`,保证本地构建可用。
|
|
94
|
+
|
|
95
|
+
### 热插拔 / HMR
|
|
96
|
+
|
|
97
|
+
- Host 半的 RPC channel 注册和 Browser 半的 slot 注册都挂在 Cordis fiber 上,插件卸载/HMR 时自动撤销。
|
|
98
|
+
- 每个插件 fiber 都会创建**自己的** `<style data-dsh-sidebar-style>` 节点,disposer 只移除自己创建的那个,因此热替换重叠期间不会互相删除样式,也不会残留旧样式。
|
|
99
|
+
|
|
100
|
+
## 配置
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
- insert:
|
|
104
|
+
- id: dsh-sidebar
|
|
105
|
+
name: '@kaijia/dsh-sidebar'
|
|
106
|
+
config:
|
|
107
|
+
maxTextBytes: 2097152
|
|
108
|
+
maxImageBytes: 8388608
|
|
109
|
+
maxEntriesPerDirectory: 2000
|
|
110
|
+
maxTreeRows: 100000
|
|
111
|
+
watchEnabled: true
|
|
112
|
+
watchDebounceMs: 200
|
|
113
|
+
watchIgnored:
|
|
114
|
+
- '**/node_modules/**'
|
|
115
|
+
- '**/.git/**'
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
| 配置 | 默认值 | 说明 |
|
|
119
|
+
| --- | --- | --- |
|
|
120
|
+
| `maxTextBytes` | `2097152` | 单次文本预览上限(UTF-8 字节) |
|
|
121
|
+
| `maxImageBytes` | `8388608` | 单张图片预览上限(字节,经 base64 返回) |
|
|
122
|
+
| `maxEntriesPerDirectory` | `2000` | 单目录最多返回的条目数;超出时截断并在树上提示 |
|
|
123
|
+
| `maxTreeRows` | `100000` | 客户端展开后可扁平化的最大树行数,防止超大目录打爆内存 |
|
|
124
|
+
| `watchEnabled` | `true` | 是否开启文件监听实时刷新(文件树与当前激活预览);关闭后侧栏不再自动刷新(当前不提供内置手动刷新按钮) |
|
|
125
|
+
| `watchDebounceMs` | `200` | `chokidar` 写入稳定后触发通知的等待时间(同时是客户端批量刷新窗口) |
|
|
126
|
+
| `watchIgnored` | `['**/node_modules/**', '**/.git/**']` | 文件监听忽略的 glob 列表;仅影响自动刷新通知,不影响文件树展示 |
|
|
127
|
+
|
|
128
|
+
## 测试
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
pnpm test
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
覆盖:
|
|
135
|
+
|
|
136
|
+
- 客户端纯模型:路径处理、根目录解析、懒加载扁平化、行数上限、循环引用保护
|
|
137
|
+
- Host RPC:`meta` / `list` / `read` 成功路径、截断、二进制回退、超大文件、非法路径;Git 的 `status` / `diff` / `log` / `show` / `branches` / `switch` 与远端分支检出
|
|
138
|
+
- 客户端契约回归:标准 hooks 必须传 selector、侧栏必须作为 body 兄弟节点挂载且不注册 `details` / `shell.overlay`、必须通过 `#root` margin-right 做 layout push、lazy-CJS bundle 可物化
|
|
139
|
+
- 前端契约:样式必须使用 DSH alias token + Tailwind 入口(且不注入 preflight)、style installer 必须按 fiber 独立创建/移除(热插拔安全)
|
|
140
|
+
|
|
141
|
+
## 常见问题
|
|
142
|
+
|
|
143
|
+
- **右侧看不到文件树内容?** 当前会话必须带工作区 cwd;无 cwd 时右栏会显示提示。右栏会保持打开。
|
|
144
|
+
- **点了文件显示“二进制文件”?** 非 UTF-8 文本会回退为二进制提示,这是 `dsh-fs` 的文本语义。
|
|
145
|
+
- **图片看不到?** 仅支持 png / jpg / jpeg / gif / webp / bmp / ico / avif,且大小不能超过 `maxImageBytes`。
|
|
146
|
+
- **Git 追踪显示错误?** “Git 追踪”视图依赖本机 `git` 命令;当前工作区目录需要处于 Git 仓库内,才能显示分支、改动和 diff。
|
|
147
|
+
- **升级 DSH 后布局异常?** 本插件依赖 `#root` 作为 DSH 原生根节点和 `--dsh-sidebar-width` 做 layout push;升级后若 DSH 调整根节点结构,先检查 `#root` 的 margin-right 是否仍生效。
|
|
148
|
+
|
|
149
|
+
## License
|
|
150
|
+
|
|
151
|
+
MIT
|
package/cordis.patch.yml
ADDED
package/lib/client.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.kaijia-panel{isolation:isolate;height:100%;min-height:0;max-width:none;flex-direction:column;background-color:transparent;font-size:.75rem;line-height:1rem;color:var(--dsw-alias-label-primary);font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}.kaijia-panel,.kaijia-panel-header{display:flex}.kaijia-panel-header{flex:none;align-items:center;gap:.375rem;border-bottom-width:1px;border-color:var(--dsw-alias-border-l2);padding:0 .625rem;height:34px}.kaijia-panel-title{white-space:nowrap;font-weight:600;letter-spacing:.025em}.kaijia-panel-title-icon{flex:none;color:var(--dsw-alias-label-secondary)}.kaijia-panel-root{min-width:0;flex:1 1 0%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary)}.kaijia-panel-actions{margin-left:auto;display:flex;align-items:center;gap:.125rem}.kaijia-header-button,.kaijia-icon-button,.kaijia-toolbar-button{display:inline-flex;cursor:pointer;align-items:center;gap:.375rem;border-radius:.375rem;border-width:0;background-color:transparent;padding:.375rem;font:inherit;color:inherit;transition:background-color .12s ease,color .12s ease,transform .12s ease}.kaijia-header-button:hover,.kaijia-icon-button:hover,.kaijia-toolbar-button:hover{background-color:var(--dsw-alias-interactive-bg-hover)}.kaijia-header-button:active,.kaijia-icon-button:active,.kaijia-toolbar-button:active{transform:scale(.96)}.kaijia-header-button{white-space:nowrap;border-width:1px;border-color:transparent}.kaijia-header-button:hover{border-color:var(--dsw-alias-border-l2)}.kaijia-toolbar-active{background-color:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-brand-primary)}.kaijia-git-body,.kaijia-panel-body{display:flex;min-height:0;flex:1 1 0%;flex-direction:column}.kaijia-git-body{position:relative}.kaijia-git-list{overflow:auto}.kaijia-git-empty,.kaijia-git-list{position:relative;min-height:0;flex:1 1 0%}.kaijia-git-empty{overflow:hidden}.kaijia-git-spacer{position:relative;min-width:100%}.kaijia-git-section-header{gap:.375rem;border-bottom-width:1px;border-color:var(--dsw-alias-border-l2);font-size:11px;font-weight:500;color:var(--dsw-alias-label-tertiary)}.kaijia-git-row,.kaijia-git-section-header{position:absolute;left:0;right:0;display:flex;align-items:center;padding-left:.625rem;padding-right:.625rem}.kaijia-git-row{cursor:pointer;gap:.5rem;border-width:0 0 0 2px;border-left-color:transparent;background-color:transparent;text-align:left;font-size:.75rem;line-height:1rem;font:inherit;color:inherit;transition:background-color .12s ease,border-color .12s ease}.kaijia-git-row-selected,.kaijia-git-row-selected:hover,.kaijia-git-row:hover{background-color:var(--dsw-alias-interactive-bg-hover)}.kaijia-git-row-selected,.kaijia-git-row-selected:hover{border-left-color:var(--dsw-alias-brand-primary)}.kaijia-git-status{flex:none;font-size:10px;font-weight:500}.kaijia-git-diff{display:flex;min-height:60px;flex:1 1 0%;flex-direction:column}.kaijia-git-diff-header{display:flex;height:30px;flex:none;align-items:center;gap:.375rem;border-bottom-width:1px;border-color:var(--dsw-alias-border-l2);padding-left:.625rem;padding-right:.625rem}.kaijia-git-diff-content{position:relative;display:flex;min-height:0;flex:1 1 0%;flex-direction:column;overflow:hidden}.kaijia-git-tabs{display:flex;flex:none;align-items:stretch;border-bottom-width:1px;border-color:var(--dsw-alias-border-l2)}.kaijia-git-tab{display:inline-flex;height:30px;flex:1 1 0%;cursor:pointer;align-items:center;justify-content:center;gap:.25rem;border-bottom-width:2px;border-color:transparent;background-color:transparent;font-size:11px;color:var(--dsw-alias-label-secondary);font:inherit;transition:background-color .12s ease,color .12s ease,border-color .12s ease}.kaijia-git-tab:hover{background-color:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.kaijia-git-tab-active,.kaijia-git-tab-active:hover{border-bottom-color:var(--dsw-alias-brand-primary);background-color:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary)}.kaijia-git-notice{flex:none;border-bottom-width:1px;border-color:var(--dsw-alias-border-l2);padding:.375rem .625rem;font-size:11px}.kaijia-git-branches,.kaijia-git-history{position:relative;display:flex;min-height:0;flex:1 1 0%;flex-direction:column}.kaijia-git-branches{overflow:auto}.kaijia-branch-row:disabled{cursor:default;opacity:.8}.kaijia-git-commit-row{overflow:visible}.kaijia-load-more-button{display:flex;height:30px;flex:none;cursor:pointer;align-items:center;justify-content:center;gap:.375rem;border-width:1px 0 0;border-color:var(--dsw-alias-border-l2);background-color:transparent;font-size:11px;color:var(--dsw-alias-label-secondary);font:inherit;transition:background-color .12s ease,color .12s ease}.kaijia-load-more-button:hover:not(:disabled){background-color:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.kaijia-commit-meta{-webkit-user-select:text;-moz-user-select:text;user-select:text}.kaijia-confirm-backdrop{display:flex;align-items:center;justify-content:center;padding:1rem;background:color-mix(in srgb,var(--dsw-alias-bg-layer-1) 55%,transparent)}.kaijia-confirm-dialog{border-radius:.5rem;border-width:1px;border-color:var(--dsw-alias-border-l2);background-color:var(--dsw-specific-sidebar-fill);padding:.75rem;box-shadow:0 8px 28px rgba(0,0,0,.28)}.kaijia-diff-scroll{position:relative;min-height:0;flex:1 1 0%;overflow:auto}.kaijia-diff-spacer{position:relative;min-width:100%}.kaijia-diff-line{position:absolute;left:0;right:0;display:flex;align-items:center;padding-left:.625rem;padding-right:.625rem;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:.75rem;line-height:1.25rem}.kaijia-diff-text{white-space:pre;padding-right:.5rem}.kaijia-diff-add,.kaijia-diff-line-add{background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 14%,transparent);color:var(--dsw-alias-state-success-primary)}.kaijia-diff-del,.kaijia-diff-line-del{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 14%,transparent);color:var(--dsw-alias-state-error-primary)}.kaijia-diff-hunk,.kaijia-diff-line-hunk{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent);color:var(--dsw-alias-state-business-primary)}.kaijia-diff-line-meta,.kaijia-diff-meta{color:var(--dsw-alias-label-tertiary)}.kaijia-diff-line-context{color:var(--dsw-alias-label-primary)}.kaijia-activity-bar{display:flex;width:2.5rem;flex:none;flex-direction:column;gap:.125rem;border-left-width:1px;border-color:var(--dsw-alias-border-l2);padding-top:.25rem;padding-bottom:.25rem}.kaijia-activity-bar,.kaijia-activity-item{align-items:center}.kaijia-activity-item{position:relative;display:inline-flex;height:2rem;width:2rem;flex:none;cursor:pointer;justify-content:center;border-radius:.375rem;border-width:0;background-color:transparent;color:var(--dsw-alias-label-secondary);font:inherit;transition:background-color .12s ease,color .12s ease,transform .12s ease}.kaijia-activity-item:hover{background-color:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.kaijia-activity-item:active{transform:scale(.96)}.kaijia-activity-item-active,.kaijia-activity-item-active:hover{background-color:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.kaijia-activity-item-active:before{content:"";position:absolute;left:-4px;top:6px;bottom:6px;width:2px;border-radius:0 1px 1px 0;background:var(--dsw-alias-brand-primary)}.kaijia-sidebar-view{position:relative;flex:1 1 0%}.kaijia-sidebar-view,.kaijia-sidebar-view-pane{display:flex;min-height:0;min-width:0;flex-direction:column}.kaijia-sidebar-view-pane{position:absolute;inset:0}.kaijia-sidebar-view-closed,.kaijia-sidebar-view-hidden{visibility:hidden;pointer-events:none}.kaijia-sidebar-view-closed{position:absolute;inset:0}.kaijia-tree-pane{min-height:120px;flex-shrink:0;flex-direction:column;overflow:hidden}.kaijia-divider,.kaijia-tree-pane{position:relative;display:flex}.kaijia-divider{height:7px;flex:none;touch-action:none;align-items:center;justify-content:center;cursor:row-resize}.kaijia-divider:before{content:"";position:absolute;left:0;right:0;top:50%;height:3px;--tw-translate-y:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));background-color:transparent;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.1s}.kaijia-divider:hover:before{background-color:var(--dsw-alias-brand-primary);opacity:.4}.kaijia-divider-grip{height:3px;width:26px;border-radius:.125rem;background-color:var(--dsw-alias-border-l2)}.kaijia-preview-pane{display:flex;min-height:60px;flex:1 1 0%;flex-direction:column}.kaijia-preview-content,.kaijia-preview-root{display:flex;min-height:0;flex:1 1 0%;flex-direction:column}.kaijia-preview-content{position:relative}.kaijia-tabs-scroll{flex:none;overflow-x:auto;border-bottom-width:1px;border-color:var(--dsw-alias-border-l2);scrollbar-width:none;scrollbar-color:transparent transparent}.kaijia-tabs-scroll::-webkit-scrollbar{height:6px}.kaijia-tabs-scroll::-webkit-scrollbar-thumb{background:transparent;border-radius:9999px}.kaijia-tabs-scroll.is-scrolling{scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,var(--dsw-alias-border-l2)) transparent}.kaijia-tabs-scroll.is-scrolling::-webkit-scrollbar-thumb{background:var(--dsw-alias-scrollbar-bg-l2,var(--dsw-alias-border-l2))}.kaijia-tabs{display:inline-flex;min-width:100%;align-items:stretch}.kaijia-tab{display:flex;height:30px;max-width:180px;flex:none;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;align-items:center;gap:.375rem;white-space:nowrap;border-bottom-width:2px;border-color:transparent;padding-left:.625rem;padding-right:.625rem;font-size:.75rem;line-height:1rem;color:var(--dsw-alias-label-secondary);transition:background-color .12s ease,color .12s ease,border-color .12s ease}.kaijia-tab:hover{background-color:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.kaijia-tab-active,.kaijia-tab-active:hover{border-bottom-color:var(--dsw-alias-brand-primary);background-color:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary)}.kaijia-tab-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kaijia-tab-close{display:inline-flex;height:1rem;width:1rem;flex:none;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;border-width:0;background-color:transparent;padding:0;color:var(--dsw-alias-label-tertiary);font:inherit;opacity:0;transition:opacity .12s ease,background-color .12s ease,color .12s ease}.kaijia-tab-active .kaijia-tab-close,.kaijia-tab:hover .kaijia-tab-close{opacity:1}.kaijia-tab-close:hover{background-color:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.kaijia-code-scroll,.kaijia-diff-scroll,.kaijia-git-list,.kaijia-image-preview,.kaijia-markdown-scroll,.kaijia-tree-scroll{position:relative;min-height:0;flex:1 1 0%;overflow:auto}.kaijia-tree-scroll{outline:2px solid transparent;outline-offset:2px}.kaijia-code-spacer,.kaijia-tree-spacer{position:relative;min-width:100%}.kaijia-tree-row{position:absolute;left:0;right:0;display:flex;height:1.5rem;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;align-items:center;gap:.25rem;white-space:nowrap;background:var(--dsw-specific-sidebar-fill);transition:background-color 80ms ease}.kaijia-tree-row-selected,.kaijia-tree-row-selected:hover,.kaijia-tree-row:hover{background-color:var(--dsw-alias-interactive-bg-hover)}.kaijia-tree-row-selected:before{content:"";position:absolute;top:0;bottom:0;left:0;width:.125rem;background-color:var(--dsw-alias-brand-primary)}.kaijia-tree-note{cursor:default;font-style:italic;color:var(--dsw-alias-label-tertiary)}.kaijia-tree-chevron-slot{display:inline-flex;height:1.5rem;width:.875rem;flex:none;align-items:center;justify-content:center}.kaijia-chevron,.kaijia-tree-chevron{display:inline-flex;align-items:center;justify-content:center;color:var(--dsw-alias-label-tertiary)}.kaijia-chevron{height:.75rem;width:.75rem;flex:none;transition:transform .2s cubic-bezier(.2,0,0,1);will-change:transform}.kaijia-icon{flex:none;color:var(--dsw-alias-label-tertiary)}.kaijia-icon-folder{color:var(--dsw-alias-state-warn-primary)}.kaijia-icon-file{color:var(--dsw-alias-label-tertiary)}.kaijia-icon-image{color:var(--dsw-alias-brand-primary)}.kaijia-icon-markdown{color:var(--dsw-alias-state-success-primary)}.kaijia-tree-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kaijia-panel-message,.kaijia-preview-empty,.kaijia-preview-error,.kaijia-preview-message,.kaijia-tree-empty{display:flex;height:100%;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:1rem;text-align:center;color:var(--dsw-alias-label-tertiary)}.kaijia-preview-error{height:auto;overflow:auto;color:var(--dsw-alias-state-error-primary)}.kaijia-preview-message{color:var(--dsw-alias-label-tertiary)}.kaijia-preview-message strong{color:var(--dsw-alias-label-primary)}.kaijia-preview-meta,.kaijia-tree-truncated{font-size:11px;color:var(--dsw-alias-label-tertiary)}.kaijia-tree-truncated{padding:.25rem .5rem}.kaijia-spinner{display:inline-block;height:11px;width:11px;flex:none;border-radius:9999px;border-width:2px;border-color:var(--dsw-alias-border-l2);border-top-color:var(--dsw-alias-brand-primary);animation:kaijia-spin .8s linear infinite}.kaijia-text-preview{display:flex;min-height:0;flex:1 1 0%;flex-direction:column}.kaijia-preview-toolbar{display:flex;height:26px;flex:none;align-items:center;gap:.125rem;border-bottom-width:1px;border-color:var(--dsw-alias-border-l2);padding-left:.375rem;padding-right:.375rem}.kaijia-preview-toolbar .kaijia-preview-meta{margin-left:auto}.kaijia-code-row{position:absolute;right:0;display:flex;height:1.25rem;align-items:flex-start;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:.75rem;line-height:1.25rem}.kaijia-code-gutter,.kaijia-code-row{left:0}.kaijia-code-gutter{position:sticky;z-index:10;min-width:34px;flex:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;border-right-width:1px;border-color:var(--dsw-alias-border-l2);background-color:var(--dsw-alias-bg-layer-2);padding-left:.5rem;padding-right:.5rem;text-align:right;color:var(--dsw-alias-label-tertiary);padding-left:4px;font-variant-numeric:tabular-nums}.kaijia-code-line{white-space:pre;padding-right:1rem}.kaijia-token-comment{font-style:italic;color:var(--dsw-alias-label-tertiary)}.kaijia-token-string{color:var(--dsw-alias-state-success-primary)}.kaijia-token-number{color:var(--dsw-alias-state-warn-primary)}.kaijia-token-keyword{color:var(--dsw-alias-state-business-primary)}.kaijia-markdown{margin-left:auto;margin-right:auto;max-width:760px;padding:.75rem;line-height:1.625;color:var(--dsw-alias-label-primary);padding-bottom:32px}.kaijia-markdown a{color:var(--dsw-alias-brand-primary);text-decoration-line:none}.kaijia-markdown a:hover{text-decoration-line:underline}.kaijia-markdown h1,.kaijia-markdown h2,.kaijia-markdown h3,.kaijia-markdown h4,.kaijia-markdown h5,.kaijia-markdown h6{margin-top:.5rem;margin-bottom:.5rem;font-weight:600;line-height:1.375}.kaijia-markdown h1{font-size:1.25rem;line-height:1.75rem}.kaijia-markdown h2{font-size:1.125rem;line-height:1.75rem}.kaijia-markdown h3{font-size:1rem;line-height:1.5rem}.kaijia-markdown ol,.kaijia-markdown p,.kaijia-markdown ul{margin-top:.25rem;margin-bottom:.25rem}.kaijia-markdown ol,.kaijia-markdown ul{padding-left:1.5rem}.kaijia-markdown blockquote{margin-top:.25rem;margin-bottom:.25rem;border-left-width:3px;border-color:var(--dsw-alias-border-l3);padding-left:.75rem;padding-right:.75rem;color:var(--dsw-alias-label-secondary)}.kaijia-markdown hr{margin-top:.75rem;margin-bottom:.75rem;border-width:1px 0 0;border-color:var(--dsw-alias-border-l2)}.kaijia-markdown pre{overflow:auto;border-radius:.375rem;border-width:1px;border-color:var(--dsw-alias-border-l2);background-color:var(--dsw-alias-bg-layer-1);padding:.625rem}.kaijia-markdown code{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:.92em}.kaijia-md-code{border-radius:.125rem;background-color:var(--dsw-alias-bg-layer-1);padding:.125rem .25rem}.kaijia-image{margin-left:auto;margin-right:auto;display:block;max-height:100%;max-width:100%;-o-object-fit:contain;object-fit:contain;box-shadow:0 0 0 1px rgba(0,0,0,.1)}body[data-ds-dark-theme] .kaijia-image{box-shadow:0 0 0 1px hsla(0,0%,100%,.1)}.visible{visibility:visible}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-0{bottom:0}.left-0{left:0}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.ml-1{margin-left:.25rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.hidden{display:none}.h-3{height:.75rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-\[11px\]{height:11px}.h-\[26px\]{height:26px}.h-\[30px\]{height:30px}.h-\[3px\]{height:3px}.h-\[7px\]{height:7px}.h-auto{height:auto}.h-full{height:100%}.max-h-full{max-height:100%}.min-h-0{min-height:0}.min-h-\[120px\]{min-height:120px}.min-h-\[60px\]{min-height:60px}.w-0\.5{width:.125rem}.w-10{width:2.5rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-8{width:2rem}.w-\[11px\]{width:11px}.w-\[26px\]{width:26px}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[34px\]{min-width:34px}.min-w-full{min-width:100%}.max-w-\[110px\]{max-width:110px}.max-w-\[180px\]{max-width:180px}.max-w-\[220px\]{max-width:220px}.max-w-\[280px\]{max-width:280px}.max-w-\[760px\]{max-width:760px}.max-w-\[90px\]{max-width:90px}.max-w-full{max-width:100%}.max-w-none{max-width:none}.flex-1{flex:1 1 0%}.flex-none{flex:none}.shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.gap-0{gap:0}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-l{border-left-width:1px}.border-l-2{border-left-width:2px}.border-l-\[3px\]{border-left-width:3px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-\[var\(--dsw-alias-border-l2\)\]{border-color:var(--dsw-alias-border-l2)}.border-\[var\(--dsw-alias-border-l3\)\]{border-color:var(--dsw-alias-border-l3)}.border-\[var\(--dsw-alias-state-error-primary\)\]{border-color:var(--dsw-alias-state-error-primary)}.border-transparent{border-color:transparent}.border-b-\[var\(--dsw-alias-brand-primary\)\]{border-bottom-color:var(--dsw-alias-brand-primary)}.border-l-\[var\(--dsw-alias-brand-primary\)\]{border-left-color:var(--dsw-alias-brand-primary)}.border-l-transparent{border-left-color:transparent}.border-t-\[var\(--dsw-alias-brand-primary\)\]{border-top-color:var(--dsw-alias-brand-primary)}.bg-\[var\(--dsw-alias-bg-layer-1\)\]{background-color:var(--dsw-alias-bg-layer-1)}.bg-\[var\(--dsw-alias-bg-layer-2\)\]{background-color:var(--dsw-alias-bg-layer-2)}.bg-\[var\(--dsw-alias-border-l2\)\]{background-color:var(--dsw-alias-border-l2)}.bg-\[var\(--dsw-alias-brand-primary\)\]{background-color:var(--dsw-alias-brand-primary)}.bg-\[var\(--dsw-alias-interactive-bg-hover\)\]{background-color:var(--dsw-alias-interactive-bg-hover)}.bg-\[var\(--dsw-specific-sidebar-fill\)\]{background-color:var(--dsw-specific-sidebar-fill)}.bg-transparent{background-color:transparent}.p-0{padding:0}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-0{padding-top:0;padding-bottom:0}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.pr-4{padding-right:1rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace}.text-\[0\.92em\]{font-size:.92em}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[9px\]{font-size:9px}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-5{line-height:1.25rem}.leading-relaxed{line-height:1.625}.tracking-wide{letter-spacing:.025em}.text-\[var\(--dsw-alias-brand-primary\)\]{color:var(--dsw-alias-brand-primary)}.text-\[var\(--dsw-alias-label-primary\)\]{color:var(--dsw-alias-label-primary)}.text-\[var\(--dsw-alias-label-secondary\)\]{color:var(--dsw-alias-label-secondary)}.text-\[var\(--dsw-alias-label-tertiary\)\]{color:var(--dsw-alias-label-tertiary)}.text-\[var\(--dsw-alias-state-business-primary\)\]{color:var(--dsw-alias-state-business-primary)}.text-\[var\(--dsw-alias-state-error-primary\)\]{color:var(--dsw-alias-state-error-primary)}.text-\[var\(--dsw-alias-state-success-primary\)\]{color:var(--dsw-alias-state-success-primary)}.text-\[var\(--dsw-alias-state-warn-primary\)\]{color:var(--dsw-alias-state-warn-primary)}.underline{text-decoration-line:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}@keyframes kaijia-spin{to{transform:rotate(1turn)}}.kaijia-code-scroll,.kaijia-diff-scroll,.kaijia-git-diff-content,.kaijia-git-list,.kaijia-image-preview,.kaijia-markdown-scroll,.kaijia-tree-scroll{scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,var(--dsw-alias-border-l2)) transparent;scrollbar-width:thin}#root{margin-right:var(--dsh-sidebar-width,0);transition:margin-right var(--ds-transition-duration-slow) var(--ds-ease-in-out)}body[data-dsh-sidebar-dragging] #root{transition:none}.kaijia-sidebar-root,[data-dsh-sidebar-root]{background:var(--dsw-specific-sidebar-fill)}.kaijia-sidebar-root{position:fixed;top:0;right:0;bottom:0;z-index:10;display:flex;flex-direction:column;border-left:1px solid var(--dsw-alias-border-l2)}.kaijia-sidebar-root.kaijia-sidebar-open{min-width:280px;max-width:640px}.kaijia-sidebar-root.kaijia-sidebar-collapsed{width:40px;min-width:40px;max-width:40px;border-left:none}.kaijia-sidebar-drag-handle{position:absolute;left:-4px;top:0;bottom:0;width:8px;cursor:col-resize;touch-action:none}.kaijia-sidebar-drag-handle:after{content:"";position:absolute;left:3px;top:0;bottom:0;width:2px;background:transparent;transition:background-color .12s ease}.kaijia-sidebar-drag-handle:hover:after,.kaijia-sidebar-root[data-dragging] .kaijia-sidebar-drag-handle:after{background:var(--dsw-alias-brand-primary);opacity:.5}.kaijia-sidebar-body{display:flex;flex:1;min-height:0;flex-direction:row;background:var(--dsw-specific-sidebar-fill)}@media (prefers-reduced-motion:reduce){#root{transition:none}.kaijia-chevron{transition:none;will-change:auto}}.hover\:bg-\[var\(--dsw-alias-interactive-bg-hover\)\]:hover{background-color:var(--dsw-alias-interactive-bg-hover)}.hover\:text-\[var\(--dsw-alias-label-primary\)\]:hover{color:var(--dsw-alias-label-primary)}
|