feat(fields): RichTextField honors mobile_fullscreen with a fullscreen editing dialog (#3301) - #3302
Merged
Conversation
…een editing dialog (#3301) `ObjectFormSchema.mobile.fullscreenLongText` is documented as "textarea/ rich-text get an expand button", and `ObjectForm` has always stamped `mobile_fullscreen` onto `field:markdown` / `field:html` fields to deliver it. Both types resolve to `RichTextField`, and that widget never read the flag — a producer with no consumer. Turning the setting on gave a phone user an expand affordance on textareas and nothing at all on markdown or HTML fields, with nothing reporting that half the feature was inert. `RichTextField` now reads `field.mobile_fullscreen` — the single metadata carrier (#3233), the same single read `TextAreaField` performs — and renders the same affordance and full-height dialog. No prop spelling, no `??` fallback chain: a misspelled flag stays inert in both widgets rather than being quietly caught by a tolerant consumer. The affordance, the dialog and the draft/commit semantics move into a shared `FullscreenFieldEditor` that both widgets render; only the EDITOR is per-widget. One form-level setting should produce one behaviour, and a second hand-written copy of that state machine is this same defect with an extra step. The rich-text dialog hosts the widget's real editing surface rather than a bare textarea, so both positions upgrade together. Removes a dead type from the producer: `'string-multiline'` was stamped here and `grep -rn` finds it exactly once across both this repo and `objectstack` — that line itself. No producer, no registry key, no reader. The four remaining stamped types each have a real reader. Coverage: the integration chain (real `ObjectForm` → real form renderer → real `RichTextField`, no mocks) now covers rich text, including a fullscreen edit committing back into react-hook-form state and a mixed form lighting up both widget families from the one setting. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NVPjPzmmAJ2Ngtvgg5MSRa
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
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 free
to 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.
Closes #3301
按 2026-08-03 的维护者裁决走 A 路:兑现承诺,不收窄。
mobile.fullscreenLongText对field:markdown/field:html从「盖了没人读」变成真的能用。缺陷复核(premise check,全部确证)
RichTextField不读 flaggrep -n "fullscreen|mobile_" packages/fields/src/widgets/RichTextField.tsx零命中field:markdown/field:html都落到RichTextFieldpackages/fields/src/index.tsx:2349,2353,两处createFieldRenderer(RichTextField))string-multiline无人产出objectstack兄弟仓(排除node_modules/dist/.git)全类型 grep,全仓合计 1 处命中,就是判定式那一行本身改了什么
读取(唯一载体):
RichTextField读field.mobile_fullscreen,只此一处。没有新 prop、没有第二载体、没有??兜底链——与TextAreaField逐字同构。拼错的 flag 在两个 widget 里都保持 inert,不会被某一侧的宽容消费悄悄接住(AGENTS #0.1)。复用决策:抽出共享件。展开按钮 + 对话框 + draft/commit 状态机进入新的
packages/fields/src/widgets/FullscreenFieldEditor.tsx,两个 widget 共用;per-widget 的只有编辑器本身(children注入)。判断依据:
fullscreenLongText是一个表单级设置,用户打开它期待一种行为。手写第二份状态机就是本 issue 的缺陷再来一遍(只是多绕一步)——它会漂移,而且没有任何东西会报告漂移。抽出来之后这一点是机械可验的:见下方 sabotage C,改坏共享件的 commit 一处,TextAreaField与RichTextField的测试同时变红。对话框里是真编辑器:
RichTextEditorSurface内联与全屏两处渲染同一份(同 format 指示、同编辑器),fullHeight是唯一差异。若对话框内联一个裸Textarea,两个界面当场就已经不一致(少了 format 指示),且这个 widget 每长出一个 affordance 就再不一致一次。string-multiline死分支删除:证据见上表,ObjectForm判定式里附了注释说明依据。剩下 4 个 type 每个都有真实 reader。无既有测试引用该字串,故无测试需要调整。行为一致性:draft 在打开时从已提交值播种、输入期间保持本地(RHF 不会因用户可能取消的编辑被标脏)、"Done" 提交一次、"Cancel" 丢弃。testid 沿用既有约定但按 widget 命名空间(
richtext-fullscreen-toggle/-dialog/-input/-save)——一个表单里可以同时有 textarea 和 markdown 字段,共用一个 id 会让测试说不清自己找到的是谁。焦点管理 /Esc/ overlay 沿用仓内Dialog(Radix),未另行作答。验证证据
Sabotage(每条:改坏见红、还原见绿)
RichTextField停止读 flag(还原到 #3301 之前)Textarea(降级副本)puts the REAL editor in the dialog(expected [ span ] to have a length of 2 but got 1)RichTextField+TextAreaField的 commit 测试 + 集成链的表单状态测试 → 证明复用是真共享discards the draft on CancelfullscreenLongText开关(无条件盖章)TextAreaField与RichTextField两条负向控制测试
新增/扩展:
packages/fields/src/widgets/__tests__/RichTextField.mobileFullscreen.test.tsx(新,8 例)— 含 readonly 不出 affordance、Cancel 丢弃且重开从已提交值播种、无第二载体。packages/plugin-form/src/__tests__/ObjectForm.mobileFullscreen.test.tsx(扩展,+4 例)— 镜像 fix(plugin-form,types): carrymobile_fullscreenon the field metadata, where widgets actually read (#3245) #3300 范式,真ObjectForm→ 真渲染器 → 真RichTextField,除 dataSource 外无 mock:自动生成的field:markdown+field:html双双出现 affordance;未开启则不出现;对话框内编辑 → 关闭 → 通过内联控件观察到 react-hook-form 状态已更新;textarea + markdown 混合表单由同一个设置同时点亮两族 widget。TextAreaField既有测试未做任何修改,全绿(回归不变)。FullscreenFieldEditor.tsx零 lint warning。changeset:@object-ui/fields+@object-ui/plugin-formminor(pnpm changeset:check双绿)。需要维护者裁决的一处(未擅自修改)
packages/types/src/field-types.ts中mobile_fullscreen的 JSDoc 现在过时了:本 PR 之后消费者是两个。
packages/types在本单的范围栅栏外(指示要求「停下回报而不是直接改」),所以这行注释原样保留,请裁决是否另开一个 2 行 docs PR 补上RichTextField。留着不改的代价正是本 issue 那类 declared-vs-actual 漂移,只不过方向反了:声明比实现窄。(
packages/types/src/objectql.ts:1265那句fullscreenLongText: true, // textarea/rich-text get an "expand" button不必改——本 PR 之后它第一次成为事实。)未做
apps/console、packages/components、packages/types、packages/spec、content/docs/releases/。TextAreaField.tsxas any消费侧洞:未处理,issue 自陈「不必然与上面同单处理」,且彻底修复需先决定 widget 如何收窄FieldMetadata联合。