You've already forked react-forms
version 1.0
This commit is contained in:
9
.babelrc
Normal file
9
.babelrc
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
["env", {
|
||||||
|
"modules": false
|
||||||
|
}],
|
||||||
|
"stage-0",
|
||||||
|
"react"
|
||||||
|
]
|
||||||
|
}
|
||||||
9
.editorconfig
Normal file
9
.editorconfig
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
23
.eslintrc
Normal file
23
.eslintrc
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"parser": "babel-eslint",
|
||||||
|
"extends": [
|
||||||
|
"standard",
|
||||||
|
"standard-react"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"es6": true
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"react"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
// don't force es6 functions to include space before paren
|
||||||
|
"space-before-function-paren": 0,
|
||||||
|
|
||||||
|
// allow specifying true explicitly for boolean props
|
||||||
|
"react/jsx-boolean-value": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules/
|
||||||
|
.idea/
|
||||||
|
example/
|
||||||
4
.travis.yml
Normal file
4
.travis.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- 9
|
||||||
|
- 8
|
||||||
28
README.md
Normal file
28
README.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# react-forms
|
||||||
|
|
||||||
|
> React form components
|
||||||
|
|
||||||
|
[](https://www.npmjs.com/package/react-forms) [](https://standardjs.com)
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save react-forms
|
||||||
|
yarn react-forms
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import React, { Component } from 'react'
|
||||||
|
|
||||||
|
import MyComponent from 'react-forms'
|
||||||
|
|
||||||
|
class Example extends Component {
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<MyComponent />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
8137
dist/index.es.js
vendored
Normal file
8137
dist/index.es.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
dist/index.es.js.map
vendored
Normal file
1
dist/index.es.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
8155
dist/index.js
vendored
Normal file
8155
dist/index.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
dist/index.js.map
vendored
Normal file
1
dist/index.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
65
package.json
Normal file
65
package.json
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"name": "react-forms",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "React form components",
|
||||||
|
"author": "Maxime Renou",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "bluesquare-packages/react-forms",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"module": "dist/index.es.js",
|
||||||
|
"jsnext:main": "dist/index.es.js",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8",
|
||||||
|
"npm": ">=5"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "cross-env CI=1 react-scripts test --env=jsdom",
|
||||||
|
"test:watch": "react-scripts test --env=jsdom",
|
||||||
|
"build": "rollup -c",
|
||||||
|
"start": "rollup -c -w",
|
||||||
|
"prepare": "npm run build",
|
||||||
|
"predeploy": "cd example && npm install && npm run build",
|
||||||
|
"deploy": "gh-pages -d example/build"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"prop-types": "^15.5.4",
|
||||||
|
"react": "^15.0.0 || ^16.0.0",
|
||||||
|
"react-dom": "^15.0.0 || ^16.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@svgr/rollup": "^2.4.1",
|
||||||
|
"babel-core": "^6.26.3",
|
||||||
|
"babel-eslint": "^8.2.5",
|
||||||
|
"babel-plugin-external-helpers": "^6.22.0",
|
||||||
|
"babel-preset-env": "^1.7.0",
|
||||||
|
"babel-preset-react": "^6.24.1",
|
||||||
|
"babel-preset-stage-0": "^6.24.1",
|
||||||
|
"cross-env": "^5.1.4",
|
||||||
|
"eslint": "^5.0.1",
|
||||||
|
"eslint-config-standard": "^11.0.0",
|
||||||
|
"eslint-config-standard-react": "^6.0.0",
|
||||||
|
"eslint-plugin-import": "^2.13.0",
|
||||||
|
"eslint-plugin-node": "^7.0.1",
|
||||||
|
"eslint-plugin-promise": "^4.0.0",
|
||||||
|
"eslint-plugin-react": "^7.10.0",
|
||||||
|
"eslint-plugin-standard": "^3.1.0",
|
||||||
|
"gh-pages": "^1.2.0",
|
||||||
|
"react": "^16.4.1",
|
||||||
|
"react-dom": "^16.4.1",
|
||||||
|
"react-scripts": "^1.1.4",
|
||||||
|
"rollup": "^0.64.1",
|
||||||
|
"rollup-plugin-babel": "^3.0.7",
|
||||||
|
"rollup-plugin-commonjs": "^9.1.3",
|
||||||
|
"rollup-plugin-node-resolve": "^3.3.0",
|
||||||
|
"rollup-plugin-peer-deps-external": "^2.2.0",
|
||||||
|
"rollup-plugin-postcss": "^1.6.2",
|
||||||
|
"rollup-plugin-url": "^1.4.0"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"moment": "^2.24.0",
|
||||||
|
"react-toastify": "^4.5.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
39
rollup.config.js
Normal file
39
rollup.config.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import babel from 'rollup-plugin-babel'
|
||||||
|
import commonjs from 'rollup-plugin-commonjs'
|
||||||
|
import external from 'rollup-plugin-peer-deps-external'
|
||||||
|
import postcss from 'rollup-plugin-postcss'
|
||||||
|
import resolve from 'rollup-plugin-node-resolve'
|
||||||
|
import url from 'rollup-plugin-url'
|
||||||
|
import svgr from '@svgr/rollup'
|
||||||
|
|
||||||
|
import pkg from './package.json'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: 'src/index.js',
|
||||||
|
output: [
|
||||||
|
{
|
||||||
|
file: pkg.main,
|
||||||
|
format: 'cjs',
|
||||||
|
sourcemap: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: pkg.module,
|
||||||
|
format: 'es',
|
||||||
|
sourcemap: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
external(),
|
||||||
|
postcss({
|
||||||
|
modules: true
|
||||||
|
}),
|
||||||
|
url(),
|
||||||
|
svgr(),
|
||||||
|
babel({
|
||||||
|
exclude: 'node_modules/**',
|
||||||
|
plugins: [ 'external-helpers' ]
|
||||||
|
}),
|
||||||
|
resolve(),
|
||||||
|
commonjs()
|
||||||
|
]
|
||||||
|
}
|
||||||
5
src/.eslintrc
Normal file
5
src/.eslintrc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"jest": true
|
||||||
|
}
|
||||||
|
}
|
||||||
49
src/CheckBox.js
Normal file
49
src/CheckBox.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import {FormConsumer} from "./FormContext";
|
||||||
|
import FormItemError from "./FormItemError";
|
||||||
|
|
||||||
|
export default class CheckBox extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<FormConsumer>
|
||||||
|
{(data) => this.renderCheckBox(data)}
|
||||||
|
</FormConsumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCheckBox(data)
|
||||||
|
{
|
||||||
|
let props = {...this.props}
|
||||||
|
if (props.children) delete props.children
|
||||||
|
if (props.onChangeValue) delete props.onChangeValue
|
||||||
|
return (
|
||||||
|
<div className="form-check">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={this.props.value}
|
||||||
|
onChange={(e) => this.props.onChangeValue(e.target.checked)}
|
||||||
|
{...props} />
|
||||||
|
{this.renderLabel(data)}
|
||||||
|
<FormItemError name={this.props.name} data={data} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLabel(data)
|
||||||
|
{
|
||||||
|
if (this.props.children.length) {
|
||||||
|
return (
|
||||||
|
<label className="form-check-label" htmlFor={this.props.id}>{this.props.children}</label>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckBox.defaultProps = {
|
||||||
|
name: 'checkbox',
|
||||||
|
id: 'checkbox',
|
||||||
|
className: 'form-check-input',
|
||||||
|
onChangeValue: (checked) => {}
|
||||||
|
}
|
||||||
60
src/DatePicker.js
Normal file
60
src/DatePicker.js
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import moment from 'moment';
|
||||||
|
import {FormConsumer} from "./FormContext";
|
||||||
|
import FormItemError from "./FormItemError";
|
||||||
|
|
||||||
|
export default class DatePicker extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<FormConsumer>
|
||||||
|
{(data) => this.renderDatePicker(data)}
|
||||||
|
</FormConsumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDatePicker(data)
|
||||||
|
{
|
||||||
|
const value = this.props.value
|
||||||
|
let props = {...this.props}
|
||||||
|
if (props.children) delete props.children
|
||||||
|
if (props.value) delete props.value
|
||||||
|
if (props.onChangeValue) delete props.onChangeValue
|
||||||
|
return (
|
||||||
|
<div className="form-group">
|
||||||
|
{this.renderLabel(data)}
|
||||||
|
<input
|
||||||
|
value={this.parseValue(value)}
|
||||||
|
onChange={(e) => this.props.onChangeValue(moment(e.target.value))} {...props} />
|
||||||
|
<p className="text-muted">DatePicker {this.props.type}</p>
|
||||||
|
<FormItemError name={this.props.name} data={data} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
parseValue(value)
|
||||||
|
{
|
||||||
|
if (this.props.type == 'date') return moment(value).format('YYYY-MM-DD')
|
||||||
|
if (this.props.type == 'time') return moment(value).format('HH:mm:ss')
|
||||||
|
return moment(value).format('YYYY-MM-DDTHH:mm')
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLabel(data)
|
||||||
|
{
|
||||||
|
if (this.props.label) {
|
||||||
|
return (
|
||||||
|
<label htmlFor={this.props.id}>{this.props.label}</label>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DatePicker.defaultProps = {
|
||||||
|
name: 'input',
|
||||||
|
id: 'input',
|
||||||
|
className: 'form-control',
|
||||||
|
type: 'datetime-local',
|
||||||
|
value: null,
|
||||||
|
onChangeValue: (text) => {}
|
||||||
|
}
|
||||||
71
src/FilePicker.js
Normal file
71
src/FilePicker.js
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import {FormConsumer} from "./FormContext";
|
||||||
|
import FormItemError from "./FormItemError";
|
||||||
|
|
||||||
|
export default class FilePicker extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<FormConsumer>
|
||||||
|
{(data) => this.renderFilePicker(data)}
|
||||||
|
</FormConsumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderFilePicker(data)
|
||||||
|
{
|
||||||
|
const value = this.props.value
|
||||||
|
let props = {...this.props}
|
||||||
|
if (props.children) delete props.children
|
||||||
|
if (props.onChangeValue) delete props.onChangeValue
|
||||||
|
if (!(typeof props.value instanceof File)) delete props.value
|
||||||
|
return (
|
||||||
|
<div className="form-group">
|
||||||
|
{this.renderLabel(data)}
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
onChange={(e) => this.props.onChangeValue(e.target.value)} {...props} />
|
||||||
|
{this.renderValue(value)}
|
||||||
|
<FormItemError name={this.props.name} data={data} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderValue(value)
|
||||||
|
{
|
||||||
|
if (value instanceof File)
|
||||||
|
return <p className="text-muted">{value.name} {this.renderDeleteButton()}</p>
|
||||||
|
|
||||||
|
if (value !== null)
|
||||||
|
return <p className="text-muted">{value} {this.renderDeleteButton()}</p>
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDeleteButton()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<i className="fa fa-trash" onClick={() => {
|
||||||
|
this.props.onChangeValue(null)
|
||||||
|
}}/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLabel(data)
|
||||||
|
{
|
||||||
|
if (this.props.label) {
|
||||||
|
return (
|
||||||
|
<label htmlFor={this.props.id}>{this.props.label}</label>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePicker.defaultProps = {
|
||||||
|
name: 'file-picker',
|
||||||
|
id: 'file-picker',
|
||||||
|
className: 'form-control',
|
||||||
|
value: null,
|
||||||
|
onChangeValue: (file) => {}
|
||||||
|
}
|
||||||
87
src/Form.js
Normal file
87
src/Form.js
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import FormContext from './FormContext';
|
||||||
|
import {toast, ToastContainer} from 'react-toastify';
|
||||||
|
import FormTranslationContext, {FormTranslationConsumer} from './FormTranslationContext'
|
||||||
|
|
||||||
|
class ContextAwareForm extends Component
|
||||||
|
{
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
data: props.data
|
||||||
|
}
|
||||||
|
|
||||||
|
this.displayError = true
|
||||||
|
this.handleError(props)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(props)
|
||||||
|
{
|
||||||
|
this.handleError(props)
|
||||||
|
this.setState({
|
||||||
|
data: props.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleError(props)
|
||||||
|
{
|
||||||
|
if (props.data && props.data.error && props.toast && this.displayError == true) {
|
||||||
|
toast.error(this.props.translator.renderText(props.data.error))
|
||||||
|
this.displayError = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<FormContext.Provider value={this.state.data}>
|
||||||
|
<form onSubmit={this._onSubmit}>
|
||||||
|
{this.renderError()}
|
||||||
|
{this.props.children}
|
||||||
|
</form>
|
||||||
|
<ToastContainer />
|
||||||
|
</FormContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
_onSubmit = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
this.props.onSubmit()
|
||||||
|
this.displayError = true
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderError()
|
||||||
|
{
|
||||||
|
if (this.state.data && this.state.data.error && !this.props.toast)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<p className="alert alert-danger">{this.props.translator.renderText(this.state.data.error)}</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Form extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<FormTranslationConsumer>
|
||||||
|
{(translator) => (
|
||||||
|
<ContextAwareForm translator={translator} {...this.props}/>
|
||||||
|
)}
|
||||||
|
</FormTranslationConsumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Form.defaultProps = {
|
||||||
|
data: null,
|
||||||
|
toast: false,
|
||||||
|
onSubmit: () => {
|
||||||
|
console.log('[Form] submitted')
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/FormContext.js
Normal file
17
src/FormContext.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import React, { Component } from 'react'
|
||||||
|
|
||||||
|
const FormContext = React.createContext({ data: null });
|
||||||
|
|
||||||
|
export default FormContext
|
||||||
|
|
||||||
|
export class FormConsumer extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<FormContext.Consumer>
|
||||||
|
{(props) => this.props.children(props)}
|
||||||
|
</FormContext.Consumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/FormItemError.js
Normal file
22
src/FormItemError.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import {FormTranslationConsumer} from './FormTranslationContext'
|
||||||
|
|
||||||
|
export default class FormItemError extends Component
|
||||||
|
{
|
||||||
|
render() {
|
||||||
|
const data = this.props.data
|
||||||
|
|
||||||
|
if (!data || !data.errors || !data.errors[this.props.name]) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormTranslationConsumer>
|
||||||
|
{(translator) => this.renderError(data, translator)}
|
||||||
|
</FormTranslationConsumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderError(data, translator)
|
||||||
|
{
|
||||||
|
return <p className="text-danger">{translator.renderText(data.errors[this.props.name].error)}</p>
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/FormTranslationContext.js
Normal file
19
src/FormTranslationContext.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import React, { Component } from 'react'
|
||||||
|
|
||||||
|
const FormTranslationContext = React.createContext({
|
||||||
|
renderText: (text) => (text)
|
||||||
|
});
|
||||||
|
|
||||||
|
export default FormTranslationContext
|
||||||
|
|
||||||
|
export class FormTranslationConsumer extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<FormTranslationContext.Consumer>
|
||||||
|
{(props) => this.props.children(props)}
|
||||||
|
</FormTranslationContext.Consumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/Input.js
Normal file
46
src/Input.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import {FormConsumer} from "./FormContext";
|
||||||
|
import FormItemError from "./FormItemError";
|
||||||
|
|
||||||
|
export default class Input extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<FormConsumer>
|
||||||
|
{(data) => this.renderInput(data)}
|
||||||
|
</FormConsumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderInput(data)
|
||||||
|
{
|
||||||
|
let props = {...this.props}
|
||||||
|
if (props.children) delete props.children
|
||||||
|
if (props.onChangeValue) delete props.onChangeValue
|
||||||
|
return (
|
||||||
|
<div className="form-group">
|
||||||
|
{this.renderLabel(data)}
|
||||||
|
<input onChange={(e) => this.props.onChangeValue(e.target.value)} {...props} />
|
||||||
|
<FormItemError name={this.props.name} data={data} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLabel(data)
|
||||||
|
{
|
||||||
|
if (this.props.label) {
|
||||||
|
return (
|
||||||
|
<label htmlFor={this.props.id}>{this.props.label}</label>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Input.defaultProps = {
|
||||||
|
name: 'input',
|
||||||
|
id: 'input',
|
||||||
|
className: 'form-control',
|
||||||
|
type: 'text',
|
||||||
|
onChangeValue: (text) => {}
|
||||||
|
}
|
||||||
27
src/Option.js
Normal file
27
src/Option.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import {OptionGroupConsumer} from "./OptionGroup";
|
||||||
|
|
||||||
|
export default class Option extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<OptionGroupConsumer>
|
||||||
|
{(data) => this.renderOption(data)}
|
||||||
|
</OptionGroupConsumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderOption(data)
|
||||||
|
{
|
||||||
|
let props = {...this.props}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<option {...props}>{this.props.children}</option>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Option.defaultProps = {
|
||||||
|
value: 'option'
|
||||||
|
}
|
||||||
83
src/OptionGroup.js
Normal file
83
src/OptionGroup.js
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import {FormConsumer} from './FormContext';
|
||||||
|
import FormItemError from "./FormItemError";
|
||||||
|
|
||||||
|
const OptionGroupContext = React.createContext({});
|
||||||
|
|
||||||
|
export class OptionGroupConsumer extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<OptionGroupContext.Consumer>
|
||||||
|
{(props) => this.props.children(props)}
|
||||||
|
</OptionGroupContext.Consumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class OptionGroup extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<FormConsumer>
|
||||||
|
{(data) => this.renderOptionGroup(data)}
|
||||||
|
</FormConsumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderOptionGroup(data)
|
||||||
|
{
|
||||||
|
const props = {...this.props}
|
||||||
|
return (
|
||||||
|
<div className="form-group">
|
||||||
|
{this.renderLabel()}
|
||||||
|
<select {...this.props.data} {...props} onChange={(e) => this._onChange(e)}>
|
||||||
|
{this.renderChildren()}
|
||||||
|
</select>
|
||||||
|
<FormItemError name={this.props.name} data={data} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
_onChange = (e) => {
|
||||||
|
if (this.props.multiple) {
|
||||||
|
let value = []
|
||||||
|
const options = e.target.options;
|
||||||
|
for (let i = 0, l = options.length; i < l; i++) {
|
||||||
|
if (options[i].selected) {
|
||||||
|
value.push(options[i].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.props.onChangeValue(value)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.props.onChangeValue(e.target.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLabel()
|
||||||
|
{
|
||||||
|
if (!this.props.label) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<label htmlFor={this.props.id}>{this.props.label}</label>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderChildren()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<OptionGroupContext.Provider value={{}}>
|
||||||
|
{this.props.children}
|
||||||
|
</OptionGroupContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionGroup.defaultProps = {
|
||||||
|
name: 'select',
|
||||||
|
className: 'form-control',
|
||||||
|
onChangeValue: (value) => {}
|
||||||
|
}
|
||||||
48
src/Radio.js
Normal file
48
src/Radio.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import {RadioGroupConsumer} from "./RadioGroup";
|
||||||
|
|
||||||
|
export default class Radio extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<RadioGroupConsumer>
|
||||||
|
{(data) => this.renderRadio(data)}
|
||||||
|
</RadioGroupConsumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderRadio(data)
|
||||||
|
{
|
||||||
|
let props = {...this.props}
|
||||||
|
if (props.children) delete props.children
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="form-check">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
checked={data.value === this.props.value}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (e.target.checked)
|
||||||
|
data.onChangeValue(this.props.value)
|
||||||
|
}}
|
||||||
|
{...props} />
|
||||||
|
{this.renderLabel(data)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLabel(data)
|
||||||
|
{
|
||||||
|
if (this.props.children.length) {
|
||||||
|
return (
|
||||||
|
<label className="form-check-label" htmlFor={this.props.id}>{this.props.children}</label>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Radio.defaultProps = {
|
||||||
|
value: 'option',
|
||||||
|
className: 'form-check-input'
|
||||||
|
}
|
||||||
66
src/RadioGroup.js
Normal file
66
src/RadioGroup.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import {FormConsumer} from './FormContext';
|
||||||
|
import FormItemError from "./FormItemError";
|
||||||
|
|
||||||
|
const RadioGroupContext = React.createContext({});
|
||||||
|
|
||||||
|
export class RadioGroupConsumer extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<RadioGroupContext.Consumer>
|
||||||
|
{(props) => this.props.children(props)}
|
||||||
|
</RadioGroupContext.Consumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class RadioGroup extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<FormConsumer>
|
||||||
|
{(data) => this.renderRadioGroup(data)}
|
||||||
|
</FormConsumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderRadioGroup(data)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<div className="form-options mb-3">
|
||||||
|
{this.renderLabel()}
|
||||||
|
{this.renderChildren()}
|
||||||
|
<FormItemError name={this.props.name} data={data} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLabel()
|
||||||
|
{
|
||||||
|
if (!this.props.label) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<p className="mb-0 mt-2">{this.props.label}</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderChildren()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<RadioGroupContext.Provider value={{
|
||||||
|
onChangeValue: (value) => this.props.onChangeValue(value),
|
||||||
|
value: this.props.value
|
||||||
|
}}>
|
||||||
|
{this.props.children}
|
||||||
|
</RadioGroupContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RadioGroup.defaultProps = {
|
||||||
|
name: 'radio',
|
||||||
|
onChangeValue: (value) => {}
|
||||||
|
}
|
||||||
13
src/Submit.js
Normal file
13
src/Submit.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
|
||||||
|
export default class Submit extends Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<button type="submit" {...this.props}>{this.props.children}</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Submit.defaultProps = {
|
||||||
|
className: 'btn btn-primary'
|
||||||
|
}
|
||||||
44
src/TextArea.js
Normal file
44
src/TextArea.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import {FormConsumer} from "./FormContext";
|
||||||
|
import FormItemError from "./FormItemError";
|
||||||
|
|
||||||
|
export default class TextArea extends Component
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<FormConsumer>
|
||||||
|
{(data) => this.renderTextArea(data)}
|
||||||
|
</FormConsumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTextArea(data)
|
||||||
|
{
|
||||||
|
let props = {...this.props}
|
||||||
|
if (props.onChangeValue) delete props.onChangeValue
|
||||||
|
return (
|
||||||
|
<div className="form-group">
|
||||||
|
{this.renderLabel(data)}
|
||||||
|
<textarea onChange={(e) => this.props.onChangeValue(e.target.value)} {...props} />
|
||||||
|
<FormItemError name={this.props.name} data={data} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLabel(data)
|
||||||
|
{
|
||||||
|
if (this.props.label) {
|
||||||
|
return (
|
||||||
|
<label htmlFor={this.props.id}>{this.props.label}</label>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextArea.defaultProps = {
|
||||||
|
name: 'textarea',
|
||||||
|
id: 'textarea',
|
||||||
|
className: 'form-control',
|
||||||
|
onChangeValue: (text) => {}
|
||||||
|
}
|
||||||
14
src/index.js
Normal file
14
src/index.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import CheckBox from './CheckBox'
|
||||||
|
import Form from './Form'
|
||||||
|
import Input from './Input'
|
||||||
|
import Option from './Option'
|
||||||
|
import OptionGroup from './OptionGroup'
|
||||||
|
import Radio from './Radio'
|
||||||
|
import RadioGroup from './RadioGroup'
|
||||||
|
import Submit from './Submit'
|
||||||
|
import TextArea from './TextArea'
|
||||||
|
import FormTranslationContext from './FormTranslationContext'
|
||||||
|
import DatePicker from './DatePicker'
|
||||||
|
import FilePicker from './FilePicker'
|
||||||
|
|
||||||
|
export { CheckBox, Form, Input, Option, OptionGroup, RadioGroup, Radio, DatePicker, FilePicker, Submit, TextArea, FormTranslationContext }
|
||||||
Reference in New Issue
Block a user