Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@huyngth/react-selection

huyngth13MIT1.0.3TypeScript support: included

A selection feature same as ones in OS (File Explorer/Finder)

react, react-selection, reactselection, selection, react-selection-zone, drag-n-select, drag-n-select-react, react-drag-n-select

readme

React Selection

A powerful React library that enables interactive selection functionality similar to file explorers, with support for mouse-based selection boxes, collision detection, and customizable styling.

Features

  • 🎯 Click-and-drag selection box
  • 🎨 Customizable selection box styling
  • 🎮 Flexible collision detection modes
  • 📦 Lightweight with zero external dependencies
  • 🔄 Controlled selection state management
  • 🎁 Written in TypeScript with full type safety
  • 💅 Customizable CSS classes and styles

Installation

npm install react-selection
# or
yarn add react-selection

Core Components

SelectionZone

The main container component that manages selection state and handles selection logic.

import { SelectionZone } from "react-selection";

interface MyData {
  ID: string; // ID is required for all items
  // ... other properties
}

function App() {
  const [selectedItems, setSelectedItems] = useState<MyData[]>([]);

  return (
    <SelectionZone<MyData>
      items={data}
      onSelectReturn={setSelectedItems}
      collisionType="intersect"
      className="grid grid-cols-12 gap-2"
    >
      {/* SelectableItem components */}
    </SelectionZone>
  );
}

Props

Prop Type Required Description
items T[] Yes Array of selectable items. Each item must have an ID property
onSelectReturn (items: T[]) => void Yes Callback fired with selected items when selection changes
collisionType "intersect" | "absolutely-inside" No Detection mode for item selection (default: "intersect")
className string No Additional CSS classes for the container
style CSSProperties No Additional inline styles for the container
classes { root?: string; selectionBox?: string } No Custom classes for components
selectionBoxStyle CSSProperties No Custom styles for the selection box
mouseDownExtendedCallBack () => void No Additional callback for mouseDown events

SelectableItem

The component that wraps each selectable element.

import { SelectableItem } from "react-selection";

<SelectableItem id="unique-id" className="aspect-square bg-gray-200">
  {/* Optional content */}
</SelectableItem>;

Props

Prop Type Required Description
id string Yes Unique identifier for the item (must match the ID in your data)
className string No Additional CSS classes
children ReactNode No Content to render inside the item

Selection Mechanics

Collision Detection

The library supports two collision detection modes:

  1. "intersect" (default): Items are selected when they intersect with the selection box
  2. "absolutely-inside": Items are selected only when they are completely inside the selection box
<SelectionZone
  collisionType="absolutely-inside"
  // ... other props
>

Selection Box Styling

The selection box can be customized using either classes or inline styles:

<SelectionZone
  classes={{
    root: "selection-container",
    selectionBox: "selection-box"
  }}
  selectionBoxStyle={{
    border: "2px dashed #000",
    backgroundColor: "rgba(0, 0, 255, 0.1)"
  }}
>

Default selection box styles:

  • Border: 1px dashed #3b82f6
  • Background: #bfdbfe
  • Opacity: 0.5
  • Z-index: 50

Advanced Usage

Using the Selection Hook

For custom implementations, you can use the useSelectionZone hook directly:

import { useSelectionZone } from "react-selection";

function CustomSelectionContainer<T extends { ID: string }>() {
  const {
    selectionContainerRef,
    isSelecting,
    selection,
    handleMouseDown,
    handleMouseMove,
    handleMouseUp,
  } = useSelectionZone<T>({
    collisionType: "intersect",
  });

  // ... custom implementation
}

Custom Styling Example

import { SelectionZone, SelectableItem } from "react-selection";
import { cn } from "./utils";

function App() {
  return (
    <SelectionZone
      items={data}
      onSelectReturn={setSelected}
      classes={{
        root: "selection-container",
        selectionBox: "selection-box-custom",
      }}
      className="grid grid-cols-12 gap-2 p-4"
    >
      {data.map((item) => (
        <SelectableItem
          key={item.ID}
          id={item.ID}
          className={cn(
            "aspect-square rounded-lg transition-colors",
            "hover:bg-gray-100",
            selected.includes(item) && "bg-blue-500"
          )}
        />
      ))}
    </SelectionZone>
  );
}

TypeScript Support

The library is written in TypeScript and provides full type safety. The only requirement is that your data type extends the TSelectableItem interface:

interface TSelectableItem {
  ID: string;
}

interface MyData extends TSelectableItem {
  name: string;
  value: number;
  // ... other properties
}

<SelectionZone<MyData>
  items={myData}
  onSelectReturn={(selected) => {
    // Type-safe selected items
  }}
>
  {/* SelectableItem components */}
</SelectionZone>;

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License