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

react-ds

v1.13.0

Published

Simple React Drag-to-Select component

Downloads

689

Readme

React DS

Tiny (7KB) React Drag-to-Select component (with no dependencies! with support for touch devices!

Travis npm Coverage Status npm npm Codacy grade

react-ds gif

I wrote this library because I couldn't find any existing one to do selections without having to wrap the items in their component.

In some cases you really need an unobtrusive way to make items selectable, this will do just that.

Installation

$ npm i react-ds

Or if you prefer yarn

$ yarn add react-ds

Usage

import Selection from 'react-ds';

// target (ref) is the parent component (so that selects only happen when clicking and dragging on it)
// elements (refs[]) is an array of refs to the components that are selectable
<Selection
    target={ ref }
    elements={ refs[] }
    onSelectionChange={ this.handleSelection }
/>

Props

target

Element where the selection should be applied to. This is to scope the mouse/touch event handlers and make sure that it doesn't affect your whole web app.

It must be a React ref, it should also exist, so you may want to check if it's already initialized before rendering the Selection component.

elements

Array of refs to the elements that are selectable. The Selection component will use this to get their location and sizes to determine whether they are within the selection area.

The should exist before rendering the Selection component.

onSelectionChange

Function that will be executed when the selection changes. An array of element indexes will be passed (with the same indexes as the elements prop).

This is where you want to update your state, to highlight them as selected for example.

onHighlightChange

While dragging, onHighlightChange is called only when the highlighted elements have changed.

When the mouse is released, it will be called with an empty array.

onHighlightChange Example

offset (Optional)

This is used to calculate the coordinates of the mouse when drawing the Selection box, since the mouse events gives coordinates relative to the document, but the Selection box may have a different parent.

Essentially you need to pass the offset of the parent element where the Selection is being rendered. If it's rendered in the same component as the items to be selected then the default value will work fine.

If passing your own offset keep in mind that getBoundingClientRect() depends on the scroll, so you may want to do something like this:

const boundingBox = target.getBoundingClientRect();
const offset = {
  top: boundingBox.top + window.scrollY,
  left: boundingBox.left + window.scrollX,
};

style (Optional)

If you want to override the styles for the selection area, you can either pass any styles here, or use css and declare any styles on the .react-ds-border class.

The styles are merged, so you can override just one property if you need (typically the zIndex).

The default styles are:

const style = {
  position: 'absolute',
  background: 'rgba(159, 217, 255, 0.3)',
  border: 'solid 1px rgba(123, 123, 123, 0.61)',
  zIndex: 9,
  cursor: 'crosshair',
}

ignoreTargets (Optional)

Specify an array of CSS3 selectors for DOM targets that should be ignored when initiating a selection. i.e. ['div', 'div > p', '#someId']

This is specially useful because react-ds uses native browser events that bypass React's event queue, so you won't be able to stopPropagation as usual.

<Selection
    target={ this.state.ref}
    elements={ this.state.elRefs }
    onSelectionChange={ this.handleSelection }
    ignoreTargets={ ['.handle'] }
/>

Example

This example was taken from example/app/src/Example.js which you can see running at https://aurbano.eu/react-ds/

import React from 'react';
import PropTypes from 'prop-types';
import Selection from 'react-ds';

export default class Example extends React.PureComponent {

  constructor() {
    super();

    this.state = {
      ref: null,
      elRefs: [],
      selectedElements: [], // track the elements that are selected
    };
  }

  handleSelection = (indexes) => {
    this.setState({
      selectedElements: indexes,
    });
  };

  getStyle = (index) => {
    if (this.state.selectedElements.indexOf(index) > -1) {
      // Selected state
      return {
        background: '#2185d0',
        borderColor: '#2185d0',
        color: 'white',
      };
    }
    return {};
  };

  addElementRef = (ref) => {
    const elRefs = this.state.elRefs;
    elRefs.push(ref);
    this.setState({
      elRefs,
    });
  };

  renderSelection() {
    if (!this.state.ref || !this.state.elRefs) {
      return null;
    }
    return (
      <Selection
        target={ this.state.ref}
        elements={ this.state.elRefs }
        onSelectionChange={ this.handleSelection }
        style={ this.props.style }
      />
    );
  }

  render() {
    const selectableElements = [
      'one',
      'another',
      'hey there',
      'item',
      'two',
      'three',
      'something longer?',
      'last'
    ];
    return (
      <div ref={ (ref) => { this.setState({ ref }); } } className='item-container'>
        { selectableElements.map((el, index) => (
          <div
            key={ el }
            ref={ this.addElementRef }
            style={ this.getStyle(index) }
            className='item'
          >
            { el }
          </div>
        )) }
        { this.renderSelection() }
      </div>
    );
  }
}

Example.PropTypes = {
  style: PropTypes.object,
};

Contributing

Only edit the files in the src folder. I'll update dist manually before publishing new versions to npm.

To run the tests simply run npm test. Add tests as you see fit to the test folder, they must be called {string}.test.js.

Meta

Copyright © Alejandro U. Alvarez 2017. MIT Licensed.