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

comins-sortable

v0.1.6

Published

Zero-dependency drag-and-drop sorting for Vanilla JavaScript, React, Vue, and Svelte. Sortable lists, grids, nested trees, multi-drag, and swap with a TypeScript core.

Readme

Comins Sortable

Comins Brand

Drag-and-drop sorting for Vanilla JavaScript, React, Vue, and Svelte, built on one TypeScript core with zero runtime dependencies. Build sortable lists, grids, kanban boards, and nested trees with controlled application state.

npm package · English docs · 한국어 가이드

Comins Sortable Playground demonstrating empty-slot return, drag start areas, drop feedback styles, per-list state updates, and subtree movement

The animation shows real React Playground interactions: emptying and refilling a list between fixed slots, changing drag start areas, comparing accepted and rejected drop styles, updating a child list, and moving a complete subtree. By default, drag a card's left handle to move it and select its body text to copy it. The Drag start areas example also demonstrates title-only and whole-card dragging.

Features

| Capability | What to try in the Playground | | --- | --- | | Sortable lists and kanban boards | Reorder items, transfer them between lists, or copy them to another list. | | Drag start areas and text selection | Compare handle, title-only, and whole-card dragging; use handle mode to select and copy body text. | | Multi-drag | Command/Ctrl-click handles, or use Shift for a range, then move the selected items together. | | Sorting thresholds | Change the shaded target region to see when a drag changes order; this differs from the distance needed to start dragging. | | Grid and Swap Grid | Grid inserts and shifts items from the dragged card’s center, including off-center handle grabs. Swap Grid exchanges only the dragged and highlighted cells. | | Nested lists and Tree | Per-list state control updates separate arrays in React, Vue, and Svelte; Vanilla demonstrates direct DOM updates. Subtree movement preserves descendants when a node changes parent. Both include structure diagrams and step-by-step instructions. | | Drag feedback | Compare accepted/rejected drop styles and their CSS; customize animation, placeholders, skeleton feedback, and auto-scroll. |

Vanilla uses no framework peer. React, React DOM, Vue, and Svelte integrations use optional peers (react, react-dom, vue, and svelte).

Installation

npm install comins-sortable

Install the peers used by your chosen adapter: React >=18.2 <20 with React DOM >=18.2 <20, Vue >=3.5 <4, or Svelte >=5 <6. Vanilla needs no framework peer. Use the repository Playground below to try the examples.

Quick Start with React

Comins Sortable is controlled: the application owns the item array and commits each proposed order through onItemsChange.

import { useState } from 'react';
import { SortableArea, SortableRoot } from 'comins-sortable/react';
import 'comins-sortable/styles.css';

type Item = { id: string; label: string };

export function TaskList() {
  const [items, setItems] = useState<Item[]>([
    { id: 'task-1', label: 'Plan' },
    { id: 'task-2', label: 'Build' },
  ]);

  return (
    <SortableRoot<Item>>
      <SortableArea
        areaId="tasks"
        items={items}
        itemKey="id"
        handle=".task-handle"
        onItemsChange={(nextItems) => setItems([...nextItems])}
      >
        {(item) => (
          <div>
            <button
              type="button"
              className="task-handle"
              aria-label={`Drag ${item.label}`}
              style={{ touchAction: 'none', userSelect: 'none', WebkitUserSelect: 'none' }}
            >
              ⠿
            </button>
            <span>{item.label}</span>
          </div>
        )}
      </SortableArea>
    </SortableRoot>
  );
}

The handle confines pointer activation to the button, so the label remains available for text selection. A labelled button does not add keyboard sorting; this module's sorting interaction is pointer-based. See the handle and text-selection guide for styling and multi-selection behavior.

Choose an adapter

| Adapter | State updates | Guide | | --- | --- | --- | | Vanilla JavaScript | Direct DOM sorting with createSortable | Vanilla guide | | React | Controlled items and onItemsChange | React guide | | Vue | v-model and a typed item slot | Vue guide | | Svelte | Controlled items and update callbacks | Svelte guide |

Use stable string or number IDs. Framework adapters propose updates; the application commits them to its state. Cross-list moves need a shared root.

Guides and API

createSortableTree maps your tree schema to sortable areas and applies area updates to an immutable tree value. It preserves descendants when a node moves; it does not render a tree component. Placeholder classes and CSS variables customize insertion and rejection feedback without changing sorting behavior.

Run the Playground locally

The Playground currently provides 25 routes per adapter, covering Vanilla JavaScript, React, Vue, and Svelte. Clone the repository to run the examples:

git clone https://github.com/kim1124/comins-sortable.git
cd comins-sortable
npm ci --ignore-scripts
npm run build
npm run dev

Open the React simple-sorting example. The development server uses port 4003.

Use Reset to restore the example and clear multi-selection, including its Shift-range anchor, in all four adapters.

0.1.6

Version 0.1.6 keeps the existing public APIs and zero runtime dependencies. It fixes:

  • Drag feedback offsets inside tested transformed, filtered or contained ancestors, including scrolling and list-size changes after placeholder relocation.
  • Detached copy/table preview sizing when source and body containers use different scales or inherited CSS min/max dimensions.
  • Off-center grid handle drags that needed extra travel or inserted in the previous row.
  • The development-only source-map-js dependency, updated to patched 1.2.2.

Development tooling now uses Vite 8.3.4, Playwright 1.64.0 and Svelte 5.57.2. Lightning CSS has an exact maintainer-approved development-only license scope; its code/binaries are not shipped in the Sortable npm package.

Fresh verification passed 72 policy tests, 293 unit tests, 301 Core E2E tests and 701 Playground E2E tests, including 48 adjacent-cell/row grid regressions. Desktop Chrome Computer Use confirmed 16 grid drags across all four adapters. Feedback/copy geometry and native text copying have separate recorded checks. Resource results, including a Svelte GC-sample failure and unchanged-source recheck, are recorded in the verification guidance. Touch emulation is separate from physical-device verification.

See changes and verification for the scope, evidence and release status.

Browser support and limits

Automated tests cover Chromium, Firefox, and WebKit. Sorting uses pointer input; keyboard reordering is not implemented. Browser touch emulation is distinct from physical-device testing. See the changelog for published changes and the performance verification guide for reproducible large-list and resource measurements.

A previously recorded native Safari title-only drag can leave body text selected. Use a dedicated handle when selecting and copying body text matters; see the handle guide. Automated WebKit results do not establish native Safari or Galaxy coverage.

License and support

MIT · Changelog · Issues · Report a security issue