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 |
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 |
--------------------------------------------------------------------------------