# @holochain-syn/text-editor

> Collaborative text editing grammar and editor element for syn

Latest version **0.701.1** (published 2026-10-16) · CAL-1.0 license · 0 weekly downloads

## Install

```sh
npm install @holochain-syn/text-editor
pnpm add @holochain-syn/text-editor
yarn add @holochain-syn/text-editor
bun add @holochain-syn/text-editor
```

## Health

**Score 70/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.701.1 |
| Published | 2026-10-16 |
| First published | 2022-03-11 |
| Weekly downloads | 0 |
| License | CAL-1.0 |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 12 |
| Unpacked size | 46.6 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 97 |
| Maintainers | guillem.cordoba, zippy314, leosprograms |

## Links

- npm: https://www.npmjs.com/package/@holochain-syn/text-editor
- Repository: https://github.com/holochain-apps/syn
- Homepage: https://github.com/holochain-apps/syn#readme
- Issues: https://github.com/holochain-apps/syn/issues
- npm.io page: https://npm.io/package/@holochain-syn/text-editor

## Dependencies (12)

- [lit](https://npm.io/package/lit.md) ^3.0.0
- [@lit/context](https://npm.io/package/@lit/context.md) ^1.0.0
- [@lit/localize](https://npm.io/package/@lit/localize.md) ^0.12.0
- [@holochain/client](https://npm.io/package/@holochain/client.md) ^0.21.1
- [@holochain-syn/core](https://npm.io/package/@holochain-syn/core.md) ^0.701.1
- [@automerge/automerge](https://npm.io/package/@automerge/automerge.md) ^3.4.0
- [@shoelace-style/shoelace](https://npm.io/package/@shoelace-style/shoelace.md) ^2.3.0
- [@vanillawc/wc-codemirror](https://npm.io/package/@vanillawc/wc-codemirror.md) ^2.1.0
- [@holochain-open-dev/utils](https://npm.io/package/@holochain-open-dev/utils.md) ^0.701.0
- [@holochain-open-dev/stores](https://npm.io/package/@holochain-open-dev/stores.md) ^0.701.0
- [@holochain-open-dev/elements](https://npm.io/package/@holochain-open-dev/elements.md) ^0.701.0
- [@holochain-open-dev/profiles](https://npm.io/package/@holochain-open-dev/profiles.md) ^0.702.0

## Recent versions

- 0.701.1 (latest) — 2026-10-16
- 0.300.0-dev.0 (dev) — 2024-03-19
- 0.701.0 — 2026-10-16
- 0.700.1 — 2026-08-11
- 0.700.0 — 2026-08-07
- 0.603.0 — 2026-08-07
- 0.601.4 — 2026-06-12
- 0.601.3 — 2026-03-24
- 0.601.2 — 2026-03-24
- 0.601.1 — 2026-03-20
- 0.601.0 — 2026-02-28
- 0.600.0 — 2025-12-05
- 0.600.0-rc.2 — 2025-11-26
- 0.600.0-rc.1 — 2025-11-26
- 0.600.0-rc.0 — 2025-11-23
- … 60 more at https://npm.io/package/@holochain-syn/text-editor/versions

## README

# @holochain-syn/text-editor

Collaborative text editing for [syn](https://holochain-apps.github.io/syn): a text grammar plus an editor element with live remote cursors.

Text can be the entire state of your syn document, or one field inside a larger document.

## Installing

```bash
npm install @holochain-syn/text-editor @holochain-syn/core
```

The minor version encodes the Holochain version a release targets: `0.700.x` targets Holochain `0.7.0`, `0.603.x` targets Holochain `0.6.3`.

## The grammar

`textEditorGrammar` is a small helper over an Automerge document. It defines two shapes:

```ts
type TextEditorState = { text: string[] };            // committed
type TextEditorEphemeralState = { [agentB64: string]: AgentSelection };  // cursors, never committed
```

and gives you `initialState()` plus `changes(myPubKey, state, ephemeral)`, which returns the edit operations. There is no `applyDelta` and no delta type to define — you mutate the state inside `sessionStore.change` and syn takes care of merging.

### As the only state in your app

```ts
import { textEditorGrammar } from '@holochain-syn/text-editor';

const documentStore = await synStore.createDocument(textEditorGrammar.initialState());
const workspaceStore = await documentStore.createWorkspace('main', undefined);
const sessionStore = await workspaceStore.joinSession();

sessionStore.change((state, ephemeral) =>
  textEditorGrammar
    .changes(sessionStore.myPubKey, state, ephemeral)
    .insert(0, 'Hello, world')
);
```

### As one field of a larger document

Nest the text state inside your own, then use `extractSlice` to hand components a view that looks exactly like a whole session:

```ts
import { extractSlice } from '@holochain-syn/store';
import { textEditorGrammar, TextEditorState } from '@holochain-syn/text-editor';

interface DocumentState {
  title: string;
  body: TextEditorState;
}

const initialState = (): DocumentState => ({
  title: '',
  body: textEditorGrammar.initialState(),
});

// A slice over just the body, with the cursors passed through
const textSlice = sessionStore =>
  extractSlice(
    sessionStore,
    state => state.body,
    ephemeral => ephemeral
  );
```

Editing the title and the body are then the same kind of operation:

```ts
sessionStore.change(state => {
  state.title = 'New title';
});
```

## The `<syn-markdown-editor>` element

1. Set up the syn context as described in [@holochain-syn/core](https://npmjs.com/package/@holochain-syn/core).

2. Define the element:

```ts
import '@holochain-syn/text-editor/dist/elements/syn-markdown-editor.js';
```

3. Include it in your html and give it a slice:

```html
<syn-context>
  <syn-markdown-editor id="text-editor"></syn-markdown-editor>
</syn-context>
```

```ts
document.getElementById('text-editor').slice = textSlice(sessionStore);
```

The element expects a `SliceStore<TextEditorState, TextEditorEphemeralState>` — a `SessionStore` typed that way works directly, and `extractSlice` produces one for a nested field. It renders every other participant's cursor from the ephemeral state, and writes your own back as you type and select.

It also accepts an `autotype` boolean, which types random text on a timer. That is a load-testing aid, not something to ship enabled.

## See also

- [@holochain-syn/store](https://npmjs.com/package/@holochain-syn/store) — the engine, including how ephemeral state works
- [@holochain-syn/core](https://npmjs.com/package/@holochain-syn/core) — contexts and elements for syn UIs
- The [SynText demo](https://github.com/holochain-apps/syn/tree/main/demo) — a working app built on exactly this

---
_Source: https://npm.io/package/@holochain-syn/text-editor · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
