This repository was archived by the owner on Oct 12, 2026. It is now read-only.
Repository navigation
Add initial SSR support for LiveProvider previews - #1
Open
tujoworker wants to merge 6 commits into
Open
tujoworker wants to merge 6 commits into
tujoworker wants to merge 6 commits into
Conversation
…bs#418) Rebuilds the repo tooling and fixes four library bugs. We'll eventually release as `v5`. ## Library - `LivePreview` overloads use `React.JSX` instead of the global `JSX` namespace, which `@types/react@19` removed. This is the breaking change. - Adds an `exports` map. Published filenames are unchanged, so `main`/`module`/ `types` resolve as before; deep imports into `dist/` no longer resolve. - Build target `es6` → `es2022`. `engines.node` `>= 0.12.0` → `>=20.19.0`. - Forwards `Editor`'s `prism` prop, which was typed but never passed through. - Transpiles with sucrase `production`, dropping the `__self`/`__source` props and React 19's outdated-JSX-transform warning. - Adds `getDerivedStateFromError` to the internal error boundary. Same exports, same props, same `react >=18` peer range. ## Tooling - pnpm → npm workspaces, tsup → tsdown (publint + attw on every build), jest → vitest, eslint → oxlint, Prettier 3, Docusaurus 2 → 3. - Removes Storybook and the duplicate `packages/demo`. Stories are now a plain Vite app under `packages/react-live/stories`, smoke-tested in Chromium. - 93 tests across jsdom and Chromium; 93% statement coverage, reported not gated. - CI: checks, browser tests, and a React 18 job for the other end of the peer range. - Release: changesets v2 actions, npm trusted publishing over OIDC, approval gate.
…bleLabs#421) * `live` was `Record<string, unknown>`, so wrapped components saw `unknown` for every key; it now uses the context's own type. Narrowing, so: major. * Stories become `*.stories.tsx` and name their component, typing `args` as its props, so bad props fail `npm run typecheck`. * Unrelated: turn off thanks in changesets
# Releases ## react-live@5.0.0 ### Major Changes - [FormidableLabs#418](FormidableLabs#418) [`be53ccd`](FormidableLabs@be53ccd) - Support React 19 type definitions, add an `exports` map, drop `engines`, and raise the output target. `LivePreview`'s overloads referenced the global `JSX` namespace, which `@types/react@19` removed. Because those types are emitted into the published declarations, consumers on React 19 types failed to compile. They now use `React.JSX`, which resolves under both `@types/react@18` and `@types/react@19`. The package also gains an `exports` map with separate types for the ESM and CJS conditions. Filenames are unchanged from 4.1.x (`dist/index.js`, `dist/index.mjs`, `dist/index.d.ts`), so `main`, `module`, and `types` resolve exactly as before. Subpaths other than `./package.json` are no longer importable; only the package root was ever documented. Output is now built for `es2022` rather than `es6`, so the bundle may contain syntax such as optional chaining that previous releases transpiled away. The `engines` field is gone, along with the `node: ">= 0.12.0"` and `npm: ">= 2.0.0"` it declared. Both were years out of date, and neither constrained anything real: this is browser code, so the Node version that installs it has no bearing on whether it runs. npm will no longer print an engine warning against those bounds. None of this changes the public API -- same exports, same props, same `react >=18` peer range -- but the `exports` map and the raised output target are enough that a major release is the honest way to ship them. - [FormidableLabs#421](FormidableLabs#421) [`004b007`](FormidableLabs@004b007) - Type the `live` prop that `withLive` injects, instead of `Record<string, unknown>`. Wrapped components saw `unknown` for every key, so `live.element` could not be rendered and `live.error` could not be read without casting first. The prop now uses the same type the context is created with, which is the shape [the docs](https://github.com/FormidableLabs/react-live/blob/main/docs/api.md) have always described: `code`, `error`, `element`, `onError`, `onChange`. ```tsx const Panel = withLive(({ live }) => { const Result = live.element; // was `unknown`, now a component return Result ? <Result /> : <pre>{live.error}</pre>; }); ``` Types only, with no runtime change. It is a narrowing, so a wrapped component that reads a key outside that shape off `live` will now fail to compile. ### Patch Changes - [FormidableLabs#418](FormidableLabs#418) [`be53ccd`](FormidableLabs@be53ccd) - Forward the `Editor` `prism` prop to `prism-react-renderer`. It was typed but never passed through, so a custom Prism instance was silently ignored. - [FormidableLabs#418](FormidableLabs#418) [`be53ccd`](FormidableLabs@be53ccd) - Stop emitting React's `__self` and `__source` debug props from transpiled code. Sucrase adds these props to every element it compiles. They describe a source file, and there is no source file here -- the code comes from a live editor rather than from disk, so the filename sucrase emitted was always the empty string. React ignores both props, and React 19 additionally treats `__self` as the signature of an outdated JSX transform, logging "Your app (or one of its dependencies) is using an outdated JSX transform" to the console of every page rendering a `LiveProvider`. Transpiling with sucrase's `production` option drops both props, and with them the `_jsxFileName` constant that the transform pipeline used to splice out and re-add solely to keep `__source` resolvable. - [FormidableLabs#418](FormidableLabs#418) [`be53ccd`](FormidableLabs@be53ccd) - Add `getDerivedStateFromError` to the internal error boundary, so a runtime error in live code no longer logs a React warning about it. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
tujoworker
force-pushed
the
feat/ssr
branch
from
September 24, 2026 13:20
fa9e0c8 to
4ab62dc
Compare
langz
approved these changes
Sep 24, 2026
tujoworker
force-pushed
the
feat/ssr
branch
from
September 24, 2026 13:49
4ab62dc to
188edc8
Compare
…ormidableLabs#416) ### Description Fixes FormidableLabs#415. The standalone `Editor` lost DOM focus after the first keystroke, so only one character could be typed until the user clicked back in. `use-editable` keys its editing-setup layout effect on the element ref, which is still `null` during the first render. `LiveProvider` re-renders when its initial transpile resolves, so that effect settles before the user types; the standalone `Editor` does not re-render until the first edit, so the first edit is what makes the effect re-run. The effect's cleanup resets `contentEditable` (which blurs the element in Chrome) and its setup then calls `focus()` while the element is still non-editable, so focus is not restored. `Editor` now re-renders once after mount, so use-editable's setup settles before the editor can be edited. The branch is rebased on master, so the test uses the vitest setup from FormidableLabs#418: `packages/react-live/src/components/Editor/index.test.jsx`. #### Type of Change - [x] Bug fix (non-breaking change which fixes an issue) ### How Has This Been Tested? Added a regression test in `packages/react-live/src/components/Editor/index.test.jsx`. It mounts the standalone `Editor`, drives an edit through use-editable the same way the browser does (DOM mutation plus keydown/keyup), and asserts the editing surface is not torn down and rebuilt. Without the fix it fails: `contentEditable` is written twice (`undefined`, then `"plaintext-only"`), which is the teardown/rebuild that resets the surface and drops focus. With the fix no writes occur and the edit is applied. Running the same scenario against `<LiveProvider>` + `<LiveEditor>` never writes `contentEditable`, matching the report that the provider path was unaffected. The test takes `act` from `@testing-library/react` rather than `react`, because `React.act` only exists from 18.3.0 and the `React 18.0.0` job fails with `act is not a function` without it. The library re-exports `act` for whichever React it is testing against, and the other tests in this package already import it from there. jsdom has no contentEditable editing or focus model, so the browser-level focus loss itself cannot be reproduced in this suite; the regression test asserts the cause instead. I did not run a real-browser test. Validation, all run locally on the rebased branch against the lockfile React 19.3.0 and against React 18.0.0 (pinned exactly the way the `react-compat` job does): - `npm run check` under React 19.3.0 - lint, format, typecheck, and tests passed (8 files, 58 tests). - `npm run check` under React 18.0.0 - same result, and the test fails with `act is not a function` before the import change. - `npm run build` - library and docs site build passed under both. ### Checklist: - [x] I have included a changeset if this change will require a version change to one of the packages. - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have run all builds, tests, and linting and all checks pass - [x] I have added tests that prove my fix is effective or that my feature works - [x] My changes generate no new warnings
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to master, this PR will be updated. # Releases ## react-live@5.0.1 ### Patch Changes - [FormidableLabs#416](FormidableLabs#416) [`b8bf7a0`](FormidableLabs@b8bf7a0) - Fix the standalone `Editor` losing focus after the first keystroke. `use-editable` rebuilt its editing surface on the first edit's re-render, which reset `contentEditable` and dropped focus; `Editor` now settles that surface before it can be edited. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Summary
Adds server-side rendering (SSR) support for
LiveProvider, allowing previews to render during the initial server render pass instead of being empty until client-side hydration.Changes
LiveProvider.tsx: Refactored state initialization so that whenuseStateruns (including on the server), it synchronously transpiles the providedcodeand produces anelement— enablingLivePreviewto render meaningful content inrenderToString/renderToStaticMarkup.transpile/index.ts: Minor adjustment to support the SSR transpilation path.LiveProvider.ssr.test.js: New test suite covering inline previews,noInlinepreviews, synchronoustransformCode, and the asynctransformCodedeferred case.api.md,usage.md): Updated to document SSR behavior and usage.Behavior
noInlinewithrender()transformCodetransformCode