@nolwenture/formik-jsonschema-form 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -46
- package/dist/Form.js +4 -2
- package/dist/fields/ObjectField.js +9 -8
- package/dist/templates/ObjectFieldTemplate.js +20 -4
- package/dist/types.d.ts +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,46 +1,149 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
1
|
+
# formik-jsonschema-form
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
With npm:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
npm install @nolwenture/formik-jsonschema-form
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
With yarn:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
yarn add @nolwenture/formik-jsonschema-form
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Basic usage
|
|
20
|
+
|
|
21
|
+
Pass your schema to the `Form` component, which should be passed as a child to the `Formik` component, for example:
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { Form } from "@nolwenture/formik-jsonschema-form";
|
|
25
|
+
import { Formik } from "formik";
|
|
26
|
+
|
|
27
|
+
const schema = {
|
|
28
|
+
title: "My form",
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
firstName: { type: "string", title: "First name" },
|
|
32
|
+
lastName: { type: "string", title: "Last name" },
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const uiSchema = {
|
|
37
|
+
"ui:description": "Form description",
|
|
38
|
+
firstName: { "ui:description": "Field description" },
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export function MyFormComponent() {
|
|
42
|
+
return (
|
|
43
|
+
<Formik
|
|
44
|
+
initialValues={{ firstName: "", lastName: "" }}
|
|
45
|
+
onSubmit={handleSubmit}
|
|
46
|
+
>
|
|
47
|
+
<Form schema={schema} uiSchema={uiSchema}></Form>
|
|
48
|
+
</Formik>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Using custom components
|
|
54
|
+
|
|
55
|
+
Form components (such as wrappers) can be overriden with custom ones
|
|
56
|
+
|
|
57
|
+
Here is an example of overriding `FieldWrapper` (wrapper used on all fields):
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
function CustomFieldWrapper({ children }) {
|
|
61
|
+
return (
|
|
62
|
+
<div
|
|
63
|
+
style={{
|
|
64
|
+
backgroundColor: "lightgrey",
|
|
65
|
+
boxShadow: "1px 1px 5px gray",
|
|
66
|
+
margin: "10px",
|
|
67
|
+
padding: "10px",
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
{children}
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
...
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<Formik initialValues={initialValues} onSubmit={handleOnSubmit}>
|
|
79
|
+
<Form
|
|
80
|
+
schema={schema}
|
|
81
|
+
uiSchema={uiSchema}
|
|
82
|
+
components={{
|
|
83
|
+
FieldWrapper: CustomFieldWrapper,
|
|
84
|
+
}}
|
|
85
|
+
></Form>
|
|
86
|
+
</Formik>
|
|
87
|
+
);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Custom fields can be used in addition to all the default fields:
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { Form, FormRegistry } from "@nolwenture/formik-jsonschema-form";
|
|
94
|
+
import { useContext } from "react";
|
|
95
|
+
|
|
96
|
+
const schema = {
|
|
97
|
+
title: "My form",
|
|
98
|
+
type: "object",
|
|
99
|
+
properties: {
|
|
100
|
+
firstField: { title: "First field" },
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
function MyCustomFieldComponent(props) {
|
|
105
|
+
const {
|
|
106
|
+
templates: { FieldTemplate },
|
|
107
|
+
} = useContext(FormRegistry);
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<FieldTemplate {...props}>
|
|
111
|
+
<p>My awesome field!</p>
|
|
112
|
+
</FieldTemplate>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const fields = { myField: MyCustomFieldComponent };
|
|
117
|
+
|
|
118
|
+
// Specify the fields that should use your custom field component in uiSchema
|
|
119
|
+
const uiSchema = {
|
|
120
|
+
firstField = { "ui:field": "myField" },
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
...
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<Formik initialValues={initialValues} onSubmit={handleOnSubmit}>
|
|
127
|
+
<Form schema={schema} uiSchema={uiSchema} fields={fields}></Form>
|
|
128
|
+
</Formik>
|
|
129
|
+
);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Props
|
|
133
|
+
|
|
134
|
+
`Form` component props:
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
<Form
|
|
138
|
+
// Required
|
|
139
|
+
schema={schema} // Form schema
|
|
140
|
+
// Optional
|
|
141
|
+
uiSchema={uiSchema} // Form UI schema
|
|
142
|
+
className={"className"} // Form class name
|
|
143
|
+
fields={fields} // Additional custom field components
|
|
144
|
+
templates={templates} // Additional custom field templates
|
|
145
|
+
components={components} // Override form components (e.g. wrappers) with custom ones
|
|
146
|
+
formContext={formContext} // Form context
|
|
147
|
+
useItemsAsAdditionalItems={true} // Allow "items" to be used as "additionalItems" in array fields that are missing "additionalItems", false by default
|
|
148
|
+
/>
|
|
149
|
+
```
|
package/dist/Form.js
CHANGED
|
@@ -23,6 +23,7 @@ export var FormRegistry = React.createContext({
|
|
|
23
23
|
definitions: {},
|
|
24
24
|
formContext: {},
|
|
25
25
|
useItemsAsAdditionalItems: false,
|
|
26
|
+
hideUnmarkedAdditionalProperties: false,
|
|
26
27
|
});
|
|
27
28
|
export function Form(props) {
|
|
28
29
|
warnFromUnsupportedKeys("Form", props, [
|
|
@@ -37,7 +38,7 @@ export function Form(props) {
|
|
|
37
38
|
"formContext",
|
|
38
39
|
]);
|
|
39
40
|
var isSubmitting = useFormikContext().isSubmitting;
|
|
40
|
-
var schema = props.schema, _a = props.uiSchema, uiSchema = _a === void 0 ? {} : _a, className = props.className, children = props.children, _b = props.fields, fields = _b === void 0 ? {} : _b, _c = props.templates, templates = _c === void 0 ? {} : _c, _d = props.components, components = _d === void 0 ? {} : _d, _e = props.formContext, formContext = _e === void 0 ? {} : _e, _f = props.useItemsAsAdditionalItems, useItemsAsAdditionalItems = _f === void 0 ? false : _f;
|
|
41
|
+
var schema = props.schema, _a = props.uiSchema, uiSchema = _a === void 0 ? {} : _a, className = props.className, children = props.children, _b = props.fields, fields = _b === void 0 ? {} : _b, _c = props.templates, templates = _c === void 0 ? {} : _c, _d = props.components, components = _d === void 0 ? {} : _d, _e = props.formContext, formContext = _e === void 0 ? {} : _e, _f = props.useItemsAsAdditionalItems, useItemsAsAdditionalItems = _f === void 0 ? false : _f, _g = props.hideUnmarkedAdditionalProperties, hideUnmarkedAdditionalProperties = _g === void 0 ? false : _g;
|
|
41
42
|
var registry = {
|
|
42
43
|
fields: __assign(__assign({}, defaultFields), fields),
|
|
43
44
|
templates: __assign(__assign({}, defaultTemplates), templates),
|
|
@@ -45,8 +46,9 @@ export function Form(props) {
|
|
|
45
46
|
definitions: {},
|
|
46
47
|
formContext: formContext,
|
|
47
48
|
useItemsAsAdditionalItems: useItemsAsAdditionalItems,
|
|
49
|
+
hideUnmarkedAdditionalProperties: hideUnmarkedAdditionalProperties,
|
|
48
50
|
};
|
|
49
|
-
var
|
|
51
|
+
var _h = registry.components, FormEl = _h.Form, FormButton = _h.FormButton, FormButtonWrapper = _h.FormButtonWrapper;
|
|
50
52
|
var _SchemaField = registry.fields.SchemaField;
|
|
51
53
|
return (_jsx(FormRegistry.Provider, __assign({ value: registry }, { children: _jsxs(FormEl, __assign({ className: className }, { children: [_jsx(_SchemaField, { name: "", schema: schema, uiSchema: uiSchema }), children ? (children) : (_jsx(FormButtonWrapper, { children: _jsx(FormButton, __assign({ type: "submit", disabled: isSubmitting }, { children: "Send" })) }))] })) })));
|
|
52
54
|
}
|
|
@@ -26,7 +26,7 @@ import { useContext, useMemo } from "react";
|
|
|
26
26
|
import { FormRegistry } from "../Form";
|
|
27
27
|
import { ObjectFieldButtonPurpose } from "../types";
|
|
28
28
|
export function ObjectField(props) {
|
|
29
|
-
var _a = useContext(FormRegistry), SchemaField = _a.fields.SchemaField, ObjectFieldTemplate = _a.templates.ObjectFieldTemplate, _b = _a.components, ObjectFieldItem = _b.ObjectFieldItem, ObjectFieldList = _b.ObjectFieldList, ObjectFieldItemButtons = _b.ObjectFieldItemButtons, ObjectFieldButton = _b.ObjectFieldButton;
|
|
29
|
+
var _a = useContext(FormRegistry), SchemaField = _a.fields.SchemaField, ObjectFieldTemplate = _a.templates.ObjectFieldTemplate, _b = _a.components, ObjectFieldItem = _b.ObjectFieldItem, ObjectFieldList = _b.ObjectFieldList, ObjectFieldItemButtons = _b.ObjectFieldItemButtons, ObjectFieldButton = _b.ObjectFieldButton, hideUnmarkedAdditionalProperties = _a.hideUnmarkedAdditionalProperties;
|
|
30
30
|
var name = props.name, schema = props.schema, uiSchema = props.uiSchema;
|
|
31
31
|
var _c = useField(name), value = _c[0].value, _ = _c[1], setValue = _c[2].setValue;
|
|
32
32
|
var properties = schema.properties, additionalProperties = schema.additionalProperties;
|
|
@@ -40,13 +40,14 @@ export function ObjectField(props) {
|
|
|
40
40
|
return (_jsxs(ObjectFieldTemplate, __assign({}, props, { children: [Object.entries(properties || {}).map(function (_a) {
|
|
41
41
|
var childName = _a[0], childSchema = _a[1];
|
|
42
42
|
return (_jsx(SchemaField, { name: name ? [name, childName].join(".") : childName, schema: typeof childSchema !== "boolean" ? childSchema : {}, uiSchema: uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema[childName] }, childName));
|
|
43
|
-
}),
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
}), (!hideUnmarkedAdditionalProperties || additionalProperties) &&
|
|
44
|
+
Object.entries(additionalValues || {}).map(function (_a) {
|
|
45
|
+
var childName = _a[0], childSchema = _a[1];
|
|
46
|
+
return (_jsxs(ObjectFieldItem, { children: [_jsx(SchemaField, { name: name ? [name, childName].join(".") : childName, schema: typeof childSchema !== "boolean" ? childSchema : {}, uiSchema: uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema[childName] }), _jsx(ObjectFieldItemButtons, { children: _jsx(ObjectFieldButton, { purpose: ObjectFieldButtonPurpose.REMOVE, onClick: function () {
|
|
47
|
+
var _a = value, _b = childName, _removedProperty = _a[_b], newValue = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
|
|
48
|
+
setValue(newValue);
|
|
49
|
+
} }) })] }, childName));
|
|
50
|
+
}), additionalProperties && (_jsx(ObjectFieldButton, { purpose: ObjectFieldButtonPurpose.ADD, onClick: function () {
|
|
50
51
|
var _a;
|
|
51
52
|
var key = prompt("Give key");
|
|
52
53
|
if (key) {
|
|
@@ -1,11 +1,27 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
1
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
13
|
import { useContext } from "react";
|
|
3
14
|
import { FormRegistry } from "../Form";
|
|
4
|
-
import { getDescription, getTitle } from "../utils";
|
|
15
|
+
import { getDescription, getTitle, useExtractUiSchema } from "../utils";
|
|
5
16
|
export function ObjectFieldTemplate(props) {
|
|
6
|
-
var _a = useContext(FormRegistry).components, FieldDescription = _a.FieldDescription, ObjectFieldTitle = _a.ObjectFieldTitle, ObjectFieldWrapper = _a.ObjectFieldWrapper;
|
|
7
|
-
var children = props.children;
|
|
17
|
+
var _a = useContext(FormRegistry).components, FieldDescription = _a.FieldDescription, ObjectFieldTitle = _a.ObjectFieldTitle, ObjectFieldWrapper = _a.ObjectFieldWrapper, FieldHelp = _a.FieldHelp;
|
|
18
|
+
var children = props.children, uiSchema = props.uiSchema;
|
|
8
19
|
var title = getTitle(props);
|
|
9
20
|
var description = getDescription(props);
|
|
10
|
-
|
|
21
|
+
var _b = useExtractUiSchema(uiSchema), help = _b.help,
|
|
22
|
+
//TODO: This is not right
|
|
23
|
+
_c = _b.props,
|
|
24
|
+
//TODO: This is not right
|
|
25
|
+
_d = _c === void 0 ? {} : _c, wrapperProps = _d.wrapper, titleProps = _d.title, descriptionProps = _d.description, helpProps = _d.help;
|
|
26
|
+
return (_jsxs(ObjectFieldWrapper, __assign({}, wrapperProps, { children: [title && _jsx(ObjectFieldTitle, __assign({}, titleProps, { children: title })), description && _jsx(FieldDescription, __assign({}, descriptionProps, { children: description })), children, help && _jsx(FieldHelp, __assign({}, helpProps, { children: help }))] })));
|
|
11
27
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export type FormProps<T> = React.PropsWithChildren<{
|
|
|
5
5
|
disabled?: boolean | undefined;
|
|
6
6
|
/** If true, array field schemas missing 'additionalItems' will replace it with 'items' */
|
|
7
7
|
useItemsAsAdditionalItems?: boolean | undefined;
|
|
8
|
+
/** If true, properties in object fields' data that aren't in the schema will only be displayed if `additionalProperties` is enabled in the schema */
|
|
9
|
+
hideUnmarkedAdditionalProperties?: boolean;
|
|
8
10
|
className?: string | undefined;
|
|
9
11
|
/** Form schema */
|
|
10
12
|
schema: Schema;
|
|
@@ -43,6 +45,7 @@ export type FormRegistryContextValue = {
|
|
|
43
45
|
definitions: Record<string, any>;
|
|
44
46
|
formContext: Record<string, any>;
|
|
45
47
|
useItemsAsAdditionalItems: boolean;
|
|
48
|
+
hideUnmarkedAdditionalProperties: boolean;
|
|
46
49
|
};
|
|
47
50
|
export interface FieldProps extends Pick<React.HTMLAttributes<HTMLElement>, Exclude<keyof React.HTMLAttributes<HTMLElement>, "onBlur">> {
|
|
48
51
|
name: string;
|