Skip to content

code-gio/svelty-editor

Repository files navigation

Svelty Editor

A Svelte 5 wrapper component for Editor.js -- built with runes, TypeScript, and lazy-loaded tools.

Features

  • Svelte 5 -- uses $props, $state, and $effect runes
  • TypeScript -- fully typed props, events, and exports
  • Bring your own tools -- install only the Editor.js plugins you need
  • Snippet support -- render custom UI around the editor with Svelte 5 snippets
  • Component API -- save(), setReadOnly(), registerTool(), and getManager() via bind:this
  • EditorManager -- access the underlying manager class directly for advanced use cases

Installation

npm install svelty-editor @editorjs/editorjs

Then install whichever Editor.js tools you want to use:

npm install @editorjs/header @editorjs/list @editorjs/paragraph

Available tool packages

Package Block type
@editorjs/header Headings (H1-H6)
@editorjs/list Ordered / unordered lists
@editorjs/paragraph Paragraphs
@editorjs/image Image blocks
@editorjs/embed Embedded content (YouTube, etc.)
@editorjs/delimiter Visual dividers
@editorjs/marker Inline text highlighting
@editorjs/quote Block quotes
@editorjs/table Tables
@editorjs/warning Warning callouts

You can also use any Editor.js plugin -- just pass its class in the tools prop.

Quick Start

<script lang="ts">
  import { SveltyEditor } from 'svelty-editor';
  import Header from '@editorjs/header';
  import List from '@editorjs/list';
  import Paragraph from '@editorjs/paragraph';

  let editor: ReturnType<typeof SveltyEditor>;

  async function handleSave() {
    const data = await editor.save();
    console.log(data);
  }
</script>

<SveltyEditor
  bind:this={editor}
  tools={{
    header: { class: Header },
    list: { class: List },
    paragraph: { class: Paragraph }
  }}
  placeholder="Start writing..."
/>

<button onclick={handleSave}>Save</button>

Props

SveltyEditor accepts all Editor.js configuration options (except holder, which is managed internally), plus:

Prop Type Description
tools Record<string, EditorTool> Map of tool names to their config (including the class).
data OutputData Initial editor content.
placeholder string Placeholder text for an empty editor.
autofocus boolean Focus the editor on mount.
readOnly boolean Start in read-only mode.
onChange (api, event) => void Called when editor content changes.
onReady () => void Called when the editor is ready.
class string CSS class applied to the outer wrapper.
children Snippet Svelte 5 snippet rendered above the editor.

Component Methods

Access these via bind:this:

<SveltyEditor bind:this={editor} ... />

save()

Returns the editor content as an OutputData object.

const data = await editor.save();

setReadOnly(readOnly: boolean)

Toggle read-only mode.

editor.setReadOnly(true);

registerTool(name, loader, config?)

Dynamically register a tool at runtime. The editor will reinitialize to pick it up.

await editor.registerTool(
  'checklist',
  () => import('@editorjs/checklist'),
  { inlineToolbar: true }
);

getManager()

Returns the underlying EditorManager instance for advanced use cases.

const manager = editor.getManager();
const editorjs = manager.getEditor(); // raw Editor.js instance

Tool Configuration

Each tool entry accepts an EditorTool object:

tools={{
  header: {
    class: Header,
    inlineToolbar: true,
    config: {
      levels: [1, 2, 3],
      defaultLevel: 2
    },
    shortcut: 'CMD+SHIFT+H'
  }
}}
Field Type Description
class Tool constructor The Editor.js tool class.
inlineToolbar boolean | string[] Enable inline toolbar for this block.
config Record<string, unknown> Tool-specific configuration.
shortcut string Keyboard shortcut.
tunes string[] Block tunes to apply.

Using Snippets

Render custom UI above the editor content using Svelte 5 snippets:

<SveltyEditor bind:this={editor} tools={...}>
  {#snippet children()}
    <div class="my-toolbar">
      <button onclick={() => editor.save()}>Save</button>
    </div>
  {/snippet}
</SveltyEditor>

Listening to Changes

<SveltyEditor
  tools={...}
  onChange={(api, event) => {
    console.log('Content changed:', event);
  }}
  onReady={() => {
    console.log('Editor is ready');
  }}
/>

Loading Initial Data

<SveltyEditor
  tools={...}
  data={{
    blocks: [
      { type: 'header', data: { text: 'Hello', level: 2 } },
      { type: 'paragraph', data: { text: 'Some content here.' } }
    ]
  }}
/>

Advanced: EditorManager

For more control, import EditorManager directly:

import { EditorManager } from 'svelty-editor';
import type { EditorOptions } from 'svelty-editor';

The manager exposes:

  • initialize() -- create the editor instance
  • save() -- get editor output
  • destroy() -- clean up
  • setReadOnly(boolean) -- toggle read-only
  • registerTool(name, loader, config?) -- add a tool dynamically
  • updateOptions(options) -- update editor options
  • getEditor() -- access the raw Editor.js instance
  • getInitializedTools() -- get loaded tool configs

TypeScript

All types are exported:

import type {
  EditorOptions,
  EditorTool,
  EditorChangeEvent,
  I18nConfig,
  ToolsLoadMap,
  SveltyEditorProps
} from 'svelty-editor';

Development

git clone https://github.com/code-gio/svelty-editor.git
cd svelty-editor
npm install
npm run dev

Visit http://localhost:5173 to see the demo page.

License

MIT

About

A Svelte 5 wrapper component for Editor.js -- built with runes, TypeScript, and lazy-loaded tools.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors