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

@composable-svelte/chat

v0.2.2

Published

Streaming chat component with collaborative features for Composable Svelte - Built for LLM interactions with transport-agnostic design

Readme

@composable-svelte/chat

Streaming chat components with collaborative features for Composable Svelte. Built for LLM interactions with a transport-agnostic design.

Features

  • Transport-agnostic - Bring your own streaming backend (WebSocket, SSE, REST, etc.)
  • Three UI tiers - Minimal, Standard, and Full chat variants for different complexity needs
  • Markdown rendering - Built-in markdown support with code highlighting via marked
  • File attachments - Attach images, documents, and media to messages
  • Message reactions - Emoji reactions on messages
  • Message editing - Edit and delete sent messages
  • Collaborative - Real-time presence tracking, typing indicators, and cursor markers
  • WebSocket management - Built-in WebSocket client with reconnection and cleanup
  • State-driven - Full Composable Architecture integration with testable reducers
  • Customizable - Custom sender names, avatars, labels, and message rendering

Installation

pnpm add @composable-svelte/chat

Peer dependencies:

pnpm add @composable-svelte/core svelte

Optional peer dependencies (for enhanced features):

pnpm add @composable-svelte/code   # Code block syntax highlighting
pnpm add @composable-svelte/media  # Audio/video embeds in messages
pnpm add prismjs                   # Prism.js syntax highlighting
pnpm add pdfjs-dist                # PDF attachment previews

Quick Start

<script lang="ts">
  import { createStore } from '@composable-svelte/core';
  import {
    FullStreamingChat,
    streamingChatReducer,
    createInitialStreamingChatState
  } from '@composable-svelte/chat';

  const store = createStore({
    initialState: createInitialStreamingChatState(),
    reducer: streamingChatReducer,
    dependencies: {
      streamMessage: (message, onChunk, onComplete, onError) => {
        // Connect to your LLM backend
        const response = await fetch('/api/chat', {
          method: 'POST',
          body: JSON.stringify({ message })
        });
        const reader = response.body.getReader();
        // Stream chunks...
        return new AbortController(); // For cancellation
      },
      generateId: () => crypto.randomUUID(),
      getTimestamp: () => Date.now()
    }
  });
</script>

<FullStreamingChat {store} />

Chat Variants

MinimalStreamingChat

Bare-bones chat with just messages and input. Best for embedding in tight spaces.

<MinimalStreamingChat {store} />

StandardStreamingChat

Adds message metadata (timestamps, sender info), typing indicators, and scroll management.

<StandardStreamingChat {store} userLabel="You" assistantLabel="AI" />

FullStreamingChat

Complete chat experience with attachments, reactions, editing, and all features enabled.

<FullStreamingChat
  {store}
  userLabel="You"
  assistantLabel="Assistant"
  enableAttachments={true}
  enableReactions={true}
/>

SimpleChatMessage / ChatMessage

Individual message components for custom layouts:

<ChatMessage message={msg} variant="assistant" showAvatar={true} />

Collaborative Features

For multi-user chat with real-time presence:

<script lang="ts">
  import {
    collaborativeReducer,
    PresenceAvatarStack,
    TypingIndicator,
    usePresenceTracking,
    useTypingEmitter,
    WebSocketManager
  } from '@composable-svelte/chat';
</script>

<!-- Show who's online -->
<PresenceAvatarStack users={$store.presence.users} />

<!-- Show who's typing -->
<TypingIndicator users={$store.typing.activeUsers} />

Collaborative Hooks

| Hook | Purpose | |------|---------| | usePresenceTracking | Track user online/offline/idle status | | useTypingEmitter | Broadcast typing start/stop events | | useCursorTracking | Share cursor position in real-time | | useHeartbeat | Keep-alive pings for connection health |

WebSocketManager

Manages WebSocket lifecycle with automatic reconnection:

import { WebSocketManager } from '@composable-svelte/chat';

const ws = new WebSocketManager('wss://chat.example.com', {
  reconnect: true,
  maxRetries: 5
});

State Management

State Shape

interface StreamingChatState {
  messages: Message[];
  currentStreaming: StreamingState | null;
  pendingAttachments: MessageAttachment[];
  isLoading: boolean;
  error: string | null;
}

Key Actions

| Action | Description | |--------|-------------| | sendMessage | Send a user message and trigger streaming | | addAttachment / removeAttachment | Manage file attachments | | editMessage / deleteMessage | Modify existing messages | | addReaction / removeReaction | Toggle emoji reactions | | cancelStreaming | Abort in-progress streaming | | restoreMessages | Restore messages from a previous session |

Dependencies

interface StreamingChatDependencies {
  streamMessage: (message: string, onChunk, onComplete, onError) => AbortController;
  generateId: () => string;
  getTimestamp: () => number;
}

Testing

import { createTestStore } from '@composable-svelte/core';
import { streamingChatReducer, createInitialStreamingChatState } from '@composable-svelte/chat';

const store = createTestStore({
  initialState: createInitialStreamingChatState(),
  reducer: streamingChatReducer,
  dependencies: {
    streamMessage: vi.fn((msg, onChunk, onComplete) => {
      setTimeout(() => onComplete(), 0);
      return new AbortController();
    }),
    generateId: () => 'test-id',
    getTimestamp: () => 1000
  }
});

await store.send({ type: 'sendMessage', content: 'Hello' }, (state) => {
  expect(state.messages).toHaveLength(1);
});

API Reference

Components

| Component | Description | |-----------|-------------| | MinimalStreamingChat | Minimal chat UI (messages + input) | | StandardStreamingChat | Standard chat with metadata and typing | | FullStreamingChat | Full-featured chat with attachments and reactions | | SimpleChatMessage | Single message display (simple) | | ChatMessage | Single message display (full features) | | PresenceBadge | Online status indicator | | PresenceAvatarStack | Stacked avatar display for online users | | PresenceList | List of users with presence status | | TypingIndicator | Animated typing dots | | TypingUsersList | List of currently typing users | | CursorMarker | Remote cursor position display | | CursorOverlay | Overlay layer for all remote cursors |

Functions

| Function | Description | |----------|-------------| | streamingChatReducer | Main chat reducer | | createInitialStreamingChatState() | Create initial state with defaults | | collaborativeReducer | Reducer for collaborative features | | createMockStreamingChat() | Mock for testing |

Dependencies

  • Runtime: marked (markdown parsing)
  • Peer: @composable-svelte/core, svelte
  • Optional: @composable-svelte/code, @composable-svelte/media, prismjs, pdfjs-dist