@nolwenture/formik-jsonschema-form 0.1.3 → 0.3.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 CHANGED
@@ -1,46 +1,268 @@
1
- # Getting Started with Create React App
1
+ # formik-jsonschema-form
2
2
 
3
- This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
3
+ ## Installation
4
4
 
5
- ## Available Scripts
5
+ With npm:
6
6
 
7
- In the project directory, you can run:
7
+ ```text
8
+ npm install @nolwenture/formik-jsonschema-form
9
+ ```
8
10
 
9
- ### `npm start`
11
+ With yarn:
10
12
 
11
- Runs the app in the development mode.\
12
- Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13
+ ```text
14
+ yarn add @nolwenture/formik-jsonschema-form
15
+ ```
13
16
 
14
- The page will reload if you make edits.\
15
- You will also see any lint errors in the console.
17
+ ## Usage
16
18
 
17
- ### `npm test`
19
+ ### Basic usage
18
20
 
19
- Launches the test runner in the interactive watch mode.\
20
- See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21
+ Pass your schema to the `Form` component, which should be passed as a child to the `Formik` component, for example:
21
22
 
22
- ### `npm run build`
23
+ ```tsx
24
+ import { Form } from "@nolwenture/formik-jsonschema-form";
25
+ import { Formik } from "formik";
23
26
 
24
- Builds the app for production to the `build` folder.\
25
- It correctly bundles React in production mode and optimizes the build for the best performance.
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
+ };
26
35
 
27
- The build is minified and the filenames include the hashes.\
28
- Your app is ready to be deployed!
36
+ const uiSchema = {
37
+ "ui:description": "Form description",
38
+ firstName: { "ui:description": "Field description" },
39
+ };
29
40
 
30
- See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
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
+ ```
31
52
 
32
- ### `npm run eject`
53
+ ### Using custom components
33
54
 
34
- **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
55
+ Form components (such as wrappers) can be overriden with custom ones
35
56
 
36
- If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
57
+ Here is an example of overriding `FieldWrapper` (wrapper used on all fields):
37
58
 
38
- Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
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
+ }
39
74
 
40
- You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
75
+ ...
41
76
 
42
- ## Learn More
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
+ ```
43
89
 
44
- You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
90
+ Custom fields can be used in addition to all the default fields:
45
91
 
46
- To learn React, check out the [React documentation](https://reactjs.org/).
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
+ The style for buttons to add and remove (and move) array or object items can be overridden within the uiSchema by giving inline style.
133
+
134
+ The buttons that can be customized that way are:
135
+
136
+ - "ui:addButtonOptions"
137
+ - "ui:removeButtonOptions"
138
+ - "ui:upButtonOptions"
139
+ - "ui:downButtonOptions"
140
+ - "ui:customButtonOptions"
141
+
142
+ `content` takes a ReactNode as input.
143
+
144
+ ```tsx
145
+
146
+ const schema = {
147
+ title: "Form with customized buttons",
148
+ type: "object",
149
+ properties: {
150
+ someArray: {
151
+ type: "array",
152
+ title: "Some array",
153
+ description: "Array with customized buttons",
154
+ additionalItems: {
155
+ type: "string",
156
+ },
157
+ },
158
+ }
159
+ }
160
+
161
+ const uiSchema = {
162
+ "ui:description": "Form description",
163
+ // make a green ADD button for someArray that reads "Hello!"
164
+ someArray: {
165
+ "ui:addButtonOptions": {
166
+ content: <b>Hello!</b>,
167
+ props: { style: { background: "green" } },
168
+ },
169
+ };
170
+
171
+ ...
172
+
173
+ return (
174
+ <Formik initialValues={initialValues} onSubmit={handleOnSubmit}>
175
+ <Form
176
+ schema={schema}
177
+ uiSchema={uiSchema}
178
+ ></Form>
179
+ </Formik>
180
+ );
181
+ ```
182
+
183
+ ### Required input
184
+
185
+ Required input can be displayed with an asterisk next to the title.
186
+ The respective fieldname needs to be given inside the required-array of the object holding the field in question in the schema.
187
+ In the example, required fields are 'lastName', 'favouriteFood' inside the arrayOfObject, and 'tasks' in nestedObject.
188
+
189
+ The styling of the asterisk can be customised by applying style to styledComponents.RequiredIndicator.
190
+
191
+ ```tsx
192
+ import { Form } from "@nolwenture/formik-jsonschema-form";
193
+ import { Formik } from "formik";
194
+
195
+ const CustomizedRequiredIndicator = styled(styledComponents.RequiredIndicator)`
196
+ color: aqua;
197
+ `;
198
+
199
+ const schema = {
200
+ title: "My Form",
201
+ required: ["lastName"],
202
+ properties: {
203
+ firstName: { type: "string", title: "First name" },
204
+ lastName: { type: "string", title: "Last name" },
205
+ arrayOfObject: {
206
+ type: "array",
207
+ title: "Array of objects",
208
+ items: {
209
+ type: "object",
210
+ title: "Favourites",
211
+ required: ["favouriteFood"],
212
+ properties: {
213
+ favouriteFood: { type: "string", title: "Favourite food" },
214
+ favouriteSong: { type: "string", title: "Favourite song" },
215
+ },
216
+ },
217
+ },
218
+ nestedObject: {
219
+ type: "object",
220
+ title: "Nested Object",
221
+ required: ["tasks"],
222
+ properties: {
223
+ hobbies: { type: "string", title: "Hobbies" },
224
+ tasks: { type: "string", title: "Tasks" },
225
+ },
226
+ },
227
+ },
228
+ };
229
+
230
+ const uiSchema = {
231
+ "ui:description": "Form description",
232
+ firstName: { "ui:description": "Field description" },
233
+ };
234
+
235
+ export function MyFormComponent() {
236
+ return (
237
+ <Formik
238
+ initialValues={{ firstName: "", lastName: "" }}
239
+ onSubmit={handleSubmit}
240
+ >
241
+ <Form
242
+ schema={schema}
243
+ uiSchema={uiSchema}
244
+ components={{ RequiredIndicator: CustomizedRequiredIndicator }}
245
+ ></Form>
246
+ </Formik>
247
+ );
248
+ }
249
+ ```
250
+
251
+ ## Props
252
+
253
+ `Form` component props:
254
+
255
+ ```tsx
256
+ <Form
257
+ // Required
258
+ schema={schema} // Form schema
259
+ // Optional
260
+ uiSchema={uiSchema} // Form UI schema
261
+ className={"className"} // Form class name
262
+ fields={fields} // Additional custom field components
263
+ templates={templates} // Additional custom field templates
264
+ components={components} // Override form components (e.g. wrappers) with custom ones
265
+ formContext={formContext} // Form context
266
+ useItemsAsAdditionalItems={true} // Allow "items" to be used as "additionalItems" in array fields that are missing "additionalItems", false by default
267
+ />
268
+ ```
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 _g = registry.components, FormEl = _g.Form, FormButton = _g.FormButton, FormButtonWrapper = _g.FormButtonWrapper;
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
  }
@@ -9,3 +9,4 @@ export declare const CompleteSchema: ComponentStory<typeof Form>;
9
9
  export declare const StrictlyTyped: () => JSX.Element;
10
10
  export declare const StylesCustomized: () => JSX.Element;
11
11
  export declare const WithGeneratedSchema: ComponentStory<typeof Form>;
12
+ export declare const WithRequiredInput: ComponentStory<typeof Form>;
@@ -53,7 +53,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
53
53
  import { action } from "@storybook/addon-actions";
54
54
  import styled from "styled-components";
55
55
  import { Formik, useFormikContext } from "formik";
56
- import { completeSchema, completeUiSchema, simpleSchema, simpleUiSchema, generatedSchema, } from "./_sampleData";
56
+ import { completeSchema, completeUiSchema, simpleSchema, simpleUiSchema, generatedSchema, requiredInputSchema, } from "./_sampleData";
57
57
  import { Form, styledComponents } from "./";
58
58
  export default {
59
59
  title: "Form",
@@ -105,6 +105,7 @@ var CustomizedErrorMessage = function (props) {
105
105
  var error = errors[name];
106
106
  return error ? _jsx("p", { children: error }) : _jsx("p", { children: "Hurray! No errors" });
107
107
  };
108
+ var CustomizedRequiredIndicator = styled(styledComponents.RequiredIndicator)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n color: aqua;\n"], ["\n color: aqua;\n"])));
108
109
  export var StylesCustomized = function () {
109
110
  return (_jsx(Formik, __assign({ initialValues: {}, onSubmit: function (values, formikHelpers) { return __awaiter(void 0, void 0, void 0, function () {
110
111
  return __generator(this, function (_a) {
@@ -124,6 +125,7 @@ export var StylesCustomized = function () {
124
125
  }, components: {
125
126
  FieldWrapper: CustomizedFieldWrapper,
126
127
  ErrorMessage: CustomizedErrorMessage,
128
+ RequiredIndicator: CustomizedRequiredIndicator,
127
129
  } }) })));
128
130
  };
129
131
  export var WithGeneratedSchema = Template.bind({});
@@ -132,4 +134,9 @@ WithGeneratedSchema.args = {
132
134
  uiSchema: {},
133
135
  useItemsAsAdditionalItems: true,
134
136
  };
135
- var templateObject_1, templateObject_2;
137
+ export var WithRequiredInput = Template.bind({});
138
+ WithRequiredInput.args = {
139
+ schema: requiredInputSchema,
140
+ uiSchema: {},
141
+ };
142
+ var templateObject_1, templateObject_2, templateObject_3;
@@ -8,3 +8,4 @@ export declare const simpleUiSchema: UiSchema;
8
8
  export declare const completeSchema: Schema;
9
9
  export declare const completeUiSchema: UiSchema;
10
10
  export declare const generatedSchema: Schema;
11
+ export declare const requiredInputSchema: Schema;
@@ -1,3 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  export var simpleSchema = {
2
3
  title: "TITLE",
3
4
  properties: {
@@ -178,6 +179,7 @@ export var completeSchema = {
178
179
  },
179
180
  },
180
181
  },
182
+ default: [{ string: "Hello" }],
181
183
  },
182
184
  },
183
185
  };
@@ -207,6 +209,7 @@ export var completeUiSchema = {
207
209
  enum: {
208
210
  "ui:help": "Enum help",
209
211
  },
212
+ enumOneOf: { placeholder: "Select one" },
210
213
  null: {
211
214
  "ui:help": "Null help",
212
215
  },
@@ -239,6 +242,34 @@ export var completeUiSchema = {
239
242
  null: {
240
243
  "ui:help": "Null help",
241
244
  },
245
+ "ui:addButtonOptions": {
246
+ content: _jsx("b", { children: "Hello in an Object!" }),
247
+ props: { style: { background: "pink" } },
248
+ },
249
+ },
250
+ partiallyFixedArray: {
251
+ "ui:addButtonOptions": {
252
+ content: _jsx("b", { children: "Hello!" }),
253
+ props: { style: { background: "green" } },
254
+ },
255
+ "ui:removeButtonOptions": {
256
+ content: _jsx("span", { children: "-" }),
257
+ props: {
258
+ style: {
259
+ height: "25px",
260
+ width: "25px",
261
+ background: "red",
262
+ borderRadius: "50%",
263
+ display: "inline-block",
264
+ border: "unset",
265
+ padding: "unset",
266
+ color: "white",
267
+ fontWeight: "bolder",
268
+ textAlign: "center",
269
+ lineHeight: "1.4em",
270
+ },
271
+ },
272
+ },
242
273
  },
243
274
  };
244
275
  export var generatedSchema = {
@@ -260,3 +291,42 @@ export var generatedSchema = {
260
291
  required: ["object", "value", "property"],
261
292
  additionalProperties: false,
262
293
  };
294
+ export var requiredInputSchema = {
295
+ title: "TITLE",
296
+ required: ['lastName'],
297
+ properties: {
298
+ firstName: { type: "string", title: "First name" },
299
+ lastName: { type: "string", title: "Last name" },
300
+ arrayOfObject: {
301
+ type: "array",
302
+ title: "Array of objects",
303
+ items: {
304
+ type: "object",
305
+ title: "Favourites",
306
+ required: ['favouriteFood'],
307
+ properties: {
308
+ favouriteFood: { type: "string", title: "Favourite food" },
309
+ favouriteSong: { type: "string", title: "Favourite song" }
310
+ }
311
+ },
312
+ additionalItems: {
313
+ type: "object",
314
+ title: "Second favourites",
315
+ required: ['secondFavouriteSong'],
316
+ properties: {
317
+ secondFavouriteFood: { type: "string", title: "Second favourite food" },
318
+ secondFavouriteSong: { type: "string", title: "Second favourite song" }
319
+ }
320
+ }
321
+ },
322
+ nestedObject: {
323
+ type: "object",
324
+ title: "Nested Object",
325
+ required: ["tasks"],
326
+ properties: {
327
+ hobbies: { type: "string", title: "Hobbies" },
328
+ tasks: { type: "string", title: "Tasks" }
329
+ }
330
+ }
331
+ },
332
+ };
@@ -23,7 +23,8 @@ import { useContext, useMemo } from "react";
23
23
  import { FormRegistry } from "../Form";
24
24
  import { useField } from "formik";
25
25
  import { ArrayFieldButtonPurpose } from "../types";
26
- import { useExtractUiSchema } from "../utils";
26
+ import { useExtractUiSchema, useSetDefault } from "../utils";
27
+ import { GetArrayFieldButton } from "../styledComponents";
27
28
  function appendArray(values) {
28
29
  return values ? __spreadArray(__spreadArray([], values, true), [""], false) : [""];
29
30
  }
@@ -45,7 +46,8 @@ function moveInArray(values, index, direction) {
45
46
  }
46
47
  }
47
48
  export function ArrayField(props) {
48
- var _a = useContext(FormRegistry), SchemaField = _a.fields.SchemaField, ArrayFieldTemplate = _a.templates.ArrayFieldTemplate, _b = _a.components, ArrayFieldItem = _b.ArrayFieldItem, ArrayFieldList = _b.ArrayFieldList, ArrayFieldItemButtons = _b.ArrayFieldItemButtons, ArrayFieldButton = _b.ArrayFieldButton, useItemsAsAdditionalItems = _a.useItemsAsAdditionalItems;
49
+ var _a = useContext(FormRegistry), SchemaField = _a.fields.SchemaField, ArrayFieldTemplate = _a.templates.ArrayFieldTemplate, _b = _a.components, ArrayFieldItem = _b.ArrayFieldItem, ArrayFieldList = _b.ArrayFieldList, ArrayFieldItemButtons = _b.ArrayFieldItemButtons, useItemsAsAdditionalItems = _a.useItemsAsAdditionalItems;
50
+ useSetDefault(props);
49
51
  var name = props.name, schema = props.schema, uiSchema = props.uiSchema;
50
52
  var _c = useField(name), value = _c[0].value, _ = _c[1], setValue = _c[2].setValue;
51
53
  var _d = useMemo(function () {
@@ -106,14 +108,35 @@ export function ArrayField(props) {
106
108
  // [schema]
107
109
  // );
108
110
  // Bacwards compatibility ends
109
- var _e = useExtractUiSchema(uiSchema), inputProps = _e.props, disabled = _e.disabled;
110
- return (_jsxs(ArrayFieldTemplate, __assign({}, props, { children: [_jsxs(ArrayFieldList, { children: [(items || []).map(function (itemSchema, index) { return (_jsx(ArrayFieldItem, { children: _jsx(SchemaField, { name: "".concat(name, "[").concat(index, "]"), schema: typeof itemSchema !== "boolean" ? itemSchema : {}, uiSchema: (uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema[index]) || (uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema.items) }, index) })); }), ((value === null || value === void 0 ? void 0 : value.slice(items.length)) || []).map(function (_, index) { return (_jsxs(ArrayFieldItem, { children: [_jsx(SchemaField, __assign({}, __assign({ disabled: disabled }, inputProps), { name: "".concat(name, "[").concat(index + items.length, "]"), schema: additionalItems && typeof additionalItems !== "boolean"
111
+ var disabled = useExtractUiSchema(uiSchema).disabled;
112
+ return (_jsxs(ArrayFieldTemplate, __assign({}, props, { children: [_jsxs(ArrayFieldList, { children: [(items || []).map(function (itemSchema, index) { return (_jsx(ArrayFieldItem, { children: _jsx(SchemaField, { name: "".concat(name, "[").concat(index, "]"), schema: typeof itemSchema !== "boolean" ? itemSchema : {}, uiSchema: (uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema[index]) || (uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema.items), forceDefaultValue: true }) }, index)); }), ((value === null || value === void 0 ? void 0 : value.slice(items.length)) || []).map(function (_, index) { return (_jsxs(ArrayFieldItem, { children: [_jsx(SchemaField, { name: "".concat(name, "[").concat(index + items.length, "]"), schema: additionalItems && typeof additionalItems !== "boolean"
111
113
  ? additionalItems
112
- : {}, uiSchema: __assign({ disabled: disabled }, ((uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema[index + items.length]) || (uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema.items))) }), index), _jsxs(ArrayFieldItemButtons, { children: [_jsx(ArrayFieldButton, { purpose: ArrayFieldButtonPurpose.REMOVE, onClick: function () {
114
+ : {}, uiSchema: __assign({ disabled: disabled }, ((uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema[index + items.length]) || (uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema.items))) }), _jsxs(ArrayFieldItemButtons, { children: [GetArrayFieldButton({
115
+ purpose: ArrayFieldButtonPurpose.REMOVE,
116
+ onClick: function () {
113
117
  return setValue(removeFromArray(value, index + items.length));
114
- } }), value.length > 1 && index > 0 && (_jsx(ArrayFieldButton, { purpose: ArrayFieldButtonPurpose.MOVE_UP, onClick: function () {
115
- return setValue(moveInArray(value, index + items.length, -1));
116
- } })), value.length > 1 && index < value.length - 1 && (_jsx(ArrayFieldButton, { purpose: ArrayFieldButtonPurpose.MOVE_DOWN, onClick: function () {
117
- return setValue(moveInArray(value, index + items.length, 1));
118
- } }))] })] })); })] }), additionalItems && (_jsx(ArrayFieldButton, { purpose: ArrayFieldButtonPurpose.ADD, onClick: function () { return setValue(appendArray(value)); } }))] })));
118
+ },
119
+ uiSchema: uiSchema,
120
+ }), value.length > 1 &&
121
+ index > 0 &&
122
+ GetArrayFieldButton({
123
+ purpose: ArrayFieldButtonPurpose.MOVE_UP,
124
+ onClick: function () {
125
+ return setValue(moveInArray(value, index + items.length, -1));
126
+ },
127
+ uiSchema: uiSchema,
128
+ }), value.length > 1 &&
129
+ index < value.length - 1 &&
130
+ GetArrayFieldButton({
131
+ purpose: ArrayFieldButtonPurpose.MOVE_DOWN,
132
+ onClick: function () {
133
+ return setValue(moveInArray(value, index + items.length, 1));
134
+ },
135
+ uiSchema: uiSchema,
136
+ })] })] }, index)); })] }), additionalItems &&
137
+ GetArrayFieldButton({
138
+ purpose: ArrayFieldButtonPurpose.ADD,
139
+ onClick: function () { return setValue(appendArray(value)); },
140
+ uiSchema: uiSchema,
141
+ })] })));
119
142
  }
@@ -25,11 +25,14 @@ import { useField } from "formik";
25
25
  import { useContext, useMemo } from "react";
26
26
  import { FormRegistry } from "../Form";
27
27
  import { ObjectFieldButtonPurpose } from "../types";
28
+ import { useSetDefault } from "../utils";
29
+ import { getObjectFieldButton } from "../styledComponents";
28
30
  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;
31
+ var _a = useContext(FormRegistry), SchemaField = _a.fields.SchemaField, ObjectFieldTemplate = _a.templates.ObjectFieldTemplate, _b = _a.components, ObjectFieldItem = _b.ObjectFieldItem, ObjectFieldItemButtons = _b.ObjectFieldItemButtons, hideUnmarkedAdditionalProperties = _a.hideUnmarkedAdditionalProperties;
32
+ useSetDefault(props);
30
33
  var name = props.name, schema = props.schema, uiSchema = props.uiSchema;
31
34
  var _c = useField(name), value = _c[0].value, _ = _c[1], setValue = _c[2].setValue;
32
- var properties = schema.properties, additionalProperties = schema.additionalProperties;
35
+ var properties = schema.properties, additionalProperties = schema.additionalProperties, required = schema.required;
33
36
  var propertyKeys = useMemo(function () { return Object.keys(properties || {}); }, [properties]);
34
37
  var additionalValues = useMemo(function () {
35
38
  return Object.fromEntries(Object.entries(value || {}).filter(function (_a) {
@@ -39,18 +42,28 @@ export function ObjectField(props) {
39
42
  }, [value, propertyKeys]);
40
43
  return (_jsxs(ObjectFieldTemplate, __assign({}, props, { children: [Object.entries(properties || {}).map(function (_a) {
41
44
  var childName = _a[0], childSchema = _a[1];
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
- }), Object.entries(additionalValues || {}).map(function (_a) {
44
- var childName = _a[0], childSchema = _a[1];
45
- 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] }, childName), _jsx(ObjectFieldItemButtons, { children: _jsx(ObjectFieldButton, { purpose: ObjectFieldButtonPurpose.REMOVE, onClick: function () {
46
- var _a = value, _b = childName, _removedProperty = _a[_b], newValue = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
47
- setValue(newValue);
48
- } }) })] }));
49
- }), additionalProperties && (_jsx(ObjectFieldButton, { purpose: ObjectFieldButtonPurpose.ADD, onClick: function () {
50
- var _a;
51
- var key = prompt("Give key");
52
- if (key) {
53
- setValue(__assign(__assign({}, value), (_a = {}, _a[key] = undefined, _a)));
54
- }
55
- } }))] })));
45
+ return (_jsx(SchemaField, { required: required === null || required === void 0 ? void 0 : required.includes(childName), name: name ? [name, childName].join(".") : childName, schema: typeof childSchema !== "boolean" ? childSchema : {}, uiSchema: uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema[childName] }, childName));
46
+ }), (!hideUnmarkedAdditionalProperties || additionalProperties) &&
47
+ Object.entries(additionalValues || {}).map(function (_a) {
48
+ var childName = _a[0], childSchema = _a[1];
49
+ return (_jsxs(ObjectFieldItem, { children: [_jsx(SchemaField, { required: required === null || required === void 0 ? void 0 : required.includes(childName), name: name ? [name, childName].join(".") : childName, schema: typeof childSchema !== "boolean" ? childSchema : {}, uiSchema: uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema[childName] }, childName), _jsx(ObjectFieldItemButtons, { children: getObjectFieldButton({
50
+ purpose: ObjectFieldButtonPurpose.REMOVE,
51
+ onClick: function () {
52
+ var _a = value, _b = childName, _removedProperty = _a[_b], newValue = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
53
+ setValue(newValue);
54
+ },
55
+ uiSchema: uiSchema,
56
+ }) })] }, childName));
57
+ }), additionalProperties &&
58
+ getObjectFieldButton({
59
+ purpose: ObjectFieldButtonPurpose.ADD,
60
+ onClick: function () {
61
+ var _a;
62
+ var key = prompt("Give key");
63
+ if (key) {
64
+ setValue(__assign(__assign({}, value), (_a = {}, _a[key] = undefined, _a)));
65
+ }
66
+ },
67
+ uiSchema: uiSchema,
68
+ })] })));
56
69
  }
@@ -14,7 +14,7 @@ import { useContext } from "react";
14
14
  import { useExtractUiSchema, getSchemaType } from "../utils";
15
15
  import { FormRegistry } from "../Form";
16
16
  import { COMPONENT_TYPES } from "./types";
17
- function getFieldComponent(schema, uiSchema, fields) {
17
+ function useFieldComponent(schema, uiSchema, fields) {
18
18
  var field = useExtractUiSchema(uiSchema).field;
19
19
  if (typeof field === "function") {
20
20
  return field;
@@ -34,6 +34,6 @@ function getFieldComponent(schema, uiSchema, fields) {
34
34
  export function SchemaField(props) {
35
35
  var schema = props.schema, uiSchema = props.uiSchema;
36
36
  var fields = useContext(FormRegistry).fields;
37
- var FieldComponent = getFieldComponent(schema, uiSchema, fields);
37
+ var FieldComponent = useFieldComponent(schema, uiSchema, fields);
38
38
  return _jsx(FieldComponent, __assign({}, props));
39
39
  }
@@ -53,7 +53,7 @@ export function StringField(props) {
53
53
  switch (enums === null || enums === void 0 ? void 0 : enums.type) {
54
54
  case "select":
55
55
  case "multiSelect":
56
- return (_jsx(FieldTemplate, __assign({}, props, { children: _jsxs(FieldInput, __assign({}, __assign({ type: type, placeholder: placeholder }, inputProps), { name: name, formikAs: "select", multiple: enums.type === "multiSelect" }, { children: [enums.type !== "multiSelect" && _jsx("option", { value: "" }), enums === null || enums === void 0 ? void 0 : enums.values.map(function (option, index) { return (_jsx("option", __assign({ value: option.const }, { children: option.title }), index)); })] })) })));
56
+ return (_jsx(FieldTemplate, __assign({}, props, { children: _jsxs(FieldInput, __assign({}, __assign({ type: type, placeholder: placeholder }, inputProps), { name: name, formikAs: "select", multiple: enums.type === "multiSelect" }, { children: [enums.type !== "multiSelect" && (_jsx("option", __assign({ value: "", disabled: true, selected: true, hidden: true }, { children: placeholder }))), enums === null || enums === void 0 ? void 0 : enums.values.map(function (option, index) { return (_jsx("option", __assign({ value: option.const }, { children: option.title }), index)); })] })) })));
57
57
  default:
58
58
  return (_jsx(FieldTemplate, __assign({}, props, { children: _jsx(FieldInput, __assign({}, __assign({ type: type, placeholder: placeholder }, inputProps), { name: name })) })));
59
59
  }
@@ -9,18 +9,29 @@ export declare const ObjectFieldTitle: import("styled-components").StyledCompone
9
9
  export declare const ObjectFieldList: import("styled-components").StyledComponent<"ul", any, {}, never>;
10
10
  export declare const ObjectFieldItem: import("styled-components").StyledComponent<"li", any, {}, never>;
11
11
  export declare const ObjectFieldItemButtons: import("styled-components").StyledComponent<"div", any, {}, never>;
12
- export declare const ObjectFieldButtonEl: import("styled-components").StyledComponent<"a", any, {}, never>;
13
- export declare function ObjectFieldButton({ purpose, onClick, }: ObjectFieldButtonProps): JSX.Element;
12
+ export declare const ObjectFieldButton: import("styled-components").StyledComponent<"a", any, {}, never>;
13
+ export declare const ObjectFieldLineButton: import("styled-components").StyledComponent<"a", any, {}, never>;
14
+ export declare const ObjectFieldUpButton: import("styled-components").StyledComponent<"a", any, {}, never>;
15
+ export declare const ObjectFieldDownButton: import("styled-components").StyledComponent<"a", any, {}, never>;
16
+ export declare const ObjectFieldRemoveButton: import("styled-components").StyledComponent<"a", any, {}, never>;
17
+ export declare const ObjectFieldAddButton: import("styled-components").StyledComponent<"a", any, {}, never>;
18
+ export declare function getObjectFieldButton({ purpose, onClick, uiSchema, }: ObjectFieldButtonProps): JSX.Element;
14
19
  export declare const ArrayFieldWrapper: import("styled-components").StyledComponent<"fieldset", any, {}, never>;
15
20
  export declare const ArrayFieldTitle: import("styled-components").StyledComponent<"legend", any, {}, never>;
16
21
  export declare const ArrayFieldList: import("styled-components").StyledComponent<"ul", any, {}, never>;
17
22
  export declare const ArrayFieldItem: import("styled-components").StyledComponent<"li", any, {}, never>;
18
23
  export declare const ArrayFieldItemButtons: import("styled-components").StyledComponent<"div", any, {}, never>;
19
- export declare const ArrayFieldButtonEl: import("styled-components").StyledComponent<"a", any, {}, never>;
20
- export declare function ArrayFieldButton({ purpose, onClick }: ArrayFieldButtonProps): JSX.Element;
24
+ export declare const ArrayFieldButton: import("styled-components").StyledComponent<"a", any, {}, never>;
25
+ export declare const ArrayFieldLineButton: import("styled-components").StyledComponent<"a", any, {}, never>;
26
+ export declare const ArrayFieldUpButton: import("styled-components").StyledComponent<"a", any, {}, never>;
27
+ export declare const ArrayFieldDownButton: import("styled-components").StyledComponent<"a", any, {}, never>;
28
+ export declare const ArrayFieldRemoveButton: import("styled-components").StyledComponent<"a", any, {}, never>;
29
+ export declare const ArrayFieldAddButton: import("styled-components").StyledComponent<"a", any, {}, never>;
30
+ export declare function GetArrayFieldButton({ purpose, onClick, uiSchema, }: ArrayFieldButtonProps): JSX.Element;
21
31
  export declare const FieldWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
22
32
  export declare const FieldTitle: import("styled-components").StyledComponent<"label", any, {}, never>;
23
33
  export declare const FieldDescription: import("styled-components").StyledComponent<"p", any, {}, never>;
24
34
  export declare const FieldHelp: import("styled-components").StyledComponent<"p", any, {}, never>;
25
35
  export declare const ErrorMessage: import("styled-components").StyledComponent<import("react").ComponentType<formik.ErrorMessageProps>, any, {}, never>;
26
36
  export declare const FieldInput: import("styled-components").StyledComponent<({ formikAs, ...props }: any) => JSX.Element, any, {}, never>;
37
+ export declare const RequiredIndicator: import("styled-components").StyledComponent<"span", any, {}, never>;
@@ -28,6 +28,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
28
28
  import styled from "styled-components";
29
29
  import * as formik from "formik";
30
30
  import { ArrayFieldButtonPurpose, ObjectFieldButtonPurpose, } from "./types";
31
+ import { useContext } from "react";
32
+ import { FormRegistry } from "./Form";
31
33
  export var Form = styled(formik.Form)(templateObject_1 || (templateObject_1 = __makeTemplateObject([""], [""])));
32
34
  export var FormButtonWrapper = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject([""], [""])));
33
35
  export var FormButton = styled.button(templateObject_3 || (templateObject_3 = __makeTemplateObject([""], [""])));
@@ -36,20 +38,26 @@ export var ObjectFieldTitle = styled.legend(templateObject_5 || (templateObject_
36
38
  export var ObjectFieldList = styled.ul(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n list-style-type: none;\n padding: 0;\n"], ["\n list-style-type: none;\n padding: 0;\n"])));
37
39
  export var ObjectFieldItem = styled.li(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n display: flex;\n"], ["\n display: flex;\n"])));
38
40
  export var ObjectFieldItemButtons = styled.div(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n display: flex;\n margin: 0.5rem;\n"], ["\n display: flex;\n margin: 0.5rem;\n"])));
39
- export var ObjectFieldButtonEl = styled.a(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n cursor: pointer;\n border: 1px solid black;\n display: block;\n line-height: 1em;\n height: 1em;\n width: 1em;\n text-align: center;\n"], ["\n cursor: pointer;\n border: 1px solid black;\n display: block;\n line-height: 1em;\n height: 1em;\n width: 1em;\n text-align: center;\n"])));
40
- export function ObjectFieldButton(_a) {
41
- var purpose = _a.purpose, onClick = _a.onClick;
41
+ export var ObjectFieldButton = styled.a(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n cursor: pointer;\n border: 1px solid black;\n line-height: 1em;\n height: 1em;\n padding: 0 0.3em;\n"], ["\n cursor: pointer;\n border: 1px solid black;\n line-height: 1em;\n height: 1em;\n padding: 0 0.3em;\n"])));
42
+ export var ObjectFieldLineButton = styled(ObjectFieldButton)(templateObject_10 || (templateObject_10 = __makeTemplateObject([""], [""])));
43
+ export var ObjectFieldUpButton = styled(ObjectFieldLineButton)(templateObject_11 || (templateObject_11 = __makeTemplateObject([""], [""])));
44
+ export var ObjectFieldDownButton = styled(ObjectFieldLineButton)(templateObject_12 || (templateObject_12 = __makeTemplateObject([""], [""])));
45
+ export var ObjectFieldRemoveButton = styled(ObjectFieldLineButton)(templateObject_13 || (templateObject_13 = __makeTemplateObject([""], [""])));
46
+ export var ObjectFieldAddButton = styled(ObjectFieldButton)(templateObject_14 || (templateObject_14 = __makeTemplateObject([""], [""])));
47
+ export function getObjectFieldButton(_a) {
48
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
49
+ var purpose = _a.purpose, onClick = _a.onClick, uiSchema = _a.uiSchema;
42
50
  switch (purpose) {
43
51
  case ObjectFieldButtonPurpose.ADD:
44
- return _jsx(ObjectFieldButtonEl, __assign({ onClick: onClick }, { children: "+" }));
52
+ return (_jsx(ObjectFieldAddButton, __assign({}, ((_c = (_b = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:addButtonOptions"]) === null || _b === void 0 ? void 0 : _b.props) !== null && _c !== void 0 ? _c : {}), { onClick: onClick }, { children: (_e = (_d = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:addButtonOptions"]) === null || _d === void 0 ? void 0 : _d.content) !== null && _e !== void 0 ? _e : "+" })));
45
53
  case ObjectFieldButtonPurpose.REMOVE:
46
- return _jsx(ObjectFieldButtonEl, __assign({ onClick: onClick }, { children: "-" }));
54
+ return (_jsx(ObjectFieldRemoveButton, __assign({}, ((_g = (_f = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:removeButtonOptions"]) === null || _f === void 0 ? void 0 : _f.props) !== null && _g !== void 0 ? _g : {}), { onClick: onClick }, { children: (_j = (_h = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:removeButtonOptions"]) === null || _h === void 0 ? void 0 : _h.content) !== null && _j !== void 0 ? _j : "-" })));
47
55
  case ObjectFieldButtonPurpose.MOVE_UP:
48
- return _jsx(ObjectFieldButtonEl, __assign({ onClick: onClick }, { children: "\u2191" }));
56
+ return (_jsx(ObjectFieldUpButton, __assign({}, ((_l = (_k = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:upButtonOptions"]) === null || _k === void 0 ? void 0 : _k.props) !== null && _l !== void 0 ? _l : {}), { onClick: onClick }, { children: (_o = (_m = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:upButtonOptions"]) === null || _m === void 0 ? void 0 : _m.content) !== null && _o !== void 0 ? _o : "↑" })));
49
57
  case ObjectFieldButtonPurpose.MOVE_DOWN:
50
- return _jsx(ObjectFieldButtonEl, __assign({ onClick: onClick }, { children: "\u2193" }));
58
+ return (_jsx(ObjectFieldDownButton, __assign({}, ((_q = (_p = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:downButtonOptions"]) === null || _p === void 0 ? void 0 : _p.props) !== null && _q !== void 0 ? _q : {}), { onClick: onClick }, { children: (_s = (_r = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:downButtonOptions"]) === null || _r === void 0 ? void 0 : _r.content) !== null && _s !== void 0 ? _s : "↓" })));
51
59
  default:
52
- return (_jsx(ObjectFieldButtonEl, __assign({ onClick: onClick }, { children: "UNKNOWN PURPOSE" })));
60
+ return (_jsx(ObjectFieldButton, __assign({}, ((_u = (_t = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:customButtonOptions"]) === null || _t === void 0 ? void 0 : _t.props) !== null && _u !== void 0 ? _u : {}), { onClick: onClick }, { children: (_w = (_v = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:customButtonOptions"]) === null || _v === void 0 ? void 0 : _v.content) !== null && _w !== void 0 ? _w : "" })));
53
61
  }
54
62
  }
55
63
  export var ArrayFieldWrapper = ObjectFieldWrapper;
@@ -57,27 +65,34 @@ export var ArrayFieldTitle = ObjectFieldTitle;
57
65
  export var ArrayFieldList = ObjectFieldList;
58
66
  export var ArrayFieldItem = ObjectFieldItem;
59
67
  export var ArrayFieldItemButtons = ObjectFieldItemButtons;
60
- export var ArrayFieldButtonEl = ObjectFieldButtonEl;
61
- export function ArrayFieldButton(_a) {
62
- var purpose = _a.purpose, onClick = _a.onClick;
68
+ export var ArrayFieldButton = styled(ObjectFieldButton)(templateObject_15 || (templateObject_15 = __makeTemplateObject([""], [""])));
69
+ export var ArrayFieldLineButton = styled(ArrayFieldButton)(templateObject_16 || (templateObject_16 = __makeTemplateObject([""], [""])));
70
+ export var ArrayFieldUpButton = styled(ArrayFieldLineButton)(templateObject_17 || (templateObject_17 = __makeTemplateObject([""], [""])));
71
+ export var ArrayFieldDownButton = styled(ArrayFieldLineButton)(templateObject_18 || (templateObject_18 = __makeTemplateObject([""], [""])));
72
+ export var ArrayFieldRemoveButton = styled(ArrayFieldLineButton)(templateObject_19 || (templateObject_19 = __makeTemplateObject([""], [""])));
73
+ export var ArrayFieldAddButton = styled(ArrayFieldButton)(templateObject_20 || (templateObject_20 = __makeTemplateObject([""], [""])));
74
+ export function GetArrayFieldButton(_a) {
75
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
76
+ var purpose = _a.purpose, onClick = _a.onClick, uiSchema = _a.uiSchema;
77
+ var _x = useContext(FormRegistry).components, ArrayFieldAddButton = _x.ArrayFieldAddButton, ArrayFieldRemoveButton = _x.ArrayFieldRemoveButton, ArrayFieldUpButton = _x.ArrayFieldUpButton, ArrayFieldDownButton = _x.ArrayFieldDownButton;
63
78
  switch (purpose) {
64
79
  case ArrayFieldButtonPurpose.ADD:
65
- return _jsx(ArrayFieldButtonEl, __assign({ onClick: onClick }, { children: "+" }));
80
+ return (_jsx(ArrayFieldAddButton, __assign({}, ((_c = (_b = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:addButtonOptions"]) === null || _b === void 0 ? void 0 : _b.props) !== null && _c !== void 0 ? _c : {}), { onClick: onClick }, { children: (_e = (_d = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:addButtonOptions"]) === null || _d === void 0 ? void 0 : _d.content) !== null && _e !== void 0 ? _e : "+" })));
66
81
  case ArrayFieldButtonPurpose.REMOVE:
67
- return _jsx(ArrayFieldButtonEl, __assign({ onClick: onClick }, { children: "-" }));
82
+ return (_jsx(ArrayFieldRemoveButton, __assign({}, ((_g = (_f = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:removeButtonOptions"]) === null || _f === void 0 ? void 0 : _f.props) !== null && _g !== void 0 ? _g : {}), { onClick: onClick }, { children: (_j = (_h = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:removeButtonOptions"]) === null || _h === void 0 ? void 0 : _h.content) !== null && _j !== void 0 ? _j : "-" })));
68
83
  case ArrayFieldButtonPurpose.MOVE_UP:
69
- return _jsx(ArrayFieldButtonEl, __assign({ onClick: onClick }, { children: "\u2191" }));
84
+ return (_jsx(ArrayFieldUpButton, __assign({}, ((_l = (_k = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:upButtonOptions"]) === null || _k === void 0 ? void 0 : _k.props) !== null && _l !== void 0 ? _l : {}), { onClick: onClick }, { children: (_o = (_m = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:upButtonOptions"]) === null || _m === void 0 ? void 0 : _m.content) !== null && _o !== void 0 ? _o : "↑" })));
70
85
  case ArrayFieldButtonPurpose.MOVE_DOWN:
71
- return _jsx(ArrayFieldButtonEl, __assign({ onClick: onClick }, { children: "\u2193" }));
86
+ return (_jsx(ArrayFieldDownButton, __assign({}, ((_q = (_p = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:downButtonOptions"]) === null || _p === void 0 ? void 0 : _p.props) !== null && _q !== void 0 ? _q : {}), { onClick: onClick }, { children: (_s = (_r = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:downButtonOptions"]) === null || _r === void 0 ? void 0 : _r.content) !== null && _s !== void 0 ? _s : "↓" })));
72
87
  default:
73
- return (_jsx(ArrayFieldButtonEl, __assign({ onClick: onClick }, { children: "UNKNOWN PURPOSE" })));
88
+ return (_jsx(ArrayFieldButton, __assign({}, ((_u = (_t = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:customButtonOptions"]) === null || _t === void 0 ? void 0 : _t.props) !== null && _u !== void 0 ? _u : {}), { onClick: onClick }, { children: (_w = (_v = uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:customButtonOptions"]) === null || _v === void 0 ? void 0 : _v.content) !== null && _w !== void 0 ? _w : "" })));
74
89
  }
75
90
  }
76
- export var FieldWrapper = styled.div(templateObject_10 || (templateObject_10 = __makeTemplateObject(["\n margin: 0.5rem 0;\n"], ["\n margin: 0.5rem 0;\n"])));
77
- export var FieldTitle = styled.label(templateObject_11 || (templateObject_11 = __makeTemplateObject(["\n font-weight: 700;\n"], ["\n font-weight: 700;\n"])));
78
- export var FieldDescription = styled.p(templateObject_12 || (templateObject_12 = __makeTemplateObject(["\n margin: 0;\n font-size: 0.9em;\n"], ["\n margin: 0;\n font-size: 0.9em;\n"])));
79
- export var FieldHelp = styled.p(templateObject_13 || (templateObject_13 = __makeTemplateObject(["\n margin: 0;\n font-size: 0.9em;\n"], ["\n margin: 0;\n font-size: 0.9em;\n"])));
80
- export var ErrorMessage = styled(formik.ErrorMessage)(templateObject_14 || (templateObject_14 = __makeTemplateObject([""], [""])));
91
+ export var FieldWrapper = styled.div(templateObject_21 || (templateObject_21 = __makeTemplateObject(["\n margin: 0.5rem 0;\n"], ["\n margin: 0.5rem 0;\n"])));
92
+ export var FieldTitle = styled.label(templateObject_22 || (templateObject_22 = __makeTemplateObject(["\n font-weight: 700;\n"], ["\n font-weight: 700;\n"])));
93
+ export var FieldDescription = styled.p(templateObject_23 || (templateObject_23 = __makeTemplateObject(["\n margin: 0;\n font-size: 0.9em;\n"], ["\n margin: 0;\n font-size: 0.9em;\n"])));
94
+ export var FieldHelp = styled.p(templateObject_24 || (templateObject_24 = __makeTemplateObject(["\n margin: 0;\n font-size: 0.9em;\n"], ["\n margin: 0;\n font-size: 0.9em;\n"])));
95
+ export var ErrorMessage = styled(formik.ErrorMessage)(templateObject_25 || (templateObject_25 = __makeTemplateObject([""], [""])));
81
96
  /*
82
97
  * Works like Formik field, but "as" props needs to be given with "formikAs", since styled components uses as.
83
98
  *
@@ -85,5 +100,6 @@ export var ErrorMessage = styled(formik.ErrorMessage)(templateObject_14 || (temp
85
100
  export var FieldInput = styled(function (_a) {
86
101
  var formikAs = _a.formikAs, props = __rest(_a, ["formikAs"]);
87
102
  return _jsx(formik.Field, __assign({}, props, { as: formikAs }));
88
- })(templateObject_15 || (templateObject_15 = __makeTemplateObject([""], [""])));
89
- var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12, templateObject_13, templateObject_14, templateObject_15;
103
+ })(templateObject_26 || (templateObject_26 = __makeTemplateObject([""], [""])));
104
+ export var RequiredIndicator = styled.span(templateObject_27 || (templateObject_27 = __makeTemplateObject([""], [""])));
105
+ var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12, templateObject_13, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22, templateObject_23, templateObject_24, templateObject_25, templateObject_26, templateObject_27;
@@ -14,7 +14,7 @@ import { useContext } from "react";
14
14
  import { FormRegistry } from "../Form";
15
15
  import { useExtractUiSchema, getDescription, getTitle } from "../utils";
16
16
  export function FieldTemplate(props) {
17
- var _a = useContext(FormRegistry).components, FieldWrapper = _a.FieldWrapper, FieldTitle = _a.FieldTitle, FieldDescription = _a.FieldDescription, ErrorMessage = _a.ErrorMessage, FieldHelp = _a.FieldHelp;
17
+ var _a = useContext(FormRegistry).components, FieldWrapper = _a.FieldWrapper, FieldTitle = _a.FieldTitle, FieldDescription = _a.FieldDescription, ErrorMessage = _a.ErrorMessage, FieldHelp = _a.FieldHelp, RequiredIndicator = _a.RequiredIndicator;
18
18
  var name = props.name, uiSchema = props.uiSchema, children = props.children;
19
19
  var title = getTitle(props);
20
20
  var description = getDescription(props);
@@ -23,5 +23,5 @@ export function FieldTemplate(props) {
23
23
  _c = _b.props,
24
24
  //TODO: This is not right
25
25
  _d = _c === void 0 ? {} : _c, wrappertProps = _d.wrapper, titleProps = _d.title, descriptionProps = _d.description, helpProps = _d.help, errorProps = _d.error;
26
- return (_jsxs(FieldWrapper, __assign({}, wrappertProps, { children: [title && (_jsx(FieldTitle, __assign({}, titleProps, { htmlFor: name }, { children: title }))), description && (_jsx(FieldDescription, __assign({}, descriptionProps, { children: description }))), children, help && _jsx(FieldHelp, __assign({}, helpProps, { children: help })), _jsx(ErrorMessage, __assign({}, errorProps, { name: name }))] })));
26
+ return (_jsxs(FieldWrapper, __assign({}, wrappertProps, { children: [title && (_jsxs(FieldTitle, __assign({}, titleProps, { htmlFor: name }, { children: [title, props.required && _jsx(RequiredIndicator, { children: "*" })] }))), description && (_jsx(FieldDescription, __assign({}, descriptionProps, { children: description }))), children, help && _jsx(FieldHelp, __assign({}, helpProps, { children: help })), _jsx(ErrorMessage, __assign({}, errorProps, { name: name }))] })));
27
27
  }
@@ -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
- return (_jsxs(ObjectFieldWrapper, { children: [title && _jsx(ObjectFieldTitle, { children: title }), description && _jsx(FieldDescription, { children: description }), children] }));
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;
@@ -94,19 +97,28 @@ export type ComponentsType = {
94
97
  ObjectFieldItem: React.FunctionComponent<any>;
95
98
  ObjectFieldItemButtons: React.FunctionComponent<any>;
96
99
  ObjectFieldList: React.FunctionComponent<any>;
97
- ObjectFieldButton: React.FunctionComponent<ObjectFieldButtonProps>;
100
+ ObjectFieldButton: React.FunctionComponent<any>;
101
+ ObjectFieldAddButton: React.FunctionComponent<any>;
102
+ ObjectFieldRemoveButton: React.FunctionComponent<any>;
103
+ ObjectFieldUpButton: React.FunctionComponent<any>;
104
+ ObjectFieldDownButton: React.FunctionComponent<any>;
98
105
  ArrayFieldWrapper: React.FunctionComponent<any>;
99
106
  ArrayFieldTitle: React.FunctionComponent<any>;
100
107
  ArrayFieldItem: React.FunctionComponent<any>;
101
108
  ArrayFieldItemButtons: React.FunctionComponent<any>;
102
109
  ArrayFieldList: React.FunctionComponent<any>;
103
- ArrayFieldButton: React.FunctionComponent<ArrayFieldButtonProps>;
110
+ ArrayFieldButton: React.FunctionComponent<any>;
111
+ ArrayFieldAddButton: React.FunctionComponent<any>;
112
+ ArrayFieldRemoveButton: React.FunctionComponent<any>;
113
+ ArrayFieldUpButton: React.FunctionComponent<any>;
114
+ ArrayFieldDownButton: React.FunctionComponent<any>;
104
115
  FieldWrapper: React.FunctionComponent<any>;
105
116
  FieldTitle: React.FunctionComponent<any>;
106
117
  FieldDescription: React.FunctionComponent<any>;
107
118
  FieldHelp: React.FunctionComponent<any>;
108
119
  ErrorMessage: React.FunctionComponent<any>;
109
120
  FieldInput: React.FunctionComponent<any>;
121
+ RequiredIndicator: React.FunctionComponent<any>;
110
122
  };
111
123
  export declare enum ObjectFieldButtonPurpose {
112
124
  ADD = 0,
@@ -117,6 +129,7 @@ export declare enum ObjectFieldButtonPurpose {
117
129
  export type ObjectFieldButtonProps = {
118
130
  purpose: ObjectFieldButtonPurpose;
119
131
  onClick: () => void;
132
+ uiSchema: UiSchema;
120
133
  };
121
134
  export declare enum ArrayFieldButtonPurpose {
122
135
  ADD = 0,
@@ -127,6 +140,7 @@ export declare enum ArrayFieldButtonPurpose {
127
140
  export type ArrayFieldButtonProps = {
128
141
  purpose: ArrayFieldButtonPurpose;
129
142
  onClick: () => void;
143
+ uiSchema: UiSchema;
130
144
  };
131
145
  /*** ***/
132
146
  export type AjvError = {
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { FieldProps, Schema, UiSchema } from "./types";
2
+ import { JSONSchema7 } from "json-schema";
2
3
  export declare function getTitle({ title, uiSchema, schema, name, }: {
3
4
  title?: string;
4
5
  uiSchema?: UiSchema;
@@ -10,6 +11,7 @@ export declare function getDescription({ description, uiSchema, schema, }: {
10
11
  uiSchema?: UiSchema;
11
12
  schema?: Schema;
12
13
  }): any;
14
+ export declare function getDefaultValueForType(type: JSONSchema7["type"]): {} | null;
13
15
  export declare function useSetDefault(props: FieldProps): void;
14
16
  export declare function useExtractUiSchema(props?: UiSchema | undefined): {
15
17
  [name: string]: any;
package/dist/utils.js CHANGED
@@ -39,11 +39,25 @@ export function getDescription(_a) {
39
39
  (uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema["ui:description"]) ||
40
40
  (schema === null || schema === void 0 ? void 0 : schema.description));
41
41
  }
42
+ export function getDefaultValueForType(type) {
43
+ if (type && !Array.isArray(type)) {
44
+ if (type === "array")
45
+ return [];
46
+ if (type === "object")
47
+ return {};
48
+ }
49
+ return null;
50
+ }
42
51
  export function useSetDefault(props) {
43
52
  var _a = useField(props.name), value = _a[0].value, _ = _a[1], setValue = _a[2].setValue;
44
53
  useEffect(function () {
45
- if (!value && props.schema.default) {
46
- setValue(props.schema.default);
54
+ if (!value) {
55
+ if (props.schema.default) {
56
+ setValue(props.schema.default);
57
+ }
58
+ else if (props.forceDefaultValue) {
59
+ setValue(getDefaultValueForType(props.schema.type));
60
+ }
47
61
  }
48
62
  }, []);
49
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nolwenture/formik-jsonschema-form",
3
- "version": "0.1.3",
3
+ "version": "0.3.0",
4
4
  "description": "Formik form generation from json schema",
5
5
  "author": "Antti Vikman <antti.vikman@nolwenture.com>",
6
6
  "contributors": [