├── .eslintrc ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .nvmrc ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── screenshot.png ├── src ├── actions.ts ├── components │ ├── Dock.tsx │ ├── Draggable.tsx │ ├── FormControls.tsx │ ├── FormOptions.tsx │ ├── Header.tsx │ ├── RenderFormData.tsx │ ├── SelectInitialForm.tsx │ ├── SelectMenu.tsx │ ├── SimpleCheckbox.tsx │ ├── Window.tsx │ └── WindowPortal.tsx ├── form.options.ts ├── handlers.ts ├── icons.ts ├── index.tsx ├── parser.ts ├── props.ts ├── store.ts ├── styles │ ├── Dock.ts │ ├── Draggable.ts │ ├── FormOptions.ts │ ├── Header.ts │ ├── RenderFormData.ts │ ├── SelectInitialForm.ts │ ├── SelectMenu.ts │ ├── SimpleCheckbox.ts │ ├── _.theme.ts │ └── _.utils.ts └── utils.ts ├── tests └── tests.ts ├── tsconfig.json └── webpack.config.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "plugins": ["import"], 4 | "rules": { 5 | "import/no-unresolved": "off", 6 | "import/extensions": "off", 7 | "react/forbid-prop-types": 0, 8 | "class-methods-use-this": 0, 9 | "no-confusing-arrow": 0, 10 | "quote-props": ["error", "consistent-as-needed"] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Mobx React Form Devtools 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | CI: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v3 12 | - run: npm install --force 13 | - run: npm run cover 14 | - run: npm run coverage:check 15 | - run: npm run build 16 | - run: npm run coverage:report 17 | - name: Semantic Release 18 | uses: cycjimmy/semantic-release-action@v3 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /coverage 3 | /es6 4 | /lib 5 | /umd 6 | /.nyc_output 7 | npm-debug.log 8 | coverage.lcov 9 | codecov.yml 10 | yarn.lock 11 | .DS_Store -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v16.19.1 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Claudio Savino 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 | # MobX React Form DevTools 2 | 3 | ##### DevTools for [MobX React Form](https://github.com/foxhound87/mobx-react-form) 4 | 5 | --- 6 | 7 | [![NPM](https://nodei.co/npm/mobx-react-form-devtools.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/mobx-react-form-devtools/) 8 | 9 | ![GitHub Workflow Status (with branch)](https://img.shields.io/github/actions/workflow/status/foxhound87/mobx-react-form-devtools/ci.yml?branch=next) 10 | ![GitHub release (latest by date)](https://img.shields.io/github/v/release/foxhound87/mobx-react-form-devtools) 11 | ![npm bundle size](https://img.shields.io/bundlephobia/min/mobx-react-form-devtools) 12 | [![Codecov Coverage](https://img.shields.io/codecov/c/github/foxhound87/mobx-react-form-devtools/master.svg)](https://codecov.io/gh/foxhound87/mobx-react-form-devtools) 13 | [![node](https://img.shields.io/node/v/mobx-react-form-devtools.svg)]() 14 | [![GitHub license](https://img.shields.io/github/license/foxhound87/mobx-react-form-devtools.svg)]() 15 | ![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed/foxhound87/mobx-react-form-devtools) 16 | ![GitHub closed issues](https://img.shields.io/github/issues-closed-raw/foxhound87/mobx-react-form-devtools) 17 | [![Downloads](https://img.shields.io/npm/dt/mobx-react-form-devtools.svg)]() 18 | [![Downloads](https://img.shields.io/npm/dm/mobx-react-form-devtools.svg)]() 19 | 20 | --- 21 | 22 | ## Install 23 | 24 | ```bash 25 | npm install --save mobx-react-form-devtools 26 | ``` 27 | 28 | ## Demo 29 | 30 | [MobX React Form DevTools Demo](https://foxhound87.github.io/mobx-react-form-demo) 31 | 32 | ## Usage 33 | 34 | ```javascript 35 | import MobxReactFormDevTools from 'mobx-react-form-devtools'; 36 | 37 | // register forms (mobx-react-form Instances) 38 | MobxReactFormDevTools.register({ 39 | loginForm, 40 | registerForm, 41 | supportForm, 42 | }); 43 | 44 | // select form to show into the devtools 45 | MobxReactFormDevTools.select('registerForm'); 46 | 47 | // open the devtools (closed by default) 48 | MobxReactFormDevTools.open(true); 49 | 50 | // render the component 51 | 52 | ``` 53 | 54 | ## Theme 55 | 56 | ```javascript 57 | // custom theme colors 58 | MobxReactFormDevTools.theme({ 59 | base00: '#2b303b', 60 | base01: '#343d46', 61 | base02: '#4f5b66', 62 | base03: '#65737e', 63 | base04: '#a7adba', 64 | base05: '#c0c5ce', 65 | base06: '#dfe1e8', 66 | base07: '#eff1f5', 67 | base08: '#bf616a', 68 | base09: '#d08770', 69 | base0A: '#ebcb8b', 70 | base0B: '#a3be8c', 71 | base0C: '#96b5b4', 72 | base0D: '#8fa1b3', 73 | base0E: '#b48ead', 74 | base0F: '#ab7967', 75 | }); 76 | ``` 77 | 78 | ## Screenshot 79 | 80 | ![DevTools](https://github.com/foxhound87/mobx-react-form-devtools/blob/master/screenshot.png?raw=true) 81 | 82 | ## Contributing 83 | 84 | If you want to contribute to the development, do not hesitate to fork the repo and send pull requests. 85 | 86 | And don't forget to star the repo, I will ensure more frequent updates! Thanks! 87 | 88 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mobx-react-form-devtools", 3 | "license": "MIT", 4 | "version": "0.0.0-development", 5 | "author": "Claudio Savino (https://twitter.com/foxhound87)", 6 | "description": "DevTools for MobX React Form", 7 | "homepage": "https://www.npmjs.com/package/mobx-react-form-devtools", 8 | "main": "lib/index.js", 9 | "types": "./lib/index.d.ts", 10 | "scripts": { 11 | "clean:build": "rimraf lib && rimraf umd", 12 | "clean:modules": "rimraf node_modules && npm cache clean", 13 | "clean:all": "npm run clean:build && npm run clean:modules", 14 | "lint": "eslint . src --ext .ts --ignore-path .gitignore", 15 | "build": "npm-run-all --parallel build:*", 16 | "build:main": "tsc -d", 17 | "build:umd": "webpack", 18 | "build:umdmin": "MINIFY=YES webpack", 19 | "prebuild": "npm run clean:build", 20 | "precommit": "npm run lint && npm run cover", 21 | "commit": "git-cz && git push origin", 22 | "watch:build": "tsc --watch -d", 23 | "watch:test": "npm run test -- -w", 24 | "test": "TEST=true mocha -r ts-node/register ./tests/*.ts", 25 | "cover": "nyc npm test", 26 | "coverage:check": "nyc check-coverage --satements 0 --branches 0 --functions 0 --lines 0", 27 | "coverage:report": "nyc report --reporter=text-lcov > coverage.lcov && codecov", 28 | "semantic-release": "semantic-release" 29 | }, 30 | "repository": { 31 | "type": "git", 32 | "url": "https://github.com/foxhound87/mobx-react-form-devtools.git" 33 | }, 34 | "keywords": [ 35 | "mobx", 36 | "react", 37 | "form", 38 | "devtools" 39 | ], 40 | "files": [ 41 | "src", 42 | "lib", 43 | "umd" 44 | ], 45 | "engines": { 46 | "node": ">=16.0.0" 47 | }, 48 | "config": { 49 | "commitizen": { 50 | "path": "node_modules/cz-conventional-changelog" 51 | } 52 | }, 53 | "dependencies": { 54 | "@emotion/css": "^11.10.6", 55 | "classnames": "^2.3.2", 56 | "lodash": "^4.17.21", 57 | "react-dock": "0.2.4", 58 | "react-icons": "^2.2.7", 59 | "react-json-tree": "0.11.0" 60 | }, 61 | "peerDependencies": { 62 | "mobx": "*", 63 | "mobx-react": "*", 64 | "mobx-react-form": "*", 65 | "prop-types": "*", 66 | "react": "*", 67 | "react-dom": "*" 68 | }, 69 | "devDependencies": { 70 | "@types/react": "^18.0.28", 71 | "@typescript-eslint/parser": "^5.54.1", 72 | "chai": "^3.5.0", 73 | "codecov": "^3.8.3", 74 | "commitizen": "^4.3.0", 75 | "css-loader": "^6.7.3", 76 | "cz-conventional-changelog": "^1.2.0", 77 | "eslint": "^8.35.0", 78 | "eslint-plugin-import": "^2.27.5", 79 | "husky": "^0.12.0", 80 | "mocha": "^10.2.0", 81 | "npm-run-all": "^3.1.2", 82 | "nyc": "^15.1.0", 83 | "prop-types": "^15.8.1", 84 | "react": "^16.14.0", 85 | "react-dom": "^16.14.0", 86 | "rimraf": "^2.5.4", 87 | "semantic-release": "^19.0.5", 88 | "style-loader": "^3.3.1", 89 | "terser-webpack-plugin": "^5.3.6", 90 | "ts-loader": "^9.4.2", 91 | "ts-node": "^10.9.1", 92 | "typescript": "^4.9.5", 93 | "webpack": "^5.75.0", 94 | "webpack-cli": "^5.0.1" 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxhound87/mobx-react-form-devtools/84bc15c29c829528c709522f229e7263cdb37fed/screenshot.png -------------------------------------------------------------------------------- /src/actions.ts: -------------------------------------------------------------------------------- 1 | import { action } from 'mobx'; 2 | import _ from 'lodash'; 3 | 4 | export default $store => ({ 5 | 6 | open: action(flag => _.set($store, 'open', flag)), 7 | 8 | theme: action(theme => _.merge($store.theme, theme)), 9 | 10 | selectForm: action((key) => { 11 | _.map($store.select, ($val, $key) => _.set($store.select, $key, false)); 12 | _.set($store.select, key, true); 13 | _.set($store.selected, 'key', key); 14 | _.set($store.selected, 'form', $store.forms[key]); 15 | }), 16 | 17 | registerForm: action((forms) => { 18 | _.merge($store.forms, forms); 19 | _.map(forms, ($form, $key) => _.set($store.select, $key, false)); 20 | _.map(forms, ($form, $key) => _.set($store.menu, $key, $form.name || $key)); 21 | }), 22 | 23 | toggleTools: action((toggle) => { 24 | let $flag; 25 | if (toggle === 'open') $flag = true; 26 | if (toggle === 'close') $flag = false; 27 | _.set($store, 'open', $flag); 28 | }), 29 | 30 | toggleOptions: action(() => { 31 | _.set($store, 'showOptions', !$store.showOptions); 32 | }), 33 | 34 | changeDockSize: action((size) => { 35 | _.set($store.dock, 'size', size); 36 | }), 37 | 38 | handleFormControls: action((type) => { 39 | switch (type) { 40 | case 'submit': $store.selected.form.submit(); break; 41 | case 'clear': $store.selected.form.clear(); break; 42 | case 'reset': $store.selected.form.reset(); break; 43 | default: $store.selected.form.submit(); 44 | } 45 | }), 46 | 47 | openInWindow: action(() => { 48 | _.set($store, 'mode', 'windowed'); 49 | _.set($store.dock, 'position', 'left'); 50 | _.set($store.dock, 'fluid', true); 51 | }), 52 | 53 | onCloseWindow: action(() => { 54 | _.set($store, 'mode', 'docked'); 55 | _.set($store.dock, 'position', 'right'); 56 | _.set($store.dock, 'fluid', false); 57 | }), 58 | 59 | }); 60 | 61 | -------------------------------------------------------------------------------- /src/components/Dock.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { observer } from 'mobx-react'; 3 | import cx from 'classnames'; 4 | import Dock from 'react-dock'; 5 | 6 | import Header from './Header'; 7 | import Draggable from './Draggable'; 8 | import SelectInitialForm from './SelectInitialForm'; 9 | import RenderFormData from './RenderFormData'; 10 | 11 | import $U from '../styles/_.utils'; 12 | import style from '../styles/Dock'; 13 | 14 | export default observer(({ store, handlers }) => ( 15 |
16 | 26 |
27 | 28 |
29 | 30 |
31 | 32 | {(store.selected.form && store.selected.key) 33 | ? 34 | : } 35 | 36 | 37 |
38 | )); 39 | -------------------------------------------------------------------------------- /src/components/Draggable.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | import { observer } from 'mobx-react'; 3 | import cx from 'classnames'; 4 | // import Draggable from 'react-draggable'; 5 | 6 | import { 7 | FaBars, 8 | FaChevronLeft, 9 | FaBook, 10 | FaWindows, 11 | } from '../icons'; 12 | 13 | import $U from '../styles/_.utils'; 14 | import style from '../styles/Draggable'; 15 | 16 | export default observer(({ handlers }) => { 17 | 18 | const handleOnDragEnd = (e) => { 19 | e.target.style.top = (e.clientY - 100) + "px"; 20 | }; 21 | 22 | return ( 23 | //
28 |
29 | 32 | 39 | 46 | 53 |
54 | // 55 | )}); 56 | -------------------------------------------------------------------------------- /src/components/FormControls.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { observer } from 'mobx-react'; 3 | import cx from 'classnames'; 4 | 5 | import { 6 | FaDotCircleO, 7 | FaEraser, 8 | FaRefresh, 9 | FaCog, 10 | } from '../icons'; 11 | import $U from '../styles/_.utils'; 12 | import style from '../styles/RenderFormData'; 13 | 14 | const { icon, iconOptionsActive } = style.controls; 15 | 16 | export default observer(({ store, handlers }) => ( 17 |
18 | 26 | 34 | 42 | 50 |
51 | )); 52 | -------------------------------------------------------------------------------- /src/components/FormOptions.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { observer } from 'mobx-react'; 3 | import cx from 'classnames'; 4 | 5 | import SimpleCheckbox from './SimpleCheckbox'; 6 | import style from '../styles/FormOptions'; 7 | 8 | export default observer(({ form }) => ( 9 |
10 |

FORM OPTIONS

11 | {form.map(field => )} 12 | 13 | )); 14 | -------------------------------------------------------------------------------- /src/components/Header.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { observer } from 'mobx-react'; 3 | import cx from 'classnames'; 4 | 5 | import { 6 | FaChevronCircleRight, 7 | FaBook, 8 | FaWindows, 9 | } from '../icons'; 10 | 11 | import $U from '../styles/_.utils'; 12 | import style from '../styles/Header'; 13 | 14 | export default observer(({ store, handlers }) => ( 15 |
16 |
17 | 18 | MOBX-REACT-FORM 19 | 20 | 21 | DEVTOOLS 22 | 23 |
24 | {!store.windowIsOpen && } 31 | 38 | {!store.windowIsOpen && } 45 |
46 | )); 47 | -------------------------------------------------------------------------------- /src/components/RenderFormData.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { observer } from 'mobx-react'; 3 | import cx from 'classnames' 4 | import JSONTree from 'react-json-tree'; 5 | 6 | import SelectMenu from './SelectMenu'; 7 | import FormControls from './FormControls'; 8 | import FormOptions from './FormOptions'; 9 | 10 | import { parseFormData, parseFieldsData } from '../parser'; 11 | 12 | import { 13 | FaTh, 14 | FaBars, 15 | } from '../icons'; 16 | import $U from '../styles/_.utils'; 17 | import style from '../styles/RenderFormData'; 18 | 19 | export default observer(({ store, handlers }) => ( 20 |
21 |

22 |
25 | Form 26 |
27 |
30 | 31 |
32 |

33 | 34 | 35 | {store.showOptions 36 | && } 37 | 38 |
39 | 46 |

47 | Fields 48 |

49 |
50 | 56 |
57 |
58 | )); 59 | -------------------------------------------------------------------------------- /src/components/SelectInitialForm.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { observer } from 'mobx-react'; 3 | import cx from 'classnames'; 4 | 5 | import { mapo } from '../utils'; 6 | import { FaCircleO } from '../icons'; 7 | import $U from '../styles/_.utils'; 8 | import style from '../styles/SelectInitialForm'; 9 | 10 | export default observer(({ store, handlers }) => ( 11 |
12 |

SELECT A FORM

13 | {mapo(store.menu, (key, val) => 14 | // eslint-disable-next-line 15 | )} 22 |
23 | )); 24 | -------------------------------------------------------------------------------- /src/components/SelectMenu.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { observer } from 'mobx-react'; 3 | import _ from 'lodash'; 4 | import cx from 'classnames'; 5 | import style from '../styles/SelectMenu'; 6 | 7 | export default observer(({ store, handlers }) => ( 8 | 17 | )); 18 | -------------------------------------------------------------------------------- /src/components/SimpleCheckbox.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { observer } from 'mobx-react'; 3 | import cx from 'classnames'; 4 | import style from '../styles/SimpleCheckbox'; 5 | 6 | export default observer(({ field }) => ( 7 | 10 | )); 11 | -------------------------------------------------------------------------------- /src/components/Window.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { observer } from 'mobx-react'; 3 | import cx from 'classnames'; 4 | 5 | import Header from './Header'; 6 | import SelectInitialForm from './SelectInitialForm'; 7 | import RenderFormData from './RenderFormData'; 8 | 9 | import style from '../styles/Dock'; 10 | 11 | export default observer(({ store, handlers }) => ( 12 |
13 | 14 |
15 | 16 | {(store.selected.form && store.selected.key) 17 | ? 18 | : } 19 | 20 |
21 | )); 22 | -------------------------------------------------------------------------------- /src/components/WindowPortal.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from "react"; 2 | import ReactDOM from "react-dom"; 3 | import { copyStyles } from "../utils"; 4 | 5 | export const WindowPortal = ({ children, closeWindowPortal }) => { 6 | const externalWindow = useRef( 7 | window.open("", "", "width=350,height=650,left=200,top=200") 8 | ); 9 | 10 | const containerEl = document.createElement("div"); 11 | 12 | useEffect(() => { 13 | const currentWindow = externalWindow.current; 14 | return () => currentWindow.close(); 15 | }, []); 16 | 17 | externalWindow.current.document.title = "mobx-react-form-devtools"; 18 | externalWindow.current.document.body.appendChild(containerEl); 19 | copyStyles(document, externalWindow.current.document); 20 | 21 | externalWindow.current.addEventListener("beforeunload", (e) => { 22 | closeWindowPortal(e); 23 | }); 24 | 25 | return ReactDOM.createPortal(children, containerEl); 26 | }; 27 | -------------------------------------------------------------------------------- /src/form.options.ts: -------------------------------------------------------------------------------- 1 | import Form from 'mobx-react-form'; 2 | import _ from 'lodash'; 3 | 4 | const observer = form => ({ field }) => 5 | form.state.options.set({ [field.key]: field.value }); 6 | 7 | const setProp = (fields, prop) => 8 | _.reduce(fields, (obj, val, key) => 9 | _.merge(obj, { [key]: prop }), {}); 10 | 11 | const setObserversProp = (form, fields) => 12 | setProp(fields, [{ call: observer(form) }]); 13 | 14 | const setCheckboxProp = fields => 15 | setProp(fields, 'checkbox'); 16 | 17 | const getBooleanOptions = form => 18 | _.pickBy(form.state.options.options, _.isBoolean); 19 | 20 | export const makeFormOptions = (form) => { 21 | const fields = getBooleanOptions(form); 22 | const types = setCheckboxProp(fields); 23 | const observers = setObserversProp(form, fields); 24 | 25 | return new Form({ 26 | fields, 27 | types, 28 | observers, 29 | }); 30 | }; 31 | -------------------------------------------------------------------------------- /src/handlers.ts: -------------------------------------------------------------------------------- 1 | export default $actions => ({ 2 | 3 | handleOnSizeChange: (size) => { 4 | $actions.changeDockSize(size); 5 | }, 6 | 7 | handleOnCloseTools: (e) => { 8 | e.preventDefault(); 9 | $actions.toggleTools('close'); 10 | }, 11 | 12 | handleOnOpenTools: (e) => { 13 | e.preventDefault(); 14 | $actions.toggleTools('open'); 15 | }, 16 | 17 | handleOnOpenDoc: (e) => { 18 | e.preventDefault(); 19 | const link = 'https://foxhound87.github.io/mobx-react-form/'; 20 | window.open(link, '_blank'); // eslint-disable-line 21 | }, 22 | 23 | handleSelect: (e) => { 24 | $actions.selectForm(e.target.value); 25 | }, 26 | 27 | handleInitialFormSelect: (e) => { 28 | e.preventDefault(); 29 | $actions.selectForm(e.target.value); 30 | }, 31 | 32 | handleToggleOptions: (e) => { 33 | e.preventDefault(); 34 | $actions.toggleOptions(); 35 | }, 36 | 37 | handleFormOnSubmit: (e) => { 38 | e.preventDefault(); 39 | $actions.handleFormControls('submit'); 40 | }, 41 | 42 | handleFormOnClear: (e) => { 43 | e.preventDefault(); 44 | $actions.handleFormControls('clear'); 45 | }, 46 | 47 | handleFormOnReset: (e) => { 48 | e.preventDefault(); 49 | $actions.handleFormControls('reset'); 50 | }, 51 | 52 | handleOpenInWindow: (e) => { 53 | e.preventDefault(); 54 | $actions.openInWindow(); 55 | }, 56 | 57 | handleOnCloseWindow: (e) => { 58 | e.preventDefault(); 59 | $actions.onCloseWindow(); 60 | }, 61 | 62 | }); 63 | -------------------------------------------------------------------------------- /src/icons.ts: -------------------------------------------------------------------------------- 1 | import FaTh from 'react-icons/lib/fa/th'; 2 | import FaCog from 'react-icons/lib/fa/cog'; 3 | import FaBars from 'react-icons/lib/fa/bars'; 4 | import FaBook from 'react-icons/lib/fa/book'; 5 | import FaRefresh from 'react-icons/lib/fa/refresh'; 6 | import FaEraser from 'react-icons/lib/fa/eraser'; 7 | import FaCircleO from 'react-icons/lib/fa/circle-o'; 8 | import FaDotCircleO from 'react-icons/lib/fa/dot-circle-o'; 9 | import FaChevronLeft from 'react-icons/lib/fa/chevron-left'; 10 | import FaChevronCircleRight from 'react-icons/lib/fa/chevron-circle-right'; 11 | import FaWindows from 'react-icons/lib/md/desktop-windows'; 12 | 13 | export { 14 | FaTh, 15 | FaCog, 16 | FaBars, 17 | FaBook, 18 | FaRefresh, 19 | FaEraser, 20 | FaCircleO, 21 | FaDotCircleO, 22 | FaChevronLeft, 23 | FaChevronCircleRight, 24 | FaWindows, 25 | }; 26 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { observe, action } from 'mobx'; 3 | import Dock from './components/Dock'; 4 | import FormOptions from './components/FormOptions'; 5 | import { WindowPortal } from './components/WindowPortal'; 6 | 7 | import store from './store'; 8 | import actions from './actions'; 9 | import handlers from './handlers'; 10 | import { observer } from 'mobx-react'; 11 | import Window from './components/Window'; 12 | 13 | const $actions = actions(store); 14 | const $handlers = handlers($actions); 15 | 16 | observe(store.dock, 'size', action((change) => { 17 | const w = window.innerWidth; 18 | if (change.newValue >= w) store.dock.size = w; 19 | if (change.newValue < 350) store.dock.size = 350; 20 | })); 21 | 22 | export default { 23 | 24 | theme: $actions.theme, 25 | 26 | open: $actions.open, 27 | 28 | register: $actions.registerForm, 29 | 30 | select: $actions.selectForm, 31 | 32 | Options: () => , 33 | 34 | UI: observer(() => 35 | store.windowIsOpen 36 | ? 37 | 38 | 39 | : 40 | ), 41 | 42 | }; 43 | -------------------------------------------------------------------------------- /src/parser.ts: -------------------------------------------------------------------------------- 1 | import { values as mobxValues, toJS } from 'mobx'; 2 | import _ from 'lodash'; 3 | 4 | import { 5 | fieldPropsToPick, 6 | formPropsToPick, 7 | } from './props'; 8 | 9 | const parseFormData = form => 10 | toJS(_.pick(form, formPropsToPick)); 11 | 12 | const getObservableMapValues = observableMap => 13 | mobxValues 14 | ? mobxValues(observableMap) 15 | : observableMap.values(); 16 | 17 | const parseFieldsData = fields => 18 | _.reduce(getObservableMapValues(fields), (obj, field) => { 19 | const $nested = $fields => ($fields.size !== 0) 20 | ? parseFieldsData($fields) 21 | : undefined; 22 | 23 | const data = toJS(_.pick(field, fieldPropsToPick)); 24 | 25 | Object.assign(obj, { 26 | [field.key]: Object.assign(data, { 27 | fields: $nested(field.fields), 28 | }), 29 | }); 30 | 31 | return obj; 32 | }, {}); 33 | 34 | 35 | export { 36 | parseFormData, 37 | parseFieldsData, 38 | }; 39 | -------------------------------------------------------------------------------- /src/props.ts: -------------------------------------------------------------------------------- 1 | const base = [ 2 | 'size', 3 | 'submitted', 4 | 'validated', 5 | 'submitting', 6 | 'validating', 7 | ]; 8 | 9 | const shared = [ 10 | 'clearing', 11 | 'resetting', 12 | 'hasError', 13 | 'isValid', 14 | 'isDirty', 15 | 'isPristine', 16 | 'isDefault', 17 | 'isEmpty', 18 | 'disabled', 19 | 'deleted', 20 | 'touched', 21 | 'focused', 22 | 'blurred', 23 | 'changed', 24 | 'error', 25 | ]; 26 | 27 | const fieldPropsToPick = [ 28 | 'id', 29 | 'name', 30 | 'path', 31 | 'type', 32 | 'bindings', 33 | 'options', 34 | 'default', 35 | 'initial', 36 | 'value', 37 | 'label', 38 | 'placeholder', 39 | 'autoFocus', 40 | 'related', 41 | 'rules', 42 | ...shared, 43 | ...base, 44 | ]; 45 | 46 | const formPropsToPick = [ 47 | ...base, 48 | ...shared, 49 | ]; 50 | 51 | export { 52 | fieldPropsToPick, 53 | formPropsToPick, 54 | }; 55 | -------------------------------------------------------------------------------- /src/store.ts: -------------------------------------------------------------------------------- 1 | import { makeAutoObservable } from 'mobx'; 2 | import theme from './styles/_.theme'; 3 | import {makeFormOptions} from './form.options'; 4 | 5 | export default makeAutoObservable({ 6 | mode: 'docked', 7 | theme, 8 | showOptions: false, 9 | open: false, 10 | forms: {}, 11 | menu: {}, 12 | select: {}, 13 | selected: { 14 | key: null, 15 | form: null, 16 | }, 17 | dock: { 18 | visible: true, 19 | fluid: false, 20 | size: 350, 21 | position: 'right', 22 | mode: 'none', 23 | style: { 24 | background: theme.base00, 25 | }, 26 | }, 27 | get formOptions() { 28 | return makeFormOptions(this.selected.form); 29 | }, 30 | 31 | get windowIsOpen() { 32 | return this.mode === 'windowed'; 33 | }, 34 | 35 | }); 36 | -------------------------------------------------------------------------------- /src/styles/Dock.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/css' 2 | import theme from './_.theme'; 3 | 4 | export default { 5 | window: css({ 6 | fontFamily: 'Helvetica Neue', 7 | background: theme.base00, 8 | marginTop: '-45px', 9 | paddingBottom: '20px', 10 | }), 11 | dock: css({ 12 | 'fontFamily': 'Helvetica Neue', 13 | '@media (min-width: 0px) and (max-width: 450px)': { 14 | display: 'none', 15 | }, 16 | }), 17 | draggable: css({ 18 | position: 'fixed', 19 | right: '0px', 20 | top: '100px', 21 | }), 22 | 23 | }; 24 | -------------------------------------------------------------------------------- /src/styles/Draggable.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/css' 2 | import theme from './_.theme'; 3 | 4 | export default { 5 | icon: css({ 6 | fontSize: '15px', 7 | }), 8 | dragIcon: css({ 9 | fontSize: '22px', 10 | color: theme.base04, 11 | }), 12 | draggable: css({ 13 | position: 'absolute', 14 | right: 0, 15 | top: 0, 16 | padding: '5px 5px 7px 5px', 17 | background: theme.base00, 18 | borderTopLeftRadius: '5px', 19 | borderBottomLeftRadius: '5px', 20 | }), 21 | dragButton: css({ 22 | cursor: 'ns-resize', 23 | }), 24 | btn: css({ 25 | 'display': 'block', 26 | 'width': '20px', 27 | 'height': '20px', 28 | 'padding': 0, 29 | 'margin': '4px 0 0 1px', 30 | 'background': theme.base0B, 31 | 'borderRadius': '2px', 32 | ':hover': { 33 | background: theme.base0A, 34 | }, 35 | }), 36 | }; 37 | -------------------------------------------------------------------------------- /src/styles/FormOptions.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/css' 2 | import theme from './_.theme'; 3 | 4 | export default { 5 | h4: css({ 6 | color: theme.base0B, 7 | fontSize: '14px', 8 | margin: '0', 9 | padding: '20px 0 5px 20px', 10 | }), 11 | }; 12 | -------------------------------------------------------------------------------- /src/styles/Header.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/css' 2 | import theme from './_.theme'; 3 | 4 | export default { 5 | btn: css({ 6 | float: 'right', 7 | margin: '-3px', 8 | }), 9 | icon: css({ 10 | 'fontSize': '22px', 11 | 'color': theme.base0B, 12 | 'paddingRight': '10px', 13 | ':hover': { 14 | color: theme.base0A, 15 | }, 16 | }), 17 | hli: css({ 18 | color: theme.base0D, 19 | paddingLeft: '25px', 20 | }), 21 | hlb: css({ 22 | color: theme.base09, 23 | paddingLeft: '10px', 24 | }), 25 | heading: css({ 26 | fontSize: '14px', 27 | background: theme.base00, 28 | color: theme.base00, 29 | fontWeight: 'bold', 30 | textTransform: 'uppercase', 31 | padding: '14px 0 13px 0', 32 | margin: 0, 33 | position: 'absolute', 34 | width: '100%', 35 | zIndex: 99, 36 | }), 37 | }; 38 | -------------------------------------------------------------------------------- /src/styles/RenderFormData.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/css' 2 | import theme from './_.theme'; 3 | 4 | export default { 5 | container: css({ 6 | marginLeft: '10px', 7 | }), 8 | heading: css({ 9 | color: theme.base00, 10 | padding: '10px', 11 | margin: '44px 0 0 0', 12 | background: theme.base03, 13 | fontSize: '15px', 14 | textTransform: 'uppercase', 15 | }), 16 | select: css({ 17 | textAlign: 'right', 18 | }), 19 | windowed: css({ 20 | marginTop: '45px', 21 | }), 22 | icon: css({ 23 | marginTop: '-3px', 24 | }), 25 | controls: { 26 | button: css({ 27 | 'borderRadius': 0, 28 | 'width': '25%', 29 | 'display': 'block', 30 | 'float': 'left', 31 | 'fontSize': '20px', 32 | 'padding': '3px 0 6px 0', 33 | 'background': theme.base01, 34 | 'color': theme.base00, 35 | ':hover': { 36 | background: theme.base03, 37 | color: theme.base00, 38 | }, 39 | ':hover g': { 40 | color: theme.base00, 41 | }, 42 | }), 43 | icon: css({ 44 | color: theme.base00, 45 | }), 46 | iconOptionsActive: css({ 47 | 'color': theme.base0B, 48 | ':hover': { 49 | color: theme.base00, 50 | }, 51 | }), 52 | }, 53 | }; 54 | -------------------------------------------------------------------------------- /src/styles/SelectInitialForm.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/css' 2 | import theme from './_.theme'; 3 | 4 | export default { 5 | icon: css({ 6 | color: theme.base0A, 7 | }), 8 | btn: css({ 9 | 'margin': 0, 10 | 'width': '100%', 11 | 'color': theme.base04, 12 | 'display': 'block', 13 | 'padding': '15px 30px', 14 | 'fontSize': '16px', 15 | 'textAlign': 'left', 16 | 'letterSpacing': '3px', 17 | ':hover': { 18 | background: theme.base01, 19 | }, 20 | }), 21 | }; 22 | -------------------------------------------------------------------------------- /src/styles/SelectMenu.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/css' 2 | import theme from './_.theme'; 3 | 4 | export default { 5 | select: css({ 6 | border: 0, 7 | margin: '-5px', 8 | color: theme.base0B, 9 | width: '250px', 10 | height: '28px', 11 | padding: '5px 35px 5px 10px', 12 | fontSize: '14px', 13 | appearance: 'none', 14 | backgroundColor: theme.base00, 15 | backgroundPosition: 'right 50%', 16 | backgroundRepeat: 'no-repeat', 17 | backgroundImage: "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAMCAYAAABSgIzaAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDZFNDEwNjlGNzFEMTFFMkJEQ0VDRTM1N0RCMzMyMkIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDZFNDEwNkFGNzFEMTFFMkJEQ0VDRTM1N0RCMzMyMkIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0NkU0MTA2N0Y3MUQxMUUyQkRDRUNFMzU3REIzMzIyQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0NkU0MTA2OEY3MUQxMUUyQkRDRUNFMzU3REIzMzIyQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuGsgwQAAAA5SURBVHjaYvz//z8DOYCJgUxAf42MQIzTk0D/M+KzkRGPoQSdykiKJrBGpOhgJFYTWNEIiEeAAAMAzNENEOH+do8AAAAASUVORK5CYII=')", 18 | }), 19 | }; 20 | -------------------------------------------------------------------------------- /src/styles/SimpleCheckbox.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/css' 2 | import theme from './_.theme'; 3 | 4 | export default { 5 | label: css({ 6 | 'display': 'block', 7 | 'fontSize': '15px', 8 | 'padding': '0 0 0 20px', 9 | 'margin': '0', 10 | 'color': theme.base04, 11 | ':hover': { 12 | color: theme.base0B, 13 | }, 14 | }), 15 | input: css({ 16 | margin: '0 5px 0 0', 17 | }), 18 | }; 19 | -------------------------------------------------------------------------------- /src/styles/_.theme.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | // scheme: 'ocean', 3 | // author: 'chris kempson (http://chriskempson.com)', 4 | base00: '#2b303b', 5 | base01: '#343d46', 6 | base02: '#4f5b66', 7 | base03: '#65737e', 8 | base04: '#a7adba', 9 | base05: '#c0c5ce', 10 | base06: '#dfe1e8', 11 | base07: '#eff1f5', 12 | base08: '#bf616a', 13 | base09: '#d08770', 14 | base0A: '#ebcb8b', 15 | base0B: '#a3be8c', 16 | base0C: '#96b5b4', 17 | base0D: '#8fa1b3', 18 | base0E: '#b48ead', 19 | base0F: '#ab7967', 20 | }; 21 | -------------------------------------------------------------------------------- /src/styles/_.utils.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/css' 2 | 3 | export default { 4 | clearfix: css({ 5 | overflow: 'auto', 6 | zoom: 1, 7 | }), 8 | hidden: css({ 9 | display: 'none !important', 10 | }), 11 | left: css({ 12 | float: 'left', 13 | }), 14 | rigth: css({ 15 | float: 'right', 16 | }), 17 | button: css({ 18 | border: 0, 19 | margin: 0, 20 | padding: 0, 21 | cursor: 'pointer', 22 | background: 'transparent', 23 | }), 24 | }; 25 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | export const mapo = (object, callback) => 2 | Object.keys(object).map(key => 3 | callback(key, object[key])); 4 | 5 | export function copyStyles(sourceDoc, targetDoc) { 6 | Array.from(sourceDoc.styleSheets).forEach((styleSheet: any) => { 7 | if (styleSheet.cssRules) { 8 | const newStyleEl = sourceDoc.createElement("style"); 9 | 10 | Array.from(styleSheet.cssRules).forEach((cssRule: any) => { 11 | newStyleEl.appendChild(sourceDoc.createTextNode(cssRule.cssText)); 12 | }); 13 | 14 | targetDoc.head.appendChild(newStyleEl); 15 | } 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /tests/tests.ts: -------------------------------------------------------------------------------- 1 | /* TEST */ 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | "jsx": "react", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "commonjs", /* Specify what module code is generated. */ 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "resolveJsonModule": true, /* Enable importing .json files. */ 39 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 40 | 41 | /* JavaScript Support */ 42 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 43 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 44 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 45 | 46 | /* Emit */ 47 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 48 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 49 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 50 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 51 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 52 | "outDir": "./lib", /* Specify an output folder for all emitted files. */ 53 | // "removeComments": true, /* Disable emitting comments. */ 54 | // "noEmit": true, /* Disable emitting files from a compilation. */ 55 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 56 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 57 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 58 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 61 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 62 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 63 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 64 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 65 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 66 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 67 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 68 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 69 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 70 | 71 | /* Interop Constraints */ 72 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 73 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 74 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 75 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 76 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 77 | 78 | /* Type Checking */ 79 | "strict": false, /* Enable all strict type-checking options. */ 80 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 81 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 82 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 83 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 84 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 85 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 86 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 87 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 88 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 89 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 90 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 91 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 92 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 93 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 94 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 95 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 96 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 97 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 98 | 99 | /* Completeness */ 100 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 101 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 102 | }, 103 | "include": ["./src/**/*"], 104 | "exclude": ["./lib/"] 105 | } 106 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const TerserPlugin = require("terser-webpack-plugin"); 3 | 4 | const MINIFY = process.env.MINIFY === "YES"; 5 | 6 | const rules = [{ 7 | test: /\.tsx?$/, 8 | exclude: /node_modules/, 9 | use: ['ts-loader'], 10 | }, { 11 | test: /\.css$/, 12 | use: ["style-loader", "css-loader"], 13 | }]; 14 | 15 | module.exports = { 16 | mode: MINIFY ? "production" : "development", 17 | devtool: 'source-map', 18 | entry: './src/index', 19 | output: { 20 | path: path.join(__dirname, 'umd'), 21 | library: 'MobxReactFormDevTools', 22 | libraryTarget: 'umd', 23 | filename: MINIFY ? "MobxReactFormDevTools.umd.min.js" : "MobxReactFormDevTools.umd.js", 24 | }, 25 | resolve: { 26 | modules: [path.resolve(__dirname, 'node_modules')], 27 | extensions: ['', '.js', '.ts', '.tsx', '.json'], 28 | alias: { 29 | mobx: path.resolve(__dirname, 'node_modules/mobx'), 30 | // 'react-icons': path.resolve(__dirname, 'node_modules/react-icons'), 31 | }, 32 | }, 33 | externals: { 34 | 'mobx-react-form': 'mobx-react-form', 35 | 'mobx-react': 'mobx-react', 36 | 'react': 'react', 37 | 'mobx': 'mobx', 38 | }, 39 | optimization: { 40 | minimize: MINIFY, 41 | minimizer: [new TerserPlugin()], 42 | }, 43 | module: { rules }, 44 | }; 45 | --------------------------------------------------------------------------------