Uh oh!
There was an error while loading. Please reload this page.
fix(fields): 注册路径的全屏长文本编辑器认 disabled(#3402) - #3403
Merged
yinlianghui merged 2 commits intoAug 5, 2026
Merged
Conversation
…ath (#3402) `disabled` reached the inline control of `TextAreaField` / `RichTextField` and nothing else. `showFullscreenButton` did not consult it, neither call site forwarded it, and `FullscreenFieldEditor` did not declare the prop at all — so a disabled long-text or rich-text field was greyed out inline while its expand button stayed live, its dialog accepted any edit, and "Done" wrote that edit back through `onCommit`. The issue carried static evidence only, so the premise was reproduced with a dynamic probe first: toggle `disabled=false`, dialog opened, dialog input `disabled=false`, `onChange` called with "EDITED WHILE DISABLED" — on both widgets, and again with `disabled` flipped true under an already-open dialog. `FullscreenFieldEditor` now declares `disabled`, shaped like the built-in path's `locked` gate (#3400 / PR #3401): the toggle stays but is disabled and refuses to open, the dialog's editor is disabled via a new third `children` argument, and "Done" is disabled and gated before `onCommit`. The dialog holds on its own rather than trusting the button, because `disabled` also carries the form's `isSubmitting` and can flip true while the dialog is open. Cancel and Esc stay live so a submit in flight cannot trap the user in a modal. `readonly` is untouched: both widgets early-return a read-only display before the affordance is computed, which is why readonly was never part of this defect, and no `readonly` prop is added here that no host would produce. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
…ed helper Comment-only. Two JSDoc blocks had accreted on `openThenDisable`; they say one thing, so they are one block. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
yinlianghui
marked this pull request as ready for review
August 5, 2026 19:13
Uh oh!
There was an error while loading. Please reload this page.
yinlianghui
deleted the
claude/issue-3402-registered-fullscreen-disabled
branch
August 5, 2026 19:13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#3402
前提先坐实(issue 自标 static-only)
issue 只有静态证据,所以先写动态探针复现,再动手。探针断言的是
origin/main上的缺陷行为,跑出来是绿的 —— 前提成立:最后一行就是缺陷本身:禁用字段的值被改掉了。内联控件正确地灰着 —— 这正是它难被发现的原因,绕过它的按钮就贴在它上面。修完再跑同一个探针,3/3 全红(方向:Red,与预期一致),探针随即删除,由下面的 pin 测试取代。
改了什么
disabled此前只落到内联控件:showFullscreenButton不看它,两个调用点不传它,FullscreenFieldEditor压根没声明这个 prop。FullscreenFieldEditor现在声明disabled,形制对齐内置分支的locked闸门(#3400 / PR #3401),四条各司其职:disabled——disabled是「不可交互、灰掉」,不是readonly的「平铺展示」(后者由两个 widget 的只读提前返回负责,连按钮都不渲染);openFullscreen自己也拦 —— 属性和pointer-events都可能在重构里丢掉;disabled不只是静态标志,表单渲染器把isSubmitting也 OR 了进来,它可能在对话框已经打开时翻真,那一刻按钮已经不是闸门了。所以编辑器经children的第三个参数收到disabled,"Done" 也disabled;onCommit前置 gate —— 值离开该组件进入宿主状态的唯一出口,没有任何原生机制守它(它是另一个控件上读 React state 的 click handler)。Cancel / Esc 任何状态下都保持可用 —— 否则提交进行中会把用户关死在模态框里。
两个 widget 各把
disabled解析一次交给两个编辑面(RichTextField里与formatLabel/hint/placeholder完全同形,原因也相同)。⛔ 按裁定未碰:
form.tsx(内置分支 #3401 已修)、两个 widget 的 readonly 提前返回、ObjectForm/stripRegisteredFieldProps。没有加
readonlyprop:两个宿主都在算出展开按钮之前就提前返回只读展示,该组件在 readonly 下根本不会被渲染,加了就是「声明了但没有生产者」—— 本包一直在删的形状(#3232/#3233)。将来若有宿主要在只读下渲染编辑器,prop 与生产者必须一起加。逐条 limb 反向验证(先定方向,再跑)
四组实验,每组的预期方向都在跑之前写死,四组全部命中:
commitFullscreen的if (!disabled)(保留 "Done" 的disabled属性)disabled属性(保留 handler gate)locks the dialog controls×2 红,refuses the write-back×2 绿onChange被调用,值为EDITED WHILE SUBMITTINGdisabled属性(保留openFullscreengate)keeps the expand button and disables it×2 红,does not open the dialog…×2 绿limb A 是个如实要说明的结果:那条 handler gate 单独拆掉时,任何 DOM 驱动的测试都照不出来 —— 只要按钮还带着
disabled,点击就被 React 过滤掉了。它不是「白写的」:limb B/C 证明属性一旦丢失,它就是挡在点击和写回之间的唯一一道。这也直接改了测试的写法:最初「锁住控件 + 拒绝写回」是同一个 test,limb B 暴露出写回断言在属性断言失败时根本执行不到 —— 也就是说它只能在「原生属性已经在干活」的世界里运行,那等于没 pin。现已拆成两个独立 test。测试
新增两个文件(每个 widget 一组,共 21 个 case):
disabled按钮禁 / 点了也不开框 / 内联仍禁 / 不写回 / 提交中翻真时对话框自锁 / 仍可 Cancel 退出 / 正常字段全屏编辑与提交不回归 / readonly 提前返回不回归 / 未开mobile_fullscreen时(禁用与否)都不出按钮。按规则消费半径而非改动包来扫 fixture:
FullscreenFieldEditor只有这两个宿主(未从包入口导出,children增加第三个参数是包内改动),但两个 widget 被 form 渲染器、ObjectForm、ActionParamDialog、SDUI 注册适配器消费,故一并跑了packages/fields+plugin-form的 mobileFullscreen +components的 form 全屏套件 +types的 metadata 测试 +ActionParamDialog:vitest list确认两个新文件确实落在过滤范围内(防「路径过滤被吞」假绿):type-check绿(@object-ui/fields,10 tasks successful);lint0 error;check-control-bytesOK,改动文件另做了越过该 gate 盲区的自查(grep -naP,零命中)。Changeset:
@object-ui/fieldspatch。🤖 Generated with Claude Code
https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
Generated by Claude Code