npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@open-wysiwyg-editor/solid

v1.0.2

Published

SolidJS directive for open-wysiwyg-editor: <div use:richText>. Accessible (WCAG 2.2 AA), RTL-first, CSP-safe.

Readme

@open-wysiwyg-editor/solid

npm version license

Live demo → · GitHub · npm

A SolidJS directive that turns any element into the Open WYSIWYG Editor: an accessible (WCAG 2.2 AA), RTL-first rich text editor that runs under a strict Content Security Policy. It works with Solid 1.6+ and SolidStart, and ships its own TypeScript types.

<div use:richText={{ content: html(), onUpdate: (e) => setHtml(e.getHTML()) }} />

Install

npm install @open-wysiwyg-editor/solid

This one package gives you the whole editor API (StarterKit, getUI, types…): it re-exports everything from open-wysiwyg-editor.

Usage

import { createSignal } from "solid-js";
import { richText } from "@open-wysiwyg-editor/solid";
import "@open-wysiwyg-editor/solid/style.css";

// Keep this line. TypeScript and Babel drop imports that look unused,
// and `use:richText` is only a reference to the function.
richText;

export default function App() {
  const [html, setHtml] = createSignal("<p>Hello <strong>world</strong></p>");

  return (
    <>
      <div
        use:richText={{
          content: html(),
          placeholder: "Write something…",
          onUpdate: (editor) => setHtml(editor.getHTML()),
        }}
      />
      <pre>{html()}</pre>
    </>
  );
}

The directive creates the editor when the element mounts and destroys it when its owner is disposed. The object you pass is read reactively, so signals used inside it (like html() above) are tracked.

In TypeScript, use:richText is typed for you: this package augments JSX.Directives in solid-js.

Two-way binding

content goes in, onUpdate sends the HTML back.

  • When the signal changes from outside (a reset button, a loaded record), the editor loads it.
  • When it changed because the editor itself reported it, nothing is reloaded, so the cursor stays where it is.

Options and language

Pass any editor option except element.

<div
  use:richText={{
    content: html(),
    language: "ar",
    dir: "rtl",
    contentLang: "ar",
    ariaLabel: "Article body",
    onUpdate: (e) => setHtml(e.getHTML()),
  }}
/>

Toolbar

<div
  use:richText={{
    content: html(),
    ui: { toolbar: ["bold", "italic", "|", "link", "bulletList", "orderedList"] },
    onUpdate: (e) => setHtml(e.getHTML()),
  }}
/>

Getting the editor

onCreate receives the editor instance.

import type { Editor } from "@open-wysiwyg-editor/solid";

let editor: Editor | undefined;

<div use:richText={{ onCreate: (e) => (editor = e) }} />
<button type="button" onClick={() => editor?.chain().focus().toggleBold().run()}>Bold</button>

Forms

The editor does not submit by itself. Keep the HTML in a hidden input so a normal form post (or a SolidStart action) receives it.

<form method="post">
  <div use:richText={{ content: html(), onUpdate: (e) => setHtml(e.getHTML()) }} />
  <input type="hidden" name="body" value={html()} />
  <button>Save</button>
</form>

Always sanitize or escape the HTML again on the server before you render it for other users.

Updates after mount

| Changes after mount | What happens | | --- | --- | | content | Loaded into the editor (unless it is the editor's own HTML) | | editable, placeholder, ariaLabel, ariaLabelledBy, ariaDescribedBy, dir, contentLang | Applied live | | Callbacks (onUpdate, onFocus…) | The latest one is always called | | Everything else (extensions, ui, language…) | Read once when the editor is created. Re-render it inside a keyed <Show> to recreate it |

Options

The directive takes the same options as createEditor() (without element). See the full list in the core docs. The editor API, commands and extensions are documented there too.

Styling

import "@open-wysiwyg-editor/solid/style.css"; // editor UI + content (also style.min.css)
import "@open-wysiwyg-editor/solid/content.css"; // only the content styles, to show saved HTML (also content.min.css)

Theme it with CSS variables; see Styling in the core docs.

SSR and SolidStart

Directives only run in the browser. On the server the element is rendered empty, and the editor starts when the page hydrates, so there is nothing to guard with isServer. Import the CSS in root.tsx or entry-client.tsx to avoid a flash of unstyled content.

Links

License

MIT © alhassan-ahmed