{"id":13459067,"url":"https://github.com/i-like-robots/react-tags","last_synced_at":"2025-04-08T13:14:16.998Z","repository":{"id":5667459,"uuid":"51769887","full_name":"i-like-robots/react-tags","owner":"i-like-robots","description":"⚛️ Legacy repo for the fantastically simple tagging component for your React projects (legacy repo)","archived":false,"fork":false,"pushed_at":"2024-06-19T14:57:39.000Z","size":6024,"stargazers_count":457,"open_issues_count":11,"forks_count":170,"subscribers_count":8,"default_branch":"main","last_synced_at":"2024-10-29T17:32:05.626Z","etag":null,"topics":["autocomplete","preact","preact-components","react","react-component","tagging"],"latest_commit_sha":null,"homepage":"http://i-like-robots.github.io/react-tags","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/i-like-robots.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-02-15T16:48:10.000Z","updated_at":"2024-08-21T11:05:48.000Z","dependencies_parsed_at":"2024-01-13T17:58:07.813Z","dependency_job_id":"702b7aac-6db3-4708-83ea-a1a68085e726","html_url":"https://github.com/i-like-robots/react-tags","commit_stats":{"total_commits":492,"total_committers":41,"mean_commits":12.0,"dds":0.5548780487804879,"last_synced_commit":"d6d8145bfac18474d923bd33b74f0bac1d7a7a0d"},"previous_names":[],"tags_count":65,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i-like-robots%2Freact-tags","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i-like-robots%2Freact-tags/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i-like-robots%2Freact-tags/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i-like-robots%2Freact-tags/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/i-like-robots","download_url":"https://codeload.github.com/i-like-robots/react-tags/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247847611,"owners_count":21006100,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["autocomplete","preact","preact-components","react","react-component","tagging"],"created_at":"2024-07-31T09:01:02.535Z","updated_at":"2025-04-08T13:14:16.973Z","avatar_url":"https://github.com/i-like-robots.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# React Tag Autocomplete\n\n[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/i-like-robots/react-tags/blob/main/LICENSE) ![build status](https://github.com/i-like-robots/react-tags/actions/workflows/test.yml/badge.svg?branch=main) [![Coverage Status](https://coveralls.io/repos/github/i-like-robots/react-tags/badge.svg?branch=main)](https://coveralls.io/github/i-like-robots/react-tags?branch=main) [![npm version](https://img.shields.io/npm/v/react-tag-autocomplete/legacy.svg?style=flat)](https://www.npmjs.com/package/react-tag-autocomplete)\n\nReact 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. [View demo](http://i-like-robots.github.io/react-tags/).\n\n![Screenshot of React Tag Autocomplete](https://cloud.githubusercontent.com/assets/271645/25478773/54aa2bbe-2b3a-11e7-95cf-d419f3c24418.png)\n\n**_Please note:_ This repository is for v6 and older versions of this component. For later releases, compatible with React v18+, please go to [the new repository](https://github.com/i-like-robots/react-tag-autocomplete).**\n\n## Installation\n\nThis is a [Node.js] module available through the [npm] registry. Before installing, download and install Node.js.\n\nInstallation is done using the [npm install] command:\n\n```\nnpm install --save react-tag-autocomplete@legacy\n```\n\n[Node.js]: https://nodejs.org/en/\n[npm]: https://www.npmjs.com/\n[npm install]: https://docs.npmjs.com/getting-started/installing-npm-packages-locally\n\n## Usage\n\nHere's a sample implementation that initializes the component with an empty list of `tags` and a pre-populated list of `suggestions`. For further customization details, see [options](#options).\n\n```js\nimport React, { useCallback, useRef, useState } from 'react'\nimport ReactTags from 'react-tag-autocomplete'\n\nfunction App () {\n  const [tags, setTags] = useState([])\n\n  const [suggestions, setSuggestions] = useState([\n    { id: 1, name: \"Apples\" },\n    { id: 2, name: \"Pears\" },\n    { id: 3, name: \"Bananas\" },\n    { id: 4, name: \"Mangos\" },\n    { id: 5, name: \"Lemons\" },\n    { id: 6, name: \"Apricots\" }\n  ])\n\n  const reactTags = useRef()\n\n  const onDelete = useCallback((tagIndex) =\u003e {\n    setTags(tags.filter((_, i) =\u003e i !== tagIndex))\n  }, [tags])\n\n  const onAddition = useCallback((newTag) =\u003e {\n    setTags([...tags, newTag])\n  }, [tags])\n\n  return (\n    \u003cReactTags\n      ref={reactTags}\n      tags={tags}\n      suggestions={suggestions}\n      onDelete={onDelete}\n      onAddition={onAddition}\n    /\u003e\n  )\n}\n```\n\n### Options\n\n- [`id`](#id-optional)\n- [`tags`](#tags-optional)\n- [`suggestions`](#suggestions-optional)\n- [`suggestionsFilter`](#suggestionsfilter-optional)\n- [`suggestionsTransform`](#suggestionsTransform-optional)\n- [`placeholderText`](#placeholdertext-optional)\n- [`ariaLabelText`](#arialabeltext-optional)\n- [`removeButtonText`](#removeButtontext-optional)\n- [`noSuggestionsText`](#noSuggestionsText-optional)\n- [`newTagText`](#newtagtext-optional)\n- [`autoresize`](#autoresize-optional)\n- [`delimiters`](#delimiters-optional)\n- [`minQueryLength`](#minquerylength-optional)\n- [`maxSuggestionsLength`](#maxsuggestionslength-optional)\n- [`classNames`](#classnames-optional)\n- [`onAddition`](#onaddition-required)\n- [`onDelete`](#ondelete-required)\n- [`onInput`](#oninput-optional)\n- [`onFocus`](#onfocus-optional)\n- [`onBlur`](#onblur-optional)\n- [`onValidate`](#onvalidate-optional)\n- [`addOnBlur`](#addonblur-optional)\n- [`allowNew`](#allownew-optional)\n- [`allowBackspace`](#allowbackspace-optional)\n- [`tagComponent`](#tagcomponent-optional)\n- [`suggestionComponent`](#suggestioncomponent-optional)\n- [`inputAttributes`](#inputAttributes-optional)\n\n#### id (optional)\n\nThe ID attribute given to the listbox element. Default: `ReactTags`.\n\n#### tags (optional)\n\nAn array of selected tags. Each tag is an object which must have an `id` and a `name` property. Defaults to `[]`.\n\n```js\nconst tags =  [\n  { id: 1, name: 'Apples' },\n  { id: 2, name: 'Pears' }\n]\n```\n\n#### suggestions (optional)\n\nAn 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 `[]`.\n\n```js\nconst suggestions = [\n  { id: 3, name: 'Bananas' },\n  { id: 4, name: 'Mangos' },\n  { id: 5, name: 'Lemons' },\n  { id: 6, name: 'Apricots', disabled: true }\n]\n```\n\n#### suggestionsFilter (optional)\n\nA callback function to filter suggestion items with. The callback receives two arguments; a `suggestion` and the current `query` and must return a boolean value.\n\nIf no function is supplied the default filter is applied. Defaults to `null`.\n\n**Note:** This filter will be ignored if [suggestionsTransform](#suggestionsTransform-optional) is supplied.\n\n#### suggestionsTransform (optional)\n\nA callback function to apply a custom filter to the suggestions. The callback receives two arguments; a `query` and the input [suggestions](#suggestions-optional) and must return a new array of suggestion items. Using this option you can filter and sort suggestions.\n\n**Note:** This will supersede [suggestionsFilter](#suggestionsfilter-optional) in future.\n\n```js\nimport matchSorter from \"match-sorter\";\n\nfunction suggestionsFilter(query, suggestions) {\n  return matchSorter(suggestions, query, { keys: [\"name\"] });\n}\n```\n\n#### placeholderText (optional)\n\nThe placeholder string shown for the input. Defaults to `'Add new tag'`.\n\n#### ariaLabelText (optional)\n\nThe aria-label string for the input. Defaults to placeholder string.\n\n#### removeButtonText (optional)\n\nThe title text to add to the remove selected tag button. Default `'Click to remove tag'`.\n\n#### noSuggestionsText (optional)\n\nMessage shown if there are no matching suggestions. Defaults to `null`.\n\n#### newTagText (optional)\n\nEnables users to show a prompt to add a new tag at the bottom of the suggestions list if `allowNew` is enabled. Defaults to `null`.\n\n#### autoresize (optional)\n\nBoolean parameter to control whether the text-input should be automatically resized to fit its value. Defaults to `true`.\n\n#### delimiters (optional)\n\nArray of keys matching `KeyboardEvent.key` values. When a corresponding key is pressed it will trigger tag selection or creation. Defaults to `['Enter', 'Tab']`.\n\n#### minQueryLength (optional)\n\nMinimum query length required to show the suggestions list. Defaults to `2`.\n\n#### maxSuggestionsLength (optional)\n\nMaximum number of suggestions to display. Defaults to `6`.\n\n#### classNames (optional)\n\nOverride the default class names used by the component. Defaults to:\n\n```js\n{\n  root: 'react-tags',\n  rootFocused: 'is-focused',\n  selected: 'react-tags__selected',\n  selectedTag: 'react-tags__selected-tag',\n  selectedTagName: 'react-tags__selected-tag-name',\n  search: 'react-tags__search',\n  searchWrapper: 'react-tags__search-wrapper',\n  searchInput: 'react-tags__search-input',\n  suggestions: 'react-tags__suggestions',\n  suggestionActive: 'is-active',\n  suggestionDisabled: 'is-disabled',\n  suggestionPrefix: 'react-tags__suggestion-prefix'\n}\n```\n\n#### onAddition (required)\n\nFunction called when the user wants to add a tag. Receives the tag.\n\n```js\nconst [tags, setTags] = useState([])\n\nfunction onAddition (newTag) {\n  setTags([...tags, newTag])\n}\n```\n\n#### onDelete (required)\n\nFunction called when the user wants to delete a tag. Receives the tag index.\n\n```js\nconst [tags, setTags] = useState([])\n\nfunction onDelete (tagIndex) {\n  setTags(tags.filter((_, i) =\u003e i !== tagIndex))\n}\n```\n\n#### onInput (optional)\n\nOptional event handler when the input value changes. Receives the current query.\n\n```js\nconst [isBusy, setIsBusy] = useState(false)\n\nfunction onInput (query) {\n  if (!isBusy) {\n    setIsBusy(true)\n\n    return fetch(`?query=${query}`).then((result) =\u003e {\n      setIsBusy(false)\n    })\n  }\n}\n```\n\n#### onFocus (optional)\n\nOptional callback function for when the input receives focus. Receives no arguments.\n\n#### onBlur (optional)\n\nOptional callback function for when focus on the input is lost. Receives no arguments.\n\n#### onValidate (optional)\n\nOptional validation function that determines if tag should be added. Receives the tag object and must return a boolean.\n\n```js\nfunction onValidate (tag) {\n  return tag.name.length \u003e= 5;\n}\n```\n\n#### addOnBlur (optional)\n\nCreates a tag from the current input value when focus on the input is lost. Defaults to `false`.\n\n#### allowNew (optional)\n\nEnable users to add new (not suggested) tags. Defaults to `false`.\n\n#### allowBackspace (optional)\n\nEnable users to delete selected tags when backspace is pressed while focussed on the text input when empty. Defaults to `true`.\n\n#### tagComponent (optional)\n\nProvide a custom tag component to render. Receives the tag, button text, and delete callback as props. Defaults to `null`.\n\n```jsx\nfunction TagComponent ({ tag, removeButtonText, onDelete }) {\n  return (\n    \u003cbutton type='button' title={`${removeButtonText}: ${tag.name}`} onClick={onDelete}\u003e\n      {tag.name}\n    \u003c/button\u003e\n  )\n}\n```\n\n#### suggestionComponent (optional)\n\nProvide a custom suggestion component to render. Receives the suggestion and current query as props. Defaults to `null`.\n\n```jsx\nfunction SuggestionComponent ({ item, query }) {\n  return (\n    \u003cspan id={item.id} className={item.name === query ? 'match' : 'no-match'}\u003e\n      {item.name}\n    \u003c/span\u003e\n  )\n}\n```\n\n#### inputAttributes (optional)\n\nAn 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 `{}`.\n\n\n### API\n\nBy adding a `ref` to any instances of this component you can access its API methods.\n\n#### `addTag(tag)`\n\nAdds a tag to the list of selected tags. This will trigger the validation and addition callbacks.\n\n#### `deleteTag(index)`\n\nRemoves a tag from the list of selected tags. This will trigger the delete callback.\n\n#### `clearInput()`\n\nClears the input, current query and selected suggestion.\n\n#### `clearSelectedIndex()`\n\nClears the currently selected suggestion.\n\n#### `focusInput()`\n\nSets cursor focus to the text input element.\n\n### Styling\n\nIt is possible to customize the appearance of the component, the included styles found in `/example/styles.css` are only an example.\n\n\n### Development\n\nThe component is written in ES6 and uses [Rollup](https://rollupjs.org/) as its build tool. Tests are written with [Jasmine](https://jasmine.github.io/) using [JSDOM](https://github.com/jsdom/jsdom).\n\n```sh\nnpm install\nnpm run dev # will open http://localhost:8080 and watch files for changes\n```\n\n### Upgrading\n\nTo see all changes refer to [the changelog](CHANGELOG.md).\n\n#### Upgrading from 5.x to 6.x\n\n- React 16.5 or above is now required.\n- Event handlers and callbacks have been renamed to use `on` prefixes, e.g. the `handleAddition()` callback should now be called `onAddition()`.\n- 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.\n- The `placeholder` option has been renamed `placeholderText`\n- The `ariaLabel` option has been renamed `ariaLabelText`\n- The `delimiterChars` option has been removed, use the `delimiters` option instead.\n- The `clearInputOnDelete` option has been removed and is now the default behaviour\n- The `autofocus` option has been removed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fi-like-robots%2Freact-tags","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fi-like-robots%2Freact-tags","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fi-like-robots%2Freact-tags/lists"}