26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/docs/asset-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "main.css": "static/css/main.1d316427.css",
3 | "main.css.map": "static/css/main.1d316427.css.map",
4 | "main.js": "static/js/main.f2da4b7a.js",
5 | "main.js.map": "static/js/main.f2da4b7a.js.map",
6 | "static/media/dynamic_docs.md": "static/media/dynamic_docs.c45dd5e7.md",
7 | "static/media/form_docs.md": "static/media/form_docs.c680d6e1.md",
8 | "static/media/forms.png": "static/media/forms.aec5c7b8.png",
9 | "static/media/getting_started.md": "static/media/getting_started.2be5c59d.md",
10 | "static/media/glyphicons-halflings-regular.eot": "static/media/glyphicons-halflings-regular.f4769f9b.eot",
11 | "static/media/glyphicons-halflings-regular.svg": "static/media/glyphicons-halflings-regular.89889688.svg",
12 | "static/media/glyphicons-halflings-regular.ttf": "static/media/glyphicons-halflings-regular.e18bbf61.ttf",
13 | "static/media/glyphicons-halflings-regular.woff": "static/media/glyphicons-halflings-regular.fa277232.woff",
14 | "static/media/glyphicons-halflings-regular.woff2": "static/media/glyphicons-halflings-regular.448c34a5.woff2",
15 | "static/media/intro.md": "static/media/intro.fda87512.md",
16 | "static/media/list_docs.md": "static/media/list_docs.12101c16.md",
17 | "static/media/schema_docs.md": "static/media/schema_docs.01abfc75.md"
18 | }
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/lib/js/constants.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var _keymirror = require("keymirror");
4 |
5 | var _keymirror2 = _interopRequireDefault(_keymirror);
6 |
7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
8 |
9 | module.exports = {
10 | /**
11 | * At Form can either:
12 | * * ALL - Always show edit state for all of its fields
13 | * * SELECTION - Show edit icons next to items, selecting one show edit state for that item
14 | * * NEVER - Never show edit state for the items (view only)
15 | */
16 | FormEditStates: (0, _keymirror2.default)({
17 | ALWAYS: null,
18 | SELECTED: null,
19 | NEVER: null,
20 | TABLE: null
21 | }),
22 |
23 | FormGroupLayout: (0, _keymirror2.default)({
24 | ROW: null,
25 | COLUMN: null,
26 | INLINE: null
27 | })
28 | }; /**
29 | * Copyright (c) 2017 - present, The Regents of the University of California,
30 | * through Lawrence Berkeley National Laboratory (subject to receipt
31 | * of any required approvals from the U.S. Dept. of Energy).
32 | * All rights reserved.
33 | *
34 | * This source code is licensed under the BSD-style license found in the
35 | * LICENSE file in the root directory of this source tree.
36 | */
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 | React Dynamic Forms
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/src/components/View.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015 - present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | import React from "react";
12 |
13 | import formGroup from "../js/formGroup";
14 |
15 | class View extends React.Component {
16 | render() {
17 | const text = this.props.value;
18 | const view = this.props.view;
19 | let color = "";
20 | let background = "";
21 | const style = {
22 | color,
23 | background,
24 | // height: 23,
25 | height: "100%",
26 | width: "100%",
27 | paddingLeft: 3
28 | };
29 | if (!view) {
30 | return (
31 |
32 | {text}
33 |
34 | );
35 | } else {
36 | return (
37 |
38 | {view(text)}
39 |
40 | );
41 | }
42 | }
43 | }
44 |
45 | export default formGroup(View, true);
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/src/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015 - present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | import Form from "./components/Form";
12 | import Schema from "./components/Schema";
13 | import Field from "./components/Field";
14 | import formGroup from "./js/formGroup";
15 | import formList from "./js/formList";
16 | import List from "./components/List";
17 | import TextEdit from "./components/TextEdit";
18 | import TextArea from "./components/TextArea";
19 | import Chooser from "./components/Chooser.js";
20 | import DateEdit from "./components/DateEdit";
21 | import TagsEdit from "./components/TagsEdit";
22 | import RadioButtons from "./components/RadioButtons";
23 | import CheckBoxes from "./components/CheckBoxes";
24 | import View from "./components/View";
25 | import { FormEditStates, FormGroupLayout } from "./js/constants";
26 |
27 | export { Form };
28 | export { Schema };
29 | export { Field };
30 | export { formGroup };
31 | export { formList };
32 | export { List };
33 | export { TextEdit };
34 | export { TextArea };
35 | export { Chooser };
36 | export { DateEdit };
37 | export { TagsEdit };
38 | export { RadioButtons };
39 | export { CheckBoxes };
40 | export { View };
41 | export { FormEditStates, FormGroupLayout };
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/lib/css/dateedit.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015 - present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | input.datepicker__input.rdf {
12 | font-size: 12px;
13 | height: 30px;
14 | margin-bottom: 10px;
15 | border-radius: 3px;
16 | padding-left: 6px;
17 | color: #555555;
18 | background-color: #ffffff;
19 | background-image: none;
20 | border: 1px solid #cccccc;
21 | border-radius: 4px;
22 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
23 | box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
24 | -webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
25 | -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
26 | transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
27 | }
28 |
29 | input.datepicker__input.rdf:focus {
30 | border-color: #66afe9;
31 | outline: 0;
32 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);
33 | box-shadow: inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);
34 | }
35 |
36 | input.datepicker__input.has-error {
37 | border-color: #B94A48;
38 | }
39 |
40 | input.datepicker__input.is-missing {
41 | background-color: floralwhite;
42 | }
43 |
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/src/css/dateedit.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015 - present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | input.datepicker__input.rdf {
12 | font-size: 12px;
13 | height: 30px;
14 | margin-bottom: 10px;
15 | border-radius: 3px;
16 | padding-left: 6px;
17 | color: #555555;
18 | background-color: #ffffff;
19 | background-image: none;
20 | border: 1px solid #cccccc;
21 | border-radius: 4px;
22 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
23 | box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
24 | -webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
25 | -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
26 | transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
27 | }
28 |
29 | input.datepicker__input.rdf:focus {
30 | border-color: #66afe9;
31 | outline: 0;
32 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);
33 | box-shadow: inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);
34 | }
35 |
36 | input.datepicker__input.has-error {
37 | border-color: #B94A48;
38 | }
39 |
40 | input.datepicker__input.is-missing {
41 | background-color: floralwhite;
42 | }
43 |
--------------------------------------------------------------------------------
/packages/website/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | React Dynamic Forms
16 |
17 |
18 |
19 |
20 |
29 |
30 |
31 |
32 |
33 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/src/components/Schema.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015 - present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | import invariant from "invariant";
12 |
13 | /**
14 | * A schema can be specified using JSX to define the rules for
15 | * each form field. As an example, here is a Form that will take the
16 | * first name, last name and email of a contact. We can define also
17 | * that the email should be of format `email` and that the first and
18 | * last names are `required`:
19 | *
20 | * ```
21 | * const schema = (
22 | *
23 | *
25 | *
27 | *
29 | *
30 | * );
31 | * ```
32 | *
33 | * See also `Field`.
34 | */
35 | export default class Schema {
36 | render() {
37 | invariant(
38 | false,
39 | `${this.constructor
40 | .name} elements are for schema configuration only and should not be rendered`
41 | );
42 | return;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/lib/css/tagsedit.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015 - present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | .Select-control {
12 | height: 26px;
13 | }
14 |
15 | .Select-value {
16 | line-height: 26px !important;
17 | }
18 |
19 | .Select-value-label {
20 | line-height: 24px;
21 | font-size: 12px;
22 | }
23 |
24 | .Select-menu-outer {
25 | font-size: 12px;
26 | }
27 |
28 | .Select-input {
29 | height: 26px;
30 | }
31 |
32 | .Select.is-missing > .Select-control {
33 | background: floralwhite;
34 | }
35 |
36 | .Select--multi .Select-value {
37 | height: 26px;
38 | height: 24px;
39 | margin-top: 1px;
40 | border-color: #ccc
41 | }
42 |
43 | .Select--multi .Select-value-label {
44 | line-height: 22px;
45 | font-size: 12px;
46 | padding: 0px;
47 | margin-top: -6px;
48 | padding-left: 5px;
49 | padding-right: 5px;
50 | background: #DDD;
51 | color: #555555;
52 | border-color: #555;
53 | }
54 |
55 | .Select--multi .Select-value-icon {
56 | line-height: 22px;
57 | font-size: 12px;
58 | padding: 0px;
59 | margin-top: -6px;
60 | padding-left: 5px;
61 | padding-right: 5px;
62 | background: #DDD;
63 | color: #555555;
64 | border-right-color: #ccc;
65 | }
66 |
67 | .Select--multi .Select-value-icon:hover {
68 | background: #DFDFDF;
69 | color: #b94a48;
70 | }
71 |
72 | .Select.missing.Select--multi.is-searchable > .Select-control {
73 | background: floralwhite;
74 | }
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/src/css/tagsedit.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015 - present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | .Select-control {
12 | height: 26px;
13 | }
14 |
15 | .Select-value {
16 | line-height: 26px !important;
17 | }
18 |
19 | .Select-value-label {
20 | line-height: 24px;
21 | font-size: 12px;
22 | }
23 |
24 | .Select-menu-outer {
25 | font-size: 12px;
26 | }
27 |
28 | .Select-input {
29 | height: 26px;
30 | }
31 |
32 | .Select.is-missing > .Select-control {
33 | background: floralwhite;
34 | }
35 |
36 | .Select--multi .Select-value {
37 | height: 26px;
38 | height: 24px;
39 | margin-top: 1px;
40 | border-color: #ccc
41 | }
42 |
43 | .Select--multi .Select-value-label {
44 | line-height: 22px;
45 | font-size: 12px;
46 | padding: 0px;
47 | margin-top: -6px;
48 | padding-left: 5px;
49 | padding-right: 5px;
50 | background: #DDD;
51 | color: #555555;
52 | border-color: #555;
53 | }
54 |
55 | .Select--multi .Select-value-icon {
56 | line-height: 22px;
57 | font-size: 12px;
58 | padding: 0px;
59 | margin-top: -6px;
60 | padding-left: 5px;
61 | padding-right: 5px;
62 | background: #DDD;
63 | color: #555555;
64 | border-right-color: #ccc;
65 | }
66 |
67 | .Select--multi .Select-value-icon:hover {
68 | background: #DFDFDF;
69 | color: #b94a48;
70 | }
71 |
72 | .Select.missing.Select--multi.is-searchable > .Select-control {
73 | background: floralwhite;
74 | }
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/tests/TextEditTests.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | import React from "react";
12 | import {
13 | TestBasic // TextEditDisabled, // TextEditPlaceholder,
14 | } from // TextEditPassword,
15 | // TextEditRequired1,
16 | // TextEditRequired2,
17 | // TextEditRequired3,
18 | // TextEditValidate,
19 | // TextEditValidateInt
20 | "./components_test/TextEditExamples";
21 |
22 | export default React.createClass({
23 | render() {
24 | return (
25 |
26 |
27 |
28 |
TextEdit Tests
29 | TextEdit initial value
30 |
31 | {/*}
32 | Diabled TextEdit
33 |
34 | With a placeholder
35 |
36 | Password type
37 |
38 | Required field (with showRequired turned ON):
39 |
40 | Required field (with showRequired turned OFF):
41 |
42 | Required field (with showRequired turned ON and initial value):
43 |
44 | Validated field (email address)
45 |
46 | Validated field (integer)
47 | */}
48 |
49 |
50 |
51 | );
52 | }
53 | });
54 |
--------------------------------------------------------------------------------
/packages/website/src/App.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | import "./App.css";
12 | import React, { Component } from "react";
13 | import { HashRouter as Router, Route, Switch } from "react-router-dom";
14 |
15 | import Prism from "prismjs"; // eslint-disable-line
16 | import "prismjs/components/prism-typescript";
17 | import "prismjs/themes/prism.css";
18 |
19 | import Header from "./Header";
20 | import Sidebar from "./Sidebar";
21 | import Guide from "./components/Guide";
22 | import Example from "./components/Example";
23 | import API from "./components/API";
24 |
25 | import { bodyStyle, mainStyle, contentStyle } from "./styles";
26 |
27 | class Page extends Component {
28 | render() {
29 | return (
30 |
54 |
55 | );
56 | }
57 | }
58 |
59 | export default App;
60 |
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute to ESnet React Forms
2 |
3 | In general we follow the "fork & pull" model as outlined in the
4 | [GitHub docs](https://help.github.com/articles/using-pull-requests/).
5 |
6 | Here are a few additional thoughts on how to make the contribution process as
7 | painless as possible for yourself and for the developers.
8 |
9 | 1. *Communicate.* please create an GitHub issue in the appropriate GitHub
10 | project communicating your plans. This allows coordination -- it's possible
11 | someone else has ideas about this topic and it can save a lot of time if
12 | things are disucssed before you dive in. When you submit your pull request
13 | please include the issue number with the discussion relevant to this pull
14 | request.
15 |
16 | 2. *Work on a branch.* Work on a branch in a fork of the project code. *DO NOT
17 | WORK ON `master` or `develop`.*
18 |
19 | 3. *Follow the style of the code.* All code must follow the style of the
20 | project. We generally adhere to the [Google JavaScript style
21 | guide](https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml).
22 | Please lint your code with a reasonable linting tool.
23 |
24 | 4. *Create examples.* All new features must have appropriate examples in the
25 | examples directory. If you are adding a major feature you may wish to create a
26 | new example page. If you are adding a smaller feature you may just wish to
27 | augment one of the existing examples.
28 |
29 | 5. *Tests.* We currently evaluating how to test this library. In the mean time
30 | please be sure to check that all of the examples continue to work before
31 | submitting your pull request. If you have suggestions on how to build tests
32 | we'd love to hear them.
33 |
34 | The [jQuery guidlines](http://contribute.jquery.org/commits-and-pull-requests/)
35 | have some good suggestions for rectifying common Git mistakes
36 |
37 | Once you have you are ready to share your code go ahead and follow the
38 | instructions in the [GitHub
39 | docs](https://help.github.com/articles/using-pull-requests/) to submit your
40 | pull request.
41 |
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/tests/ChooserTests.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | import React from "react";
12 | import {
13 | ChooserBasic,
14 | ChooserWider,
15 | ChooserSortedList,
16 | ChooserInitialValue,
17 | ChooserInitialNull,
18 | ChooserSortedInitial,
19 | ChooserDisabled,
20 | ChooserSearchDisabled,
21 | ChooserSingleDeselect,
22 | ChooserLongList
23 | } from "./components_test/ChooserExamples";
24 |
25 | export default React.createClass({
26 | render() {
27 | return (
28 |
29 |
30 |
31 |
Chooser Tests
32 | Chooser with simple list
33 |
34 | Wider chooser
35 |
36 | Chooser with a sorted list
37 |
38 | Chooser with initial value
39 |
40 | Chooser with a null initial value
41 |
42 | Chooser with sorted list and initial value
43 |
44 | Disabled chooser
45 |
46 | Chooser with no search
47 |
48 | Chooser allowing clearing single selection
49 |
50 | Chooser with a very long list
51 |
52 |
53 |
54 |
55 | );
56 | }
57 | });
58 |
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/src/components/Field.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017 - present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | import React from "react";
12 | import invariant from "invariant";
13 | import PropTypes from "prop-types";
14 |
15 | /**
16 | * A `Field` is a part of the JSX definition of a `Schema`. Each `Field` describes
17 | * the rules and meta data associated with a field on the `Form`.
18 | *
19 | * For example, here is an `Field` which will input the users email address, defining
20 | * a user friendly label "Email", a placeholder and a validation rule that expects
21 | * the field to be a valid email address. The field is also required to be filled in.
22 | *
23 | * ```
24 | *
25 | * ...
26 | *
32 | * ...
33 | *
34 | * ```
35 | */
36 | export default class Field extends React.Component {
37 | render() {
38 | invariant(
39 | false,
40 | `${this.constructor.name} elements are for schema configuration only and should not be rendered`
41 | );
42 | return;
43 | }
44 | }
45 |
46 | Field.propTypes = {
47 | /**
48 | * name - The name of the field, or basically how it is referenced when rendering the field
49 | */
50 | name: PropTypes.string,
51 |
52 | /**
53 | * label - The UI fieldly name of the field, used when constructing a `Group`.
54 | */
55 | label: PropTypes.string,
56 |
57 | /**
58 | * placeholder - If appropiate to the widget, displays placeholder text.
59 | */
60 | placeholder: PropTypes.string,
61 |
62 | /**
63 | * validation* - See [Revalidator](https://github.com/flatiron/revalidator) for possible formats
64 | * for the validation property.
65 | */
66 | validation: PropTypes.object
67 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | "ESnet React Forms Library, Copyright (c) 2015-2017, The Regents of the
2 | University of California, through Lawrence Berkeley National Laboratory
3 | (subject to receipt of any required approvals from the U.S. Dept. of Energy).
4 | All rights reserved."
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | (1) Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | (2) Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation and/
14 | or other materials provided with the distribution.
15 |
16 | (3) Neither the name of the University of California, Lawrence Berkeley
17 | National Laboratory, U.S. Dept. of Energy nor the names of its contributors may
18 | be used to endorse or promote products derived from this software without
19 | specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | You are under no obligation whatsoever to provide any bug fixes, patches, or
33 | upgrades to the features, functionality or performance of the source code
34 | ("Enhancements") to anyone; however, if you choose to make your Enhancements
35 | available either publicly, or directly to Lawrence Berkeley National
36 | Laboratory, without imposing a separate written license agreement for such
37 | Enhancements, then you hereby grant the following license: a non-exclusive,
38 | royalty-free perpetual license to install, use, modify, prepare derivative
39 | works, incorporate into other computer software, distribute, and sublicense
40 | such enhancements or derivative works thereof, in binary and source code form.
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/LICENSE:
--------------------------------------------------------------------------------
1 | "ESnet React Forms Library, Copyright (c) 2015-2017, The Regents of the
2 | University of California, through Lawrence Berkeley National Laboratory
3 | (subject to receipt of any required approvals from the U.S. Dept. of Energy).
4 | All rights reserved."
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | (1) Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | (2) Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation and/
14 | or other materials provided with the distribution.
15 |
16 | (3) Neither the name of the University of California, Lawrence Berkeley
17 | National Laboratory, U.S. Dept. of Energy nor the names of its contributors may
18 | be used to endorse or promote products derived from this software without
19 | specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | You are under no obligation whatsoever to provide any bug fixes, patches, or
33 | upgrades to the features, functionality or performance of the source code
34 | ("Enhancements") to anyone; however, if you choose to make your Enhancements
35 | available either publicly, or directly to Lawrence Berkeley National
36 | Laboratory, without imposing a separate written license agreement for such
37 | Enhancements, then you hereby grant the following license: a non-exclusive,
38 | royalty-free perpetual license to install, use, modify, prepare derivative
39 | works, incorporate into other computer software, distribute, and sublicense
40 | such enhancements or derivative works thereof, in binary and source code form.
--------------------------------------------------------------------------------
/packages/website/src/components/Guide.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2016-present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | import React, {Component} from "react";
12 | import Markdown from "react-markdown";
13 | import Prism from "prismjs";
14 |
15 | import Guides from "../guides/guides";
16 | import { codeRenderer, codeBlockRenderer } from "../renderers";
17 |
18 | export default class extends Component {
19 | constructor(props) {
20 | super(props);
21 | this.state = {
22 | markdown: null
23 | };
24 | }
25 |
26 | componentDidMount() {
27 | window.scrollTo(0, 0);
28 | Prism.highlightAll();
29 | const guideName = this.props.match.params.doc || "intro";
30 | const markdownFile = Guides[guideName];
31 | fetch(markdownFile)
32 | .then(response => {
33 | return response.text();
34 | })
35 | .then(markdown => {
36 | this.setState({ markdown });
37 | });
38 | this.setState({ markdown: null });
39 | }
40 |
41 | componentWillReceiveProps(nextProps) {
42 | window.scrollTo(0, 0);
43 | const guideName = nextProps.match.params.doc || "intro";
44 | const markdownFile = Guides[guideName];
45 | fetch(markdownFile)
46 | .then(response => {
47 | return response.text();
48 | })
49 | .then(markdown => {
50 | this.setState({ markdown });
51 | });
52 | this.setState({ markdown: null });
53 | }
54 |
55 | componentDidUpdate() {
56 | Prism.highlightAll();
57 | }
58 |
59 | render() {
60 | if (this.state.markdown !== null) {
61 | return (
62 |
63 |
64 |
65 |
69 |
70 |
71 |
72 | );
73 | } else {
74 | return (
75 |
76 |
77 |
78 | );
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/lib/css/list.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015 - present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | /*
12 | * The container includes the whole list, but not the [+] at the bottom
13 | */
14 | .esnet-forms-listeditview-container {
15 | padding-left: 0px;
16 | list-style-type: none;
17 | margin-bottom: 0px;
18 | }
19 |
20 | .esnet-forms-listeditview-container:last-child {
21 | margin-bottom: 0;
22 | }
23 |
24 | /*
25 | * The inner LI of the container is each item, including the [-] control
26 | */
27 |
28 | .esnet-forms-listeditview-container li {
29 | margin-left: 0px;
30 | }
31 |
32 | /*
33 | * The main styling for each item
34 | */
35 |
36 | .esnet-forms-listeditview-edit-item {
37 | width: 95%;
38 | margin-bottom: 10px;
39 | padding-top: 2px;
40 | }
41 |
42 | .esnet-forms-listeditview-edit-item.no-controls {
43 | width: 95%;
44 | }
45 |
46 | /*
47 | .esnet-forms-minus-action-box {
48 | float: left;
49 | margin-top: 5px;
50 | vertical-align: top;
51 | width: 28px;
52 | height: 28px;
53 | background: #EDEDED;
54 | margin-left: -5px;
55 | z-index: 10;
56 | border: #E5E5E5;
57 | border-style: solid;
58 | border-width: 1px;
59 | border-radius: 2px;
60 | }*/
61 |
62 | .esnet-forms-plus-action-box-dialog {
63 | clear: both;
64 | border-width: 1px;
65 | border-color: #cef4d2;
66 | border-style: solid;
67 | border-radius: 4px;
68 | padding: 10px;
69 | height: 70px;
70 | width: 95%;
71 | background: #efe;
72 | }
73 |
74 | /*
75 | List transitions
76 | */
77 |
78 | .esnet-forms-list {
79 | font-size: 12px;
80 | }
81 |
82 | /** start of entering and end of leaving **/
83 | li.esnet-forms-list-item-enter,
84 | li.esnet-forms-list-item-leave.esnet-forms-list-item-leave-active {
85 | opacity: 0.01;
86 | max-height: 0px;
87 | }
88 |
89 | /** start of leaving and end of entering **/
90 | li.esnet-forms-list-item-leave,
91 | li.esnet-forms-list-item-enter.esnet-forms-list-item-enter-active {
92 | opacity: 1;
93 | max-height: 100px;
94 | /*max-height: 50px;*/
95 | }
96 |
97 | /** ease in out quint **/
98 | li.esnet-forms-list-item-enter,
99 | li.esnet-forms-list-item-leave {
100 | -moz-transition: all 100ms ease 0s;
101 | -webkit-transition: all 100ms ease 0s;
102 | transition: all 100ms ease 0s;
103 | }
104 |
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/src/css/list.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015 - present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | /*
12 | * The container includes the whole list, but not the [+] at the bottom
13 | */
14 | .esnet-forms-listeditview-container {
15 | padding-left: 0px;
16 | list-style-type: none;
17 | margin-bottom: 0px;
18 | }
19 |
20 | .esnet-forms-listeditview-container:last-child {
21 | margin-bottom: 0;
22 | }
23 |
24 | /*
25 | * The inner LI of the container is each item, including the [-] control
26 | */
27 |
28 | .esnet-forms-listeditview-container li {
29 | margin-left: 0px;
30 | }
31 |
32 | /*
33 | * The main styling for each item
34 | */
35 |
36 | .esnet-forms-listeditview-edit-item {
37 | width: 95%;
38 | margin-bottom: 10px;
39 | padding-top: 2px;
40 | }
41 |
42 | .esnet-forms-listeditview-edit-item.no-controls {
43 | width: 95%;
44 | }
45 |
46 | /*
47 | .esnet-forms-minus-action-box {
48 | float: left;
49 | margin-top: 5px;
50 | vertical-align: top;
51 | width: 28px;
52 | height: 28px;
53 | background: #EDEDED;
54 | margin-left: -5px;
55 | z-index: 10;
56 | border: #E5E5E5;
57 | border-style: solid;
58 | border-width: 1px;
59 | border-radius: 2px;
60 | }*/
61 |
62 | .esnet-forms-plus-action-box-dialog {
63 | clear: both;
64 | border-width: 1px;
65 | border-color: #cef4d2;
66 | border-style: solid;
67 | border-radius: 4px;
68 | padding: 10px;
69 | height: 70px;
70 | width: 95%;
71 | background: #efe;
72 | }
73 |
74 | /*
75 | List transitions
76 | */
77 |
78 | .esnet-forms-list {
79 | font-size: 12px;
80 | }
81 |
82 | /** start of entering and end of leaving **/
83 | li.esnet-forms-list-item-enter,
84 | li.esnet-forms-list-item-leave.esnet-forms-list-item-leave-active {
85 | opacity: 0.01;
86 | max-height: 0px;
87 | }
88 |
89 | /** start of leaving and end of entering **/
90 | li.esnet-forms-list-item-leave,
91 | li.esnet-forms-list-item-enter.esnet-forms-list-item-enter-active {
92 | opacity: 1;
93 | max-height: 100px;
94 | /*max-height: 50px;*/
95 | }
96 |
97 | /** ease in out quint **/
98 | li.esnet-forms-list-item-enter,
99 | li.esnet-forms-list-item-leave {
100 | -moz-transition: all 100ms ease 0s;
101 | -webkit-transition: all 100ms ease 0s;
102 | transition: all 100ms ease 0s;
103 | }
104 |
--------------------------------------------------------------------------------
/docs/static/media/intro.fda87512.md:
--------------------------------------------------------------------------------
1 | ## Introduction
2 |
3 | ---
4 |
5 | This repository contains a set of React based forms components which are used within ESnet for our network database application (ESDB), but could be used by any React based project needing to build complex forms.
6 |
7 | Our approach is to treat a form as a controlled input, essentially an input with many inputs (which may have many inputs, and so on...) You maintain your form's state however you want, you pass that state down into the form as its value prop. If the form is edited, a callback is called and you can update your form state. When it comes time to save the form, that's up to you, you always have your form's state. On top of this the form has a schema defining rules. Therefore, you can also listen to changes in the count of either missing values or errors. With this information it is simple to control if the user can submit the form as well.
8 |
9 | The library is built on Immutable.js, so form state should be passed into the form as an Immutable.Map. This allows efficient operations on your form data, minimizing copying while ensuring safety as the form state is mutated.
10 |
11 | While part of defining a form is to specify a schema for your form, you still maintain complete control over the layout in the form in your `render()` method, just like any other react app. The schema and presentation are entirely separate. This React friendly approach makes it easy to build forms which dynamically change values or structure based on the current state of the form.
12 |
13 | This library contains:
14 |
15 | * Low level forms control wrappers that communicate errors and missing values to parent components and style themselves appropriately for errors and missing value state. You can write your own in the same way. Supplied standard form controls:
16 | * Textedit
17 | * TextArea
18 | * Checkboxes
19 | * RadioButtons
20 | * Chooser (internally we use react-select)
21 | * TagsEdit (again using react-select)
22 | * DateEdit (react-datepicker)
23 | * A `` component that lets you define the rules for each field. Each field is specified in a `` component
24 | * A `` component that acts as a top level controlled input for all of the form state, to assemble controls together and track state change, errors and missing values and enabling dynamic forms with via a declarative schema
25 | * Higher Order Components:
26 | * for grouping of controls with their labels, required state and editing control
27 | * building lists of forms
28 | * Inline editing
29 | * List editing
30 |
31 | The library is built on several other open source libraries, especially:
32 |
33 | * react
34 | * immutable.js
35 | * revalidator
36 | * react-bootstrap
37 | * react-select
38 | * react-virtualized
39 | * react-datepicker
40 |
41 | Please browse the examples for a feel for the library, or read on to get started.
42 |
--------------------------------------------------------------------------------
/packages/website/src/guides/intro.md:
--------------------------------------------------------------------------------
1 | ## Introduction
2 |
3 | ---
4 |
5 | This repository contains a set of React based forms components which are used within ESnet for our network database application (ESDB), but could be used by any React based project needing to build complex forms.
6 |
7 | Our approach is to treat a form as a controlled input, essentially an input with many inputs (which may have many inputs, and so on...) You maintain your form's state however you want, you pass that state down into the form as its value prop. If the form is edited, a callback is called and you can update your form state. When it comes time to save the form, that's up to you, you always have your form's state. On top of this the form has a schema defining rules. Therefore, you can also listen to changes in the count of either missing values or errors. With this information it is simple to control if the user can submit the form as well.
8 |
9 | The library is built on Immutable.js, so form state should be passed into the form as an Immutable.Map. This allows efficient operations on your form data, minimizing copying while ensuring safety as the form state is mutated.
10 |
11 | While part of defining a form is to specify a schema for your form, you still maintain complete control over the layout in the form in your `render()` method, just like any other react app. The schema and presentation are entirely separate. This React friendly approach makes it easy to build forms which dynamically change values or structure based on the current state of the form.
12 |
13 | This library contains:
14 |
15 | * Low level forms control wrappers that communicate errors and missing values to parent components and style themselves appropriately for errors and missing value state. You can write your own in the same way. Supplied standard form controls:
16 | * Textedit
17 | * TextArea
18 | * Checkboxes
19 | * RadioButtons
20 | * Chooser (internally we use react-select)
21 | * TagsEdit (again using react-select)
22 | * DateEdit (react-datepicker)
23 | * A `` component that lets you define the rules for each field. Each field is specified in a `` component
24 | * A `` component that acts as a top level controlled input for all of the form state, to assemble controls together and track state change, errors and missing values and enabling dynamic forms with via a declarative schema
25 | * Higher Order Components:
26 | * for grouping of controls with their labels, required state and editing control
27 | * building lists of forms
28 | * Inline editing
29 | * List editing
30 |
31 | The library is built on several other open source libraries, especially:
32 |
33 | * react
34 | * immutable.js
35 | * revalidator
36 | * react-bootstrap
37 | * react-select
38 | * react-virtualized
39 | * react-datepicker
40 |
41 | Please browse the examples for a feel for the library, or read on to get started.
42 |
--------------------------------------------------------------------------------
/packages/website/src/Header.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | import React, { Component } from "react";
12 | import logo from "./img/forms.png";
13 | import githubLogo from "./img/github.png";
14 |
15 | /* eslint-disable jsx-a11y/href-no-hash */
16 |
17 | export default class Header extends Component {
18 | render() {
19 | const githubLogoStyle = {
20 | width: 24,
21 | paddingRight: 5,
22 | marginTop: -4
23 | };
24 | return (
25 |
66 | );
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/src/components/RadioButtons.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017 - present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | import React from "react";
12 | import _ from "underscore";
13 |
14 | import formGroup from "../js/formGroup";
15 |
16 | class RadioButtons extends React.Component {
17 | handleChange(v) {
18 | // Callbacks
19 | if (this.props.onChange) {
20 | this.props.onChange(this.props.name, v);
21 | }
22 | if (this.props.onBlur) {
23 | this.props.onBlur(this.props.name);
24 | }
25 | }
26 |
27 | getCurrentChoiceLabel() {
28 | const choiceItem = this.props.optionList.find(item => {
29 | return item.get("id") === this.props.value;
30 | });
31 | return choiceItem ? choiceItem.get("label") : "";
32 | }
33 |
34 | inlineStyle(hasError, isMissing) {
35 | let color = "inherited";
36 | let background = "inherited";
37 | if (hasError) {
38 | color = "#b94a48";
39 | background = "#fff0f3";
40 | } else if (isMissing) {
41 | background = "floralwhite";
42 | }
43 | return {
44 | color,
45 | background,
46 | width: "100%",
47 | paddingLeft: 3
48 | };
49 | }
50 |
51 | render() {
52 | if (this.props.edit) {
53 | const items = this.props.optionList.map((item, i) => {
54 | const id = item.get("id");
55 | const label = item.get("label");
56 | return (
57 |
58 |
69 |
70 | );
71 | });
72 | return (
73 |
74 | {items}
75 |
76 | );
77 | } else {
78 | let text = this.getCurrentChoiceLabel();
79 | return (
80 |
121 | );
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/docs/static/media/form_docs.c680d6e1.md:
--------------------------------------------------------------------------------
1 | ### Forms example
2 |
3 | The forms library is designed to help you build a complete form. In this example
4 | we create a simple contacts form. There are other examples too of forms which change
5 | their structure as the user interacts with tham, as well as demostrating the use
6 | of lists within the forms. But here we keep it relatively simple.
7 |
8 | **What do we want from our form?**
9 |
10 | Essentially we want to provide perhaps some initial data, our form `"value"`,
11 | defaults in the case of a new form, or maybe our current
12 | database state in the case of editing an existing entity.
13 |
14 | As the user edits the data, we'll want to track that. We may choose to save
15 | it on submit (if it's a new form, that's likely), or save it as the user edits it
16 | (perhaps if they are using inline editing we might
17 | want to save the data when any fields are changed). Either way, the forms library
18 | allows you to provide a callback function, which will be called whenever the values
19 | in the form change. How you want to respond to that is up to you, but this example
20 | demostrates one possible approach.
21 |
22 | In addition to knowing that the form values have changed, we also need to know if
23 | the form has any errors or missing fields. We do this via callbacks as well, where
24 | each callback will tell you the number of missing or empty fields that exist within
25 | the form. You can use that to control if the user can submit the form or not, as
26 | we do in this example.
27 |
28 | Okay, so we have initial values and we have some callbacks.
29 |
30 | **How do we get a form up and running to use those?**
31 |
32 | Forms have two concerns. Each form has a schema which we use to provide the meta
33 | data for fields within the form. This includes UI elements like the label for each
34 | fields, the placeholder text, etc, but also rules around the field itself. For
35 | example a field (called an Field in this library),
36 |
37 | The form elements are defined by a **schema**. Schemas can be defined with JSX or manually. Here's the schema used in this page:
38 |
39 | const schema = (
40 |
41 |
43 |
45 |
47 |
48 |
49 |
50 | );
51 |
52 | As you can see the schema is used to associate the Field name (`"first_name"` for example) with some properties which define how it looks and what is a valid value for that Field. Here we define a label (`"First name"`), a placeholder text, and some validation properties. Required can be set true to have the form track that this Field field needs to be filled out before the form is submitted. More on errors and missing value counts below. In addition to being required or not, the Field can have a validation prop set which will be passed to Revalidator for field validation while the user interacts with the form. It is most common to use it to specify the type (`"string", "integer", or "number"`), but you can also specify a format, such as in the example above where the email Field is checked to make sure it is a valid email address. Maximum string lengths, or ranges of numeric values can also be specified. For full details see the [Revalidator website](https://github.com/flatiron/revalidator).
53 |
54 | Rendering is not automatic. Instead the form itself is a React component that you define. We define the form itself like this:
55 |
56 | class ContactForm extends React.Component {
57 |
58 | }
59 |
60 | And then implement the form layout like this:
61 |
62 | renderForm() {
63 | const disableSubmit = this.hasErrors();
64 | return (
65 |
73 | );
74 | }
75 |
76 | As you can see, we return a `
73 | );
74 | }
75 |
76 | As you can see, we return a `
44 | ```
45 |
46 | #### Tags
47 |
48 | The forms library `schema` supports visibility tags, which can be used to quickly control which set of fields show be visible and which should not, rather than setting each one. The schema for our example looks like
49 | this:
50 |
51 | ```jsx
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | ```
72 |
73 | You can see that for each Field we've defined a `tags` prop. This is a list of visibility tags. Here we've named our tags based on our type values ("Equipment Port", "Patch Panel" and "Foreign"). A special tag "all" can also be added meaning that the attr will always be visible.
74 |
75 | To turn on visibility we use the `visibility` prop on the `Form`. This method takes as its argument the tag to match against the schema to control the visibility of the fields. For example, if we passed in "Equipment Port" then all the attrs with a tag of "all" would be shown, as would those with a tag of "Equipment Port" ("device_name" and "interface"). All others would be hidden.
76 |
77 | ## Dynamic changing the form
78 |
79 | In this form we have a bookmark chooser. When the user selects a preset from this chooser it will fill the form with values. The subtle thing here is that this also sets the type chooser further down the form, which itself controls what fields will be shown. It's this kind of behavior that the forms code is designed to handle.
80 |
81 | Let's think this through:
82 |
83 | 1. The first thing that happens is that the user selects a bookmark from the top chooser.
84 | 2. We know when the user changes something by handling `onChange` in `handleChange()`, so we can compare the previous and next version of the form value
85 | 3. If the bookmark has indeed changed then we can merge in some pre-baked data for that bookmark into the form value before setting it as our source of truth. In this way the change of a single field can cause a change to many fields.
86 |
87 | ```js
88 | if (value.get("bookmarked") !== this.state.value.get("bookmarked")) {
89 | const bookmark = bookmarked[value.get("bookmarked")];
90 | const merged = value.merge(bookmark);
91 | this.setState({ value: merged });
92 | } else {
93 | this.setState({ value });
94 | }
95 | ```
96 |
97 | 4. The form will then re-render and update to show the new values. However we need to handle the visibility state of the form. The visibility of the form is a function of the data in the form (at least in this case), meaning that if the form data is in a particular state, we only show certain fields. Specifically, in this case, when we set the "type" between to one of three possible values we show different fields that only apply to that "type". Therefore, in our `render()` function we get the "type" out of our form state and then set our visibility based on that:
98 |
99 | ```js
100 | render() {
101 |
102 | // Current type
103 | const currentType = values.get("type");
104 |
105 | // Find the visibility tag given our current type
106 | const visibilityTag = getVisibilityTag(currentType);
107 |
108 | ...
109 | }
110 | ```
111 |
112 | As mentioned above, we encode the tags within the `Schema`, so here we are simply mapping between the current type value and the tags in the schema.
113 |
114 | 5. Finally, to complete the dynamically updating form, we simply render
115 | the form but set the visibility prop to our `visibilityTag`.
116 |
117 | ```
118 | render() {
119 | ...
120 | return (
121 |
128 | );
129 | }
130 | ```
131 |
--------------------------------------------------------------------------------
/packages/website/src/examples/dynamic/dynamic_docs.md:
--------------------------------------------------------------------------------
1 | ### Description
2 |
3 | The forms library allows you to create forms that dynamically change depending on other filled out fields. An example of this is a form which has a type field and that field controls several other fields that only apply to that type. In this case we want to:
4 |
5 | * Hide and show fields in reaction to a change in the type
6 | * Have hidden fields not be required, i.e. support conditional requires
7 |
8 | #### Render
9 |
10 | The above example begins with a pretty simple `renderForm()` implementation. In fact there's not much to see here. Regardless of the visibility that we'll control in a minute, we can just render all the fields and the forms code will take care of selectively hiding fields for us. Here is the rendered `
44 | ```
45 |
46 | #### Tags
47 |
48 | The forms library `schema` supports visibility tags, which can be used to quickly control which set of fields show be visible and which should not, rather than setting each one. The schema for our example looks like
49 | this:
50 |
51 | ```jsx
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | ```
72 |
73 | You can see that for each Field we've defined a `tags` prop. This is a list of visibility tags. Here we've named our tags based on our type values ("Equipment Port", "Patch Panel" and "Foreign"). A special tag "all" can also be added meaning that the attr will always be visible.
74 |
75 | To turn on visibility we use the `visibility` prop on the `Form`. This method takes as its argument the tag to match against the schema to control the visibility of the fields. For example, if we passed in "Equipment Port" then all the attrs with a tag of "all" would be shown, as would those with a tag of "Equipment Port" ("device_name" and "interface"). All others would be hidden.
76 |
77 | ## Dynamic changing the form
78 |
79 | In this form we have a bookmark chooser. When the user selects a preset from this chooser it will fill the form with values. The subtle thing here is that this also sets the type chooser further down the form, which itself controls what fields will be shown. It's this kind of behavior that the forms code is designed to handle.
80 |
81 | Let's think this through:
82 |
83 | 1. The first thing that happens is that the user selects a bookmark from the top chooser.
84 | 2. We know when the user changes something by handling `onChange` in `handleChange()`, so we can compare the previous and next version of the form value
85 | 3. If the bookmark has indeed changed then we can merge in some pre-baked data for that bookmark into the form value before setting it as our source of truth. In this way the change of a single field can cause a change to many fields.
86 |
87 | ```js
88 | if (value.get("bookmarked") !== this.state.value.get("bookmarked")) {
89 | const bookmark = bookmarked[value.get("bookmarked")];
90 | const merged = value.merge(bookmark);
91 | this.setState({ value: merged });
92 | } else {
93 | this.setState({ value });
94 | }
95 | ```
96 |
97 | 4. The form will then re-render and update to show the new values. However we need to handle the visibility state of the form. The visibility of the form is a function of the data in the form (at least in this case), meaning that if the form data is in a particular state, we only show certain fields. Specifically, in this case, when we set the "type" between to one of three possible values we show different fields that only apply to that "type". Therefore, in our `render()` function we get the "type" out of our form state and then set our visibility based on that:
98 |
99 | ```js
100 | render() {
101 |
102 | // Current type
103 | const currentType = values.get("type");
104 |
105 | // Find the visibility tag given our current type
106 | const visibilityTag = getVisibilityTag(currentType);
107 |
108 | ...
109 | }
110 | ```
111 |
112 | As mentioned above, we encode the tags within the `Schema`, so here we are simply mapping between the current type value and the tags in the schema.
113 |
114 | 5. Finally, to complete the dynamically updating form, we simply render
115 | the form but set the visibility prop to our `visibilityTag`.
116 |
117 | ```
118 | render() {
119 | ...
120 | return (
121 |
128 | );
129 | }
130 | ```
131 |
--------------------------------------------------------------------------------
/packages/react-dynamic-forms/src/components/TextArea.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015 - present, The Regents of the University of California,
3 | * through Lawrence Berkeley National Laboratory (subject to receipt
4 | * of any required approvals from the U.S. Dept. of Energy).
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree.
9 | */
10 |
11 | import React from "react";
12 | import _ from "underscore";
13 | import { validate } from "revalidator";
14 |
15 | import formGroup from "../js/formGroup";
16 |
17 | import "../css/textarea.css";
18 |
19 | /**
20 | * Form control to edit a Text Area field
21 | */
22 | class TextArea extends React.Component {
23 | constructor(props) {
24 | super(props);
25 | this.state = {
26 | touched: false
27 | };
28 | }
29 |
30 | isEmpty(value) {
31 | return _.isNull(value) || _.isUndefined(value) || value === "";
32 | }
33 |
34 | isMissing(v) {
35 | return this.props.required && !this.props.disabled && this.isEmpty(v);
36 | }
37 |
38 | getError(value) {
39 | let result = { validationError: false, validationErrorMessage: null };
40 |
41 | // If the user has a field blank then that is never an error
42 | // Likewise if this item is disabled it can't be called an error
43 | if (this.isEmpty(value) || this.props.disabled) {
44 | return result;
45 | }
46 |
47 | // Validate the value with Revalidator, given the rules in this.props.rules
48 | let obj = {};
49 | obj[this.props.name] = value;
50 |
51 | let properties = {};
52 | properties[this.props.name] = this.props.rules;
53 |
54 | const rules = this.props.rules ? { properties } : null;
55 | if (obj && rules) {
56 | const validation = validate(obj, rules, { cast: true });
57 | const name = this.props.name || "Value";
58 |
59 | let msg;
60 | if (!validation.valid) {
61 | msg = `${name} ${validation.errors[0].message}`;
62 | result.validationError = true;
63 | result.validationErrorMessage = msg;
64 | }
65 | }
66 | return result;
67 | }
68 |
69 | componentWillReceiveProps(nextProps) {
70 | if (this.props.value !== nextProps.value) {
71 | const missing = this.isMissing(nextProps.value);
72 | const { validationError } = this.getError(nextProps.value);
73 |
74 | // Broadcast error and missing states up to the owner
75 | if (this.props.onErrorCountChange) {
76 | this.props.onErrorCountChange(this.props.name, validationError ? 1 : 0);
77 | }
78 |
79 | if (this.props.onMissingCountChange) {
80 | this.props.onMissingCountChange(this.props.name, missing ? 1 : 0);
81 | }
82 | }
83 | }
84 |
85 | componentDidMount() {
86 | const missing = this.isMissing(this.props.value);
87 | const { validationError } = this.getError(this.props.value);
88 |
89 | // Initial error and missing states are fed up to the owner
90 | if (this.props.onErrorCountChange) {
91 | this.props.onErrorCountChange(this.props.name, validationError ? 1 : 0);
92 | }
93 |
94 | if (this.props.onMissingCountChange) {
95 | this.props.onMissingCountChange(this.props.name, missing ? 1 : 0);
96 | }
97 | }
98 |
99 | onBlur() {
100 | const { value } = this.textInput;
101 | const missing = this.props.required && this.isEmpty(value);
102 | const { validationError } = this.getError(value);
103 |
104 | // Callbacks
105 | if (this.props.onChange) {
106 | this.props.onChange(this.props.name, value);
107 | }
108 | if (this.props.onErrorCountChange) {
109 | this.props.onErrorCountChange(this.props.name, validationError ? 1 : 0);
110 | }
111 | if (this.props.onMissingCountChange) {
112 | this.props.onMissingCountChange(this.props.name, missing ? 1 : 0);
113 | }
114 |
115 | this.setState({ touched: true });
116 | }
117 |
118 | inlineStyle(hasError, isMissing) {
119 | let color = "";
120 | let background = "";
121 | if (hasError) {
122 | color = "#b94a48";
123 | background = "#fff0f3";
124 | } else if (isMissing) {
125 | background = "floralwhite";
126 | }
127 | return {
128 | color,
129 | background,
130 | height: "100%",
131 | width: "100%",
132 | paddingLeft: 3
133 | };
134 | }
135 |
136 | render() {
137 | // Control state
138 | const isMissing = this.isMissing(this.props.value);
139 | const { validationError, validationErrorMessage } = this.getError(this.props.value);
140 |
141 | if (this.props.edit) {
142 | // Error style/message
143 | let className = "";
144 | const msg = validationError ? validationErrorMessage : "";
145 | let helpClassName = "help-block";
146 | if (validationError && this.state.touched) {
147 | helpClassName += " has-error";
148 | className = "has-error";
149 | }
150 |
151 | // Warning style
152 | const style = isMissing ? { background: "floralwhite" } : {};
153 |
154 | return (
155 |