Skip to content

feat: Add onChange callback with content string emission - #534

Open
handreyrc wants to merge 4 commits into
open-workflow-specification:feature/node-editingfrom
handreyrc:onChange-callback
Open

handreyrc wants to merge 4 commits into
open-workflow-specification:feature/node-editingfrom
handreyrc:onChange-callback

Conversation

@handreyrc

Copy link
Copy Markdown
Contributor

Closes #299

This PR adds an onChange callback to the diagram editor ref API and fixes validation errors going stale after undo/redo, applying the following approach:

  • A. Add setOnChangeCallback to DiagramEditorRef: Lets the host register (or clear with null/undefined) a function that receives the latest serialized content after every change made inside the editor (side-panel edits, undo, redo). It is never called for content arriving through the content prop or setContent(), so calling setContent() from inside the callback is safe.
  • B. Isolate host callbacks from the editor: Host-provided functions (onContentChange and the new on-change callback) run through invokeSafely, so an exception can no longer break the editor. The error is rethrown asynchronously so the host's global error handling still sees it. A serialization failure is ignored and nothing is reported.
  • C. Derive validation errors from the model: Validation errors are now computed from the model currently shown instead of being stored in separate state. Parse errors are only used while there is no model (unparseable content).

How it works

The callback runs only when the origin of the change is the editor itself.

What changed the workflow Callback called?
The user edits a task in the side panel Yes
undo() / redo() (button, shortcut or API) Yes
setContent() called by the host No
The content prop is updated by the host No
Initial load No

Because external changes never trigger the callback, a host can safely forward the received content somewhere and write it back without creating a loop.

Changes

  • Added setOnChangeCallback to DiagramEditorRef in diagram-editor/DiagramEditor.tsx, with documentation for it and for setContent(). Also tightened a few doc comments and added explicit React.JSX.Element return types.
  • Added lib/invokeSafely.ts: runs a host function and rethrows any error via queueMicrotask.
  • Updated store/DiagramEditorContextProvider.tsx:
    • Stores the callback in a ref, exposed through useImperativeHandle.
    • Reports changes to both onContentChange and the on-change callback via invokeSafely, and skips reporting on serialization failure.
    • Replaced the errors state with parseErrors plus a memoized validationErrors derived from model.
  • Extracted the toolbar layout from UndoRedo.stories.tsx into the shared stories/features/shared/EditorToolbarLayout.tsx.
  • Added the OnChangeCallback.stories.tsx story.
  • Added tests: invokeSafely.test.ts, DiagramEditorContextProvider.onChange.test.tsx, additional cases in DiagramEditorContextProvider.test.tsx, and an update to DiagramEditor.test.tsx.

How to test

  • Use the story FEATURES/OnChange Callback to test. Refer to the Docs section for further information on how to set a callback and consume it externally.

@changeset-bot

changeset-bot Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a57ce71

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@openworkflowspec/diagram-editor Minor
@openworkflowspec/core Minor
@openworkflowspec/i18n Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify

netlify Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for openworkflow-editor ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit a57ce71
🔍 Latest deploy log https://app.netlify.com/projects/openworkflow-editor/deploys/6af71d2a38037d7fd9f6a195
😎 Deploy Preview https://deploy-preview-534--openworkflow-editor.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Batched host loads can incorrectly emit onChange for externally supplied content, and editors without change callbacks unnecessarily serialize the entire workflow on every edit, undo, and redo.

2 open issues
What changed in this PR

Adds a ref-based callback that delivers serialized workflow content to host applications after editor changes, supporting the integration described in #299. It also makes validation errors follow the current model through undo and redo.

Changes:

  • Adds setOnChangeCallback and isolates host callback exceptions.
  • Derives validation errors from the displayed model.
  • Adds callback documentation, a demonstration story, shared toolbar code, and regression tests.
File Description
packages/​open-workflow-diagram-editor/​tests/​store/​DiagramEditorContextProvider.test.tsx Tests validation and form errors across history changes.
packages/​open-workflow-diagram-editor/​tests/​store/​DiagramEditorContextProvider.onChange.test.tsx Tests callback payloads, registration, origins, and error isolation.
packages/​open-workflow-diagram-editor/​tests/​lib/​invokeSafely.test.ts Tests asynchronous rethrow behavior.
packages/​open-workflow-diagram-editor/​tests/​diagram-editor/​DiagramEditor.test.tsx Checks the expanded ref API.
packages/​open-workflow-diagram-editor/​stories/​features/​UndoRedo.stories.tsx Reuses the shared toolbar and updates API examples.
packages/​open-workflow-diagram-editor/​stories/​features/​shared/​EditorToolbarLayout.tsx Extracts reusable toolbar and content dialogs.
packages/​open-workflow-diagram-editor/​stories/​features/​OnChangeCallback.stories.tsx Demonstrates and documents callback integration.
packages/​open-workflow-diagram-editor/​src/​store/​DiagramEditorContextProvider.tsx Implements callback delivery and model-derived validation.
packages/​open-workflow-diagram-editor/​src/​lib/​invokeSafely.ts Isolates synchronous host callback exceptions.
packages/​open-workflow-diagram-editor/​src/​diagram-editor/​DiagramEditor.tsx Declares and documents the callback API.
.changeset/​fix-errors-after-undo-redo.md Records the validation fix as a patch release.
.changeset/​add-onChange-callback.md Records the callback API as a minor release.

Review effort: Balanced

@lornakelly

Copy link
Copy Markdown
Collaborator

@handreyrc Still reviewing but a small thing I noticed, in the undo story - the undo is not enabled if you make an edit in sidepanel, only works if you first use SetContent in toolbar, after that it recognises changes in sidepanel as well

@handreyrc

Copy link
Copy Markdown
Contributor Author

@handreyrc Still reviewing but a small thing I noticed, in the undo story - the undo is not enabled if you make an edit in sidepanel, only works if you first use SetContent in toolbar, after that it recognises changes in sidepanel as well

@lornakelly,

I ported and refactored the code to make it simpler once this code is reference for the editor integration.
I also updated the Docs for the Undo Redo story to reflect those changes.
The issue should be fixed!

@lornakelly

Copy link
Copy Markdown
Collaborator

Thanks @handreyrc Looks good but worth rebasing with feature branch and test how it works when you remove an optional field clicking x and make sure its all good

Signed-off-by: Handrey Cunha <handrey.cunha@gmail.com>
Signed-off-by: Handrey Cunha <handrey.cunha@gmail.com>
Signed-off-by: Handrey Cunha <handrey.cunha@gmail.com>
@handreyrc

Copy link
Copy Markdown
Contributor Author

Thanks @handreyrc Looks good but worth rebasing with feature branch and test how it works when you remove an optional field clicking x and make sure its all good

@lornakelly,

It is rebased!

What really matters are the model changes. If we have a model change we have a new snapshot in the history (undo/redo) and the onChange callback is executed.

@lornakelly lornakelly left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@fantonangeli fantonangeli left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM, I only have a question about the panel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@handreyrc Instead of implementing a custom OutputPanel, I would evaluate the Action feature of StoryBook which is built-in and integrated in SB panel already.
https://storybook.js.org/docs/essentials/actions
Wdyt?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fantonangeli Ok, Done!
Check the tab "Actions" in the addons panel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot @handreyrc

…ons tab in the addons panel

Signed-off-by: Handrey Cunha <handrey.cunha@gmail.com>

@fantonangeli fantonangeli left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@handreyrc

Copy link
Copy Markdown
Contributor Author

@lornakelly,

This PR is good enough to be merged!

Thanks

This branch has not been deployed

No deployments
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.

4 participants