观察类记录(finding,不带 pm:queue)。在实施 #3303(PR #3397,删掉内置 textarea 分支的无生产者 fullscreen 别名)时确认。
#3303 正文里记过这条,但那单即将随 PR #3397 关闭,这条观察会被埋进已关闭的 issue 里;PM 当时的裁定是「不做,依赖方向反,需单独裁决」,那就需要一个自己的载体来承接这次裁决。单独开一条,不带 pm:queue,等 triage。
现象
同一个「全屏编辑长文本」的交互(展开按钮 + 全高对话框 + draft/commit 语义),当前有两份独立实现:
| 实现 |
位置 |
消费者 |
FullscreenTextarea |
packages/components/src/renderers/form/form.tsx:357(origin/main @ 4eeb932) |
表单渲染器的内置(未注册)textarea 分支 |
FullscreenFieldEditor |
packages/fields/src/widgets/FullscreenFieldEditor.tsx:95(160 行) |
TextAreaField.tsx:85、RichTextField.tsx:145 |
#3302(issue #3301)已经把 widget 侧原本的两份合并成了共享的 FullscreenFieldEditor,内置分支这一份没有跟进 —— 不是遗漏,是搬不过去(见下)。
为什么这不是一次简单搬运
依赖方向是反的,实测自 package.json:
packages/fields/package.json 依赖 "@object-ui/components": "workspace:*";
packages/components/package.json 的 dependencies / peerDependencies 里没有 @object-ui/fields。
即 fields → components。所以 components/src/renderers/form/form.tsx 不能 import FullscreenFieldEditor。AGENTS.md §3 的拓扑也是这么排的(Atoms 在下、Fields 在上)。
为什么今天不算 bug(观察类的理由)
两份实现目前行为一致,用户碰不到差异;#3272(PR #3392)刚把 FullscreenTextarea 的文案接进 i18n,两边都是活的、都被测试覆盖。它是漂移风险,不是现存缺陷 —— 但 #3301 那一单的教训正是「一个表单级开关产出两种行为、且没有任何东西报告这个漂移」,两份状态机长期并存就是同一形状的种子。
一个已经发生的具体例子:#3393(全屏对话框拿不到字段 label)只落在 FullscreenTextarea 这一份上;同类问题要不要在 FullscreenFieldEditor 上再修一遍,取决于这两份最终是否合并。
可能的方向(需裁决,本 issue 不预设结论)
- A. 把共享实现下沉到
packages/components,fields 的两个 widget 改为从下层 import。顺依赖方向,一份实现;代价是 components(定位「Pure UI, no business logic」)要接纳一个带 draft/commit 状态机的编辑器外壳,且要确认它不拖进 fields 侧的依赖。
- B. 维持两份,显式记为「两个渲染路径各自拥有」,并加一条对齐测试防漂移。成本最低,但把重复固化了。
- C. 让内置
textarea 分支干脆不再自带全屏实现(例如该分支本身就走注册 widget)。最彻底,但改动面远超本条观察,需要单独评估内置分支的存在理由。
倾向不在此下:这条取决于 packages/components 的职责边界怎么划,属于架构裁决,不是实现细节。
证据等级
静态证据:读 form.tsx / FullscreenFieldEditor.tsx / 两个 widget 的调用点,以及两个 package.json 的依赖字段。未做浏览器复现(两份实现当前行为一致,无可复现的用户可见差异 —— 这正是它属于观察类的原因)。
关联:#3301(PR #3302 合并了 widget 侧两份)、#3303(PR #3397)、#3393、#3272(PR #3392)。
观察类记录(
finding,不带pm:queue)。在实施 #3303(PR #3397,删掉内置 textarea 分支的无生产者fullscreen别名)时确认。#3303 正文里记过这条,但那单即将随 PR #3397 关闭,这条观察会被埋进已关闭的 issue 里;PM 当时的裁定是「不做,依赖方向反,需单独裁决」,那就需要一个自己的载体来承接这次裁决。单独开一条,不带
pm:queue,等 triage。现象
同一个「全屏编辑长文本」的交互(展开按钮 + 全高对话框 + draft/commit 语义),当前有两份独立实现:
FullscreenTextareapackages/components/src/renderers/form/form.tsx:357(origin/main@ 4eeb932)textarea分支FullscreenFieldEditorpackages/fields/src/widgets/FullscreenFieldEditor.tsx:95(160 行)TextAreaField.tsx:85、RichTextField.tsx:145#3302(issue #3301)已经把 widget 侧原本的两份合并成了共享的
FullscreenFieldEditor,内置分支这一份没有跟进 —— 不是遗漏,是搬不过去(见下)。为什么这不是一次简单搬运
依赖方向是反的,实测自
package.json:packages/fields/package.json依赖"@object-ui/components": "workspace:*";packages/components/package.json的 dependencies / peerDependencies 里没有@object-ui/fields。即
fields → components。所以components/src/renderers/form/form.tsx不能 importFullscreenFieldEditor。AGENTS.md §3 的拓扑也是这么排的(Atoms 在下、Fields 在上)。为什么今天不算 bug(观察类的理由)
两份实现目前行为一致,用户碰不到差异;#3272(PR #3392)刚把
FullscreenTextarea的文案接进 i18n,两边都是活的、都被测试覆盖。它是漂移风险,不是现存缺陷 —— 但 #3301 那一单的教训正是「一个表单级开关产出两种行为、且没有任何东西报告这个漂移」,两份状态机长期并存就是同一形状的种子。一个已经发生的具体例子:#3393(全屏对话框拿不到字段 label)只落在
FullscreenTextarea这一份上;同类问题要不要在FullscreenFieldEditor上再修一遍,取决于这两份最终是否合并。可能的方向(需裁决,本 issue 不预设结论)
packages/components,fields的两个 widget 改为从下层 import。顺依赖方向,一份实现;代价是components(定位「Pure UI, no business logic」)要接纳一个带 draft/commit 状态机的编辑器外壳,且要确认它不拖进fields侧的依赖。textarea分支干脆不再自带全屏实现(例如该分支本身就走注册 widget)。最彻底,但改动面远超本条观察,需要单独评估内置分支的存在理由。倾向不在此下:这条取决于
packages/components的职责边界怎么划,属于架构裁决,不是实现细节。证据等级
静态证据:读
form.tsx/FullscreenFieldEditor.tsx/ 两个 widget 的调用点,以及两个package.json的依赖字段。未做浏览器复现(两份实现当前行为一致,无可复现的用户可见差异 —— 这正是它属于观察类的原因)。关联:#3301(PR #3302 合并了 widget 侧两份)、#3303(PR #3397)、#3393、#3272(PR #3392)。