├── .gitignore ├── .snyk ├── LICENSE ├── README.md ├── app.js ├── main.js ├── master.css └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | 35 | #Ignore public 36 | public 37 | -------------------------------------------------------------------------------- /.snyk: -------------------------------------------------------------------------------- 1 | version: v1.5.0 2 | ignore: {} 3 | patch: 4 | 'npm:minimatch:20160620': 5 | - catw > glob > minimatch: 6 | patched: '2016-12-02T03:53:38.349Z' 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 code-kotis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-floating-label 2 | > Floating label input. 3 | 4 | Checkout the [DEMO](http://code-kotis.github.io/react-floating-label/) 5 | 6 | __Install it:__ 7 | 8 | ```sh 9 | npm install --save react-floating-label 10 | ``` 11 | 12 | __Usage:__ 13 | 14 | ```js 15 | var FloatingLabel = require('react-floating-label'); 16 | 17 | 20 | 21 | ``` 22 | 23 | __Props:__ 24 | 25 | 26 | ```js 27 | autoComplete: PropTypes.bool, 28 | errorMsg: PropTypes.string, 29 | placeholder: PropTypes.string.isRequired, 30 | pattern: PropTypes.any, 31 | type: PropTypes.string.isRequired, 32 | id: PropTypes.string.isRequired, 33 | isDisabled: PropTypes.bool 34 | ``` 35 | 36 | __Building and running:__ 37 | 38 | ``` 39 | Lifecycle scripts included in react-floating-label: 40 | start 41 | ecstatic -p 8000 public 42 | 43 | available via `npm run-script`: 44 | build-js 45 | NODE_ENV=production browserify main.js | uglifyjs -cm > public/bundle.js 46 | build-css 47 | cat master.css > public/bundle.css 48 | build 49 | npm run build-js && npm run build-css 50 | watch-js 51 | watchify main.js -o public/bundle.js -dv 52 | watch-css 53 | catw master.css -o public/bundle.css -v 54 | watch 55 | npm run watch-js & npm run watch-css 56 | ``` 57 | 58 | __License:__ 59 | 60 | MIT 61 | 62 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import FloatingLabel from './main.js'; 3 | const target = document.getElementById('content'); 4 | React.render(,target); 6 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import React, {PropTypes} from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import classNames from 'classnames' 4 | 5 | 6 | export default class FloatingLabel extends React.Component { 7 | static propTypes: { 8 | autoComplete: PropTypes.bool, 9 | errorMsg: PropTypes.string, 10 | placeholder: PropTypes.string.isRequired, 11 | pattern: PropTypes.any, 12 | type: PropTypes.string.isRequired, 13 | id: PropTypes.string.isRequired, 14 | isDisabled: PropTypes.bool 15 | }; 16 | _bind(...methods) { 17 | methods.map(method=>this[method]=this[method].bind(this)); 18 | } 19 | constructor (props) { 20 | super(props) 21 | this.state = {hasValue: false, hasError: false}; 22 | this._bind('onBlur','onChange'); 23 | } 24 | 25 | onBlur(event) { 26 | this.setState({hasValue: Boolean(event.currentTarget.value)}); 27 | } 28 | 29 | onChange(event) { 30 | const {pattern} = this.props; 31 | this.setState({ 32 | hasError: !pattern.test(event.currentTarget.value), 33 | hasValue: Boolean(event.currentTarget.value) 34 | }); 35 | } 36 | 37 | render () { 38 | const {autoComplete, errorMsg, id, isDisabled, pattern, placeholder, type} = this.props; 39 | const {hasValue, hasError} = this.state; 40 | 41 | const inputClasses = classNames('fl-input', {'fl-valid': hasValue && !hasError}, {'fl-invalid': hasValue && hasError}); 42 | const errMsgClasses = classNames({'fl-error-msg': errorMsg}, {'fl-error-show': (hasError && hasValue) && (errorMsg && pattern)}); 43 | 44 | return( 45 |
46 | 54 | 55 | 56 | { errorMsg && {errorMsg} } 57 |
58 | ); 59 | } 60 | } 61 | 62 | FloatingLabel.defaultProps = { 63 | autoComplete: false, 64 | type: 'text', 65 | isDisabled: false, 66 | id: 'text-box', 67 | placeholder: 'name' 68 | }; 69 | 70 | 71 | module.exports = FloatingLabel; 72 | 73 | //TODO: remove below lines 74 | const target = document.getElementById('content'); 75 | ReactDOM.render(, 79 | target); 80 | 81 | -------------------------------------------------------------------------------- /master.css: -------------------------------------------------------------------------------- 1 | .fl-input-container { 2 | -ms-flex-direction: column; 3 | -webkit-flex-direction: column; 4 | display: -ms-flexbox; 5 | display: -webkit-flex; 6 | display: flex; 7 | flex-direction: column; 8 | padding: 25px; 9 | position: relative; 10 | } 11 | 12 | .fl-input-container input:not(:focus):not(.fl-valid):not(.fl-invalid) { 13 | color: transparent; 14 | } 15 | 16 | .fl-input-container input, 17 | .fl-input-container label, 18 | .fl-error-msg { 19 | -webkit-font-smoothing: antialiased; 20 | font-family: 'Roboto', sans-serif; 21 | text-shadow: none; 22 | } 23 | 24 | .fl-input-container input { 25 | -moz-appearance: none; 26 | -webkit-appearance: none; 27 | -webkit-tap-highlight-color: transparent; 28 | border-radius: 0; 29 | display: -moz-flex; 30 | display: -ms-flexbox; 31 | display: -webkit-flex; 32 | display: flex; 33 | font-size: 100%; 34 | line-height: 25px; 35 | } 36 | 37 | .fl-input-label { 38 | -moz-transform-origin: left top; 39 | -moz-transform: scale(1) translate3d(0, 22px, 0); 40 | -moz-transition: 200ms ease all; 41 | -ms-flex-order: 1; 42 | -webkit-order: 1; 43 | -webkit-transform-origin: left top; 44 | -webkit-transform: scale(1) translate3d(0, 22px, 0); 45 | -webkit-transition: 200ms ease all; 46 | color: #999; 47 | font-weight: normal; 48 | opacity: 0.75; 49 | order: 1; 50 | padding-left: 2px; 51 | pointer-events: none; 52 | text-transform: capitalize; 53 | transform-origin: left top; 54 | transform: scale(1) translate3d(0, 22px, 0); 55 | transition: 200ms ease all; 56 | } 57 | 58 | .fl-input-container input:focus + label, 59 | .fl-input-container input.fl-valid + label, 60 | .fl-invalid + label { 61 | -moz-transform: scale(0.8) translate3d(0, 5px, 0); 62 | -webkit-transform: scale(0.8) translate3d(0, 5px, 0); 63 | color: #3949AB; 64 | opacity: 1; 65 | transform: scale(0.8) translate3d(0, 5px, 0); 66 | } 67 | 68 | .fl-input:active, 69 | .fl-input:focus, 70 | .fl-input-label { 71 | outline: 0; 72 | } 73 | 74 | .fl-input { 75 | -ms-flex-order: 2; 76 | -ms-flex: 1 1 auto; 77 | -webkit-flex: 1 1 auto; 78 | -webkit-order: 2; 79 | border: 0; 80 | border-bottom: 1px solid rgba(0, 0, 0, 0.15); 81 | color: #000; 82 | flex: 1 1 auto; 83 | order: 2; 84 | } 85 | 86 | .fl-input-bar { 87 | -ms-flex-order: 3; 88 | -webkit-order: 3; 89 | display: block; 90 | order: 3; 91 | top: 0; 92 | } 93 | 94 | .fl-input-bar::after, 95 | .fl-input-bar::before { 96 | -moz-transition: 200ms ease all; 97 | -webkit-transition: 200ms ease all; 98 | background: #3949AB; 99 | bottom: 0; 100 | content: ""; 101 | height: 2px; 102 | position: absolute; 103 | transition: 200ms ease all; 104 | width: 0; 105 | } 106 | 107 | .fl-input-bar::before { 108 | left: 50%; 109 | } 110 | 111 | .fl-input-bar::after { 112 | right: 50%; 113 | } 114 | 115 | .fl-input:focus ~ .fl-input-bar::after, 116 | .fl-input:focus ~ .fl-input-bar::before, 117 | .fl-invalid ~ .fl-input-bar::after, 118 | .fl-invalid ~ .fl-input-bar::before { 119 | width: 50%; 120 | } 121 | 122 | .fl-input-bar, 123 | .fl-error-msg { 124 | position: relative; 125 | width: inherit; 126 | } 127 | 128 | .fl-error-msg { 129 | bottom: 0; 130 | display: none; 131 | font-size: 13px; 132 | overflow: hidden; 133 | position: absolute; 134 | text-overflow: ellipsis; 135 | white-space: nowrap; 136 | width: 90%; 137 | word-break: break-all; 138 | word-wrap: break-word; 139 | } 140 | 141 | .fl-error-show { 142 | display: inline-block; 143 | } 144 | 145 | .fl-invalid ~ .fl-input-bar::after, 146 | .fl-invalid ~ .fl-input-bar::before { 147 | background: #E74C3C; 148 | } 149 | 150 | .fl-input-container .fl-input.fl-invalid + label, 151 | .fl-error-msg { 152 | color: #E74C3C; 153 | } 154 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-floating-label", 3 | "version": "1.0.0", 4 | "description": "A material design styled floating label input using react.js", 5 | "main": "main.js", 6 | "scripts": { 7 | "build-js": "NODE_ENV=production rm -rf public && mkdir public && browserify app.js | uglifyjs -cm > public/bundle.js", 8 | "build-css": "cat master.css > public/bundle.css", 9 | "build": "npm run build-js && npm run build-css", 10 | "start": "ecstatic -p 8000 public", 11 | "watch-js": "watchify app.js -o public/bundle.js -dv", 12 | "watch-css": "catw master.css -o public/bundle.css -v", 13 | "watch": "npm run watch-js & npm run watch-css", 14 | "snyk-protect": "snyk protect", 15 | "prepublish": "npm run snyk-protect" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/code-kotis/react-floating-label.git" 20 | }, 21 | "author": "Gokulakrishnan Kalaikovan (http://gokulkrishh.github.io/about/)", 22 | "contributors": [ 23 | { 24 | "name": "hemanth.hm", 25 | "email": "hemanth.hm@gmail.com", 26 | "url": "http://h3manth.com" 27 | } 28 | ], 29 | "license": "ISC", 30 | "bugs": { 31 | "url": "https://github.com/code-kotis/react-floating-label/issues" 32 | }, 33 | "homepage": "https://github.com/code-kotis/react-floating-label#readme", 34 | "browserify": { 35 | "transform": [ 36 | "babelify" 37 | ] 38 | }, 39 | "dependencies": { 40 | "classnames": "^2.2.3" 41 | }, 42 | "peerDependencies": { 43 | "react": "~0.14.7" 44 | }, 45 | "devDependencies": { 46 | "babelify": "^7.0.0", 47 | "browserify": "^12.0.0", 48 | "catw": "~0.0.1", 49 | "classnames": "^2.2.3", 50 | "ecstatic": "~0.8.0", 51 | "react": "~0.14.7", 52 | "react-dom": "~0.14.7", 53 | "ecstatic": "~1.4.0", 54 | "snyk": "^1.21.2", 55 | "uglify-js": "^2.4.24", 56 | "watchify": "^3.2.3" 57 | }, 58 | "snyk": true 59 | } 60 | --------------------------------------------------------------------------------