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

svelte-yjs

v0.0.1

Published

Reactive [Svelte](https://svelte.dev/) wrappers around [Yjs](https://yjs.dev/).

Downloads

6

Readme

svelte-yjs

Reactive Svelte wrappers around Yjs.

Usage

The heart of svelte-yjs is the wrapYjsDocumentInState(...) function. You can pass in an initialized Yjs document (a Y.Doc instance) and work with the result like with any $state wrapped object.

import { wrapYjsDocumentInState, type DeclareSyncableDocument } from 'svelte-yjs';
import * as Y from 'yjs';

// Yjs only supports certain "shared types". It's recommended that you
// declare your document structure with `DeclareSyncableDocument<...>`,
// which enforces a specific typed structure.
type TodoListDocument = DeclareSyncableDocument<{
	title: string;
	description?: string;
	items: {
		text: string;
		done: boolean;
	}[];
}>;

const doc = new Y.Doc();

// You should initialize persistence and/or syncing here using Yjs
// providers like "y-indexeddb" or "y-websocket".

const state = wrapYjsDocumentInState<TodoListDocument>({
	yjsDocument: doc,
	initialState: {
		title: 'New Todo List',
		items: []
	}
});

function createNewTodoItem() {
	// Interact with the document state like you would with any object.
	// The underlying Y.Array in the document is updated automatically.
	state.items.push({ text: '', done: false });
}

// Svelte runes can be used on the synchronized state. This also updates
// when any connected peers add or remove an item from the list.
let hasAnyTodoItems = $derived(state.items.length > 0);

Allowed Types

The following types are allowed for declaring the structure of your document. The generic type T of complex data structures like arrays and maps is deeply bound to the same restrictions.

| Syncable Type | Yjs Structure | | ------------------- | ------------- | | boolean | (atomic) | | number | (atomic) | | string | (atomic) | | null | (atomic) | | undefined | (atomic) | | Uint8Array | (atomic) | | Record<string, T> | Y.Map<T> | | Map<string, T> | Y.Map<T> | | Array<T> | Y.Array<T> | | SyncedText | Y.Text |

Note that Record<string, T> refers to any JavaScript object which consists of syncable type properties. In other words, you can declare your document as an object with multiple nesting levels - during runtime, each level is internally represented as a Y.Map.

SyncedText is an exported class from svelte-yjs, which can be used to implement collaborative text editing. Instead of replacing the entire shared text string on every keypress, you can use the "delta" functions on SyncedText instances to insert text at one point or to delete some characters at another point.

Awareness

Awareness (or "presence") in Yjs represents live user information that isn't persisted in the document. For example, this could be a nickname or the current cursor position of any connected user.

In svelte-yjs, this live information can be modified and reacted to using the wrapYjsAwarenessInState(...) function.

import { wrapYjsAwarenessInState } from 'svelte-yjs';

interface UserState {
	nickname: string;
	cursor?: {
		x: number;
		y: number;
	};
}

// Most Yjs providers expose an interactable "Awareness"
// instance as a property. That instance can be passed to
// wrapYjsAwarenessInState(...) to produce a reactive version.
const yjsProvider = /** */;

const awareness = wrapYjsAwarenessInState<UserState>({
	yjsAwareness: yjsProvider.awareness,
	initialState: {
		nickname: 'Alice'
	}
});

function onMouseMove(ev: MouseEvent) {
	// Modify the live information associated with the local
	// user by updating the `local` property.
	awareness.local.cursor = { x: ev.pageX, y: ev.pageY };
}

// `states` maps all connected client IDs to their current state.
// Whenever a user updates their nickname, this $derived value
// gets automatically re-evaluated.
let allOnlineNames = $derived(
	awareness.states
		.values()
		.map((state) => state.nickname)
		.toArray()
);