Add @openuidev/svelte-lang and extract @openuidev/lang-core#347
Merged
abhithesys merged 14 commits intothesysdev:mainfrom Mar 25, 2026
Merged
Add @openuidev/svelte-lang and extract @openuidev/lang-core#347abhithesys merged 14 commits intothesysdev:mainfrom
abhithesys merged 14 commits intothesysdev:mainfrom
Conversation
be5c41e to
70c5c87
Compare
Move parser, prompt generation, validation, and generic library types out of react-lang into a new @openuidev/lang-core package. The generic DefinedComponent<T, C = unknown> and Library<C> allow each framework adapter (React, Svelte, etc.) to narrow the component type parameter independently.
Replace local parser, prompt, and validation code with imports from @openuidev/lang-core. The library.ts becomes a thin wrapper that narrows the generic C parameter to React.FC<ComponentRenderProps>. Public API is unchanged — all existing examples build without modification.
Introduce @openuidev/svelte-lang — a Svelte 5 port of react-lang built on top of @openuidev/lang-core. Uses runes ($state, $derived, $effect, $props), snippets for renderNode, getContext/setContext for the OpenUI context, and <svelte:boundary> for error handling. Includes 30 passing tests.
A SvelteKit demo app showing @openuidev/svelte-lang in action with mock streaming, four components (Stack, Card, TextContent, Button), and action event handling. No API key required. Also add .svelte-kit to .gitignore.
70c5c87 to
c45b238
Compare
abhithesys
reviewed
Mar 23, 2026
Contributor
abhithesys
left a comment
There was a problem hiding this comment.
I ran the example, chat ui isn't working. At high level PR looks good. Can you update the example to use OpenAI api, while we are reviewing.
This covers: - New eslint.config.cjs and tsconfig.test.json for lang-core (matching react-lang pattern) - Parser test file moved from react-lang to lang-core - package.json updated with vitest dev dependency and formatting - src/index.ts export updated (ValidationError → ValidationErrorCode)
Contributor
|
@shipooor I m making minor changes required in this PR to unblock other Renderers. |
…and useSetDefaultValue
- RenderNode: auto-retry rendering when props change after an error
(captures reset fn from svelte:boundary and calls it on prop change,
with untrack to prevent infinite loops)
- getIsStreaming: return () => boolean getter instead of a plain boolean
snapshot so consumers get reactive updates
- useSetDefaultValue: read existing value from form state inside
instead of accepting a stale snapshot parameter, fixing reactivity
- README: add children rendering, parser errors, context reactivity
note, streaming parser docs, types, and React comparison table
abhithesys
approved these changes
Mar 25, 2026
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 #302
What
Adds @openuidev/svelte-lang — a Svelte 5 renderer for OpenUI Lang — and extracts the framework-agnostic core into @openuidev/lang-core, as suggested by @AbhinRustagi in this comment.
Architecture
Library<C>/DefinedComponent<T, C>system whereCis the framework component type.CtoReact.FCand re-exports everything. Public API is unchanged — this is a transparent refactor.CtoComponent<Props>and implements the Svelte 5 rendering layer.This structure makes adding future framework adapters (Vue, Solid, etc.) straightforward.
Changes
1.
@openuidev/lang-core(new package)createParser,createStreamingParser) moved from react-langgeneratePrompt) moved from react-langvalidate,parseRules,builtInValidators) moved from react-langLibrary<C>andDefinedComponent<T, C>types2.
@openuidev/react-lang(refactored, no API change)library.tsis now a thin wrapper that narrowsCtoReact.FC3.
@openuidev/svelte-lang(new package)Renderer.svelte— streaming renderer using$derivedfor reactive parsingRenderNode.svelte— recursive component renderer with<svelte:boundary>error handlinglibrary.ts—defineComponent/createLibrarywith Svelte 5 typescontext.svelte.ts— context API (getOpenUIContext,getTriggerAction, etc.)validation.svelte.ts— form validation with$state-backed reactive errors4.
examples/svelte-chat(new example)Svelte 5 features used
$props(),$state,$derived,$effectrunes{#snippet}/{@render}for recursive rendering (renderNodepassed as snippet prop)<svelte:boundary>for per-component error isolationgetContext/setContextwith Symbol keys and getter pattern for reactivityReact → Svelte API mapping
useOpenUI()getOpenUIContext()getContext, not hooksuseRenderNode()useTriggerAction()getTriggerAction()useIsStreaming()getIsStreaming()useState/useMemo$state/$deriveduseEffect$effectErrorBoundaryclass<svelte:boundary>Verification