Skip to content

[editor] Improve EditContext API - #1006

Merged
amadeus merged 10 commits into
beta-1.3from
amadeus/edit-context-improvement
Jul 20, 2026
Merged

[editor] Improve EditContext API#1006
amadeus merged 10 commits into
beta-1.3from
amadeus/edit-context-improvement

Conversation

@amadeus

@amadeus amadeus commented Jul 20, 2026

Copy link
Copy Markdown
Member

Overall this branch converts the 1:1 editor context API into a function factory context to make edit more developer friendly to implement.

TL;DR

So it was kinda buggin me that to use edit in react involved this architecture:

<EditProvider>
  <FileDiff edit />
</EditProvider>
<EditProvider>
  <File edit />
</EditProvider>

Basically this created a scenario where you had to create an edit context for every File/FileDiff. It also created situations where if you want to toggle edit on or off, and didn't want to pay the cost for an editor instance when it wasn't used, you'd essentially have to remount FileDiff (changing parent/child relationships in react is always an automatic re-mount).

Of course, part of the reason this is necessary is because we don't want to force people to import/use the Editor codebase if they aren't going to use it.

When I worked through adding support for CodeView, I took a slightly different approach -- you create an editFactory function that then CodeView would automatically use to create Editor instances on demand for items.

I feel like this is a much cleaner solution for the React API so I did a bit of an agentic port to rework EditContext to supply a factory function, and utilize that to automatically generate instances on demand.

I also changed the contentEditable prop to edit which feels more on brand for how we are making the feature.

So now, when building out a page that uses diffs, that might also selectively edit, you can just do

function createEditor(options) {
  return new Editor(options);
}

// Ideally you place this context high up in your app's layout,
// so anything that needs it can just get it
<EditContext createEditor={createEditor}>
  <File edit />
  <FileDiff edit />
  {/* ...etc */}
</EditContext>

The Longer Version:

  • Breaking: Replace <EditProvider editor={editor}> with <EditProvider createEditor={factory}>, export CreateEditor, EditProviderProps, and useCreateEditor, and remove useEditor.
  • Breaking: Rename contentEditable to edit on File, FileDiff, MultiFileDiff, and PatchDiff, and add per-surface editOptions; UnresolvedFile remains non-editable.
  • Create an independent editor for every surface and edit session without remounting the underlying DOM or imperative instance; exiting cleans the editor, re-entry starts fresh history, and factory or option replacements apply to the next session.
  • Move React CodeView editor creation into the nearest EditProvider, add CodeView-level editOptions, preserve per-item editors across virtualization, and keep vanilla CodeViewOptions.createEditor unchanged.
  • Route React CodeView changes through item-aware onItemEditChange and onItemEditComplete callbacks, with completion limited to changed sessions ending through edit-off, collapse, or removal.
  • Validate missing or invalid editor factories lazily when an editable surface or rendered CodeView item needs attachment, and clean newly created editors when attachment fails.
  • Remove the ignored controlledSelection and onSelectedLinesChange keys from React CodeView's options object; controlled prop-based and uncontrolled selection remain supported.
  • Prevent deferred Editor.onAttach callbacks from outliving their edit sessions, preserve correct delivery across virtualization, and make shared render scheduling idempotent.
  • Mount one shared editor factory provider at the docs app root, migrate all diffs and trees examples to edit and memoized editOptions, fix Live Editing state across layout changes, and refresh the Agent UI starter/generated artifacts.
  • Expand React lifecycle coverage for every editable surface, simultaneous siblings, factory and option replacement, StrictMode, virtualization, attachment failures, cleanup, selection, and CodeView edit completion.

@vercel

vercel Bot commented Jul 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pierre-docs-diffs Ready Ready Preview Jul 20, 2026 7:25pm
pierre-docs-diffshub Ready Ready Preview Jul 20, 2026 7:25pm
pierre-docs-trees Ready Ready Preview Jul 20, 2026 7:25pm
pierrejs-diff-demo Ready Ready Preview Jul 20, 2026 7:25pm

Request Review

@amadeus

amadeus commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: 50b0c904f7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

amadeus added 9 commits July 20, 2026 11:37
Keep EditProvider mounted while File, diff, and CodeView surfaces enter
and leave edit mode. Each session now receives its own editor from the
provider factory without remounting the rendered surface.

Expose edit and editOptions across editable React surfaces, route
CodeView items through the shared context, and migrate docs apps,
examples, generated snapshots, and lifecycle coverage.
An edit-enabled CodeView item could render read-only when no editor
factory was available.

Assert the factory when a mounted item needs a new editor, without
scanning the full item collection. Preserve active sessions when the
factory changes and cover vanilla, React, and virtualized paths.
React CodeView callers could pass selection controls through both props
and options, but the wrapper silently discarded the option values.

Remove the React-managed selection keys from the public options type and
cover controlled, uncontrolled, and provider-mounted selection flows.
End an edit session before the next render frame and the queued onAttach
callback could run against a cleaned editor, breaking imperative setup such
as marker installation.

Track pending notifications by attachment generation, cancel them during
cleanup, and only deliver once to a live session. Preserve recycle behavior
and persisted-state restoration across repeated teardown.
Edit a diff, then switch between unified and split layouts: Reset became
disabled even though the edited contents remained. An edit immediately
after a reset could also be ignored.

Remove the stale debounce window now that onChange is synchronous. Keep
layout changes within the current session, while Reset and surface switches
still remount from pristine input.
Keep files, diffs, items, and styles stable at module scope while
memoizing component options with useMemo. Correct public type imports
and make the snippets compile under strict TypeScript settings.

Clarify per-surface editor creation and CodeView completion semantics,
including the teardown paths that remain silent. Refresh demo comments
and callback wiring to match the current edit-session lifecycle.
Cover File and FileDiff session creation, option replacement, cleanup,
and instance preservation with the same lifecycle assertions. Keep
wrapper coverage focused on edit-option forwarding and verify sibling
callbacks stay isolated.

Exercise CodeView completion behavior for changed and unchanged
sessions across edit-off, collapse, removal, direct cleanup, and React
unmount.
Describe the stable onChange callback consistently in both Agent UI
starter states. Refresh the generated mock session data so its displayed
diff matches the source snapshots.
Comment thread packages/diffs/src/react/utils/useFileDiffInstance.ts Outdated
@amadeus
amadeus merged commit 6a0ecb5 into beta-1.3 Jul 20, 2026
8 checks passed
@amadeus
amadeus deleted the amadeus/edit-context-improvement branch July 20, 2026 19:35
amadeus added a commit that referenced this pull request Jul 21, 2026
* feat(diffs): Create editors per React edit session

Keep EditProvider mounted while File, diff, and CodeView surfaces enter
and leave edit mode. Each session now receives its own editor from the
provider factory without remounting the rendered surface.

Expose edit and editOptions across editable React surfaces, route
CodeView items through the shared context, and migrate docs apps,
examples, generated snapshots, and lifecycle coverage.

* fix(diffs): Validate CodeView editor factories on attachment

An edit-enabled CodeView item could render read-only when no editor
factory was available.

Assert the factory when a mounted item needs a new editor, without
scanning the full item collection. Preserve active sessions when the
factory changes and cover vanilla, React, and virtualized paths.

* fix(diffs): Keep React CodeView selection prop-driven

React CodeView callers could pass selection controls through both props
and options, but the wrapper silently discarded the option values.

Remove the React-managed selection keys from the public options type and
cover controlled, uncontrolled, and provider-mounted selection flows.

* bugfix(UniversalRenderingManager): improve idempotency, add some tests

* fix(diffs): Keep deferred onAttach within its edit session

End an edit session before the next render frame and the queued onAttach
callback could run against a cleaned editor, breaking imperative setup such
as marker installation.

Track pending notifications by attachment generation, cancel them during
cleanup, and only deliver once to a live session. Preserve recycle behavior
and persisted-state restoration across repeated teardown.

* fix(docs): Preserve Live Editing state across layout changes

Edit a diff, then switch between unified and split layouts: Reset became
disabled even though the edited contents remained. An edit immediately
after a reset could also be ignored.

Remove the stale debounce window now that onChange is synchronous. Keep
layout changes within the current session, while Reset and surface switches
still remount from pristine input.

* docs(diffs): Correct React examples and edit guidance

Keep files, diffs, items, and styles stable at module scope while
memoizing component options with useMemo. Correct public type imports
and make the snippets compile under strict TypeScript settings.

Clarify per-surface editor creation and CodeView completion semantics,
including the teardown paths that remain silent. Refresh demo comments
and callback wiring to match the current edit-session lifecycle.

* test(diffs): Strengthen React edit lifecycle coverage

Cover File and FileDiff session creation, option replacement, cleanup,
and instance preservation with the same lifecycle assertions. Keep
wrapper coverage focused on edit-option forwarding and verify sibling
callbacks stay isolated.

Exercise CodeView completion behavior for changed and unchanged
sessions across edit-off, collapse, removal, direct cleanup, and React
unmount.

* docs(diffs): Refresh Agent UI edit callback snapshots

Describe the stable onChange callback consistently in both Agent UI
starter states. Refresh the generated mock session data so its displayed
diff matches the source snapshots.

* lmao fixed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants