New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

collaborative-textarea

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install
Package was removed
Sorry, it seems this package was removed from the registry

collaborative-textarea

CRDT-powered <collaborative-textarea> custom element with remote cursors, persistence hooks, and TypeScript support.

latest
npmnpm
Version
1.0.3
Version published
Maintainers
1
Created
Source

Collaborative Textarea

CRDT-powered <collaborative-textarea> custom element with remote cursor overlays, persistence hooks, and first-class TypeScript types. Drop it into any web app, wire it to your transport of choice (WebRTC data channels work great), and get resilient collaborative editing without frameworks or build tools.

Why this component

  • Uses a Text RGA CRDT (simple-crdts) so edits merge deterministically and survive offline/latency.
  • Ships as a standard custom element; no React/Vue/Svelte runtime required.
  • Remote cursor labels and colors are drawn in an overlay that matches your textarea’s typography.
  • Built-in onWritingPaused callback and toJSON() make persisting snapshots trivial.
  • Fully typed API surface, with zero dependencies beyond simple-crdts.

Installation

npm install collaborative-textarea

The package is ESM-only ("type": "module"). Importing it registers the <collaborative-textarea> tag globally and also exports the class.

import { CollaborativeTextarea } from "collaborative-textarea";

Quick start

Render the element, optionally hydrating from a saved snapshot and tagging the local user with a display name and color.

<collaborative-textarea
  id="editor"
  spellcheck="false"
  style="width: 100%; height: 320px;"
></collaborative-textarea>
<script type="module">
  import { CollaborativeTextarea } from "collaborative-textarea";

  const saved = localStorage.getItem("collab-snapshot");
  const rgaSnapshot = saved ? JSON.parse(saved) : undefined;

  const editor = new CollaborativeTextarea(
    "node-a",
    { name: "Ava", color: "#ec4899" },
    [],
    rgaSnapshot
  );

  editor.onWritingPaused = (snapshot) => {
    localStorage.setItem("collab-snapshot", JSON.stringify(snapshot));
  };

  document.getElementById("editor").replaceWith(editor);
</script>

Wiring up peers (e.g., WebRTC)

peerConnections expects objects with a send(operation) method. When using RTCDataChannel, wrap serialization yourself and call applyRemoteOp on inbound messages.

// Outbound: serialize before sending.
const channel = rtcPeerConnection.createDataChannel("collab");
const peer = {
  send: (operation) => channel.send(JSON.stringify(operation)),
};
editor.addPeer(peer);

// Inbound: parse and feed into the CRDT.
channel.onmessage = ({ data }) => {
  const operation = JSON.parse(data);
  editor.applyRemoteOp(operation);
};

You can also call insertCharAt, deleteCharAt, or applyRemoteOp directly if you bridge through another transport (WebSocket, BroadcastChannel, etc.).

API overview

Constructor

new CollaborativeTextarea(localNodeId?, userMeta?, peerConnections?, rgaSnapshot?)

  • localNodeId (string): unique id for this client. A UUID is generated if omitted.
  • userMeta ({ name?: string; color?: string; }): label and caret color shown in the overlay.
  • peerConnections (CollaborativePeer[]): objects with a send method to broadcast operations.
  • rgaSnapshot (TextRGAJSON): previously persisted CRDT state to hydrate from.

Key properties

  • spellcheck (boolean): mirrors the underlying textarea. Set via property or spellcheck attribute.
  • onWritingPaused (callback | null): invoked ~1s after edits stop with toJSON() snapshot.
  • textarea (HTMLTextAreaElement): access the underlying textarea if you need to wire extra handlers.

Methods

  • addPeer(peer) / removePeer(peer): manage outbound peer targets.
  • insertCharAt(index, char): local insert routed through the CRDT.
  • deleteCharAt(index): local delete routed through the CRDT.
  • applyRemoteOp(operation): apply an incoming insert/delete/cursor operation from a peer.
  • toJSON(): CRDT snapshot suitable for persistence or hydration.

Styling

Style the host element as you would a normal textarea wrapper; the component mirrors your font, size, alignment, and padding onto the internal textarea so the cursor overlay lines up. Example:

collaborative-textarea {
  display: block;
  width: 100%;
  height: 280px;
  border: 1px solid #d1d5db;
  border-radius: 8px;
  padding: 12px;
  font: 400 16px/1.5 "Inter", system-ui, sans-serif;
}

Persisting state

  • Listen to onWritingPaused for a debounced snapshot callback, or call toJSON() anytime.
  • Pass the stored snapshot back into the constructor to hydrate the CRDT with the correct ordering.

Notes and compatibility

  • Requires browsers with Custom Elements and ResizeObserver support (falls back to window.resize if unavailable).
  • Ships unbundled ES modules; bring your own bundler or load directly in modern browsers.
  • Dependency footprint: simple-crdts only.

Keywords

collaborative

FAQs

Package last updated on 29 Dec 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts