Skip to content
This repository has been archived by the owner on Jan 15, 2021. It is now read-only.

Commit

Permalink
Feature/decouple deps (#43)
Browse files Browse the repository at this point in the history
* Remove sass

* feat(Picky): Remove virtualised support

Virtualized was bloating the bundle size. This should be opt in, not forced.

BREAKING CHANGE: Removed virtualized support

* [CI Skip] Bump to 2.0
  • Loading branch information
Aidurber authored Jul 8, 2018
1 parent f46a2a2 commit 028bb50
Show file tree
Hide file tree
Showing 12 changed files with 13,372 additions and 1,923 deletions.
99 changes: 41 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Picky ☜

Yet another React select list with virtualised option.
Yet another React select list.

[![Build Status](https://travis-ci.org/Aidurber/react-picky.svg?branch=master)](https://travis-ci.org/Aidurber/react-picky)
[![codecov](https://codecov.io/gh/Aidurber/react-picky/branch/master/graph/badge.svg)](https://codecov.io/gh/Aidurber/react-picky)
Expand Down Expand Up @@ -78,14 +78,6 @@ import 'react-picky/dist/picky.css'; // Include CSS

[![Edit mmpq6z7lr8](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/mmpq6z7lr8)

**Note** If you check the network tag in your dev tools, notice how all images aren't loaded, this is because it's a virtual list.

### With and without virtual list example

[![Edit [No virtual list] Simple example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/9462xq75wy)

An example of a large multiselect with no virtual list, note the performance difference.

## Props

```javascript
Expand All @@ -95,10 +87,8 @@ Picky.defaultProps = {
filterDebounce: 150,
dropdownHeight: 300,
onChange: () => {},
itemHeight: 35,
tabIndex: 0,
keepOpen: true,
virtual: true,
selectAllText: 'Select all'
};
Picky.propTypes = {
Expand All @@ -124,10 +114,8 @@ Picky.propTypes = {
valueKey: PropTypes.string,
labelKey: PropTypes.string,
render: PropTypes.func,
itemHeight: PropTypes.number,
tabIndex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
keepOpen: PropTypes.bool,
virtual: PropTypes.bool,
manySelectedPlaceholder: PropTypes.string,
allSelectedPlaceholder: PropTypes.string,
selectAllText: PropTypes.string,
Expand All @@ -138,32 +126,30 @@ Picky.propTypes = {

### Prop descriptions

* `placeholder` - Default message when no items are selected.
* `value` - The selected value(s), array if multiple is true. **Not needed if using as an uncontolled component**
* `numberDisplayed` - Then number of selected options displayed until it turns into '(selected count) selected'.
* `multiple` - Set to true for a multiselect, defaults to false.
* `options` - Array of possible options.
* `onChange` - Called whenever selected value(s) have changed. If you are using this as a controlled component, pass the selected value back into `value`.
* `open` - Can open or close the dropdown manually. Defaults to false.
* `includeSelectAll` - If set to `true` will add a `Select All` checkbox at the top of the list.
* `includeFilter` - If set to `true` will add an input at the top of the dropdown for filtering the results.
* `filterDebounce` - Debounce timeout, used to limit the rate the internal `onFilterChange` gets called. Defaults to 150ms.
* `dropdownHeight` - The height of the dropdown. Defaults to 300px.
* `onFiltered` - Called after a filter has been done with the filtered options.
* `onOpen` - Called after the dropdown has opened.
* `onClose` - Called after the dropdown has closed.
* `valueKey` - If supplying an array of objects as options, this is required. It's used to identify which property on the object is the value.
* `labelKey` - If supplying an array of objects as options, this is required. It's used to identify which property on the object is the label.
* `render` - Used for custom rendering of items in the dropdown. More info below.
* `itemHeight` - Used when dropdown item height is larger than 35px. This is so the virtualised list can calculate correctly.
* `tabIndex` - Pass tabIndex to component for accessibility. Defaults to 0
* `keepOpen` - Default true. Single selects close automatically when selecting a value unless this is set to true.
* `virtual` - Default true. Renders out a non-virtual list when set to false. This is for more control over dropdown height. The side-effect of this is that you lose the performance gains of a virtualised list. However, the case where shorter dropdown lists tends to be for smaller lists.
* `manySelectedPlaceholder` - Default "%s selected" where %s is the number of items selected. This gets used when the number if items selected is more than the `numberDisplayed` prop and when all options are not selected.
* `allSelectedPlaceholder` - Default "%s selected" where %s is the number of items selected. This gets used when all options are selected.
* `selectAllText` - Default "Select all", use this to override "Select all" text from top of dropdown when included with `includeSelectAll`.
* `renderSelectAll` - Used for rendering a custom select all
* `defaultFocusFilter` - If set to true, will focus the filter by default when opened.
- `placeholder` - Default message when no items are selected.
- `value` - The selected value(s), array if multiple is true. **Not needed if using as an uncontolled component**
- `numberDisplayed` - Then number of selected options displayed until it turns into '(selected count) selected'.
- `multiple` - Set to true for a multiselect, defaults to false.
- `options` - Array of possible options.
- `onChange` - Called whenever selected value(s) have changed. If you are using this as a controlled component, pass the selected value back into `value`.
- `open` - Can open or close the dropdown manually. Defaults to false.
- `includeSelectAll` - If set to `true` will add a `Select All` checkbox at the top of the list.
- `includeFilter` - If set to `true` will add an input at the top of the dropdown for filtering the results.
- `filterDebounce` - Debounce timeout, used to limit the rate the internal `onFilterChange` gets called. Defaults to 150ms.
- `dropdownHeight` - The height of the dropdown. Defaults to 300px.
- `onFiltered` - Called after a filter has been done with the filtered options.
- `onOpen` - Called after the dropdown has opened.
- `onClose` - Called after the dropdown has closed.
- `valueKey` - If supplying an array of objects as options, this is required. It's used to identify which property on the object is the value.
- `labelKey` - If supplying an array of objects as options, this is required. It's used to identify which property on the object is the label.
- `render` - Used for custom rendering of items in the dropdown. More info below.
- `tabIndex` - Pass tabIndex to component for accessibility. Defaults to 0
- `keepOpen` - Default true. Single selects close automatically when selecting a value unless this is set to true.
- `manySelectedPlaceholder` - Default "%s selected" where %s is the number of items selected. This gets used when the number if items selected is more than the `numberDisplayed` prop and when all options are not selected.
- `allSelectedPlaceholder` - Default "%s selected" where %s is the number of items selected. This gets used when all options are selected.
- `selectAllText` - Default "Select all", use this to override "Select all" text from top of dropdown when included with `includeSelectAll`.
- `renderSelectAll` - Used for rendering a custom select all
- `defaultFocusFilter` - If set to true, will focus the filter by default when opened.

## Custom rendering

Expand All @@ -185,7 +171,6 @@ You can render out custom items for the dropdown.
includeSelectAll={true}
includeFilter={true}
dropdownHeight={600}
itemHeight={50}
render={({
style,
isSelected,
Expand Down Expand Up @@ -214,18 +199,17 @@ You can render out custom items for the dropdown.
The render callback gets called with the following properties:
style, isSelected, item, labelKey, valueKey, selectValue, multiple

* `style` - object - used by react-tiny-virtual-list for rendering out the items. It needs these to calculate the items location and size. This is required.
* `isSelected` - boolean - true if item is selected. Use this for styling accordingly.
* `item` - object | number | string - The item to render.
* `labelKey` - Used to get the label if item is an object
* `valueKey` - Used to get the value if item is an object, good for keys.
* `selectValue` - function(item) - Selects the item on click
* `multiple` - boolean - Indicates if is a multiselect.
- `isSelected` - boolean - true if item is selected. Use this for styling accordingly.
- `item` - object | number | string - The item to render.
- `labelKey` - Used to get the label if item is an object
- `valueKey` - Used to get the value if item is an object, good for keys.
- `selectValue` - function(item) - Selects the item on click
- `multiple` - boolean - Indicates if is a multiselect.

**Note**

* If your rendered item affects the height of the item in anyway. Supply `itemHeight` to Picky.
* If you wish to show a radio button or a checkbox, be sure to add `readOnly` prop to the input.
- If your rendered item affects the height of the item in anyway. Supply `itemHeight` to Picky.
- If you wish to show a radio button or a checkbox, be sure to add `readOnly` prop to the input.

### Select All

Expand Down Expand Up @@ -259,16 +243,18 @@ style, isSelected, item, labelKey, valueKey, selectValue, multiple

Gets called with the following properties:

* `filtered`: boolean - true if items have been filtered.
* `allSelected`: boolean true if all items are selected.
* `toggleSelectAll`: function selects or deselects all items.
* `tabIndex`: number used for specifying tab index.
* `multiple`: boolean true if multiselect.
- `filtered`: boolean - true if items have been filtered.
- `allSelected`: boolean true if all items are selected.
- `toggleSelectAll`: function selects or deselects all items.
- `tabIndex`: number used for specifying tab index.
- `multiple`: boolean true if multiselect.

# styled-components support
Support is pretty basic by allowing a `className` prop to `<Picky>`, so as a side effect you can add a custom class to the core Picky for easier style overrides.

Support is pretty basic by allowing a `className` prop to `<Picky>`, so as a side effect you can add a custom class to the core Picky for easier style overrides.

**Usage**

```javascript
const Select = styled(Picky)`
background-color: #ff0000;
Expand All @@ -278,6 +264,3 @@ const Select = styled(Picky)`
}
`;
```
# Internals

The component uses [React Virtualized](https://github.com/bvaughn/react-virtualized) for rendering out the items. This is a for a performance gain. You can have 1,000,000 items in the dropdown with no performance drop! It's such a great little library. This is why we have a dropdown height.
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

210 changes: 111 additions & 99 deletions dist/picky.css
Original file line number Diff line number Diff line change
@@ -1,99 +1,111 @@
.picky {
width: 100%;
position: relative; }
.picky * {
box-sizing: border-box; }
.picky__input {
width: 100%;
background-color: white;
border: 0;
border-width: 1px;
border-color: #eee;
border-style: solid;
border-radius: 2px;
padding: 5px;
text-align: left;
position: relative;
box-sizing: border-box;
height: 38px; }
.picky__input::after {
position: absolute;
width: 0;
height: 0;
margin-left: 2px;
vertical-align: middle;
border-top: 4px solid;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
content: '';
right: 16px;
top: 16px; }
.picky__dropdown {
-webkit-touch-callout: none;
/* iOS Safari */
-webkit-user-select: none;
/* Safari */
-khtml-user-select: none;
/* Konqueror HTML */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently supported by Chrome and Opera */
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 99;
background: white;
border-left: 1px solid #eee;
border-right: 1px solid #eee;
border-bottom: 1px solid #eee;
top: 39px; }
.picky__dropdown .option,
.picky__dropdown li {
list-style: none;
background-color: white;
-webkit-touch-callout: none;
/* iOS Safari */
-webkit-user-select: none;
/* Safari */
-khtml-user-select: none;
/* Konqueror HTML */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently supported by Chrome and Opera */
padding: 0.5em;
cursor: pointer;
border-bottom: 1px solid #eee;
text-align: left; }
.picky__dropdown .option:hover,
.picky__dropdown li:hover {
background-color: #ecf0f1; }
.picky__dropdown .option.selected,
.picky__dropdown li.selected {
background-color: #ecf0f1; }
.picky__dropdown .option:focus,
.picky__dropdown li:focus {
outline: -webkit-focus-ring-color auto 5px !important; }
.picky__dropdown .option input[type='checkbox'],
.picky__dropdown .option input[type='radio'],
.picky__dropdown li input[type='checkbox'],
.picky__dropdown li input[type='radio'] {
margin-right: 3px; }
.picky__filter {
display: flex;
width: 100%;
padding: 3px; }
.picky__filter__input {
width: 100%;
padding: 3px;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
position: relative;
height: 30px; }
.picky {
width: 100%;
position: relative;
}
.picky * {
box-sizing: border-box;
}
.picky__input {
width: 100%;
background-color: white;
border: 0;
border-width: 1px;
border-color: #eee;
border-style: solid;
border-radius: 2px;
padding: 5px;
text-align: left;
position: relative;
box-sizing: border-box;
height: 38px;
}
.picky__input::after {
position: absolute;
width: 0;
height: 0;
margin-left: 2px;
vertical-align: middle;
border-top: 4px solid;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
content: '';
right: 16px;
top: 16px;
}
.picky__dropdown {
-webkit-touch-callout: none;
/* iOS Safari */
-webkit-user-select: none;
/* Safari */
-khtml-user-select: none;
/* Konqueror HTML */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently supported by Chrome and Opera */
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 99;
background: white;
border-left: 1px solid #eee;
border-right: 1px solid #eee;
border-bottom: 1px solid #eee;
top: 39px;
}
.picky__dropdown .option,
.picky__dropdown li {
list-style: none;
background-color: white;
-webkit-touch-callout: none;
/* iOS Safari */
-webkit-user-select: none;
/* Safari */
-khtml-user-select: none;
/* Konqueror HTML */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently supported by Chrome and Opera */
padding: 0.5em;
cursor: pointer;
border-bottom: 1px solid #eee;
text-align: left;
}
.picky__dropdown .option:hover,
.picky__dropdown li:hover {
background-color: #ecf0f1;
}
.picky__dropdown .option.selected,
.picky__dropdown li.selected {
background-color: #ecf0f1;
}
.picky__dropdown .option:focus,
.picky__dropdown li:focus {
outline: -webkit-focus-ring-color auto 5px !important;
}
.picky__dropdown .option input[type='checkbox'],
.picky__dropdown .option input[type='radio'],
.picky__dropdown li input[type='checkbox'],
.picky__dropdown li input[type='radio'] {
margin-right: 3px;
}
.picky__filter {
display: flex;
width: 100%;
padding: 3px;
}
.picky__filter__input {
width: 100%;
padding: 3px;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
position: relative;
height: 30px;
}
Loading

0 comments on commit 028bb50

Please sign in to comment.