111 lines
2.5 KiB
Markdown
111 lines
2.5 KiB
Markdown
# 4-7 [done] Tree Shell UI State Boundary v1
|
|
|
|
> 更新时间:2026-04-18
|
|
>
|
|
> 目的:明确哪些状态属于 projection,哪些状态只能留在 tree shell / renderer 本地。
|
|
|
|
## 1. 结论
|
|
|
|
树域必须严格区分:
|
|
|
|
- projection truth
|
|
- local UI state
|
|
|
|
否则 Rust projection、Leptos tree shell、Next 挂载切流会继续把状态缠回旧前端壳。
|
|
|
|
## 2. 属于 projection 的状态
|
|
|
|
这些状态必须来自上游 projection 或 command 结果,而不是由 UI 自行猜测:
|
|
|
|
- `nodeId`
|
|
- `parentNodeId`
|
|
- `projectionKind`
|
|
- `nodeType`
|
|
- `title`
|
|
- `depth`
|
|
- `position`
|
|
- `childCount`
|
|
- `expandable`
|
|
- `expandedByDefault`
|
|
- `capabilities`
|
|
- `resourceMeta`
|
|
- `iconHint`
|
|
|
|
说明:
|
|
|
|
- projection 只描述“结构真相”和“允许做什么”
|
|
- projection 不承载 hover、selected、dragging 等临时交互态
|
|
|
|
## 3. 只能留在 UI 本地的状态
|
|
|
|
这些状态只能存在于 tree shell / renderer 本地:
|
|
|
|
- `expanded`
|
|
- `selected`
|
|
- `hover`
|
|
- `focus`
|
|
- `dragging`
|
|
- `drop target`
|
|
- `context menu open`
|
|
- `keyboard navigation anchor`
|
|
|
|
说明:
|
|
|
|
- `expandedByDefault` 是 projection 建议值
|
|
- `expanded` 是本地会话态,不直接回写 projection
|
|
|
|
## 4. 边界规则
|
|
|
|
### 4.1 `expanded`
|
|
|
|
- 初始值可由 `expandedByDefault` 推导
|
|
- 运行期展开/折叠必须只保留在本地状态
|
|
- 不能把 `expanded` 反向写回 projection item
|
|
|
|
### 4.2 `selected`
|
|
|
|
- `selected` 属于当前用户当前会话的局部状态
|
|
- 不能作为 projection 的共享字段
|
|
|
|
### 4.3 `focus`
|
|
|
|
- `focus` 属于 keyboard / accessibility 层本地状态
|
|
- 不能参与结构真相
|
|
|
|
### 4.4 `dragging` / `drop target`
|
|
|
|
- `dragging` 与 `drop target` 是瞬时状态
|
|
- 只能存在于 DnD 状态机
|
|
- drop 成功后,真正持久化的是 `tree.subtree.move` 等命令结果
|
|
|
|
## 5. Rust 与前端共识
|
|
|
|
Rust 负责:
|
|
|
|
- 输出 projection
|
|
- 接收 command
|
|
- 返回 command result / resync snapshot
|
|
|
|
前端或 Leptos shell 负责:
|
|
|
|
- `expanded`
|
|
- `selected`
|
|
- `hover`
|
|
- `focus`
|
|
- `dragging`
|
|
- `drop target`
|
|
|
|
## 6. 对 `page_tree` / `file_tree` / picker 的影响
|
|
|
|
- `page_tree`、`file_tree`、picker 必须共用同一套本地状态边界
|
|
- picker 只是交互能力更窄,不是另一套状态模型
|
|
- `keyboard`、`selection`、`focus`、`dragging` 的命名与语义必须一致
|
|
|
|
## 7. 完成判定
|
|
|
|
当以下条件同时成立时,视为状态边界冻结完成:
|
|
|
|
- 文档明确列出 projection 与本地状态
|
|
- Rust 和前端都不再把 `expanded/selected/focus/dragging/drop target` 写进 projection
|
|
- 后续 Leptos shell 与 Next consumer 使用同一份边界说明
|