@astryxdesign/richtext
Astryx rich text — a Lexical-based rich text editor and viewer. Published to npm only under the @canary dist-tag for early testing; never released as a stable (latest) version.Astryx rich text — a Lexical-based rich text editor and read-only viewer, styled
with Astryx design tokens.
tsximport {RichTextEditor, RichTextView} from '@astryxdesign/richtext';<RichTextEditor label="Notes" onChange={setState} />;<RichTextView value={serializedState} />;
The editor is deliberately minimal and extensible: pass
nodes and plugins to
layer richer behaviour (toolbars, mentions, hover cards) on top without forking.
RichTextEditorToolbar is a composable formatting toolbar that drops into the
editor's plugins slot, and markdownToEditorStateJSON /
editorStateJSONToMarkdown convert Markdown to/from serialized editor state
headlessly (no mounted editor required). It consumes @astryxdesign/core theme
tokens directly (StyleX build mirrors @astryxdesign/lab / @astryxdesign/charts).Built on Lexical
RichText is built on Lexical and does not hide it:
nodes and transformers take Lexical types, plugins takes Lexical React
plugins, and onChange(editorState, editor) and the editor ref's
getEditorState() report Lexical types, so you extend the editor with Lexical
directly. The value you store is serialized Lexical editor state;
markdownToEditorStateJSON and editorStateJSONToMarkdown convert it to and
from Markdown.RichText supports one Lexical minor at a time, named by its
lexical and
@lexical/* peer ranges. Those are optional peer dependencies, so your
package manager does not add them: install them at that minor alongside
richtext. See the RFC:
facebook/astryx#3899.It ships to npm only under the
@canary dist-tag — there is never a stable
(latest) release yet.Note: this package is the successor to the experimentalRichTextEditorthat used to live in@astryxdesign/lab; that code has moved here so it can be canaried independently by an adopting application without a fresh package rollout.
Status
Under active development. The editor, view, composable toolbar, and Markdown
serializers are in place; API and visuals are still being refined. The goal is
graduation to
@astryxdesign/core after the design/API stabilizes.Usage
Inside the monorepo (storybook/sandbox), imports resolve via pnpm workspaces:
tsximport {RichTextEditor, RichTextView} from '@astryxdesign/richtext';import '@astryxdesign/core/astryx.css';import '@astryxdesign/richtext/richtext.css';
Interactive examples live in the storybook app under Lab/RichTextEditor
(
apps/storybook/stories/RichTextEditor.stories.tsx).Trying richtext in your own project (canary)
@astryxdesign/richtext is published only under the @canary dist-tag, so
you must request that tag explicitly. There is no latest version to install.bashnpm install @astryxdesign/richtext@canary @astryxdesign/core@canary
Then install every
lexical and @lexical/* package listed in richtext's
peerDependencies, at the range shown there (npm view
@astryxdesign/richtext@canary peerDependencies prints them).Canary builds track the latest commit onmain(0.x.y-canary.<sha>). They can break between any two versions — pin an exact version if you need stability.
Why no stable release?
package.json keeps "private": true plus an "astryx": { "canaryOnly": true }
marker. The release workflow's stable (latest) job skips both private and
canaryOnly packages, while the canary job strips private in its ephemeral CI
checkout only (never in git) to publish the @canary tag. The committed
private: true is npm's hard guarantee that no stable publish can ever happen —
do not remove it.Publishing publicly (when the editor/view are ready)
When maintainers are ready to promote richtext to a stable public release:
- Remove
"private": trueand the"astryx": { "canaryOnly": true }marker frompackage.json. - Add a changeset (
pnpm changeset) selecting@astryxdesign/richtextso the release workflow versions and publishes it to thelatestdist-tag. - The stable (
latest) release job (.github/workflows/release.yml) will then include richtext on the next release.