@nolwenture/formik-jsonschema-form 0.7.0 → 0.8.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.
Files changed (67) hide show
  1. package/README.md +52 -1
  2. package/dist/Form.stories.d.ts +1 -0
  3. package/dist/Form.stories.js +8 -0
  4. package/dist/Form.test.d.ts +1 -1
  5. package/dist/Form.test.js +3 -1
  6. package/dist/fields/ArrayField.js +1 -1
  7. package/dist/fields/MultipleChoiceField.d.ts +3 -0
  8. package/dist/fields/MultipleChoiceField.js +15 -0
  9. package/dist/fields/ObjectField.js +3 -1
  10. package/dist/fields/StringField.js +1 -1
  11. package/dist/fields/index.d.ts +1 -0
  12. package/dist/fields/index.js +1 -0
  13. package/dist/fields/stories/AnyField.stories.d.ts +5 -0
  14. package/dist/fields/stories/AnyField.stories.js +79 -0
  15. package/dist/fields/stories/ArrayField.stories.d.ts +7 -0
  16. package/dist/fields/stories/ArrayField.stories.js +191 -0
  17. package/dist/fields/stories/BooleanField.stories.d.ts +5 -0
  18. package/dist/fields/stories/BooleanField.stories.js +36 -0
  19. package/dist/fields/stories/DateField.stories.d.ts +5 -0
  20. package/dist/fields/stories/DateField.stories.js +34 -0
  21. package/dist/fields/stories/NullField.stories.d.ts +5 -0
  22. package/dist/fields/stories/NullField.stories.js +38 -0
  23. package/dist/fields/stories/NumberField.stories.d.ts +5 -0
  24. package/dist/fields/stories/NumberField.stories.js +33 -0
  25. package/dist/fields/stories/ObjectField.stories.d.ts +5 -0
  26. package/dist/fields/stories/ObjectField.stories.js +76 -0
  27. package/dist/fields/stories/RadioField.stories.d.ts +5 -0
  28. package/dist/fields/stories/RadioField.stories.js +42 -0
  29. package/dist/fields/stories/SchemaField.stories.d.ts +1673 -0
  30. package/dist/fields/stories/SchemaField.stories.js +39 -0
  31. package/dist/fields/stories/SearchMultiTagSelectField.stories.d.ts +5 -0
  32. package/dist/fields/stories/SearchMultiTagSelectField.stories.js +58 -0
  33. package/dist/fields/stories/StringField.stories.d.ts +7 -0
  34. package/dist/fields/stories/StringField.stories.js +75 -0
  35. package/dist/fields/stories/ToggleField.stories.d.ts +5 -0
  36. package/dist/fields/stories/ToggleField.stories.js +34 -0
  37. package/dist/hooks/__tests__/useExtractUiSchema.test.d.ts +1 -0
  38. package/dist/hooks/__tests__/useExtractUiSchema.test.js +45 -0
  39. package/dist/hooks/__tests__/useSetDefault.test.d.ts +1 -0
  40. package/dist/hooks/__tests__/useSetDefault.test.js +65 -0
  41. package/dist/hooks/useExtractUiSchema.js +7 -3
  42. package/dist/sampleData/multipleChoiceSchema.d.ts +3 -0
  43. package/dist/sampleData/multipleChoiceSchema.js +112 -0
  44. package/dist/sampleData/requiredInputSchema.js +0 -5
  45. package/dist/styledComponents.d.ts +2 -1
  46. package/dist/styledComponents.js +15 -9
  47. package/dist/types.d.ts +15 -0
  48. package/dist/utils/__tests/createInitialValues.test.d.ts +1 -0
  49. package/dist/utils/__tests/createInitialValues.test.js +72 -0
  50. package/dist/utils/__tests/deepOverlap.test.d.ts +1 -0
  51. package/dist/utils/__tests/deepOverlap.test.js +41 -0
  52. package/dist/utils/__tests/getEnums.test.js +11 -16
  53. package/dist/utils/__tests/getTitleAndDescription.test.d.ts +1 -0
  54. package/dist/utils/__tests/getTitleAndDescription.test.js +53 -0
  55. package/dist/utils/__tests/getTypes.test.d.ts +1 -0
  56. package/dist/utils/__tests/getTypes.test.js +62 -0
  57. package/dist/utils/__tests/mergeSchemas.test.d.ts +1 -0
  58. package/dist/utils/__tests/mergeSchemas.test.js +40 -0
  59. package/dist/utils/__tests/resolveSchema.test.js +28 -28
  60. package/dist/utils/createInitialValues.d.ts +4 -0
  61. package/dist/utils/createInitialValues.js +27 -0
  62. package/dist/utils/getStyle.d.ts +5 -0
  63. package/dist/utils/getStyle.js +18 -0
  64. package/dist/utils/getTypes.js +1 -1
  65. package/dist/utils/index.d.ts +1 -0
  66. package/dist/utils/index.js +1 -0
  67. package/package.json +5 -2
package/README.md CHANGED
@@ -14,6 +14,26 @@ With yarn:
14
14
  yarn add @nolwenture/formik-jsonschema-form
15
15
  ```
16
16
 
17
+ ## Testing
18
+
19
+ Run unit tests:
20
+
21
+ ```text
22
+ npm run test
23
+ ```
24
+
25
+ To run storybook tests make sure you have Playwright installed:
26
+
27
+ ```text
28
+ npx playwright install
29
+ ```
30
+
31
+ Run storybook tests:
32
+
33
+ ```text
34
+ npm run test-storybook
35
+ ```
36
+
17
37
  ## Usage
18
38
 
19
39
  ### Basic usage
@@ -400,7 +420,9 @@ const uiSchema = {
400
420
  ### Alternative fields
401
421
 
402
422
  There are alternative fields available for certain types.
403
- For `type: "string"` there is `DateField`, that has a "dd.mm.yyyy" date input field and a calendar date picker and will save the date input as "yyyy-mm-dd" string.
423
+ For `type: "string"` there is `DateField` and `MultipleChoiceField`.
424
+
425
+ `DateField` has a "dd.mm.yyyy" date input field and a calendar date picker and will save the date input as "yyyy-mm-dd" string.
404
426
 
405
427
  ```tsx
406
428
  const schema = {
@@ -414,6 +436,35 @@ const uiSchema = {
414
436
  };
415
437
  ```
416
438
 
439
+ `MultipleChoiceField` takes an array of `oneOf` or `anyOf`. The choices provided inside an `oneOf`array will be presented on the UI as Radio button selectables and only one of the given values can be selected. The choices provided inside an `anyOf` array will be presented on the UI as Checkbox selectables and multiple values can be selected.
440
+ `MultipleChoiceField` comes with a small number of predefined styles, which are `inline`, `oneColumn`, `twoColumns` and `threeColumns`. When no style is given, the choice options are listed in a row under the title.
441
+
442
+ ```tsx
443
+ const schema = {
444
+ properties: {
445
+ feeling: {
446
+ type: "string",
447
+ title: "How are you feeling today?",
448
+ oneOf: [
449
+ { const: "happy", title: "Happy" },
450
+ { const: "creative", title: "Creative" },
451
+ { const: "tired", title: "Tired" },
452
+ { const: "nope", title: "Please don't even ask..." },
453
+ ],
454
+ },
455
+ },
456
+ };
457
+
458
+ const uiSchema = {
459
+ feeling: {
460
+ "ui:field": "MultipleChoiceField",
461
+ "ui:option": {
462
+ style: "twoColumns",
463
+ },
464
+ },
465
+ };
466
+ ```
467
+
417
468
  For `type: "boolean"` there is `RadioField` and `ToggleField`.
418
469
  `RadioField` can take labels for the "true" and "false" options. If left empty, the default labels will be "true" and "false".
419
470
 
@@ -11,3 +11,4 @@ export declare const StylesCustomized: () => import("react/jsx-runtime").JSX.Ele
11
11
  export declare const WithGeneratedSchema: Story;
12
12
  export declare const WithRequiredInput: Story;
13
13
  export declare const WithConditions: Story;
14
+ export declare const MultipleChoice: Story;
@@ -25,6 +25,7 @@ import { Formik, useFormikContext } from "formik";
25
25
  import { InfoFieldButton, SearchableMultiTagSelectField, } from "./styledComponents";
26
26
  import { completeSchema, completeUiSchema, simpleSchema, simpleUiSchema, generatedSchema, requiredInputSchema, requiredInputUiSchema, conditionsSchema, conditionsUiSchema, } from "./sampleData";
27
27
  import { Form, styledComponents } from "./";
28
+ import { multipleChoiceSchema, multipleChoiceUiSchema, } from "./sampleData/multipleChoiceSchema";
28
29
  const meta = {
29
30
  title: "Form",
30
31
  component: Form,
@@ -46,6 +47,7 @@ export default meta;
46
47
  export const Simple = {
47
48
  args: {
48
49
  schema: simpleSchema,
50
+ uiSchema: simpleUiSchema,
49
51
  },
50
52
  };
51
53
  const InfoFieldButtonNew = styled(InfoFieldButton) `
@@ -183,3 +185,9 @@ export const WithConditions = {
183
185
  hideUnmarkedAdditionalProperties: true,
184
186
  },
185
187
  };
188
+ export const MultipleChoice = {
189
+ args: {
190
+ schema: multipleChoiceSchema,
191
+ uiSchema: multipleChoiceUiSchema,
192
+ },
193
+ };
@@ -1 +1 @@
1
- export {};
1
+ import "@testing-library/jest-dom";
package/dist/Form.test.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import "@testing-library/jest-dom";
2
3
  import { render, screen } from "@testing-library/react";
4
+ import { Formik } from "formik";
3
5
  import { Form } from "./Form";
4
6
  import { simpleSchema } from "./sampleData";
5
7
  test("renders title", () => {
6
- render(_jsx(Form, { schema: simpleSchema }));
8
+ render(_jsx(Formik, { initialValues: {}, onSubmit: () => { }, children: _jsx(Form, { schema: simpleSchema }) }));
7
9
  const titleElement = screen.getByText(/TITLE/i);
8
10
  expect(titleElement).toBeInTheDocument();
9
11
  });
@@ -106,7 +106,7 @@ export const ArrayField = (props) => {
106
106
  onClick: () => setValue(moveInArray(value, index + items.length, -1)),
107
107
  uiSchema,
108
108
  }), value.length > 1 &&
109
- index < value.length - 1 &&
109
+ index < (value === null || value === void 0 ? void 0 : value.slice(items.length).length) - 1 &&
110
110
  GetArrayFieldButton({
111
111
  purpose: ArrayFieldButtonPurpose.MOVE_DOWN,
112
112
  onClick: () => setValue(moveInArray(value, index + items.length, 1)),
@@ -0,0 +1,3 @@
1
+ import type { FieldProps } from "../types";
2
+ import React from "react";
3
+ export declare const MultipleChoiceField: React.FC<FieldProps>;
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useContext, useMemo } from "react";
3
+ import { FormRegistry } from "../Form";
4
+ import { useExtractUiSchema, useSetDefault } from "../hooks";
5
+ import { getEnums } from "../utils/getEnums";
6
+ export const MultipleChoiceField = (props) => {
7
+ const { templates: { FieldTemplate }, components: { MultipleChoiceField }, } = useContext(FormRegistry);
8
+ useSetDefault(props);
9
+ const { name, uiSchema } = props;
10
+ const { props: inputProps, option } = useExtractUiSchema(uiSchema);
11
+ const enums = useMemo(() => getEnums(props), [props]);
12
+ console.log("option", option);
13
+ console.log("uiSchema", uiSchema);
14
+ return (_jsx(FieldTemplate, Object.assign({}, props, { children: _jsx(MultipleChoiceField, { inputProps: inputProps, name: name, enums: enums, style: option === null || option === void 0 ? void 0 : option.style }) })));
15
+ };
@@ -53,7 +53,9 @@ export const ObjectField = (props) => {
53
53
  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));
54
54
  })
55
55
  .filter((x) => x), (!hideUnmarkedAdditionalProperties || additionalProperties) &&
56
- Object.entries(additionalValues || {}).map(([childName, childSchema]) => (_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({
56
+ Object.entries(additionalValues || {}).map(([childName]) => (_jsxs(ObjectFieldItem, { children: [_jsx(SchemaField, { required: required === null || required === void 0 ? void 0 : required.includes(childName), name: name ? [name, childName].join(".") : childName, schema: typeof schema.additionalProperties !== "boolean"
57
+ ? schema.additionalProperties
58
+ : {}, uiSchema: uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema[childName] }, childName), _jsx(ObjectFieldItemButtons, { children: getObjectFieldButton({
57
59
  purpose: ObjectFieldButtonPurpose.REMOVE,
58
60
  onClick: () => {
59
61
  const _a = value, _b = childName, _removedProperty = _a[_b], newValue = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
@@ -13,7 +13,7 @@ export const StringField = (props) => {
13
13
  switch (enums === null || enums === void 0 ? void 0 : enums.type) {
14
14
  case "select":
15
15
  case "multiSelect":
16
- return (_jsx(FieldTemplate, Object.assign({}, props, { children: _jsxs(FieldInput, Object.assign({ type }, inputProps, { name: name, formikAs: "select", multiple: enums.type === "multiSelect" }, (enums.type !== "multiSelect" ? { defaultValue: "" } : {}), { children: [enums.type !== "multiSelect" && (_jsx("option", Object.assign({ value: "", disabled: true,
16
+ return (_jsx(FieldTemplate, Object.assign({}, props, { children: _jsxs(FieldInput, Object.assign({ type }, inputProps, { name: name, formikAs: "select", multiple: enums.type === "multiSelect", children: [enums.type !== "multiSelect" && (_jsx("option", Object.assign({ value: "", disabled: true,
17
17
  hidden: true }, (_a = uiSchema["ui:placeholderOptionOptions"]) === null || _a === void 0 ? void 0 : _a.props, { children: placeholder }))), enums === null || enums === void 0 ? void 0 : enums.values.map((option, index) => (_jsx("option", { value: option.const, children: option.title }, index)))] })) })));
18
18
  default:
19
19
  return (_jsx(FieldTemplate, Object.assign({}, props, { children: _jsx(FieldInput, Object.assign({ type,
@@ -10,3 +10,4 @@ export * from "./AnyField";
10
10
  export * from "./RadioField";
11
11
  export * from "./ToggleField";
12
12
  export * from "./SearchMultiTagSelectField";
13
+ export * from "./MultipleChoiceField";
@@ -10,3 +10,4 @@ export * from "./AnyField";
10
10
  export * from "./RadioField";
11
11
  export * from "./ToggleField";
12
12
  export * from "./SearchMultiTagSelectField";
13
+ export * from "./MultipleChoiceField";
@@ -0,0 +1,5 @@
1
+ import { StoryObj } from "@storybook/react";
2
+ import { AnyField } from "./../AnyField";
3
+ declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
4
+ export default _default;
5
+ export declare const Default: StoryObj<typeof AnyField>;
@@ -0,0 +1,79 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { within, userEvent, expect } from "@storybook/test";
12
+ import { Formik, Form } from "formik";
13
+ import { AnyField } from "./../AnyField";
14
+ export default {
15
+ title: "Components/AnyField",
16
+ component: AnyField,
17
+ decorators: [
18
+ (Story) => (_jsx(Formik, { initialValues: { dynamicField: "" }, onSubmit: (values) => console.log(values), children: _jsx(Form, { children: Story() }) })),
19
+ ],
20
+ };
21
+ export const Default = {
22
+ args: {
23
+ name: "dynamicField",
24
+ schema: {},
25
+ uiSchema: {},
26
+ },
27
+ play: (_a) => __awaiter(void 0, [_a], void 0, function* ({ canvasElement }) {
28
+ const canvas = within(canvasElement);
29
+ const select = canvasElement.querySelector("select");
30
+ // Null
31
+ yield userEvent.selectOptions(select, "null");
32
+ const allInputs = canvasElement.querySelectorAll("input");
33
+ expect(allInputs).toHaveLength(0);
34
+ // AnyField
35
+ yield userEvent.selectOptions(select, "any");
36
+ const anySelect = canvasElement.querySelectorAll("select");
37
+ const input = canvasElement.querySelector('input[name="dynamicField"]');
38
+ yield userEvent.type(input, "testString");
39
+ expect(input).toHaveValue("testString");
40
+ yield userEvent.selectOptions(anySelect[1], "boolean");
41
+ yield userEvent.click(input);
42
+ expect(input).toBeChecked;
43
+ // StringField
44
+ yield userEvent.selectOptions(select, "string");
45
+ yield userEvent.type(input, "testString");
46
+ expect(input).toHaveValue("testString");
47
+ // IntegerField
48
+ yield userEvent.selectOptions(select, "integer");
49
+ const integerInput = canvasElement.querySelector('input[name="dynamicField"]');
50
+ yield userEvent.type(integerInput, "321");
51
+ expect(integerInput).toHaveValue(321);
52
+ // NumberField
53
+ yield userEvent.selectOptions(select, "number");
54
+ const numberInput = canvasElement.querySelector('input[name="dynamicField"]');
55
+ yield userEvent.clear(numberInput);
56
+ yield userEvent.type(numberInput, "123");
57
+ expect(numberInput).toHaveValue(123);
58
+ // BooleanField
59
+ yield userEvent.selectOptions(select, "boolean");
60
+ const checkBox = canvasElement.querySelector('input[name="dynamicField"]');
61
+ yield userEvent.click(checkBox);
62
+ expect(checkBox).toBeChecked();
63
+ // ObjectField
64
+ // TODO Find out how to handle modal
65
+ // ArrayField
66
+ yield userEvent.selectOptions(select, "array");
67
+ const addButton = canvas.getByText("+");
68
+ yield userEvent.click(addButton);
69
+ yield userEvent.click(addButton);
70
+ const downArrow = canvas.queryAllByText("↓");
71
+ const inputFirst = canvasElement.querySelector('input[name="dynamicField[0]"]');
72
+ const inputSecond = canvasElement.querySelector('input[name="dynamicField[1]"]');
73
+ yield userEvent.type(inputFirst, "first");
74
+ yield userEvent.type(inputSecond, "second");
75
+ yield userEvent.click(downArrow[0]);
76
+ expect(inputFirst).toHaveValue("second");
77
+ expect(inputSecond).toHaveValue("first");
78
+ }),
79
+ };
@@ -0,0 +1,7 @@
1
+ import { StoryObj } from "@storybook/react";
2
+ import { ArrayField } from "./../ArrayField";
3
+ declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
4
+ export default _default;
5
+ export declare const BasicArray: StoryObj<typeof ArrayField>;
6
+ export declare const EnumArray: StoryObj<typeof ArrayField>;
7
+ export declare const ObjectArray: StoryObj<typeof ArrayField>;
@@ -0,0 +1,191 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { within, userEvent, expect } from "@storybook/test";
12
+ import { Formik, Form } from "formik";
13
+ import { ArrayField } from "./../ArrayField";
14
+ export default {
15
+ title: "Components/ArrayField",
16
+ component: ArrayField,
17
+ decorators: [
18
+ (Story) => (_jsx(Formik, { initialValues: { itemsList: [] }, onSubmit: (values) => console.log(values), children: _jsx(Form, { children: Story() }) })),
19
+ ],
20
+ };
21
+ export const BasicArray = {
22
+ args: {
23
+ name: "itemsList",
24
+ schema: {
25
+ type: "array",
26
+ title: "Array",
27
+ description: "Array description",
28
+ additionalItems: { type: "boolean" },
29
+ },
30
+ uiSchema: {},
31
+ },
32
+ play: (_a) => __awaiter(void 0, [_a], void 0, function* ({ canvasElement }) {
33
+ const canvas = within(canvasElement);
34
+ // Add three items
35
+ const addButton = canvas.getByText("+");
36
+ yield userEvent.click(addButton);
37
+ yield userEvent.click(addButton);
38
+ yield userEvent.click(addButton);
39
+ const allDownArrows = canvas.queryAllByText("↓");
40
+ const allUpArrows = canvas.queryAllByText("↑");
41
+ const firstCheckbox = canvasElement.querySelector('input[name="itemsList[0]"]');
42
+ const secondCheckbox = canvasElement.querySelector('input[name="itemsList[1]"]');
43
+ const thirdCheckbox = canvasElement.querySelector('input[name="itemsList[2]"]');
44
+ const allLabelsAfterAdd = canvasElement.querySelectorAll('[name^="itemsList["]');
45
+ expect(allLabelsAfterAdd.length).toEqual(3);
46
+ // Check that moving items work
47
+ yield userEvent.click(firstCheckbox);
48
+ expect(firstCheckbox).toBeChecked();
49
+ expect(secondCheckbox).not.toBeChecked();
50
+ expect(thirdCheckbox).not.toBeChecked();
51
+ yield userEvent.click(allDownArrows[0]);
52
+ expect(firstCheckbox).not.toBeChecked();
53
+ expect(secondCheckbox).toBeChecked();
54
+ expect(thirdCheckbox).not.toBeChecked();
55
+ yield userEvent.click(allDownArrows[1]);
56
+ expect(firstCheckbox).not.toBeChecked();
57
+ expect(secondCheckbox).not.toBeChecked();
58
+ expect(thirdCheckbox).toBeChecked();
59
+ yield userEvent.click(allUpArrows[1]);
60
+ expect(firstCheckbox).not.toBeChecked();
61
+ expect(secondCheckbox).toBeChecked();
62
+ expect(thirdCheckbox).not.toBeChecked();
63
+ // Remove items
64
+ const removeButton = canvas.queryAllByText("-");
65
+ yield userEvent.click(removeButton[2]);
66
+ yield userEvent.click(removeButton[1]);
67
+ yield userEvent.click(removeButton[0]);
68
+ const allLabelsAfterRemove = canvasElement.querySelectorAll('[name^="itemsList["]');
69
+ expect(allLabelsAfterRemove.length).toEqual(0);
70
+ }),
71
+ };
72
+ export const EnumArray = {
73
+ args: {
74
+ name: "itemsList",
75
+ schema: {
76
+ type: "array",
77
+ title: "Enum array",
78
+ description: "Enum array description",
79
+ additionalItems: {
80
+ type: "number",
81
+ enum: [1, 2, 3, 4],
82
+ },
83
+ },
84
+ uiSchema: {},
85
+ },
86
+ play: (_b) => __awaiter(void 0, [_b], void 0, function* ({ canvasElement }) {
87
+ const canvas = within(canvasElement);
88
+ // Add three items
89
+ const addButton = canvas.getByText("+");
90
+ yield userEvent.click(addButton);
91
+ yield userEvent.click(addButton);
92
+ yield userEvent.click(addButton);
93
+ const allDownArrows = canvas.queryAllByText("↓");
94
+ const allUpArrows = canvas.queryAllByText("↑");
95
+ const firstSelect = canvasElement.querySelector('select[name="itemsList[0]"]');
96
+ const secondSelect = canvasElement.querySelector('select[name="itemsList[1]"]');
97
+ const thirdSelect = canvasElement.querySelector('select[name="itemsList[2]"]');
98
+ const allLabelsAfterAdd = canvasElement.querySelectorAll('[name^="itemsList["]');
99
+ expect(allLabelsAfterAdd.length).toEqual(3);
100
+ yield userEvent.selectOptions(firstSelect, "1");
101
+ yield userEvent.selectOptions(secondSelect, "2");
102
+ yield userEvent.selectOptions(thirdSelect, "3");
103
+ // Check that moving items work
104
+ yield expect(firstSelect).toHaveValue("1");
105
+ yield expect(secondSelect).toHaveValue("2");
106
+ yield expect(thirdSelect).toHaveValue("3");
107
+ yield userEvent.click(allDownArrows[0]);
108
+ yield expect(firstSelect).toHaveValue("2");
109
+ yield expect(secondSelect).toHaveValue("1");
110
+ yield expect(thirdSelect).toHaveValue("3");
111
+ yield userEvent.click(allDownArrows[1]);
112
+ yield expect(firstSelect).toHaveValue("2");
113
+ yield expect(secondSelect).toHaveValue("3");
114
+ yield expect(thirdSelect).toHaveValue("1");
115
+ yield userEvent.click(allUpArrows[1]);
116
+ yield expect(firstSelect).toHaveValue("2");
117
+ yield expect(secondSelect).toHaveValue("1");
118
+ yield expect(thirdSelect).toHaveValue("3");
119
+ // Remove items
120
+ const removeButton = canvas.queryAllByText("-");
121
+ yield userEvent.click(removeButton[2]);
122
+ yield userEvent.click(removeButton[1]);
123
+ yield userEvent.click(removeButton[0]);
124
+ const allLabelsAfterRemove = canvasElement.querySelectorAll('[name^="itemsList["]');
125
+ expect(allLabelsAfterRemove.length).toEqual(0);
126
+ }),
127
+ };
128
+ export const ObjectArray = {
129
+ args: {
130
+ name: "itemsList",
131
+ schema: {
132
+ type: "array",
133
+ title: "Object array",
134
+ description: "Object array description",
135
+ additionalItems: {
136
+ type: "object",
137
+ title: "Item title",
138
+ description: "Item description",
139
+ properties: {
140
+ string: {
141
+ type: "string",
142
+ title: "String field",
143
+ description: "String description",
144
+ },
145
+ number: {
146
+ type: "number",
147
+ title: "Number field",
148
+ description: "Number description",
149
+ },
150
+ },
151
+ },
152
+ },
153
+ uiSchema: {},
154
+ },
155
+ play: (_c) => __awaiter(void 0, [_c], void 0, function* ({ canvasElement }) {
156
+ const canvas = within(canvasElement);
157
+ // Add two items
158
+ const addButton = canvas.getByText("+");
159
+ yield userEvent.click(addButton);
160
+ yield userEvent.click(addButton);
161
+ const allDownArrows = canvas.queryAllByText("↓");
162
+ const allUpArrows = canvas.queryAllByText("↑");
163
+ const firstStringInput = canvasElement.querySelector('input[name="itemsList[0].string"]');
164
+ const secondStringInput = canvasElement.querySelector('input[name="itemsList[1].string"]');
165
+ const firstNumberInput = canvasElement.querySelector('input[name="itemsList[0].number"]');
166
+ const secondNumberInput = canvasElement.querySelector('input[name="itemsList[1].number"]');
167
+ const allLabelsAfterAdd = canvasElement.querySelectorAll('[name^="itemsList["]');
168
+ expect(allLabelsAfterAdd.length).toEqual(4);
169
+ yield userEvent.type(firstStringInput, "first");
170
+ yield userEvent.type(firstNumberInput, "1");
171
+ yield userEvent.type(secondStringInput, "second");
172
+ yield userEvent.type(secondNumberInput, "2");
173
+ // Check that moving items work
174
+ yield userEvent.click(allDownArrows[0]);
175
+ yield expect(firstStringInput).toHaveValue("second");
176
+ yield expect(firstNumberInput).toHaveValue(2);
177
+ yield expect(secondStringInput).toHaveValue("first");
178
+ yield expect(secondNumberInput).toHaveValue(1);
179
+ yield userEvent.click(allUpArrows[0]);
180
+ yield expect(firstStringInput).toHaveValue("first");
181
+ yield expect(firstNumberInput).toHaveValue(1);
182
+ yield expect(secondStringInput).toHaveValue("second");
183
+ yield expect(secondNumberInput).toHaveValue(2);
184
+ // Remove items
185
+ const removeButton = canvas.queryAllByText("-");
186
+ yield userEvent.click(removeButton[1]);
187
+ yield userEvent.click(removeButton[0]);
188
+ const allLabelsAfterRemove = canvasElement.querySelectorAll('[name^="itemsList["]');
189
+ expect(allLabelsAfterRemove.length).toEqual(0);
190
+ }),
191
+ };
@@ -0,0 +1,5 @@
1
+ import { StoryObj } from "@storybook/react";
2
+ import { BooleanField } from "./../BooleanField";
3
+ declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
4
+ export default _default;
5
+ export declare const Default: StoryObj<typeof BooleanField>;
@@ -0,0 +1,36 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { userEvent, expect } from "@storybook/test";
12
+ import { Formik, Form } from "formik";
13
+ import { BooleanField } from "./../BooleanField";
14
+ export default {
15
+ title: "Components/BooleanField",
16
+ component: BooleanField,
17
+ decorators: [
18
+ (Story) => (_jsx(Formik, { initialValues: { acceptTerms: false }, onSubmit: (values) => console.log(values), children: _jsx(Form, { children: Story() }) })),
19
+ ],
20
+ };
21
+ export const Default = {
22
+ args: {
23
+ name: "acceptTerms",
24
+ schema: { type: "boolean" },
25
+ uiSchema: {
26
+ "ui:label": "I accept the terms and conditions",
27
+ },
28
+ },
29
+ play: (_a) => __awaiter(void 0, [_a], void 0, function* ({ canvasElement }) {
30
+ const checkbox = canvasElement.querySelector('input[type="checkbox"][name="acceptTerms"]');
31
+ yield userEvent.click(checkbox);
32
+ yield expect(checkbox).toBeChecked();
33
+ yield userEvent.click(checkbox);
34
+ yield expect(checkbox).not.toBeChecked();
35
+ }),
36
+ };
@@ -0,0 +1,5 @@
1
+ import { StoryObj } from "@storybook/react";
2
+ import { DateField } from "./../DateField";
3
+ declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
4
+ export default _default;
5
+ export declare const Default: StoryObj<typeof DateField>;
@@ -0,0 +1,34 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { userEvent, expect } from "@storybook/test";
12
+ import { Formik, Form } from "formik";
13
+ import { DateField } from "./../DateField";
14
+ export default {
15
+ title: "Components/DateField",
16
+ component: DateField,
17
+ decorators: [
18
+ (Story) => (_jsx(Formik, { initialValues: { birthDate: "" }, onSubmit: (values) => console.log(values), children: _jsx(Form, { children: Story() }) })),
19
+ ],
20
+ };
21
+ export const Default = {
22
+ args: {
23
+ name: "birthDate",
24
+ schema: { type: "string", format: "date" },
25
+ uiSchema: {},
26
+ },
27
+ play: (_a) => __awaiter(void 0, [_a], void 0, function* ({ canvasElement }) {
28
+ const dateInput = canvasElement.querySelector('input[name="birthDate"]');
29
+ expect(dateInput).toBeInTheDocument();
30
+ const dateToInput = "2023-02-01";
31
+ yield userEvent.type(dateInput, dateToInput);
32
+ yield expect(dateInput).toHaveValue(dateToInput);
33
+ }),
34
+ };
@@ -0,0 +1,5 @@
1
+ import { StoryObj } from "@storybook/react";
2
+ import { NullField } from "./../NullField";
3
+ declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
4
+ export default _default;
5
+ export declare const Default: StoryObj<typeof NullField>;
@@ -0,0 +1,38 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ import { within, expect } from "@storybook/test";
12
+ import { Formik, Form } from "formik";
13
+ import { NullField } from "./../NullField";
14
+ export default {
15
+ title: "Components/NullField",
16
+ component: NullField,
17
+ decorators: [
18
+ (Story) => (_jsx(Formik, { initialValues: { someField: null }, onSubmit: (values) => console.log(values), children: _jsxs(Form, { children: [Story(), _jsx("button", { type: "submit", children: "Submit" })] }) })),
19
+ ],
20
+ };
21
+ export const Default = {
22
+ args: {
23
+ name: "nullField",
24
+ description: "Additional info",
25
+ schema: { type: "null", title: "Null Field" },
26
+ uiSchema: {},
27
+ },
28
+ play: (_a) => __awaiter(void 0, [_a], void 0, function* ({ canvasElement }) {
29
+ const canvas = within(canvasElement);
30
+ const title = canvasElement.querySelector('label[for="nullField"]');
31
+ const submitButton = canvasElement.querySelector('button[type="submit"]');
32
+ const additionalInfo = yield canvas.findByText("Additional info");
33
+ expect(title).toBeInTheDocument();
34
+ expect(title.textContent).toBeTruthy();
35
+ expect(additionalInfo).toBeInTheDocument();
36
+ expect(submitButton).toBeInTheDocument();
37
+ }),
38
+ };
@@ -0,0 +1,5 @@
1
+ import { StoryObj } from "@storybook/react";
2
+ import { NumberField } from "./../NumberField";
3
+ declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
4
+ export default _default;
5
+ export declare const Default: StoryObj<typeof NumberField>;