{"id":16294737,"url":"https://github.com/finesse/react-friendly-input","last_synced_at":"2026-04-12T17:49:56.600Z","repository":{"id":94077395,"uuid":"131932781","full_name":"Finesse/react-friendly-input","owner":"Finesse","description":"React components to make a not interrupting input field","archived":false,"fork":false,"pushed_at":"2020-10-24T04:33:44.000Z","size":85,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-09T14:28:30.628Z","etag":null,"topics":["friendly","higher-order-component","input","library","react","react-component","reactjs","select","textarea","ui","usability"],"latest_commit_sha":null,"homepage":"","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/Finesse.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2018-05-03T02:47:59.000Z","updated_at":"2022-04-05T06:35:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"40d56dce-7749-4950-91b0-43a60ed46ee3","html_url":"https://github.com/Finesse/react-friendly-input","commit_stats":{"total_commits":41,"total_committers":1,"mean_commits":41.0,"dds":0.0,"last_synced_commit":"b9b116b9b2d6fab14f214e8bfc343b2a73dd11c2"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/Finesse/react-friendly-input","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Finesse%2Freact-friendly-input","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Finesse%2Freact-friendly-input/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Finesse%2Freact-friendly-input/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Finesse%2Freact-friendly-input/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Finesse","download_url":"https://codeload.github.com/Finesse/react-friendly-input/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Finesse%2Freact-friendly-input/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270149345,"owners_count":24535728,"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","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["friendly","higher-order-component","input","library","react","react-component","reactjs","select","textarea","ui","usability"],"created_at":"2024-10-10T20:16:19.233Z","updated_at":"2026-04-12T17:49:56.559Z","avatar_url":"https://github.com/Finesse.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Friendly Input\n\n[![npm](https://img.shields.io/npm/v/react-friendly-input.svg)](https://www.npmjs.com/package/react-friendly-input)\n![Supported React versions](https://img.shields.io/badge/React-v0.14,_v15,_v16,_v17-brightgreen.svg)\n[![Gzip size](https://badgen.net/bundlephobia/minzip/react-friendly-input?color=green)](https://bundlephobia.com/result?p=react-friendly-input)\n\nThis is a set of [React](https://reactjs.org) form field components which don't change their value programmatically \nwhen focused. It helps to build controlled inputs that don't annoy users.\n\nHere is a simple example. It is a React application where a user can change his/her name. A name must not start or end \nwith a space and must be not more than 10 characters long. The user is typing ` I am typing a text ` and pressing \u003ckbd\u003eTab\u003c/kbd\u003e.\n\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\u003cth\u003ePlain input\u003c/th\u003e\u003cth\u003eFriendly input\u003c/th\u003e\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd align=\"center\"\u003e\n      \n![Plain input demo](docs/plainInput.gif?raw=true)\n        \n\u003c/td\u003e\n\u003ctd align=\"center\"\u003e\n      \n![Friendly input demo](docs/friendlyInput.gif?raw=true)\n        \n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\n\n```jsx\nclass App extends React.Component {\n  state = {\n    name: ''\n  };\n  \n  setName = event =\u003e {\n    this.setState({\n      name: event.target.value\n        .trim().slice(0, 10)\n    });\n  };\n  \n  render() {\n    return \u003cinput\n      value={this.state.name}\n      onChange={this.setName}\n    /\u003e;\n  }\n}\n\nReactDOM.render(\u003cApp/\u003e, document.body);\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```jsx\nclass App extends React.Component {\n  state = {\n    name: ''\n  };\n  \n  setName = event =\u003e {\n    this.setState({\n      name: event.target.value\n        .trim().slice(0, 10)\n    });\n  };\n  \n  render() {\n    return \u003creactFriendlyInput.Input\n      value={this.state.name}\n      onChange={this.setName}\n    /\u003e;\n  }\n}\n\nReactDOM.render(\u003cApp/\u003e, document.body);\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n[Live demo](https://codepen.io/TheFinesse/pen/XqRVRL?editors=0010)\n\n\n## Status\n\n[![Build Status](https://travis-ci.org/Finesse/react-friendly-input.svg?branch=master)](https://travis-ci.org/Finesse/react-friendly-input)\n[![dependencies Status](https://david-dm.org/Finesse/react-friendly-input/status.svg)](https://david-dm.org/Finesse/react-friendly-input)\n[![devDependencies Status](https://david-dm.org/Finesse/react-friendly-input/dev-status.svg)](https://david-dm.org/Finesse/react-friendly-input?type=dev)\n[![peerDependencies Status](https://david-dm.org/Finesse/react-friendly-input/peer-status.svg)](https://david-dm.org/Finesse/react-friendly-input?type=peer)\n\n\n## Installation\n\nThere are several ways to install the components:\n\n\u003cdetails open\u003e\n\u003csummary\u003eSimple\u003c/summary\u003e\n\nDownload the [plugin script](dist/react-friendly-input.umd.min.js) and import it using a `\u003cscript\u003e` tag after the React \nimport.\n\n```html\n\u003c!-- React --\u003e\n\u003cscript type=\"text/javascript\" src=\"//cdn.jsdelivr.net/npm/react@17.0.1/umd/react.production.min.js\"\u003e\u003c/script\u003e\n\n\u003c!-- React Friendly Input --\u003e\n\u003cscript type=\"text/javascript\" src=\"//cdn.jsdelivr.net/npm/react-friendly-input@0.1.4/dist/react-friendly-input.umd.min.js\"\u003e\u003c/script\u003e\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eAMD/RequireJS\u003c/summary\u003e\n\nThe script requires the following AMD modules to be available:\n\n* `react` — React.\n\nInstallation:\n\n```js\nrequire.config({\n  paths: {\n    react: '//cdn.jsdelivr.net/npm/react@17.0.1/umd/react.production.min',\n    'react-friendly-input': '//cdn.jsdelivr.net/npm/react-friendly-input@0.1.4/dist/react-friendly-input.umd.min'\n  }\n});\n\ndefine('myModule', ['react-friendly-input'], function (reactFriendlyInput) {\n    // ...\n});\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eNode.js/NPM/Yarn/Webpack/Rollup/Browserify\u003c/summary\u003e\n\nInstall the package:\n\n```bash\nnpm install react-friendly-input --save\n```\n\nRequire it:\n\n```js\nconst reactFriendlyInput = require('react-friendly-input');\n```\n\u003c/details\u003e\n\n\n## Usage\n\nThe components are rendered like the plain React form fields. All the props are passed to the underlying DOM elements.\n\n```jsx\nconst {Input, TextArea, Select} = reactFriendlyInput;\n\nReactDOM.render(\n  \u003cdiv\u003e\n    \u003cInput type=\"text\" value=\"some value\" /\u003e\n    \u003cTextArea value=\"big text\" rows=\"4\" /\u003e\n    \u003cSelect value=\"1\"\u003e\n      \u003coption value=\"0\"\u003eNo\u003c/option\u003e\n      \u003coption value=\"1\"\u003eYes\u003c/option\u003e\n    \u003cSelect\u003e\n  \u003c/div\u003e,\n  document.body\n);\n```\n\nIf a field is focused, the field value doesn't change when a new value is given through the props.\nThe new value is applied as soon as the field loses the focus.\n\nA component can be uncontrolled:\n\n```jsx\nconst {Input} = reactFriendlyInput;\n\nreturn \u003cInput defaultValue=\"initial value\" /\u003e;\n```\n\nYou can change a field value using the `value` property. If the field is focused the value doesn't change.\n\n```jsx\nconst {Input} = reactFriendlyInput;\n\nlet input;\nReactDOM.render(\u003cInput defaultValue=\"value1\" ref={i =\u003e input = i} /\u003e, document.body);\ninput.value = 'value2';\n```\n\nYou can set a new value despite the focus using the `forceValue` method:\n\n```jsx\ninput.forceValue('value2');\n```\n\n### Making a custom friendly input\n\nIf you have a component that acts like a form field:\n\n* Its element has a writable `value` attribute\n* Has the `defaultValue`, `onFocus` and `onBlur` props that acts the same as in the `\u003cinput\u003e` component\n* Uncontrolled when doesn't receive the `value` prop\n\nYou can use the [higher-order component](https://reactjs.org/docs/higher-order-components.html) function to make it \nfriendly:\n\n```js\nconst {palInput} = reactFriendlyInput;\n\nclass CustomField extends React.Component {\n  // ...\n}\n\nconst FriendlyCustomField = palInput(CustomField);\n```\n\n### Getting a reference to the DOM element\n\nIf you need to get a reference to the underlying element (e.g. to focus it), you have several options.\n\nFirst is to use the friendly input `input` property:\n\n```jsx\nconst {Input} = reactFriendlyInput;\n\nreturn \u003cInput ref={friendlyInput =\u003e friendlyInput.input.focus()} /\u003e;\n```\n\nSecond is to use the `inputRef` prop:\n\n```jsx\nconst {Input} = reactFriendlyInput;\n\nreturn \u003cInput inputRef={input =\u003e input.focus()} /\u003e; // String refs are not supported here\n```\n\n\n## Building and testing\n\nThe source code is located in the `src` directory. When you first download the code, install \n[node.js](https://nodejs.org/) version 8 or greater, open a console, go to the project root directory and run:\n \n```bash\nnpm install\n```\n\nRun to compile the source code:\n\n```bash\nnpm run build\n```\n\nRun to test:\n\n```bash\nnpm test\n```\n\nCompile the code before testing because the test uses the compiled code. \nAn Internet connection is required to test because multiple React versions are downloaded while testing.\n\n\n## Versions compatibility\n\nThe project follows the [Semantic Versioning](http://semver.org).\n\n\n## License\n\nMIT. See [the LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinesse%2Freact-friendly-input","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffinesse%2Freact-friendly-input","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinesse%2Freact-friendly-input/lists"}