@tsed/react-formio 1.13.1 → 1.13.4

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 (184) hide show
  1. package/.eslintignore +13 -0
  2. package/.eslintrc.js +7 -0
  3. package/coverage.json +6 -0
  4. package/dist/components/actions-table/actionsTable.component.d.ts +0 -1
  5. package/dist/components/actions-table/actionsTable.stories.d.ts +0 -1
  6. package/dist/components/alert/alert.component.d.ts +1 -2
  7. package/dist/components/alert/alert.stories.d.ts +0 -1
  8. package/dist/components/card/card.stories.d.ts +0 -1
  9. package/dist/components/form/form.component.d.ts +1 -2
  10. package/dist/components/form/form.component.spec.d.ts +1 -0
  11. package/dist/components/form/form.stories.d.ts +3754 -156
  12. package/dist/components/form/useForm.hook.d.ts +6 -3
  13. package/dist/components/form-access/formAccess.stories.d.ts +1 -2
  14. package/dist/components/form-action/formAction.stories.d.ts +0 -1
  15. package/dist/components/form-builder/formBuilder.stories.d.ts +518 -153
  16. package/dist/components/form-control/formControl.component.d.ts +2 -2
  17. package/dist/components/form-control/formControl.component.spec.d.ts +1 -0
  18. package/dist/components/form-control/formControl.stories.d.ts +57 -0
  19. package/dist/components/form-edit/formEdit.component.d.ts +0 -1
  20. package/dist/components/form-edit/formEdit.stories.d.ts +18 -19
  21. package/dist/components/form-settings/formSettings.component.d.ts +0 -1
  22. package/dist/components/form-settings/formSettings.stories.d.ts +1 -2
  23. package/dist/components/forms-table/components/formCell.component.d.ts +0 -1
  24. package/dist/components/forms-table/formsTable.component.d.ts +0 -1
  25. package/dist/components/forms-table/formsTable.stories.d.ts +0 -1
  26. package/dist/components/index.d.ts +2 -2
  27. package/dist/components/input-tags/inputTags.component.d.ts +0 -1
  28. package/dist/components/input-tags/inputTags.stories.d.ts +2 -3
  29. package/dist/components/input-text/inputText.component.d.ts +0 -1
  30. package/dist/components/input-text/inputText.stories.d.ts +0 -1
  31. package/dist/components/loader/loader.component.d.ts +1 -1
  32. package/dist/components/loader/loader.stories.d.ts +0 -1
  33. package/dist/components/modal/modal.component.d.ts +1 -1
  34. package/dist/components/modal/modal.stories.d.ts +0 -1
  35. package/dist/components/pagination/pagination.component.d.ts +0 -1
  36. package/dist/components/pagination/pagination.stories.d.ts +0 -1
  37. package/dist/components/react-component/reactComponent.component.d.ts +3 -3
  38. package/dist/components/select/select.stories.d.ts +2 -3
  39. package/dist/components/submissions-table/submissionsTable.component.d.ts +0 -1
  40. package/dist/components/submissions-table/submissionsTable.stories.d.ts +13 -14
  41. package/dist/components/table/components/defaultArrowSort.component.d.ts +0 -1
  42. package/dist/components/table/components/defaultCell.component.d.ts +0 -1
  43. package/dist/components/table/components/defaultCellHeader.component.d.ts +1 -2
  44. package/dist/components/table/components/defaultCellOperations.component.d.ts +0 -1
  45. package/dist/components/table/components/defaultOperationButton.component.d.ts +0 -1
  46. package/dist/components/table/filters/defaultColumnFilter.component.d.ts +0 -1
  47. package/dist/components/table/filters/selectColumnFilter.component.d.ts +0 -1
  48. package/dist/components/table/filters/sliderColumnFilter.component.d.ts +0 -1
  49. package/dist/components/table/index.d.ts +1 -1
  50. package/dist/components/table/table.stories.d.ts +4 -5
  51. package/dist/components/tabs/tabs.component.stories.d.ts +0 -1
  52. package/dist/hooks/useTooltip.d.ts +1 -1
  53. package/dist/index.d.ts +3 -3
  54. package/dist/index.js +8014 -7967
  55. package/dist/index.js.map +1 -1
  56. package/dist/index.modern.js +7392 -7340
  57. package/dist/index.modern.js.map +1 -1
  58. package/dist/stores/actions/index.d.ts +1 -1
  59. package/dist/stores/auth/auth.selectors.d.ts +1 -1
  60. package/dist/stores/auth/index.d.ts +4 -4
  61. package/dist/stores/index.d.ts +2 -2
  62. package/jest.config.js +6 -1
  63. package/package.json +8 -5
  64. package/src/components/__fixtures__/form.fixture.json +23 -0
  65. package/src/components/actions-table/actionsTable.component.spec.tsx +11 -11
  66. package/src/components/actions-table/actionsTable.component.tsx +8 -9
  67. package/src/components/actions-table/actionsTable.stories.tsx +1 -0
  68. package/src/components/alert/alert.component.spec.tsx +21 -19
  69. package/src/components/alert/alert.stories.tsx +1 -0
  70. package/src/components/card/card.component.spec.tsx +5 -4
  71. package/src/components/card/card.stories.tsx +1 -0
  72. package/src/components/form/form.component.spec.tsx +57 -0
  73. package/src/components/form/form.component.tsx +4 -3
  74. package/src/components/form/form.stories.tsx +206 -57
  75. package/src/components/form/useForm.hook.ts +68 -37
  76. package/src/components/form-access/formAccess.component.tsx +3 -2
  77. package/src/components/form-access/formAccess.schema.ts +1 -0
  78. package/src/components/form-access/formAccess.stories.tsx +1 -0
  79. package/src/components/form-access/formAccess.utils.ts +6 -5
  80. package/src/components/form-action/formAction.component.tsx +5 -4
  81. package/src/components/form-action/formAction.stories.tsx +225 -227
  82. package/src/components/form-builder/formBuilder.component.tsx +2 -1
  83. package/src/components/form-builder/formBuilder.stories.tsx +1 -0
  84. package/src/components/form-control/formControl.component.spec.tsx +76 -0
  85. package/src/components/form-control/formControl.component.tsx +15 -7
  86. package/src/components/form-control/formControl.stories.tsx +65 -0
  87. package/src/components/form-edit/formCtas.component.tsx +10 -9
  88. package/src/components/form-edit/formEdit.component.tsx +2 -1
  89. package/src/components/form-edit/formEdit.reducer.ts +1 -0
  90. package/src/components/form-edit/formEdit.stories.tsx +1 -0
  91. package/src/components/form-edit/formParameters.component.tsx +1 -0
  92. package/src/components/form-edit/useFormEdit.hook.ts +1 -0
  93. package/src/components/form-settings/formSettings.component.spec.tsx +7 -6
  94. package/src/components/form-settings/formSettings.component.tsx +12 -14
  95. package/src/components/form-settings/formSettings.stories.tsx +1 -0
  96. package/src/components/form-settings/formSettings.utils.ts +4 -3
  97. package/src/components/forms-table/components/formCell.component.tsx +1 -0
  98. package/src/components/forms-table/formsTable.component.tsx +23 -25
  99. package/src/components/forms-table/formsTable.stories.tsx +1 -0
  100. package/src/components/index.ts +2 -2
  101. package/src/components/input-tags/inputTags.component.tsx +7 -6
  102. package/src/components/input-tags/inputTags.stories.tsx +1 -0
  103. package/src/components/input-text/inputText.component.spec.tsx +12 -11
  104. package/src/components/input-text/inputText.component.tsx +3 -2
  105. package/src/components/input-text/inputText.stories.tsx +1 -0
  106. package/src/components/loader/loader.component.spec.tsx +6 -5
  107. package/src/components/loader/loader.component.tsx +1 -0
  108. package/src/components/loader/loader.stories.tsx +1 -0
  109. package/src/components/modal/modal.component.spec.tsx +36 -33
  110. package/src/components/modal/modal.component.tsx +3 -3
  111. package/src/components/modal/modal.stories.tsx +1 -0
  112. package/src/components/modal/removeModal.component.tsx +1 -0
  113. package/src/components/pagination/pagination.component.spec.tsx +24 -21
  114. package/src/components/pagination/pagination.component.tsx +1 -0
  115. package/src/components/pagination/pagination.stories.tsx +1 -0
  116. package/src/components/react-component/reactComponent.component.tsx +11 -7
  117. package/src/components/select/select.component.spec.tsx +17 -18
  118. package/src/components/select/select.component.tsx +3 -2
  119. package/src/components/select/select.stories.tsx +1 -0
  120. package/src/components/submissions-table/submissionsTable.component.tsx +3 -2
  121. package/src/components/submissions-table/submissionsTable.stories.tsx +1 -0
  122. package/src/components/table/components/defaultArrowSort.component.tsx +1 -0
  123. package/src/components/table/components/defaultCellHeader.component.tsx +1 -1
  124. package/src/components/table/components/defaultCellOperations.component.tsx +1 -0
  125. package/src/components/table/components/defaultOperationButton.component.tsx +1 -0
  126. package/src/components/table/filters/defaultColumnFilter.component.spec.tsx +5 -3
  127. package/src/components/table/filters/defaultColumnFilter.component.tsx +1 -0
  128. package/src/components/table/filters/selectColumnFilter.component.spec.tsx +9 -7
  129. package/src/components/table/filters/selectColumnFilter.component.tsx +1 -0
  130. package/src/components/table/index.ts +1 -1
  131. package/src/components/table/table.component.tsx +5 -4
  132. package/src/components/table/table.stories.tsx +2 -1
  133. package/src/components/table/utils/mapFormToColumns.tsx +3 -2
  134. package/src/components/table/utils/useOperations.hook.tsx +1 -0
  135. package/src/components/tabs/tabs.component.spec.tsx +6 -5
  136. package/src/components/tabs/tabs.component.stories.tsx +1 -0
  137. package/src/components/tabs/tabs.component.tsx +11 -5
  138. package/src/hooks/useTooltip.ts +1 -1
  139. package/src/index.ts +3 -4
  140. package/src/interfaces/Operation.ts +1 -0
  141. package/src/stores/action/action.actions.spec.ts +1 -0
  142. package/src/stores/action/action.actions.ts +1 -0
  143. package/src/stores/action/action.reducers.ts +1 -1
  144. package/src/stores/action-info/action-info.actions.spec.ts +1 -0
  145. package/src/stores/action-info/action-info.actions.ts +2 -1
  146. package/src/stores/action-info/action-info.reducers.ts +2 -1
  147. package/src/stores/action-info/action-info.selectors.ts +2 -1
  148. package/src/stores/actions/actions.actions.spec.ts +1 -0
  149. package/src/stores/actions/actions.actions.ts +1 -0
  150. package/src/stores/actions/actions.reducers.ts +1 -0
  151. package/src/stores/actions/index.ts +1 -1
  152. package/src/stores/auth/auth.actions.ts +1 -0
  153. package/src/stores/auth/auth.reducers.ts +1 -0
  154. package/src/stores/auth/auth.selectors.ts +1 -0
  155. package/src/stores/auth/auth.utils.tsx +3 -2
  156. package/src/stores/auth/getAccess.action.spec.ts +1 -0
  157. package/src/stores/auth/getAccess.action.ts +3 -2
  158. package/src/stores/auth/getProjectAccess.action.ts +1 -0
  159. package/src/stores/auth/index.ts +4 -4
  160. package/src/stores/auth/initAuth.action.spec.ts +1 -0
  161. package/src/stores/auth/initAuth.action.ts +1 -0
  162. package/src/stores/auth/logout.action.spec.ts +2 -0
  163. package/src/stores/auth/logout.action.ts +1 -0
  164. package/src/stores/auth/setUser.action.spec.ts +1 -0
  165. package/src/stores/auth/setUser.action.ts +1 -0
  166. package/src/stores/form/form.actions.spec.ts +1 -0
  167. package/src/stores/form/form.actions.ts +1 -0
  168. package/src/stores/form/form.reducers.ts +1 -0
  169. package/src/stores/form/form.selectors.ts +1 -1
  170. package/src/stores/forms/forms.actions.spec.ts +1 -0
  171. package/src/stores/forms/forms.actions.ts +1 -0
  172. package/src/stores/forms/forms.reducers.ts +1 -0
  173. package/src/stores/index.ts +3 -2
  174. package/src/stores/root/root.selectors.ts +3 -3
  175. package/src/stores/submission/submission.actions.spec.ts +1 -0
  176. package/src/stores/submission/submission.actions.ts +1 -0
  177. package/src/stores/submission/submission.reducers.ts +1 -0
  178. package/src/stores/submissions/submissions.actions.spec.ts +1 -0
  179. package/src/stores/submissions/submissions.actions.ts +1 -0
  180. package/src/stores/submissions/submissions.reducers.ts +1 -0
  181. package/tsconfig.json +10 -27
  182. package/tsconfig.node.json +8 -0
  183. package/craco.config.js +0 -11
  184. package/tsconfig.test.json +0 -6
@@ -1,7 +1,8 @@
1
- import React from "react";
2
- import {Form} from "./form.component";
1
+ import React, { useState } from "react";
2
+
3
+ import { Submission } from "../../interfaces";
3
4
  import form from "../__fixtures__/form.fixture.json";
4
- import {Submission} from "../../interfaces";
5
+ import { Form } from "./form.component";
5
6
 
6
7
  export default {
7
8
  title: "ReactFormio/Form",
@@ -11,88 +12,236 @@ export default {
11
12
  control: {
12
13
  type: "object"
13
14
  }
14
- }
15
- },
16
- parameters: {}
15
+ },
16
+ onPrevPage: { action: "onPrevPage" },
17
+ onNextPage: { action: "onNextPage" },
18
+ onCancel: { action: "onCancel" },
19
+ onChange: { action: "onChange" },
20
+ onCustomEvent: { action: "onCustomEvent" },
21
+ onComponentChange: { action: "onComponentChange" },
22
+ onSubmit: { action: "onSubmit" },
23
+ onAsyncSubmit: { action: "onAsyncSubmit" },
24
+ onSubmitDone: { action: "onSubmitDone" },
25
+ onFormLoad: { action: "onFormLoad" },
26
+ onError: { action: "onError" },
27
+ onRender: { action: "onRender" },
28
+ onAttach: { action: "onAttach" },
29
+ onBuild: { action: "onBuild" },
30
+ onFocus: { action: "onFocus" },
31
+ onBlur: { action: "onBlur" },
32
+ onInitialized: { action: "onInitialized" },
33
+ onFormReady: { action: "onFormReady" }
34
+ }
17
35
  };
18
36
 
37
+ function filter(args: any[]) {
38
+ return args.map((item) => {
39
+ if (item && item._form) {
40
+ return "FormioInstance";
41
+ }
42
+
43
+ if (item && item.component) {
44
+ return ["Component", item.component.type, item.component.key].filter(Boolean).join(":");
45
+ }
46
+
47
+ if (item && item.changed) {
48
+ return `${item.changed.component.key}(${item.changed.value})`;
49
+ }
50
+
51
+ return item;
52
+ });
53
+ }
54
+
55
+ function wrap(args: any) {
56
+ return {
57
+ ...args,
58
+ onPrevPage: (...list: any[]) => {
59
+ return args.onPrevPage(...filter(list));
60
+ },
61
+ onNextPage: (...list: any[]) => {
62
+ return args.onNextPage(...filter(list));
63
+ },
64
+ onCancel: (...list: any[]) => {
65
+ return args.onCancel(...filter(list));
66
+ },
67
+ onChange: (...list: any[]) => {
68
+ return args.onChange(...filter(list));
69
+ },
70
+ onCustomEvent: (...list: any[]) => {
71
+ return args.onCustomEvent(...filter(list));
72
+ },
73
+ onComponentChange: (...list: any[]) => {
74
+ return args.onComponentChange(...filter(list));
75
+ },
76
+ onSubmit: (...list: any[]) => {
77
+ return args.onSubmit(...filter(list));
78
+ },
79
+ onAsyncSubmit: (...list: any[]) => {
80
+ return args.onAsyncSubmit(...filter(list));
81
+ },
82
+ onSubmitDone: (...list: any[]) => {
83
+ return args.onSubmitDone(...filter(list));
84
+ },
85
+ onFormLoad: (...list: any[]) => {
86
+ return args.onFormLoad(...filter(list));
87
+ },
88
+ onError: (...list: any[]) => {
89
+ return args.onError(...filter(list));
90
+ },
91
+ onRender: (...list: any[]) => {
92
+ return args.onRender(...filter(list));
93
+ },
94
+ onAttach: (...list: any[]) => {
95
+ return args.onAttach(...filter(list));
96
+ },
97
+ onBuild: (...list: any[]) => {
98
+ return args.onBuild(...filter(list));
99
+ },
100
+ onFocus: (...list: any[]) => {
101
+ return args.onFocus(...filter(list));
102
+ },
103
+ onBlur: (...list: any[]) => {
104
+ return args.onBlur(...filter(list));
105
+ },
106
+ onInitialized: (...list: any[]) => {
107
+ return args.onInitialized(...filter(list));
108
+ },
109
+ onFormReady: (...list: any[]) => {
110
+ return args.onFormReady(...filter(list));
111
+ }
112
+ };
113
+ }
114
+
19
115
  export const Sandbox = (args: any) => {
20
- delete args.onRender;
21
- delete args.onComponentChange;
116
+ return <Form {...wrap(args)} form={args.form} options={{ template: "tailwind", iconset: "bx" }} />;
117
+ };
118
+
119
+ Sandbox.args = {
120
+ form
121
+ };
122
+
123
+ export const TriggerError = (args: any) => {
124
+ const onAsyncSubmit = (submission: Submission) => {
125
+ return new Promise((resolve, reject) => {
126
+ setTimeout(() => {
127
+ reject(new Error("server error"));
128
+ }, 500);
129
+ }).catch((error) => {
130
+ error.errors = {
131
+ message: "My custom message about this field",
132
+ type: "custom",
133
+ path: ["firstName"],
134
+ level: "error"
135
+ };
136
+ throw error;
137
+ });
138
+ };
139
+
140
+ return <Form<any> {...wrap(args)} form={args.form} onAsyncSubmit={onAsyncSubmit} />;
141
+ };
142
+
143
+ TriggerError.args = {
144
+ form: {
145
+ type: "form",
146
+ display: "form",
147
+ tags: [],
148
+ components: [
149
+ {
150
+ label: "First name",
151
+ widget: {
152
+ type: "input"
153
+ },
154
+ errorLabel: "",
155
+ key: "firstName",
156
+ inputType: "text",
157
+ type: "textfield",
158
+ id: "eqb1o4r",
159
+ defaultValue: ""
160
+ },
161
+ {
162
+ label: "Submit",
163
+ showValidations: false,
164
+ tableView: false,
165
+ key: "submit",
166
+ type: "button",
167
+ input: true
168
+ }
169
+ ]
170
+ }
171
+ };
172
+
173
+ export const ReadOnly = (args: any) => {
22
174
  return (
23
175
  <Form
24
- {...args}
176
+ {...wrap(args)}
177
+ options={{ template: "tailwind", iconset: "bx", readOnly: args.readOnly }}
25
178
  form={args.form}
26
- onFormReady={(formio) => {
27
- console.log("ready", formio);
179
+ submission={{
180
+ data: {
181
+ editGrid: [{ currency: "EUR" }]
182
+ }
28
183
  }}
29
- options={{template: "tailwind", iconset: "bx"}}
30
184
  />
31
185
  );
32
186
  };
33
187
 
34
- Sandbox.args = {
188
+ ReadOnly.args = {
189
+ readonly: true,
35
190
  form
36
191
  };
37
192
 
38
- export const TriggerError = (args: any) => {
39
- delete args.onRender;
40
- delete args.onComponentChange;
193
+ export const OnChange = (args: any) => {
194
+ const [data, setForm] = useState<any>(() => {});
195
+ const props = wrap(args);
41
196
 
42
197
  return (
43
198
  <Form
44
- {...args}
199
+ {...props}
200
+ options={{ template: "tailwind", iconset: "bx", readOnly: args.readOnly }}
45
201
  form={args.form}
46
- onAsyncSubmit={(submission: Submission) => {
47
- return new Promise((resolve, reject) => {
48
- setTimeout(() => {
49
- reject(new Error("server error"));
50
- }, 500);
51
- }).catch((error) => {
52
- error.errors = {
53
- "message": "My custom message about this field",
54
- "type": "custom",
55
- "path": ["firstName"],
56
- "level": "error"
57
- }
58
- throw error
59
- });
60
- }}
61
- options={{
62
- hooks: {
63
- template: "tailwind",
64
- iconset: "bx"
65
- }
202
+ submission={{ data }}
203
+ onChange={(changedSubmission) => {
204
+ setForm(changedSubmission.data);
66
205
  }}
67
206
  />
68
207
  );
69
208
  };
70
209
 
71
- TriggerError.args = {
210
+ OnChange.args = {
72
211
  form: {
73
- "type": "form",
74
- "display": "form",
75
- "tags": [],
76
- "components": [
212
+ type: "form",
213
+ display: "form",
214
+ tags: [],
215
+ components: [
77
216
  {
78
- "label": "First name",
79
- "widget": {
80
- "type": "input"
217
+ label: "First name",
218
+ widget: {
219
+ type: "input"
81
220
  },
82
- "errorLabel": "",
83
- "key": "firstName",
84
- "inputType": "text",
85
- "type": "textfield",
86
- "id": "eqb1o4r",
87
- "defaultValue": ""
221
+ errorLabel: "",
222
+ key: "firstName",
223
+ inputType: "text",
224
+ type: "textfield",
225
+ id: "eqb1o4r",
226
+ defaultValue: "",
227
+ validate: {
228
+ required: true
229
+ }
88
230
  },
89
231
  {
90
- "label": "Submit",
91
- "showValidations": false,
92
- "tableView": false,
93
- "key": "submit",
94
- "type": "button",
95
- "input": true
232
+ label: "Last name",
233
+ widget: {
234
+ type: "input"
235
+ },
236
+ errorLabel: "",
237
+ key: "lastName",
238
+ inputType: "text",
239
+ type: "textfield",
240
+ id: "eqb1o4r",
241
+ defaultValue: "",
242
+ validate: {
243
+ required: true
244
+ }
96
245
  }
97
246
  ]
98
247
  }
@@ -3,11 +3,16 @@ import { get } from "lodash";
3
3
  import cloneDeep from "lodash/cloneDeep";
4
4
  import isEqual from "lodash/isEqual";
5
5
  import { useEffect, useRef } from "react";
6
- import { callLast } from "../../utils/callLast";
6
+
7
7
  import { FormOptions, FormSchema, Submission } from "../../interfaces";
8
+ import { callLast } from "../../utils/callLast";
8
9
 
9
10
  export interface ChangedSubmission<T = any> extends Submission<T> {
10
- changed: any;
11
+ changed: {
12
+ component: ExtendedComponentSchema;
13
+ instance: Form;
14
+ value: any;
15
+ } & Record<string, any>;
11
16
  isValid: boolean;
12
17
  }
13
18
 
@@ -34,6 +39,8 @@ export interface UseFormHookProps<Data = any> extends Record<string, any> {
34
39
  * Data submission
35
40
  */
36
41
  submission?: Submission<Data>;
42
+
43
+ /// events
37
44
  onPrevPage?: (obj: FormPageChangeProps<Data>) => void;
38
45
  onNextPage?: (obj: FormPageChangeProps<Data>) => void;
39
46
  onCancel?: Function;
@@ -41,7 +48,7 @@ export interface UseFormHookProps<Data = any> extends Record<string, any> {
41
48
  onCustomEvent?: (obj: { type: string; event: string; component: ExtendedComponentSchema; data: any }) => void;
42
49
  onComponentChange?: (component: ExtendedComponentSchema) => void;
43
50
  onSubmit?: (submission: Submission<Data>) => void;
44
- onAsyncSubmit?: (submission: Submission<Data>) => Promise<void>;
51
+ onAsyncSubmit?: (submission: Submission<Data>) => Promise<any>;
45
52
  onSubmitDone?: (submission: Submission<Data>) => void;
46
53
  onFormLoad?: Function;
47
54
  onError?: (errors: any) => void;
@@ -52,7 +59,53 @@ export interface UseFormHookProps<Data = any> extends Record<string, any> {
52
59
  onBlur?: Function;
53
60
  onInitialized?: Function;
54
61
  onFormReady?: (formio: Form) => void;
55
- formioform?: any;
62
+ }
63
+
64
+ function useEvent(event: string, callback: any, events: Map<string, any>) {
65
+ useEffect(() => {
66
+ if (callback) {
67
+ // if (event === "onChange") {
68
+ // callback = callLast(callback, 200);
69
+ // }
70
+ events.set(event, callback);
71
+ }
72
+ }, [callback, event, events]);
73
+ }
74
+
75
+ function useEvents(funcs: any) {
76
+ const events = useRef<Map<string, any>>(new Map());
77
+
78
+ const hasEvent = (event: string) => {
79
+ return funcs.hasOwnProperty(event) && typeof funcs[event] === "function";
80
+ };
81
+
82
+ const emit = (event: string, ...args: any[]) => {
83
+ if (hasEvent(event)) {
84
+ const fn = events.current.has(event) ? events.current.get(event) : funcs[event];
85
+ return fn(...args);
86
+ }
87
+ };
88
+
89
+ useEvent("onBlur", funcs["onBlur"], events.current);
90
+ useEvent("onPrevPage", funcs["onPrevPage"], events.current);
91
+ useEvent("onNextPage", funcs["onNextPage"], events.current);
92
+ useEvent("onCancel", funcs["onCancel"], events.current);
93
+ useEvent("onChange", funcs["onChange"], events.current);
94
+ useEvent("onCustomEvent", funcs["onCustomEvent"], events.current);
95
+ useEvent("onComponentChange", funcs["onComponentChange"], events.current);
96
+ useEvent("onSubmit", funcs["onSubmit"], events.current);
97
+ useEvent("onAsyncSubmit", funcs["onAsyncSubmit"], events.current);
98
+ useEvent("onSubmitDone", funcs["onSubmitDone"], events.current);
99
+ useEvent("onFormLoad", funcs["onFormLoad"], events.current);
100
+ useEvent("onError", funcs["onError"], events.current);
101
+ useEvent("onRender", funcs["onRender"], events.current);
102
+ useEvent("onAttach", funcs["onAttach"], events.current);
103
+ useEvent("onBuild", funcs["onBuild"], events.current);
104
+ useEvent("onFocus", funcs["onFocus"], events.current);
105
+ useEvent("onBlur", funcs["onBlur"], events.current);
106
+ useEvent("onInitialized", funcs["onInitialized"], events.current);
107
+
108
+ return { events, emit, hasEvent };
56
109
  }
57
110
 
58
111
  export function useForm<Data = any>(props: UseFormHookProps<Data>) {
@@ -60,12 +113,12 @@ export function useForm<Data = any>(props: UseFormHookProps<Data>) {
60
113
  const element = useRef<any>();
61
114
  const isLoaded = useRef<boolean>();
62
115
  const instance = useRef<Form>();
63
- const events = useRef<Map<string, any>>(new Map());
116
+ const { emit, hasEvent } = useEvents(funcs);
64
117
 
65
118
  async function customValidation(submission: Submission, callback: (err: Error | null) => void) {
66
- if (events.current.has("onAsyncSubmit")) {
119
+ if (hasEvent("onAsyncSubmit")) {
67
120
  try {
68
- await events.current.get("onAsyncSubmit")(submission);
121
+ await emit("onAsyncSubmit", submission, instance.current);
69
122
  } catch (err) {
70
123
  callback(err?.errors || err);
71
124
  }
@@ -93,27 +146,13 @@ export function useForm<Data = any>(props: UseFormHookProps<Data>) {
93
146
  }
94
147
 
95
148
  if (event.startsWith("formio.")) {
96
- const funcName = `on${event.charAt(7).toUpperCase()}${event.slice(8)}`;
149
+ const eventName = `on${event.charAt(7).toUpperCase()}${event.slice(8)}`;
97
150
 
98
- if (funcName === "onChange") {
99
- if (isEqual(get(submission, "data"), args[0].data)) {
100
- return;
101
- }
151
+ if (eventName === "onChange" && !args[0].changed) {
152
+ return;
102
153
  }
103
154
 
104
- if (
105
- // eslint-disable-next-line no-prototype-builtins
106
- props.hasOwnProperty(funcName) &&
107
- typeof funcs[funcName] === "function"
108
- ) {
109
- if (!events.current.has(funcName)) {
110
- const fn = callLast(funcs[funcName], 100);
111
- events.current.set(funcName, fn);
112
- }
113
-
114
- instance.current.instance.setAlert("success", "");
115
- events.current.get(funcName)(...args, instance.current);
116
- }
155
+ emit(eventName, ...args, instance.current);
117
156
  }
118
157
  });
119
158
 
@@ -134,6 +173,10 @@ export function useForm<Data = any>(props: UseFormHookProps<Data>) {
134
173
  useEffect(() => {
135
174
  if (instance.current) {
136
175
  instance.current.ready.then((formio: any) => {
176
+ if (isEqual(formio.submission.data, submission?.data)) {
177
+ return;
178
+ }
179
+
137
180
  submission && (formio.submission = cloneDeep(submission));
138
181
  });
139
182
  }
@@ -172,18 +215,6 @@ export function useForm<Data = any>(props: UseFormHookProps<Data>) {
172
215
  };
173
216
  }, []);
174
217
 
175
- useEffect(() => {
176
- props.onSubmit && events.current.set("onSubmit", props.onSubmit);
177
- }, [props.onSubmit, events]);
178
-
179
- useEffect(() => {
180
- props.onAsyncSubmit && events.current.set("onAsyncSubmit", props.onAsyncSubmit);
181
- }, [props.onAsyncSubmit, events]);
182
-
183
- useEffect(() => {
184
- props.onSubmitDone && events.current.set("onSubmitDone", props.onSubmitDone);
185
- }, [props.onSubmitDone, events]);
186
-
187
218
  return {
188
219
  element
189
220
  };
@@ -1,8 +1,10 @@
1
1
  import PropTypes from "prop-types";
2
2
  import React, { PropsWithChildren, ReactElement, useCallback, useEffect, useMemo, useState } from "react";
3
+
3
4
  import { FormOptions, FormSchema, Submission } from "../../interfaces";
4
5
  import { Card } from "../card/card.component";
5
6
  import { Form } from "../form/form.component";
7
+ import { ChangedSubmission } from "../form/useForm.hook";
6
8
  import {
7
9
  AccessRoles,
8
10
  dataAccessToSubmissions,
@@ -13,7 +15,6 @@ import {
13
15
  submissionsToDataAccess,
14
16
  updateSubmissions
15
17
  } from "./formAccess.utils";
16
- import { ChangedSubmission } from "../form/useForm.hook";
17
18
 
18
19
  export interface FormAccessProps {
19
20
  form: Partial<FormSchema>;
@@ -51,7 +52,7 @@ function useFormAccess({ form: formDefinition, roles, onSubmit, options }: FormA
51
52
  submissions,
52
53
  onChange,
53
54
  onSubmit: () => {
54
- onSubmit(submissionsToDataAccess(formDefinition, submissions));
55
+ onSubmit && onSubmit(submissionsToDataAccess(formDefinition, submissions));
55
56
  }
56
57
  };
57
58
  }
@@ -1,4 +1,5 @@
1
1
  import { ExtendedComponentSchema } from "formiojs";
2
+
2
3
  import { FormSchema } from "../../interfaces/FormSchema";
3
4
 
4
5
  export function getRoleComponent({ label, key, description, choices, data }: any): ExtendedComponentSchema {
@@ -1,4 +1,5 @@
1
1
  import React from "react";
2
+
2
3
  import { FormAccess } from "./formAccess.component";
3
4
 
4
5
  export default {
@@ -2,6 +2,7 @@ import { ExtendedComponentSchema } from "formiojs";
2
2
  import cloneDeep from "lodash/cloneDeep";
3
3
  import isEqual from "lodash/isEqual";
4
4
  import noop from "lodash/noop";
5
+
5
6
  import { FormSchema, Submission } from "../../interfaces";
6
7
  import { RoleSchema } from "../../interfaces/RoleSchema";
7
8
  import { getAccessPermissionForm, getSubmissionPermissionForm } from "./formAccess.schema";
@@ -31,19 +32,19 @@ export type SubmissionAccess = {
31
32
  function rolesToChoices(roles: RoleSchema[]): Choice[] {
32
33
  return Object.values(roles).map((role) => {
33
34
  return {
34
- label: role.title,
35
- value: role._id
35
+ label: role.title || "",
36
+ value: role._id || ""
36
37
  };
37
38
  });
38
39
  }
39
40
 
40
- function accessToHash(keys: string[], access: Access[] = []): AccessRoles {
41
+ function accessToHash(keys: (string | undefined)[] | undefined, access: Access[] = []): AccessRoles {
41
42
  const hash = Object.values(access).reduce((o: any, role: any) => {
42
43
  o[role.type] = role.roles;
43
44
  return o;
44
45
  }, {});
45
46
 
46
- return keys.reduce((data, key) => {
47
+ return ((keys || []).filter(Boolean) as any[]).reduce((data, key: string) => {
47
48
  return {
48
49
  ...data,
49
50
  [key]: hash[key] || []
@@ -100,7 +101,7 @@ export function submissionsToDataAccess(form: Partial<FormSchema>, submissions:
100
101
  }
101
102
 
102
103
  export function shouldUpdate(type: string, submission: Submission<AccessRoles>, submissions: SubmissionAccess) {
103
- return !isEqual(submission.data, submissions[type].data);
104
+ return !isEqual(submission.data, (submissions as any)[type].data);
104
105
  }
105
106
 
106
107
  export function updateSubmissions(type: string, submission: Submission<AccessRoles>, submissions: SubmissionAccess, cb: Function = noop) {
@@ -1,5 +1,6 @@
1
1
  import FormioUtils from "formiojs/utils";
2
- import React, { PropsWithChildren, ReactElement, useMemo } from "react";
2
+ import React, { PropsWithChildren, ReactElement } from "react";
3
+
3
4
  import { ActionDefaultsSchema, ActionSchema, FormOptions, Submission } from "../../interfaces";
4
5
  import { Form } from "../form/form.component";
5
6
 
@@ -38,12 +39,12 @@ export interface FormActionProps {
38
39
  }
39
40
 
40
41
  export function FormAction({ actionInfo, children, onSubmit, options, ...props }: PropsWithChildren<FormActionProps>): ReactElement {
41
- const { form, submission } = useMemo(() => {
42
- const submission = mapData(props.submission || {}, actionInfo.defaults);
42
+ const { form, submission } = (() => {
43
+ const submission = mapData(props.submission || {}, actionInfo.defaults!);
43
44
  const form = mapSettingsForm(actionInfo.settingsForm);
44
45
 
45
46
  return { form, submission: { data: submission } };
46
- }, [props.submission, actionInfo.settingsForm]);
47
+ })();
47
48
 
48
49
  return (
49
50
  <div>