Giter VIP home page Giter VIP logo

hc-oss / react-multi-select-component Goto Github PK

View Code? Open in Web Editor NEW
377.0 3.0 89.0 5.97 MB

Lightweight (~5KB gzipped) multiple selection dropdown component

Home Page: https://codesandbox.io/s/react-multi-select-example-uqtgs

License: MIT License

JavaScript 4.81% TypeScript 86.06% HTML 0.43% CSS 8.70%
dropdown react-select multiselect checkboxes select-all select react hacktoberfest typescript component

react-multi-select-component's Introduction

react-multi-select-component

Simple and lightweight multiple selection dropdown component with checkboxes, search and select-all

Storybook GitHub Actions Status NPM gzip

โœจ Features

  • ๐Ÿ•ถ Zero Dependency
  • ๐Ÿƒ Lightweight (<5KB)
  • ๐Ÿ’… Themeable
  • โœŒ Written w/ TypeScript

๐Ÿ”ง Installation

npm i react-multi-select-component    # npm
yarn add react-multi-select-component # yarn

๐Ÿ“ฆ Example

Example

import React, { useState } from "react";
import { MultiSelect } from "react-multi-select-component";

const options = [
  { label: "Grapes ๐Ÿ‡", value: "grapes" },
  { label: "Mango ๐Ÿฅญ", value: "mango" },
  { label: "Strawberry ๐Ÿ“", value: "strawberry", disabled: true },
];

const Example = () => {
  const [selected, setSelected] = useState([]);

  return (
    <div>
      <h1>Select Fruits</h1>
      <pre>{JSON.stringify(selected)}</pre>
      <MultiSelect
        options={options}
        value={selected}
        onChange={setSelected}
        labelledBy="Select"
      />
    </div>
  );
};

export default Example;

More examples can be found here โ†—

๐Ÿ‘€ Props

Prop Description Type Default
labelledBy value for aria-labelledby string
options options for dropdown [{label, value, disabled}]
value pre-selected rows [{label, value}] []
hasSelectAll toggle 'Select All' option boolean true
isLoading show spinner on select boolean false
shouldToggleOnHover toggle dropdown on hover option boolean false
overrideStrings localization โ†— object
onChange onChange callback function
disabled disable dropdown boolean false
disableSearch hide search textbox boolean false
filterOptions custom filter options (async supported) โ†— function Fuzzy Search
className class name for parent component string multi-select
valueRenderer custom dropdown header โ†— function
ItemRenderer custom dropdown option โ†— function
ClearIcon Custom Clear Icon for Search ReactNode
ArrowRenderer Custom Arrow Icon for Dropdown ReactNode
debounceDuration debounce duration for Search number 300
ClearSelectedIcon Custom Clear Icon for Selected Items (Hint: Pass null to prevent it from rendering completely) ReactNode
isCreatable Allows user to create unavailable option(s) example โ†— boolean false
onCreateOption allows to override newly created option example โ†— function
closeOnChangedValue automatically closes dropdown when its value is changed boolean false

๐Ÿ“ Changelog

For every release changelog/migration-guide will be available in releases

๐Ÿค  Credits

๐Ÿ“œ License

MIT ยฉ harshzalavadiya

react-multi-select-component's People

Contributors

bdokimakis avatar breynolds-dev avatar brijeshlakkad avatar chenjie-b1 avatar cristianbote avatar dependabot-preview[bot] avatar dependabot[bot] avatar harshzalavadiya avatar jose-donato avatar kannndev avatar lucas-lm avatar maxnathaniel avatar megakeegman avatar mkhbragg avatar porteron avatar ryzoo avatar tefferson avatar yuvalshim avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

react-multi-select-component's Issues

Mod request - Add Prop to declare callback() for when the dropdown list is closed.

Modification Request - Add new Prop to declare callback function when the dropdown list is closed.
image

Hello - I am trying to send your 'selected' hook's data to a global store via redux action, to then update a chart component with the multi-selected data sets. Global state is successfully updated with 'selected' data upon component render (each time a new checkbox is clicked). My chart fails to render due to:
Warning: Cannot update a component ('Dropdown') while rendering a different component ('ChartBuilder').
and
Warning: unstable_flushDiscreteUpdates: Cannot flush updates when React is already rendering.

I believe I can get around this issue if I were able to call the action as a declared callback function upon closing the checklist dropdown.


This feature is needed on the below application so multiple state's data can be aggregated into each line of a line chart.
www.corona.tomjmcnamee.com

missing types

The type definitions dist/index.d.ts is missing. It's not generated when running the build script

automatic close

The select options doesnt close automatically when a option is selected it needs to closed manually by clicking on other side of screen to close the options bar, how can we make it to close automaticallly

Support for onBlur and onClose events

The props are pretty limited right now and is inactionable when closing or completing interaction with the MultiSelect.

It would be great to be able to use these events (onBlur and onClose), especially for scenarios where data should be fetched upon close of dropdown.

Weird behavior of the search

During testing the component, I've found a weird issue when searching. This is reproducible on your own CodeSanbox example.

When I type, the order of the items change and the search string doesn't represent the expected result(s). Could you take a look at this?

GIF for clarity: https://i.imgur.com/hZStnR7.gifv

Dropdown content position

I change the position of the dropdown content using css styles but cannot change the direction of the icon.

unselect pre-selected rows

I want the user to unselect pre-selected options using the UI.
Given that the value prop is set to some options, can the user unselect the value or add additional select?
Current behavior:
If the value state is changed programmatically, the select box will be disabled for both adding or removing selected values.

remote data search

Hi, thanks for making this component so beautiful, but i have some problem when load thousands data into this component, it makes slow. Please suggest how to make it possible to load data when it match with the search term. Thank you!

Testing with React Testing Library

Greetings,

I'd like to know if there is any recommended way to test interactions with this component using RTL. Currently, with the most updated versions of @testing-library/react (10.4.9) and @testing-library/user-event (12.1.3) I'm not able to simulate options being select by the user.

I've already tried simulating click events choosing the select by its placeholder (e.g: userEvent.click(getByText('Select...'))) but it didn't show the options inside the testing environment so I could simulate another click event on one of them. I've also already tried simulating clicks on the parent div elements of the placeholder node, but it didn't work either. Apart from that, I cannot use userEvent.selectOptions because react-multi-select-component doesn't render to an html select component.

So, can someone shed me a light on this? Thanks in advance!

Multi select is not displaying values after clicking on item

I am using reactjs class to have this Multi Select. When i select item in the drop down onClick is working and value is getting selected. The selected value is not shown after selection.
Here is the code i used for it,

import React, { Component } from 'react';
import MultiSelect from '../../../multi-select';

class Forms extends Component {

    
  constructor(props) {
    super(props);
    this.state = {
      selected: [],
      options: [
        { label: "USA ๐Ÿด๓ ต๓ ณ๓ ก๓ ณ๓ ฟ", value: "USA" },
        { label: "India ๐Ÿ˜Š", value: "INDIA" },
        { label: "Japan ๐Ÿ“", value: "Japan" }
      ]
      };
  }

  setSelected() {
      this.setState({selected: this.state.selected})
  }

 
  render() {
       return (
      <MultiSelect
        options={this.state.options}
        value={this.state.selected}
        onChange={() => this.setSelected}
        labelledBy={"Select"}
      />
    );
  }
}

export default Forms;
image

Using object styles instead of tagged templates reduces the output gzipped size with `-200B`

Hey @harshzalavadiya,

First of all kudos for this project! Really love the output and the small sizes! ๐Ÿ˜‰ Also love that you chose to use goober ๐Ÿ˜„ thank you for that!

Second, was noticing that you've used css function with tagged template and looking at the minified output in here https://unpkg.com/[email protected]/dist/react-multi-select-component.cjs.production.min.js the space occupied by those \n and other strings is enormous. ๐Ÿ˜„ So I've played around a bit with it and if you change the tagged template into object styles, the output is shaved with -200B!

The syntax will change as:

css`
  opacity: 1;

  &:hover {
    color: tomato;
  }
`;

// To
css({
  opacity: 1,

  '&:hover': {
    color: 'tomato'
  }
});
Filesizes
                                   brotli   gzip     none     
  โœ” original/react-multi-*.min.js  3.14 kb  3.58 kb  9.93 kb  
  โœ”     dist/react-multi-*.min.js  3.00 kb  3.37 kb  8.83 kb

Let me know if you're looking to shave that I can open a PR with those changes.

Small UI improvements

First of, thanks for this nice and simple little component!

I'd like to propose a few small improvements to the IU:

  • Use different colors for :hover state and .selected class. Maybe by providing a --rmsc-selected CSS var.
  • The DOM element .item-renderer does not inherits the cursor: pointer, which results in a weird behavior of the cursor: we have default cursor when hovering the text and checkbox, but pointer cursor in the border of the box (in the padding surrounding it). It would be nice to have it consistent.
  • The margins of items should be defined, to avoid inconsistency between the "select-all" which is into a label element, and other options which are wrapped in ul > li elements.

Nice work, by the way!

Expand disabled dropdown?

Is there a reason that the dropdown is still expandable when it's disabled? If not, here's a teeny tiny PR to address that ๐Ÿ‘‰ #66. If it is intentional, could you explain why?

Thanks! And thank you for this component ๐Ÿ™

Error: Text strings must be rendered within a <Text> component

I tried to use the basic demo to show a simple multiselect however I get this weird error not sure why I copied exactly like the demo code.

const options = [
    { label: "1/2", value: "1/2" },
    { label: "1/3", value: "1/3" },
    { label: "1/4", value: "1/4"},
    { label: "1/5", value: "1/5" },
    { label: "1/6", value: "1/6" },
    { label: "1/7", value: "1/7" },
    { label: "1/8", value: "1/8" },
  ];
const [selected, setSelected] = useState([]);
return (
      <div><pre>{JSON.stringify(selected)}</pre>
      <MultiSelect
        options={options}
        value={selected}
        onChange={setSelected}
        labelledBy={"Select"}
      />
    </div>

);

Dropdown is not closed when clicking away on another input

Hi,
I've noticed some strange behavior whenever I try to close the dropdown by clicking away. When I click on some empty space, it works fine, however, when I click on another input, that input receives the focus but the dropdown is not closed.

As far as I understand, the issue is with these lines of code in dropdown.tsx:

    if (!e.relatedTarget) {
      setHasFocus(false);
      setExpanded(false);
    }
  };

Since another input is receiving the focus with this click, e.relatedTarget is defined and contains that new input, which means that setExpanded(false) is not called.

I see that this check has been purposefully added, but I'm not sure exactly why. @harshzalavadiya could you please shed some light on it?

Goober styles leak into global scope

Not sure if this is an issue with this repo or with Goober.

The styles that are defined for the DefaultRenderer in select-panel/default-item.tsx leak out into the global CSS scope.

This source code:

const DefaultRenderer = css({
  "input,span": {
    verticalAlign: "middle",
    margin: 0,
  },
  span: {
    display: "inline-block",
    paddingLeft: "5px",
  },
  "&.disabled": {
    opacity: 0.5,
  },
});

creates this CSS when rendered with Goober:

.go3532419405 input,span{vertical-align:middle;margin:0;}
.go3532419405 span{display:inline-block;padding-left:5px;}
.go3532419405.disabled{opacity:0.5;}

The ,span is the problematic part that leaks out into the global styles. The browser interprets that first line as "all elements that

  • match that goober class and also are an input tag, or
  • are a span tag"

Screenshot of the problematic style tag in the DOM

I am not sure how to fix this, perhaps this is an issue with Goober itself.

CodeSandBox example not working

Thanks for creating a great multi-select component!

Unfortunately, the CodeSandBox example seems to be failing to render with error message: "SyntaxError: export declarations may only appear at top level of a module".

See the following screenshot for details.

image

This may not be the component's fault since it (v2.0.8) works just fine for a React app I'm working on. But the CodeSandBox example failing makes it difficult for (potential) users to quickly check it out on the browser.

Reset not working

Hi,
When i am trying to reset the form, it does not reset multi select fields..

Feature request: Managed open/close by external state and defaultOpen prop

Awesome work! Might I request a feature for 4.0?

I'd like to see a managed open/closed prop.

It could look like: <MultiSelect {...props} open={true} />. This could then be managed by external state. What would be a perfect addon to this is another prop called: defaultOpen, that when true, if the component is mounted, it opens the dropdown automatically. The defaultOpen would only work when the open prop is not passed.

Better support for keyboard interaction?

I've noticed that <MultiSelect> works quite differently from, say, a native <select> tag when using keyboard to interact with it. I think it would be great if the component can behave similarly to how <select> works.

For instance, native <select> dropdown opens when I hit spacebar while on focus. Hitting tab closes the dropdown, and hitting tab once more will move the focus to the next element.

In contrast, <MultiSelect> dropdown opens on hitting arrow down while on focus, and there is no apparent way to close it using keyboard only without losing focus.1 In fact, if I hit tab while the dropdown is open, the focus is moved to another element but the dropdown remains open. I believe this different behavior can be confusing to users other than myself.

Footnotes

  1. For your reference, with react-select's multi select component, hitting spacebar (or arrow down key) opens dropdown, and hitting escape closes dropdown without losing focus. โ†ฉ

Ability to add custom classnames

Awesome component, thanks!

It would be great if a prop className existed, that would add the specified string to the classes of the parent div.

Roadmap v4.0.0 [Will be worked on once pandemic ends ๐Ÿ˜ฌ]

Why

This component was written a year ago (when I was just starting to get hang of react) so there were many things that I didn't knew back then so after revisiting codebase today I realized that there are so many things that can be improved and that might make this tiny component even better

TODO

  • Utilize React Context API instead of Prop Drilling (might reduce bundle size even more)
  • Proper naming convention for all prop and className (kept as it is since this might break things and it's nominal)
  • Clean up unnecessary CSS properties
  • Dark Mode (Maybe) (cancelled because overriding variables are easy using css-variables)

Most changes will be done internally so migration from v3 to v4 should be mostly smooth so external changes might only be at renaming props and classes if you directly target them

Since I have a seprate job (that does not pay me to maintain this) so it might be hard to have proper fixed date for this ๐Ÿ˜…

Ability to disable options

It would be amazing if it was possible to disable options by passing a: disabled: true along with the label and value properties. Making the checkbox disabled, but still appear in the list.

Ability to use another arrow icon

To keep our application uniform, it would be nice to have the ability to change the arrow icon to the icon that we use in the rest of our app.

Click outside to close not working with itemRenderer

If 'Select All' was the most recent option selected, then the dropdown does not close when you click outside. Please see the gif below and relevant code sandbox. Notice that click-outside-to-close works well when the most recently clicked option is not the 'select all' item ๐Ÿง

bug react-multi-select-component

Call function & setSelected in onchange ?

Hello,
I would need to call another function (like handleSelectedChange) to update another state related to the setSelected.I was thinking of doing this in a function and calling it in the onChange, but unfortunately I can't figure out how to do it... Is this possible?
like :
onChange={{() => setSelected, handleSelectedChange}} ?

labelledBy prop not working

labelledBy Prop dosen't reflect any changes..show "Select" value.

<MultiSelect
  hasSelectAll={false}
  id="examClasses"
  name="examClasses"
  options={classesDropdown}
  value={values.selected}
  onChange={(e) => {
    setFieldValue("selected", [...e]);
  }}
  onBlur={handleBlur}
  labelledBy={"Select Classes"}
/>

labelledBy={"Select Classes"}/>
also tried
labelledBy = "Select Classes"

O/P
IMG :

selectProp

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.