├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── babel.config.js ├── example ├── babel.config.js ├── package.json ├── public │ └── index.html ├── src │ ├── FieldArrayExample.jsx │ ├── SimpleFormExample.jsx │ ├── data │ │ ├── countries.json │ │ └── skills.json │ ├── index.css │ └── index.js └── webpack.config.js ├── package-lock.json ├── package.json ├── scripts └── copy-files.js └── src ├── Autocomplete ├── Autocomplete.d.ts ├── Autocomplete.jsx ├── index.d.ts └── index.js ├── ChipInput ├── ChipInput.d.ts ├── ChipInput.jsx ├── index.d.ts └── index.js ├── DatePicker ├── DatePicker.d.ts ├── DatePicker.jsx ├── index.d.ts └── index.js ├── DateTimePicker ├── DateTimePicker.d.ts ├── DateTimePicker.jsx ├── index.d.ts └── index.js ├── KeyboardDatePicker ├── KeyboardDatePicker.d.ts ├── KeyboardDatePicker.jsx ├── index.d.ts └── index.js ├── KeyboardDateTimePicker ├── KeyboardDateTimePicker.d.ts ├── KeyboardDateTimePicker.jsx ├── index.d.ts └── index.js ├── KeyboardTimePicker ├── KeyboardTimePicker.d.ts ├── KeyboardTimePicker.jsx ├── index.d.ts └── index.js ├── RadioGroup ├── RadioGroup.d.ts ├── RadioGroup.jsx ├── index.d.ts └── index.js ├── Select ├── Select.d.ts ├── Select.jsx ├── index.d.ts └── index.js ├── Switch ├── Switch.d.ts ├── Switch.jsx ├── index.d.ts └── index.js ├── TextField ├── TextField.d.ts ├── TextField.jsx ├── index.d.ts └── index.js ├── TimePicker ├── TimePicker.d.ts ├── TimePicker.jsx ├── index.d.ts └── index.js ├── index.d.ts └── index.js /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/** 2 | node_modules/** 3 | public/** 4 | scripts/** -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "airbnb", 4 | "prettier", 5 | "prettier/react" 6 | ], 7 | "plugins": ["prettier"], 8 | "rules": { 9 | "prettier/prettier": "error", 10 | "react/jsx-filename-extension": [ 11 | 1, 12 | { 13 | "extensions": [".js", ".jsx"] 14 | } 15 | ], 16 | "react/prop-types": 0, 17 | "no-underscore-dangle": 0, 18 | "import/imports-first": ["error", "absolute-first"], 19 | "import/newline-after-import": "error", 20 | "import/no-extraneous-dependencies": ["error", { "devDependencies": true }], 21 | "import/prefer-default-export": 0 22 | }, 23 | "env": { 24 | "jest": true 25 | }, 26 | "globals": { 27 | "window": true, 28 | "document": true, 29 | "localStorage": true, 30 | "FormData": true, 31 | "FileReader": true, 32 | "Blob": true, 33 | "navigator": true 34 | }, 35 | "parser": "babel-eslint" 36 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # testing 5 | /coverage 6 | 7 | # production 8 | /dist 9 | 10 | # misc 11 | .DS_Store 12 | .env.local 13 | .env.development.local 14 | .env.test.local 15 | .env.production.local 16 | 17 | npm-debug.log* 18 | yarn-debug.log* 19 | yarn-error.log* 20 | 21 | # specific example files 22 | /example/node_modules 23 | /example/package-lock.json 24 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | babel.config.js 2 | src -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.md 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "trailingComma": "es5", 4 | "tabWidth": 2, 5 | "semi": false, 6 | "singleQuote": true 7 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### [Versions](https://github.com/gerhat/material-ui-formik-components/releases) 2 | 3 | ## 0.7.3 4 | ###### _Oct 22, 2020_ 5 | - `Switch`: fixed warning for changing from uncontrolled to controlled state 6 | - `Autocomplete`: fixed TypeScript autocomplete props interface extension 7 | - Updated dependencies in main project 8 | 9 | ## 0.7.2 10 | ###### _Sept 6, 2020_ 11 | - Fixed [Issue: #40](https://github.com/gerhat/material-ui-formik-components/issues/40) - cannot read property 'formControl' of undefined thanks @wsmith2020 12 | - Added `RadioGroup` to SimpleExample demo 13 | - Updated devDependencies in main project 14 | - Updated dependencies and devDependencies in example project 15 | 16 | ## 0.7.1 17 | ###### _May 12, 2020_ 18 | - Moved `@material-ui/pickers`, `@date-io/date-fns`, `date-fns` and `material-ui-chip-input` to optionalDependencies [Issue: #33](https://github.com/gerhat/material-ui-formik-components/issues/33) thanks @depiction 19 | - Updated dev dependencies to latest versions 20 | 21 | ## 0.7.0 22 | ###### _May 2, 2020_ 23 | - Added Support for Keyboard Pickers ( `KeyboardDatePicker`, `KeyboardTimePicker`, `KeyboardDateTimePicker` and `TimePicker`) [PR: #30](https://github.com/gerhat/material-ui-formik-components/pull/30) thanks @shtjefeen 24 | - Updated `SimpleFormExample.jsx` to use Keyboard Pickers 25 | 26 | ## 0.6.3 27 | ###### _May 2, 2020_ 28 | - Fixed handling of null initial values at `AutoComplete` with prop `multiple`. [Issue: #31](https://github.com/gerhat/material-ui-formik-components/issues/31) thanks @shtjefeen 29 | - Updated packages to latest versions 30 | 31 | ## 0.6.2 32 | ###### _Apr 23, 2020_ 33 | - Fixed initial values not being displayed at AutoComplete. [Issue: #28](https://github.com/gerhat/material-ui-formik-components/issues/28) 34 | - Updated examples to demonstrate the `initialValues` prop 35 | - Updated packages to latest versions 36 | 37 | ## 0.6.1 38 | ###### _Mar 29, 2020_ 39 | - Package updates for fixing `minimist` security vulnerability 40 | 41 | ## 0.6.0 42 | ###### _Mar 8, 2020_ 43 | ### General 44 | - Updated library and example packages to the latest versions 45 | - Refactored Formik code in `example/src/SimpleFormExample.jsx` to not use the `render` prop 46 | 47 | ### Autocomplete 48 | - Replaced `react-select` with `@material-ui/lab/Autocomplete` for improved compatibility 49 | 50 | **Breaking changes** 51 | - Prop `isMultiple` has been changed to `multiple` 52 | - Props `label` and `required` must be provided as items in `textFieldProps` props e.g. 53 | ```javascript 54 | textFieldProps={{ 55 | label: 'Country', 56 | required: true, 57 | variant: 'outlined', 58 | }} 59 | ``` 60 | ### Select 61 | - Simplified select component by replacing `@material-ui/core/Select` with `@material-ui/core/TextField` + `select` prop _(see: https://material-ui.com/components/text-fields/#select)_ 62 | 63 | ## 0.5.2 64 | ###### _Nov 24, 2019_ 65 | - Added missing ts export for `` - thanks [@cargallo](https://github.com/cargallo) 66 | 67 | ## 0.5.1 68 | ###### _Nov 09, 2019_ 69 | - Implemented `` component. Issue: [(issue: #19)](https://github.com/gerhat/material-ui-formik-components/issues/19) 70 | 71 | ## 0.5.0 72 | ###### _Nov 09, 2019_ 73 | - Added support for use in Formik's ``. Issue: [(issue: #17)](https://github.com/gerhat/material-ui-formik-components/issues/17) 74 | - Added [FieldArray example form](https://github.com/gerhat/material-ui-formik-components/tree/master/example/src/FieldArrayExample.jsx) 75 | 76 | ## 0.4.1 77 | ###### _Sep 16, 2019_ 78 | - Updated dependencies to the latest version 79 | 80 | ## 0.4.0 81 | ###### _Jun 2, 2019_ 82 | - Added support for `Material UI v4` 83 | - Replaced `material-ui-pickers v2` with `@material-ui/pickers v3` 84 | 85 | ## 0.3.0 86 | ###### _Apr 26, 2019_ 87 | - Added `ChipInput` component based on [material-ui-chip-input](https://github.com/TeamWertarbyte/material-ui-chip-input) 88 | - Improved code quality and styling using `eslint-config-airbnb`, `prettier` and `husky` 89 | 90 | ## 0.2.4 91 | ###### _Apr 06, 2019_ 92 | - Fixed error in `RadioGroup` PropTypes 93 | 94 | ## 0.2.3 95 | ###### _Apr 06, 2019_ 96 | - Added the ability to fully customize `RadioGroup` 97 | 98 | ## 0.2.2 99 | ###### _Mar 20, 2019_ 100 | - Resolved `InputProps` ambiguity in `TextField` component [(issue: #6)](https://github.com/gerhat/material-ui-formik-components/issues/6) 101 | 102 | ## 0.2.1 103 | ###### _Mar 19, 2019_ 104 | - **Breaking:** Added prop `isMultiple` in `Autocomplete` and set it `false` by default 105 | - Improved example and removed react-scripts 106 | 107 | ## 0.2.0 108 | ###### _Feb 23, 2019_ 109 | - Added `DateTimePicker`, `RadioGroup` and `Switch` components 110 | - Added default value for `required` prop 111 | - Updated README 112 | - Minor refactoring in typescript definitions for `OptionsType` 113 | 114 | ## 0.1.5 115 | ###### _Feb 19, 2019_ 116 | - Props `fullWidth` and `margin` are not hard-coded anymore 117 | - Fixed `Autocomplete` typescript definitions 118 | - Bumped up `formik` version to 1.5.1 and `react-select` to 2.4.1 119 | - Added information about the example in README 120 | 121 | ## 0.1.4 122 | ###### _Feb 17, 2019_ 123 | - **Breaking:** Changed default error behavior. Errors now appear only when the field is `touched` [(issue: #2)](https://github.com/gerhat/material-ui-formik-components/issues/2) 124 | - Added the ability to show error messages in `Select` 125 | - Fixed asterisk not showing in `Autocomplete` label when `required` is `true` 126 | - Error message in `TextField` is now displayed only when there is an error 127 | - Updated devDependencies in `package.json` 128 | - Added validation to the example project 129 | - Updated dependencies in example's `package.json` 130 | - Minor typo in README 131 | 132 | ## 0.1.3 133 | ###### _Jan 10, 2019_ 134 | - Added Typescript types 135 | - Minor refactoring in `Autocomplete.jsx` and `Select.jsx` 136 | - Added npm package link to README 137 | 138 | ## 0.1.2 139 | ###### _Sept 20, 2018_ 140 | - Fixed a typo in README 141 | - Moved `react-select` to peer dependencies 142 | 143 | ## 0.1.1 144 | ###### _Sept 20, 2018_ 145 | - Added `react-dom` to peer dependencies 146 | - Added example to README 147 | 148 | ## 0.1.0 149 | ###### _Sept 18, 2018_ 150 | - Initial commit 151 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 gerhat 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 | # Material-UI Formik Components
[![NPM](https://img.shields.io/npm/v/material-ui-formik-components?color=%23177bbb)](https://www.npmjs.com/package/material-ui-formik-components) · [![Total Downloads](https://img.shields.io/npm/dm/material-ui-formik-components?style=flat)](https://www.npmjs.com/package/material-ui-formik-components) · [![devDependency Status](https://david-dm.org/gerhat/material-ui-formik-components/dev-status.svg)](https://david-dm.org/gerhat/material-ui-formik-components?type=dev) · [![npm bundle size](https://img.shields.io/bundlephobia/minzip/material-ui-formik-components)](https://www.npmjs.com/package/material-ui-formik-components) 2 | We all love [Material-UI](https://material-ui.com) and [Formik](https://formik.org), we just need an easy way to make them work seamlessly together. This library was built just for that. 3 | 4 | # Installation 5 | Install the `material-ui-formik-components` package using the following command: 6 | 7 | ```sh 8 | $ npm install --save material-ui-formik-components 9 | ``` 10 | 11 | ## Peer dependencies 12 | The extension depends on the following packages: 13 | 14 | **Required** 15 | - [react](https://www.npmjs.com/package/react) >= 16.8 16 | - [react-dom](https://www.npmjs.com/package/react-dom) >= 16.8 17 | - [Material-UI](https://material-ui.com) >= 4.0 18 | - [Formik](https://formik.org) >= 2.0 19 | 20 | **Optional** 21 | - [Material-UI Lab](https://material-ui.com/components/about-the-lab/) >4.0 - used by `Autocomplete` 22 | - [Material-UI Pickers](https://material-ui-pickers.dev/) >= 3.0 - used by `DatePicker`, `DateTimePicker`, `KeyboardDatePicker`, `KeyboardTimePicker`, `KeyboardDateTimePicker` and `TimePicker` 23 | - [material-ui-chip-input](https://github.com/TeamWertarbyte/material-ui-chip-input) >= 1.0 - used by `ChipInput` 24 | 25 | # Using the components 26 | The following components are supported: 27 | 28 | - `Autocomplete` - requires [Material-UI Lab](https://material-ui.com/components/about-the-lab/) 29 | - `ChipInput` - requires [material-ui-chip-input](https://github.com/TeamWertarbyte/material-ui-chip-input) 30 | - `DatePicker`, `DateTimePicker`, `KeyboardDatePicker`, `KeyboardTimePicker`, `KeyboardDateTimePicker` and `TimePicker` - please make sure you have installed `date-fns`, `moment` or `luxon` see: [Material-UI Pickers / Installation](https://material-ui-pickers.dev/getting-started/installation) 31 | - `RadioGroup` 32 | - `Select` 33 | - `Switch` 34 | - `TextField` 35 | 36 | Below is an example of `TextField` and `Select` components. Code sandbox url: https://codesandbox.io/s/xoplpm1w84 37 | 38 | ```jsx 39 | import React from 'react' 40 | import { Formik, Form, Field } from 'formik' 41 | import { TextField } from 'material-ui-formik-components/TextField' 42 | import { Select } from 'material-ui-formik-components/Select' 43 | 44 | class RegistrationForm extends React.PureComponent { 45 | render() { 46 | return ( 47 |
48 |

Register

49 | { 55 | alert(`Username: ${values.username}\nGender: ${values.gender}`) 56 | }} 57 | > 58 | {formik => ( 59 |
60 | 61 | 72 | 75 | 76 | )} 77 |
78 |
79 | ) 80 | } 81 | } 82 | 83 | export default RegistrationForm 84 | ``` 85 | 86 | # Example 87 | For a more detailed use of the package, please refer to the code in the [example folder](https://github.com/gerhat/material-ui-formik-components/tree/master/example) of this project. 88 | 89 | # License 90 | MIT 91 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@babel/preset-env', '@babel/preset-react'], 3 | plugins: [['@babel/plugin-proposal-class-properties', { loose: true }]], 4 | } 5 | -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@babel/preset-env', 4 | '@babel/preset-react' 5 | ], 6 | plugins: [ 7 | ['@babel/plugin-proposal-class-properties', { loose: true }] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "material-ui-formik-components-example", 3 | "version": "0.1.2", 4 | "description": "Example project showcasing material-ui-formik-components package", 5 | "keywords": [], 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/gerhat/material-ui-formik-components/tree/master/example" 9 | }, 10 | "license": "MIT", 11 | "main": "src/index.js", 12 | "dependencies": { 13 | "@date-io/date-fns": "1.3.13", 14 | "@material-ui/core": "^4.11.0", 15 | "@material-ui/lab": "4.0.0-alpha.56", 16 | "@material-ui/pickers": "^3.2.10", 17 | "date-fns": "^2.16.1", 18 | "formik": "^2.1.5", 19 | "material-ui-chip-input": "^1.1.0", 20 | "react": "^16.13.1", 21 | "react-dom": "^16.13.1", 22 | "yup": "^0.29.3" 23 | }, 24 | "devDependencies": { 25 | "@babel/cli": "^7.11.6", 26 | "@babel/core": "^7.11.6", 27 | "@babel/node": "^7.10.5", 28 | "@babel/plugin-proposal-class-properties": "^7.10.4", 29 | "@babel/preset-env": "^7.11.5", 30 | "@babel/preset-react": "^7.10.4", 31 | "babel-eslint": "^10.1.0", 32 | "babel-loader": "^8.1.0", 33 | "babel-plugin-module-resolver": "^4.0.0", 34 | "clean-webpack-plugin": "^3.0.0", 35 | "cross-env": "^7.0.2", 36 | "css-loader": "^4.2.2", 37 | "eslint": "^7.8.1", 38 | "eslint-config-standard": "^14.1.1", 39 | "eslint-config-standard-react": "^9.2.0", 40 | "eslint-plugin-import": "^2.22.0", 41 | "eslint-plugin-jsx-a11y": "^6.3.1", 42 | "eslint-plugin-node": "^11.1.0", 43 | "eslint-plugin-promise": "^4.2.1", 44 | "eslint-plugin-react": "^7.20.6", 45 | "eslint-plugin-standard": "^4.0.1", 46 | "eslint-watch": "^7.0.0", 47 | "file-loader": "^6.1.0", 48 | "fs-extra": "^9.0.1", 49 | "html-loader": "^1.3.0", 50 | "html-webpack-plugin": "^4.4.1", 51 | "jest": "^26.4.2", 52 | "prop-types": "^15.7.2", 53 | "rimraf": "3.0.2", 54 | "style-loader": "^1.2.1", 55 | "webpack": "^4.44.1", 56 | "webpack-cli": "^3.3.12", 57 | "webpack-dev-server": "^3.11.0" 58 | }, 59 | "scripts": { 60 | "start": "webpack-dev-server --open" 61 | }, 62 | "browserslist": [ 63 | ">0.2%", 64 | "not dead", 65 | "not ie <= 11", 66 | "not op_mini all" 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /example/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | Material-UI Formik Components 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /example/src/FieldArrayExample.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Formik, Form, Field, FieldArray } from 'formik' 3 | import { object, string, array, date } from 'yup' 4 | import { ChipInput, TextField, Select, DateTimePicker } from '../../src' 5 | 6 | const validationSchema = object().shape({ 7 | friends: array().of( 8 | object().shape({ 9 | name: string().min(3, 'Name is too short').required('Name is Required'), 10 | interests: array().required('Interests is required'), 11 | gender: string().required('Gender is required'), 12 | birthdate: date().nullable().required('Birth date is required'), 13 | }) 14 | ), 15 | }) 16 | 17 | const initialValues = { 18 | friends: [], 19 | } 20 | 21 | const emptyFriendObject = { 22 | name: '', 23 | interests: [], 24 | gender: '', 25 | birthdate: null, 26 | } 27 | 28 | const FieldArrayExample = () => ( 29 |
30 |

FieldArray Example

31 | { 36 | // eslint-disable-next-line no-alert 37 | window.alert(JSON.stringify(values, null, 2)) 38 | }} 39 | > 40 | {(props) => ( 41 |
42 | ( 45 |
46 | {props.values.friends && props.values.friends.length > 0 ? ( 47 | props.values.friends.map((friend, index) => ( 48 | // eslint-disable-next-line react/no-array-index-key 49 |
50 | 56 | 62 | 74 | 80 |
81 | 87 | 93 |
94 |
95 | )) 96 | ) : ( 97 | 104 | )} 105 |
106 | 107 |
108 |
109 | )} 110 | /> 111 | 112 | )} 113 |
114 |
115 | ) 116 | 117 | export default FieldArrayExample 118 | -------------------------------------------------------------------------------- /example/src/SimpleFormExample.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Formik, Form, Field } from 'formik' 3 | import { object, string, array, date, mixed } from 'yup' 4 | import { 5 | Autocomplete, 6 | Select, 7 | TextField, 8 | KeyboardDatePicker, 9 | KeyboardTimePicker, 10 | RadioGroup, 11 | } from '../../src' 12 | import countries from './data/countries.json' 13 | import skills from './data/skills.json' 14 | 15 | const validationSchema = object().shape({ 16 | username: string().required('Username is required'), 17 | gender: string().required('Gender selection is required'), 18 | country: string().nullable().required('Country is required'), 19 | skills: array().required('At least one skill is required'), 20 | birthdate: date().nullable().required('Birth date is required'), 21 | interviewTime: mixed().required('Interview Time is required'), 22 | education: string().required('Education is required'), 23 | }) 24 | 25 | const initialValues = { 26 | username: '', 27 | gender: 'Female', 28 | country: null, 29 | skills: [ 30 | { 31 | label: 'ASP.NET', 32 | value: 'ASP.NET', 33 | }, 34 | ], 35 | birthdate: null, 36 | interviewTime: null, 37 | education: '', 38 | } 39 | 40 | const SimpleFormExample = () => ( 41 |
42 |

Simple Form Example

43 | { 49 | // eslint-disable-next-line no-alert 50 | window.alert(` 51 | Username: ${values.username} 52 | Gender: ${values.gender} 53 | Country: ${values.country.label} 54 | Skills: ${values.skills.map((v) => v.label).join(', ')} 55 | Birth date: ${values.birthdate} 56 | Interview Time: ${values.interviewTime} 57 | `) 58 | }} 59 | > 60 | {(formik) => ( 61 |
62 | 70 | 84 | 95 | 107 | 116 | 126 | 141 | 144 | 145 | )} 146 |
147 |
148 | ) 149 | 150 | export default SimpleFormExample 151 | -------------------------------------------------------------------------------- /example/src/data/countries.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "label": "Afghanistan", 4 | "value": "AF" 5 | }, 6 | { 7 | "label": "Åland Islands", 8 | "value": "AX" 9 | }, 10 | { 11 | "label": "Albania", 12 | "value": "AL" 13 | }, 14 | { 15 | "label": "Algeria", 16 | "value": "DZ" 17 | }, 18 | { 19 | "label": "American Samoa", 20 | "value": "AS" 21 | }, 22 | { 23 | "label": "Andorra", 24 | "value": "AD" 25 | }, 26 | { 27 | "label": "Angola", 28 | "value": "AO" 29 | }, 30 | { 31 | "label": "Anguilla", 32 | "value": "AI" 33 | }, 34 | { 35 | "label": "Antarctica", 36 | "value": "AQ" 37 | }, 38 | { 39 | "label": "Antigua and Barbuda", 40 | "value": "AG" 41 | }, 42 | { 43 | "label": "Argentina", 44 | "value": "AR" 45 | }, 46 | { 47 | "label": "Armenia", 48 | "value": "AM" 49 | }, 50 | { 51 | "label": "Aruba", 52 | "value": "AW" 53 | }, 54 | { 55 | "label": "Australia", 56 | "value": "AU" 57 | }, 58 | { 59 | "label": "Austria", 60 | "value": "AT" 61 | }, 62 | { 63 | "label": "Azerbaijan", 64 | "value": "AZ" 65 | }, 66 | { 67 | "label": "Bahamas", 68 | "value": "BS" 69 | }, 70 | { 71 | "label": "Bahrain", 72 | "value": "BH" 73 | }, 74 | { 75 | "label": "Bangladesh", 76 | "value": "BD" 77 | }, 78 | { 79 | "label": "Barbados", 80 | "value": "BB" 81 | }, 82 | { 83 | "label": "Belarus", 84 | "value": "BY" 85 | }, 86 | { 87 | "label": "Belgium", 88 | "value": "BE" 89 | }, 90 | { 91 | "label": "Belize", 92 | "value": "BZ" 93 | }, 94 | { 95 | "label": "Benin", 96 | "value": "BJ" 97 | }, 98 | { 99 | "label": "Bermuda", 100 | "value": "BM" 101 | }, 102 | { 103 | "label": "Bhutan", 104 | "value": "BT" 105 | }, 106 | { 107 | "label": "Bolivia", 108 | "value": "BO" 109 | }, 110 | { 111 | "label": "Bosnia and Herzegovina", 112 | "value": "BA" 113 | }, 114 | { 115 | "label": "Botswana", 116 | "value": "BW" 117 | }, 118 | { 119 | "label": "Bouvet Island", 120 | "value": "BV" 121 | }, 122 | { 123 | "label": "Brazil", 124 | "value": "BR" 125 | }, 126 | { 127 | "label": "British Indian Ocean Territory", 128 | "value": "IO" 129 | }, 130 | { 131 | "label": "Brunei Darussalam", 132 | "value": "BN" 133 | }, 134 | { 135 | "label": "Bulgaria", 136 | "value": "BG" 137 | }, 138 | { 139 | "label": "Burkina Faso", 140 | "value": "BF" 141 | }, 142 | { 143 | "label": "Burundi", 144 | "value": "BI" 145 | } 146 | ] 147 | -------------------------------------------------------------------------------- /example/src/data/skills.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "label": "Acceptance Testing", 4 | "value": "Acceptance Testing" 5 | }, 6 | { 7 | "label": "ASP.NET", 8 | "value": "ASP.NET" 9 | }, 10 | { 11 | "label": "Automated Testing", 12 | "value": "Automated Testing" 13 | }, 14 | { 15 | "label": "C#", 16 | "value": "C#" 17 | }, 18 | { 19 | "label": "C", 20 | "value": "C" 21 | }, 22 | { 23 | "label": "C++", 24 | "value": "C++" 25 | }, 26 | { 27 | "label": "CSS3", 28 | "value": "CSS3" 29 | }, 30 | { 31 | "label": "Docker", 32 | "value": "Docker" 33 | }, 34 | { 35 | "label": "ES6", 36 | "value": "ES6" 37 | }, 38 | { 39 | "label": "HTML5", 40 | "value": "HTML5" 41 | }, 42 | { 43 | "label": "Java", 44 | "value": "Java" 45 | }, 46 | { 47 | "label": "Javascript", 48 | "value": "Javascript" 49 | }, 50 | { 51 | "label": "MongoDB", 52 | "value": "MongoDB" 53 | }, 54 | { 55 | "label": "MySQL", 56 | "value": "MySQL" 57 | }, 58 | { 59 | "label": "PostgreSQL", 60 | "value": "PostgreSQL" 61 | }, 62 | { 63 | "label": "Python", 64 | "value": "Python" 65 | }, 66 | { 67 | "label": "React", 68 | "value": "React" 69 | }, 70 | { 71 | "label": "Redis", 72 | "value": "Redis" 73 | }, 74 | { 75 | "label": "Swift", 76 | "value": "Swift" 77 | }, 78 | { 79 | "label": "Webpack", 80 | "value": "Webpack" 81 | } 82 | ] -------------------------------------------------------------------------------- /example/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: sans-serif; 3 | padding: 20px; 4 | } 5 | 6 | h1 { 7 | font-weight: 300; 8 | } 9 | -------------------------------------------------------------------------------- /example/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import { MuiPickersUtilsProvider } from '@material-ui/pickers' 4 | import DateFnsUtils from '@date-io/date-fns' 5 | import SimpleFormExample from './SimpleFormExample' 6 | import FieldArrayExample from './FieldArrayExample' 7 | 8 | import './index.css' 9 | 10 | const rootElement = document.getElementById('root') 11 | ReactDOM.render( 12 | 13 | 14 |
15 | 16 | , 17 | rootElement 18 | ) 19 | -------------------------------------------------------------------------------- /example/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const { CleanWebpackPlugin } = require('clean-webpack-plugin') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | 5 | module.exports = { 6 | mode: 'development', 7 | devtool: 'inline-source-map', 8 | entry: { 9 | app: './src/index.js', 10 | }, 11 | output: { 12 | filename: 'app.min.js', 13 | path: path.resolve(__dirname, '../dist'), 14 | publicPath: '/', 15 | }, 16 | module: { 17 | rules: [ 18 | { 19 | test: /\.(js|jsx)$/, 20 | exclude: /node_modules/, 21 | use: { 22 | loader: 'babel-loader', 23 | }, 24 | }, 25 | { 26 | test: /\.html$/, 27 | use: [ 28 | { 29 | loader: 'html-loader', 30 | }, 31 | ], 32 | }, 33 | { 34 | test: /\.css$/, 35 | use: [ 36 | 'style-loader', // creates style nodes from JS strings 37 | 'css-loader', // translates CSS into CommonJS 38 | ], 39 | }, 40 | ], 41 | }, 42 | plugins: [ 43 | new CleanWebpackPlugin(), 44 | new HtmlWebpackPlugin({ 45 | template: './public/index.html', 46 | filename: 'index.html', 47 | }), 48 | ], 49 | devServer: { 50 | contentBase: path.join(__dirname, '../public'), 51 | compress: true, 52 | historyApiFallback: true, 53 | }, 54 | resolve: { 55 | alias: { 56 | react: path.resolve('./node_modules/react'), 57 | '@material-ui/core': path.resolve('./node_modules/@material-ui/core'), 58 | '@material-ui/lab': path.resolve('./node_modules/@material-ui/lab'), 59 | '@material-ui/styles': path.resolve('./node_modules/@material-ui/styles'), 60 | '@material-ui/pickers': path.resolve( 61 | './node_modules/@material-ui/pickers' 62 | ), 63 | 'prop-types': path.resolve('./node_modules/prop-types'), 64 | formik: path.resolve('./node_modules/formik'), 65 | 'material-ui-chip-input': path.resolve( 66 | './node_modules/material-ui-chip-input' 67 | ), 68 | }, 69 | extensions: ['.jsx', '.js', '.json'], 70 | }, 71 | } 72 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "material-ui-formik-components", 3 | "version": "0.7.3", 4 | "author": "Gerasimos Chatzidamianos (https://github.com/gerhat)", 5 | "license": "MIT", 6 | "keywords": [ 7 | "react", 8 | "formik", 9 | "material-ui", 10 | "form component", 11 | "form", 12 | "autocomplete", 13 | "material-ui-pickers", 14 | "material-ui-chip-input" 15 | ], 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/gerhat/material-ui-formik-components.git" 19 | }, 20 | "peerDependencies": { 21 | "@material-ui/core": ">=4", 22 | "@material-ui/lab": ">=4.0.0-alpha.45", 23 | "formik": ">=2", 24 | "react": ">=16.8", 25 | "react-dom": ">=16.8" 26 | }, 27 | "optionalDependencies": { 28 | "@material-ui/pickers": ">=3", 29 | "@date-io/date-fns": ">= 1 <2", 30 | "date-fns": ">=2", 31 | "material-ui-chip-input": ">=1" 32 | }, 33 | "devDependencies": { 34 | "@babel/cli": "^7.12.1", 35 | "@babel/core": "^7.12.3", 36 | "@babel/node": "^7.12.1", 37 | "@babel/plugin-proposal-class-properties": "^7.12.1", 38 | "@babel/preset-env": "^7.12.1", 39 | "@babel/preset-react": "^7.12.1", 40 | "@material-ui/core": "^4.11.0", 41 | "@material-ui/lab": "4.0.0-alpha.56", 42 | "@material-ui/pickers": "^3.2.10", 43 | "babel-eslint": "^10.1.0", 44 | "classnames": "^2.2.6", 45 | "cross-env": "^7.0.2", 46 | "eslint": "^7.11.0", 47 | "eslint-config-airbnb": "^18.2.0", 48 | "eslint-config-prettier": "^6.14.0", 49 | "eslint-config-standard": "^15.0.0", 50 | "eslint-config-standard-react": "^9.2.0", 51 | "eslint-import-resolver-webpack": "^0.13.0", 52 | "eslint-module-utils": "^2.6.0", 53 | "eslint-plugin-import": "^2.22.1", 54 | "eslint-plugin-jsx-a11y": "^6.3.1", 55 | "eslint-plugin-node": "^11.1.0", 56 | "eslint-plugin-prettier": "^3.1.4", 57 | "eslint-plugin-promise": "^4.2.1", 58 | "eslint-plugin-react": "^7.21.5", 59 | "eslint-plugin-standard": "^4.0.2", 60 | "eslint-watch": "^7.0.0", 61 | "formik": "^2.2.0", 62 | "fs-extra": "^9.0.1", 63 | "glob": "^7.1.6", 64 | "husky": "^4.3.0", 65 | "lint-staged": "^10.4.2", 66 | "material-ui-chip-input": "^1.1.0", 67 | "path": "^0.12.7", 68 | "prettier": "^2.1.2", 69 | "pretty-quick": "^3.1.0", 70 | "prop-types": "^15.7.2", 71 | "react": "^17.0.1", 72 | "react-dom": "^17.0.1", 73 | "react-test-renderer": "^17.0.1", 74 | "rimraf": "^3.0.2" 75 | }, 76 | "main": "index.js", 77 | "module": "index.es.js", 78 | "types": "index.d.ts", 79 | "scripts": { 80 | "prebuild": "rimraf dist", 81 | "build:es2015": "cross-env NODE_ENV=production babel --config-file ./babel.config.js ./src --out-dir ./dist --ignore *.test.js* --copy-files", 82 | "build:es2015modules": "cross-env NODE_ENV=production BABEL_ENV=modules babel --config-file ./babel.config.js ./src/index.js --out-file ./dist/index.es.js --copy-files", 83 | "build:copy-files": "babel-node --config-file ./babel.config.js ./scripts/copy-files.js", 84 | "build:all": "npm run build:es2015 && npm run build:es2015modules && npm run build:es && npm run build:umd && npm run build:copy-files", 85 | "build": "npm run build:es2015 && npm run build:es2015modules && npm run build:copy-files", 86 | "link": "npm run build && npm link dist", 87 | "lint": "eslint src/**/*.{js,jsx}", 88 | "lint:watch": "esw -w src/**/*.{js,jsx}", 89 | "lint:fix": "eslint src/ --fix src/**/*.{js,jsx}", 90 | "release": "npm run build && npm publish dist", 91 | "release:test": "npm run release --dry-run" 92 | }, 93 | "husky": { 94 | "hooks": { 95 | "pre-commit": "cross-env NODE_ENV=production lint-staged" 96 | } 97 | }, 98 | "lint-staged": { 99 | "*.{js,jsx}": [ 100 | "pretty-quick --staged", 101 | "eslint src/ --fix" 102 | ] 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /scripts/copy-files.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import path from 'path' 4 | import fse from 'fs-extra' 5 | import glob from 'glob' 6 | 7 | const outDir = 'dist' 8 | 9 | async function copyFile (file) { 10 | const buildPath = path.resolve(__dirname, `../${outDir}/`, path.basename(file)) 11 | await fse.copy(file, buildPath) 12 | console.log(`Copied ${file} to ${buildPath}`) 13 | } 14 | 15 | function typescriptCopy (from, to) { 16 | const files = glob.sync('**/*.d.ts', { cwd: from }) 17 | const cmds = files.map(file => fse.copy(path.resolve(from, file), path.resolve(to, file))) 18 | return Promise.all(cmds) 19 | } 20 | 21 | async function createPackageFile () { 22 | const packageData = await fse.readFile(path.resolve(__dirname, '../package.json'), 'utf8') 23 | const { nyc, scripts, devDependencies, workspaces, ...packageDataOther } = JSON.parse( 24 | packageData 25 | ) 26 | const newPackageData = { 27 | ...packageDataOther, 28 | main: './index.js', 29 | module: './index.es.js' 30 | } 31 | const buildPath = path.resolve(__dirname, `../${outDir}/package.json`) 32 | 33 | await fse.writeFile(buildPath, JSON.stringify(newPackageData, null, 2), 'utf8') 34 | console.log(`Created package.json in ${buildPath}`) 35 | 36 | return newPackageData 37 | } 38 | 39 | async function prepend (file, string) { 40 | const data = await fse.readFile(file, 'utf8') 41 | await fse.writeFile(file, string + data, 'utf8') 42 | } 43 | 44 | async function addLicense (packageData) { 45 | const license = `/** @license material-ui-formik-components v${packageData.version} 46 | * 47 | * This source code is licensed under the MIT license found in the 48 | * LICENSE file in the root directory of this source tree. 49 | */ 50 | ` 51 | await Promise.all( 52 | [ 53 | `../${outDir}/index.js`, 54 | `../${outDir}/index.es.js` 55 | ].map(file => prepend(path.resolve(__dirname, file), license)) 56 | ) 57 | } 58 | 59 | async function run () { 60 | await Promise.all( 61 | ['README.md', 'CHANGELOG.md', 'LICENSE'].map(file => copyFile(file)) 62 | ) 63 | const packageData = await createPackageFile() 64 | await addLicense(packageData) 65 | 66 | // TypeScript 67 | const from = path.resolve(__dirname, '../src') 68 | await Promise.all([ 69 | typescriptCopy(from, path.resolve(__dirname, `../${outDir}`)), 70 | typescriptCopy(from, path.resolve(__dirname, `../${outDir}/es`)) 71 | ]) 72 | } 73 | 74 | run() 75 | -------------------------------------------------------------------------------- /src/Autocomplete/Autocomplete.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { AutocompleteProps } from '@material-ui/lab/Autocomplete' 3 | import { FieldProps, FormikProps, FormikValues } from 'formik' 4 | import { SelectOptionsType } from '..' 5 | 6 | export interface FAutocompleteProps 7 | extends AutocompleteProps { 8 | field: FieldProps 9 | form: FormikProps 10 | options: Array 11 | textFieldProps: { 12 | label?: string 13 | required?: boolean 14 | fullWidth?: boolean 15 | margin?: 'none' | 'dense' | 'normal' 16 | } 17 | } 18 | 19 | declare const FAutocomplete: React.ComponentType 20 | 21 | export default FAutocomplete 22 | -------------------------------------------------------------------------------- /src/Autocomplete/Autocomplete.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/jsx-props-no-spreading */ 2 | import React from 'react' 3 | import PropTypes from 'prop-types' 4 | import TextField from '@material-ui/core/TextField' 5 | import Autocomplete from '@material-ui/lab/Autocomplete' 6 | import { getIn } from 'formik' 7 | 8 | const FAutocomplete = (props) => { 9 | const { 10 | field, 11 | form: { dirty, touched, errors, setFieldValue }, 12 | options, 13 | getOptionLabel, 14 | textFieldProps, 15 | ...autoCompleteProps 16 | } = props 17 | 18 | // Merge default textFieldProps with textFieldProps passed in the component 19 | const mergedTextFieldProps = { 20 | ...FAutocomplete.defaultProps.textFieldProps, 21 | ...textFieldProps, 22 | } 23 | const errorText = getIn(errors, field.name) 24 | const touchedVal = getIn(touched, field.name) 25 | const hasError = dirty && touchedVal && errorText !== undefined 26 | const isMultiple = autoCompleteProps.multiple 27 | const isMultipleWithValue = isMultiple && field.value 28 | const canBeRendered = !isMultiple || isMultipleWithValue 29 | 30 | if (isMultiple && field.value === null) { 31 | // eslint-disable-next-line no-console 32 | console.error( 33 | `Initial value of autocomplete with name: "${field.name}" cannot be null. Use [] instead.` 34 | ) 35 | } 36 | 37 | return ( 38 | <> 39 | {canBeRendered && ( 40 | setFieldValue(field.name, value)} 44 | value={field.value} 45 | getOptionSelected={(option, val) => option.value === val.value} 46 | renderInput={(params) => ( 47 | 53 | )} 54 | {...autoCompleteProps} 55 | /> 56 | )} 57 | 58 | ) 59 | } 60 | 61 | FAutocomplete.propTypes = { 62 | form: PropTypes.shape({ 63 | dirty: PropTypes.bool, 64 | errors: PropTypes.object, 65 | setFieldValue: PropTypes.func, 66 | }).isRequired, 67 | options: PropTypes.arrayOf( 68 | PropTypes.shape({ 69 | label: PropTypes.string, 70 | value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 71 | }) 72 | ).isRequired, 73 | getOptionLabel: PropTypes.func, 74 | textFieldProps: PropTypes.shape({ 75 | label: PropTypes.string, 76 | required: PropTypes.bool, 77 | fullWidth: PropTypes.bool, 78 | margin: PropTypes.oneOf(['none', 'dense', 'normal']), 79 | }), 80 | } 81 | 82 | FAutocomplete.defaultProps = { 83 | getOptionLabel: (option) => option.label, 84 | textFieldProps: { 85 | required: false, 86 | fullWidth: true, 87 | margin: 'normal', 88 | }, 89 | } 90 | 91 | export default FAutocomplete 92 | -------------------------------------------------------------------------------- /src/Autocomplete/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as Autocomplete } from './Autocomplete' 2 | -------------------------------------------------------------------------------- /src/Autocomplete/index.js: -------------------------------------------------------------------------------- 1 | export { default as Autocomplete } from './Autocomplete' 2 | -------------------------------------------------------------------------------- /src/ChipInput/ChipInput.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { FieldProps, FormikProps, FormikValues } from 'formik' 3 | 4 | export interface FChipInputProps { 5 | label?: string 6 | field: FieldProps 7 | form: FormikProps 8 | fullWidth?: boolean 9 | margin?: 'none' | 'dense' | 'normal' 10 | newChipKeyCodes?: number 11 | } 12 | 13 | declare const FChipInputProps: React.ComponentType 14 | 15 | export default FChipInputProps 16 | -------------------------------------------------------------------------------- /src/ChipInput/ChipInput.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | import ChipInput from 'material-ui-chip-input' 4 | import { getIn } from 'formik' 5 | 6 | class FChipInput extends React.PureComponent { 7 | handleAddChip = chip => { 8 | const { 9 | form: { setFieldValue }, 10 | field: { name, value }, 11 | } = this.props 12 | 13 | const newValue = [...value, chip] 14 | setFieldValue(name, newValue) 15 | } 16 | 17 | handleDeleteChip = (chip, index) => { 18 | const { 19 | form: { setFieldValue }, 20 | field: { name, value }, 21 | } = this.props 22 | 23 | const newValue = value.filter((val, idx) => idx !== index) 24 | setFieldValue(name, newValue) 25 | } 26 | 27 | render() { 28 | const { 29 | required, 30 | form: { dirty, touched, errors }, 31 | field: { name, value }, 32 | options, 33 | fullWidth, 34 | margin, 35 | ...other 36 | } = this.props 37 | 38 | const id = `chip_${name}` 39 | const errorText = getIn(errors, name) 40 | const touchedVal = getIn(touched, name) 41 | const hasError = dirty && touchedVal && errorText !== undefined 42 | 43 | return ( 44 | 60 | ) 61 | } 62 | } 63 | 64 | FChipInput.propTypes = { 65 | label: PropTypes.string, 66 | field: PropTypes.shape({ 67 | name: PropTypes.string, 68 | onChange: PropTypes.func, 69 | value: PropTypes.arrayOf(PropTypes.string), 70 | }).isRequired, 71 | form: PropTypes.shape({ 72 | dirty: PropTypes.bool, 73 | errors: PropTypes.object, 74 | }).isRequired, 75 | fullWidth: PropTypes.bool, 76 | margin: PropTypes.oneOf(['none', 'dense', 'normal']), 77 | newChipKeyCodes: PropTypes.arrayOf(PropTypes.number), 78 | } 79 | 80 | FChipInput.defaultProps = { 81 | label: '', 82 | fullWidth: true, 83 | margin: 'normal', 84 | // http://gcctech.org/csc/javascript/javascript_keycodes.htm 85 | // Enter, Space, Comma 86 | newChipKeyCodes: [13, 32, 188], 87 | } 88 | 89 | export default FChipInput 90 | -------------------------------------------------------------------------------- /src/ChipInput/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as ChipInput } from './ChipInput' 2 | -------------------------------------------------------------------------------- /src/ChipInput/index.js: -------------------------------------------------------------------------------- 1 | export { default as ChipInput } from './ChipInput' 2 | -------------------------------------------------------------------------------- /src/DatePicker/DatePicker.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { FieldProps, FormikProps, FormikValues } from 'formik' 3 | 4 | export interface FDatePickerProps { 5 | label?: string 6 | field: FieldProps 7 | form: FormikProps 8 | fullWidth?: boolean 9 | margin?: 'none' | 'dense' | 'normal' 10 | autoOk?: boolean 11 | } 12 | 13 | declare const FDatePickerProps: React.ComponentType 14 | 15 | export default FDatePickerProps 16 | -------------------------------------------------------------------------------- /src/DatePicker/DatePicker.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | import { DatePicker } from '@material-ui/pickers' 4 | import { getIn } from 'formik' 5 | 6 | const FDatePicker = (props) => { 7 | const { 8 | label, 9 | field, 10 | form: { touched, errors, setFieldValue }, 11 | ...other 12 | } = props 13 | const errorText = getIn(errors, field.name) 14 | const touchedVal = getIn(touched, field.name) 15 | const hasError = touchedVal && errorText !== undefined 16 | return ( 17 | setFieldValue(field.name, value)} 22 | value={field.value} 23 | // eslint-disable-next-line react/jsx-props-no-spreading 24 | {...other} 25 | /> 26 | ) 27 | } 28 | 29 | FDatePicker.propTypes = { 30 | label: PropTypes.string.isRequired, 31 | field: PropTypes.shape({ 32 | name: PropTypes.string, 33 | value: PropTypes.any, 34 | }).isRequired, 35 | form: PropTypes.shape({ 36 | dirty: PropTypes.bool, 37 | errors: PropTypes.object, 38 | }).isRequired, 39 | fullWidth: PropTypes.bool, 40 | margin: PropTypes.oneOf(['none', 'dense', 'normal']), 41 | autoOk: PropTypes.bool, 42 | } 43 | 44 | FDatePicker.defaultProps = { 45 | fullWidth: true, 46 | margin: 'normal', 47 | autoOk: true, 48 | } 49 | 50 | export default FDatePicker 51 | -------------------------------------------------------------------------------- /src/DatePicker/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as DatePicker } from './DatePicker' 2 | -------------------------------------------------------------------------------- /src/DatePicker/index.js: -------------------------------------------------------------------------------- 1 | export { default as DatePicker } from './DatePicker' 2 | -------------------------------------------------------------------------------- /src/DateTimePicker/DateTimePicker.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { FieldProps, FormikProps, FormikValues } from 'formik'; 3 | 4 | export interface FDateTimePickerProps { 5 | label?: string; 6 | field: FieldProps; 7 | form: FormikProps; 8 | fullWidth?: boolean; 9 | margin?: 'none' | 'dense' | 'normal'; 10 | ampm?: boolean; 11 | autoOk?: boolean; 12 | } 13 | 14 | declare const FDateTimePickerProps: React.ComponentType; 15 | 16 | export default FDateTimePickerProps; 17 | -------------------------------------------------------------------------------- /src/DateTimePicker/DateTimePicker.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | import { DateTimePicker } from '@material-ui/pickers' 4 | import { getIn } from 'formik' 5 | 6 | class FDateTimePicker extends React.PureComponent { 7 | render() { 8 | const { 9 | label, 10 | field, 11 | form: { touched, errors, setFieldValue }, 12 | ...other 13 | } = this.props 14 | const errorText = getIn(errors, field.name) 15 | const touchedVal = getIn(touched, field.name) 16 | const hasError = touchedVal && errorText !== undefined 17 | return ( 18 | setFieldValue(field.name, value)} 23 | value={field.value} 24 | // eslint-disable-next-line react/jsx-props-no-spreading 25 | {...other} 26 | /> 27 | ) 28 | } 29 | } 30 | 31 | FDateTimePicker.propTypes = { 32 | label: PropTypes.string.isRequired, 33 | field: PropTypes.shape({ 34 | name: PropTypes.string, 35 | value: PropTypes.any, 36 | }).isRequired, 37 | form: PropTypes.shape({ 38 | dirty: PropTypes.bool, 39 | errors: PropTypes.object, 40 | }).isRequired, 41 | fullWidth: PropTypes.bool, 42 | margin: PropTypes.oneOf(['none', 'dense', 'normal']), 43 | ampm: PropTypes.bool, 44 | autoOk: PropTypes.bool, 45 | } 46 | 47 | FDateTimePicker.defaultProps = { 48 | fullWidth: true, 49 | margin: 'normal', 50 | ampm: false, 51 | autoOk: true, 52 | } 53 | 54 | export default FDateTimePicker 55 | -------------------------------------------------------------------------------- /src/DateTimePicker/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as DateTimePicker } from './DateTimePicker' 2 | -------------------------------------------------------------------------------- /src/DateTimePicker/index.js: -------------------------------------------------------------------------------- 1 | export { default as DateTimePicker } from './DateTimePicker' 2 | -------------------------------------------------------------------------------- /src/KeyboardDatePicker/KeyboardDatePicker.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { FieldProps, FormikProps, FormikValues } from 'formik' 3 | 4 | export interface FKeyboardDatePickerProps { 5 | label?: string 6 | field: FieldProps 7 | form: FormikProps 8 | fullWidth?: boolean 9 | margin?: 'none' | 'dense' | 'normal' 10 | autoOk?: boolean 11 | } 12 | 13 | declare const FKeyboardDatePickerProps: React.ComponentType 14 | 15 | export default FKeyboardDatePickerProps 16 | -------------------------------------------------------------------------------- /src/KeyboardDatePicker/KeyboardDatePicker.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | import { KeyboardDatePicker } from '@material-ui/pickers' 4 | import { getIn } from 'formik' 5 | 6 | const FKeyboardDatePicker = (props) => { 7 | const { 8 | label, 9 | field, 10 | form: { touched, errors, setFieldValue }, 11 | ...other 12 | } = props 13 | const errorText = getIn(errors, field.name) 14 | const touchedVal = getIn(touched, field.name) 15 | const hasError = touchedVal && errorText !== undefined 16 | return ( 17 | setFieldValue(field.name, value)} 22 | value={field.value} 23 | // eslint-disable-next-line react/jsx-props-no-spreading 24 | {...other} 25 | /> 26 | ) 27 | } 28 | 29 | FKeyboardDatePicker.propTypes = { 30 | label: PropTypes.string.isRequired, 31 | field: PropTypes.shape({ 32 | name: PropTypes.string, 33 | value: PropTypes.any, 34 | }).isRequired, 35 | form: PropTypes.shape({ 36 | dirty: PropTypes.bool, 37 | errors: PropTypes.object, 38 | }).isRequired, 39 | fullWidth: PropTypes.bool, 40 | margin: PropTypes.oneOf(['none', 'dense', 'normal']), 41 | autoOk: PropTypes.bool, 42 | } 43 | 44 | FKeyboardDatePicker.defaultProps = { 45 | fullWidth: true, 46 | margin: 'normal', 47 | autoOk: true, 48 | } 49 | 50 | export default FKeyboardDatePicker 51 | -------------------------------------------------------------------------------- /src/KeyboardDatePicker/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as KeyboardDatePicker } from './KeyboardDatePicker' 2 | -------------------------------------------------------------------------------- /src/KeyboardDatePicker/index.js: -------------------------------------------------------------------------------- 1 | export { default as KeyboardDatePicker } from './KeyboardDatePicker' 2 | -------------------------------------------------------------------------------- /src/KeyboardDateTimePicker/KeyboardDateTimePicker.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { FieldProps, FormikProps, FormikValues } from 'formik' 3 | 4 | export interface FKeyboardDateTimePickerProps { 5 | label?: string 6 | field: FieldProps 7 | form: FormikProps 8 | fullWidth?: boolean 9 | margin?: 'none' | 'dense' | 'normal' 10 | autoOk?: boolean 11 | } 12 | 13 | declare const FKeyboardDateTimePickerProps: React.ComponentType 14 | 15 | export default FKeyboardDateTimePickerProps 16 | -------------------------------------------------------------------------------- /src/KeyboardDateTimePicker/KeyboardDateTimePicker.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | import { KeyboardDateTimePicker } from '@material-ui/pickers' 4 | import { getIn } from 'formik' 5 | 6 | const FKeyboardDateTimePicker = (props) => { 7 | const { 8 | label, 9 | field, 10 | form: { touched, errors, setFieldValue }, 11 | ...other 12 | } = props 13 | const errorText = getIn(errors, field.name) 14 | const touchedVal = getIn(touched, field.name) 15 | const hasError = touchedVal && errorText !== undefined 16 | return ( 17 | setFieldValue(field.name, value)} 22 | value={field.value} 23 | // eslint-disable-next-line react/jsx-props-no-spreading 24 | {...other} 25 | /> 26 | ) 27 | } 28 | 29 | FKeyboardDateTimePicker.propTypes = { 30 | label: PropTypes.string.isRequired, 31 | field: PropTypes.shape({ 32 | name: PropTypes.string, 33 | value: PropTypes.any, 34 | }).isRequired, 35 | form: PropTypes.shape({ 36 | dirty: PropTypes.bool, 37 | errors: PropTypes.object, 38 | }).isRequired, 39 | fullWidth: PropTypes.bool, 40 | margin: PropTypes.oneOf(['none', 'dense', 'normal']), 41 | autoOk: PropTypes.bool, 42 | } 43 | 44 | FKeyboardDateTimePicker.defaultProps = { 45 | fullWidth: true, 46 | margin: 'normal', 47 | autoOk: true, 48 | } 49 | 50 | export default FKeyboardDateTimePicker 51 | -------------------------------------------------------------------------------- /src/KeyboardDateTimePicker/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as KeyboardDateTimePicker } from './KeyboardDateTimePicker' 2 | -------------------------------------------------------------------------------- /src/KeyboardDateTimePicker/index.js: -------------------------------------------------------------------------------- 1 | export { default as KeyboardDateTimePicker } from './KeyboardDateTimePicker' 2 | -------------------------------------------------------------------------------- /src/KeyboardTimePicker/KeyboardTimePicker.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { FieldProps, FormikProps, FormikValues } from 'formik' 3 | 4 | export interface FKeyboardTimePickerProps { 5 | label?: string 6 | field: FieldProps 7 | form: FormikProps 8 | fullWidth?: boolean 9 | margin?: 'none' | 'dense' | 'normal' 10 | autoOk?: boolean 11 | } 12 | 13 | declare const FKeyboardTimePickerProps: React.ComponentType 14 | 15 | export default FKeyboardTimePickerProps 16 | -------------------------------------------------------------------------------- /src/KeyboardTimePicker/KeyboardTimePicker.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | import { KeyboardTimePicker } from '@material-ui/pickers' 4 | import { getIn } from 'formik' 5 | 6 | const FKeyboardTimePicker = (props) => { 7 | const { 8 | label, 9 | field, 10 | form: { touched, errors, setFieldValue }, 11 | ...other 12 | } = props 13 | const errorText = getIn(errors, field.name) 14 | const touchedVal = getIn(touched, field.name) 15 | const hasError = touchedVal && errorText !== undefined 16 | return ( 17 | setFieldValue(field.name, value)} 22 | value={field.value} 23 | // eslint-disable-next-line react/jsx-props-no-spreading 24 | {...other} 25 | /> 26 | ) 27 | } 28 | 29 | FKeyboardTimePicker.propTypes = { 30 | label: PropTypes.string.isRequired, 31 | field: PropTypes.shape({ 32 | name: PropTypes.string, 33 | value: PropTypes.any, 34 | }).isRequired, 35 | form: PropTypes.shape({ 36 | dirty: PropTypes.bool, 37 | errors: PropTypes.object, 38 | }).isRequired, 39 | fullWidth: PropTypes.bool, 40 | margin: PropTypes.oneOf(['none', 'dense', 'normal']), 41 | autoOk: PropTypes.bool, 42 | } 43 | 44 | FKeyboardTimePicker.defaultProps = { 45 | fullWidth: true, 46 | margin: 'normal', 47 | autoOk: true, 48 | } 49 | 50 | export default FKeyboardTimePicker 51 | -------------------------------------------------------------------------------- /src/KeyboardTimePicker/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as KeyboardTimePicker } from './KeyboardTimePicker' 2 | -------------------------------------------------------------------------------- /src/KeyboardTimePicker/index.js: -------------------------------------------------------------------------------- 1 | export { default as KeyboardTimePicker } from './KeyboardTimePicker' 2 | -------------------------------------------------------------------------------- /src/RadioGroup/RadioGroup.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { FieldProps, FormikProps, FormikValues } from 'formik' 3 | import { RadioGroupOptionsType } from '..' 4 | 5 | /** 6 | * Classnames that can be used for the customization of RadioGroup 7 | */ 8 | export interface FRadioClasses { 9 | formControl?: string 10 | formLabel?: string 11 | radioGroup?: string 12 | formControlLabel?: string 13 | radio?: string 14 | formHelperText?: string 15 | } 16 | 17 | export interface FRadioGroupComponentProps { 18 | row?: boolean 19 | } 20 | 21 | export interface FRadioGroupProps { 22 | /** 23 | * The RadioGroup label 24 | */ 25 | label?: string 26 | 27 | /** 28 | * Field props passed from Formik 29 | * https://formik.org/docs/api/field#props-1 30 | */ 31 | field: FieldProps 32 | 33 | /** 34 | * Formik props passed from Formik 35 | * https://formik.org/docs/api/formik#props-1 36 | */ 37 | form: FormikProps 38 | 39 | /** 40 | * The radio group options 41 | */ 42 | options: Array 43 | 44 | /** 45 | * Displays an asterisk if required is true 46 | */ 47 | required?: boolean 48 | 49 | /** 50 | * If `true`, the component will take up the full width of its container 51 | * @default true 52 | */ 53 | fullWidth?: boolean 54 | 55 | /** 56 | * If `dense` or `normal`, will adjust vertical spacing of this and contained components 57 | * @default normal 58 | */ 59 | margin?: 'none' | 'dense' | 'normal' 60 | 61 | /** 62 | * Use this prop to set classNames to the various internal components 63 | */ 64 | classes?: FRadioClasses 65 | 66 | /** 67 | * RadioGroup props that are spread at `` component 68 | * https://material-ui.com/api/radio-group/ 69 | */ 70 | groupProps?: FRadioGroupComponentProps 71 | } 72 | 73 | declare const FRadioGroupProps: React.ComponentType 74 | 75 | export default FRadioGroupProps 76 | -------------------------------------------------------------------------------- /src/RadioGroup/RadioGroup.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/forbid-prop-types */ 2 | import React from 'react' 3 | import PropTypes, { bool } from 'prop-types' 4 | import RadioGroup from '@material-ui/core/RadioGroup' 5 | import Radio from '@material-ui/core/Radio' 6 | import FormControl from '@material-ui/core/FormControl' 7 | import FormControlLabel from '@material-ui/core/FormControlLabel' 8 | import FormLabel from '@material-ui/core/FormLabel' 9 | import FormHelperText from '@material-ui/core/FormHelperText' 10 | import { getIn } from 'formik' 11 | 12 | class FRadioGroup extends React.PureComponent { 13 | render() { 14 | const { 15 | label, 16 | field, 17 | form: { touched, errors, setFieldValue }, 18 | options, 19 | required, 20 | fullWidth, 21 | margin, 22 | classes, 23 | groupProps, 24 | ...other 25 | } = this.props 26 | const errorText = getIn(errors, field.name) 27 | const touchedVal = getIn(touched, field.name) 28 | const hasError = touchedVal && errorText !== undefined 29 | return ( 30 | 40 | 43 | {label} 44 | 45 | setFieldValue(field.name, event.target.value)} 52 | className={classes && classes.radioGroup ? classes.radioGroup : ''} 53 | > 54 | {options.map((item) => ( 55 | 62 | } 63 | label={item.label} 64 | className={ 65 | classes && classes.formControlLabel 66 | ? classes.formControlLabel 67 | : '' 68 | } 69 | /> 70 | ))} 71 | 72 | {hasError && ( 73 | 78 | {errorText} 79 | 80 | )} 81 | 82 | ) 83 | } 84 | } 85 | 86 | FRadioGroup.propTypes = { 87 | label: PropTypes.string.isRequired, 88 | field: PropTypes.shape({ 89 | name: PropTypes.string, 90 | value: PropTypes.string, 91 | }).isRequired, 92 | form: PropTypes.shape({ 93 | touched: PropTypes.object, 94 | errors: PropTypes.object, 95 | setFieldValue: PropTypes.func, 96 | }).isRequired, 97 | options: PropTypes.arrayOf( 98 | PropTypes.shape({ 99 | value: PropTypes.string.isRequired, 100 | label: PropTypes.string.isRequired, 101 | }) 102 | ).isRequired, 103 | required: PropTypes.bool, 104 | fullWidth: PropTypes.bool, 105 | margin: PropTypes.oneOf(['none', 'dense', 'normal']), 106 | classes: PropTypes.shape({ 107 | formControl: PropTypes.string, 108 | formLabel: PropTypes.string, 109 | radioGroup: PropTypes.string, 110 | formControlLabel: PropTypes.string, 111 | radio: PropTypes.string, 112 | formHelperText: PropTypes.string, 113 | }), 114 | groupProps: PropTypes.shape({ 115 | row: bool, 116 | }), 117 | } 118 | 119 | FRadioGroup.defaultProps = { 120 | required: false, 121 | fullWidth: true, 122 | margin: 'normal', 123 | classes: undefined, 124 | groupProps: undefined, 125 | } 126 | 127 | export default FRadioGroup 128 | -------------------------------------------------------------------------------- /src/RadioGroup/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as RadioGroup } from './RadioGroup' 2 | -------------------------------------------------------------------------------- /src/RadioGroup/index.js: -------------------------------------------------------------------------------- 1 | export { default as RadioGroup } from './RadioGroup' 2 | -------------------------------------------------------------------------------- /src/Select/Select.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { FieldProps, FormikProps, FormikValues } from 'formik' 3 | import { SelectOptionsType } from '..' 4 | 5 | export interface FSelectProps { 6 | label?: string 7 | field: FieldProps 8 | form: FormikProps 9 | options: Array 10 | fullWidth?: boolean 11 | margin?: 'none' | 'dense' | 'normal' 12 | } 13 | 14 | declare const FSelect: React.ComponentType 15 | 16 | export default FSelect 17 | -------------------------------------------------------------------------------- /src/Select/Select.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/jsx-props-no-spreading */ 2 | import React from 'react' 3 | import PropTypes from 'prop-types' 4 | import MenuItem from '@material-ui/core/MenuItem' 5 | import TextField from '@material-ui/core/TextField' 6 | import { getIn } from 'formik' 7 | 8 | const FSelect = (props) => { 9 | const { 10 | label, 11 | form: { dirty, touched, errors, setFieldValue }, 12 | field: { name, value }, 13 | options, 14 | margin, 15 | fullWidth, 16 | ...other 17 | } = props 18 | const id = `sel_${name}` 19 | const errorText = getIn(errors, name) 20 | const touchedVal = getIn(touched, name) 21 | const hasError = dirty && touchedVal && errorText !== undefined 22 | 23 | return ( 24 | setFieldValue(name, e.target.value)} 30 | value={value} 31 | margin={margin} 32 | fullWidth={fullWidth} 33 | {...other} 34 | > 35 | {options.map((item) => ( 36 | 37 | {item.label} 38 | 39 | ))} 40 | 41 | ) 42 | } 43 | 44 | FSelect.propTypes = { 45 | label: PropTypes.string.isRequired, 46 | field: PropTypes.shape({ 47 | name: PropTypes.string, 48 | onChange: PropTypes.func, 49 | value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 50 | }).isRequired, 51 | form: PropTypes.shape({ 52 | dirty: PropTypes.bool, 53 | errors: PropTypes.object, 54 | }).isRequired, 55 | options: PropTypes.arrayOf( 56 | PropTypes.shape({ 57 | label: PropTypes.string.isRequired, 58 | value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) 59 | .isRequired, 60 | }) 61 | ).isRequired, 62 | fullWidth: PropTypes.bool, 63 | margin: PropTypes.oneOf(['none', 'dense', 'normal']), 64 | } 65 | 66 | FSelect.defaultProps = { 67 | fullWidth: true, 68 | margin: 'normal', 69 | } 70 | 71 | export default FSelect 72 | -------------------------------------------------------------------------------- /src/Select/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as Select } from './Select' 2 | -------------------------------------------------------------------------------- /src/Select/index.js: -------------------------------------------------------------------------------- 1 | export { default as Select } from './Select' 2 | -------------------------------------------------------------------------------- /src/Switch/Switch.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { FieldProps, FormikProps, FormikValues } from 'formik'; 3 | 4 | export interface FSwitchProps { 5 | label?: string; 6 | field: FieldProps; 7 | form: FormikProps; 8 | required?: boolean; 9 | fullWidth?: boolean; 10 | margin?: 'none' | 'dense' | 'normal'; 11 | } 12 | 13 | declare const FSwitchProps: React.ComponentType; 14 | 15 | export default FSwitchProps; 16 | -------------------------------------------------------------------------------- /src/Switch/Switch.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/forbid-prop-types */ 2 | /* eslint-disable react/jsx-props-no-spreading */ 3 | import React from 'react' 4 | import PropTypes from 'prop-types' 5 | import Switch from '@material-ui/core/Switch' 6 | import FormControl from '@material-ui/core/FormControl' 7 | import FormControlLabel from '@material-ui/core/FormControlLabel' 8 | import { withTheme } from '@material-ui/core/styles' 9 | import FormHelperText from '@material-ui/core/FormHelperText' 10 | import { getIn } from 'formik' 11 | 12 | class FSwitch extends React.PureComponent { 13 | render() { 14 | const { 15 | label, 16 | field, 17 | form: { touched, errors, setFieldValue }, 18 | required, 19 | fullWidth, 20 | margin, 21 | theme, 22 | ...other 23 | } = this.props 24 | 25 | const errorText = getIn(errors, field.name) 26 | const touchedVal = getIn(touched, field.name) 27 | const hasError = touchedVal && errorText !== undefined 28 | const errorColor = theme.palette.error.main 29 | const labelStyle = hasError ? { color: errorColor } : {} 30 | 31 | const controlProps = { 32 | checked: field.value || false, 33 | onChange: (event) => { 34 | setFieldValue(field.name, event.target.checked) 35 | }, 36 | } 37 | 38 | return ( 39 | 45 | } 48 | label={{label}} 49 | /> 50 | {hasError && {errorText}} 51 | 52 | ) 53 | } 54 | } 55 | 56 | FSwitch.propTypes = { 57 | label: PropTypes.string.isRequired, 58 | field: PropTypes.shape({ 59 | name: PropTypes.string, 60 | }).isRequired, 61 | form: PropTypes.shape({ 62 | touched: PropTypes.object, 63 | errors: PropTypes.object, 64 | values: PropTypes.object, 65 | setFieldValue: PropTypes.func, 66 | }).isRequired, 67 | theme: PropTypes.shape({ palette: PropTypes.object }), 68 | required: PropTypes.bool, 69 | fullWidth: PropTypes.bool, 70 | margin: PropTypes.oneOf(['none', 'dense', 'normal']), 71 | } 72 | 73 | FSwitch.defaultProps = { 74 | theme: {}, 75 | required: false, 76 | fullWidth: true, 77 | margin: 'normal', 78 | } 79 | 80 | export default withTheme(FSwitch) 81 | -------------------------------------------------------------------------------- /src/Switch/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as Switch } from './Switch' 2 | -------------------------------------------------------------------------------- /src/Switch/index.js: -------------------------------------------------------------------------------- 1 | export { default as Switch } from './Switch' 2 | -------------------------------------------------------------------------------- /src/TextField/TextField.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { FieldProps, FormikProps, FormikValues } from 'formik'; 3 | import { InputProps } from '@material-ui/core/Input'; 4 | 5 | export interface FTextFieldProps { 6 | label?: string; 7 | field: FieldProps; 8 | form: FormikProps; 9 | inputProps?: InputProps; 10 | fullWidth?: boolean; 11 | margin?: 'none' | 'dense' | 'normal'; 12 | } 13 | 14 | declare const FTextField: React.ComponentType; 15 | 16 | export default FTextField; 17 | -------------------------------------------------------------------------------- /src/TextField/TextField.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/jsx-props-no-spreading */ 2 | import React from 'react' 3 | import PropTypes from 'prop-types' 4 | import TextField from '@material-ui/core/TextField' 5 | import { getIn } from 'formik' 6 | 7 | const FTextField = ({ 8 | label, 9 | field, 10 | form: { dirty, touched, errors }, 11 | ...other 12 | }) => { 13 | const errorText = getIn(errors, field.name) 14 | const touchedVal = getIn(touched, field.name) 15 | const hasError = dirty && touchedVal && errorText !== undefined 16 | 17 | return ( 18 | 25 | ) 26 | } 27 | 28 | FTextField.propTypes = { 29 | label: PropTypes.string.isRequired, 30 | field: PropTypes.shape({ 31 | name: PropTypes.string, 32 | onChange: PropTypes.func, 33 | value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 34 | }).isRequired, 35 | form: PropTypes.shape({ 36 | dirty: PropTypes.bool, 37 | errors: PropTypes.object, 38 | }).isRequired, 39 | fullWidth: PropTypes.bool, 40 | margin: PropTypes.oneOf(['none', 'dense', 'normal']), 41 | } 42 | 43 | FTextField.defaultProps = { 44 | fullWidth: true, 45 | margin: 'normal', 46 | } 47 | 48 | export default FTextField 49 | -------------------------------------------------------------------------------- /src/TextField/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as TextField } from './TextField' 2 | -------------------------------------------------------------------------------- /src/TextField/index.js: -------------------------------------------------------------------------------- 1 | export { default as TextField } from './TextField' 2 | -------------------------------------------------------------------------------- /src/TimePicker/TimePicker.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { FieldProps, FormikProps, FormikValues } from 'formik' 3 | 4 | export interface FTimePickerProps { 5 | label?: string 6 | field: FieldProps 7 | form: FormikProps 8 | fullWidth?: boolean 9 | margin?: 'none' | 'dense' | 'normal' 10 | autoOk?: boolean 11 | } 12 | 13 | declare const FTimePickerProps: React.ComponentType 14 | 15 | export default FTimePickerProps 16 | -------------------------------------------------------------------------------- /src/TimePicker/TimePicker.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | import { TimePicker } from '@material-ui/pickers' 4 | import { getIn } from 'formik' 5 | 6 | const FTimePicker = (props) => { 7 | const { 8 | label, 9 | field, 10 | form: { touched, errors, setFieldValue }, 11 | ...other 12 | } = props 13 | const errorText = getIn(errors, field.name) 14 | const touchedVal = getIn(touched, field.name) 15 | const hasError = touchedVal && errorText !== undefined 16 | return ( 17 | setFieldValue(field.name, value)} 22 | value={field.value} 23 | // eslint-disable-next-line react/jsx-props-no-spreading 24 | {...other} 25 | /> 26 | ) 27 | } 28 | 29 | FTimePicker.propTypes = { 30 | label: PropTypes.string.isRequired, 31 | field: PropTypes.shape({ 32 | name: PropTypes.string, 33 | value: PropTypes.any, 34 | }).isRequired, 35 | form: PropTypes.shape({ 36 | dirty: PropTypes.bool, 37 | errors: PropTypes.object, 38 | }).isRequired, 39 | fullWidth: PropTypes.bool, 40 | margin: PropTypes.oneOf(['none', 'dense', 'normal']), 41 | autoOk: PropTypes.bool, 42 | } 43 | 44 | FTimePicker.defaultProps = { 45 | fullWidth: true, 46 | margin: 'normal', 47 | autoOk: true, 48 | } 49 | 50 | export default FTimePicker 51 | -------------------------------------------------------------------------------- /src/TimePicker/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as TimePicker } from './TimePicker' 2 | -------------------------------------------------------------------------------- /src/TimePicker/index.js: -------------------------------------------------------------------------------- 1 | export { default as TimePicker } from './TimePicker' 2 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Used in Autocomplete and Select components 3 | */ 4 | export interface SelectOptionsType { 5 | label: string 6 | value: string | number 7 | } 8 | 9 | /** 10 | * Used in RadioGroup component 11 | */ 12 | export interface RadioGroupOptionsType { 13 | label: string 14 | value: string 15 | } 16 | 17 | export * from './Autocomplete' 18 | export * from './ChipInput' 19 | export * from './DatePicker' 20 | export * from './DateTimePicker' 21 | export * from './KeyboardDatePicker' 22 | export * from './KeyboardTimePicker' 23 | export * from './KeyboardDateTimePicker' 24 | export * from './RadioGroup' 25 | export * from './Select' 26 | export * from './Switch' 27 | export * from './TextField' 28 | export * from './TimePicker' 29 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export * from './Autocomplete' 2 | export * from './ChipInput' 3 | export * from './DatePicker' 4 | export * from './DateTimePicker' 5 | export * from './KeyboardDatePicker' 6 | export * from './KeyboardTimePicker' 7 | export * from './KeyboardDateTimePicker' 8 | export * from './RadioGroup' 9 | export * from './Select' 10 | export * from './Switch' 11 | export * from './TextField' 12 | export * from './TimePicker' 13 | --------------------------------------------------------------------------------