react-tag-autocomplete
Advanced tools
Comparing version 6.0.0-beta.1 to 6.0.0-beta.2
@@ -21,2 +21,6 @@ # Changelog | ||
## 5.11.2 | ||
- Fixed an issue with the delimiter key logic which would attempt to add a previously selected suggestion even when it was no longer in the suggestion list. | ||
## 5.11.1 | ||
@@ -23,0 +27,0 @@ |
@@ -186,3 +186,3 @@ 'use strict'; | ||
if (index > -1) { | ||
if (index > -1 && this.state.options[index]) { | ||
this.addTag(this.state.options[index]); | ||
@@ -218,9 +218,10 @@ } else if (this.props.allowNew) { | ||
function filterSuggestions (query, suggestions, suggestionsFilter) { | ||
if (!suggestionsFilter) { | ||
const regexp = matchPartial(query); | ||
suggestionsFilter = (item) => regexp.test(item.name); | ||
} | ||
function defaultSuggestionsFilter (item, query) { | ||
const regexp = matchPartial(query); | ||
return regexp.test(item.name) | ||
} | ||
return suggestions.filter((item) => suggestionsFilter(item, query)) | ||
function getOptions (query) { | ||
const filtered = this.props.suggestions.filter((item) => this.props.suggestionsFilter(item, query)); | ||
return filtered.slice(0, this.props.maxSuggestionsLength) | ||
} | ||
@@ -235,3 +236,3 @@ | ||
focused: false, | ||
options: [], | ||
options: getOptions.call(this, ''), | ||
index: -1 | ||
@@ -263,5 +264,3 @@ }; | ||
if (query !== this.state.query) { | ||
const filtered = filterSuggestions(query, this.props.suggestions, this.props.suggestionsFilter); | ||
const options = filtered.slice(0, this.props.maxSuggestionsLength); | ||
const options = getOptions.call(this, query); | ||
this.setState({ query, options }); | ||
@@ -332,7 +331,3 @@ } | ||
// reset the state | ||
this.setState({ | ||
query: '', | ||
index: -1 | ||
}); | ||
this.clearInput(); | ||
} | ||
@@ -345,3 +340,7 @@ | ||
clearInput () { | ||
this.setState({ query: '' }); | ||
this.setState({ | ||
query: '', | ||
index: -1, | ||
options: getOptions.call(this, '') | ||
}); | ||
} | ||
@@ -383,3 +382,3 @@ | ||
suggestions: [], | ||
suggestionsFilter: null, | ||
suggestionsFilter: defaultSuggestionsFilter, | ||
autoresize: true, | ||
@@ -386,0 +385,0 @@ classNames: CLASS_NAMES, |
@@ -182,3 +182,3 @@ import React from 'react'; | ||
if (index > -1) { | ||
if (index > -1 && this.state.options[index]) { | ||
this.addTag(this.state.options[index]); | ||
@@ -214,9 +214,10 @@ } else if (this.props.allowNew) { | ||
function filterSuggestions (query, suggestions, suggestionsFilter) { | ||
if (!suggestionsFilter) { | ||
const regexp = matchPartial(query); | ||
suggestionsFilter = (item) => regexp.test(item.name); | ||
} | ||
function defaultSuggestionsFilter (item, query) { | ||
const regexp = matchPartial(query); | ||
return regexp.test(item.name) | ||
} | ||
return suggestions.filter((item) => suggestionsFilter(item, query)) | ||
function getOptions (query) { | ||
const filtered = this.props.suggestions.filter((item) => this.props.suggestionsFilter(item, query)); | ||
return filtered.slice(0, this.props.maxSuggestionsLength) | ||
} | ||
@@ -231,3 +232,3 @@ | ||
focused: false, | ||
options: [], | ||
options: getOptions.call(this, ''), | ||
index: -1 | ||
@@ -259,5 +260,3 @@ }; | ||
if (query !== this.state.query) { | ||
const filtered = filterSuggestions(query, this.props.suggestions, this.props.suggestionsFilter); | ||
const options = filtered.slice(0, this.props.maxSuggestionsLength); | ||
const options = getOptions.call(this, query); | ||
this.setState({ query, options }); | ||
@@ -328,7 +327,3 @@ } | ||
// reset the state | ||
this.setState({ | ||
query: '', | ||
index: -1 | ||
}); | ||
this.clearInput(); | ||
} | ||
@@ -341,3 +336,7 @@ | ||
clearInput () { | ||
this.setState({ query: '' }); | ||
this.setState({ | ||
query: '', | ||
index: -1, | ||
options: getOptions.call(this, '') | ||
}); | ||
} | ||
@@ -379,3 +378,3 @@ | ||
suggestions: [], | ||
suggestionsFilter: null, | ||
suggestionsFilter: defaultSuggestionsFilter, | ||
autoresize: true, | ||
@@ -382,0 +381,0 @@ classNames: CLASS_NAMES, |
@@ -223,3 +223,3 @@ (function (global, factory) { | ||
if (index > -1) { | ||
if (index > -1 && this.state.options[index]) { | ||
this.addTag(this.state.options[index]); | ||
@@ -255,9 +255,12 @@ } else if (this.props.allowNew) { | ||
function filterSuggestions (query, suggestions, suggestionsFilter) { | ||
if (!suggestionsFilter) { | ||
var regexp = matchPartial(query); | ||
suggestionsFilter = function (item) { return regexp.test(item.name); }; | ||
} | ||
function defaultSuggestionsFilter (item, query) { | ||
var regexp = matchPartial(query); | ||
return regexp.test(item.name) | ||
} | ||
return suggestions.filter(function (item) { return suggestionsFilter(item, query); }) | ||
function getOptions (query) { | ||
var this$1 = this; | ||
var filtered = this.props.suggestions.filter(function (item) { return this$1.props.suggestionsFilter(item, query); }); | ||
return filtered.slice(0, this.props.maxSuggestionsLength) | ||
} | ||
@@ -272,3 +275,3 @@ | ||
focused: false, | ||
options: [], | ||
options: getOptions.call(this, ''), | ||
index: -1 | ||
@@ -304,5 +307,3 @@ }; | ||
if (query !== this.state.query) { | ||
var filtered = filterSuggestions(query, this.props.suggestions, this.props.suggestionsFilter); | ||
var options = filtered.slice(0, this.props.maxSuggestionsLength); | ||
var options = getOptions.call(this, query); | ||
this.setState({ query: query, options: options }); | ||
@@ -373,7 +374,3 @@ } | ||
// reset the state | ||
this.setState({ | ||
query: '', | ||
index: -1 | ||
}); | ||
this.clearInput(); | ||
}; | ||
@@ -386,3 +383,7 @@ | ||
ReactTags.prototype.clearInput = function clearInput () { | ||
this.setState({ query: '' }); | ||
this.setState({ | ||
query: '', | ||
index: -1, | ||
options: getOptions.call(this, '') | ||
}); | ||
}; | ||
@@ -428,3 +429,3 @@ | ||
suggestions: [], | ||
suggestionsFilter: null, | ||
suggestionsFilter: defaultSuggestionsFilter, | ||
autoresize: true, | ||
@@ -431,0 +432,0 @@ classNames: CLASS_NAMES, |
{ | ||
"name": "react-tag-autocomplete", | ||
"version": "6.0.0-beta.1", | ||
"version": "6.0.0-beta.2", | ||
"description": "React Tag Autocomplete is a simple tagging component ready to drop in your React projects.", | ||
@@ -49,11 +49,11 @@ "main": "dist/ReactTags.cjs.js", | ||
"jasmine": "^3.3.0", | ||
"jsdom": "^14.0.0", | ||
"nyc": "^13.3.0", | ||
"jsdom": "^15.1.0", | ||
"nyc": "^14.1.0", | ||
"prop-types": "^15.7.0", | ||
"react": "^16.8.0", | ||
"react-dom": "^16.8.0", | ||
"rollup": "^1.7.0", | ||
"react": "^16.10.0", | ||
"react-dom": "^16.10.0", | ||
"rollup": "^1.22.0", | ||
"rollup-plugin-buble": "^0.19.6", | ||
"rollup-plugin-commonjs": "^9.2.0", | ||
"rollup-plugin-node-resolve": "^4.0.0", | ||
"rollup-plugin-commonjs": "^10.1.0", | ||
"rollup-plugin-node-resolve": "^5.2.0", | ||
"rollup-plugin-replace": "^2.1.0", | ||
@@ -60,0 +60,0 @@ "rollup-plugin-serve": "^1.0.0", |
131
README.md
@@ -5,3 +5,3 @@ # React Tag Autocomplete | ||
React Tag Autocomplete is a simple tagging component ready to drop in your React projects. Originally based on the [React Tags project](http://prakhar.me/react-tags/example) by Prakhar Srivastav this version removes the drag-and-drop re-ordering functionality, adds appropriate roles and ARIA states and introduces a resizing text input. React Tag Autocomplete is compatible with [Preact](https://preactjs.com/) >= 6.0.0. | ||
React Tag Autocomplete is a simple tagging component ready to drop in your React projects. Originally based on the [React Tags project](http://prakhar.me/react-tags/example) by Prakhar Srivastav this version removes the drag-and-drop re-ordering functionality, adds appropriate roles and ARIA states and introduces a resizing text input. | ||
@@ -14,4 +14,6 @@ **Please note, this version is in beta, you can check out the [latest stable version here](https://github.com/i-like-robots/react-tags)** 📢 | ||
The preferred way of using the component is via npm. | ||
This is a [Node.js] module available through the [npm] registry. Before installing, download and install Node.js. | ||
Installation is done using the [npm install] command: | ||
``` | ||
@@ -21,10 +23,14 @@ npm install --save react-tag-autocomplete@pre-release | ||
[Node.js]: https://nodejs.org/en/ | ||
[npm]: https://www.npmjs.com/ | ||
[npm install]: https://docs.npmjs.com/getting-started/installing-npm-packages-locally | ||
## Usage | ||
Here's a sample implementation that initializes the component with a list of preselected `tags` and a `suggestions` list. For more details, go through the [API](#Options). | ||
Here's a sample implementation that initializes the component with a list of preselected `tags` and a `suggestions` list. For further customization details, see [options](#options). | ||
```js | ||
const React = require('react') | ||
const ReactDOM = require('react-dom') | ||
const ReactTags = require('react-tag-autocomplete') | ||
import React from 'react' | ||
import ReactDOM from 'react-dom' | ||
import ReactTags from 'react-tag-autocomplete' | ||
@@ -74,2 +80,3 @@ class App extends React.Component { | ||
### Options | ||
@@ -80,5 +87,5 @@ | ||
- [`suggestions`](#suggestions-optional) | ||
- [`suggestionsFilter`](#suggestionsFilter-optional) | ||
- [`placeholderText`](#placeholderText-optional) | ||
- [`removeButtonText`](#removeButtonText-optional) | ||
- [`suggestionsFilter`](#suggestionsfilter-optional) | ||
- [`placeholderText`](#placeholdertext-optional) | ||
- [`removeButtonText`](#removeButtontext-optional) | ||
- [`autoresize`](#autoresize-optional) | ||
@@ -107,8 +114,8 @@ - [`delimiters`](#delimiters-optional) | ||
An array of tags that are displayed as pre-selected. Each tag must have an `id` and a `name` property. Default: `[]`. | ||
An array of selected tags. Each tag is an object which must have an `id` and a `name` property. Defaults to `[]`. | ||
```js | ||
const tags = [ | ||
{ id: 1, name: "Apples" }, | ||
{ id: 2, name: "Pears" } | ||
{ id: 1, name: 'Apples' }, | ||
{ id: 2, name: 'Pears' } | ||
] | ||
@@ -119,10 +126,10 @@ ``` | ||
An array of suggestions that are used as basis for showing suggestions. Each suggestion must have an `id` and a `name` property and an optional `disabled` property. Default: `[]`. | ||
An array of tag suggestions. Each suggestion is an object which must have an `id` and a `name` property and an optional `disabled` property to make the suggestion non-selectable. Defaults to `[]`. | ||
```js | ||
const suggestions = [ | ||
{ id: 3, name: "Bananas" }, | ||
{ id: 4, name: "Mangos" }, | ||
{ id: 5, name: "Lemons" }, | ||
{ id: 6, name: "Apricots", disabled: true } | ||
{ id: 3, name: 'Bananas' }, | ||
{ id: 4, name: 'Mangos' }, | ||
{ id: 5, name: 'Lemons' }, | ||
{ id: 6, name: 'Apricots', disabled: true } | ||
] | ||
@@ -135,18 +142,7 @@ ``` | ||
If no function is supplied the default filter is applied. Default: `null`. | ||
If no function is supplied the default filter is applied. Defaults to `null`. | ||
Below is an example of a function which returns items containing `query`: | ||
```js | ||
import stringScore from 'string-score' | ||
function suggestionsFilter(item, query) { | ||
const score = stringScore(item.name, query) | ||
return score > 0.5 | ||
} | ||
``` | ||
#### placeholderText (optional) | ||
The input placeholder text displayed when no text has been entered. Default: `'Add new tag'`. | ||
The placeholder string shown for the input. Defaults to `'Add new tag'`. | ||
@@ -159,19 +155,19 @@ #### removeButtonText (optional) | ||
Boolean parameter to control whether the text-input should be automatically resized to fit its value. Default: `true`. | ||
Boolean parameter to control whether the text-input should be automatically resized to fit its value. Defaults to `true`. | ||
#### delimiters (optional) | ||
Array of keys matching keyboard event `key` values. When a corresponding key is pressed, the preceding string is finalised as tag. Default: `['Enter', 'Tab']`. | ||
Array of keys matching `KeyboardEvent.key` values. When a corresponding key is pressed it will trigger tag selection or creation. Defaults to `['Enter', 'Tab']`. | ||
#### minQueryLength (optional) | ||
How many characters are needed for suggestions to appear. Default: `2`. | ||
Minimum query length required to show the suggestions list. Defaults to `2`. | ||
#### maxSuggestionsLength (optional) | ||
Maximum number of suggestions to display. Default: `6`. | ||
Maximum number of suggestions to display. Defaults to `6`. | ||
#### classNames (optional) | ||
Override the default class names. Defaults: | ||
Override the default class names used by the component. Defaults to: | ||
@@ -200,4 +196,4 @@ ```js | ||
function onAddition(tag) { | ||
// Add the tag { id, name } to the tag list | ||
tags.push(tag) | ||
const tags = [...this.state.tags, tag] | ||
this.setState({ tags }) | ||
} | ||
@@ -212,4 +208,5 @@ ``` | ||
function onDelete(i) { | ||
// Delete the tag at index i | ||
const tags = this.state.tags.slice(0) | ||
tags.splice(i, 1) | ||
this.setState({ tags }) | ||
} | ||
@@ -220,10 +217,10 @@ ``` | ||
Optional event handler when the input changes. Receives the current input value. | ||
Optional event handler when the input value changes. Receives the current query. | ||
```js | ||
function onInput(input) { | ||
function onInput(query) { | ||
if (!this.state.busy) { | ||
this.setState({ busy: true }) | ||
return fetch(`query=${input}`).then((result) => { | ||
return fetch(`query=${query}`).then((result) => { | ||
this.setState({ busy: false }) | ||
@@ -237,11 +234,11 @@ }) | ||
Optional event handler when the input receives focus. Receives no arguments. | ||
Optional callback function for when the input receives focus. Receives no arguments. | ||
#### onBlur (optional) | ||
Optional event handler when focus on the input is lost. Receives no arguments. | ||
Optional callback function for when focus on the input is lost. Receives no arguments. | ||
#### onValidate (optional) | ||
Optional validation function that determines if tag should be added to tags. Receives a tag object. Should return a boolean. | ||
Optional validation function that determines if tag should be added. Receives the tag object and must return a boolean. | ||
@@ -256,15 +253,15 @@ ```js | ||
Creates a tag from the current input value when focus on the input is lost. Default: `false`. | ||
Creates a tag from the current input value when focus on the input is lost. Defaults to `false`. | ||
#### allowNew (optional) | ||
Allows users to add new (not suggested) tags. Default: `false`. | ||
Enable users to add new (not suggested) tags. Defaults to `false`. | ||
#### allowBackspace (optional) | ||
Disables ability to delete the selected tags when backspace is pressed while focussed on the text input. Default: `true`. | ||
Enable users to delete selected tags when backspace is pressed while focussed on the text input when empty. Defaults to `true`. | ||
#### tagComponent (optional) | ||
Provide a custom tag component to render. Default: `null`. | ||
Provide a custom tag component to render. Defaults to `null`. | ||
@@ -277,5 +274,4 @@ #### suggestionComponent (optional) | ||
An object containing additional attributes that will be applied to the underlying text `<input />` field. | ||
An object containing additional attributes that will be applied to the text input. _Please note_ that this prop cannot overwrite existing attributes, it can only add new ones. Defaults to `{}`. | ||
As an example `inputAttributes={{ maxLength: 10 }}` would be applied as `<input maxlength="10" … />`. Note this prop won't overwrite existing attributes, it can only add new ones. | ||
@@ -292,4 +288,5 @@ ### API | ||
It is possible to customize the look of the component the way you want it. An example can be found in `/example/styles.css`. | ||
It is possible to customize the appearance of the component, the included styles found in `/example/styles.css` are only an example. | ||
### Development | ||
@@ -310,34 +307,8 @@ | ||
- React 16.3 or above is now required. | ||
- React 16.5 or above is now required. | ||
- Event handlers and callbacks have been renamed to use `on` prefixes, e.g. the `handleAddition()` callback should now be called `onAddition()`. | ||
- The `delimiters` option is now an array of `KeyboardEvent.key` values and not `KeyboardEvent.keyCode` codes, e.g. `[13, 9]` should now be written as `['Enter', 'Tab']`. See https://keycode.info/ for more information. | ||
- The `placeholder` option has been renamed `placeholderText` | ||
- The `delimiterChars` option has been removed, use the `delimiters` option instead. | ||
- The `clearInputOnDelete` option has been removed and is now the default behaviour | ||
- The `autofocus` option has been removed. | ||
#### Upgrading from 4.x to 5.x | ||
1. The `delimiters` option has been removed, any references to this will now be ignored. | ||
2. The `classNames` option has been updated: | ||
```udiff | ||
{ | ||
- root: 'ReactTags', | ||
- tagInput: 'ReactTags__tagInput', | ||
- selected: 'ReactTags__selected', | ||
- tag: 'ReactTags__tag', | ||
- tagName: 'ReactTags__tagName', | ||
- suggestions: 'ReactTags__suggestions', | ||
- isActive: 'is-active', | ||
- isDisabled: 'is-disabled' | ||
+ root: 'react-tags', | ||
+ rootFocused: 'is-focused', | ||
+ selected: 'react-tags__selected', | ||
+ selectedTag: 'react-tags__selected-tag', | ||
+ selectedTagName: 'react-tags__selected-tag-name', | ||
+ search: 'react-tags__search', | ||
+ searchInput: 'react-tags__search-input', | ||
+ suggestions: 'react-tags__suggestions', | ||
+ suggestionActive: 'is-active', | ||
+ suggestionDisabled: 'is-disabled' | ||
} | ||
``` |
1087
55760
298