@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.
View Components
Astryx rich text — a Lexical-based rich text editor and read-only viewer, styled with Astryx design tokens.
tsx
import {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 experimental RichTextEditor that 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:
tsx
import {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.
bash
npm 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 on main (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:
  1. Remove "private": true and the "astryx": { "canaryOnly": true } marker from package.json.
  2. Add a changeset (pnpm changeset) selecting @astryxdesign/richtext so the release workflow versions and publishes it to the latest dist-tag.
  3. The stable (latest) release job (.github/workflows/release.yml) will then include richtext on the next release.