├── .babelrc ├── .eslintrc.json ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── lib └── index.js ├── package.json ├── src ├── index.js └── index.spec.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-react", "@babel/preset-env"], 3 | "plugins": [ 4 | "@babel/plugin-proposal-object-rest-spread" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "extends": "airbnb-base", 7 | "rules": { 8 | "indent": [ 9 | "error", 10 | 4 11 | ] 12 | } 13 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | node_modules 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | .babelrc 3 | .eslintrc 4 | .travis.yml 5 | Makefile 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "node" 5 | 6 | env: 7 | global: 8 | - NODE_ENV=test 9 | 10 | dist: trusty 11 | 12 | cache: 13 | directories: 14 | - node_modules 15 | 16 | install: 17 | - "make --silent install" 18 | 19 | script: 20 | make test 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Marmelab 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | help: 2 | @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 3 | 4 | install: ## Install dependencies 5 | yarn install 6 | 7 | clean: ## Clean up the lib folder for building 8 | @rm -rf lib 9 | 10 | build: clean ## Compile ES6 files to JS 11 | @NODE_ENV=production ./node_modules/.bin/babel \ 12 | --out-dir=lib \ 13 | --ignore=*.spec.js \ 14 | ./src 15 | 16 | test: ## Launch unit tests 17 | @NODE_ENV=test ./node_modules/.bin/jest ./src 18 | 19 | test-watch: ## Launch unit tests 20 | @NODE_ENV=test ./node_modules/.bin/jest --watch ./src 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # redux-form-inspector 2 | 3 | [](https://travis-ci.org/marmelab/redux-form-inspector) 4 | 5 | An HOC for computing dynamic props from values inside an existing [redux-form](https://github.com/erikras/redux-form) component. 6 | 7 | - [Installation](#installation) 8 | - [Usage](#installation) 9 | - [API](#api) 10 | 11 | ## Installation 12 | 13 | Install with: 14 | 15 | ```sh 16 | npm install -S redux-form-inspector 17 | ``` 18 | 19 | or 20 | 21 | ```sh 22 | yarn add redux-form-inspector 23 | ``` 24 | 25 | ## Usage 26 | 27 | [Redux-form](https://github.com/erikras/redux-form) is a fantastic library which let you create forms inside your react application. In the following example, we create a simple form component with `hello` as an unique identifier thanks to the [reduxForm](http://redux-form.com/6.7.0/docs/api/ReduxForm.md/) HOC . 28 | 29 | ```js 30 | import React from 'react'; 31 | import { Field, reduxForm } from 'redux-form'; 32 | 33 | export const HelloForm = ({ handleSubmit }) => ( 34 |
38 | ); 39 | 40 | export default reduxForm({ form: 'hello' })(HelloForm); 41 | ``` 42 | 43 | `redux-form-inspector` let you add some `dynamic props` to you component (wrapped by your HOC) who are based on the values `of any registered form` of your application. For example, you can disable fields, change the background color of your form, ... the sky is the limit. 44 | 45 | ```js 46 | import React from 'react'; 47 | import { compose } from 'recompose'; 48 | import { Field, reduxForm } from 'redux-form'; 49 | import formInspector from 'redux-form-inspector'; 50 | 51 | export const HelloForm = ({ handleSubmit, backgroundColor, showSecret }) => ( 52 | 58 | ); 59 | 60 | export const fieldsToProps = { 61 | backgroundColor: ({ message }) => message.includes('hello') ? 'red' : 'blue', 62 | showSecret: ({ message, email }) => message.length > 0 && email === 'john@doe.com' 63 | }; 64 | 65 | export default compose( 66 | reduxForm({ form: 'hello' }), 67 | formInspector({ form: 'hello', fieldsToProps }), 68 | )(HelloForm); 69 | ``` 70 | 71 | ## API 72 | 73 | The `formInspector` function take a configuration object of the following form as input. In result of this call, it return a new HOC which can be used on any component (not just form). 74 | 75 | ```js 76 | const fieldsToProps = { 77 | mySubprop: (fields, errors) => { ... }, 78 | ... 79 | }; 80 | 81 | const myCustomFormInspector = formInspector({ 82 | form: 'myForm', // The redux-form instance identifier 83 | fieldsToProps, // An empty object by default 84 | inspectorKey: 'myInspectorPropKey' // [optionnal] no "sub-prop" by default 85 | }); 86 | ``` 87 | 88 | #### form 89 | 90 | The form name must be the same as the name you have passed to the [reduxForm](http://redux-form.com/6.7.0/docs/api/ReduxForm.md/) on the form that you're inspect. In the previous example, the form name was `hello`. 91 | 92 | If the provided form name does not exist or is not registred by `redux-form`, each value of the resulting `fieldsToProps` object will be equal to `null`. 93 | 94 | #### fieldsToProps 95 | 96 | `fieldsToProps` is the most important part of `redux-form-inspector`. It is defined as a simple object with a prop name as key and a callback as value. At runtime, each callback is executed with the form field values and errors (both sync and async) as arguments. Each result is assigned to the following prop name. 97 | 98 | The strength of `fieldsToProps` lies in the fact that it can be easily tested. 99 | 100 | #### inspectorKey [optionnal] 101 | 102 | This attribute let you assign a custom root key for your `fieldsToProps` result object. 103 | 104 | If not specified, `formInspector` will merge the `fieldsToProps` result object inside your existing component props. 105 | 106 | ## Contributing 107 | 108 | Run the tests with this command: 109 | 110 | ```sh 111 | make test 112 | ``` 113 | 114 | ## Maintainer 115 | 116 | [](https://github.com/jdemangeon) 117 | [Julien Demangeon](https://github.com/jdemangeon) 118 | 119 | ## License 120 | 121 | redux-form-inspector is licensed under the [MIT License](LICENSE), courtesy of [Marmelab](http://marmelab.com). 122 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = void 0; 7 | 8 | var _reactRedux = require("react-redux"); 9 | 10 | var _reduxForm = require("redux-form"); 11 | 12 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } 13 | 14 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 15 | 16 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 17 | 18 | var _default = function _default(_ref) { 19 | var form = _ref.form, 20 | _ref$fieldsToProps = _ref.fieldsToProps, 21 | fieldsToProps = _ref$fieldsToProps === void 0 ? {} : _ref$fieldsToProps, 22 | inspectorKey = _ref.inspectorKey; 23 | 24 | if (!form) { 25 | throw new Error('You must provide a form identifier in the "form" configuration key.'); 26 | } 27 | 28 | return (0, _reactRedux.connect)(function (state) { 29 | var fieldValues = (0, _reduxForm.getFormValues)(form)(state); 30 | 31 | var errors = _objectSpread(_objectSpread({}, (0, _reduxForm.getFormAsyncErrors)(form)(state)), (0, _reduxForm.getFormSyncErrors)(form)(state)); 32 | 33 | var inspection = Object.keys(fieldsToProps).reduce(function (r, prop) { 34 | return _objectSpread(_objectSpread({}, r), {}, _defineProperty({}, prop, fieldValues ? fieldsToProps[prop](fieldValues, errors) : null)); 35 | }, {}); 36 | return !inspectorKey ? inspection : _defineProperty({}, inspectorKey, inspection); 37 | }, function () { 38 | return {}; 39 | }); 40 | }; 41 | 42 | exports["default"] = _default; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redux-form-inspector", 3 | "description": "React HOC which add inspection capabilities to redux-form instances", 4 | "version": "1.0.0", 5 | "license": "MIT", 6 | "authors": [ 7 | "Demangeon Julien