# 规则面板

[← 返回 README](../README.md) · [文档索引](./index.md)

编辑器里的**选择器本身就是按钮**（`.cm-peak-strip` 这样的选择器带悬停底色与指针光标），
点它在编辑器下方展开面板。面板是「这条规则现在是什么样的」摘要，不是一张空白表单。

它由三段组成：**顶部**选择器字段、**中间**已声明的属性、**底部**声明模板。

---

## 顶部：选择器字段

可重命名，铺满面板宽度。**关闭按钮 `×` 在字段内部**、靠右。

- 改名会**原地改写**样式表里的选择器，注释与缩进不受影响。
- 整个字段获得焦点时统一显示 `brand-primary` 聚焦环。

## 中间：已声明的属性

- 解析规则块里**真实存在**的声明并逐条列出。枚举型属性显示**中文名 + 中文值下拉**
  （`flex-direction: row` → 「主轴方向：水平排列」）；非枚举型（`gap`、`margin-top`、`min-width`…）
  显示属性名 + **值输入框**，可以直接改。
- **值写错了会当场说**：输入框在**失焦时**判断这个值是不是合法 CSS，不合法就描红并把提示换成
  一句说明（「这个值 notacolor 不是合法的 color 值」）。

  判据取**失焦时**的值，不是边打边判 —— 半输入的值按定义就是非法的
  （实测 `re`、`rgb(`、`calc(`、一个光秃秃的 `8` 都会被引擎判否），
  边打边判会让字段几乎每次按键都变红。**空值不算错**：清空一个字段不该变红。

- 下拉里可选「（删除此项）」移除该声明；**手工写的、不在选项里的值会被保留为当前选项**，
  不会被静默改掉。
- **未设置的属性不占行** —— 它们收在属性列表下方的「**＋ 添加属性…**」菜单里（只列当前还没设的）。
- 规则里一条声明都没有时，面板显示「这条规则还没有声明」。

### 「＋ 添加属性…」菜单

- 控件铺满面板宽度、文案靠左箭头靠右；按用途分成 **布局 / 弹性与对齐 / 网格 / 尺寸 / 间距 /
  文本 / 背景 / 描边与圆角 / 效果与动效 / 交互** 十组（**整组都被设完时该组自动隐藏**）。
- 这是一个长列表：**约 4000px 内容装在 260px 的滚动框里**，分组标题**黏顶**、
  黏住时显示一块不透明底色（否则标题会压在下面的行上看不清）。
- **所有下拉都是插件自绘的菜单**（DSH 原生菜单的底色 + 阴影 + 20px 圆角，与文件下拉同一套）：
  原生 `<select>` 的弹出层不受 CSS 控制（方角、跟随系统配色），所以这里不用它。
  菜单以 `position: fixed` 按触发按钮的位置定位，**不会被容器或面板自身的滚动裁掉**，
  视口下方不够高时自动向上展开。

### 属性行布局

**自适应多列**：最小列宽 200px，面板宽时一行能放两个属性（`上外边距 4px`、`最小宽度 0` 并排），
窄面板自动回到一列。

---

## 属性字典（112 条，三种形态）

| 形态 | 属性 | 界面 |
| --- | --- | --- |
| 枚举型 | `display`、`position`、`justify-content`… | 中文名 + **中文值下拉**，写入的是 CSS 值本身 |
| 长度 / 颜色 / 阴影 / 函数型 | `gap`、`margin-top`、`font-size`、`box-shadow`、`grid-template-columns`… | 中文名 + **自由输入框**，选中即以一个可用的种子值写入（如 `gap: 8px`）；占位文本就是取值提示（`0 / 8px / auto`） |
| 分量形态（简写属性） | `flex` → 放大 / 收缩 / 基准尺寸；`margin`、`padding`、`inset`、`border-radius` → 上 / 右 / 下 / 左；`gap` → 行间距 / 列间距；`aspect-ratio` → 宽 / 高 | 每个分量是 `名字 [值]` 的一对、**排在同一行**，分量名渲染为**浅底小标签**（`--dsw-alias-markdown-tag` 底 + `--dsw-alias-label-secondary` 文字 + 6px 圆角），与行标题、字段值在视觉上分开 |

**字典里没有的属性也不会丢**：仍然按原属性名给一个自由输入框。

### 分量形态的读写

- 读取时按 CSS 的简写展开规则拆分：`margin: 8px 12px` → 8px / 12px / 8px / 12px。
- 写回时**收敛成最短等价形式**：四个都是 8px 就写回 `margin: 8px` ——
  所以编辑一个角不会把你的样式表改得啰嗦。
- `border-radius` 的斜杠形式（`8px / 12px`）表达的是两个轴向，一个角一个框表达不了，
  因此**那种写法保留为自由输入框**。

---

## 底部：声明模板

容器 / 横向排列 / 居中 / 网格 / 文本 / 背景 / 描边 / 阴影 / 尺寸 / 间距 / 截断 / 滚动 / 吸顶 / 隐藏
—— 点一下按 2 空格缩进追加到块内（已有内容保留）。

---

## 写入语义

这两条是面板最容易被写错的地方，都踩过：

- **改属性是替换，不是叠加** —— 同一个属性反复改只会有一条，绝不堆成
  `display: flex; display: grid;`。
- 写入走的是「逐条声明」的**扫描**而不是正则替换：声明之间是换行分隔、**最后一条常常没有分号**，
  任何假设 `;` 分隔的做法都会失手并追加重复。
- 块在写入前会**规范化**：若某条声明缺了结尾的 `;`（老版本模板插入留下的、或手写的），
  自动补上再做编辑 —— 所以那种被粘连的老文件也能被**逐次修正**，不需要手工清理。

## 相关

- [编辑器](./editor.md) —— 面板上方的代码区
- [格式校验](./validation.md) —— 面板里改的值同样会被校验
- [控件 · 强调显示](./controls.md#强调显示三种看起来都像-0-的情况) —— 面板里那颗带命中数的胶囊
