1.0.3 • Published 11 months ago

@huyngth/react-selection v1.0.3

Weekly downloads
-
License
MIT
Repository
github
Last release
11 months ago

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

PropTypeRequiredDescription
itemsT[]YesArray of selectable items. Each item must have an ID property
onSelectReturn(items: T[]) => voidYesCallback fired with selected items when selection changes
collisionType"intersect" \| "absolutely-inside"NoDetection mode for item selection (default: "intersect")
classNamestringNoAdditional CSS classes for the container
styleCSSPropertiesNoAdditional inline styles for the container
classes{ root?: string; selectionBox?: string }NoCustom classes for components
selectionBoxStyleCSSPropertiesNoCustom styles for the selection box
mouseDownExtendedCallBack() => voidNoAdditional 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

PropTypeRequiredDescription
idstringYesUnique identifier for the item (must match the ID in your data)
classNamestringNoAdditional CSS classes
childrenReactNodeNoContent 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