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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@y-sweet/react

v0.7.0

Published

React library for building collaboration features with y-sweet.

Downloads

981

Readme

@y-sweet/react

GitHub Repo stars Chat on Discord npm

React library for building collaboration features with y-sweet.

Installation

npm install @y-sweet/react

Examples

Explore our collaborative examples to help you get started.

All examples are open source and live in this repository, within /examples.

Using @y-sweet/react

Yjs models data as a nested data structure with types like Y.Array corresponding to array data, Y.Map corresponding to objects and key/value maps, and Y.Text corresponding to strings. Each hook returns a Yjs type, so refer to Yjs documentation for details on how to use them.

In addition to returning a Yjs type, each hook also subscribes the component to changes to that type. By default, changes to that value, or any descendent of that value, triggers a rerender of the component.

The @y-sweet/react hooks provide a way to access data for each of these types.

useMap is a shared object or map

useMap exposes a Yjs Y.Map. You can refer to the documentation for Y.Map here.

Our Color Grid example uses useMap to store a grid of colors using coordinates as keys.

const items = useMap<string>('colorgrid')

items.delete(key)
items.set(`${x},${y}`, color)

useArray is a shared array

useArray exposes a Yjs Y.Array. You can refer to the documentation for Y.Array here.

Our To Do List example, which uses useArray to store a list of To Do items.

The To Do List stores an array of objects of type Y.Map (a Yjs type). This maintains the order of the To Do List, while being able to indicate whether an item is ‘done’.

const items = useArray<Y.Map<any>>('todolist')

const pushItem = useCallback((text: string) => {
    let item = new Y.Map([
        ['text', text],
        ['done', false],
    ] as [string, any][])

    items?.push([item])
},[items])

const clearCompleted = useCallback(() => {
    let indexOffset = 0
    items?.forEach((item, index) => {
        if (item.get('done')) {
            items.delete(index - indexOffset, 1)
            indexOffset += 1
        }
    })
}, [items])

useText is a shared string

useText exposes a Yjs Y.Text. You can refer to the documentation for Y.Text here.

Our Text Editor example, which uses useText to store the text document.

const yText = useText('text')

Add presence features

useAwareness returns an Yjs awareness object

The awareness object can be applied to editor bindings with Yjs that have built in presence features.

Our Code Editor demo passes the awareness object to the CodeMirror Yjs binding.

const awareness = useAwareness()

bindingRef.current = new CodemirrorBinding(yText!, editorRef.current, awareness)

usePresence for general purpose presence features

The usePresence and usePresenceSetter hooks are a higher-level React abstraction on top of Yjs’s awareness.

usePresence returns a Map<number, object> of presence data for other users. The key is the user ID, and the value is whatever that user has set as their presence data.

usePresenceSetter returns a function that can be used to set the current user’s presence data.

Our Presence demo defines presence as a map of x,y keys and color value pairs.

'use client'

import { usePresence, usePresenceSetter } from '@y-sweet/react'
import { useCallback, useRef } from 'react'

const COLORS = ['bg-red-500', 'bg-blue-500', 'bg-green-500', 'bg-purple-500', 'bg-pink-500']

type Presence = { x: number; y: number; color: string }

export function Presence() {
  const myColor = useRef(COLORS[Math.floor(Math.random() * COLORS.length)])
  const presence = usePresence<Presence>()
  const setPresence = usePresenceSetter<Presence>()

  const updatePresence = useCallback(
    (e: React.MouseEvent<HTMLDivElement>) => {
      setPresence({
        x: e.clientX - e.currentTarget.offsetLeft,
        y: e.clientY - e.currentTarget.offsetTop,
        color: myColor.current,
      })
    },
    [setPresence],
  )

  return (
    <div
      className="border-blue-400 border relative overflow-hidden w-[500px] h-[500px]"
      onMouseMove={updatePresence}
    >
      {Array.from(presence.entries()).map(([key, value]) => (
        <div
          key={key}
          className={`absolute rounded-full ${value.color}`}
          style={{ left: value.x - 6, top: value.y - 8, width: 10, height: 10 }}
        />
      ))}
    </div>
  )
}